Describe the bug
When generating a synchronous, modeless Python ARM client, an LRO operation whose final response has a JSON body but no response headers produces invalid Python code.
With models-mode=none, the generated get_long_running_output callback references response without assigning it:
def get_long_running_output(pipeline_response):
if response.content:
deserialized = response.json()
else:
deserialized = None
When the long-running operation reaches a successful terminal state, the callback raises:
NameError: name 'response' is not defined
The callback should first assign the HTTP response:
def get_long_running_output(pipeline_response):
response = pipeline_response.http_response
if response.content:
deserialized = response.json()
else:
deserialized = None
The current implementation in
packages/http-client-python/generator/pygen/codegen/serializers/builder_serializer.py
only emits response = pipeline_response.http_response when one of these conditions is true:
- models are enabled;
- models-mode == "dpg" ; or
- the LRO final response contains response headers.
However, response_headers_and_deserialization(...) can still emit code that reads response.content when models-mode=none and the final response has no headers.
This is also a generated-output regression: an earlier TypeSpec-generated ARM client emitted the response assignment for the equivalent LRO callback.
Reproduction
Reproduction:
Reproduced with:
- Node.js 24.18.0
- `@typespec/compiler` 1.15.0
- `@azure-tools/typespec-python` 0.63.5
- `@typespec/http-client-python` 0.36.0
- `@azure-tools/typespec-azure-resource-manager` 0.71.0
- `@azure-tools/typespec-client-generator-core` 0.71.1
Create `main.tsp`:
```typespec
import "@typespec/rest";
import "@typespec/http";
import "@azure-tools/typespec-azure-resource-manager";
import "@typespec/versioning";
using Azure.ResourceManager;
using Versioning;
using Http;
@armProviderNamespace
@versioned(Versions)
namespace Microsoft.LroResponseRepro;
interface Operations extends Azure.ResourceManager.Operations {}
enum Versions {
@armCommonTypesVersion(Azure.ResourceManager.CommonTypes.Versions.v5)
@Azure.Core.previewVersion
`2025-01-01-preview`,
}
model WidgetProperties {
value: string;
...DefaultProvisioningStateProperty;
}
model Widget is TrackedResource<WidgetProperties> {
...ResourceNameParameter<Widget>;
}
@armResourceOperations
interface Widgets {
get is ArmResourceRead<Widget>;
createOrUpdate is ArmResourceCreateOrReplaceAsync<Widget>;
delete is ArmResourceDeleteWithoutOkAsync<Widget>;
}
Compile it with:
tsp compile main.tsp \
--emit @azure-tools/typespec-python \
--option "@azure-tools/typespec-python.models-mode=none" \
--option "@azure-tools/typespec-python.no-async=true" \
--option "@azure-tools/typespec-python.namespace=lro_repro" \
--option "@azure-tools/typespec-python.emitter-output-dir=./generated"
Inspect generated/lro_repro/operations/_operations.py .
The generated begin_create_or_update callback reads response.content without first assigning
response = pipeline_response.http_response .
### Checklist
- [x] Follow our [Code of Conduct](https://github.com/microsoft/typespec/blob/main/CODE_OF_CONDUCT.md)
- [x] Check that there isn't already an issue that request the same bug to avoid creating a duplicate.
- [x] Check that this is a concrete bug. For Q&A open a [GitHub Discussion](https://github.com/Microsoft/typespec/discussions).
- [x] The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.
Describe the bug
When generating a synchronous, modeless Python ARM client, an LRO operation whose final response has a JSON body but no response headers produces invalid Python code.
With
models-mode=none, the generatedget_long_running_outputcallback referencesresponsewithout assigning it:When the long-running operation reaches a successful terminal state, the callback raises:
NameError: name 'response' is not definedThe callback should first assign the HTTP response:
The current implementation in
packages/http-client-python/generator/pygen/codegen/serializers/builder_serializer.py
only emits response = pipeline_response.http_response when one of these conditions is true:
However, response_headers_and_deserialization(...) can still emit code that reads
response.contentwhenmodels-mode=noneand the final response has no headers.This is also a generated-output regression: an earlier TypeSpec-generated ARM client emitted the response assignment for the equivalent LRO callback.
Reproduction
Reproduction: