From 1dd8fe8202212218321db88d365383371c323231 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 28 Jan 2026 11:40:10 -0500 Subject: [PATCH 1/5] failsafe deserialize xml errors --- .../pygen/codegen/serializers/builder_serializer.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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..0da134683fd 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 @@ -1062,8 +1062,12 @@ 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": + if xml_serializable(str(e.default_content_type)): + fn = "_failsafe_deserialize_xml" + else: + fn = "_failsafe_deserialize" retval.append( - f" error = _failsafe_deserialize({type_annotation},{pylint_disable}\n response)" + f" error = {fn}({type_annotation},{pylint_disable}\n response)" ) else: retval.extend( From daaef2903949ba08e96116547c42bd233602dc05 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 28 Jan 2026 11:40:45 -0500 Subject: [PATCH 2/5] add changeset --- .../python-xmlErrorDeserialization-2026-0-28-11-40-34.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .chronus/changes/python-xmlErrorDeserialization-2026-0-28-11-40-34.md 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 From c0cb91b76050725cbd08f17633fb2580899cd89c Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 28 Jan 2026 12:07:14 -0500 Subject: [PATCH 3/5] lint builder serializer --- .../pygen/codegen/serializers/builder_serializer.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 0da134683fd..7261211f878 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,7 @@ 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 builder.non_default_errors and self.code_model.options["models-mode"]: # pylint: disable=too-many-nested-blocks error_model = ", model=error" condition = "if" retval.append(" error = None") @@ -1066,9 +1066,7 @@ def handle_error_response( # pylint: disable=too-many-statements, too-many-bran fn = "_failsafe_deserialize_xml" else: fn = "_failsafe_deserialize" - retval.append( - f" error = {fn}({type_annotation},{pylint_disable}\n response)" - ) + retval.append(f" error = {fn}({type_annotation},{pylint_disable}\n response)") else: retval.extend( [ From 20514c29817dd0ae1854f4bfea98bf84e5de4f64 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 28 Jan 2026 12:24:10 -0500 Subject: [PATCH 4/5] get all instances of xml error --- .../generator/pygen/codegen/models/operation.py | 9 ++++++++- .../pygen/codegen/serializers/builder_serializer.py | 11 +++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) 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..9474b34c9dd 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,14 @@ 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 + ) + default_error = next(e for e in self.exceptions if "default" in e.status_codes and e.type) + if xml_non_default_errors or 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 7261211f878..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"]: # pylint: disable=too-many-nested-blocks + 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") @@ -1132,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})", From 65cbfa1a26252df13bd4d91e0e9187675ad5fc49 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 28 Jan 2026 14:00:48 -0500 Subject: [PATCH 5/5] fix stop iteration --- .../generator/pygen/codegen/models/operation.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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 9474b34c9dd..f5fb1c6241d 100644 --- a/packages/http-client-python/generator/pygen/codegen/models/operation.py +++ b/packages/http-client-python/generator/pygen/codegen/models/operation.py @@ -451,8 +451,13 @@ def imports( # pylint: disable=too-many-branches, disable=too-many-statements xml_non_default_errors = any( xml_serializable(str(e.default_content_type)) for e in self.non_default_errors ) - default_error = next(e for e in self.exceptions if "default" in e.status_codes and e.type) - if xml_non_default_errors or xml_serializable(str(default_error.default_content_type)): + 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)