@autorest/python 5.19.0 → 6.0.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 (52) hide show
  1. package/ChangeLog.md +61 -2
  2. package/README.md +9 -0
  3. package/autorest/__init__.py +54 -13
  4. package/autorest/black/__init__.py +14 -8
  5. package/autorest/codegen/__init__.py +126 -89
  6. package/autorest/codegen/models/base_builder.py +17 -6
  7. package/autorest/codegen/models/client.py +1 -1
  8. package/autorest/codegen/models/code_model.py +7 -12
  9. package/autorest/codegen/models/lro_operation.py +2 -6
  10. package/autorest/codegen/models/lro_paging_operation.py +3 -9
  11. package/autorest/codegen/models/model_type.py +1 -6
  12. package/autorest/codegen/models/operation.py +6 -37
  13. package/autorest/codegen/models/operation_group.py +4 -7
  14. package/autorest/codegen/models/paging_operation.py +17 -7
  15. package/autorest/codegen/models/parameter.py +3 -7
  16. package/autorest/codegen/models/parameter_list.py +20 -36
  17. package/autorest/codegen/models/request_builder.py +0 -22
  18. package/autorest/codegen/serializers/__init__.py +46 -98
  19. package/autorest/codegen/serializers/builder_serializer.py +53 -36
  20. package/autorest/codegen/serializers/client_serializer.py +20 -31
  21. package/autorest/codegen/serializers/general_serializer.py +2 -7
  22. package/autorest/codegen/serializers/import_serializer.py +11 -22
  23. package/autorest/codegen/serializers/metadata_serializer.py +0 -2
  24. package/autorest/codegen/serializers/{model_base_serializer.py → model_serializer.py} +47 -38
  25. package/autorest/codegen/serializers/operation_groups_serializer.py +0 -7
  26. package/autorest/codegen/serializers/operations_init_serializer.py +2 -23
  27. package/autorest/codegen/serializers/patch_serializer.py +1 -3
  28. package/autorest/codegen/serializers/request_builders_serializer.py +1 -4
  29. package/autorest/codegen/serializers/utils.py +1 -4
  30. package/autorest/codegen/templates/client.py.jinja2 +3 -3
  31. package/autorest/codegen/templates/config.py.jinja2 +2 -2
  32. package/autorest/codegen/templates/metadata.json.jinja2 +4 -4
  33. package/autorest/codegen/templates/model_init.py.jinja2 +5 -12
  34. package/autorest/codegen/templates/operation_group.py.jinja2 +1 -1
  35. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +0 -6
  36. package/autorest/codegen/templates/patch.py.jinja2 +1 -2
  37. package/autorest/codegen/templates/request_builders.py.jinja2 +0 -3
  38. package/autorest/codegen/templates/rest_init.py.jinja2 +3 -8
  39. package/autorest/codegen/templates/serialization.py.jinja2 +3 -3
  40. package/autorest/codegen/templates/setup.py.jinja2 +1 -1
  41. package/autorest/jsonrpc/server.py +7 -7
  42. package/autorest/m2r/__init__.py +7 -2
  43. package/autorest/m4reformatter/__init__.py +13 -5
  44. package/autorest/multiapi/__init__.py +56 -29
  45. package/autorest/multiapi/serializers/__init__.py +26 -31
  46. package/autorest/multiapi/serializers/import_serializer.py +4 -8
  47. package/autorest/multiapi/serializers/multiapi_serializer.py +33 -26
  48. package/autorest/postprocess/__init__.py +14 -11
  49. package/autorest/preprocess/__init__.py +36 -7
  50. package/package.json +2 -2
  51. package/autorest/codegen/serializers/model_generic_serializer.py +0 -32
  52. package/autorest/codegen/serializers/model_python3_serializer.py +0 -72
@@ -33,7 +33,6 @@ class LROOperationBase(OperationBase[LROResponseType]):
33
33
  overloads: Optional[List[Operation]] = None,
34
34
  public: bool = True,
35
35
  want_tracing: bool = True,
36
- abstract: bool = False,
37
36
  ) -> None:
38
37
  super().__init__(
39
38
  code_model=code_model,
@@ -46,7 +45,6 @@ class LROOperationBase(OperationBase[LROResponseType]):
46
45
  overloads=overloads,
47
46
  public=public,
48
47
  want_tracing=want_tracing,
49
- abstract=abstract,
50
48
  )
51
49
  self.name = "begin_" + self.name
52
50
  self.lro_options: Dict[str, Any] = self.yaml_data.get("lroOptions", {})
@@ -120,10 +118,8 @@ class LROOperationBase(OperationBase[LROResponseType]):
120
118
  def get_no_polling_method(self, async_mode: bool) -> str:
121
119
  return self.responses[0].get_no_polling_method(async_mode)
122
120
 
123
- def imports(
124
- self, async_mode: bool, is_python3_file: bool, **kwargs: Any
125
- ) -> FileImport:
126
- file_import = super().imports(async_mode, is_python3_file, **kwargs)
121
+ def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
122
+ file_import = super().imports(async_mode, **kwargs)
127
123
  if self.abstract:
128
124
  return file_import
129
125
  if async_mode:
@@ -25,15 +25,9 @@ class LROPagingOperation(
25
25
  def cls_type_annotation(self, *, async_mode: bool) -> str:
26
26
  return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode)}]" # pylint: disable=no-member
27
27
 
28
- def imports(
29
- self, async_mode: bool, is_python3_file: bool, **kwargs: Any
30
- ) -> FileImport:
31
- lro_imports = LROOperationBase.imports(
32
- self, async_mode, is_python3_file, **kwargs
33
- )
34
- paging_imports = PagingOperationBase.imports(
35
- self, async_mode, is_python3_file, **kwargs
36
- )
28
+ def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
29
+ lro_imports = LROOperationBase.imports(self, async_mode, **kwargs)
30
+ paging_imports = PagingOperationBase.imports(self, async_mode, **kwargs)
37
31
 
38
32
  file_import = lro_imports
39
33
  file_import.merge(paging_imports)
@@ -238,13 +238,8 @@ class ModelType(BaseType): # pylint: disable=too-many-instance-attributes
238
238
  relative_path, "models", ImportType.LOCAL, alias="_models"
239
239
  )
240
240
  else:
241
- # a little hacky, but we only do this for version tolerant
242
- # models files, which are all python3 only
243
- models_filename = self.code_model.get_models_filename(
244
- is_python3_file=True
245
- )
246
241
  file_import.add_submodule_import(
247
- f"{relative_path}models.{models_filename}",
242
+ f"{relative_path}models.{self.code_model.models_filename}",
248
243
  self.name,
249
244
  ImportType.LOCAL,
250
245
  )
@@ -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 itertools import chain
8
7
  from typing import (
9
8
  Dict,
@@ -43,8 +42,6 @@ from .request_builder import OverloadedRequestBuilder, RequestBuilder
43
42
  if TYPE_CHECKING:
44
43
  from .code_model import CodeModel
45
44
 
46
- _LOGGER = logging.getLogger(__name__)
47
-
48
45
  ResponseType = TypeVar(
49
46
  "ResponseType",
50
47
  bound=Union[Response, PagingResponse, LROResponse, LROPagingResponse],
@@ -67,7 +64,6 @@ class OperationBase( # pylint: disable=too-many-public-methods
67
64
  overloads: Optional[List["Operation"]] = None,
68
65
  public: bool = True,
69
66
  want_tracing: bool = True,
70
- abstract: bool = False,
71
67
  ) -> None:
72
68
  super().__init__(
73
69
  code_model=code_model,
@@ -75,7 +71,6 @@ class OperationBase( # pylint: disable=too-many-public-methods
75
71
  name=name,
76
72
  parameters=parameters,
77
73
  overloads=overloads,
78
- abstract=abstract,
79
74
  want_tracing=want_tracing,
80
75
  )
81
76
  self.overloads: List["Operation"] = overloads or []
@@ -274,22 +269,14 @@ class OperationBase( # pylint: disable=too-many-public-methods
274
269
  alias="rest",
275
270
  )
276
271
  if self.code_model.options["builders_visibility"] == "embedded" and async_mode:
277
- suffix = (
278
- "_py3"
279
- if self.code_model.options["add_python3_operation_files"]
280
- and not self.code_model.options["python3_only"]
281
- else ""
282
- )
283
272
  file_import.add_submodule_import(
284
- f"...{self.code_model.operations_folder_name}.{self.filename}{suffix}",
273
+ f"...{self.code_model.operations_folder_name}.{self.filename}",
285
274
  request_builder.name,
286
275
  import_type=ImportType.LOCAL,
287
276
  )
288
277
  return file_import
289
278
 
290
- def imports(
291
- self, async_mode: bool, is_python3_file: bool, **kwargs: Any
292
- ) -> FileImport:
279
+ def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
293
280
  if self.abstract:
294
281
  return FileImport()
295
282
  file_import = self._imports_shared(async_mode, **kwargs)
@@ -326,11 +313,10 @@ class OperationBase( # pylint: disable=too-many-public-methods
326
313
  "azure.core.exceptions", "ResourceExistsError", ImportType.AZURECORE
327
314
  )
328
315
 
329
- kwargs_to_pop = self.parameters.kwargs_to_pop(is_python3_file)
330
316
  if self.has_kwargs_to_pop_with_default(
331
- kwargs_to_pop, ParameterLocation.HEADER
317
+ self.parameters.kwargs_to_pop, ParameterLocation.HEADER
332
318
  ) or self.has_kwargs_to_pop_with_default(
333
- kwargs_to_pop, ParameterLocation.QUERY
319
+ self.parameters.kwargs_to_pop, ParameterLocation.QUERY
334
320
  ):
335
321
  file_import.add_submodule_import(
336
322
  "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
@@ -438,20 +424,6 @@ class OperationBase( # pylint: disable=too-many-public-methods
438
424
  cls.from_yaml(overload, code_model)
439
425
  for overload in yaml_data.get("overloads", [])
440
426
  ]
441
- abstract = False
442
- if (
443
- code_model.options["version_tolerant"]
444
- and parameter_list.has_body
445
- and isinstance(parameter_list.body_parameter, MultipartBodyParameter)
446
- ):
447
- _LOGGER.warning(
448
- 'Not going to generate operation "%s" because it has multipart / urlencoded body parameters. '
449
- "Multipart / urlencoded body parameters are not supported for version tolerant generation right now. "
450
- 'Please write your own custom operation in the "_patch.py" file '
451
- "following https://aka.ms/azsdk/python/dpcodegen/python/customize",
452
- name,
453
- )
454
- abstract = True
455
427
 
456
428
  return cls(
457
429
  yaml_data=yaml_data,
@@ -463,15 +435,12 @@ class OperationBase( # pylint: disable=too-many-public-methods
463
435
  responses=responses,
464
436
  exceptions=exceptions,
465
437
  want_tracing=not yaml_data["isOverload"],
466
- abstract=abstract,
467
438
  )
468
439
 
469
440
 
470
441
  class Operation(OperationBase[Response]):
471
- def imports(
472
- self, async_mode: bool, is_python3_file: bool, **kwargs: Any
473
- ) -> FileImport:
474
- file_import = super().imports(async_mode, is_python3_file, **kwargs)
442
+ def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
443
+ file_import = super().imports(async_mode, **kwargs)
475
444
  if self.abstract:
476
445
  return file_import
477
446
  if async_mode:
@@ -36,12 +36,11 @@ class OperationGroup(BaseModel):
36
36
  def has_abstract_operations(self) -> bool:
37
37
  return any(o for o in self.operations if o.abstract)
38
38
 
39
- def base_class(self, async_mode: bool) -> str:
39
+ @property
40
+ def base_class(self) -> str:
40
41
  base_classes: List[str] = []
41
42
  if self.is_mixin and self.code_model.need_mixin_abc:
42
43
  base_classes.append("MixinABC")
43
- if not (async_mode or self.code_model.options["python3_only"]):
44
- base_classes.append("object")
45
44
  return ", ".join(base_classes)
46
45
 
47
46
  def imports_for_multiapi(self, async_mode: bool) -> FileImport:
@@ -67,15 +66,13 @@ class OperationGroup(BaseModel):
67
66
  return " # type: ignore"
68
67
  return ""
69
68
 
70
- def imports(self, async_mode: bool, is_python3_file: bool) -> FileImport:
69
+ def imports(self, async_mode: bool) -> FileImport:
71
70
  file_import = FileImport()
72
71
 
73
72
  relative_path = "..." if async_mode else ".."
74
73
  for operation in self.operations:
75
74
  file_import.merge(
76
- operation.imports(
77
- async_mode, is_python3_file, relative_path=relative_path
78
- )
75
+ operation.imports(async_mode, relative_path=relative_path)
79
76
  )
80
77
  # for multiapi
81
78
  if not self.code_model.options["version_tolerant"]:
@@ -38,7 +38,6 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
38
38
  overloads: Optional[List[Operation]] = None,
39
39
  public: bool = True,
40
40
  want_tracing: bool = True,
41
- abstract: bool = False,
42
41
  override_success_response_to_200: bool = False,
43
42
  ) -> None:
44
43
  super().__init__(
@@ -52,7 +51,6 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
52
51
  overloads=overloads,
53
52
  public=public,
54
53
  want_tracing=want_tracing,
55
- abstract=abstract,
56
54
  )
57
55
  self.next_request_builder: Optional[
58
56
  Union[RequestBuilder, OverloadedRequestBuilder]
@@ -127,13 +125,11 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
127
125
  def has_optional_return_type(self) -> bool:
128
126
  return False
129
127
 
130
- def imports(
131
- self, async_mode: bool, is_python3_file: bool, **kwargs: Any
132
- ) -> FileImport:
128
+ def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
133
129
  if self.abstract:
134
130
  return FileImport()
135
131
  file_import = self._imports_shared(async_mode, **kwargs)
136
- file_import.merge(super().imports(async_mode, is_python3_file, **kwargs))
132
+ file_import.merge(super().imports(async_mode, **kwargs))
137
133
  if self.code_model.options["tracing"] and self.want_tracing:
138
134
  file_import.add_submodule_import(
139
135
  "azure.core.tracing.decorator",
@@ -144,7 +140,21 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
144
140
  file_import.merge(
145
141
  self.get_request_builder_import(self.next_request_builder, async_mode)
146
142
  )
147
-
143
+ elif "api-version" in [
144
+ p.rest_api_name for p in self.code_model.client.parameters
145
+ ]:
146
+ file_import.add_submodule_import(
147
+ "urllib.parse", "urlparse", ImportType.STDLIB
148
+ )
149
+ file_import.add_submodule_import(
150
+ "urllib.parse", "urljoin", ImportType.STDLIB
151
+ )
152
+ file_import.add_submodule_import(
153
+ "urllib.parse", "parse_qs", ImportType.STDLIB
154
+ )
155
+ file_import.add_submodule_import(
156
+ "azure.core.utils", "case_insensitive_dict", ImportType.AZURECORE
157
+ )
148
158
  return file_import
149
159
 
150
160
 
@@ -179,15 +179,11 @@ class _ParameterBase(
179
179
  def in_method_signature(self) -> bool:
180
180
  ...
181
181
 
182
- def method_signature(self, is_python3_file: bool, async_mode: bool) -> str:
182
+ def method_signature(self, async_mode: bool) -> str:
183
183
  type_annot = self.type_annotation(async_mode=async_mode)
184
- if is_python3_file:
185
- if self.client_default_value is not None or self.optional:
186
- return f"{self.client_name}: {type_annot} = {self.client_default_value_declaration},"
187
- return f"{self.client_name}: {type_annot},"
188
184
  if self.client_default_value is not None or self.optional:
189
- return f"{self.client_name}={self.client_default_value_declaration}, # type: {type_annot}"
190
- return f"{self.client_name}, # type: {type_annot}"
185
+ return f"{self.client_name}: {type_annot} = {self.client_default_value_declaration},"
186
+ return f"{self.client_name}: {type_annot},"
191
187
 
192
188
 
193
189
  class _BodyParameterBase(_ParameterBase):
@@ -235,49 +235,36 @@ class _ParameterListBase(
235
235
  """Sorted method params. First positional, then keyword only, then kwarg"""
236
236
  return self.positional + self.keyword_only + self.kwarg
237
237
 
238
- def method_signature(self, is_python3_file: bool, async_mode: bool) -> List[str]:
238
+ def method_signature(self, async_mode: bool) -> List[str]:
239
239
  """Method signature for this parameter list."""
240
240
  return method_signature_helper(
241
- positional=self.method_signature_positional(is_python3_file, async_mode),
242
- keyword_only=self.method_signature_keyword_only(
243
- is_python3_file, async_mode
244
- ),
245
- kwarg_params=self.method_signature_kwargs(is_python3_file),
241
+ positional=self.method_signature_positional(async_mode),
242
+ keyword_only=self.method_signature_keyword_only(async_mode),
243
+ kwarg_params=self.method_signature_kwargs,
246
244
  )
247
245
 
248
- def method_signature_positional(
249
- self, is_python3_file: bool, async_mode: bool
250
- ) -> List[str]:
246
+ def method_signature_positional(self, async_mode: bool) -> List[str]:
251
247
  """Signature for positional parameters"""
252
- return [
253
- parameter.method_signature(is_python3_file, async_mode)
254
- for parameter in self.positional
255
- ]
248
+ return [parameter.method_signature(async_mode) for parameter in self.positional]
256
249
 
257
- def method_signature_keyword_only(
258
- self, is_python3_file: bool, async_mode: bool
259
- ) -> List[str]:
250
+ def method_signature_keyword_only(self, async_mode: bool) -> List[str]:
260
251
  """Signature for keyword only parameters"""
261
- if not (self.keyword_only and is_python3_file):
252
+ if not self.keyword_only:
262
253
  return []
263
254
  return ["*,"] + [
264
- parameter.method_signature(is_python3_file, async_mode)
265
- for parameter in self.keyword_only
255
+ parameter.method_signature(async_mode) for parameter in self.keyword_only
266
256
  ]
267
257
 
268
- @staticmethod
269
- def method_signature_kwargs(is_python3_file: bool) -> List[str]:
258
+ @property
259
+ def method_signature_kwargs(self) -> List[str]:
270
260
  """Signature for kwargs"""
271
- return ["**kwargs: Any"] if is_python3_file else ["**kwargs # type: Any"]
261
+ return ["**kwargs: Any"]
272
262
 
273
- def kwargs_to_pop(
274
- self, is_python3_file: bool
275
- ) -> List[Union[ParameterType, BodyParameterType]]:
263
+ @property
264
+ def kwargs_to_pop(self) -> List[Union[ParameterType, BodyParameterType]]:
276
265
  """Method kwargs we want to pop"""
277
266
  # don't want to pop bodies unless it's a constant
278
267
  kwargs_to_pop = self.kwarg
279
- if not is_python3_file:
280
- kwargs_to_pop += self.keyword_only
281
268
  return [
282
269
  k
283
270
  for k in kwargs_to_pop
@@ -416,14 +403,12 @@ class RequestBuilderParameterList(_RequestBuilderParameterList):
416
403
  class OverloadedRequestBuilderParameterList(_RequestBuilderParameterList):
417
404
  """Parameter list for OverloadedRequestBuilder"""
418
405
 
419
- def method_signature_keyword_only(
420
- self, is_python3_file: bool, async_mode: bool
421
- ) -> List[str]:
406
+ def method_signature_keyword_only(self, async_mode: bool) -> List[str]:
422
407
  """Signature for keyword only parameters"""
423
- if not (self.keyword_only and is_python3_file):
408
+ if not self.keyword_only:
424
409
  return []
425
410
  return ["*,"] + [
426
- parameter.method_signature(is_python3_file, async_mode)
411
+ parameter.method_signature(async_mode)
427
412
  for parameter in self.keyword_only
428
413
  if parameter.location != ParameterLocation.BODY
429
414
  ]
@@ -478,13 +463,12 @@ class ClientGlobalParameterList(_ClientGlobalParameterList[ClientParameter]):
478
463
  except StopIteration:
479
464
  return None
480
465
 
481
- def kwargs_to_pop(
482
- self, is_python3_file: bool
483
- ) -> List[Union[ClientParameter, BodyParameter]]:
466
+ @property
467
+ def kwargs_to_pop(self) -> List[Union[ClientParameter, BodyParameter]]:
484
468
  """We only want to pass base url path parameters in the client"""
485
469
  return [
486
470
  k
487
- for k in super().kwargs_to_pop(is_python3_file=is_python3_file)
471
+ for k in super().kwargs_to_pop
488
472
  if k.location == ParameterLocation.ENDPOINT_PATH
489
473
  ]
490
474
 
@@ -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,
@@ -22,12 +21,10 @@ from .parameter_list import (
22
21
  OverloadedRequestBuilderParameterList,
23
22
  )
24
23
  from .imports import FileImport, ImportType, TypingSection, MsrestImportType
25
- from .request_builder_parameter import RequestBuilderMultipartBodyParameter
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 []
@@ -147,23 +142,7 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
147
142
  RequestBuilder.from_yaml(rb_yaml_data, code_model)
148
143
  for rb_yaml_data in yaml_data.get("overloads", [])
149
144
  ]
150
- abstract = False
151
145
  parameter_list = cls.parameter_list_type()(yaml_data, code_model)
152
- if (
153
- code_model.options["version_tolerant"]
154
- and parameter_list.has_body
155
- and isinstance(
156
- parameter_list.body_parameter, RequestBuilderMultipartBodyParameter
157
- )
158
- ):
159
- _LOGGER.warning(
160
- 'Not going to generate operation "%s" because it has multipart / urlencoded body parameters. '
161
- "Multipart / urlencoded body parameters are not supported for version tolerant generation right now. "
162
- 'Please write your own custom operation in the "_patch.py" file '
163
- "following https://aka.ms/azsdk/python/dpcodegen/python/customize",
164
- name,
165
- )
166
- abstract = True
167
146
 
168
147
  return cls(
169
148
  yaml_data=yaml_data,
@@ -171,7 +150,6 @@ class RequestBuilderBase(BaseBuilder[ParameterListType]):
171
150
  name=name,
172
151
  parameters=parameter_list,
173
152
  overloads=overloads,
174
- abstract=abstract,
175
153
  )
176
154
 
177
155