@typespec/http-client-python 0.5.0 → 0.6.0

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 (163) hide show
  1. package/dist/emitter/code-model.d.ts.map +1 -1
  2. package/dist/emitter/code-model.js +10 -7
  3. package/dist/emitter/code-model.js.map +1 -1
  4. package/dist/emitter/emitter.d.ts.map +1 -1
  5. package/dist/emitter/emitter.js +35 -7
  6. package/dist/emitter/emitter.js.map +1 -1
  7. package/dist/emitter/http.js +1 -1
  8. package/dist/emitter/http.js.map +1 -1
  9. package/dist/emitter/lib.d.ts +1 -0
  10. package/dist/emitter/lib.d.ts.map +1 -1
  11. package/dist/emitter/lib.js +1 -0
  12. package/dist/emitter/lib.js.map +1 -1
  13. package/dist/emitter/types.d.ts.map +1 -1
  14. package/dist/emitter/types.js +7 -4
  15. package/dist/emitter/types.js.map +1 -1
  16. package/dist/emitter/utils.d.ts +1 -0
  17. package/dist/emitter/utils.d.ts.map +1 -1
  18. package/dist/emitter/utils.js +19 -0
  19. package/dist/emitter/utils.js.map +1 -1
  20. package/emitter/src/code-model.ts +16 -6
  21. package/emitter/src/emitter.ts +37 -11
  22. package/emitter/src/http.ts +1 -1
  23. package/emitter/src/lib.ts +4 -0
  24. package/emitter/src/types.ts +16 -4
  25. package/emitter/src/utils.ts +27 -0
  26. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  27. package/eng/scripts/Test-Packages.ps1 +1 -1
  28. package/eng/scripts/ci/regenerate.ts +21 -14
  29. package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
  30. package/eng/scripts/setup/install.py +0 -5
  31. package/eng/scripts/setup/install.ts +0 -20
  32. package/generator/build/lib/pygen/black.py +2 -2
  33. package/generator/build/lib/pygen/codegen/__init__.py +6 -4
  34. package/generator/build/lib/pygen/codegen/_utils.py +4 -0
  35. package/generator/build/lib/pygen/codegen/models/base.py +2 -3
  36. package/generator/build/lib/pygen/codegen/models/base_builder.py +5 -3
  37. package/generator/build/lib/pygen/codegen/models/client.py +28 -19
  38. package/generator/build/lib/pygen/codegen/models/code_model.py +200 -33
  39. package/generator/build/lib/pygen/codegen/models/combined_type.py +8 -5
  40. package/generator/build/lib/pygen/codegen/models/constant_type.py +2 -3
  41. package/generator/build/lib/pygen/codegen/models/credential_types.py +1 -2
  42. package/generator/build/lib/pygen/codegen/models/dictionary_type.py +2 -3
  43. package/generator/build/lib/pygen/codegen/models/enum_type.py +47 -24
  44. package/generator/build/lib/pygen/codegen/models/imports.py +14 -12
  45. package/generator/build/lib/pygen/codegen/models/list_type.py +2 -3
  46. package/generator/build/lib/pygen/codegen/models/lro_operation.py +8 -4
  47. package/generator/build/lib/pygen/codegen/models/lro_paging_operation.py +2 -2
  48. package/generator/build/lib/pygen/codegen/models/model_type.py +34 -19
  49. package/generator/build/lib/pygen/codegen/models/operation.py +66 -29
  50. package/generator/build/lib/pygen/codegen/models/operation_group.py +56 -11
  51. package/generator/build/lib/pygen/codegen/models/paging_operation.py +9 -6
  52. package/generator/build/lib/pygen/codegen/models/parameter.py +10 -10
  53. package/generator/build/lib/pygen/codegen/models/parameter_list.py +7 -7
  54. package/generator/build/lib/pygen/codegen/models/primitive_types.py +23 -43
  55. package/generator/build/lib/pygen/codegen/models/property.py +7 -7
  56. package/generator/build/lib/pygen/codegen/models/request_builder.py +9 -15
  57. package/generator/build/lib/pygen/codegen/models/response.py +6 -8
  58. package/generator/build/lib/pygen/codegen/models/utils.py +11 -0
  59. package/generator/build/lib/pygen/codegen/serializers/__init__.py +201 -242
  60. package/generator/build/lib/pygen/codegen/serializers/base_serializer.py +19 -1
  61. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +53 -35
  62. package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +9 -5
  63. package/generator/build/lib/pygen/codegen/serializers/enum_serializer.py +17 -3
  64. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +26 -14
  65. package/generator/build/lib/pygen/codegen/serializers/metadata_serializer.py +26 -8
  66. package/generator/build/lib/pygen/codegen/serializers/model_init_serializer.py +9 -4
  67. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +62 -22
  68. package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +19 -16
  69. package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +5 -10
  70. package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +10 -7
  71. package/generator/build/lib/pygen/codegen/serializers/request_builders_serializer.py +10 -1
  72. package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +7 -10
  73. package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +24 -28
  74. package/generator/build/lib/pygen/codegen/serializers/types_serializer.py +6 -1
  75. package/generator/build/lib/pygen/codegen/serializers/utils.py +1 -15
  76. package/generator/build/lib/pygen/codegen/templates/client_container.py.jinja2 +1 -1
  77. package/generator/build/lib/pygen/codegen/templates/config_container.py.jinja2 +1 -1
  78. package/generator/build/lib/pygen/codegen/templates/enum_container.py.jinja2 +1 -1
  79. package/generator/build/lib/pygen/codegen/templates/init.py.jinja2 +1 -1
  80. package/generator/build/lib/pygen/codegen/templates/model_container.py.jinja2 +1 -1
  81. package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +2 -4
  82. package/generator/build/lib/pygen/codegen/templates/test.py.jinja2 +3 -3
  83. package/generator/build/lib/pygen/codegen/templates/testpreparer.py.jinja2 +2 -2
  84. package/generator/build/lib/pygen/codegen/templates/vendor.py.jinja2 +4 -4
  85. package/generator/build/lib/pygen/preprocess/__init__.py +0 -4
  86. package/generator/dev_requirements.txt +2 -2
  87. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  88. package/generator/pygen/black.py +2 -2
  89. package/generator/pygen/codegen/__init__.py +6 -4
  90. package/generator/pygen/codegen/_utils.py +4 -0
  91. package/generator/pygen/codegen/models/base.py +2 -3
  92. package/generator/pygen/codegen/models/base_builder.py +5 -3
  93. package/generator/pygen/codegen/models/client.py +28 -19
  94. package/generator/pygen/codegen/models/code_model.py +200 -33
  95. package/generator/pygen/codegen/models/combined_type.py +8 -5
  96. package/generator/pygen/codegen/models/constant_type.py +2 -3
  97. package/generator/pygen/codegen/models/credential_types.py +1 -2
  98. package/generator/pygen/codegen/models/dictionary_type.py +2 -3
  99. package/generator/pygen/codegen/models/enum_type.py +47 -24
  100. package/generator/pygen/codegen/models/imports.py +14 -12
  101. package/generator/pygen/codegen/models/list_type.py +2 -3
  102. package/generator/pygen/codegen/models/lro_operation.py +8 -4
  103. package/generator/pygen/codegen/models/lro_paging_operation.py +2 -2
  104. package/generator/pygen/codegen/models/model_type.py +34 -19
  105. package/generator/pygen/codegen/models/operation.py +66 -29
  106. package/generator/pygen/codegen/models/operation_group.py +56 -11
  107. package/generator/pygen/codegen/models/paging_operation.py +9 -6
  108. package/generator/pygen/codegen/models/parameter.py +10 -10
  109. package/generator/pygen/codegen/models/parameter_list.py +7 -7
  110. package/generator/pygen/codegen/models/primitive_types.py +23 -43
  111. package/generator/pygen/codegen/models/property.py +7 -7
  112. package/generator/pygen/codegen/models/request_builder.py +9 -15
  113. package/generator/pygen/codegen/models/response.py +6 -8
  114. package/generator/pygen/codegen/models/utils.py +11 -0
  115. package/generator/pygen/codegen/serializers/__init__.py +201 -242
  116. package/generator/pygen/codegen/serializers/base_serializer.py +19 -1
  117. package/generator/pygen/codegen/serializers/builder_serializer.py +53 -35
  118. package/generator/pygen/codegen/serializers/client_serializer.py +9 -5
  119. package/generator/pygen/codegen/serializers/enum_serializer.py +17 -3
  120. package/generator/pygen/codegen/serializers/general_serializer.py +26 -14
  121. package/generator/pygen/codegen/serializers/metadata_serializer.py +26 -8
  122. package/generator/pygen/codegen/serializers/model_init_serializer.py +9 -4
  123. package/generator/pygen/codegen/serializers/model_serializer.py +62 -22
  124. package/generator/pygen/codegen/serializers/operation_groups_serializer.py +19 -16
  125. package/generator/pygen/codegen/serializers/operations_init_serializer.py +5 -10
  126. package/generator/pygen/codegen/serializers/parameter_serializer.py +10 -7
  127. package/generator/pygen/codegen/serializers/request_builders_serializer.py +10 -1
  128. package/generator/pygen/codegen/serializers/sample_serializer.py +7 -10
  129. package/generator/pygen/codegen/serializers/test_serializer.py +24 -28
  130. package/generator/pygen/codegen/serializers/types_serializer.py +6 -1
  131. package/generator/pygen/codegen/serializers/utils.py +1 -15
  132. package/generator/pygen/codegen/templates/client_container.py.jinja2 +1 -1
  133. package/generator/pygen/codegen/templates/config_container.py.jinja2 +1 -1
  134. package/generator/pygen/codegen/templates/enum_container.py.jinja2 +1 -1
  135. package/generator/pygen/codegen/templates/init.py.jinja2 +1 -1
  136. package/generator/pygen/codegen/templates/model_container.py.jinja2 +1 -1
  137. package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +2 -4
  138. package/generator/pygen/codegen/templates/test.py.jinja2 +3 -3
  139. package/generator/pygen/codegen/templates/testpreparer.py.jinja2 +2 -2
  140. package/generator/pygen/codegen/templates/vendor.py.jinja2 +4 -4
  141. package/generator/pygen/preprocess/__init__.py +0 -4
  142. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_flatten_async.py +1 -1
  143. package/generator/test/{generic_mock_api_tests/asynctests/test_payload_pageable_async.py → azure/mock_api_tests/asynctests/test_azure_payload_pageable_async.py} +1 -1
  144. package/generator/test/azure/mock_api_tests/asynctests/test_client_namespace_async.py +31 -0
  145. package/generator/test/azure/mock_api_tests/conftest.py +5 -4
  146. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_flatten.py +1 -1
  147. package/generator/test/{generic_mock_api_tests/test_payload_pageable.py → azure/mock_api_tests/test_azure_payload_pageable.py} +1 -1
  148. package/generator/test/azure/mock_api_tests/test_client_namespace.py +29 -0
  149. package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_resiliency_srv_driven.py +4 -2
  150. package/generator/test/{generic_mock_api_tests/asynctests → azure/mock_api_tests}/test_resiliency_srv_driven_async.py +4 -2
  151. package/generator/test/azure/requirements.txt +11 -9
  152. package/generator/test/azure/tox.ini +2 -2
  153. package/generator/test/generic_mock_api_tests/conftest.py +9 -4
  154. package/generator/test/unbranded/mock_api_tests/conftest.py +4 -4
  155. package/generator/test/unbranded/mock_api_tests/test_unbranded.py +1 -1
  156. package/generator/test/unbranded/requirements.txt +2 -9
  157. package/generator/test/unbranded/tox.ini +2 -2
  158. package/package.json +5 -6
  159. package/generator/requirements.txt +0 -7
  160. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/asynctests/test_client_naming_async.py +0 -0
  161. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/asynctests/test_client_structure_async.py +0 -0
  162. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_client_naming.py +0 -0
  163. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_client_structure.py +0 -0
@@ -131,8 +131,7 @@ class CredentialType(Generic[CredentialPolicyType], BaseType):
131
131
  def docstring_text(self, **kwargs: Any) -> str:
132
132
  return "credential"
133
133
 
134
- @property
135
- def serialization_type(self) -> str:
134
+ def serialization_type(self, **kwargs: Any) -> str:
136
135
  return self.docstring_type()
137
136
 
138
137
  @classmethod
@@ -34,14 +34,13 @@ class DictionaryType(BaseType):
34
34
  def encode(self) -> Optional[str]:
35
35
  return self.element_type.encode if hasattr(self.element_type, "encode") else None # type: ignore
36
36
 
37
- @property
38
- def serialization_type(self) -> str:
37
+ def serialization_type(self, **kwargs: Any) -> str:
39
38
  """Returns the serialization value for msrest.
40
39
 
41
40
  :return: The serialization value for msrest
42
41
  :rtype: str
43
42
  """
44
- return f"{{{self.element_type.serialization_type}}}"
43
+ return f"{{{self.element_type.serialization_type(**kwargs)}}}"
45
44
 
46
45
  def type_annotation(self, **kwargs: Any) -> str:
47
46
  """The python type used for type annotation
@@ -7,6 +7,8 @@ from typing import Any, Dict, List, TYPE_CHECKING, Optional, cast
7
7
 
8
8
  from .base import BaseType
9
9
  from .imports import FileImport, ImportType, TypingSection
10
+ from .utils import NamespaceType
11
+
10
12
 
11
13
  if TYPE_CHECKING:
12
14
  from .code_model import CodeModel
@@ -63,9 +65,8 @@ class EnumValue(BaseType):
63
65
  client_default_value_declaration=client_default_value_declaration,
64
66
  )
65
67
 
66
- @property
67
- def serialization_type(self) -> str:
68
- return self.value_type.serialization_type
68
+ def serialization_type(self, **kwargs: Any) -> str:
69
+ return self.value_type.serialization_type(**kwargs)
69
70
 
70
71
  @property
71
72
  def instance_check_template(self) -> str:
@@ -75,7 +76,17 @@ class EnumValue(BaseType):
75
76
  file_import = FileImport(self.code_model)
76
77
  file_import.merge(self.value_type.imports(**kwargs))
77
78
  file_import.add_submodule_import("typing", "Literal", ImportType.STDLIB, TypingSection.REGULAR)
78
- file_import.add_submodule_import("._enums", self.enum_type.name, ImportType.LOCAL, TypingSection.REGULAR)
79
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
80
+ file_import.add_submodule_import(
81
+ self.code_model.get_relative_import_path(
82
+ serialize_namespace,
83
+ self.code_model.get_imported_namespace_for_model(self.enum_type.client_namespace),
84
+ module_name=self.code_model.enums_filename,
85
+ ),
86
+ self.enum_type.name,
87
+ ImportType.LOCAL,
88
+ TypingSection.REGULAR,
89
+ )
79
90
 
80
91
  return file_import
81
92
 
@@ -124,18 +135,18 @@ class EnumType(BaseType):
124
135
  self.value_type = value_type
125
136
  self.internal: bool = self.yaml_data.get("internal", False)
126
137
  self.cross_language_definition_id: Optional[str] = self.yaml_data.get("crossLanguageDefinitionId")
138
+ self.client_namespace: str = self.yaml_data.get("clientNamespace", code_model.namespace)
127
139
 
128
140
  def __lt__(self, other):
129
141
  return self.name.lower() < other.name.lower()
130
142
 
131
- @property
132
- def serialization_type(self) -> str:
143
+ def serialization_type(self, **kwargs: Any) -> str:
133
144
  """Returns the serialization value for msrest.
134
145
 
135
146
  :return: The serialization value for msrest
136
147
  :rtype: str
137
148
  """
138
- return self.value_type.serialization_type
149
+ return self.value_type.serialization_type(**kwargs)
139
150
 
140
151
  def description(self, *, is_operation_file: bool) -> str:
141
152
  possible_values = [self.get_declaration(v.value) for v in self.values]
@@ -160,7 +171,12 @@ class EnumType(BaseType):
160
171
  :rtype: str
161
172
  """
162
173
  if self.code_model.options["models_mode"]:
163
- module_name = "_models." if kwargs.get("need_module_name", True) else ""
174
+
175
+ module_name = ""
176
+ if kwargs.get("need_model_alias", True):
177
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
178
+ model_alias = self.code_model.get_unique_models_alias(serialize_namespace, self.client_namespace)
179
+ module_name = f"{model_alias}."
164
180
  file_name = f"{self.code_model.enums_filename}." if self.internal else ""
165
181
  model_name = module_name + file_name + self.name
166
182
  # we don't need quoted annotation in operation files, and need it in model folder files.
@@ -212,27 +228,34 @@ class EnumType(BaseType):
212
228
  )
213
229
 
214
230
  def imports(self, **kwargs: Any) -> FileImport:
215
- operation = kwargs.pop("operation", False)
216
231
  file_import = FileImport(self.code_model)
232
+ file_import.merge(self.value_type.imports(**kwargs))
217
233
  if self.code_model.options["models_mode"]:
218
234
  file_import.add_submodule_import("typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL)
219
- if not operation:
235
+
236
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
237
+ relative_path = self.code_model.get_relative_import_path(serialize_namespace, self.client_namespace)
238
+ alias = self.code_model.get_unique_models_alias(serialize_namespace, self.client_namespace)
239
+ serialize_namespace_type = kwargs.get("serialize_namespace_type")
240
+ called_by_property = kwargs.get("called_by_property", False)
241
+ if serialize_namespace_type in [NamespaceType.OPERATION, NamespaceType.CLIENT]:
220
242
  file_import.add_submodule_import(
221
- "..",
243
+ relative_path,
222
244
  "models",
223
245
  ImportType.LOCAL,
224
- TypingSection.TYPING,
225
- alias="_models",
246
+ alias=alias,
247
+ typing_section=TypingSection.REGULAR,
226
248
  )
227
- file_import.merge(self.value_type.imports(operation=operation, **kwargs))
228
- relative_path = kwargs.pop("relative_path", None)
229
- if self.code_model.options["models_mode"] and relative_path:
230
- # add import for enums in operations file
231
- file_import.add_submodule_import(
232
- relative_path,
233
- "models",
234
- ImportType.LOCAL,
235
- alias="_models",
236
- typing_section=(TypingSection.TYPING if kwargs.get("model_typing") else TypingSection.REGULAR),
237
- )
249
+ elif serialize_namespace_type == NamespaceType.TYPES_FILE or (
250
+ serialize_namespace_type == NamespaceType.MODEL and called_by_property
251
+ ):
252
+ file_import.add_submodule_import(
253
+ relative_path,
254
+ "models",
255
+ ImportType.LOCAL,
256
+ alias=alias,
257
+ typing_section=TypingSection.TYPING,
258
+ )
259
+
260
+ file_import.merge(self.value_type.imports(**kwargs))
238
261
  return file_import
@@ -5,6 +5,7 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from enum import Enum, auto
7
7
  from typing import Dict, List, Optional, Tuple, Union, Set, TYPE_CHECKING
8
+ from .._utils import get_parent_namespace
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from .code_model import CodeModel
@@ -259,7 +260,7 @@ class FileImport:
259
260
  def add_msrest_import(
260
261
  self,
261
262
  *,
262
- relative_path: str,
263
+ serialize_namespace: str,
263
264
  msrest_import_type: MsrestImportType,
264
265
  typing_section: TypingSection,
265
266
  ):
@@ -271,21 +272,22 @@ class FileImport:
271
272
  if msrest_import_type == MsrestImportType.SerializerDeserializer:
272
273
  self.add_submodule_import("msrest", "Deserializer", ImportType.THIRDPARTY, typing_section)
273
274
  else:
275
+ # _serialization.py is always in root namespace
276
+ imported_namespace = self.code_model.namespace
274
277
  if self.code_model.options["multiapi"]:
275
- relative_path += "."
278
+ # for multiapi, the namespace is azure.mgmt.xxx.v20XX_XX_XX while _serialization.py is in azure.mgmt.xxx
279
+ imported_namespace = get_parent_namespace(imported_namespace)
276
280
  if msrest_import_type == MsrestImportType.Module:
277
- self.add_submodule_import(relative_path, "_serialization", ImportType.LOCAL, typing_section)
278
- else:
279
281
  self.add_submodule_import(
280
- f"{relative_path}_serialization",
281
- "Serializer",
282
+ self.code_model.get_relative_import_path(serialize_namespace, imported_namespace),
283
+ "_serialization",
282
284
  ImportType.LOCAL,
283
285
  typing_section,
284
286
  )
287
+ else:
288
+ relative_path = self.code_model.get_relative_import_path(
289
+ serialize_namespace, imported_namespace, module_name="_serialization"
290
+ )
291
+ self.add_submodule_import(relative_path, "Serializer", ImportType.LOCAL, typing_section)
285
292
  if msrest_import_type == MsrestImportType.SerializerDeserializer:
286
- self.add_submodule_import(
287
- f"{relative_path}_serialization",
288
- "Deserializer",
289
- ImportType.LOCAL,
290
- typing_section,
291
- )
293
+ self.add_submodule_import(relative_path, "Deserializer", ImportType.LOCAL, typing_section)
@@ -29,9 +29,8 @@ class ListType(BaseType):
29
29
  def encode(self) -> Optional[str]:
30
30
  return self.element_type.encode if hasattr(self.element_type, "encode") else None # type: ignore
31
31
 
32
- @property
33
- def serialization_type(self) -> str:
34
- return f"[{self.element_type.serialization_type}]"
32
+ def serialization_type(self, **kwargs: Any) -> str:
33
+ return f"[{self.element_type.serialization_type(**kwargs)}]"
35
34
 
36
35
  def type_annotation(self, **kwargs: Any) -> str:
37
36
  if (
@@ -92,9 +92,9 @@ class LROOperationBase(OperationBase[LROResponseType]):
92
92
  return lro_response.type_annotation(**kwargs)
93
93
  return "None"
94
94
 
95
- def cls_type_annotation(self, *, async_mode: bool) -> str:
95
+ def cls_type_annotation(self, *, async_mode: bool, **kwargs: Any) -> str:
96
96
  """We don't want the poller to show up in ClsType, so we call super() on response type annotation"""
97
- return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode)}]"
97
+ return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode, **kwargs)}]"
98
98
 
99
99
  def get_poller_with_response_type(self, async_mode: bool) -> str:
100
100
  return self.response_type_annotation(async_mode=async_mode)
@@ -132,8 +132,12 @@ class LROOperationBase(OperationBase[LROResponseType]):
132
132
  ):
133
133
  # used in the case if initial operation returns none
134
134
  # but final call returns a model
135
- relative_path = "..." if async_mode else ".."
136
- file_import.add_submodule_import(f"{relative_path}_model_base", "_deserialize", ImportType.LOCAL)
135
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
136
+ file_import.add_submodule_import(
137
+ self.code_model.get_relative_import_path(serialize_namespace, module_name="_model_base"),
138
+ "_deserialize",
139
+ ImportType.LOCAL,
140
+ )
137
141
  file_import.add_submodule_import("typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL)
138
142
  file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
139
143
  return file_import
@@ -20,8 +20,8 @@ class LROPagingOperation(LROOperationBase[LROPagingResponse], PagingOperationBas
20
20
  def operation_type(self) -> str:
21
21
  return "lropaging"
22
22
 
23
- def cls_type_annotation(self, *, async_mode: bool) -> str:
24
- return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode)}]"
23
+ def cls_type_annotation(self, *, async_mode: bool, **kwargs: Any) -> str:
24
+ return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode, **kwargs)}]"
25
25
 
26
26
  def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
27
27
  lro_imports = LROOperationBase.imports(self, async_mode, **kwargs)
@@ -7,7 +7,7 @@ from enum import Enum
7
7
  from collections import OrderedDict
8
8
  from typing import Any, Dict, List, Optional, TYPE_CHECKING, cast
9
9
  import sys
10
- from .utils import add_to_pylint_disable
10
+ from .utils import add_to_pylint_disable, NamespaceType
11
11
  from .base import BaseType
12
12
  from .constant_type import ConstantType
13
13
  from .property import Property
@@ -82,6 +82,7 @@ class ModelType(BaseType): # pylint: disable=too-many-instance-attributes, too-
82
82
  self.snake_case_name: str = self.yaml_data["snakeCaseName"]
83
83
  self.cross_language_definition_id: Optional[str] = self.yaml_data.get("crossLanguageDefinitionId")
84
84
  self.usage: int = self.yaml_data.get("usage", UsageFlags.Input.value | UsageFlags.Output.value)
85
+ self.client_namespace: str = self.yaml_data.get("clientNamespace", code_model.namespace)
85
86
 
86
87
  @property
87
88
  def is_usage_output(self) -> bool:
@@ -254,8 +255,7 @@ class JSONModelType(ModelType):
254
255
  def type_annotation(self, **kwargs: Any) -> str:
255
256
  return "ET.Element" if self.is_xml else "JSON"
256
257
 
257
- @property
258
- def serialization_type(self) -> str:
258
+ def serialization_type(self, **kwargs: Any) -> str:
259
259
  return "object"
260
260
 
261
261
  def docstring_type(self, **kwargs: Any) -> str:
@@ -281,13 +281,18 @@ class GeneratedModelType(ModelType):
281
281
  def type_annotation(self, **kwargs: Any) -> str:
282
282
  is_operation_file = kwargs.pop("is_operation_file", False)
283
283
  skip_quote = kwargs.get("skip_quote", False)
284
- module_name = "_models." if kwargs.get("need_module_name", True) else ""
284
+ module_name = ""
285
+ if kwargs.get("need_model_alias", True):
286
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
287
+ model_alias = self.code_model.get_unique_models_alias(serialize_namespace, self.client_namespace)
288
+ module_name = f"{model_alias}."
285
289
  file_name = f"{self.code_model.models_filename}." if self.internal else ""
286
290
  retval = module_name + file_name + self.name
287
291
  return retval if is_operation_file or skip_quote else f'"{retval}"'
288
292
 
289
293
  def docstring_type(self, **kwargs: Any) -> str:
290
- return f"~{self.code_model.namespace}.models.{self.type_annotation(need_module_name=False, skip_quote=True)}"
294
+ type_annotation = self.type_annotation(need_model_alias=False, skip_quote=True, **kwargs)
295
+ return f"~{self.code_model.namespace}.models.{type_annotation}"
291
296
 
292
297
  def docstring_text(self, **kwargs: Any) -> str:
293
298
  return self.name
@@ -298,32 +303,43 @@ class GeneratedModelType(ModelType):
298
303
 
299
304
  def imports(self, **kwargs: Any) -> FileImport:
300
305
  file_import = super().imports(**kwargs)
301
- relative_path = kwargs.pop("relative_path", None)
302
- if relative_path:
303
- # add import for models in operations or _types file
306
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
307
+ relative_path = self.code_model.get_relative_import_path(serialize_namespace, self.client_namespace)
308
+ alias = self.code_model.get_unique_models_alias(serialize_namespace, self.client_namespace)
309
+ serialize_namespace_type = kwargs.get("serialize_namespace_type")
310
+ called_by_property = kwargs.get("called_by_property", False)
311
+ # add import for models in operations or _types file
312
+ if serialize_namespace_type in [NamespaceType.OPERATION, NamespaceType.CLIENT]:
304
313
  file_import.add_submodule_import(
305
314
  relative_path,
306
315
  "models",
307
316
  ImportType.LOCAL,
308
- alias="_models",
309
- typing_section=(TypingSection.TYPING if kwargs.get("model_typing") else TypingSection.REGULAR),
317
+ alias=alias,
310
318
  )
311
319
  if self.is_form_data:
312
320
  file_import.add_submodule_import(
313
- relative_path,
321
+ self.code_model.get_relative_import_path(serialize_namespace),
314
322
  "_model_base",
315
323
  ImportType.LOCAL,
316
- typing_section=(TypingSection.TYPING if kwargs.get("model_typing") else TypingSection.REGULAR),
317
324
  )
325
+ elif serialize_namespace_type == NamespaceType.TYPES_FILE or (
326
+ serialize_namespace_type == NamespaceType.MODEL and called_by_property
327
+ ):
328
+ file_import.add_submodule_import(
329
+ relative_path,
330
+ "models",
331
+ ImportType.LOCAL,
332
+ alias=alias,
333
+ typing_section=TypingSection.TYPING,
334
+ )
318
335
  return file_import
319
336
 
320
337
 
321
338
  class MsrestModelType(GeneratedModelType):
322
339
  base = "msrest"
323
340
 
324
- @property
325
- def serialization_type(self) -> str:
326
- return self.type_annotation(skip_quote=True) if self.internal else self.name
341
+ def serialization_type(self, **kwargs: Any) -> str:
342
+ return self.type_annotation(skip_quote=True, **kwargs) if self.internal else self.name
327
343
 
328
344
  @property
329
345
  def instance_check_template(self) -> str:
@@ -338,12 +354,11 @@ class MsrestModelType(GeneratedModelType):
338
354
  class DPGModelType(GeneratedModelType):
339
355
  base = "dpg"
340
356
 
341
- @property
342
- def serialization_type(self) -> str:
357
+ def serialization_type(self, **kwargs: Any) -> str:
343
358
  return (
344
- self.type_annotation(skip_quote=True)
359
+ self.type_annotation(skip_quote=True, **kwargs)
345
360
  if self.internal
346
- else self.type_annotation(need_module_name=False, skip_quote=True)
361
+ else self.type_annotation(need_model_alias=False, skip_quote=True, **kwargs)
347
362
  )
348
363
 
349
364
  @property
@@ -13,6 +13,7 @@ from typing import (
13
13
  Generic,
14
14
  TypeVar,
15
15
  cast,
16
+ Sequence,
16
17
  )
17
18
 
18
19
  from .request_builder_parameter import RequestBuilderParameter
@@ -35,6 +36,7 @@ from .parameter import (
35
36
  from .parameter_list import ParameterList
36
37
  from .model_type import ModelType
37
38
  from .base import BaseType
39
+ from .combined_type import CombinedType
38
40
  from .request_builder import OverloadedRequestBuilder, RequestBuilder
39
41
  from ...utils import xml_serializable, json_serializable, NAME_LENGTH_LIMIT
40
42
 
@@ -54,7 +56,7 @@ def is_internal(target: Optional[BaseType]) -> bool:
54
56
 
55
57
 
56
58
  class OperationBase( # pylint: disable=too-many-public-methods,too-many-instance-attributes
57
- Generic[ResponseType], BaseBuilder[ParameterList, List["Operation"]]
59
+ Generic[ResponseType], BaseBuilder[ParameterList, Sequence["Operation"]]
58
60
  ):
59
61
  def __init__(
60
62
  self,
@@ -67,7 +69,7 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
67
69
  responses: List[ResponseType],
68
70
  exceptions: List[Response],
69
71
  *,
70
- overloads: Optional[List["Operation"]] = None,
72
+ overloads: Optional[Sequence["Operation"]] = None,
71
73
  ) -> None:
72
74
  super().__init__(
73
75
  code_model=code_model,
@@ -77,7 +79,7 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
77
79
  parameters=parameters,
78
80
  overloads=overloads,
79
81
  )
80
- self.overloads: List["Operation"] = overloads or []
82
+ self.overloads: Sequence["Operation"] = overloads or []
81
83
  self.responses = responses
82
84
  self.request_builder = request_builder
83
85
  self.deprecated = False
@@ -144,10 +146,10 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
144
146
  retval = add_to_pylint_disable(retval, "name-too-long")
145
147
  return retval
146
148
 
147
- def cls_type_annotation(self, *, async_mode: bool) -> str:
149
+ def cls_type_annotation(self, *, async_mode: bool, **kwargs: Any) -> str:
148
150
  if self.request_builder.method.lower() == "head" and self.code_model.options["head_as_boolean"]:
149
151
  return "ClsType[None]"
150
- return f"ClsType[{self.response_type_annotation(async_mode=async_mode)}]"
152
+ return f"ClsType[{self.response_type_annotation(async_mode=async_mode, **kwargs)}]"
151
153
 
152
154
  def _response_docstring_helper(self, attr_name: str, **kwargs: Any) -> str:
153
155
  responses_with_body = [r for r in self.responses if r.type]
@@ -207,21 +209,26 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
207
209
  e for e in self.exceptions if "default" not in e.status_codes and e.type and isinstance(e.type, ModelType)
208
210
  ]
209
211
 
210
- def _imports_shared(self, async_mode: bool, **kwargs: Any) -> FileImport: # pylint: disable=unused-argument
212
+ def _imports_shared(self, async_mode: bool, **kwargs: Any) -> FileImport:
211
213
  file_import = FileImport(self.code_model)
212
214
  file_import.add_submodule_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
213
215
 
214
- response_types = [r.type_annotation(async_mode=async_mode, operation=self) for r in self.responses if r.type]
216
+ response_types = [r.type_annotation(async_mode=async_mode, **kwargs) for r in self.responses if r.type]
215
217
  if len(set(response_types)) > 1:
216
218
  file_import.add_submodule_import("typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL)
217
219
  if self.added_on:
220
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
218
221
  file_import.add_submodule_import(
219
- f"{'.' if async_mode else ''}.._validation",
222
+ self.code_model.get_relative_import_path(serialize_namespace, module_name="_validation"),
220
223
  "api_version_validation",
221
224
  ImportType.LOCAL,
222
225
  )
223
226
  return file_import
224
227
 
228
+ @property
229
+ def need_import_iobase(self) -> bool:
230
+ return self.parameters.has_body and isinstance(self.parameters.body_parameter.type, CombinedType)
231
+
225
232
  def imports_for_multiapi(self, async_mode: bool, **kwargs: Any) -> FileImport:
226
233
  if self.abstract:
227
234
  return FileImport(self.code_model)
@@ -230,15 +237,23 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
230
237
  file_import.merge(
231
238
  param.imports_for_multiapi(
232
239
  async_mode,
233
- operation=self,
240
+ need_import_iobase=self.need_import_iobase,
234
241
  **kwargs,
235
242
  )
236
243
  )
237
244
  for response in self.responses:
238
- file_import.merge(response.imports_for_multiapi(async_mode=async_mode, operation=self, **kwargs))
245
+ file_import.merge(
246
+ response.imports_for_multiapi(
247
+ async_mode=async_mode, need_import_iobase=self.need_import_iobase, **kwargs
248
+ )
249
+ )
239
250
  if self.code_model.options["models_mode"]:
240
251
  for exception in self.exceptions:
241
- file_import.merge(exception.imports_for_multiapi(async_mode=async_mode, operation=self, **kwargs))
252
+ file_import.merge(
253
+ exception.imports_for_multiapi(
254
+ async_mode=async_mode, need_import_iobase=self.need_import_iobase, **kwargs
255
+ )
256
+ )
242
257
  return file_import
243
258
 
244
259
  @staticmethod
@@ -265,6 +280,7 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
265
280
  self,
266
281
  request_builder: Union[RequestBuilder, OverloadedRequestBuilder],
267
282
  async_mode: bool,
283
+ serialize_namespace: str,
268
284
  ) -> FileImport:
269
285
  """Helper method to get a request builder import."""
270
286
  file_import = FileImport(self.code_model)
@@ -287,7 +303,11 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
287
303
  )
288
304
  if self.code_model.options["builders_visibility"] == "embedded" and async_mode:
289
305
  file_import.add_submodule_import(
290
- f"...{self.code_model.operations_folder_name}.{self.filename}",
306
+ self.code_model.get_relative_import_path(
307
+ serialize_namespace,
308
+ self.code_model.get_imported_namespace_for_operation(self.client_namespace),
309
+ module_name=self.filename,
310
+ ),
291
311
  request_builder.name,
292
312
  import_type=ImportType.LOCAL,
293
313
  )
@@ -298,24 +318,30 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
298
318
  ) -> FileImport:
299
319
  if self.abstract:
300
320
  return FileImport(self.code_model)
321
+
322
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
301
323
  file_import = self._imports_shared(async_mode, **kwargs)
302
324
 
303
325
  for param in self.parameters.method:
304
326
  file_import.merge(
305
327
  param.imports(
306
328
  async_mode,
307
- operation=self,
329
+ need_import_iobase=self.need_import_iobase,
308
330
  **kwargs,
309
331
  )
310
332
  )
311
333
  for response in self.responses:
312
- file_import.merge(response.imports(async_mode=async_mode, operation=self, **kwargs))
334
+ file_import.merge(
335
+ response.imports(async_mode=async_mode, need_import_iobase=self.need_import_iobase, **kwargs)
336
+ )
313
337
  if self.code_model.options["models_mode"]:
314
338
  for exception in self.exceptions:
315
339
  file_import.merge(exception.imports(async_mode=async_mode, **kwargs))
316
340
 
317
341
  if self.parameters.has_body and self.parameters.body_parameter.flattened:
318
- file_import.merge(self.parameters.body_parameter.type.imports(operation=self, **kwargs))
342
+ file_import.merge(
343
+ self.parameters.body_parameter.type.imports(need_import_iobase=self.need_import_iobase, **kwargs)
344
+ )
319
345
  if not async_mode:
320
346
  for param in self.parameters.headers:
321
347
  if param.wire_name.lower() == "repeatability-request-id":
@@ -353,7 +379,6 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
353
379
  if self.deprecated:
354
380
  file_import.add_import("warnings", ImportType.STDLIB)
355
381
 
356
- relative_path = "..." if async_mode else ".."
357
382
  if self.has_etag:
358
383
  file_import.add_submodule_import(
359
384
  "exceptions",
@@ -361,8 +386,17 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
361
386
  ImportType.SDKCORE,
362
387
  )
363
388
  if not async_mode:
364
- file_import.add_submodule_import(f"{relative_path}_vendor", "prep_if_match", ImportType.LOCAL)
365
- file_import.add_submodule_import(f"{relative_path}_vendor", "prep_if_none_match", ImportType.LOCAL)
389
+ relative_path = self.code_model.get_relative_import_path(serialize_namespace, module_name="_vendor")
390
+ file_import.add_submodule_import(
391
+ relative_path,
392
+ "prep_if_match",
393
+ ImportType.LOCAL,
394
+ )
395
+ file_import.add_submodule_import(
396
+ relative_path,
397
+ "prep_if_none_match",
398
+ ImportType.LOCAL,
399
+ )
366
400
  if async_mode:
367
401
  file_import.add_submodule_import(
368
402
  "rest",
@@ -376,7 +410,7 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
376
410
  ImportType.SDKCORE,
377
411
  )
378
412
  if self.code_model.options["builders_visibility"] == "embedded" and not async_mode:
379
- file_import.merge(self.request_builder.imports())
413
+ file_import.merge(self.request_builder.imports(**kwargs))
380
414
  file_import.add_submodule_import(
381
415
  f"{'' if self.code_model.is_azure_flavor else 'runtime.'}pipeline",
382
416
  "PipelineResponse",
@@ -393,34 +427,35 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
393
427
  "distributed_trace",
394
428
  ImportType.SDKCORE,
395
429
  )
396
- file_import.merge(self.get_request_builder_import(self.request_builder, async_mode))
430
+ file_import.merge(self.get_request_builder_import(self.request_builder, async_mode, serialize_namespace))
397
431
  if self.overloads:
398
432
  file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
399
433
  if self.code_model.options["models_mode"] == "dpg":
434
+ relative_path = self.code_model.get_relative_import_path(serialize_namespace, module_name="_model_base")
400
435
  if self.parameters.has_body:
401
436
  if self.has_form_data_body:
402
- file_import.add_submodule_import(relative_path, "_model_base", ImportType.LOCAL)
437
+ file_import.add_submodule_import(
438
+ self.code_model.get_relative_import_path(serialize_namespace), "_model_base", ImportType.LOCAL
439
+ )
403
440
  elif xml_serializable(self.parameters.body_parameter.default_content_type):
404
441
  file_import.add_submodule_import(
405
- f"{relative_path}_model_base",
442
+ relative_path,
406
443
  "_get_element",
407
444
  ImportType.LOCAL,
408
445
  )
409
446
  elif json_serializable(self.parameters.body_parameter.default_content_type):
410
447
  file_import.add_submodule_import(
411
- f"{relative_path}_model_base",
448
+ relative_path,
412
449
  "SdkJSONEncoder",
413
450
  ImportType.LOCAL,
414
451
  )
415
452
  file_import.add_import("json", ImportType.STDLIB)
416
453
  if any(xml_serializable(str(r.default_content_type)) for r in self.responses):
417
- file_import.add_submodule_import(f"{relative_path}_model_base", "_deserialize_xml", ImportType.LOCAL)
454
+ file_import.add_submodule_import(relative_path, "_deserialize_xml", ImportType.LOCAL)
418
455
  elif any(r.type for r in self.responses):
419
- file_import.add_submodule_import(f"{relative_path}_model_base", "_deserialize", ImportType.LOCAL)
456
+ file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
420
457
  if self.default_error_deserialization or self.non_default_errors:
421
- file_import.add_submodule_import(
422
- f"{relative_path}_model_base", "_failsafe_deserialize", ImportType.LOCAL
423
- )
458
+ file_import.add_submodule_import(relative_path, "_failsafe_deserialize", ImportType.LOCAL)
424
459
  return file_import
425
460
 
426
461
  def get_response_from_status(self, status_code: Optional[Union[str, int]]) -> ResponseType:
@@ -465,7 +500,9 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
465
500
  responses = [cast(ResponseType, get_response(r, code_model)) for r in yaml_data["responses"]]
466
501
  exceptions = [Response.from_yaml(e, code_model) for e in yaml_data["exceptions"]]
467
502
  parameter_list = ParameterList.from_yaml(yaml_data, code_model)
468
- overloads = [cls.from_yaml(overload, code_model, client) for overload in yaml_data.get("overloads", [])]
503
+ overloads = [
504
+ cast(Operation, cls.from_yaml(overload, code_model, client)) for overload in yaml_data.get("overloads", [])
505
+ ]
469
506
 
470
507
  return cls(
471
508
  yaml_data=yaml_data,