diff --git a/.chronus/changes/python-xmlErrorDeserialization-2026-0-28-11-40-34.md b/.chronus/changes/python-xmlErrorDeserialization-2026-0-28-11-40-34.md new file mode 100644 index 00000000000..ca194e6bd18 --- /dev/null +++ b/.chronus/changes/python-xmlErrorDeserialization-2026-0-28-11-40-34.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/http-client-python" +--- + +`_failsafe_deserialize_xml` xml errors \ No newline at end of file diff --git a/packages/http-client-python/generator/pygen/codegen/models/operation.py b/packages/http-client-python/generator/pygen/codegen/models/operation.py index 84b1bb24e91..f5fb1c6241d 100644 --- a/packages/http-client-python/generator/pygen/codegen/models/operation.py +++ b/packages/http-client-python/generator/pygen/codegen/models/operation.py @@ -448,7 +448,19 @@ def imports( # pylint: disable=too-many-branches, disable=too-many-statements elif self.need_deserialize: file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL) if self.default_error_deserialization(serialize_namespace) or self.non_default_errors: - file_import.add_submodule_import(relative_path, "_failsafe_deserialize", ImportType.LOCAL) + xml_non_default_errors = any( + xml_serializable(str(e.default_content_type)) for e in self.non_default_errors + ) + try: + default_error = next(e for e in self.exceptions if "default" in e.status_codes and e.type) + except StopIteration: + default_error = None + if xml_non_default_errors or ( + default_error and xml_serializable(str(default_error.default_content_type)) + ): + file_import.add_submodule_import(relative_path, "_failsafe_deserialize_xml", ImportType.LOCAL) + else: + file_import.add_submodule_import(relative_path, "_failsafe_deserialize", ImportType.LOCAL) return file_import def get_response_from_status(self, status_code: Optional[Union[str, int]]) -> ResponseType: 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 35c4215b03f..46611d152ac 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 @@ -1045,7 +1045,9 @@ def handle_error_response( # pylint: disable=too-many-statements, too-many-bran retval.extend([f" {l}" for l in response_read]) retval.append(" map_error(status_code=response.status_code, response=response, error_map=error_map)") error_model = "" - if builder.non_default_errors and self.code_model.options["models-mode"]: + if ( # pylint: disable=too-many-nested-blocks + builder.non_default_errors and self.code_model.options["models-mode"] + ): error_model = ", model=error" condition = "if" retval.append(" error = None") @@ -1062,9 +1064,11 @@ def handle_error_response( # pylint: disable=too-many-statements, too-many-bran is_operation_file=True, skip_quote=True, serialize_namespace=self.serialize_namespace ) if self.code_model.options["models-mode"] == "dpg": - retval.append( - f" error = _failsafe_deserialize({type_annotation},{pylint_disable}\n response)" - ) + if xml_serializable(str(e.default_content_type)): + fn = "_failsafe_deserialize_xml" + else: + fn = "_failsafe_deserialize" + retval.append(f" error = {fn}({type_annotation},{pylint_disable}\n response)") else: retval.extend( [ @@ -1130,9 +1134,14 @@ def handle_error_response( # pylint: disable=too-many-statements, too-many-bran if builder.non_default_errors: retval.append(" else:") if self.code_model.options["models-mode"] == "dpg": + default_exception = next(e for e in builder.exceptions if "default" in e.status_codes and e.type) + if xml_serializable(str(default_exception.default_content_type)): + fn = "_failsafe_deserialize_xml" + else: + fn = "_failsafe_deserialize" retval.extend( [ - f"{indent}error = _failsafe_deserialize(", + f"{indent}error = {fn}(", f"{indent} {default_error_deserialization}", f"{indent} response,", f"{indent})",