@autorest/python 5.18.0 → 5.19.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 (30) hide show
  1. package/ChangeLog.md +17 -16
  2. package/autorest/codegen/__init__.py +7 -2
  3. package/autorest/codegen/models/client.py +8 -5
  4. package/autorest/codegen/models/code_model.py +15 -4
  5. package/autorest/codegen/models/imports.py +57 -2
  6. package/autorest/codegen/models/lro_operation.py +2 -0
  7. package/autorest/codegen/models/operation.py +44 -45
  8. package/autorest/codegen/models/operation_group.py +6 -2
  9. package/autorest/codegen/models/paging_operation.py +2 -0
  10. package/autorest/codegen/models/request_builder.py +31 -20
  11. package/autorest/codegen/serializers/__init__.py +9 -0
  12. package/autorest/codegen/serializers/builder_serializer.py +0 -4
  13. package/autorest/codegen/serializers/client_serializer.py +8 -0
  14. package/autorest/codegen/serializers/general_serializer.py +10 -5
  15. package/autorest/codegen/serializers/model_base_serializer.py +10 -5
  16. package/autorest/codegen/serializers/operation_groups_serializer.py +3 -0
  17. package/autorest/codegen/serializers/request_builders_serializer.py +1 -1
  18. package/autorest/codegen/templates/client.py.jinja2 +3 -0
  19. package/autorest/codegen/templates/operation_group.py.jinja2 +15 -2
  20. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +2 -2
  21. package/autorest/codegen/templates/operation_tools.jinja2 +3 -1
  22. package/autorest/codegen/templates/request_builder.py.jinja2 +0 -7
  23. package/autorest/codegen/templates/request_builders.py.jinja2 +1 -1
  24. package/autorest/codegen/templates/serialization.py.jinja2 +2006 -0
  25. package/autorest/codegen/templates/setup.py.jinja2 +4 -0
  26. package/autorest/codegen/templates/vendor.py.jinja2 +10 -0
  27. package/autorest/multiapi/models/client.py +12 -2
  28. package/autorest/multiapi/serializers/__init__.py +14 -0
  29. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  30. package/package.json +1 -1
package/ChangeLog.md CHANGED
@@ -1,39 +1,40 @@
1
- # Change
1
+ # Release History
2
2
 
3
- ### 2022-07-09 - 5.18.0
3
+ ### 2022-07-13 - 5.19.0
4
4
 
5
5
  | Library | Min Version |
6
6
  | ----------------------------------------------------------------------- | ----------- |
7
7
  | `@autorest/core` | `3.8.1` |
8
8
  | `@autorest/modelerfour` | `4.23.5` |
9
- | `azure-core` dep of generated code | `1.23.0` |
10
- | `msrest` dep of generated code | `0.6.21` |
9
+ | `azure-core` dep of generated code | `1.24.0` |
10
+ | `msrest` dep of generated code | `0.7.0` |
11
11
  | `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
12
12
 
13
- **Breaking Changes in Version Tolerant**
14
-
15
- - No longer allow users to specify `api_version` on the method level #1281
16
- - Make `content_type` param required with no default if streaming with no `application/octet-stream` #1288
17
-
18
- **Bug Fixes**
19
-
20
- - Fix duplicate params in signature with `--payload-flattening-threshold` #1289
21
- - Fix overloaded request builder signatures #1289
13
+ **New Features**
14
+ - Add _serialization.py for `--client-side-validation=false` generation, and migrate serilization from msrest to _serialization.py #1236
22
15
 
23
- ### 2022-xx-xx - 5.17.1
16
+ ### 2022-07-13 - 5.18.0
24
17
 
25
18
  | Library | Min Version |
26
19
  | ----------------------------------------------------------------------- | ----------- |
27
20
  | `@autorest/core` | `3.8.1` |
28
21
  | `@autorest/modelerfour` | `4.23.5` |
29
- | `azure-core` dep of generated code | `1.23.0` |
30
- | `msrest` dep of generated code | `0.6.21` |
22
+ | `azure-core` dep of generated code | `1.24.0` |
23
+ | `msrest` dep of generated code | `0.7.0` |
31
24
  | `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
32
25
 
26
+ **Breaking Changes in Version Tolerant**
27
+
28
+ - No longer allow users to specify `api_version` on the method level #1281
29
+ - Make `content_type` param required with no default if streaming with no `application/octet-stream` #1288
30
+
33
31
  **Bug Fixes**
34
32
 
33
+ - Fix duplicate params in signature with `--payload-flattening-threshold` #1289
34
+ - Fix overloaded request builder signatures #1289
35
35
  - Improve docstring templates, specifically for polymorphic bodies #1279
36
36
 
37
+
37
38
  ### 2022-06-02 - 5.17.0
38
39
 
39
40
  | Library | Min Version |
@@ -97,6 +97,11 @@ def _validate_code_model_options(options: Dict[str, Any]) -> None:
97
97
  "We are working on creating a new multiapi SDK for version tolerant and it is not available yet."
98
98
  )
99
99
 
100
+ if options["client_side_validation"] and options["version_tolerant"]:
101
+ raise ValueError(
102
+ "Can not generate version tolerant with --client-side-validation. "
103
+ )
104
+
100
105
 
101
106
  _LOGGER = logging.getLogger(__name__)
102
107
 
@@ -130,8 +135,8 @@ class CodeGenerator(Plugin):
130
135
  def _build_package_dependency() -> Dict[str, str]:
131
136
  return {
132
137
  "dependency_azure_mgmt_core": "azure-mgmt-core<2.0.0,>=1.3.0",
133
- "dependency_azure_core": "azure-core<2.0.0,>=1.23.0",
134
- "dependency_msrest": "msrest>=0.6.21",
138
+ "dependency_azure_core": "azure-core<2.0.0,>=1.24.0",
139
+ "dependency_msrest": "msrest>=0.7.0",
135
140
  }
136
141
 
137
142
  def _create_code_model(
@@ -7,7 +7,7 @@ from typing import Any, Dict, TYPE_CHECKING, TypeVar, Generic, Union
7
7
 
8
8
  from .base_model import BaseModel
9
9
  from .parameter_list import ClientGlobalParameterList, ConfigGlobalParameterList
10
- from .imports import FileImport, ImportType, TypingSection
10
+ from .imports import FileImport, ImportType, TypingSection, MsrestImportType
11
11
  from .utils import add_to_pylint_disable
12
12
 
13
13
  ParameterListType = TypeVar(
@@ -89,10 +89,6 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
89
89
  def _imports_shared(self, async_mode: bool) -> FileImport:
90
90
  file_import = FileImport()
91
91
 
92
- file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY)
93
- file_import.add_submodule_import(
94
- "msrest", "Deserializer", ImportType.THIRDPARTY
95
- )
96
92
  file_import.add_submodule_import(
97
93
  "typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
98
94
  )
@@ -113,6 +109,13 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
113
109
  ImportType.LOCAL,
114
110
  )
115
111
 
112
+ file_import.add_msrest_import(
113
+ self.code_model,
114
+ ".." if async_mode else ".",
115
+ MsrestImportType.SerializerDeserializer,
116
+ TypingSection.REGULAR,
117
+ )
118
+
116
119
  return file_import
117
120
 
118
121
  def imports(self, async_mode: bool) -> FileImport:
@@ -200,8 +200,15 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
200
200
  name = f"_{name}"
201
201
  return name
202
202
 
203
+ @property
204
+ def has_abstract_operations(self) -> bool:
205
+ """Whether there is abstract operation in any operation group."""
206
+ return any(og.has_abstract_operations for og in self.operation_groups)
207
+
203
208
  def need_vendored_code(self, async_mode: bool) -> bool:
204
209
  """Whether we need to vendor code in the _vendor.py file for this SDK"""
210
+ if self.has_abstract_operations:
211
+ return True
205
212
  if async_mode:
206
213
  return self.need_mixin_abc
207
214
  return (
@@ -247,9 +254,7 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
247
254
 
248
255
  def get_models_filename(self, is_python3_file: bool) -> str:
249
256
  """Get the names of the model file(s)"""
250
- if (
251
- self.options["version_tolerant"] or self.options["low_level_client"]
252
- ) and self.options["python3_only"]:
257
+ if not self.is_legacy and self.options["python3_only"]:
253
258
  return "_models"
254
259
  if is_python3_file:
255
260
  return "_models_py3"
@@ -258,10 +263,16 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
258
263
  @property
259
264
  def enums_filename(self) -> str:
260
265
  """The name of the enums file"""
261
- if self.options["version_tolerant"] or self.options["low_level_client"]:
266
+ if not self.is_legacy:
262
267
  return "_enums"
263
268
  return f"_{self.module_name}_enums"
264
269
 
270
+ @property
271
+ def is_legacy(self) -> bool:
272
+ return not (
273
+ self.options["version_tolerant"] or self.options["low_level_client"]
274
+ )
275
+
265
276
  @property
266
277
  def rest_layer_name(self) -> str:
267
278
  """If we have a separate rest layer, what is its name?"""
@@ -3,8 +3,11 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- from enum import Enum
7
- from typing import Dict, List, Optional, Tuple, Union, Set, Mapping
6
+ from enum import Enum, auto
7
+ from typing import Dict, List, Optional, Tuple, Union, Set, Mapping, TYPE_CHECKING
8
+
9
+ if TYPE_CHECKING:
10
+ from .code_model import CodeModel
8
11
 
9
12
 
10
13
  class ImportType(str, Enum):
@@ -20,6 +23,16 @@ class TypingSection(str, Enum):
20
23
  TYPING = "typing" # never a typing import
21
24
 
22
25
 
26
+ class MsrestImportType(Enum):
27
+ Module = auto() # import _serialization.py or msrest.serialization as Module
28
+ Serializer = (
29
+ auto()
30
+ ) # from _serialization.py or msrest.serialization import Serializer
31
+ SerializerDeserializer = (
32
+ auto()
33
+ ) # from _serialization.py or msrest.serialization import Serializer and Deserializer
34
+
35
+
23
36
  class ImportModel:
24
37
  def __init__(
25
38
  self,
@@ -190,3 +203,45 @@ class FileImport:
190
203
  i.import_type, dict()
191
204
  ).setdefault(i.module_name, set()).add(name_import)
192
205
  return retval
206
+
207
+ def add_msrest_import(
208
+ self,
209
+ code_model: "CodeModel",
210
+ relative_path: str,
211
+ msrest_import_type: MsrestImportType,
212
+ typing_section: TypingSection,
213
+ ):
214
+ if code_model.options["client_side_validation"]:
215
+ if msrest_import_type == MsrestImportType.Module:
216
+ self.add_import(
217
+ "msrest.serialization", ImportType.AZURECORE, typing_section
218
+ )
219
+ else:
220
+ self.add_submodule_import(
221
+ "msrest", "Serializer", ImportType.THIRDPARTY, typing_section
222
+ )
223
+ if msrest_import_type == MsrestImportType.SerializerDeserializer:
224
+ self.add_submodule_import(
225
+ "msrest", "Deserializer", ImportType.THIRDPARTY, typing_section
226
+ )
227
+ else:
228
+ if code_model.options["multiapi"]:
229
+ relative_path += "."
230
+ if msrest_import_type == MsrestImportType.Module:
231
+ self.add_submodule_import(
232
+ relative_path, "_serialization", ImportType.LOCAL, typing_section
233
+ )
234
+ else:
235
+ self.add_submodule_import(
236
+ f"{relative_path}_serialization",
237
+ "Serializer",
238
+ ImportType.LOCAL,
239
+ typing_section,
240
+ )
241
+ if msrest_import_type == MsrestImportType.SerializerDeserializer:
242
+ self.add_submodule_import(
243
+ f"{relative_path}_serialization",
244
+ "Deserializer",
245
+ ImportType.LOCAL,
246
+ typing_section,
247
+ )
@@ -124,6 +124,8 @@ class LROOperationBase(OperationBase[LROResponseType]):
124
124
  self, async_mode: bool, is_python3_file: bool, **kwargs: Any
125
125
  ) -> FileImport:
126
126
  file_import = super().imports(async_mode, is_python3_file, **kwargs)
127
+ if self.abstract:
128
+ return file_import
127
129
  if async_mode:
128
130
  file_import.add_submodule_import(
129
131
  f"azure.core.tracing.decorator_async",
@@ -204,9 +204,8 @@ class OperationBase( # pylint: disable=too-many-public-methods
204
204
  file_import.add_submodule_import(
205
205
  "typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
206
206
  )
207
- if not self.abstract:
208
- for param in self.parameters.method:
209
- file_import.merge(param.imports(async_mode, **kwargs))
207
+ for param in self.parameters.method:
208
+ file_import.merge(param.imports(async_mode, **kwargs))
210
209
 
211
210
  response_types = [
212
211
  r.type_annotation(async_mode=async_mode) for r in self.responses if r.type
@@ -218,6 +217,8 @@ class OperationBase( # pylint: disable=too-many-public-methods
218
217
  return file_import
219
218
 
220
219
  def imports_for_multiapi(self, async_mode: bool, **kwargs: Any) -> FileImport:
220
+ if self.abstract:
221
+ return FileImport()
221
222
  file_import = self._imports_shared(async_mode, **kwargs)
222
223
  for response in self.responses:
223
224
  file_import.merge(
@@ -289,6 +290,8 @@ class OperationBase( # pylint: disable=too-many-public-methods
289
290
  def imports(
290
291
  self, async_mode: bool, is_python3_file: bool, **kwargs: Any
291
292
  ) -> FileImport:
293
+ if self.abstract:
294
+ return FileImport()
292
295
  file_import = self._imports_shared(async_mode, **kwargs)
293
296
 
294
297
  for response in self.responses:
@@ -301,48 +304,45 @@ class OperationBase( # pylint: disable=too-many-public-methods
301
304
  file_import.merge(self.parameters.body_parameter.type.imports(**kwargs))
302
305
 
303
306
  # Exceptions
304
- if self.abstract:
305
- file_import.add_import("abc", ImportType.STDLIB)
306
- else:
307
- file_import.add_submodule_import(
308
- "azure.core.exceptions", "map_error", ImportType.AZURECORE
309
- )
310
- if self.code_model.options["azure_arm"]:
311
- file_import.add_submodule_import(
312
- "azure.mgmt.core.exceptions", "ARMErrorFormat", ImportType.AZURECORE
313
- )
314
- file_import.add_submodule_import(
315
- "azure.core.exceptions", "HttpResponseError", ImportType.AZURECORE
316
- )
307
+ file_import.add_submodule_import(
308
+ "azure.core.exceptions", "map_error", ImportType.AZURECORE
309
+ )
310
+ if self.code_model.options["azure_arm"]:
317
311
  file_import.add_submodule_import(
318
- "azure.core.exceptions",
319
- "ClientAuthenticationError",
320
- ImportType.AZURECORE,
312
+ "azure.mgmt.core.exceptions", "ARMErrorFormat", ImportType.AZURECORE
321
313
  )
314
+ file_import.add_submodule_import(
315
+ "azure.core.exceptions", "HttpResponseError", ImportType.AZURECORE
316
+ )
317
+ file_import.add_submodule_import(
318
+ "azure.core.exceptions",
319
+ "ClientAuthenticationError",
320
+ ImportType.AZURECORE,
321
+ )
322
+ file_import.add_submodule_import(
323
+ "azure.core.exceptions", "ResourceNotFoundError", ImportType.AZURECORE
324
+ )
325
+ file_import.add_submodule_import(
326
+ "azure.core.exceptions", "ResourceExistsError", ImportType.AZURECORE
327
+ )
328
+
329
+ kwargs_to_pop = self.parameters.kwargs_to_pop(is_python3_file)
330
+ if self.has_kwargs_to_pop_with_default(
331
+ kwargs_to_pop, ParameterLocation.HEADER
332
+ ) or self.has_kwargs_to_pop_with_default(
333
+ kwargs_to_pop, ParameterLocation.QUERY
334
+ ):
322
335
  file_import.add_submodule_import(
323
- "azure.core.exceptions", "ResourceNotFoundError", ImportType.AZURECORE
336
+ "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
324
337
  )
338
+ if self.deprecated:
339
+ file_import.add_import("warnings", ImportType.STDLIB)
340
+
341
+ if self.code_model.need_request_converter:
342
+ relative_path = "..." if async_mode else ".."
325
343
  file_import.add_submodule_import(
326
- "azure.core.exceptions", "ResourceExistsError", ImportType.AZURECORE
344
+ f"{relative_path}_vendor", "_convert_request", ImportType.LOCAL
327
345
  )
328
-
329
- kwargs_to_pop = self.parameters.kwargs_to_pop(is_python3_file)
330
- if self.has_kwargs_to_pop_with_default(
331
- kwargs_to_pop, ParameterLocation.HEADER
332
- ) or self.has_kwargs_to_pop_with_default(
333
- kwargs_to_pop, ParameterLocation.QUERY
334
- ):
335
- file_import.add_submodule_import(
336
- "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
337
- )
338
- if self.deprecated:
339
- file_import.add_import("warnings", ImportType.STDLIB)
340
-
341
- if self.code_model.need_request_converter:
342
- relative_path = "..." if async_mode else ".."
343
- file_import.add_submodule_import(
344
- f"{relative_path}_vendor", "_convert_request", ImportType.LOCAL
345
- )
346
346
  if async_mode:
347
347
  file_import.add_submodule_import(
348
348
  "azure.core.pipeline.transport",
@@ -382,10 +382,9 @@ class OperationBase( # pylint: disable=too-many-public-methods
382
382
  f"distributed_trace",
383
383
  ImportType.AZURECORE,
384
384
  )
385
- if not self.abstract:
386
- file_import.merge(
387
- self.get_request_builder_import(self.request_builder, async_mode)
388
- )
385
+ file_import.merge(
386
+ self.get_request_builder_import(self.request_builder, async_mode)
387
+ )
389
388
  if self.overloads:
390
389
  file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
391
390
  return file_import
@@ -473,14 +472,14 @@ class Operation(OperationBase[Response]):
473
472
  self, async_mode: bool, is_python3_file: bool, **kwargs: Any
474
473
  ) -> FileImport:
475
474
  file_import = super().imports(async_mode, is_python3_file, **kwargs)
475
+ if self.abstract:
476
+ return file_import
476
477
  if async_mode:
477
478
  file_import.add_submodule_import(
478
479
  f"azure.core.tracing.decorator_async",
479
480
  f"distributed_trace_async",
480
481
  ImportType.AZURECORE,
481
482
  )
482
- if self.abstract:
483
- return file_import
484
483
  if (
485
484
  self.has_response_body
486
485
  and not self.has_optional_return_type
@@ -42,8 +42,6 @@ class OperationGroup(BaseModel):
42
42
  base_classes.append("MixinABC")
43
43
  if not (async_mode or self.code_model.options["python3_only"]):
44
44
  base_classes.append("object")
45
- if self.has_abstract_operations:
46
- base_classes.append("abc.ABC")
47
45
  return ", ".join(base_classes)
48
46
 
49
47
  def imports_for_multiapi(self, async_mode: bool) -> FileImport:
@@ -89,6 +87,12 @@ class OperationGroup(BaseModel):
89
87
  )
90
88
  if self.code_model.need_mixin_abc:
91
89
  file_import.add_submodule_import(".._vendor", "MixinABC", ImportType.LOCAL)
90
+ if self.has_abstract_operations:
91
+ file_import.add_submodule_import(
92
+ ".._vendor", "raise_if_not_implemented", ImportType.LOCAL
93
+ )
94
+ if all(o.abstract for o in self.operations):
95
+ return file_import
92
96
  file_import.add_submodule_import(
93
97
  "typing", "TypeVar", ImportType.STDLIB, TypingSection.CONDITIONAL
94
98
  )
@@ -130,6 +130,8 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
130
130
  def imports(
131
131
  self, async_mode: bool, is_python3_file: bool, **kwargs: Any
132
132
  ) -> FileImport:
133
+ if self.abstract:
134
+ return FileImport()
133
135
  file_import = self._imports_shared(async_mode, **kwargs)
134
136
  file_import.merge(super().imports(async_mode, is_python3_file, **kwargs))
135
137
  if self.code_model.options["tracing"] and self.want_tracing:
@@ -21,7 +21,7 @@ from .parameter_list import (
21
21
  RequestBuilderParameterList,
22
22
  OverloadedRequestBuilderParameterList,
23
23
  )
24
- from .imports import FileImport, ImportType, TypingSection
24
+ from .imports import FileImport, ImportType, TypingSection, MsrestImportType
25
25
  from .request_builder_parameter import RequestBuilderMultipartBodyParameter
26
26
 
27
27
  if TYPE_CHECKING:
@@ -73,34 +73,45 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
73
73
 
74
74
  def imports(self) -> FileImport:
75
75
  file_import = FileImport()
76
- if not self.abstract:
77
- for parameter in self.parameters.method:
78
- file_import.merge(parameter.imports(async_mode=False))
76
+ if self.abstract:
77
+ return file_import
78
+ for parameter in self.parameters.method:
79
+ file_import.merge(parameter.imports(async_mode=False))
79
80
 
80
81
  file_import.add_submodule_import(
81
82
  "azure.core.rest",
82
83
  "HttpRequest",
83
84
  ImportType.AZURECORE,
84
85
  )
85
- if not self.abstract:
86
- if self.parameters.path:
87
- relative_path = ".."
88
- if (
89
- not self.code_model.options["builders_visibility"] == "embedded"
90
- and self.group_name
91
- ):
92
- relative_path = "..." if self.group_name else ".."
93
- file_import.add_submodule_import(
94
- f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
95
- )
96
- if self.parameters.headers or self.parameters.query:
97
- file_import.add_submodule_import(
98
- "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
99
- )
86
+
87
+ if self.parameters.path:
88
+ relative_path = ".."
89
+ if (
90
+ not self.code_model.options["builders_visibility"] == "embedded"
91
+ and self.group_name
92
+ ):
93
+ relative_path = "..." if self.group_name else ".."
94
+ file_import.add_submodule_import(
95
+ f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
96
+ )
97
+ if self.parameters.headers or self.parameters.query:
98
+ file_import.add_submodule_import(
99
+ "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
100
+ )
100
101
  file_import.add_submodule_import(
101
102
  "typing", "Any", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
102
103
  )
103
- file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY)
104
+ file_import.add_msrest_import(
105
+ self.code_model,
106
+ "..."
107
+ if (
108
+ not self.code_model.options["builders_visibility"] == "embedded"
109
+ and self.group_name
110
+ )
111
+ else "..",
112
+ MsrestImportType.Serializer,
113
+ TypingSection.REGULAR,
114
+ )
104
115
  if (
105
116
  self.overloads
106
117
  and self.code_model.options["builders_visibility"] != "embedded"
@@ -477,6 +477,15 @@ class JinjaSerializer:
477
477
  namespace_path / Path("py.typed"), "# Marker file for PEP 561."
478
478
  )
479
479
 
480
+ if (
481
+ not self.code_model.options["client_side_validation"]
482
+ and not self.code_model.options["multiapi"]
483
+ ):
484
+ self._autorestapi.write_file(
485
+ namespace_path / Path("_serialization.py"),
486
+ general_serializer.serialize_serialization_file(),
487
+ )
488
+
480
489
  # Write the config file
481
490
  if self.code_model.request_builders:
482
491
  self._autorestapi.write_file(
@@ -598,8 +598,6 @@ class _OperationSerializer(
598
598
  def decorators(self, builder: OperationType) -> List[str]:
599
599
  """Decorators for the method"""
600
600
  super_decorators = super().decorators(builder)
601
- if builder.abstract:
602
- super_decorators.append("@abc.abstractmethod")
603
601
  return super_decorators
604
602
 
605
603
  def param_description(
@@ -1126,8 +1124,6 @@ class _PagingOperationSerializer(
1126
1124
  retval: List[str] = []
1127
1125
  if self.code_model.options["tracing"] and builder.want_tracing:
1128
1126
  retval.append("@distributed_trace")
1129
- if builder.abstract:
1130
- retval.append("@abc.abstractmethod")
1131
1127
  return retval
1132
1128
 
1133
1129
  def call_next_link_request_builder(self, builder: PagingOperationType) -> List[str]:
@@ -101,6 +101,14 @@ class ClientSerializer:
101
101
  except StopIteration:
102
102
  return "_endpoint"
103
103
 
104
+ @property
105
+ def should_init_super(self) -> bool:
106
+ return any(
107
+ og
108
+ for og in self.code_model.operation_groups
109
+ if og.is_mixin and og.has_abstract_operations
110
+ )
111
+
104
112
  def initialize_pipeline_client(self, async_mode: bool) -> str:
105
113
  pipeline_client_name = self.code_model.client.pipeline_class(async_mode)
106
114
  return (
@@ -5,6 +5,7 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from jinja2 import Environment
7
7
  from .import_serializer import FileImportSerializer, TypingSection
8
+ from ..models.imports import MsrestImportType
8
9
  from ..models import (
9
10
  FileImport,
10
11
  ImportType,
@@ -73,11 +74,11 @@ class GeneralSerializer:
73
74
  f"{self.code_model.client.name}Configuration",
74
75
  ImportType.LOCAL,
75
76
  )
76
- file_import.add_submodule_import(
77
- "msrest", "Serializer", ImportType.THIRDPARTY, TypingSection.TYPING
78
- )
79
- file_import.add_submodule_import(
80
- "msrest", "Deserializer", ImportType.THIRDPARTY, TypingSection.TYPING
77
+ file_import.add_msrest_import(
78
+ self.code_model,
79
+ ".." if self.async_mode else ".",
80
+ MsrestImportType.SerializerDeserializer,
81
+ TypingSection.TYPING,
81
82
  )
82
83
 
83
84
  return template.render(
@@ -120,3 +121,7 @@ class GeneralSerializer:
120
121
  params.update(self.code_model.options)
121
122
  params.update(self.code_model.package_dependency)
122
123
  return template.render(code_model=self.code_model, **params)
124
+
125
+ def serialize_serialization_file(self) -> str:
126
+ template = self.env.get_template("serialization.py.jinja2")
127
+ return template.render(code_model=self.code_model)
@@ -7,7 +7,7 @@ from abc import abstractmethod
7
7
  from typing import cast, List
8
8
  from jinja2 import Environment
9
9
  from ..models import ModelType, CodeModel, Property
10
- from ..models.imports import FileImport, ImportType
10
+ from ..models.imports import FileImport, TypingSection, MsrestImportType
11
11
  from .import_serializer import FileImportSerializer
12
12
 
13
13
 
@@ -49,7 +49,9 @@ class ModelBaseSerializer:
49
49
 
50
50
  def imports(self) -> FileImport:
51
51
  file_import = FileImport()
52
- file_import.add_import("msrest.serialization", ImportType.AZURECORE)
52
+ file_import.add_msrest_import(
53
+ self.code_model, "..", MsrestImportType.Module, TypingSection.REGULAR
54
+ )
53
55
  for model in self.code_model.model_types:
54
56
  file_import.merge(model.imports(is_operation_file=False))
55
57
  return file_import
@@ -71,9 +73,12 @@ class ModelBaseSerializer:
71
73
  properties_to_initialize = model.properties
72
74
  return properties_to_initialize
73
75
 
74
- @staticmethod
75
- def declare_model(model: ModelType) -> str:
76
- basename = "msrest.serialization.Model"
76
+ def declare_model(self, model: ModelType) -> str:
77
+ basename = (
78
+ "msrest.serialization.Model"
79
+ if self.code_model.options["client_side_validation"]
80
+ else "_serialization.Model"
81
+ )
77
82
  if model.parents:
78
83
  basename = ", ".join([cast(ModelType, m).name for m in model.parents])
79
84
  return f"class {model.name}({basename}):{model.pylint_disable}"
@@ -70,4 +70,7 @@ class OperationGroupsSerializer:
70
70
  async_mode=False,
71
71
  is_python3_file=self.is_python3_file,
72
72
  ),
73
+ request_builders=[
74
+ rb for rb in self.code_model.request_builders if not rb.abstract
75
+ ],
73
76
  )
@@ -46,7 +46,7 @@ class RequestBuildersSerializer:
46
46
 
47
47
  return template.render(
48
48
  code_model=self.code_model,
49
- request_builders=self.request_builders,
49
+ request_builders=[rb for rb in self.request_builders if not rb.abstract],
50
50
  imports=FileImportSerializer(
51
51
  self.imports,
52
52
  is_python3_file=True,
@@ -11,6 +11,9 @@
11
11
 
12
12
  {{ op_tools.serialize_with_wrap(serializer.property_descriptions(async_mode), "\n ") | indent }}
13
13
  {{ serializer.init_signature_and_response_type_annotation(async_mode) | indent }}
14
+ {% if serializer.should_init_super %}
15
+ super().__init__()
16
+ {% endif %}
14
17
  {% if code_model.client.parameters.kwargs_to_pop(async_mode) %}
15
18
  {{ op_tools.serialize(serializer.pop_kwargs_from_signature(async_mode)) | indent(8) }}
16
19
  {% endif %}