@autorest/python 6.32.3 → 6.34.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 (63) hide show
  1. package/autorest/m2r.py +1 -2
  2. package/autorest/m4reformatter/__init__.py +1 -2
  3. package/autorest/multiapi/models/imports.py +7 -2
  4. package/autorest/multiapi/serializers/__init__.py +5 -1
  5. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  6. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +13 -2
  7. package/autorest/multiapi/templates/multiapi_utils_init.py.jinja2 +10 -0
  8. package/autorest/preprocess.py +1 -2
  9. package/generator/build/lib/pygen/codegen/models/client.py +39 -2
  10. package/generator/build/lib/pygen/codegen/models/code_model.py +22 -11
  11. package/generator/build/lib/pygen/codegen/models/enum_type.py +2 -2
  12. package/generator/build/lib/pygen/codegen/models/imports.py +13 -9
  13. package/generator/build/lib/pygen/codegen/models/lro_operation.py +1 -1
  14. package/generator/build/lib/pygen/codegen/models/model_type.py +4 -3
  15. package/generator/build/lib/pygen/codegen/models/operation.py +10 -3
  16. package/generator/build/lib/pygen/codegen/models/operation_group.py +27 -31
  17. package/generator/build/lib/pygen/codegen/models/paging_operation.py +3 -1
  18. package/generator/build/lib/pygen/codegen/models/parameter.py +4 -1
  19. package/generator/build/lib/pygen/codegen/models/primitive_types.py +2 -2
  20. package/generator/build/lib/pygen/codegen/models/property.py +1 -1
  21. package/generator/build/lib/pygen/codegen/serializers/__init__.py +31 -29
  22. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +1 -1
  23. package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +32 -6
  24. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +57 -35
  25. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +4 -3
  26. package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +6 -1
  27. package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +2 -2
  28. package/generator/build/lib/pygen/codegen/templates/client.py.jinja2 +1 -1
  29. package/generator/build/lib/pygen/codegen/templates/config.py.jinja2 +2 -8
  30. package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +1 -1
  31. package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +3 -3
  32. package/generator/build/lib/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +12 -11
  33. package/generator/build/lib/pygen/codegen/templates/{vendor.py.jinja2 → utils.py.jinja2} +11 -12
  34. package/generator/component-detection-pip-report.json +4 -5
  35. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  36. package/generator/pygen/codegen/models/client.py +39 -2
  37. package/generator/pygen/codegen/models/code_model.py +22 -11
  38. package/generator/pygen/codegen/models/enum_type.py +2 -2
  39. package/generator/pygen/codegen/models/imports.py +13 -9
  40. package/generator/pygen/codegen/models/lro_operation.py +1 -1
  41. package/generator/pygen/codegen/models/model_type.py +4 -3
  42. package/generator/pygen/codegen/models/operation.py +10 -3
  43. package/generator/pygen/codegen/models/operation_group.py +27 -31
  44. package/generator/pygen/codegen/models/paging_operation.py +3 -1
  45. package/generator/pygen/codegen/models/parameter.py +4 -1
  46. package/generator/pygen/codegen/models/primitive_types.py +2 -2
  47. package/generator/pygen/codegen/models/property.py +1 -1
  48. package/generator/pygen/codegen/serializers/__init__.py +31 -29
  49. package/generator/pygen/codegen/serializers/builder_serializer.py +1 -1
  50. package/generator/pygen/codegen/serializers/client_serializer.py +32 -6
  51. package/generator/pygen/codegen/serializers/general_serializer.py +57 -35
  52. package/generator/pygen/codegen/serializers/model_serializer.py +4 -3
  53. package/generator/pygen/codegen/serializers/parameter_serializer.py +6 -1
  54. package/generator/pygen/codegen/serializers/sample_serializer.py +2 -2
  55. package/generator/pygen/codegen/templates/client.py.jinja2 +1 -1
  56. package/generator/pygen/codegen/templates/config.py.jinja2 +2 -8
  57. package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +1 -1
  58. package/generator/pygen/codegen/templates/operation_group.py.jinja2 +3 -3
  59. package/generator/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +12 -11
  60. package/generator/pygen/codegen/templates/{vendor.py.jinja2 → utils.py.jinja2} +11 -12
  61. package/generator/pygen.egg-info/SOURCES.txt +1 -1
  62. package/package.json +2 -2
  63. package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
package/autorest/m2r.py CHANGED
@@ -3,8 +3,7 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- """An autorest MD to RST plugin.
7
- """
6
+ """An autorest MD to RST plugin."""
8
7
  import logging
9
8
  from typing import Any, Dict, Set, Union
10
9
 
@@ -4,8 +4,7 @@
4
4
  # Licensed under the MIT License. See License.txt in the project root for
5
5
  # license information.
6
6
  # --------------------------------------------------------------------------
7
- """The modelerfour reformatter autorest plugin.
8
- """
7
+ """The modelerfour reformatter autorest plugin."""
9
8
  import re
10
9
  import copy
11
10
  import logging
@@ -123,9 +123,14 @@ class FileImport:
123
123
  ],
124
124
  convert_list_to_tuple(name_import),
125
125
  )
126
- self._imports.setdefault(typing_section, {}).setdefault(import_type, {}).setdefault(from_section, set()).add(
127
- name_input
126
+ target_values = (
127
+ self._imports.setdefault(typing_section, {}).setdefault(import_type, {}).setdefault(from_section, set())
128
128
  )
129
+ if isinstance(target_values, list):
130
+ if name_input not in target_values:
131
+ target_values.append(name_input)
132
+ else:
133
+ target_values.add(name_input)
129
134
 
130
135
  def add_submodule_import(
131
136
  self,
@@ -133,7 +133,11 @@ class MultiAPISerializer(ReaderAndWriter): # pylint: disable=abstract-method
133
133
  lstrip_blocks=True,
134
134
  )
135
135
  self.write_file(
136
- Path("_serialization.py"),
136
+ Path("_utils/__init__.py"),
137
+ self.env.get_template("multiapi_utils_init.py.jinja2").render(),
138
+ )
139
+ self.write_file(
140
+ Path("_utils/serialization.py"),
137
141
  codegen_env.get_template("serialization.py.jinja2").render(
138
142
  code_model=code_model,
139
143
  ),
@@ -8,7 +8,7 @@
8
8
  # Changes may cause incorrect behavior and will be lost if the code is
9
9
  # regenerated.
10
10
  # --------------------------------------------------------------------------
11
- from {{ ".." if async_mode else "." }}_serialization import Serializer, Deserializer
11
+ from {{ ".." if async_mode else "." }}_utils.serialization import Serializer, Deserializer
12
12
  {% if imports %}
13
13
  {{ imports }}
14
14
  {% endif %}
@@ -18,6 +18,7 @@ def __init__(
18
18
  {% set async_prefix = "Async" if async_mode else "" %}
19
19
  {% set a_prefix = "a" if async_mode else "" %}
20
20
  {% set await = "await " if async_mode else "" %}
21
+ {% set credential_scopes = "credential_scopes=credential_scopes, " if code_model.config.credential_scopes is not none and code_model.azure_arm else "" %}
21
22
  # coding=utf-8
22
23
  # --------------------------------------------------------------------------
23
24
  # Copyright (c) Microsoft Corporation. All rights reserved.
@@ -77,6 +78,7 @@ class {{ code_model.client.name }}({% if code_model.operation_mixin_group.mixin_
77
78
  )
78
79
 
79
80
  {{ method_signature()|indent }}
81
+ {% if not code_model.azure_arm %}
80
82
  {% if not code_model.client.host_value %}
81
83
  {% for parameterized_host_template, api_versions in code_model.client.parameterized_host_template_to_api_version|dictsort %}
82
84
  {% set if_statement = "if" if loop.first else "elif" %}
@@ -86,9 +88,17 @@ class {{ code_model.client.name }}({% if code_model.operation_mixin_group.mixin_
86
88
  else:
87
89
  raise ValueError("API version {} is not available".format(api_version))
88
90
  {% endif %}
91
+ {% endif %}
89
92
  if api_version:
90
93
  kwargs.setdefault('api_version', api_version)
91
- self._config = {{ code_model.client.name }}Configuration({{ code_model.global_parameters.call }}{{ ", " if code_model.global_parameters.call }}**kwargs)
94
+ {% if credential_scopes %}
95
+ _cloud = kwargs.pop("cloud_setting", None) or settings.current.azure_cloud # type: ignore
96
+ _endpoints = get_arm_endpoints(_cloud)
97
+ if not base_url:
98
+ base_url = _endpoints["resource_manager"]
99
+ credential_scopes = kwargs.pop("credential_scopes", _endpoints["credential_scopes"])
100
+ {% endif %}
101
+ self._config = {{ code_model.client.name }}Configuration({{ code_model.global_parameters.call }}{{ ", " if code_model.global_parameters.call }}{{ credential_scopes }}**kwargs)
92
102
  _policies = kwargs.pop("policies", None)
93
103
  if _policies is None:
94
104
  _policies = [
@@ -96,7 +106,8 @@ class {{ code_model.client.name }}({% if code_model.operation_mixin_group.mixin_
96
106
  {{ p }},
97
107
  {% endfor %}
98
108
  ]
99
- self._client: {{ async_prefix }}{{ code_model.client.pipeline_client }} = {{ async_prefix }}{{ code_model.client.pipeline_client }}(base_url={{ code_model.host_variable_name }}, policies=_policies, **kwargs)
109
+ {% set host_variable_name = "cast(str, " + code_model.host_variable_name + ")" if credential_scopes else code_model.host_variable_name %}
110
+ self._client: {{ async_prefix }}{{ code_model.client.pipeline_client }} = {{ async_prefix }}{{ code_model.client.pipeline_client }}(base_url={{ host_variable_name }}, policies=_policies, **kwargs)
100
111
  super({{ code_model.client.name }}, self).__init__(
101
112
  api_version=api_version,
102
113
  profile=profile
@@ -0,0 +1,10 @@
1
+ # coding=utf-8
2
+ # --------------------------------------------------------------------------
3
+ # Copyright (c) Microsoft Corporation. All rights reserved.
4
+ # Licensed under the MIT License. See License.txt in the project root for
5
+ # license information.
6
+ #
7
+ # Code generated by Microsoft (R) AutoRest Code Generator.
8
+ # Changes may cause incorrect behavior and will be lost if the code is
9
+ # regenerated.
10
+ # --------------------------------------------------------------------------
@@ -3,8 +3,7 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- """The preprocessing autorest plugin.
7
- """
6
+ """The preprocessing autorest plugin."""
8
7
  from typing import Dict, Any
9
8
  from pygen.preprocess import PreProcessPlugin
10
9
  from . import YamlUpdatePluginAutorest
@@ -15,7 +15,7 @@ from .request_builder import (
15
15
  OverloadedRequestBuilder,
16
16
  get_request_builder,
17
17
  )
18
- from .parameter import Parameter, ParameterMethodLocation
18
+ from .parameter import Parameter, ParameterMethodLocation, ParameterLocation
19
19
  from .lro_operation import LROOperation
20
20
  from .lro_paging_operation import LROPagingOperation
21
21
  from ...utils import extract_original_name, NAME_LENGTH_LIMIT
@@ -54,7 +54,7 @@ class _ClientConfigBase(Generic[ParameterListType], BaseModel):
54
54
  return self.yaml_data["name"]
55
55
 
56
56
 
57
- class Client(_ClientConfigBase[ClientGlobalParameterList]):
57
+ class Client(_ClientConfigBase[ClientGlobalParameterList]): # pylint: disable=too-many-public-methods
58
58
  """Model representing our service client"""
59
59
 
60
60
  def __init__(
@@ -79,6 +79,27 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
79
79
  self.request_id_header_name = self.yaml_data.get("requestIdHeaderName", None)
80
80
  self.has_etag: bool = yaml_data.get("hasEtag", False)
81
81
 
82
+ # update the host parameter value. In later logic, SDK will overwrite it
83
+ # with value from cloud_setting if users don't provide it.
84
+ if self.need_cloud_setting:
85
+ for p in self.parameters.parameters:
86
+ if p.location == ParameterLocation.ENDPOINT_PATH:
87
+ p.client_default_value = None
88
+ p.optional = True
89
+ break
90
+
91
+ @property
92
+ def need_cloud_setting(self) -> bool:
93
+ return bool(
94
+ self.code_model.options.get("azure_arm", False)
95
+ and self.credential_scopes is not None
96
+ and self.endpoint_parameter is not None
97
+ )
98
+
99
+ @property
100
+ def endpoint_parameter(self) -> Optional[Parameter]:
101
+ return next((p for p in self.parameters.parameters if p.location == ParameterLocation.ENDPOINT_PATH), None)
102
+
82
103
  def _build_request_builders(
83
104
  self,
84
105
  ) -> List[Union[RequestBuilder, OverloadedRequestBuilder]]:
@@ -233,6 +254,10 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
233
254
  "Self",
234
255
  ImportType.STDLIB,
235
256
  )
257
+ if self.need_cloud_setting:
258
+ file_import.add_submodule_import("typing", "cast", ImportType.STDLIB)
259
+ file_import.add_submodule_import("azure.core.settings", "settings", ImportType.SDKCORE)
260
+ file_import.add_submodule_import("azure.mgmt.core.tools", "get_arm_endpoints", ImportType.SDKCORE)
236
261
  return file_import
237
262
 
238
263
  @property
@@ -332,6 +357,18 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
332
357
  )
333
358
  return file_import
334
359
 
360
+ @property
361
+ def credential_scopes(self) -> Optional[List[str]]:
362
+ """Credential scopes for this client"""
363
+
364
+ if self.credential:
365
+ if hasattr(getattr(self.credential.type, "policy", None), "credential_scopes"):
366
+ return self.credential.type.policy.credential_scopes # type: ignore
367
+ for t in getattr(self.credential.type, "types", []):
368
+ if hasattr(getattr(t, "policy", None), "credential_scopes"):
369
+ return t.policy.credential_scopes
370
+ return None
371
+
335
372
  @classmethod
336
373
  def from_yaml(
337
374
  cls,
@@ -242,16 +242,26 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
242
242
  """
243
243
  return client_namespace == self.namespace
244
244
 
245
- def need_vendored_code(self, async_mode: bool, client_namespace: str) -> bool:
246
- """Whether we need to vendor code in the _vendor.py in specific namespace"""
245
+ def need_utils_folder(self, async_mode: bool, client_namespace: str) -> bool:
247
246
  return (
248
- self.need_vendored_form_data(async_mode, client_namespace)
249
- or self.need_vendored_etag(client_namespace)
250
- or self.need_vendored_abstract(client_namespace)
251
- or self.need_vendored_mixin(client_namespace)
247
+ self.need_utils_utils(async_mode, client_namespace)
248
+ or self.need_utils_serialization
249
+ or self.options["models_mode"] == "dpg"
252
250
  )
253
251
 
254
- def need_vendored_form_data(self, async_mode: bool, client_namespace: str) -> bool:
252
+ @property
253
+ def need_utils_serialization(self) -> bool:
254
+ return not self.options["client_side_validation"]
255
+
256
+ def need_utils_utils(self, async_mode: bool, client_namespace: str) -> bool:
257
+ return (
258
+ self.need_utils_form_data(async_mode, client_namespace)
259
+ or self.need_utils_etag(client_namespace)
260
+ or self.need_utils_abstract(client_namespace)
261
+ or self.need_utils_mixin
262
+ )
263
+
264
+ def need_utils_form_data(self, async_mode: bool, client_namespace: str) -> bool:
255
265
  return (
256
266
  (not async_mode)
257
267
  and self.is_top_namespace(client_namespace)
@@ -259,14 +269,15 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
259
269
  and self.options["models_mode"] == "dpg"
260
270
  )
261
271
 
262
- def need_vendored_etag(self, client_namespace: str) -> bool:
272
+ def need_utils_etag(self, client_namespace: str) -> bool:
263
273
  return self.is_top_namespace(client_namespace) and self.has_etag
264
274
 
265
- def need_vendored_abstract(self, client_namespace: str) -> bool:
275
+ def need_utils_abstract(self, client_namespace: str) -> bool:
266
276
  return self.is_top_namespace(client_namespace) and self.has_abstract_operations
267
277
 
268
- def need_vendored_mixin(self, client_namespace: str) -> bool:
269
- return self.has_mixin(client_namespace)
278
+ @property
279
+ def need_utils_mixin(self) -> bool:
280
+ return any(c_n for c_n in self.client_namespace_types if self.has_mixin(c_n))
270
281
 
271
282
  def has_mixin(self, client_namespace: str) -> bool:
272
283
  return any(c for c in self.get_clients(client_namespace) if c.has_mixin)
@@ -52,7 +52,7 @@ 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.code_model.namespace}.models.{self.name}"
55
+ enum_type_annotation = f"{self.enum_type.client_namespace}.models.{self.name}"
56
56
  return f"{type_annotation} or ~{enum_type_annotation}"
57
57
 
58
58
  def get_json_template_representation(
@@ -198,7 +198,7 @@ class EnumType(BaseType):
198
198
  """The python type used for RST syntax input and type annotation."""
199
199
  if self.code_model.options["models_mode"]:
200
200
  type_annotation = self.value_type.type_annotation(**kwargs)
201
- enum_type_annotation = f"{self.code_model.namespace}.models.{self.name}"
201
+ enum_type_annotation = f"{self.client_namespace}.models.{self.name}"
202
202
  return f"{type_annotation} or ~{enum_type_annotation}"
203
203
  return self.value_type.type_annotation(**kwargs)
204
204
 
@@ -30,9 +30,11 @@ class TypingSection(str, Enum):
30
30
 
31
31
 
32
32
  class MsrestImportType(Enum):
33
- Module = auto() # import _serialization.py or msrest.serialization as Module
34
- Serializer = auto() # from _serialization.py or msrest.serialization import Serializer
35
- SerializerDeserializer = auto() # from _serialization.py or msrest.serialization import Serializer and Deserializer
33
+ Module = auto() # import _utils/serialization.py or msrest.serialization as Module
34
+ Serializer = auto() # from _utils/serialization.py or msrest.serialization import Serializer
35
+ SerializerDeserializer = (
36
+ auto()
37
+ ) # from _utils/serialization.py or msrest.serialization import Serializer and Deserializer
36
38
 
37
39
 
38
40
  class ImportModel:
@@ -261,21 +263,23 @@ class FileImport:
261
263
  if msrest_import_type == MsrestImportType.SerializerDeserializer:
262
264
  self.add_submodule_import("msrest", "Deserializer", ImportType.THIRDPARTY, typing_section)
263
265
  else:
264
- # _serialization.py is always in root namespace
265
- imported_namespace = self.code_model.namespace
266
+ # _utils/serialization.py is always in root namespace
267
+ imported_namespace = f"{self.code_model.namespace}._utils"
266
268
  if self.code_model.options["multiapi"]:
267
- # for multiapi, the namespace is azure.mgmt.xxx.v20XX_XX_XX while _serialization.py is in azure.mgmt.xxx
268
- imported_namespace = get_parent_namespace(imported_namespace)
269
+ # for multiapi, the namespace is azure.mgmt.xxx.v20XX_XX_XX
270
+ # while _utils/serialization.py is in azure.mgmt.xxx
271
+ imported_namespace = f"{get_parent_namespace(imported_namespace)}._utils"
269
272
  if msrest_import_type == MsrestImportType.Module:
270
273
  self.add_submodule_import(
271
274
  self.code_model.get_relative_import_path(serialize_namespace, imported_namespace),
272
- "_serialization",
275
+ "serialization",
273
276
  ImportType.LOCAL,
274
277
  typing_section,
278
+ alias="_serialization",
275
279
  )
276
280
  else:
277
281
  relative_path = self.code_model.get_relative_import_path(
278
- serialize_namespace, imported_namespace, module_name="_serialization"
282
+ serialize_namespace, f"{self.code_model.namespace}._utils.serialization"
279
283
  )
280
284
  self.add_submodule_import(relative_path, "Serializer", ImportType.LOCAL, typing_section)
281
285
  if msrest_import_type == MsrestImportType.SerializerDeserializer:
@@ -134,7 +134,7 @@ class LROOperationBase(OperationBase[LROResponseType]):
134
134
  # but final call returns a model
135
135
  serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
136
136
  file_import.add_submodule_import(
137
- self.code_model.get_relative_import_path(serialize_namespace, module_name="_model_base"),
137
+ self.code_model.get_relative_import_path(serialize_namespace, module_name="_utils.model_base"),
138
138
  "_deserialize",
139
139
  ImportType.LOCAL,
140
140
  )
@@ -292,7 +292,7 @@ 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.code_model.namespace}.models.{type_annotation}"
295
+ return f"~{self.client_namespace}.models.{type_annotation}"
296
296
 
297
297
  def docstring_text(self, **kwargs: Any) -> str:
298
298
  return self.name
@@ -318,9 +318,10 @@ class GeneratedModelType(ModelType):
318
318
  )
319
319
  if self.is_form_data:
320
320
  file_import.add_submodule_import(
321
- self.code_model.get_relative_import_path(serialize_namespace),
322
- "_model_base",
321
+ self.code_model.get_relative_import_path(serialize_namespace, module_name="_utils.model_base"),
322
+ "Model",
323
323
  ImportType.LOCAL,
324
+ alias="_Model",
324
325
  )
325
326
  elif serialize_namespace_type == NamespaceType.TYPES_FILE or (
326
327
  serialize_namespace_type == NamespaceType.MODEL and called_by_property
@@ -391,7 +391,9 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
391
391
  ImportType.SDKCORE,
392
392
  )
393
393
  if not async_mode:
394
- relative_path = self.code_model.get_relative_import_path(serialize_namespace, module_name="_vendor")
394
+ relative_path = self.code_model.get_relative_import_path(
395
+ serialize_namespace, module_name="_utils.utils"
396
+ )
395
397
  file_import.add_submodule_import(
396
398
  relative_path,
397
399
  "prep_if_match",
@@ -436,12 +438,17 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
436
438
  if self.overloads:
437
439
  file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
438
440
  if self.code_model.options["models_mode"] == "dpg":
439
- relative_path = self.code_model.get_relative_import_path(serialize_namespace, module_name="_model_base")
441
+ relative_path = self.code_model.get_relative_import_path(
442
+ serialize_namespace, module_name="_utils.model_base"
443
+ )
440
444
  body_param = self.parameters.body_parameter if self.parameters.has_body else None
441
445
  if body_param and not isinstance(body_param.type, BinaryType):
442
446
  if self.has_form_data_body:
443
447
  file_import.add_submodule_import(
444
- self.code_model.get_relative_import_path(serialize_namespace), "_model_base", ImportType.LOCAL
448
+ relative_path,
449
+ "Model",
450
+ ImportType.LOCAL,
451
+ alias="_Model",
445
452
  )
446
453
  elif xml_serializable(self.parameters.body_parameter.default_content_type):
447
454
  file_import.add_submodule_import(
@@ -63,11 +63,11 @@ class OperationGroup(BaseModel):
63
63
  operation_group.has_non_abstract_operations for operation_group in self.operation_groups
64
64
  )
65
65
 
66
- @property
67
- def base_class(self) -> str:
66
+ def base_class(self, async_mode: bool) -> str:
67
+ pipeline_client = f"{'Async' if async_mode else ''}PipelineClient"
68
68
  base_classes: List[str] = []
69
69
  if self.is_mixin:
70
- base_classes.append(f"{self.client.name}MixinABC")
70
+ base_classes.append(f"ClientMixinABC[{pipeline_client}, {self.client.name}Configuration]")
71
71
  return ", ".join(base_classes)
72
72
 
73
73
  def imports_for_multiapi(self, async_mode: bool, **kwargs) -> FileImport:
@@ -100,8 +100,12 @@ class OperationGroup(BaseModel):
100
100
 
101
101
  def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
102
102
  file_import = FileImport(self.code_model)
103
-
104
103
  serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
104
+ utils_path = self.code_model.get_relative_import_path(
105
+ serialize_namespace,
106
+ f"{self.code_model.namespace}._utils.utils",
107
+ )
108
+
105
109
  for operation in self.operations:
106
110
  file_import.merge(operation.imports(async_mode, **kwargs))
107
111
  if not self.code_model.options["combine_operation_files"]:
@@ -141,32 +145,28 @@ class OperationGroup(BaseModel):
141
145
  ImportType.LOCAL,
142
146
  alias="_models",
143
147
  )
148
+ file_import.add_submodule_import(
149
+ self.code_model.get_relative_import_path(
150
+ serialize_namespace,
151
+ self.code_model.get_imported_namespace_for_client(self.client.client_namespace, async_mode),
152
+ module_name="_configuration",
153
+ ),
154
+ f"{self.client.name}Configuration",
155
+ ImportType.LOCAL,
156
+ )
157
+ file_import.add_submodule_import(
158
+ "" if self.code_model.is_azure_flavor else "runtime",
159
+ f"{'Async' if async_mode else ''}PipelineClient",
160
+ ImportType.SDKCORE,
161
+ )
144
162
  if self.is_mixin:
145
163
  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",
164
+ # XxxMixinABC is always defined in _utils of client namespace
165
+ utils_path,
166
+ "ClientMixinABC",
153
167
  ImportType.LOCAL,
154
168
  )
155
169
  else:
156
- file_import.add_submodule_import(
157
- "" if self.code_model.is_azure_flavor else "runtime",
158
- f"{'Async' if async_mode else ''}PipelineClient",
159
- ImportType.SDKCORE,
160
- )
161
- file_import.add_submodule_import(
162
- self.code_model.get_relative_import_path(
163
- serialize_namespace,
164
- self.code_model.get_imported_namespace_for_client(self.client.client_namespace, async_mode),
165
- module_name="_configuration",
166
- ),
167
- f"{self.client.name}Configuration",
168
- ImportType.LOCAL,
169
- )
170
170
  file_import.add_msrest_import(
171
171
  serialize_namespace=kwargs.get("serialize_namespace", self.code_model.namespace),
172
172
  msrest_import_type=MsrestImportType.Serializer,
@@ -179,12 +179,8 @@ class OperationGroup(BaseModel):
179
179
  )
180
180
  if self.has_abstract_operations:
181
181
  file_import.add_submodule_import(
182
- # raise_if_not_implemented is always defined in _vendor of top namespace
183
- self.code_model.get_relative_import_path(
184
- serialize_namespace,
185
- self.code_model.get_imported_namespace_for_client(self.code_model.namespace, async_mode),
186
- module_name="_vendor",
187
- ),
182
+ # raise_if_not_implemented is always defined in _utils of top namespace
183
+ utils_path,
188
184
  "raise_if_not_implemented",
189
185
  ImportType.LOCAL,
190
186
  )
@@ -157,7 +157,9 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
157
157
  ImportType.SDKCORE,
158
158
  )
159
159
  if self.code_model.options["models_mode"] == "dpg":
160
- relative_path = self.code_model.get_relative_import_path(serialize_namespace, module_name="_model_base")
160
+ relative_path = self.code_model.get_relative_import_path(
161
+ serialize_namespace, module_name="_utils.model_base"
162
+ )
161
163
  file_import.merge(self.item_type.imports(**kwargs))
162
164
  if self.default_error_deserialization or self.need_deserialize:
163
165
  file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
@@ -275,7 +275,7 @@ class BodyParameter(_ParameterBase):
275
275
  if self.is_form_data:
276
276
  serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
277
277
  file_import.add_submodule_import(
278
- self.code_model.get_relative_import_path(serialize_namespace, module_name="_vendor"),
278
+ self.code_model.get_relative_import_path(serialize_namespace, module_name="_utils.utils"),
279
279
  "prepare_multipart_form_data",
280
280
  ImportType.LOCAL,
281
281
  )
@@ -357,6 +357,9 @@ class Parameter(_ParameterBase):
357
357
  )
358
358
  if self.code_model.options["only_path_and_body_params_positional"] and query_or_header:
359
359
  return ParameterMethodLocation.KEYWORD_ONLY
360
+ # for optional path parameter, we need to use keyword only
361
+ if self.location == ParameterLocation.PATH and self.optional:
362
+ return ParameterMethodLocation.KEYWORD_ONLY
360
363
  return ParameterMethodLocation.POSITIONAL
361
364
 
362
365
  @classmethod
@@ -618,13 +618,13 @@ class MultiPartFileType(PrimitiveType):
618
618
  return self.name
619
619
 
620
620
  def docstring_type(self, **kwargs: Any) -> str:
621
- return f"~{self.code_model.namespace}._vendor.{self.name}"
621
+ return f"~{self.code_model.namespace}._utils.utils.{self.name}"
622
622
 
623
623
  def imports(self, **kwargs: Any) -> FileImport:
624
624
  file_import = super().imports(**kwargs)
625
625
  serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
626
626
  file_import.add_submodule_import(
627
- self.code_model.get_relative_import_path(serialize_namespace, module_name="_vendor"),
627
+ self.code_model.get_relative_import_path(serialize_namespace, module_name="_utils.utils"),
628
628
  self.name,
629
629
  ImportType.LOCAL,
630
630
  )
@@ -149,7 +149,7 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
149
149
  if self.code_model.options["models_mode"] == "dpg":
150
150
  serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
151
151
  file_import.add_submodule_import(
152
- self.code_model.get_relative_import_path(serialize_namespace, module_name="_model_base"),
152
+ self.code_model.get_relative_import_path(serialize_namespace, module_name="_utils.model_base"),
153
153
  "rest_discriminator" if self.is_discriminator else "rest_field",
154
154
  ImportType.LOCAL,
155
155
  )
@@ -153,7 +153,7 @@ class JinjaSerializer(ReaderAndWriter):
153
153
  general_serializer.serialize_pkgutil_init_file(),
154
154
  )
155
155
 
156
- # _model_base.py/_serialization.py/_vendor.py/py.typed/_types.py/_validation.py
156
+ # _utils/py.typed/_types.py/_validation.py
157
157
  # is always put in top level namespace
158
158
  if self.code_model.is_top_namespace(client_namespace):
159
159
  self._serialize_and_write_top_level_folder(env=env, namespace=client_namespace)
@@ -404,25 +404,41 @@ class JinjaSerializer(ReaderAndWriter):
404
404
  general_serializer.serialize_config_file(clients),
405
405
  )
406
406
 
407
- # sometimes we need define additional Mixin class for client in _vendor.py
408
- self._serialize_and_write_vendor_file(env, namespace)
407
+ # sometimes we need define additional Mixin class for client in _utils.py
408
+ self._serialize_and_write_utils_folder(env, namespace)
409
409
 
410
- def _serialize_and_write_vendor_file(self, env: Environment, namespace: str) -> None:
410
+ def _serialize_and_write_utils_folder(self, env: Environment, namespace: str) -> None:
411
411
  exec_path = self.exec_path(namespace)
412
- # write _vendor.py
413
- for async_mode, async_path in self.serialize_loop:
414
- if self.code_model.need_vendored_code(async_mode=async_mode, client_namespace=namespace):
415
- self.write_file(
416
- exec_path / Path(f"{async_path}_vendor.py"),
417
- GeneralSerializer(
418
- code_model=self.code_model, env=env, async_mode=async_mode, client_namespace=namespace
419
- ).serialize_vendor_file(),
420
- )
412
+ general_serializer = GeneralSerializer(code_model=self.code_model, env=env, async_mode=False)
413
+ utils_folder_path = exec_path / Path("_utils")
414
+ if self.code_model.need_utils_folder(async_mode=False, client_namespace=namespace):
415
+ self.write_file(
416
+ utils_folder_path / Path("__init__.py"),
417
+ self.code_model.license_header,
418
+ )
419
+ if self.code_model.need_utils_utils(async_mode=False, client_namespace=namespace):
420
+ self.write_file(
421
+ utils_folder_path / Path("utils.py"),
422
+ general_serializer.need_utils_utils_file(),
423
+ )
424
+ # write _utils/serialization.py
425
+ if self.code_model.need_utils_serialization:
426
+ self.write_file(
427
+ utils_folder_path / Path("serialization.py"),
428
+ general_serializer.serialize_serialization_file(),
429
+ )
430
+
431
+ # write _model_base.py
432
+ if self.code_model.options["models_mode"] == "dpg":
433
+ self.write_file(
434
+ utils_folder_path / Path("model_base.py"),
435
+ general_serializer.serialize_model_base_file(),
436
+ )
421
437
 
422
438
  def _serialize_and_write_top_level_folder(self, env: Environment, namespace: str) -> None:
423
439
  exec_path = self.exec_path(namespace)
424
- # write _vendor.py
425
- self._serialize_and_write_vendor_file(env, namespace)
440
+ # write _utils folder
441
+ self._serialize_and_write_utils_folder(env, namespace)
426
442
 
427
443
  general_serializer = GeneralSerializer(code_model=self.code_model, env=env, async_mode=False)
428
444
 
@@ -432,20 +448,6 @@ class JinjaSerializer(ReaderAndWriter):
432
448
  # write the empty py.typed file
433
449
  self.write_file(exec_path / Path("py.typed"), "# Marker file for PEP 561.")
434
450
 
435
- # write _serialization.py
436
- if not self.code_model.options["client_side_validation"] and not self.code_model.options["multiapi"]:
437
- self.write_file(
438
- exec_path / Path("_serialization.py"),
439
- general_serializer.serialize_serialization_file(),
440
- )
441
-
442
- # write _model_base.py
443
- if self.code_model.options["models_mode"] == "dpg":
444
- self.write_file(
445
- exec_path / Path("_model_base.py"),
446
- general_serializer.serialize_model_base_file(),
447
- )
448
-
449
451
  # write _validation.py
450
452
  if any(og for client in self.code_model.clients for og in client.operation_groups if og.need_validation):
451
453
  self.write_file(
@@ -672,7 +672,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
672
672
  [
673
673
  "_body = (",
674
674
  f" {body_param.client_name}.as_dict()",
675
- f" if isinstance({body_param.client_name}, _model_base.Model) else",
675
+ f" if isinstance({body_param.client_name}, _Model) else",
676
676
  f" {body_param.client_name}",
677
677
  ")",
678
678
  f"_file_fields: List[str] = {file_fields}",