@typespec/http-client-python 0.5.1 → 0.6.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 (146) 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 +4 -1
  6. package/dist/emitter/emitter.js.map +1 -1
  7. package/dist/emitter/lib.d.ts +1 -0
  8. package/dist/emitter/lib.d.ts.map +1 -1
  9. package/dist/emitter/lib.js +1 -0
  10. package/dist/emitter/lib.js.map +1 -1
  11. package/dist/emitter/types.d.ts.map +1 -1
  12. package/dist/emitter/types.js +7 -4
  13. package/dist/emitter/types.js.map +1 -1
  14. package/dist/emitter/utils.d.ts +1 -0
  15. package/dist/emitter/utils.d.ts.map +1 -1
  16. package/dist/emitter/utils.js +19 -0
  17. package/dist/emitter/utils.js.map +1 -1
  18. package/emitter/src/code-model.ts +16 -6
  19. package/emitter/src/emitter.ts +4 -1
  20. package/emitter/src/lib.ts +4 -0
  21. package/emitter/src/types.ts +16 -4
  22. package/emitter/src/utils.ts +27 -0
  23. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  24. package/eng/scripts/ci/regenerate.ts +7 -0
  25. package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
  26. package/generator/build/lib/pygen/black.py +2 -2
  27. package/generator/build/lib/pygen/codegen/__init__.py +2 -0
  28. package/generator/build/lib/pygen/codegen/_utils.py +4 -0
  29. package/generator/build/lib/pygen/codegen/models/base.py +2 -3
  30. package/generator/build/lib/pygen/codegen/models/base_builder.py +5 -3
  31. package/generator/build/lib/pygen/codegen/models/client.py +28 -19
  32. package/generator/build/lib/pygen/codegen/models/code_model.py +200 -33
  33. package/generator/build/lib/pygen/codegen/models/combined_type.py +8 -5
  34. package/generator/build/lib/pygen/codegen/models/constant_type.py +2 -3
  35. package/generator/build/lib/pygen/codegen/models/credential_types.py +2 -3
  36. package/generator/build/lib/pygen/codegen/models/dictionary_type.py +2 -3
  37. package/generator/build/lib/pygen/codegen/models/enum_type.py +47 -24
  38. package/generator/build/lib/pygen/codegen/models/imports.py +14 -12
  39. package/generator/build/lib/pygen/codegen/models/list_type.py +2 -3
  40. package/generator/build/lib/pygen/codegen/models/lro_operation.py +8 -4
  41. package/generator/build/lib/pygen/codegen/models/lro_paging_operation.py +2 -2
  42. package/generator/build/lib/pygen/codegen/models/model_type.py +34 -19
  43. package/generator/build/lib/pygen/codegen/models/operation.py +66 -29
  44. package/generator/build/lib/pygen/codegen/models/operation_group.py +56 -11
  45. package/generator/build/lib/pygen/codegen/models/paging_operation.py +9 -6
  46. package/generator/build/lib/pygen/codegen/models/parameter.py +10 -10
  47. package/generator/build/lib/pygen/codegen/models/parameter_list.py +7 -7
  48. package/generator/build/lib/pygen/codegen/models/primitive_types.py +23 -43
  49. package/generator/build/lib/pygen/codegen/models/property.py +7 -7
  50. package/generator/build/lib/pygen/codegen/models/request_builder.py +9 -15
  51. package/generator/build/lib/pygen/codegen/models/response.py +6 -8
  52. package/generator/build/lib/pygen/codegen/models/utils.py +11 -0
  53. package/generator/build/lib/pygen/codegen/serializers/__init__.py +201 -242
  54. package/generator/build/lib/pygen/codegen/serializers/base_serializer.py +19 -1
  55. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +53 -35
  56. package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +9 -5
  57. package/generator/build/lib/pygen/codegen/serializers/enum_serializer.py +17 -3
  58. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +26 -14
  59. package/generator/build/lib/pygen/codegen/serializers/metadata_serializer.py +26 -8
  60. package/generator/build/lib/pygen/codegen/serializers/model_init_serializer.py +9 -4
  61. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +63 -23
  62. package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +19 -16
  63. package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +5 -10
  64. package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +10 -7
  65. package/generator/build/lib/pygen/codegen/serializers/request_builders_serializer.py +10 -1
  66. package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +7 -10
  67. package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +24 -28
  68. package/generator/build/lib/pygen/codegen/serializers/types_serializer.py +6 -1
  69. package/generator/build/lib/pygen/codegen/serializers/utils.py +1 -15
  70. package/generator/build/lib/pygen/codegen/templates/client_container.py.jinja2 +1 -1
  71. package/generator/build/lib/pygen/codegen/templates/config_container.py.jinja2 +1 -1
  72. package/generator/build/lib/pygen/codegen/templates/enum_container.py.jinja2 +1 -1
  73. package/generator/build/lib/pygen/codegen/templates/init.py.jinja2 +1 -1
  74. package/generator/build/lib/pygen/codegen/templates/model_container.py.jinja2 +1 -1
  75. package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +2 -4
  76. package/generator/build/lib/pygen/codegen/templates/test.py.jinja2 +3 -3
  77. package/generator/build/lib/pygen/codegen/templates/testpreparer.py.jinja2 +2 -2
  78. package/generator/build/lib/pygen/codegen/templates/vendor.py.jinja2 +4 -4
  79. package/generator/build/lib/pygen/preprocess/__init__.py +0 -4
  80. package/generator/component-detection-pip-report.json +2 -2
  81. package/generator/dev_requirements.txt +2 -2
  82. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  83. package/generator/pygen/black.py +2 -2
  84. package/generator/pygen/codegen/__init__.py +2 -0
  85. package/generator/pygen/codegen/_utils.py +4 -0
  86. package/generator/pygen/codegen/models/base.py +2 -3
  87. package/generator/pygen/codegen/models/base_builder.py +5 -3
  88. package/generator/pygen/codegen/models/client.py +28 -19
  89. package/generator/pygen/codegen/models/code_model.py +200 -33
  90. package/generator/pygen/codegen/models/combined_type.py +8 -5
  91. package/generator/pygen/codegen/models/constant_type.py +2 -3
  92. package/generator/pygen/codegen/models/credential_types.py +2 -3
  93. package/generator/pygen/codegen/models/dictionary_type.py +2 -3
  94. package/generator/pygen/codegen/models/enum_type.py +47 -24
  95. package/generator/pygen/codegen/models/imports.py +14 -12
  96. package/generator/pygen/codegen/models/list_type.py +2 -3
  97. package/generator/pygen/codegen/models/lro_operation.py +8 -4
  98. package/generator/pygen/codegen/models/lro_paging_operation.py +2 -2
  99. package/generator/pygen/codegen/models/model_type.py +34 -19
  100. package/generator/pygen/codegen/models/operation.py +66 -29
  101. package/generator/pygen/codegen/models/operation_group.py +56 -11
  102. package/generator/pygen/codegen/models/paging_operation.py +9 -6
  103. package/generator/pygen/codegen/models/parameter.py +10 -10
  104. package/generator/pygen/codegen/models/parameter_list.py +7 -7
  105. package/generator/pygen/codegen/models/primitive_types.py +23 -43
  106. package/generator/pygen/codegen/models/property.py +7 -7
  107. package/generator/pygen/codegen/models/request_builder.py +9 -15
  108. package/generator/pygen/codegen/models/response.py +6 -8
  109. package/generator/pygen/codegen/models/utils.py +11 -0
  110. package/generator/pygen/codegen/serializers/__init__.py +201 -242
  111. package/generator/pygen/codegen/serializers/base_serializer.py +19 -1
  112. package/generator/pygen/codegen/serializers/builder_serializer.py +53 -35
  113. package/generator/pygen/codegen/serializers/client_serializer.py +9 -5
  114. package/generator/pygen/codegen/serializers/enum_serializer.py +17 -3
  115. package/generator/pygen/codegen/serializers/general_serializer.py +26 -14
  116. package/generator/pygen/codegen/serializers/metadata_serializer.py +26 -8
  117. package/generator/pygen/codegen/serializers/model_init_serializer.py +9 -4
  118. package/generator/pygen/codegen/serializers/model_serializer.py +63 -23
  119. package/generator/pygen/codegen/serializers/operation_groups_serializer.py +19 -16
  120. package/generator/pygen/codegen/serializers/operations_init_serializer.py +5 -10
  121. package/generator/pygen/codegen/serializers/parameter_serializer.py +10 -7
  122. package/generator/pygen/codegen/serializers/request_builders_serializer.py +10 -1
  123. package/generator/pygen/codegen/serializers/sample_serializer.py +7 -10
  124. package/generator/pygen/codegen/serializers/test_serializer.py +24 -28
  125. package/generator/pygen/codegen/serializers/types_serializer.py +6 -1
  126. package/generator/pygen/codegen/serializers/utils.py +1 -15
  127. package/generator/pygen/codegen/templates/client_container.py.jinja2 +1 -1
  128. package/generator/pygen/codegen/templates/config_container.py.jinja2 +1 -1
  129. package/generator/pygen/codegen/templates/enum_container.py.jinja2 +1 -1
  130. package/generator/pygen/codegen/templates/init.py.jinja2 +1 -1
  131. package/generator/pygen/codegen/templates/model_container.py.jinja2 +1 -1
  132. package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +2 -4
  133. package/generator/pygen/codegen/templates/test.py.jinja2 +3 -3
  134. package/generator/pygen/codegen/templates/testpreparer.py.jinja2 +2 -2
  135. package/generator/pygen/codegen/templates/vendor.py.jinja2 +4 -4
  136. package/generator/pygen/preprocess/__init__.py +0 -4
  137. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_access_async.py +1 -1
  138. package/generator/test/azure/mock_api_tests/asynctests/test_client_namespace_async.py +31 -0
  139. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_access.py +1 -1
  140. package/generator/test/azure/mock_api_tests/test_client_namespace.py +29 -0
  141. package/generator/test/azure/mock_api_tests/test_resiliency_srv_driven_async.py +1 -0
  142. package/generator/test/azure/requirements.txt +3 -2
  143. package/generator/test/azure/tox.ini +2 -2
  144. package/generator/test/unbranded/requirements.txt +2 -2
  145. package/generator/test/unbranded/tox.ini +2 -2
  146. package/package.json +1 -1
@@ -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,
@@ -10,7 +10,7 @@ from .utils import OrderedSet
10
10
  from .base import BaseModel
11
11
  from .operation import get_operation
12
12
  from .imports import FileImport, ImportType, TypingSection
13
- from .utils import add_to_pylint_disable
13
+ from .utils import add_to_pylint_disable, NamespaceType
14
14
  from .lro_operation import LROOperation
15
15
  from .lro_paging_operation import LROPagingOperation
16
16
  from ...utils import NAME_LENGTH_LIMIT
@@ -46,6 +46,10 @@ class OperationGroup(BaseModel):
46
46
  for op_group in self.yaml_data.get("operationGroups", [])
47
47
  ]
48
48
  self.link_lro_initial_operations()
49
+ self.client_namespace: str = self.yaml_data.get("clientNamespace", code_model.namespace)
50
+ self.has_parent_operation_group: bool = False
51
+ for og in self.operation_groups:
52
+ og.has_parent_operation_group = True
49
53
 
50
54
  @property
51
55
  def has_abstract_operations(self) -> bool:
@@ -66,11 +70,11 @@ class OperationGroup(BaseModel):
66
70
  base_classes.append(f"{self.client.name}MixinABC")
67
71
  return ", ".join(base_classes)
68
72
 
69
- def imports_for_multiapi(self, async_mode: bool) -> FileImport:
73
+ def imports_for_multiapi(self, async_mode: bool, **kwargs) -> FileImport:
70
74
  file_import = FileImport(self.code_model)
71
75
  relative_path = ".." if async_mode else "."
72
76
  for operation in self.operations:
73
- file_import.merge(operation.imports_for_multiapi(async_mode, relative_path=relative_path))
77
+ file_import.merge(operation.imports_for_multiapi(async_mode, **kwargs))
74
78
  if (self.code_model.model_types or self.code_model.enums) and self.code_model.options[
75
79
  "models_mode"
76
80
  ] == "msrest":
@@ -94,30 +98,71 @@ class OperationGroup(BaseModel):
94
98
  """Whether any of its operations need validation"""
95
99
  return any(o for o in self.operations if o.need_validation)
96
100
 
97
- def imports(self, async_mode: bool) -> FileImport:
101
+ def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
98
102
  file_import = FileImport(self.code_model)
99
103
 
100
- relative_path = ("..." if async_mode else "..") + ("." if self.client.is_subclient else "")
104
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
101
105
  for operation in self.operations:
102
- file_import.merge(operation.imports(async_mode, relative_path=relative_path))
106
+ file_import.merge(operation.imports(async_mode, **kwargs))
103
107
  if not self.code_model.options["combine_operation_files"]:
104
108
  for og in self.operation_groups:
105
109
  file_import.add_submodule_import(
106
- ".",
110
+ self.code_model.get_relative_import_path(
111
+ serialize_namespace,
112
+ self.code_model.get_imported_namespace_for_operation(self.client_namespace, async_mode),
113
+ ),
107
114
  og.class_name,
108
115
  ImportType.LOCAL,
109
116
  )
117
+ else:
118
+ for og in self.operation_groups:
119
+ namespace = self.code_model.get_serialize_namespace(
120
+ og.client_namespace, async_mode, NamespaceType.OPERATION
121
+ )
122
+ if namespace != serialize_namespace:
123
+ file_import.add_submodule_import(
124
+ self.code_model.get_relative_import_path(
125
+ serialize_namespace,
126
+ self.code_model.get_imported_namespace_for_operation(og.client_namespace, async_mode),
127
+ )
128
+ + f".{og.filename}",
129
+ og.class_name,
130
+ ImportType.LOCAL,
131
+ )
110
132
  # for multiapi
111
133
  if (
112
134
  (self.code_model.public_model_types)
113
135
  and self.code_model.options["models_mode"] == "msrest"
114
136
  and not self.is_mixin
115
137
  ):
116
- file_import.add_submodule_import(relative_path, "models", ImportType.LOCAL, alias="_models")
138
+ file_import.add_submodule_import(
139
+ self.code_model.get_relative_import_path(serialize_namespace),
140
+ "models",
141
+ ImportType.LOCAL,
142
+ alias="_models",
143
+ )
117
144
  if self.is_mixin:
118
- file_import.add_submodule_import(".._vendor", f"{self.client.name}MixinABC", ImportType.LOCAL)
145
+ file_import.add_submodule_import(
146
+ # XxxMixinABC is always defined in _vendor of client namespace
147
+ self.code_model.get_relative_import_path(
148
+ serialize_namespace,
149
+ self.code_model.get_imported_namespace_for_client(self.client.client_namespace, async_mode),
150
+ module_name="_vendor",
151
+ ),
152
+ f"{self.client.name}MixinABC",
153
+ ImportType.LOCAL,
154
+ )
119
155
  if self.has_abstract_operations:
120
- file_import.add_submodule_import(".._vendor", "raise_if_not_implemented", ImportType.LOCAL)
156
+ file_import.add_submodule_import(
157
+ # raise_if_not_implemented is always defined in _vendor of top namespace
158
+ self.code_model.get_relative_import_path(
159
+ serialize_namespace,
160
+ self.code_model.get_imported_namespace_for_client(self.code_model.namespace, async_mode),
161
+ module_name="_vendor",
162
+ ),
163
+ "raise_if_not_implemented",
164
+ ImportType.LOCAL,
165
+ )
121
166
  if all(o.abstract for o in self.operations):
122
167
  return file_import
123
168
  file_import.add_submodule_import("typing", "TypeVar", ImportType.STDLIB, TypingSection.CONDITIONAL)
@@ -128,7 +173,7 @@ class OperationGroup(BaseModel):
128
173
 
129
174
  @property
130
175
  def filename(self) -> str:
131
- return self.operations[0].filename
176
+ return self.operations[0].filename if self.operations else "_operations"
132
177
 
133
178
  @property
134
179
  def is_mixin(self) -> bool:
@@ -103,8 +103,8 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
103
103
  def operation_type(self) -> str:
104
104
  return "paging"
105
105
 
106
- def cls_type_annotation(self, *, async_mode: bool) -> str:
107
- return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode)}]"
106
+ def cls_type_annotation(self, *, async_mode: bool, **kwargs: Any) -> str:
107
+ return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode, **kwargs)}]"
108
108
 
109
109
  def _imports_shared(self, async_mode: bool, **kwargs: Any) -> FileImport:
110
110
  file_import = super()._imports_shared(async_mode, **kwargs)
@@ -117,7 +117,7 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
117
117
  and self.code_model.options["builders_visibility"] == "embedded"
118
118
  and not async_mode
119
119
  ):
120
- file_import.merge(self.next_request_builder.imports())
120
+ file_import.merge(self.next_request_builder.imports(**kwargs))
121
121
  return file_import
122
122
 
123
123
  @property
@@ -129,6 +129,7 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
129
129
  return FileImport(self.code_model)
130
130
  file_import = self._imports_shared(async_mode, **kwargs)
131
131
  file_import.merge(super().imports(async_mode, **kwargs))
132
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
132
133
  if self.code_model.options["tracing"] and self.want_tracing:
133
134
  file_import.add_submodule_import(
134
135
  "azure.core.tracing.decorator",
@@ -136,7 +137,9 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
136
137
  ImportType.SDKCORE,
137
138
  )
138
139
  if self.next_request_builder:
139
- file_import.merge(self.get_request_builder_import(self.next_request_builder, async_mode))
140
+ file_import.merge(
141
+ self.get_request_builder_import(self.next_request_builder, async_mode, serialize_namespace)
142
+ )
140
143
  elif any(p.is_api_version for p in self.client.parameters):
141
144
  file_import.add_import("urllib.parse", ImportType.STDLIB)
142
145
  file_import.add_submodule_import(
@@ -145,10 +148,10 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
145
148
  ImportType.SDKCORE,
146
149
  )
147
150
  if self.code_model.options["models_mode"] == "dpg":
148
- relative_path = "..." if async_mode else ".."
151
+ relative_path = self.code_model.get_relative_import_path(serialize_namespace, module_name="_model_base")
149
152
  file_import.merge(self.item_type.imports(**kwargs))
150
153
  if self.default_error_deserialization or any(r.type for r in self.responses):
151
- file_import.add_submodule_import(f"{relative_path}_model_base", "_deserialize", ImportType.LOCAL)
154
+ file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
152
155
  return file_import
153
156
 
154
157
 
@@ -155,23 +155,23 @@ class _ParameterBase(BaseModel, abc.ABC): # pylint: disable=too-many-instance-a
155
155
  def docstring_type(self, **kwargs: Any) -> str:
156
156
  return self.type.docstring_type(**kwargs)
157
157
 
158
- @property
159
- def serialization_type(self) -> str:
160
- return self.type.serialization_type
158
+ def serialization_type(self, **kwargs: Any) -> str:
159
+ return self.type.serialization_type(**kwargs)
161
160
 
162
- def _imports_shared(self, async_mode: bool, **_: Any) -> FileImport:
161
+ def _imports_shared(self, async_mode: bool, **kwargs: Any) -> FileImport: # pylint: disable=unused-argument
163
162
  file_import = FileImport(self.code_model)
164
163
  if self.optional and self.client_default_value is None:
165
164
  file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB)
165
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
166
166
  if self.added_on and self.implementation != "Client":
167
167
  file_import.add_submodule_import(
168
- f"{'.' if async_mode else ''}.._validation",
168
+ self.code_model.get_relative_import_path(serialize_namespace, module_name="_validation"),
169
169
  "api_version_validation",
170
170
  ImportType.LOCAL,
171
171
  )
172
172
  if isinstance(self.type, CombinedType) and self.type.name:
173
173
  file_import.add_submodule_import(
174
- "..." if async_mode else "..",
174
+ self.code_model.get_relative_import_path(serialize_namespace),
175
175
  "_types",
176
176
  ImportType.LOCAL,
177
177
  TypingSection.TYPING,
@@ -212,8 +212,8 @@ class _ParameterBase(BaseModel, abc.ABC): # pylint: disable=too-many-instance-a
212
212
  @abc.abstractmethod
213
213
  def in_method_signature(self) -> bool: ...
214
214
 
215
- def method_signature(self, async_mode: bool) -> str:
216
- type_annotation = self.type_annotation(async_mode=async_mode)
215
+ def method_signature(self, async_mode: bool, **kwargs: Any) -> str:
216
+ type_annotation = self.type_annotation(async_mode=async_mode, **kwargs)
217
217
  if self.client_default_value is not None or self.optional:
218
218
  return f"{self.client_name}: {type_annotation} = {self.client_default_value_declaration},"
219
219
  if self.default_to_unset_sentinel:
@@ -272,9 +272,9 @@ class BodyParameter(_ParameterBase):
272
272
  def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
273
273
  file_import = super().imports(async_mode, **kwargs)
274
274
  if self.is_form_data:
275
- relative_path = "..." if async_mode else ".."
275
+ serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
276
276
  file_import.add_submodule_import(
277
- f"{relative_path}_vendor",
277
+ self.code_model.get_relative_import_path(serialize_namespace, module_name="_vendor"),
278
278
  "prepare_multipart_form_data",
279
279
  ImportType.LOCAL,
280
280
  )
@@ -200,22 +200,22 @@ class _ParameterListBase(
200
200
  """Sorted method params. First positional, then keyword only, then kwarg"""
201
201
  return self.positional + self.keyword_only + self.kwarg
202
202
 
203
- def method_signature(self, async_mode: bool) -> List[str]:
203
+ def method_signature(self, async_mode: bool, **kwargs: Any) -> List[str]:
204
204
  """Method signature for this parameter list."""
205
205
  return method_signature_helper(
206
- positional=self.method_signature_positional(async_mode),
207
- keyword_only=self.method_signature_keyword_only(async_mode),
206
+ positional=self.method_signature_positional(async_mode, **kwargs),
207
+ keyword_only=self.method_signature_keyword_only(async_mode, **kwargs),
208
208
  kwarg_params=self.method_signature_kwargs,
209
209
  )
210
210
 
211
- def method_signature_positional(self, async_mode: bool) -> List[str]:
211
+ def method_signature_positional(self, async_mode: bool, **kwargs: Any) -> List[str]:
212
212
  """Signature for positional parameters"""
213
- return [parameter.method_signature(async_mode) for parameter in self.positional]
213
+ return [parameter.method_signature(async_mode, **kwargs) for parameter in self.positional]
214
214
 
215
- def method_signature_keyword_only(self, async_mode: bool) -> List[str]:
215
+ def method_signature_keyword_only(self, async_mode: bool, **kwargs: Any) -> List[str]:
216
216
  """Signature for keyword only parameters"""
217
217
  result = [
218
- parameter.method_signature(async_mode)
218
+ parameter.method_signature(async_mode, **kwargs)
219
219
  for parameter in self.keyword_only
220
220
  if not parameter.hide_in_operation_signature
221
221
  ]