@autorest/python 6.37.2 → 6.38.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/autorest/__init__.py +13 -0
  2. package/autorest/codegen.py +1 -0
  3. package/generator/build/lib/pygen/__init__.py +32 -2
  4. package/generator/build/lib/pygen/codegen/models/code_model.py +32 -0
  5. package/generator/build/lib/pygen/codegen/models/enum_type.py +4 -1
  6. package/generator/build/lib/pygen/codegen/models/model_type.py +4 -1
  7. package/generator/build/lib/pygen/codegen/models/operation.py +3 -4
  8. package/generator/build/lib/pygen/codegen/models/paging_operation.py +1 -1
  9. package/generator/build/lib/pygen/codegen/serializers/__init__.py +85 -74
  10. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +7 -6
  11. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +86 -13
  12. package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +5 -4
  13. package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +109 -0
  14. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  15. package/generator/pygen/__init__.py +32 -2
  16. package/generator/pygen/codegen/models/code_model.py +32 -0
  17. package/generator/pygen/codegen/models/enum_type.py +4 -1
  18. package/generator/pygen/codegen/models/model_type.py +4 -1
  19. package/generator/pygen/codegen/models/operation.py +3 -4
  20. package/generator/pygen/codegen/models/paging_operation.py +1 -1
  21. package/generator/pygen/codegen/serializers/__init__.py +85 -74
  22. package/generator/pygen/codegen/serializers/builder_serializer.py +7 -6
  23. package/generator/pygen/codegen/serializers/general_serializer.py +86 -13
  24. package/generator/pygen/codegen/templates/model_base.py.jinja2 +5 -4
  25. package/generator/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +109 -0
  26. package/generator/pygen.egg-info/SOURCES.txt +1 -0
  27. package/package.json +2 -2
  28. package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
@@ -1032,7 +1032,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
1032
1032
  is_operation_file=True, skip_quote=True, serialize_namespace=self.serialize_namespace
1033
1033
  )
1034
1034
  if self.code_model.options["models-mode"] == "dpg":
1035
- retval.append(f" error = _failsafe_deserialize({type_annotation}, response.json())")
1035
+ retval.append(f" error = _failsafe_deserialize({type_annotation}, response)")
1036
1036
  else:
1037
1037
  retval.append(
1038
1038
  f" error = self._deserialize.failsafe_deserialize({type_annotation}, "
@@ -1068,10 +1068,10 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
1068
1068
  if self.code_model.options["models-mode"] == "dpg":
1069
1069
  if xml_serializable(str(e.default_content_type)):
1070
1070
  retval.append(
1071
- f" error = _failsafe_deserialize_xml({type_annotation}, response.text())"
1071
+ f" error = _failsafe_deserialize_xml({type_annotation}, response)"
1072
1072
  )
1073
1073
  else:
1074
- retval.append(f" error = _failsafe_deserialize({type_annotation}, response.json())")
1074
+ retval.append(f" error = _failsafe_deserialize({type_annotation}, response)")
1075
1075
  else:
1076
1076
  retval.append(
1077
1077
  f" error = self._deserialize.failsafe_deserialize({type_annotation}, "
@@ -1079,18 +1079,19 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
1079
1079
  )
1080
1080
  condition = "elif"
1081
1081
  # default error handling
1082
- if builder.default_error_deserialization and self.code_model.options["models-mode"]:
1082
+ default_error_deserialization = builder.default_error_deserialization(self.serialize_namespace)
1083
+ if default_error_deserialization and self.code_model.options["models-mode"]:
1083
1084
  error_model = ", model=error"
1084
1085
  indent = " " if builder.non_default_errors else " "
1085
1086
  if builder.non_default_errors:
1086
1087
  retval.append(" else:")
1087
1088
  if self.code_model.options["models-mode"] == "dpg":
1088
1089
  retval.append(
1089
- f"{indent}error = _failsafe_deserialize({builder.default_error_deserialization}, response.json())"
1090
+ f"{indent}error = _failsafe_deserialize({default_error_deserialization}, response)"
1090
1091
  )
1091
1092
  else:
1092
1093
  retval.append(
1093
- f"{indent}error = self._deserialize.failsafe_deserialize({builder.default_error_deserialization}, "
1094
+ f"{indent}error = self._deserialize.failsafe_deserialize({default_error_deserialization}, "
1094
1095
  "pipeline_response)"
1095
1096
  )
1096
1097
  retval.append(
@@ -4,7 +4,10 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  import json
7
- from typing import Any, List
7
+ from typing import Any, List, TYPE_CHECKING
8
+ import re
9
+ import tomli as tomllib
10
+ from packaging.version import parse as parse_version
8
11
  from .import_serializer import FileImportSerializer, TypingSection
9
12
  from ..models.imports import MsrestImportType, FileImport
10
13
  from ..models import (
@@ -16,6 +19,9 @@ from ..models.utils import NamespaceType
16
19
  from .client_serializer import ClientSerializer, ConfigSerializer
17
20
  from .base_serializer import BaseSerializer
18
21
 
22
+ if TYPE_CHECKING:
23
+ from pathlib import Path
24
+
19
25
  VERSION_MAP = {
20
26
  "msrest": "0.7.1",
21
27
  "isodate": "0.6.1",
@@ -42,8 +48,73 @@ class GeneralSerializer(BaseSerializer):
42
48
  params.update({"options": self.code_model.options})
43
49
  return template.render(code_model=self.code_model, **params)
44
50
 
45
- def serialize_package_file(self, template_name: str, **kwargs: Any) -> str:
51
+ def _extract_min_dependency(self, s):
52
+ # Extract the minimum version from a dependency string.
53
+ #
54
+ # Handles formats like:
55
+ # - >=1.2.3
56
+ # - >=0.1.0b1 (beta versions)
57
+ # - >=1.2.3rc2 (release candidates)
58
+ #
59
+ # Returns the parsed version if found, otherwise version "0".
60
+ m = re.search(r"[>=]=?([\d.]+(?:[a-z]+\d+)?)", s)
61
+ return parse_version(m.group(1)) if m else parse_version("0")
62
+
63
+ def _keep_pyproject_fields(self, file_path: "Path") -> dict:
64
+ # Load the pyproject.toml file if it exists and extract fields to keep.
65
+ result: dict = {"KEEP_FIELDS": {}}
66
+ try:
67
+ with open(file_path, "rb") as f:
68
+ loaded_pyproject_toml = tomllib.load(f)
69
+ except Exception: # pylint: disable=broad-except
70
+ # If parsing the pyproject.toml fails, we assume the it does not exist or is incorrectly formatted.
71
+ return result
72
+
73
+ # Keep azure-sdk-build configuration
74
+ if "tool" in loaded_pyproject_toml and "azure-sdk-build" in loaded_pyproject_toml["tool"]:
75
+ result["KEEP_FIELDS"]["tool.azure-sdk-build"] = loaded_pyproject_toml["tool"]["azure-sdk-build"]
76
+
77
+ # Process dependencies
78
+ if "project" in loaded_pyproject_toml:
79
+ # Handle main dependencies
80
+ if "dependencies" in loaded_pyproject_toml["project"]:
81
+ kept_deps = []
82
+ for dep in loaded_pyproject_toml["project"]["dependencies"]:
83
+ dep_name = re.split(r"[<>=\[]", dep)[0].strip()
84
+
85
+ # Check if dependency is one we track in VERSION_MAP
86
+ if dep_name in VERSION_MAP:
87
+ # For tracked dependencies, check if the version is higher than our default
88
+ default_version = parse_version(VERSION_MAP[dep_name])
89
+ dep_version = self._extract_min_dependency(dep)
90
+ # If the version is higher than the default, update VERSION_MAP
91
+ # with higher min dependency version
92
+ if dep_version > default_version:
93
+ VERSION_MAP[dep_name] = str(dep_version)
94
+ else:
95
+ # Keep non-default dependencies
96
+ kept_deps.append(dep)
97
+
98
+ if kept_deps:
99
+ result["KEEP_FIELDS"]["project.dependencies"] = kept_deps
100
+
101
+ # Keep optional dependencies
102
+ if "optional-dependencies" in loaded_pyproject_toml["project"]:
103
+ result["KEEP_FIELDS"]["project.optional-dependencies"] = loaded_pyproject_toml["project"][
104
+ "optional-dependencies"
105
+ ]
106
+
107
+ return result
108
+
109
+ def serialize_package_file(self, template_name: str, file_path: "Path", **kwargs: Any) -> str:
46
110
  template = self.env.get_template(template_name)
111
+
112
+ # Add fields to keep from an existing pyproject.toml
113
+ if template_name == "pyproject.toml.jinja2":
114
+ params = self._keep_pyproject_fields(file_path)
115
+ else:
116
+ params = {}
117
+
47
118
  package_parts = (
48
119
  self.code_model.namespace.split(".")[:-1]
49
120
  if self.code_model.is_tsp
@@ -57,17 +128,19 @@ class GeneralSerializer(BaseSerializer):
57
128
  dev_status = "4 - Beta"
58
129
  else:
59
130
  dev_status = "5 - Production/Stable"
60
- params = {
61
- "code_model": self.code_model,
62
- "dev_status": dev_status,
63
- "token_credential": token_credential,
64
- "pkgutil_names": [".".join(package_parts[: i + 1]) for i in range(len(package_parts))],
65
- "init_names": ["/".join(package_parts[: i + 1]) + "/__init__.py" for i in range(len(package_parts))],
66
- "client_name": self.code_model.clients[0].name if self.code_model.clients else "",
67
- "VERSION_MAP": VERSION_MAP,
68
- "MIN_PYTHON_VERSION": MIN_PYTHON_VERSION,
69
- "MAX_PYTHON_VERSION": MAX_PYTHON_VERSION,
70
- }
131
+ params.update(
132
+ {
133
+ "code_model": self.code_model,
134
+ "dev_status": dev_status,
135
+ "token_credential": token_credential,
136
+ "pkgutil_names": [".".join(package_parts[: i + 1]) for i in range(len(package_parts))],
137
+ "init_names": ["/".join(package_parts[: i + 1]) + "/__init__.py" for i in range(len(package_parts))],
138
+ "client_name": self.code_model.clients[0].name if self.code_model.clients else "",
139
+ "VERSION_MAP": VERSION_MAP,
140
+ "MIN_PYTHON_VERSION": MIN_PYTHON_VERSION,
141
+ "MAX_PYTHON_VERSION": MAX_PYTHON_VERSION,
142
+ }
143
+ )
71
144
  params.update({"options": self.code_model.options})
72
145
  params.update(kwargs)
73
146
  return template.render(file_import=FileImport(self.code_model), **params)
@@ -25,6 +25,7 @@ from {{ code_model.core_library }}.exceptions import DeserializationError
25
25
  from {{ code_model.core_library }}{{ "" if code_model.is_azure_flavor else ".utils" }} import CaseInsensitiveEnumMeta
26
26
  from {{ code_model.core_library }}.{{ "" if code_model.is_azure_flavor else "runtime." }}pipeline import PipelineResponse
27
27
  from {{ code_model.core_library }}.serialization import _Null
28
+ from {{ code_model.core_library }}.rest import HttpResponse
28
29
 
29
30
  _LOGGER = logging.getLogger(__name__)
30
31
 
@@ -935,13 +936,13 @@ def _deserialize(
935
936
 
936
937
  def _failsafe_deserialize(
937
938
  deserializer: typing.Any,
938
- value: typing.Any,
939
+ response: HttpResponse,
939
940
  module: typing.Optional[str] = None,
940
941
  rf: typing.Optional["_RestField"] = None,
941
942
  format: typing.Optional[str] = None,
942
943
  ) -> typing.Any:
943
944
  try:
944
- return _deserialize(deserializer, value, module, rf, format)
945
+ return _deserialize(deserializer, response.json(), module, rf, format)
945
946
  except DeserializationError:
946
947
  _LOGGER.warning(
947
948
  "Ran into a deserialization error. Ignoring since this is failsafe deserialization",
@@ -952,10 +953,10 @@ def _failsafe_deserialize(
952
953
 
953
954
  def _failsafe_deserialize_xml(
954
955
  deserializer: typing.Any,
955
- value: typing.Any,
956
+ response: HttpResponse,
956
957
  ) -> typing.Any:
957
958
  try:
958
- return _deserialize_xml(deserializer, value)
959
+ return _deserialize_xml(deserializer, response.text())
959
960
  except DeserializationError:
960
961
  _LOGGER.warning(
961
962
  "Ran into a deserialization error. Ignoring since this is failsafe deserialization",
@@ -0,0 +1,109 @@
1
+ {% set min_version = MIN_PYTHON_VERSION.split('.')[1] | int %}
2
+ {% set max_version = MAX_PYTHON_VERSION.split('.')[1] | int %}
3
+ {% if code_model.license_header %}
4
+ {{ code_model.license_header }}
5
+ {% endif %}
6
+
7
+ [build-system]
8
+ requires = ["setuptools>=77.0.3", "wheel"]
9
+ build-backend = "setuptools.build_meta"
10
+
11
+ [project]
12
+ name = "{{ options.get('package-name')|lower }}"
13
+ {% if options.get('package-mode') %}
14
+ authors = [
15
+ { name = "{{ code_model.company_name }}"{% if code_model.is_azure_flavor %}, email = "azpysdkhelp@microsoft.com"{% endif %} },
16
+ ]
17
+ description = "{{ code_model.company_name }} {% if code_model.is_azure_flavor and not options.get('package-pprint-name').startswith('Azure ') %}Azure {% endif %}{{ options.get('package-pprint-name') }} Client Library for Python"
18
+ license = "MIT"
19
+ classifiers = [
20
+ "Development Status :: {{ dev_status }}",
21
+ "Programming Language :: Python",
22
+ "Programming Language :: Python :: 3 :: Only",
23
+ "Programming Language :: Python :: 3",
24
+ {% for version in range(min_version, max_version + 1) %}
25
+ "Programming Language :: Python :: 3.{{ version }}",
26
+ {% endfor %}
27
+ ]
28
+ requires-python = ">={{ MIN_PYTHON_VERSION }}"
29
+ {% else %}
30
+ description = "{{ options.get('package-name') }}"
31
+ {% endif %}
32
+ {% if code_model.is_azure_flavor %}
33
+ keywords = ["azure", "azure sdk"]
34
+ {% endif %}
35
+
36
+ dependencies = [
37
+ {% if code_model.is_legacy %}
38
+ "msrest>={{ VERSION_MAP['msrest'] }}",
39
+ {% else %}
40
+ "isodate>={{ VERSION_MAP['isodate'] }}",
41
+ {% endif %}
42
+ {% if options.get('azure_arm') %}
43
+ "azure-mgmt-core>={{ VERSION_MAP['azure-mgmt-core'] }}",
44
+ {% elif code_model.is_azure_flavor %}
45
+ "azure-core>={{ VERSION_MAP['azure-core'] }}",
46
+ {% else %}
47
+ "corehttp[requests]>={{ VERSION_MAP['corehttp'] }}",
48
+ {% endif %}
49
+ "typing-extensions>={{ VERSION_MAP['typing-extensions'] }}",
50
+ {% if KEEP_FIELDS and KEEP_FIELDS.get('project.dependencies') %}
51
+ {% for dep in KEEP_FIELDS.get('project.dependencies') %}
52
+ "{{ dep }}",
53
+ {% endfor %}
54
+ {% endif %}
55
+ ]
56
+ dynamic = [
57
+ {% if options.get('package-mode') %}"version", {% endif %}"readme"
58
+ ]
59
+ {% if not options.get('package-mode') %}
60
+ version = "{{ options.get("package-version", "unknown") }}"
61
+ {% endif %}
62
+ {% if KEEP_FIELDS and KEEP_FIELDS.get('project.optional-dependencies') %}
63
+
64
+ [project.optional-dependencies]
65
+ {% for key, val in KEEP_FIELDS.get('project.optional-dependencies').items() %}
66
+ {{ key }} = [
67
+ {% for dep in val %}
68
+ "{{ dep }}",
69
+ {% endfor %}
70
+ ]
71
+ {% endfor %}
72
+ {% endif %}
73
+ {% if code_model.is_azure_flavor %}
74
+
75
+ [project.urls]
76
+ repository = "https://github.com/Azure/azure-sdk-for-python/tree/main/sdk"
77
+ {% endif %}
78
+
79
+ [tool.setuptools.dynamic]
80
+ {% if options.get('package-mode') %}
81
+ {% if code_model.is_tsp %}
82
+ version = {attr = "{{ code_model.namespace|lower }}._version.VERSION"}
83
+ {% else %}
84
+ version = {attr = "{{ options.get('package-name')|lower|replace('-', '.') }}._version.VERSION"}
85
+ {% endif %}
86
+ {% endif %}
87
+ readme = {file = ["README.md"], content-type = "text/markdown"}
88
+ {% if options.get('package-mode') %}
89
+
90
+ [tool.setuptools.packages.find]
91
+ exclude = [
92
+ "tests*",
93
+ "samples*",
94
+ "doc*",
95
+ {% for pkgutil_name in pkgutil_names %}
96
+ "{{ pkgutil_name }}",
97
+ {% endfor %}
98
+ ]
99
+
100
+ [tool.setuptools.package-data]
101
+ pytyped = ["py.typed"]
102
+ {% endif %}
103
+ {% if KEEP_FIELDS and KEEP_FIELDS.get('tool.azure-sdk-build') %}
104
+
105
+ [tool.azure-sdk-build]
106
+ {% for key, val in KEEP_FIELDS.get('tool.azure-sdk-build').items() %}
107
+ {{ key }} = {{ val|tojson }}
108
+ {% endfor %}
109
+ {% endif %}
@@ -25,10 +25,10 @@ class OptionsDict(MutableMapping):
25
25
  "azure-arm": False,
26
26
  "basic-setup-py": False,
27
27
  "client-side-validation": False,
28
- "emit-cross-language-definition-file": False,
29
28
  "flavor": "azure", # need to default to azure in shared code so we don't break swagger generation
30
29
  "from-typespec": False,
31
30
  "generate-sample": False,
31
+ "keep-setup-py": False,
32
32
  "generate-test": False,
33
33
  "head-as-boolean": True,
34
34
  "keep-version-file": False,
@@ -39,13 +39,14 @@ class OptionsDict(MutableMapping):
39
39
  "polymorphic-examples": 5,
40
40
  "validate-versioning": True,
41
41
  "version-tolerant": True,
42
+ "generation-subdir": None, # subdirectory to generate the code in
42
43
  }
43
44
 
44
45
  def __init__(self, options: Optional[Dict[str, Any]] = None) -> None:
45
46
  self._data = options.copy() if options else {}
46
47
  self._validate_combinations()
47
48
 
48
- def __getitem__(self, key: str) -> Any:
49
+ def __getitem__(self, key: str) -> Any: # pylint: disable=too-many-return-statements
49
50
  if key == "head-as-boolean" and self.get("azure-arm"):
50
51
  # override to always true if azure-arm is set
51
52
  return True
@@ -60,6 +61,18 @@ class OptionsDict(MutableMapping):
60
61
  if key == "package-mode" and self._data.get("packaging-files-dir"):
61
62
  # if packaging-files-dir is set, use it as package-mode
62
63
  return self._data["packaging-files-dir"]
64
+ if key == "generation-subdir":
65
+ data = self._data.get("generation-subdir")
66
+ if data:
67
+ # Remove leading dot or ./ from generation-subdir
68
+ if data.startswith("./"):
69
+ data = data[2:]
70
+ elif data.startswith("."):
71
+ data = data[1:]
72
+ # Remove trailing slashes
73
+ if data.endswith("/") or data.endswith("\\"):
74
+ data = data[:-1]
75
+ return data
63
76
  return self._get_default(key)
64
77
 
65
78
  def __setitem__(self, key: str, value: Any) -> None:
@@ -106,6 +119,8 @@ class OptionsDict(MutableMapping):
106
119
  models_mode_default = "dpg"
107
120
  # switch to falsy value for easier code writing
108
121
  return models_mode_default
122
+ if key == "emit-cross-language-definition-file":
123
+ return self.get("flavor") == "azure"
109
124
  return self.DEFAULTS[key]
110
125
 
111
126
  def _validate_combinations(self) -> None:
@@ -134,6 +149,10 @@ class OptionsDict(MutableMapping):
134
149
  "We are working on creating a new multiapi SDK for version tolerant and it is not available yet."
135
150
  )
136
151
 
152
+ # If multiapi, do not generate default pyproject.toml
153
+ if self.get("multiapi"):
154
+ self["keep-setup-py"] = True
155
+
137
156
  if self.get("client-side-validation") and self.get("version-tolerant"):
138
157
  raise ValueError("Can not generate version tolerant with --client-side-validation. ")
139
158
 
@@ -210,6 +229,9 @@ class ReaderAndWriter:
210
229
  _LOGGER.warning("Loading python.json file. This behavior will be depreacted")
211
230
  self.options.update(python_json)
212
231
 
232
+ def get_output_folder(self) -> Path:
233
+ return self.output_folder
234
+
213
235
  def read_file(self, path: Union[str, Path]) -> str:
214
236
  """Directly reading from disk"""
215
237
  # make path relative to output folder
@@ -227,6 +249,14 @@ class ReaderAndWriter:
227
249
  with open(self.output_folder / Path(filename), "w", encoding="utf-8") as fd:
228
250
  fd.write(file_content)
229
251
 
252
+ def remove_file(self, filename: Union[str, Path]) -> None:
253
+ try:
254
+ file_path = self.output_folder / Path(filename)
255
+ if file_path.is_file():
256
+ file_path.unlink()
257
+ except FileNotFoundError:
258
+ pass
259
+
230
260
  def list_file(self) -> List[str]:
231
261
  return [str(f.relative_to(self.output_folder)) for f in self.output_folder.glob("**/*") if f.is_file()]
232
262
 
@@ -3,6 +3,7 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
+ from pathlib import Path
6
7
  from typing import List, Dict, Any, Set, Union, Literal, Optional, cast
7
8
 
8
9
  from .base import BaseType
@@ -452,3 +453,34 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
452
453
  return self.yaml_data.get("licenseInfo", {}).get("company", "")
453
454
  # typespec azure case without custom license and swagger case
454
455
  return "Microsoft Corporation"
456
+
457
+ def get_root_dir(self) -> Path:
458
+ if self.options["no-namespace-folders"]:
459
+ # when output folder contains parts different from the namespace, we fall back to current folder directly.
460
+ return Path(".")
461
+ return Path(*self.namespace.split("."))
462
+
463
+ def get_generation_dir(self, namespace: str) -> Path:
464
+ """The directory to generate the code in.
465
+
466
+ If 'generation-subdir' is specified, it will be used as a subdirectory.
467
+ """
468
+ root_dir = self.get_root_dir()
469
+ retval = self._get_relative_generation_dir(root_dir, namespace)
470
+ return retval
471
+
472
+ def _get_relative_generation_dir(self, root_dir: Path, namespace: str) -> Path:
473
+ if self.options["no-namespace-folders"]:
474
+ return Path(".")
475
+ if self.options.get("generation-subdir"):
476
+ # For the main namespace, return root_dir + generation-subdir
477
+ if namespace in ("", self.namespace):
478
+ return root_dir / self.options["generation-subdir"]
479
+
480
+ # For subnamespaces, extract the subnamespace part and append it to generation-subdir
481
+ if namespace.startswith(self.namespace + "."):
482
+ subnamespace_parts = namespace[len(self.namespace) + 1 :].split(".")
483
+ return root_dir / self.options["generation-subdir"] / Path(*subnamespace_parts)
484
+
485
+ # No generation-subdir specified, use the namespace path directly
486
+ return Path(*namespace.split("."))
@@ -52,7 +52,10 @@ class EnumValue(BaseType):
52
52
  """The python type used for RST syntax input and type annotation."""
53
53
 
54
54
  type_annotation = self.value_type.type_annotation(**kwargs)
55
- enum_type_annotation = f"{self.enum_type.client_namespace}.models.{self.name}"
55
+ client_namespace = self.enum_type.client_namespace
56
+ if self.code_model.options.get("generation-subdir"):
57
+ client_namespace += f".{self.code_model.options['generation-subdir']}"
58
+ enum_type_annotation = f"{client_namespace}.models.{self.name}"
56
59
  return f"{type_annotation} or ~{enum_type_annotation}"
57
60
 
58
61
  def get_json_template_representation(
@@ -292,7 +292,10 @@ class GeneratedModelType(ModelType):
292
292
 
293
293
  def docstring_type(self, **kwargs: Any) -> str:
294
294
  type_annotation = self.type_annotation(need_model_alias=False, skip_quote=True, **kwargs)
295
- return f"~{self.client_namespace}.models.{type_annotation}"
295
+ client_namespace = self.client_namespace
296
+ if self.code_model.options.get("generation-subdir"):
297
+ client_namespace += f".{self.code_model.options['generation-subdir']}"
298
+ return f"~{client_namespace}.models.{type_annotation}"
296
299
 
297
300
  def docstring_text(self, **kwargs: Any) -> str:
298
301
  return self.name
@@ -194,14 +194,13 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
194
194
  def any_response_has_headers(self) -> bool:
195
195
  return any(response.headers for response in self.responses)
196
196
 
197
- @property
198
- def default_error_deserialization(self) -> Optional[str]:
197
+ def default_error_deserialization(self, serialize_namespace: str) -> Optional[str]:
199
198
  default_exceptions = [e for e in self.exceptions if "default" in e.status_codes and e.type]
200
199
  if not default_exceptions:
201
200
  return None
202
201
  exception_schema = default_exceptions[0].type
203
202
  if isinstance(exception_schema, ModelType):
204
- return exception_schema.type_annotation(skip_quote=True)
203
+ return exception_schema.type_annotation(skip_quote=True, serialize_namespace=serialize_namespace)
205
204
  return None if self.code_model.options["models-mode"] == "dpg" else "'object'"
206
205
 
207
206
  @property
@@ -469,7 +468,7 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
469
468
  file_import.add_submodule_import(relative_path, "_deserialize_xml", ImportType.LOCAL)
470
469
  elif self.need_deserialize:
471
470
  file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
472
- if self.default_error_deserialization or self.non_default_errors:
471
+ if self.default_error_deserialization(serialize_namespace) or self.non_default_errors:
473
472
  file_import.add_submodule_import(relative_path, "_failsafe_deserialize", ImportType.LOCAL)
474
473
  return file_import
475
474
 
@@ -173,7 +173,7 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
173
173
  serialize_namespace, module_name="_utils.model_base"
174
174
  )
175
175
  file_import.merge(self.item_type.imports(**kwargs))
176
- if self.default_error_deserialization or self.need_deserialize:
176
+ if self.default_error_deserialization(serialize_namespace) or self.need_deserialize:
177
177
  file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
178
178
  return file_import
179
179