diff --git a/.chronus/changes/fix-paging-unset-body-placement-2026-06-10.md b/.chronus/changes/fix-paging-unset-body-placement-2026-06-10.md new file mode 100644 index 00000000000..a86f2075fa3 --- /dev/null +++ b/.chronus/changes/fix-paging-unset-body-placement-2026-06-10.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/http-client-python" +--- + +Fix `UnboundLocalError` for paging operations with a flattened JSON model body. The request body is now constructed once outside the `prepare_request` callback (and before the body is serialized into the request content) instead of inside the closure, where assigning `body` made it an unbound local on every page fetch. diff --git a/packages/http-client-python/generator/pygen/codegen/serializers/builder_serializer.py b/packages/http-client-python/generator/pygen/codegen/serializers/builder_serializer.py index 5dcf94e32b4..c615baf827f 100644 --- a/packages/http-client-python/generator/pygen/codegen/serializers/builder_serializer.py +++ b/packages/http-client-python/generator/pygen/codegen/serializers/builder_serializer.py @@ -931,7 +931,8 @@ def _call_request_builder_helper( if builder.parameters.has_body and builder.parameters.body_parameter.flattened: # serialize flattened body before passing to request builder as well retval.extend(_serialize_flattened_body(builder.parameters.body_parameter)) - if is_json_model_type(builder.parameters): + if is_json_model_type(builder.parameters) and not is_paging: + # For paging, we put the json model body outside `prepare_request` retval.extend(_serialize_json_model_body(builder.parameters.body_parameter, builder.parameters.parameters)) if builder.has_form_data_body: retval.extend(self._create_body_parameter(builder)) @@ -1369,7 +1370,13 @@ def call_next_link_request_builder(self, builder: PagingOperationType) -> list[s return retval def _prepare_request_callback(self, builder: PagingOperationType) -> list[str]: - retval = self._initialize_overloads(builder) + retval: list[str] = [] + # The json model body must be constructed before `_initialize_overloads` + # serializes it into the request content, and outside `prepare_request` so + # the closure doesn't treat `body` as an unbound local. + if is_json_model_type(builder.parameters): + retval.extend(_serialize_json_model_body(builder.parameters.body_parameter, builder.parameters.parameters)) + retval.extend(self._initialize_overloads(builder)) if builder.has_continuation_token: retval.append(f"def prepare_request({builder.next_variable_name}=None):") retval.extend([f" {line}" for line in self.call_request_builder(builder, is_paging=True)])