@typespec/http-client-python 0.11.0 → 0.11.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 (55) hide show
  1. package/dist/emitter/emitter.d.ts.map +1 -1
  2. package/dist/emitter/emitter.js +0 -5
  3. package/dist/emitter/emitter.js.map +1 -1
  4. package/dist/emitter/lib.d.ts +2 -17
  5. package/dist/emitter/lib.d.ts.map +1 -1
  6. package/dist/emitter/lib.js +0 -7
  7. package/dist/emitter/lib.js.map +1 -1
  8. package/emitter/src/emitter.ts +0 -5
  9. package/emitter/src/lib.ts +0 -7
  10. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  11. package/eng/scripts/setup/__pycache__/venvtools.cpython-39.pyc +0 -0
  12. package/generator/build/lib/pygen/codegen/models/code_model.py +22 -11
  13. package/generator/build/lib/pygen/codegen/models/imports.py +13 -9
  14. package/generator/build/lib/pygen/codegen/models/lro_operation.py +1 -1
  15. package/generator/build/lib/pygen/codegen/models/model_type.py +3 -2
  16. package/generator/build/lib/pygen/codegen/models/operation.py +10 -3
  17. package/generator/build/lib/pygen/codegen/models/operation_group.py +27 -31
  18. package/generator/build/lib/pygen/codegen/models/paging_operation.py +3 -1
  19. package/generator/build/lib/pygen/codegen/models/parameter.py +1 -1
  20. package/generator/build/lib/pygen/codegen/models/primitive_types.py +2 -2
  21. package/generator/build/lib/pygen/codegen/models/property.py +1 -1
  22. package/generator/build/lib/pygen/codegen/serializers/__init__.py +31 -29
  23. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +1 -1
  24. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +10 -21
  25. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +4 -3
  26. package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +1 -1
  27. package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +3 -3
  28. package/generator/build/lib/pygen/codegen/templates/{vendor.py.jinja2 → utils.py.jinja2} +11 -12
  29. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  30. package/generator/pygen/codegen/models/code_model.py +22 -11
  31. package/generator/pygen/codegen/models/imports.py +13 -9
  32. package/generator/pygen/codegen/models/lro_operation.py +1 -1
  33. package/generator/pygen/codegen/models/model_type.py +3 -2
  34. package/generator/pygen/codegen/models/operation.py +10 -3
  35. package/generator/pygen/codegen/models/operation_group.py +27 -31
  36. package/generator/pygen/codegen/models/paging_operation.py +3 -1
  37. package/generator/pygen/codegen/models/parameter.py +1 -1
  38. package/generator/pygen/codegen/models/primitive_types.py +2 -2
  39. package/generator/pygen/codegen/models/property.py +1 -1
  40. package/generator/pygen/codegen/serializers/__init__.py +31 -29
  41. package/generator/pygen/codegen/serializers/builder_serializer.py +1 -1
  42. package/generator/pygen/codegen/serializers/general_serializer.py +10 -21
  43. package/generator/pygen/codegen/serializers/model_serializer.py +4 -3
  44. package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +1 -1
  45. package/generator/pygen/codegen/templates/operation_group.py.jinja2 +3 -3
  46. package/generator/pygen/codegen/templates/{vendor.py.jinja2 → utils.py.jinja2} +11 -12
  47. package/generator/pygen.egg-info/SOURCES.txt +1 -1
  48. package/generator/test/generic_mock_api_tests/asynctests/test_encode_bytes_async.py +1 -0
  49. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_nullable_async.py +1 -1
  50. package/generator/test/generic_mock_api_tests/test_encode_bytes.py +1 -0
  51. package/generator/test/generic_mock_api_tests/test_typetest_property_nullable.py +1 -1
  52. package/generator/test/unittests/conftest.py +1 -0
  53. package/generator/test/unittests/test_model_base_serialization.py +1 -1
  54. package/generator/test/unittests/test_model_base_xml_serialization.py +1 -1
  55. package/package.json +1 -1
@@ -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)
@@ -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
  )
@@ -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
  )
@@ -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}",
@@ -107,44 +107,33 @@ class GeneralSerializer(BaseSerializer):
107
107
  serialize_namespace=self.serialize_namespace,
108
108
  )
109
109
 
110
- def serialize_vendor_file(self) -> str:
111
- template = self.env.get_template("vendor.py.jinja2")
110
+ def need_utils_utils_file(self) -> str:
111
+ template = self.env.get_template("utils.py.jinja2")
112
112
  clients = self.code_model.get_clients(self.client_namespace)
113
113
 
114
114
  # configure imports
115
115
  file_import = FileImport(self.code_model)
116
- if self.code_model.need_vendored_mixin(self.client_namespace):
116
+ if self.code_model.need_utils_mixin:
117
117
  file_import.add_submodule_import(
118
118
  "abc",
119
119
  "ABC",
120
120
  ImportType.STDLIB,
121
121
  )
122
- file_import.add_submodule_import(
123
- "" if self.code_model.is_azure_flavor else "runtime",
124
- f"{'Async' if self.async_mode else ''}PipelineClient",
125
- ImportType.SDKCORE,
126
- TypingSection.TYPING,
127
- )
128
122
  file_import.add_msrest_import(
129
- serialize_namespace=self.serialize_namespace,
123
+ serialize_namespace=f"{self.serialize_namespace}._utils",
130
124
  msrest_import_type=MsrestImportType.SerializerDeserializer,
131
125
  typing_section=TypingSection.TYPING,
132
126
  )
133
- for client in clients:
134
- if client.has_mixin:
135
- file_import.add_submodule_import(
136
- "._configuration",
137
- f"{client.name}Configuration",
138
- ImportType.LOCAL,
139
- )
140
- if self.code_model.need_vendored_etag(self.client_namespace):
127
+ file_import.add_submodule_import("typing", "TypeVar", ImportType.STDLIB)
128
+ file_import.add_submodule_import("typing", "Generic", ImportType.STDLIB)
129
+ if self.code_model.need_utils_etag(self.client_namespace):
141
130
  file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB)
142
131
  file_import.add_submodule_import(
143
132
  "",
144
133
  "MatchConditions",
145
134
  ImportType.SDKCORE,
146
135
  )
147
- if self.code_model.need_vendored_form_data(self.async_mode, self.client_namespace):
136
+ if self.code_model.need_utils_form_data(self.async_mode, self.client_namespace):
148
137
  file_import.add_submodule_import("typing", "IO", ImportType.STDLIB)
149
138
  file_import.add_submodule_import("typing", "Tuple", ImportType.STDLIB)
150
139
  file_import.add_submodule_import("typing", "Union", ImportType.STDLIB)
@@ -154,12 +143,12 @@ class GeneralSerializer(BaseSerializer):
154
143
  file_import.add_submodule_import("typing", "Any", ImportType.STDLIB)
155
144
  file_import.add_submodule_import("typing", "List", ImportType.STDLIB)
156
145
  file_import.add_submodule_import(
157
- "._model_base",
146
+ ".._utils.model_base",
158
147
  "SdkJSONEncoder",
159
148
  ImportType.LOCAL,
160
149
  )
161
150
  file_import.add_submodule_import(
162
- "._model_base",
151
+ ".._utils.model_base",
163
152
  "Model",
164
153
  ImportType.LOCAL,
165
154
  )
@@ -230,10 +230,11 @@ class DpgModelSerializer(_ModelSerializer):
230
230
  file_import = FileImport(self.code_model)
231
231
  if any(not m.parents for m in self.models):
232
232
  file_import.add_submodule_import(
233
- self.code_model.get_relative_import_path(self.serialize_namespace),
234
- "_model_base",
233
+ self.code_model.get_relative_import_path(self.serialize_namespace, module_name="_utils.model_base"),
234
+ "Model",
235
235
  ImportType.LOCAL,
236
236
  TypingSection.REGULAR,
237
+ alias="_Model",
237
238
  )
238
239
  for model in self.models:
239
240
  if model.base == "json":
@@ -272,7 +273,7 @@ class DpgModelSerializer(_ModelSerializer):
272
273
  return file_import
273
274
 
274
275
  def declare_model(self, model: ModelType) -> str:
275
- basename = "_model_base.Model"
276
+ basename = "_Model"
276
277
  if model.parents:
277
278
  basename = ", ".join([m.name for m in model.parents])
278
279
  if model.discriminator_value:
@@ -19,7 +19,7 @@
19
19
  """
20
20
 
21
21
  {% if model.is_polymorphic %}
22
- __mapping__: Dict[str, _model_base.Model] = {}
22
+ __mapping__: Dict[str, _Model] = {}
23
23
  {% endif %}
24
24
  {% for p in serializer.get_properties_to_declare(model)%}
25
25
  {{ serializer.declare_property(p) }}
@@ -1,4 +1,4 @@
1
- {% set base_class = ("(" + operation_group.base_class + ")") if operation_group.base_class else "" %}
1
+ {% set base_class = ("(" + operation_group.base_class(async_mode) + ")") if operation_group.base_class(async_mode) else "" %}
2
2
  {% macro check_abstract_methods() %}
3
3
  {% if operation_group.has_abstract_operations %}
4
4
  raise_if_not_implemented(self.__class__, [
@@ -8,9 +8,9 @@
8
8
  ])
9
9
  {% endif %}
10
10
  {% endmacro %}
11
- {% if operation_group.base_class %}
11
+ {% if operation_group.base_class(async_mode) %}
12
12
  class {{ operation_group.class_name }}( {{ operation_group.pylint_disable() }}
13
- {{ operation_group.base_class }}
13
+ {{ operation_group.base_class(async_mode) }}
14
14
  ):
15
15
  {% else %}
16
16
  class {{ operation_group.class_name }}: {{ operation_group.pylint_disable() }}
@@ -5,20 +5,19 @@
5
5
 
6
6
  {{ imports }}
7
7
 
8
- {% if code_model.need_vendored_mixin(client_namespace) %}
9
- {% for client in clients | selectattr("has_mixin") %}
10
- {% set pylint_disable = "# pylint: disable=name-too-long" if (client.name | length) + ("MixinABC" | length) > 40 else "" %}
11
- class {{ client.name }}MixinABC( {{ pylint_disable }}
12
- ABC
13
- ):
8
+ {% if code_model.need_utils_mixin %}
9
+
10
+ TClient = TypeVar("TClient")
11
+ TConfig = TypeVar("TConfig")
12
+
13
+ class ClientMixinABC(ABC, Generic[TClient, TConfig]):
14
14
  """DO NOT use this class. It is for internal typing use only."""
15
- _client: "{{ keywords.async_class }}PipelineClient"
16
- _config: {{ client.name }}Configuration
15
+ _client: TClient
16
+ _config: TConfig
17
17
  _serialize: "Serializer"
18
18
  _deserialize: "Deserializer"
19
- {% endfor %}
20
19
  {% endif %}
21
- {% if code_model.need_vendored_abstract(client_namespace) %}
20
+ {% if code_model.need_utils_abstract(client_namespace) %}
22
21
 
23
22
  def raise_if_not_implemented(cls, abstract_methods):
24
23
  not_implemented = [f for f in abstract_methods if not callable(getattr(cls, f, None))]
@@ -29,7 +28,7 @@ def raise_if_not_implemented(cls, abstract_methods):
29
28
  )
30
29
  {% endif %}
31
30
 
32
- {% if code_model.need_vendored_etag(client_namespace) %}
31
+ {% if code_model.need_utils_etag(client_namespace) %}
33
32
  def quote_etag(etag: Optional[str]) -> Optional[str]:
34
33
  if not etag or etag == "*":
35
34
  return etag
@@ -59,7 +58,7 @@ def prep_if_none_match(etag: Optional[str], match_condition: Optional[MatchCondi
59
58
  return "*"
60
59
  return None
61
60
  {% endif %}
62
- {% if code_model.need_vendored_form_data(async_mode, client_namespace) %}
61
+ {% if code_model.need_utils_form_data(async_mode, client_namespace) %}
63
62
  # file-like tuple could be `(filename, IO (or bytes))` or `(filename, IO (or bytes), content_type)`
64
63
  FileContent = Union[str, bytes, IO[str], IO[bytes]]
65
64
 
@@ -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)