@autorest/python 5.15.0 → 5.16.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 (86) hide show
  1. package/ChangeLog.md +20 -0
  2. package/autorest/__init__.py +1 -2
  3. package/autorest/black/__init__.py +12 -5
  4. package/autorest/codegen/__init__.py +145 -73
  5. package/autorest/codegen/models/__init__.py +29 -18
  6. package/autorest/codegen/models/base_builder.py +48 -11
  7. package/autorest/codegen/models/base_model.py +6 -4
  8. package/autorest/codegen/models/base_schema.py +19 -18
  9. package/autorest/codegen/models/client.py +65 -21
  10. package/autorest/codegen/models/code_model.py +107 -61
  11. package/autorest/codegen/models/constant_schema.py +25 -13
  12. package/autorest/codegen/models/credential_model.py +23 -15
  13. package/autorest/codegen/models/credential_schema.py +18 -14
  14. package/autorest/codegen/models/credential_schema_policy.py +11 -15
  15. package/autorest/codegen/models/dictionary_schema.py +20 -17
  16. package/autorest/codegen/models/enum_schema.py +35 -25
  17. package/autorest/codegen/models/imports.py +70 -41
  18. package/autorest/codegen/models/list_schema.py +25 -13
  19. package/autorest/codegen/models/lro_operation.py +58 -22
  20. package/autorest/codegen/models/lro_paging_operation.py +2 -3
  21. package/autorest/codegen/models/object_schema.py +99 -49
  22. package/autorest/codegen/models/operation.py +236 -117
  23. package/autorest/codegen/models/operation_group.py +64 -34
  24. package/autorest/codegen/models/paging_operation.py +45 -18
  25. package/autorest/codegen/models/parameter.py +151 -83
  26. package/autorest/codegen/models/parameter_list.py +183 -162
  27. package/autorest/codegen/models/primitive_schemas.py +84 -55
  28. package/autorest/codegen/models/property.py +44 -26
  29. package/autorest/codegen/models/request_builder.py +65 -30
  30. package/autorest/codegen/models/request_builder_parameter.py +47 -23
  31. package/autorest/codegen/models/request_builder_parameter_list.py +77 -108
  32. package/autorest/codegen/models/schema_request.py +16 -6
  33. package/autorest/codegen/models/schema_response.py +18 -13
  34. package/autorest/codegen/models/utils.py +5 -2
  35. package/autorest/codegen/serializers/__init__.py +182 -91
  36. package/autorest/codegen/serializers/builder_serializer.py +667 -331
  37. package/autorest/codegen/serializers/client_serializer.py +98 -37
  38. package/autorest/codegen/serializers/general_serializer.py +61 -26
  39. package/autorest/codegen/serializers/import_serializer.py +93 -31
  40. package/autorest/codegen/serializers/metadata_serializer.py +73 -24
  41. package/autorest/codegen/serializers/model_base_serializer.py +35 -15
  42. package/autorest/codegen/serializers/model_generic_serializer.py +1 -4
  43. package/autorest/codegen/serializers/model_init_serializer.py +5 -1
  44. package/autorest/codegen/serializers/model_python3_serializer.py +7 -6
  45. package/autorest/codegen/serializers/operation_groups_serializer.py +20 -9
  46. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  47. package/autorest/codegen/serializers/patch_serializer.py +4 -1
  48. package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
  49. package/autorest/codegen/serializers/utils.py +35 -21
  50. package/autorest/codegen/templates/init.py.jinja2 +2 -2
  51. package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
  52. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
  53. package/autorest/codegen/templates/metadata.json.jinja2 +7 -6
  54. package/autorest/codegen/templates/operation.py.jinja2 +7 -9
  55. package/autorest/codegen/templates/operation_group.py.jinja2 +2 -8
  56. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  57. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  58. package/autorest/codegen/templates/request_builder.py.jinja2 +18 -11
  59. package/autorest/jsonrpc/__init__.py +7 -12
  60. package/autorest/jsonrpc/localapi.py +4 -3
  61. package/autorest/jsonrpc/server.py +13 -6
  62. package/autorest/jsonrpc/stdstream.py +13 -6
  63. package/autorest/m2r/__init__.py +5 -8
  64. package/autorest/multiapi/__init__.py +24 -14
  65. package/autorest/multiapi/models/client.py +21 -11
  66. package/autorest/multiapi/models/code_model.py +23 -10
  67. package/autorest/multiapi/models/config.py +4 -1
  68. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  69. package/autorest/multiapi/models/global_parameter.py +2 -1
  70. package/autorest/multiapi/models/global_parameters.py +14 -8
  71. package/autorest/multiapi/models/imports.py +24 -17
  72. package/autorest/multiapi/models/mixin_operation.py +5 -5
  73. package/autorest/multiapi/models/operation_group.py +2 -1
  74. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  75. package/autorest/multiapi/serializers/__init__.py +18 -23
  76. package/autorest/multiapi/serializers/import_serializer.py +47 -17
  77. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  78. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  79. package/autorest/multiapi/utils.py +3 -3
  80. package/autorest/namer/__init__.py +2 -4
  81. package/autorest/namer/name_converter.py +200 -103
  82. package/autorest/namer/python_mappings.py +10 -22
  83. package/package.json +2 -2
  84. package/run-python3.js +2 -3
  85. package/venvtools.py +1 -1
  86. package/autorest/codegen/models/rest.py +0 -42
@@ -4,19 +4,23 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  import logging
7
- from typing import Dict, List, Any, Set
7
+ from typing import Dict, List, Any, Set, TYPE_CHECKING
8
8
 
9
9
  from .base_model import BaseModel
10
10
  from .operation import Operation
11
11
  from .lro_operation import LROOperation
12
12
  from .paging_operation import PagingOperation
13
13
  from .lro_paging_operation import LROPagingOperation
14
- from .imports import FileImport, ImportType
14
+ from .imports import FileImport, ImportType, TypingSection
15
+
16
+ if TYPE_CHECKING:
17
+ from .code_model import CodeModel
15
18
 
16
19
 
17
20
  _LOGGER = logging.getLogger(__name__)
18
21
 
19
- def _get_operation(code_model, yaml_data: Dict[str, Any]) -> Operation:
22
+
23
+ def _get_operation(yaml_data: Dict[str, Any], code_model: "CodeModel") -> Operation:
20
24
  lro_operation = yaml_data.get("extensions", {}).get("x-ms-long-running-operation")
21
25
  paging_operation = yaml_data.get("extensions", {}).get("x-ms-pageable")
22
26
  operation_schema = Operation
@@ -31,106 +35,132 @@ def _get_operation(code_model, yaml_data: Dict[str, Any]) -> Operation:
31
35
 
32
36
 
33
37
  class OperationGroup(BaseModel):
34
- """Represent an operation group.
38
+ """Represent an operation group."""
35
39
 
36
- """
37
40
  def __init__(
38
41
  self,
39
- code_model,
40
42
  yaml_data: Dict[str, Any],
43
+ code_model: "CodeModel",
41
44
  name: str,
42
45
  class_name: str,
43
46
  operations: List[Operation],
44
- api_versions: Set[str]
47
+ api_versions: Set[str],
45
48
  ) -> None:
46
- super().__init__(yaml_data)
47
- self.code_model = code_model
49
+ super().__init__(yaml_data, code_model)
48
50
  self.name = name
49
51
  self.class_name = class_name
50
52
  self.operations = operations
51
53
  self.api_versions = api_versions
52
54
 
55
+ @property
56
+ def has_abstract_operations(self) -> bool:
57
+ return any(o for o in self.operations if o.abstract)
58
+
59
+ def base_class(self, async_mode: bool) -> str:
60
+ base_classes: List[str] = []
61
+ if self.is_empty_operation_group and self.code_model.need_mixin_abc:
62
+ base_classes.append("MixinABC")
63
+ if not (async_mode or self.code_model.options["python3_only"]):
64
+ base_classes.append("object")
65
+ if self.has_abstract_operations:
66
+ base_classes.append("abc.ABC")
67
+ return ", ".join(base_classes)
68
+
53
69
  def imports_for_multiapi(self, async_mode: bool) -> FileImport:
54
70
  file_import = FileImport()
55
71
  for operation in self.operations:
56
72
  file_import.merge(operation.imports_for_multiapi(async_mode))
57
- file_import.add_submodule_import(".." if async_mode else ".", "models", ImportType.LOCAL, alias="_models")
73
+ file_import.add_submodule_import(
74
+ ".." if async_mode else ".", "models", ImportType.LOCAL, alias="_models"
75
+ )
58
76
  return file_import
59
77
 
60
78
  def imports(self, async_mode: bool, is_python3_file: bool) -> FileImport:
61
79
  file_import = FileImport()
62
- file_import.add_submodule_import("azure.core.exceptions", "ClientAuthenticationError", ImportType.AZURECORE)
63
- file_import.add_submodule_import("azure.core.exceptions", "ResourceNotFoundError", ImportType.AZURECORE)
64
- file_import.add_submodule_import("azure.core.exceptions", "ResourceExistsError", ImportType.AZURECORE)
80
+
65
81
  for operation in self.operations:
66
82
  file_import.merge(operation.imports(async_mode, is_python3_file))
67
83
  local_path = "..." if async_mode else ".."
68
84
  if self.code_model.has_schemas and self.code_model.options["models_mode"]:
69
- file_import.add_submodule_import(local_path, "models", ImportType.LOCAL, alias="_models")
85
+ file_import.add_submodule_import(
86
+ local_path, "models", ImportType.LOCAL, alias="_models"
87
+ )
70
88
  if self.code_model.options["builders_visibility"] == "embedded" and async_mode:
71
89
  if not self.code_model.options["combine_operation_files"]:
72
- operation_group_name = "" if self.is_empty_operation_group else self.name
90
+ operation_group_name = (
91
+ "" if self.is_empty_operation_group else self.name
92
+ )
73
93
  operation_group_builders = [
74
- r for r in self.code_model.rest.request_builders
94
+ r
95
+ for r in self.code_model.request_builders
75
96
  if r.operation_group_name == operation_group_name
76
97
  ]
77
98
  else:
78
- operation_group_builders = self.code_model.rest.request_builders
99
+ operation_group_builders = self.code_model.request_builders
79
100
  for request_builder in operation_group_builders:
101
+ if request_builder.abstract:
102
+ continue
80
103
  python3_only = self.code_model.options["python3_only"]
81
- typed_sync_operation_file = self.code_model.options["add_python3_operation_files"]
82
- suffix = "_py3" if typed_sync_operation_file and not python3_only else ""
104
+ typed_sync_operation_file = self.code_model.options[
105
+ "add_python3_operation_files"
106
+ ]
107
+ suffix = (
108
+ "_py3" if typed_sync_operation_file and not python3_only else ""
109
+ )
83
110
  file_import.add_submodule_import(
84
111
  f"...{self.code_model.operations_folder_name}.{self.filename}{suffix}",
85
112
  request_builder.name,
86
- import_type=ImportType.LOCAL
113
+ import_type=ImportType.LOCAL,
87
114
  )
88
115
  if self.code_model.need_mixin_abc:
89
- file_import.add_submodule_import(
90
- ".._vendor", "MixinABC", ImportType.LOCAL
91
- )
116
+ file_import.add_submodule_import(".._vendor", "MixinABC", ImportType.LOCAL)
117
+ file_import.add_submodule_import(
118
+ "typing", "TypeVar", ImportType.STDLIB, TypingSection.CONDITIONAL
119
+ )
120
+ file_import.define_mypy_type("T", "TypeVar('T')")
92
121
  type_value = "Optional[Callable[[PipelineResponse[HttpRequest, {}HttpResponse], T, Dict[str, Any]], Any]]"
93
122
  file_import.define_mypy_type(
94
- "ClsType",
95
- type_value.format(""),
96
- type_value.format("Async")
123
+ "ClsType", type_value.format(""), type_value.format("Async")
97
124
  )
98
125
  return file_import
99
126
 
100
-
101
127
  @property
102
128
  def filename(self) -> str:
103
129
  basename = self.name
104
130
  if self.is_empty_operation_group:
105
131
  basename = self.code_model.module_name
106
132
 
107
- if basename == "operations" or self.code_model.options["combine_operation_files"]:
133
+ if (
134
+ basename == "operations"
135
+ or self.code_model.options["combine_operation_files"]
136
+ ):
108
137
  return f"_operations"
109
138
  return f"_{basename}_operations"
110
139
 
111
140
  @property
112
141
  def is_empty_operation_group(self) -> bool:
113
- """The operation group with no name is the direct client methods.
114
- """
142
+ """The operation group with no name is the direct client methods."""
115
143
  return not self.yaml_data["language"]["default"]["name"]
116
144
 
117
145
  @classmethod
118
- def from_yaml(cls, code_model, yaml_data: Dict[str, Any]) -> "OperationGroup":
146
+ def from_yaml(
147
+ cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
148
+ ) -> "OperationGroup":
119
149
  name = yaml_data["language"]["python"]["name"]
120
150
  _LOGGER.debug("Parsing %s operation group", name)
121
151
 
122
152
  operations = []
123
153
  api_versions: Set[str] = set()
124
154
  for operation_yaml in yaml_data["operations"]:
125
- operation = _get_operation(code_model, operation_yaml)
155
+ operation = _get_operation(operation_yaml, code_model)
126
156
  operations.append(operation)
127
157
  api_versions.update(operation.api_versions)
128
158
 
129
159
  return cls(
130
- code_model=code_model,
131
160
  yaml_data=yaml_data,
161
+ code_model=code_model,
132
162
  name=name,
133
163
  class_name=yaml_data["language"]["python"]["className"],
134
164
  operations=operations,
135
- api_versions=api_versions
165
+ api_versions=api_versions,
136
166
  )
@@ -4,7 +4,7 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  import logging
7
- from typing import cast, Dict, List, Any, Optional, Set
7
+ from typing import cast, Dict, List, Any, Optional, Set, TYPE_CHECKING
8
8
 
9
9
  from .operation import Operation
10
10
  from .schema_response import SchemaResponse
@@ -14,14 +14,18 @@ from .object_schema import ObjectSchema
14
14
  from .schema_request import SchemaRequest
15
15
  from .parameter_list import ParameterList
16
16
 
17
+ if TYPE_CHECKING:
18
+ from .code_model import CodeModel
19
+
17
20
  _LOGGER = logging.getLogger(__name__)
18
21
 
19
22
 
20
23
  class PagingOperation(Operation):
21
24
  def __init__(
22
25
  self,
23
- code_model,
24
26
  yaml_data: Dict[str, Any],
27
+ code_model: "CodeModel",
28
+ request_builder: RequestBuilder,
25
29
  name: str,
26
30
  description: str,
27
31
  api_versions: Set[str],
@@ -34,11 +38,13 @@ class PagingOperation(Operation):
34
38
  want_description_docstring: bool = True,
35
39
  want_tracing: bool = True,
36
40
  *,
37
- override_success_response_to_200: bool = False
41
+ abstract: bool = False,
42
+ override_success_response_to_200: bool = False,
38
43
  ) -> None:
39
- super(PagingOperation, self).__init__(
40
- code_model,
44
+ super().__init__(
41
45
  yaml_data,
46
+ code_model,
47
+ request_builder,
42
48
  name,
43
49
  description,
44
50
  api_versions,
@@ -49,11 +55,16 @@ class PagingOperation(Operation):
49
55
  responses,
50
56
  exceptions,
51
57
  want_description_docstring,
52
- want_tracing
58
+ want_tracing=want_tracing,
59
+ abstract=abstract,
53
60
  )
54
61
  self._item_name: str = yaml_data["extensions"]["x-ms-pageable"].get("itemName")
55
- self._next_link_name: str = yaml_data["extensions"]["x-ms-pageable"].get("nextLinkName")
56
- self.operation_name: str = yaml_data["extensions"]["x-ms-pageable"].get("operationName")
62
+ self._next_link_name: str = yaml_data["extensions"]["x-ms-pageable"].get(
63
+ "nextLinkName"
64
+ )
65
+ self.operation_name: str = yaml_data["extensions"]["x-ms-pageable"].get(
66
+ "operationName"
67
+ )
57
68
  self.next_operation: Optional[Operation] = None
58
69
  self.override_success_response_to_200 = override_success_response_to_200
59
70
 
@@ -61,7 +72,8 @@ class PagingOperation(Operation):
61
72
  response = self.responses[0]
62
73
  if not isinstance(response.schema, ObjectSchema):
63
74
  raise ValueError(
64
- "The response of a paging operation must be of type " + f"ObjectSchema but {response.schema} is not"
75
+ "The response of a paging operation must be of type "
76
+ + f"ObjectSchema but {response.schema} is not"
65
77
  )
66
78
  return response
67
79
 
@@ -84,7 +96,8 @@ class PagingOperation(Operation):
84
96
  item_name = self._item_name or "value"
85
97
  try:
86
98
  return (
87
- self._find_python_name(item_name, "itemName") if code_model.options["models_mode"]
99
+ self._find_python_name(item_name, "itemName")
100
+ if code_model.options["models_mode"]
88
101
  else item_name
89
102
  )
90
103
  except ValueError:
@@ -125,12 +138,16 @@ class PagingOperation(Operation):
125
138
  def _imports_shared(self, async_mode: bool) -> FileImport:
126
139
  file_import = super()._imports_shared(async_mode)
127
140
  if async_mode:
128
- file_import.add_submodule_import("typing", "AsyncIterable", ImportType.STDLIB, TypingSection.CONDITIONAL)
141
+ file_import.add_submodule_import(
142
+ "typing", "AsyncIterable", ImportType.STDLIB, TypingSection.CONDITIONAL
143
+ )
129
144
  else:
130
- file_import.add_submodule_import("typing", "Iterable", ImportType.STDLIB, TypingSection.CONDITIONAL)
145
+ file_import.add_submodule_import(
146
+ "typing", "Iterable", ImportType.STDLIB, TypingSection.CONDITIONAL
147
+ )
131
148
  if (
132
- self.next_request_builder and
133
- self.code_model.options["builders_visibility"] == "embedded"
149
+ self.next_request_builder
150
+ and self.code_model.options["builders_visibility"] == "embedded"
134
151
  and not async_mode
135
152
  ):
136
153
  file_import.merge(self.next_request_builder.imports())
@@ -141,14 +158,20 @@ class PagingOperation(Operation):
141
158
  pager_import_path = ".".join(self.get_pager_path(async_mode).split(".")[:-1])
142
159
  pager = self.get_pager(async_mode)
143
160
 
144
- file_import.add_submodule_import(pager_import_path, pager, ImportType.AZURECORE, TypingSection.CONDITIONAL)
161
+ file_import.add_submodule_import(
162
+ pager_import_path, pager, ImportType.AZURECORE, TypingSection.CONDITIONAL
163
+ )
145
164
 
146
165
  return file_import
147
166
 
148
167
  def imports(self, async_mode: bool, is_python3_file: bool) -> FileImport:
149
168
  file_import = self._imports_base(async_mode, is_python3_file)
150
169
  # operation adds an import for distributed_trace_async, we don't want it
151
- file_import.imports = [i for i in file_import.imports if not i.submodule_name == "distributed_trace_async"]
170
+ file_import.imports = [
171
+ i
172
+ for i in file_import.imports
173
+ if not i.submodule_name == "distributed_trace_async"
174
+ ]
152
175
 
153
176
  pager_import_path = ".".join(self.get_pager_path(async_mode).split(".")[:-1])
154
177
  pager = self.get_pager(async_mode)
@@ -156,11 +179,15 @@ class PagingOperation(Operation):
156
179
  file_import.add_submodule_import(pager_import_path, pager, ImportType.AZURECORE)
157
180
 
158
181
  if async_mode:
159
- file_import.add_submodule_import("azure.core.async_paging", "AsyncList", ImportType.AZURECORE)
182
+ file_import.add_submodule_import(
183
+ "azure.core.async_paging", "AsyncList", ImportType.AZURECORE
184
+ )
160
185
 
161
186
  if self.code_model.options["tracing"] and self.want_tracing:
162
187
  file_import.add_submodule_import(
163
- "azure.core.tracing.decorator", "distributed_trace", ImportType.AZURECORE,
188
+ "azure.core.tracing.decorator",
189
+ "distributed_trace",
190
+ ImportType.AZURECORE,
164
191
  )
165
192
 
166
193
  return file_import