@autorest/python 5.17.0 → 6.0.0-rc.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 (56) hide show
  1. package/ChangeLog.md +63 -1
  2. package/README.md +9 -0
  3. package/autorest/codegen/__init__.py +24 -30
  4. package/autorest/codegen/models/base_builder.py +17 -6
  5. package/autorest/codegen/models/base_type.py +6 -0
  6. package/autorest/codegen/models/client.py +9 -6
  7. package/autorest/codegen/models/code_model.py +20 -14
  8. package/autorest/codegen/models/dictionary_type.py +16 -1
  9. package/autorest/codegen/models/imports.py +57 -2
  10. package/autorest/codegen/models/list_type.py +16 -1
  11. package/autorest/codegen/models/lro_operation.py +4 -6
  12. package/autorest/codegen/models/lro_paging_operation.py +3 -9
  13. package/autorest/codegen/models/model_type.py +34 -16
  14. package/autorest/codegen/models/operation.py +47 -79
  15. package/autorest/codegen/models/operation_group.py +10 -9
  16. package/autorest/codegen/models/paging_operation.py +4 -6
  17. package/autorest/codegen/models/parameter.py +3 -7
  18. package/autorest/codegen/models/parameter_list.py +26 -35
  19. package/autorest/codegen/models/property.py +14 -0
  20. package/autorest/codegen/models/request_builder.py +32 -43
  21. package/autorest/codegen/serializers/__init__.py +12 -50
  22. package/autorest/codegen/serializers/builder_serializer.py +136 -49
  23. package/autorest/codegen/serializers/client_serializer.py +23 -32
  24. package/autorest/codegen/serializers/general_serializer.py +12 -12
  25. package/autorest/codegen/serializers/import_serializer.py +11 -22
  26. package/autorest/codegen/serializers/metadata_serializer.py +0 -2
  27. package/autorest/codegen/serializers/{model_base_serializer.py → model_serializer.py} +58 -44
  28. package/autorest/codegen/serializers/operation_groups_serializer.py +3 -7
  29. package/autorest/codegen/serializers/operations_init_serializer.py +2 -23
  30. package/autorest/codegen/serializers/patch_serializer.py +1 -3
  31. package/autorest/codegen/serializers/request_builders_serializer.py +2 -5
  32. package/autorest/codegen/serializers/utils.py +3 -4
  33. package/autorest/codegen/templates/client.py.jinja2 +6 -3
  34. package/autorest/codegen/templates/config.py.jinja2 +2 -2
  35. package/autorest/codegen/templates/metadata.json.jinja2 +4 -4
  36. package/autorest/codegen/templates/model.py.jinja2 +1 -1
  37. package/autorest/codegen/templates/model_init.py.jinja2 +5 -12
  38. package/autorest/codegen/templates/operation_group.py.jinja2 +16 -3
  39. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +2 -8
  40. package/autorest/codegen/templates/operation_tools.jinja2 +3 -1
  41. package/autorest/codegen/templates/patch.py.jinja2 +1 -2
  42. package/autorest/codegen/templates/request_builder.py.jinja2 +0 -7
  43. package/autorest/codegen/templates/request_builders.py.jinja2 +1 -4
  44. package/autorest/codegen/templates/rest_init.py.jinja2 +3 -8
  45. package/autorest/codegen/templates/serialization.py.jinja2 +2006 -0
  46. package/autorest/codegen/templates/setup.py.jinja2 +4 -0
  47. package/autorest/codegen/templates/vendor.py.jinja2 +10 -0
  48. package/autorest/m4reformatter/__init__.py +82 -58
  49. package/autorest/multiapi/models/client.py +12 -2
  50. package/autorest/multiapi/serializers/__init__.py +17 -8
  51. package/autorest/multiapi/serializers/import_serializer.py +4 -8
  52. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  53. package/autorest/preprocess/__init__.py +1 -0
  54. package/package.json +2 -2
  55. package/autorest/codegen/serializers/model_generic_serializer.py +0 -32
  56. package/autorest/codegen/serializers/model_python3_serializer.py +0 -72
@@ -3,7 +3,6 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- import logging
7
6
  from typing import (
8
7
  Any,
9
8
  Callable,
@@ -21,13 +20,11 @@ from .parameter_list import (
21
20
  RequestBuilderParameterList,
22
21
  OverloadedRequestBuilderParameterList,
23
22
  )
24
- from .imports import FileImport, ImportType, TypingSection
25
- from .request_builder_parameter import RequestBuilderMultipartBodyParameter
23
+ from .imports import FileImport, ImportType, TypingSection, MsrestImportType
26
24
 
27
25
  if TYPE_CHECKING:
28
26
  from .code_model import CodeModel
29
27
 
30
- _LOGGER = logging.getLogger(__name__)
31
28
  ParameterListType = TypeVar(
32
29
  "ParameterListType",
33
30
  bound=Union[RequestBuilderParameterList, OverloadedRequestBuilderParameterList],
@@ -43,7 +40,6 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
43
40
  parameters: ParameterListType,
44
41
  *,
45
42
  overloads: Optional[List["RequestBuilder"]] = None,
46
- abstract: bool = False,
47
43
  ) -> None:
48
44
  super().__init__(
49
45
  code_model=code_model,
@@ -51,7 +47,6 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
51
47
  name=name,
52
48
  parameters=parameters,
53
49
  overloads=overloads,
54
- abstract=abstract,
55
50
  want_tracing=False,
56
51
  )
57
52
  self.overloads: List["RequestBuilder"] = overloads or []
@@ -64,7 +59,7 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
64
59
  def response_docstring_text(self, **kwargs) -> str:
65
60
  return (
66
61
  "Returns an :class:`~azure.core.rest.HttpRequest` that you will pass to the client's "
67
- + "`send_request` method. See https://aka.ms/azsdk/python/protocol/quickstart for how to "
62
+ + "`send_request` method. See https://aka.ms/azsdk/dpcodegen/python/send_request for how to "
68
63
  + "incorporate this response into your code flow."
69
64
  )
70
65
 
@@ -73,34 +68,45 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
73
68
 
74
69
  def imports(self) -> FileImport:
75
70
  file_import = FileImport()
76
- if not self.abstract:
77
- for parameter in self.parameters.method:
78
- file_import.merge(parameter.imports(async_mode=False))
71
+ if self.abstract:
72
+ return file_import
73
+ for parameter in self.parameters.method:
74
+ file_import.merge(parameter.imports(async_mode=False))
79
75
 
80
76
  file_import.add_submodule_import(
81
77
  "azure.core.rest",
82
78
  "HttpRequest",
83
79
  ImportType.AZURECORE,
84
80
  )
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
- )
81
+
82
+ if self.parameters.path:
83
+ relative_path = ".."
84
+ if (
85
+ not self.code_model.options["builders_visibility"] == "embedded"
86
+ and self.group_name
87
+ ):
88
+ relative_path = "..." if self.group_name else ".."
89
+ file_import.add_submodule_import(
90
+ f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
91
+ )
92
+ if self.parameters.headers or self.parameters.query:
93
+ file_import.add_submodule_import(
94
+ "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
95
+ )
100
96
  file_import.add_submodule_import(
101
97
  "typing", "Any", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
102
98
  )
103
- file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY)
99
+ file_import.add_msrest_import(
100
+ self.code_model,
101
+ "..."
102
+ if (
103
+ not self.code_model.options["builders_visibility"] == "embedded"
104
+ and self.group_name
105
+ )
106
+ else "..",
107
+ MsrestImportType.Serializer,
108
+ TypingSection.REGULAR,
109
+ )
104
110
  if (
105
111
  self.overloads
106
112
  and self.code_model.options["builders_visibility"] != "embedded"
@@ -136,23 +142,7 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
136
142
  RequestBuilder.from_yaml(rb_yaml_data, code_model)
137
143
  for rb_yaml_data in yaml_data.get("overloads", [])
138
144
  ]
139
- abstract = False
140
145
  parameter_list = cls.parameter_list_type()(yaml_data, code_model)
141
- if (
142
- code_model.options["version_tolerant"]
143
- and parameter_list.has_body
144
- and isinstance(
145
- parameter_list.body_parameter, RequestBuilderMultipartBodyParameter
146
- )
147
- ):
148
- _LOGGER.warning(
149
- 'Not going to generate operation "%s" because it has multipart / urlencoded body parameters. '
150
- "Multipart / urlencoded body parameters are not supported for version tolerant generation right now. "
151
- 'Please write your own custom operation in the "_patch.py" file '
152
- "following https://aka.ms/azsdk/python/dpcodegen/python/customize",
153
- name,
154
- )
155
- abstract = True
156
146
 
157
147
  return cls(
158
148
  yaml_data=yaml_data,
@@ -160,7 +150,6 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
160
150
  name=name,
161
151
  parameters=parameter_list,
162
152
  overloads=overloads,
163
- abstract=abstract,
164
153
  )
165
154
 
166
155
 
@@ -14,9 +14,8 @@ from ..models import CodeModel, OperationGroup, RequestBuilder
14
14
  from ..models import TokenCredentialType
15
15
  from .enum_serializer import EnumSerializer
16
16
  from .general_serializer import GeneralSerializer
17
- from .model_generic_serializer import ModelGenericSerializer
18
17
  from .model_init_serializer import ModelInitSerializer
19
- from .model_python3_serializer import ModelPython3Serializer
18
+ from .model_serializer import ModelSerializer
20
19
  from .operations_init_serializer import OperationsInitSerializer
21
20
  from .operation_groups_serializer import OperationGroupsSerializer
22
21
  from .metadata_serializer import MetadataSerializer
@@ -224,22 +223,9 @@ class JinjaSerializer:
224
223
  # Write the models folder
225
224
  models_path = namespace_path / Path("models")
226
225
  if self.code_model.model_types:
227
- if not self.code_model.options["python3_only"]:
228
- self._autorestapi.write_file(
229
- models_path
230
- / Path(
231
- f"{self.code_model.get_models_filename(is_python3_file=False)}.py"
232
- ),
233
- ModelGenericSerializer(
234
- code_model=self.code_model, env=env
235
- ).serialize(),
236
- )
237
226
  self._autorestapi.write_file(
238
- models_path
239
- / Path(
240
- f"{self.code_model.get_models_filename(is_python3_file=True)}.py"
241
- ),
242
- ModelPython3Serializer(code_model=self.code_model, env=env).serialize(),
227
+ models_path / Path(f"{self.code_model.models_filename}.py"),
228
+ ModelSerializer(code_model=self.code_model, env=env).serialize(),
243
229
  )
244
230
  if self.code_model.enums:
245
231
  self._autorestapi.write_file(
@@ -287,18 +273,6 @@ class JinjaSerializer:
287
273
  code_model=self.code_model,
288
274
  env=env,
289
275
  request_builders=request_builders,
290
- is_python3_file=False,
291
- ).serialize_request_builders(),
292
- )
293
-
294
- # write python3 request builders file
295
- self._autorestapi.write_file(
296
- output_path / Path("_request_builders_py3.py"),
297
- RequestBuildersSerializer(
298
- code_model=self.code_model,
299
- env=env,
300
- request_builders=request_builders,
301
- is_python3_file=True,
302
276
  ).serialize_request_builders(),
303
277
  )
304
278
 
@@ -309,7 +283,6 @@ class JinjaSerializer:
309
283
  code_model=self.code_model,
310
284
  env=env,
311
285
  request_builders=request_builders,
312
- is_python3_file=True,
313
286
  ).serialize_init(),
314
287
  )
315
288
 
@@ -325,7 +298,6 @@ class JinjaSerializer:
325
298
  code_model=self.code_model,
326
299
  env=env,
327
300
  async_mode=False,
328
- is_python3_file=self.code_model.options["python3_only"],
329
301
  operation_group=operation_group,
330
302
  )
331
303
  self._autorestapi.write_file(
@@ -335,31 +307,12 @@ class JinjaSerializer:
335
307
  operation_group_serializer.serialize(),
336
308
  )
337
309
 
338
- if (
339
- not self.code_model.options["python3_only"]
340
- and self.code_model.options["add_python3_operation_files"]
341
- ):
342
- # write typed second file if not python 3 only
343
- operation_group_serializer = OperationGroupsSerializer(
344
- code_model=self.code_model,
345
- env=env,
346
- async_mode=False,
347
- is_python3_file=True,
348
- )
349
- self._autorestapi.write_file(
350
- namespace_path
351
- / Path(self.code_model.operations_folder_name)
352
- / Path(f"{filename}_py3.py"),
353
- operation_group_serializer.serialize(),
354
- )
355
-
356
310
  if self.has_aio_folder:
357
311
  # write async operation group and operation files
358
312
  operation_group_async_serializer = OperationGroupsSerializer(
359
313
  code_model=self.code_model,
360
314
  env=env,
361
315
  async_mode=True,
362
- is_python3_file=True,
363
316
  operation_group=operation_group,
364
317
  )
365
318
  self._autorestapi.write_file(
@@ -477,6 +430,15 @@ class JinjaSerializer:
477
430
  namespace_path / Path("py.typed"), "# Marker file for PEP 561."
478
431
  )
479
432
 
433
+ if (
434
+ not self.code_model.options["client_side_validation"]
435
+ and not self.code_model.options["multiapi"]
436
+ ):
437
+ self._autorestapi.write_file(
438
+ namespace_path / Path("_serialization.py"),
439
+ general_serializer.serialize_serialization_file(),
440
+ )
441
+
480
442
  # Write the config file
481
443
  if self.code_model.request_builders:
482
444
  self._autorestapi.write_file(
@@ -30,6 +30,7 @@ from ..models import (
30
30
  OverloadedRequestBuilder,
31
31
  ConstantType,
32
32
  MultipartBodyParameter,
33
+ Property,
33
34
  RequestBuilderType,
34
35
  )
35
36
  from .parameter_serializer import ParameterSerializer, PopKwargType
@@ -83,6 +84,37 @@ def _json_dumps_template(template_representation: Any) -> Any:
83
84
  )
84
85
 
85
86
 
87
+ def _get_polymorphic_subtype_template(polymorphic_subtype: ModelType) -> List[str]:
88
+ retval: List[str] = []
89
+ retval.append("")
90
+ retval.append(
91
+ f'# JSON input template for discriminator value "{polymorphic_subtype.discriminator_value}":'
92
+ )
93
+ subtype_template = _json_dumps_template(
94
+ polymorphic_subtype.get_json_template_representation(),
95
+ )
96
+
97
+ def _get_polymorphic_parent(
98
+ polymorphic_subtype: Optional[ModelType],
99
+ ) -> Optional[ModelType]:
100
+ if not polymorphic_subtype:
101
+ return None
102
+ try:
103
+ return next(
104
+ p for p in polymorphic_subtype.parents if p.discriminated_subtypes
105
+ )
106
+ except StopIteration:
107
+ return None
108
+
109
+ polymorphic_parent = _get_polymorphic_parent(polymorphic_subtype)
110
+ while _get_polymorphic_parent(polymorphic_parent):
111
+ polymorphic_parent = _get_polymorphic_parent(polymorphic_parent)
112
+ retval.extend(
113
+ f"{cast(ModelType, polymorphic_parent).snake_case_name} = {subtype_template}".splitlines()
114
+ )
115
+ return retval
116
+
117
+
86
118
  def _serialize_grouped_body(builder: BuilderType) -> List[str]:
87
119
  retval: List[str] = []
88
120
  for grouped_parameter in builder.parameters.grouped:
@@ -144,12 +176,9 @@ def _get_json_response_template_to_status_codes(
144
176
 
145
177
 
146
178
  class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-method
147
- def __init__(
148
- self, code_model: CodeModel, async_mode: bool, is_python3_file: bool
149
- ) -> None:
179
+ def __init__(self, code_model: CodeModel, async_mode: bool) -> None:
150
180
  self.code_model = code_model
151
181
  self.async_mode = async_mode
152
- self.is_python3_file = is_python3_file
153
182
  self.parameter_serializer = ParameterSerializer()
154
183
 
155
184
  @property
@@ -193,9 +222,7 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
193
222
  function_def=self._function_def,
194
223
  method_name=builder.name,
195
224
  need_self_param=self._need_self_param,
196
- method_param_signatures=builder.method_signature(
197
- self.async_mode or self.is_python3_file, self.async_mode
198
- ),
225
+ method_param_signatures=builder.method_signature(self.async_mode),
199
226
  pylint_disable=builder.pylint_disable,
200
227
  )
201
228
 
@@ -213,7 +240,6 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
213
240
  return (
214
241
  decorators_str
215
242
  + utils.method_signature_and_response_type_annotation_template(
216
- is_python3_file=self.is_python3_file,
217
243
  method_signature=method_signature,
218
244
  response_type_annotation=response_type_annotation,
219
245
  )
@@ -268,6 +294,11 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
268
294
  return []
269
295
  return self.param_description(builder) + self.response_docstring(builder)
270
296
 
297
+ @property
298
+ @abstractmethod
299
+ def _json_response_template_name(self) -> str:
300
+ ...
301
+
271
302
  def _json_input_example_template(self, builder: BuilderType) -> List[str]:
272
303
  template: List[str] = []
273
304
  if self.code_model.options["models_mode"]:
@@ -287,14 +318,26 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
287
318
  if not isinstance(body_param.type, (ListType, DictionaryType, ModelType)):
288
319
  return template
289
320
 
290
- if isinstance(body_param.type, ModelType) and body_param.type.discriminator:
291
- discriminator_name = body_param.type.discriminator.client_name
292
- discriminator_values = body_param.type.discriminated_subtypes.keys()
321
+ polymorphic_subtypes: List[ModelType] = []
322
+ body_param.type.get_polymorphic_subtypes(polymorphic_subtypes)
323
+ if polymorphic_subtypes:
324
+ # we just assume one kind of polymorphic body for input
325
+ discriminator_name = cast(
326
+ Property, polymorphic_subtypes[0].discriminator
327
+ ).rest_api_name
293
328
  template.append(
294
- "{} = '{}'".format(
295
- discriminator_name, "' or '".join(discriminator_values)
296
- )
329
+ "# The input is polymorphic. The following are possible polymorphic "
330
+ f'inputs based off discriminator "{discriminator_name}":'
297
331
  )
332
+ for idx in range(
333
+ min(
334
+ self.code_model.options["polymorphic_examples"],
335
+ len(polymorphic_subtypes),
336
+ )
337
+ ):
338
+ template.extend(
339
+ _get_polymorphic_subtype_template(polymorphic_subtypes[idx])
340
+ )
298
341
  template.append("")
299
342
  template.append(
300
343
  "# JSON input template you can fill out and use as your body input."
@@ -337,7 +380,7 @@ class RequestBuilderSerializer(
337
380
  def description_and_summary(self, builder: RequestBuilderType) -> List[str]:
338
381
  retval = super().description_and_summary(builder)
339
382
  retval += [
340
- "See https://aka.ms/azsdk/python/protocol/quickstart for how to incorporate this "
383
+ "See https://aka.ms/azsdk/dpcodegen/python/send_request for how to incorporate this "
341
384
  "request builder into your code flow.",
342
385
  "",
343
386
  ]
@@ -351,6 +394,10 @@ class RequestBuilderSerializer(
351
394
  def serializer_name(self) -> str:
352
395
  return "_SERIALIZER"
353
396
 
397
+ @property
398
+ def _json_response_template_name(self) -> str:
399
+ return "response.json()"
400
+
354
401
  @staticmethod
355
402
  def declare_non_inputtable_constants(builder: RequestBuilderType) -> List[str]:
356
403
  def _get_value(param):
@@ -381,7 +428,7 @@ class RequestBuilderSerializer(
381
428
  def response_docstring(self, builder: RequestBuilderType) -> List[str]:
382
429
  response_str = (
383
430
  f":return: Returns an :class:`~azure.core.rest.HttpRequest` that you will pass to the client's "
384
- + "`send_request` method. See https://aka.ms/azsdk/python/protocol/quickstart for how to "
431
+ + "`send_request` method. See https://aka.ms/azsdk/dpcodegen/python/send_request for how to "
385
432
  + "incorporate this response into your code flow."
386
433
  )
387
434
  rtype_str = f":rtype: ~azure.core.rest.HttpRequest"
@@ -389,7 +436,7 @@ class RequestBuilderSerializer(
389
436
 
390
437
  def pop_kwargs_from_signature(self, builder: RequestBuilderType) -> List[str]:
391
438
  return self.parameter_serializer.pop_kwargs_from_signature(
392
- builder.parameters.kwargs_to_pop(is_python3_file=self.is_python3_file),
439
+ builder.parameters.kwargs_to_pop,
393
440
  check_kwarg_dict=True,
394
441
  pop_headers_kwarg=PopKwargType.CASE_INSENSITIVE
395
442
  if bool(builder.parameters.headers)
@@ -399,7 +446,8 @@ class RequestBuilderSerializer(
399
446
  else PopKwargType.NO,
400
447
  )
401
448
 
402
- def create_http_request(self, builder: RequestBuilderType) -> List[str]:
449
+ @staticmethod
450
+ def create_http_request(builder: RequestBuilderType) -> List[str]:
403
451
  retval = ["return HttpRequest("]
404
452
  retval.append(f' method="{builder.method}",')
405
453
  retval.append(" url=_url,")
@@ -412,9 +460,9 @@ class RequestBuilderSerializer(
412
460
  and builder.parameters.body_parameter.in_method_signature
413
461
  ):
414
462
  body_param = builder.parameters.body_parameter
415
- if body_param.constant or (
416
- self.is_python3_file
417
- and body_param.method_location != ParameterMethodLocation.KWARG
463
+ if (
464
+ body_param.constant
465
+ or body_param.method_location != ParameterMethodLocation.KWARG
418
466
  ):
419
467
  # we only need to pass it through if it's not a kwarg or it's a popped kwarg
420
468
  retval.append(
@@ -473,10 +521,38 @@ class _OperationSerializer(
473
521
  retval.append("")
474
522
  return retval
475
523
 
524
+ @property
525
+ def _json_response_template_name(self) -> str:
526
+ return "response"
527
+
476
528
  def example_template(self, builder: OperationType) -> List[str]:
477
529
  retval = super().example_template(builder)
478
530
  if self.code_model.options["models_mode"]:
479
531
  return retval
532
+ for response in builder.responses:
533
+ polymorphic_subtypes: List[ModelType] = []
534
+ if not response.type:
535
+ continue
536
+ response.type.get_polymorphic_subtypes(polymorphic_subtypes)
537
+ if polymorphic_subtypes:
538
+ # we just assume one kind of polymorphic body for input
539
+ discriminator_name = cast(
540
+ Property, polymorphic_subtypes[0].discriminator
541
+ ).rest_api_name
542
+ retval.append(
543
+ "# The response is polymorphic. The following are possible polymorphic "
544
+ f'responses based off discriminator "{discriminator_name}":'
545
+ )
546
+ for idx in range(
547
+ min(
548
+ self.code_model.options["polymorphic_examples"],
549
+ len(polymorphic_subtypes),
550
+ )
551
+ ):
552
+ retval.extend(
553
+ _get_polymorphic_subtype_template(polymorphic_subtypes[idx])
554
+ )
555
+
480
556
  if _get_json_response_template_to_status_codes(builder):
481
557
  retval.append("")
482
558
  for (
@@ -488,7 +564,9 @@ class _OperationSerializer(
488
564
  ", ".join(status_codes)
489
565
  )
490
566
  )
491
- retval.extend(f"response.json() == {response_body}".splitlines())
567
+ retval.extend(
568
+ f"{self._json_response_template_name} == {response_body}".splitlines()
569
+ )
492
570
  return retval
493
571
 
494
572
  def make_pipeline_call(self, builder: OperationType) -> List[str]:
@@ -515,8 +593,6 @@ class _OperationSerializer(
515
593
  def decorators(self, builder: OperationType) -> List[str]:
516
594
  """Decorators for the method"""
517
595
  super_decorators = super().decorators(builder)
518
- if builder.abstract:
519
- super_decorators.append("@abc.abstractmethod")
520
596
  return super_decorators
521
597
 
522
598
  def param_description(
@@ -530,9 +606,7 @@ class _OperationSerializer(
530
606
  return description_list
531
607
 
532
608
  def pop_kwargs_from_signature(self, builder: OperationType) -> List[str]:
533
- kwargs_to_pop = builder.parameters.kwargs_to_pop(
534
- is_python3_file=self.is_python3_file
535
- )
609
+ kwargs_to_pop = builder.parameters.kwargs_to_pop
536
610
  kwargs = self.parameter_serializer.pop_kwargs_from_signature(
537
611
  kwargs_to_pop,
538
612
  check_kwarg_dict=True,
@@ -616,6 +690,20 @@ class _OperationSerializer(
616
690
  body_kwarg_name = builder.request_builder.parameters.body_parameter.client_name
617
691
  if isinstance(body_param.type, BinaryType):
618
692
  retval.append(f"_{body_kwarg_name} = {body_param.client_name}")
693
+ if (
694
+ not body_param.default_content_type
695
+ and not next(
696
+ p for p in builder.parameters if p.rest_api_name == "Content-Type"
697
+ ).optional
698
+ ):
699
+ content_types = "'" + "', '".join(body_param.content_types) + "'"
700
+ retval.extend(
701
+ [
702
+ "if not content_type:",
703
+ f' raise TypeError("Missing required keyword-only argument: content_type. '
704
+ f'Known values are:" + "{content_types}")',
705
+ ]
706
+ )
619
707
  else:
620
708
  retval.extend(self._serialize_body_parameter(builder))
621
709
  return retval
@@ -727,7 +815,6 @@ class _OperationSerializer(
727
815
  is_next_request
728
816
  and builder.operation_type == "paging"
729
817
  and not bool(builder.next_request_builder) # type: ignore
730
- and not self.code_model.options["reformat_next_link"]
731
818
  and parameter.location == ParameterLocation.QUERY
732
819
  ):
733
820
  # if we don't want to reformat query parameters for next link calls
@@ -738,10 +825,15 @@ class _OperationSerializer(
738
825
  f" {parameter.client_name}={parameter.name_in_high_level_operation},"
739
826
  )
740
827
  if request_builder.overloads:
828
+ seen_body_params = set()
741
829
  for overload in request_builder.overloads:
742
830
  body_param = cast(
743
831
  RequestBuilderBodyParameter, overload.parameters.body_parameter
744
832
  )
833
+ if body_param.client_name in seen_body_params:
834
+ continue
835
+ seen_body_params.add(body_param.client_name)
836
+
745
837
  retval.append(
746
838
  f" {body_param.client_name}={body_param.name_in_high_level_operation},"
747
839
  )
@@ -1008,15 +1100,12 @@ PagingOperationType = TypeVar(
1008
1100
  class _PagingOperationSerializer(
1009
1101
  _OperationSerializer[PagingOperationType]
1010
1102
  ): # pylint: disable=abstract-method
1011
- def __init__(
1012
- self, code_model: CodeModel, async_mode: bool, is_python3_file: bool
1013
- ) -> None:
1103
+ def __init__(self, code_model: CodeModel, async_mode: bool) -> None:
1014
1104
  # for pylint reasons need to redefine init
1015
1105
  # probably because inheritance is going too deep
1016
- super().__init__(code_model, async_mode, is_python3_file)
1106
+ super().__init__(code_model, async_mode)
1017
1107
  self.code_model = code_model
1018
1108
  self.async_mode = async_mode
1019
- self.is_python3_file = is_python3_file
1020
1109
  self.parameter_serializer = ParameterSerializer()
1021
1110
 
1022
1111
  def serialize_path(self, builder: PagingOperationType) -> List[str]:
@@ -1029,8 +1118,6 @@ class _PagingOperationSerializer(
1029
1118
  retval: List[str] = []
1030
1119
  if self.code_model.options["tracing"] and builder.want_tracing:
1031
1120
  retval.append("@distributed_trace")
1032
- if builder.abstract:
1033
- retval.append("@abc.abstractmethod")
1034
1121
  return retval
1035
1122
 
1036
1123
  def call_next_link_request_builder(self, builder: PagingOperationType) -> List[str]:
@@ -1046,9 +1133,16 @@ class _PagingOperationSerializer(
1046
1133
  template_url = "next_link"
1047
1134
 
1048
1135
  request_builder = builder.next_request_builder or builder.request_builder
1049
- return self._call_request_builder_helper(
1050
- builder, request_builder, template_url=template_url, is_next_request=True
1051
- )
1136
+ if builder.next_request_builder or self.code_model.is_legacy:
1137
+ return self._call_request_builder_helper(
1138
+ builder,
1139
+ request_builder,
1140
+ template_url=template_url,
1141
+ is_next_request=True,
1142
+ )
1143
+ retval = ['request = HttpRequest("GET", next_link)']
1144
+ retval.extend(self._postprocess_http_request(builder, "request.url"))
1145
+ return retval
1052
1146
 
1053
1147
  def _prepare_request_callback(self, builder: PagingOperationType) -> List[str]:
1054
1148
  retval = ["def prepare_request(next_link=None):"]
@@ -1061,10 +1155,7 @@ class _PagingOperationSerializer(
1061
1155
  retval.extend(
1062
1156
  [f" {line}" for line in self.call_next_link_request_builder(builder)]
1063
1157
  )
1064
- if not builder.next_request_builder and builder.parameters.path:
1065
- retval.append("")
1066
- retval.extend([f" {line}" for line in self.serialize_path(builder)])
1067
- if not builder.next_request_builder:
1158
+ if not builder.next_request_builder and self.code_model.is_legacy:
1068
1159
  retval.append(' request.method = "GET"')
1069
1160
  else:
1070
1161
  retval.append("")
@@ -1142,15 +1233,12 @@ LROOperationType = TypeVar(
1142
1233
 
1143
1234
 
1144
1235
  class _LROOperationSerializer(_OperationSerializer[LROOperationType]):
1145
- def __init__(
1146
- self, code_model: CodeModel, async_mode: bool, is_python3_file: bool
1147
- ) -> None:
1236
+ def __init__(self, code_model: CodeModel, async_mode: bool) -> None:
1148
1237
  # for pylint reasons need to redefine init
1149
1238
  # probably because inheritance is going too deep
1150
- super().__init__(code_model, async_mode, is_python3_file)
1239
+ super().__init__(code_model, async_mode)
1151
1240
  self.code_model = code_model
1152
1241
  self.async_mode = async_mode
1153
- self.is_python3_file = is_python3_file
1154
1242
  self.parameter_serializer = ParameterSerializer()
1155
1243
 
1156
1244
  def param_description(self, builder: LROOperationType) -> List[str]:
@@ -1330,7 +1418,6 @@ def get_operation_serializer(
1330
1418
  builder: Operation,
1331
1419
  code_model,
1332
1420
  async_mode: bool,
1333
- is_python3_file: bool,
1334
1421
  ) -> Union[
1335
1422
  OperationSerializer,
1336
1423
  PagingOperationSerializer,
@@ -1349,4 +1436,4 @@ def get_operation_serializer(
1349
1436
  retcls = LROOperationSerializer
1350
1437
  elif builder.operation_type == "paging":
1351
1438
  retcls = PagingOperationSerializer
1352
- return retcls(code_model, async_mode, is_python3_file)
1439
+ return retcls(code_model, async_mode)