@autorest/python 5.16.0 → 5.17.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 (92) hide show
  1. package/ChangeLog.md +43 -3
  2. package/README.md +30 -4
  3. package/autorest/__init__.py +1 -1
  4. package/autorest/codegen/__init__.py +48 -209
  5. package/autorest/codegen/models/__init__.py +116 -83
  6. package/autorest/codegen/models/base_builder.py +49 -88
  7. package/autorest/codegen/models/base_model.py +1 -1
  8. package/autorest/codegen/models/{base_schema.py → base_type.py} +56 -40
  9. package/autorest/codegen/models/client.py +157 -48
  10. package/autorest/codegen/models/code_model.py +108 -254
  11. package/autorest/codegen/models/combined_type.py +107 -0
  12. package/autorest/codegen/models/{constant_schema.py → constant_type.py} +49 -40
  13. package/autorest/codegen/models/credential_types.py +224 -0
  14. package/autorest/codegen/models/{dictionary_schema.py → dictionary_type.py} +41 -31
  15. package/autorest/codegen/models/enum_type.py +195 -0
  16. package/autorest/codegen/models/imports.py +23 -0
  17. package/autorest/codegen/models/list_type.py +134 -0
  18. package/autorest/codegen/models/lro_operation.py +77 -156
  19. package/autorest/codegen/models/lro_paging_operation.py +28 -11
  20. package/autorest/codegen/models/model_type.py +239 -0
  21. package/autorest/codegen/models/operation.py +303 -269
  22. package/autorest/codegen/models/operation_group.py +48 -89
  23. package/autorest/codegen/models/paging_operation.py +80 -123
  24. package/autorest/codegen/models/parameter.py +289 -396
  25. package/autorest/codegen/models/parameter_list.py +348 -360
  26. package/autorest/codegen/models/primitive_types.py +544 -0
  27. package/autorest/codegen/models/property.py +109 -139
  28. package/autorest/codegen/models/request_builder.py +105 -88
  29. package/autorest/codegen/models/request_builder_parameter.py +112 -100
  30. package/autorest/codegen/models/response.py +325 -0
  31. package/autorest/codegen/models/utils.py +12 -19
  32. package/autorest/codegen/serializers/__init__.py +46 -37
  33. package/autorest/codegen/serializers/builder_serializer.py +604 -1146
  34. package/autorest/codegen/serializers/client_serializer.py +83 -88
  35. package/autorest/codegen/serializers/general_serializer.py +5 -64
  36. package/autorest/codegen/serializers/import_serializer.py +7 -4
  37. package/autorest/codegen/serializers/metadata_serializer.py +15 -104
  38. package/autorest/codegen/serializers/model_base_serializer.py +40 -32
  39. package/autorest/codegen/serializers/model_generic_serializer.py +8 -6
  40. package/autorest/codegen/serializers/model_init_serializer.py +2 -4
  41. package/autorest/codegen/serializers/model_python3_serializer.py +22 -16
  42. package/autorest/codegen/serializers/operation_groups_serializer.py +4 -13
  43. package/autorest/codegen/serializers/parameter_serializer.py +174 -0
  44. package/autorest/codegen/serializers/request_builders_serializer.py +12 -29
  45. package/autorest/codegen/serializers/utils.py +0 -142
  46. package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
  47. package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -7
  48. package/autorest/codegen/templates/config.py.jinja2 +13 -13
  49. package/autorest/codegen/templates/enum.py.jinja2 +4 -4
  50. package/autorest/codegen/templates/enum_container.py.jinja2 +1 -1
  51. package/autorest/codegen/templates/init.py.jinja2 +2 -2
  52. package/autorest/codegen/templates/lro_operation.py.jinja2 +4 -1
  53. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +4 -1
  54. package/autorest/codegen/templates/metadata.json.jinja2 +33 -33
  55. package/autorest/codegen/templates/model.py.jinja2 +23 -24
  56. package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
  57. package/autorest/codegen/templates/model_init.py.jinja2 +3 -5
  58. package/autorest/codegen/templates/operation.py.jinja2 +6 -8
  59. package/autorest/codegen/templates/operation_group.py.jinja2 +7 -7
  60. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
  61. package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
  62. package/autorest/codegen/templates/paging_operation.py.jinja2 +2 -2
  63. package/autorest/codegen/templates/request_builder.py.jinja2 +13 -11
  64. package/autorest/codegen/templates/setup.py.jinja2 +9 -3
  65. package/autorest/codegen/templates/vendor.py.jinja2 +1 -1
  66. package/autorest/jsonrpc/server.py +15 -3
  67. package/autorest/m4reformatter/__init__.py +1108 -0
  68. package/autorest/multiapi/models/code_model.py +1 -1
  69. package/autorest/multiapi/serializers/__init__.py +4 -4
  70. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  71. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  72. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +3 -3
  73. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  74. package/autorest/postprocess/__init__.py +202 -0
  75. package/autorest/postprocess/get_all.py +19 -0
  76. package/autorest/postprocess/venvtools.py +73 -0
  77. package/autorest/preprocess/__init__.py +209 -0
  78. package/autorest/preprocess/helpers.py +54 -0
  79. package/autorest/{namer → preprocess}/python_mappings.py +21 -16
  80. package/package.json +2 -2
  81. package/autorest/codegen/models/credential_model.py +0 -55
  82. package/autorest/codegen/models/credential_schema.py +0 -95
  83. package/autorest/codegen/models/credential_schema_policy.py +0 -73
  84. package/autorest/codegen/models/enum_schema.py +0 -225
  85. package/autorest/codegen/models/list_schema.py +0 -135
  86. package/autorest/codegen/models/object_schema.py +0 -303
  87. package/autorest/codegen/models/primitive_schemas.py +0 -495
  88. package/autorest/codegen/models/request_builder_parameter_list.py +0 -249
  89. package/autorest/codegen/models/schema_request.py +0 -55
  90. package/autorest/codegen/models/schema_response.py +0 -141
  91. package/autorest/namer/__init__.py +0 -23
  92. package/autorest/namer/name_converter.py +0 -509
@@ -3,24 +3,15 @@
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
- from typing import cast, List, Dict, Optional, Any, Set
6
+ from typing import List, Dict, Optional, Any, Set, Union
8
7
 
9
- from .base_schema import BaseSchema
10
- from .enum_schema import EnumSchema
11
- from .object_schema import ObjectSchema
8
+ from .base_type import BaseType
9
+ from .enum_type import EnumType
10
+ from .model_type import ModelType
12
11
  from .operation_group import OperationGroup
13
- from .operation import Operation
14
- from .lro_operation import LROOperation
15
- from .paging_operation import PagingOperation
12
+ from .client import Client, Config
13
+ from .request_builder import OverloadedRequestBuilder, RequestBuilder
16
14
  from .parameter import Parameter
17
- from .client import Client
18
- from .parameter_list import GlobalParameterList
19
- from .property import Property
20
- from .request_builder import RequestBuilder
21
- from .credential_model import CredentialModel
22
-
23
- _LOGGER = logging.getLogger(__name__)
24
15
 
25
16
 
26
17
  class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-public-methods
@@ -34,21 +25,19 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
34
25
  :param str description: The description of the client
35
26
  :param str namespace: The namespace of our module
36
27
  :param schemas: The list of schemas we are going to serialize in the models files. Maps their yaml
37
- id to our created ObjectSchema.
38
- :type schemas: dict[int, ~autorest.models.ObjectSchema]
28
+ id to our created ModelType.
29
+ :type schemas: dict[int, ~autorest.models.ModelType]
39
30
  :param sorted_schemas: Our schemas in order by inheritance and alphabet
40
- :type sorted_schemas: list[~autorest.models.ObjectSchema]
41
- :param enums: The enums, if any, we are going to serialize. Maps their yaml id to our created EnumSchema.
42
- :type enums: Dict[int, ~autorest.models.EnumSchema]
31
+ :type sorted_schemas: list[~autorest.models.ModelType]
32
+ :param enums: The enums, if any, we are going to serialize. Maps their yaml id to our created EnumType.
33
+ :type enums: Dict[int, ~autorest.models.EnumType]
43
34
  :param primitives: List of schemas we've created that are not EnumSchemas or ObjectSchemas. Maps their
44
35
  yaml id to our created schemas.
45
- :type primitives: Dict[int, ~autorest.models.BaseSchema]
36
+ :type primitives: Dict[int, ~autorest.models.BaseType]
46
37
  :param operation_groups: The operation groups we are going to serialize
47
38
  :type operation_groups: list[~autorest.models.OperationGroup]
48
39
  :param package_dependency: All the dependencies needed in setup.py
49
40
  :type package_dependency: Dict[str, str]
50
- :param credential_model: The class contains all the credential info
51
- :type credential_model: CredentialMode
52
41
  """
53
42
 
54
43
  def __init__(
@@ -57,53 +46,60 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
57
46
  options: Dict[str, Any],
58
47
  ) -> None:
59
48
  self.yaml_data = yaml_data
60
- self.send_request_name = (
61
- "send_request" if options["show_send_request"] else "_send_request"
62
- )
63
- self.rest_layer_name = (
64
- "rest" if options["builders_visibility"] == "public" else "_rest"
65
- )
66
49
  self.options = options
67
- self.module_name: str = ""
68
- self.class_name: str = ""
69
- self.description: str = ""
70
- self.namespace: str = ""
71
- self.namespace_path: str = ""
72
- self.schemas: Dict[int, ObjectSchema] = {}
73
- self.sorted_schemas: List[ObjectSchema] = []
74
- self.enums: Dict[int, EnumSchema] = {}
75
- self.primitives: Dict[int, BaseSchema] = {}
50
+ self.types_map: Dict[int, BaseType] = {} # map yaml id to schema
76
51
  self.operation_groups: List[OperationGroup] = []
77
- params = GlobalParameterList(self)
78
- params.code_model = self
79
- self.service_client: Client = Client(self, params)
80
- self.request_builders: List[RequestBuilder] = []
52
+ self._model_types: List[ModelType] = []
53
+ self._client: Optional[Client] = None
54
+ self._config: Optional[Config] = None
55
+ self.request_builders: List[
56
+ Union[RequestBuilder, OverloadedRequestBuilder]
57
+ ] = []
81
58
  self.package_dependency: Dict[str, str] = {}
82
- self._credential_model: Optional[CredentialModel] = None
83
-
84
- @property
85
- def global_parameters(self) -> GlobalParameterList:
86
- return self.service_client.parameters
59
+ self.namespace: str = yaml_data["client"]["namespace"].lower()
60
+ self.module_name: str = self.yaml_data["client"]["moduleName"]
87
61
 
88
- @global_parameters.setter
89
- def global_parameters(self, val: GlobalParameterList) -> None:
90
- self.service_client.parameters = val
91
-
92
- def lookup_schema(self, schema_id: int) -> BaseSchema:
62
+ def lookup_type(self, schema_id: int) -> BaseType:
93
63
  """Looks to see if the schema has already been created.
94
64
 
95
65
  :param int schema_id: The yaml id of the schema
96
66
  :return: If created, we return the created schema, otherwise, we throw.
97
- :rtype: ~autorest.models.BaseSchema
67
+ :rtype: ~autorest.models.BaseType
98
68
  :raises: KeyError if schema is not found
99
69
  """
100
- for attr in [self.schemas, self.enums, self.primitives]:
101
- for elt_key, elt_value in attr.items(): # type: ignore
102
- if schema_id == elt_key:
103
- return elt_value
104
- raise KeyError("Didn't find it!!!!!")
70
+ try:
71
+ return next(type for id, type in self.types_map.items() if id == schema_id)
72
+ except StopIteration:
73
+ raise KeyError(f"Couldn't find schema with id {schema_id}")
74
+
75
+ @property
76
+ def credential(self) -> Optional[Parameter]:
77
+ """The credential param, if one exists"""
78
+ return self.client.parameters.credential
105
79
 
106
- def lookup_request_builder(self, request_builder_id: int) -> RequestBuilder:
80
+ @property
81
+ def client(self) -> Client:
82
+ if not self._client:
83
+ raise ValueError("You haven't linked the client yet")
84
+ return self._client
85
+
86
+ @client.setter
87
+ def client(self, val: Client) -> None:
88
+ self._client = val
89
+
90
+ @property
91
+ def config(self) -> Config:
92
+ if not self._config:
93
+ raise ValueError("You haven't linked the config yet")
94
+ return self._config
95
+
96
+ @config.setter
97
+ def config(self, val: Config) -> None:
98
+ self._config = val
99
+
100
+ def lookup_request_builder(
101
+ self, request_builder_id: int
102
+ ) -> Union[RequestBuilder, OverloadedRequestBuilder]:
107
103
  """Find the request builder based off of id"""
108
104
  try:
109
105
  return next(
@@ -115,20 +111,31 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
115
111
  raise KeyError(f"No request builder with id {request_builder_id} found.")
116
112
 
117
113
  @property
118
- def exception_ids(self) -> Set[int]:
119
- exceptions_set = set()
120
- for group in self.yaml_data["operationGroups"]:
121
- for operation in group["operations"]:
122
- if not operation.get("exceptions"):
123
- continue
124
- for exception in operation["exceptions"]:
125
- if not exception.get("schema"):
126
- continue
127
- exceptions_set.add(id(exception["schema"]))
128
- return exceptions_set
114
+ def model_types(self) -> List[ModelType]:
115
+ """All of the model types in this class"""
116
+ if not self._model_types:
117
+ self._model_types = [
118
+ t for t in self.types_map.values() if isinstance(t, ModelType)
119
+ ]
120
+ return self._model_types
121
+
122
+ @model_types.setter
123
+ def model_types(self, val: List[ModelType]) -> None:
124
+ self._model_types = val
125
+
126
+ @property
127
+ def public_model_types(self) -> List[ModelType]:
128
+ return [m for m in self.model_types if m.is_public]
129
+
130
+ @property
131
+ def enums(self) -> List[EnumType]:
132
+ """All of the enums"""
133
+ return [t for t in self.types_map.values() if isinstance(t, EnumType)]
129
134
 
130
135
  @staticmethod
131
- def _sort_schemas_helper(current, seen_schema_names, seen_schema_yaml_ids):
136
+ def _sort_model_types_helper(
137
+ current: ModelType, seen_schema_names: Set[str], seen_schema_yaml_ids: Set[int]
138
+ ):
132
139
  if current.id in seen_schema_yaml_ids:
133
140
  return []
134
141
  if current.name in seen_schema_names:
@@ -136,15 +143,14 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
136
143
  f"We have already generated a schema with name {current.name}"
137
144
  )
138
145
  ancestors = [current]
139
- if current.base_models:
140
- for base_model in current.base_models:
141
- parent = cast(ObjectSchema, base_model)
146
+ if current.parents:
147
+ for parent in current.parents:
142
148
  if parent.id in seen_schema_yaml_ids:
143
149
  continue
144
150
  seen_schema_names.add(current.name)
145
151
  seen_schema_yaml_ids.add(current.id)
146
152
  ancestors = (
147
- CodeModel._sort_schemas_helper(
153
+ CodeModel._sort_model_types_helper(
148
154
  parent, seen_schema_names, seen_schema_yaml_ids
149
155
  )
150
156
  + ancestors
@@ -153,7 +159,7 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
153
159
  seen_schema_yaml_ids.add(current.id)
154
160
  return ancestors
155
161
 
156
- def sort_schemas(self) -> None:
162
+ def sort_model_types(self) -> None:
157
163
  """Sorts the final object schemas by inheritance and by alphabetical order.
158
164
 
159
165
  :return: None
@@ -161,38 +167,14 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
161
167
  """
162
168
  seen_schema_names: Set[str] = set()
163
169
  seen_schema_yaml_ids: Set[int] = set()
164
- sorted_schemas: List[ObjectSchema] = []
165
- for schema in sorted(self.schemas.values(), key=lambda x: x.name.lower()):
166
- sorted_schemas.extend(
167
- CodeModel._sort_schemas_helper(
170
+ sorted_object_schemas: List[ModelType] = []
171
+ for schema in sorted(self.model_types, key=lambda x: x.name.lower()):
172
+ sorted_object_schemas.extend(
173
+ CodeModel._sort_model_types_helper(
168
174
  schema, seen_schema_names, seen_schema_yaml_ids
169
175
  )
170
176
  )
171
- self.sorted_schemas = sorted_schemas
172
-
173
- def setup_client_input_parameters(self, yaml_data: Dict[str, Any]):
174
- dollar_host = [
175
- parameter
176
- for parameter in self.global_parameters
177
- if parameter.rest_api_name == "$host"
178
- ]
179
- if not dollar_host:
180
- # We don't want to support multi-api customurl YET (will see if that goes well....)
181
- # So far now, let's get the first one in the first operation
182
- # UGLY as hell.....
183
- if yaml_data.get("operationGroups"):
184
- first_req_of_first_op_of_first_grp = yaml_data["operationGroups"][0][
185
- "operations"
186
- ][0]["requests"][0]
187
- self.service_client.parameterized_host_template = (
188
- first_req_of_first_op_of_first_grp["protocol"]["http"]["uri"]
189
- )
190
- else:
191
- for host in dollar_host:
192
- self.global_parameters.remove(host)
193
- self.service_client.parameters.add_host(
194
- dollar_host[0].yaml_data["clientDefaultValue"]
195
- )
177
+ self.model_types = sorted_object_schemas
196
178
 
197
179
  def format_lro_operations(self) -> None:
198
180
  """Adds operations and attributes needed for LROs.
@@ -203,156 +185,23 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
203
185
  i = 0
204
186
  while i < len(operation_group.operations):
205
187
  operation = operation_group.operations[i]
206
- if isinstance(operation, LROOperation):
207
- operation_group.operations.insert(i, operation.initial_operation)
188
+ if operation.operation_type in ("lro", "lropaging"):
189
+ operation_group.operations.insert(i, operation.initial_operation) # type: ignore
208
190
  i += 1
209
191
  i += 1
210
192
 
211
- def remove_next_operation(self) -> None:
212
- """Linking paging operations together."""
213
-
214
- def _lookup_operation(yaml_id: int) -> Operation:
215
- for operation_group in self.operation_groups:
216
- for operation in operation_group.operations:
217
- if operation.id == yaml_id:
218
- return operation
219
- raise KeyError("Didn't find it!!!!!")
220
-
221
- for operation_group in self.operation_groups:
222
- next_operations = []
223
- for operation in operation_group.operations:
224
- # when we add in "LRO" functions we don't include yaml_data, so yaml_data can be empty in these cases
225
- next_link_yaml = None
226
- if operation.yaml_data and operation.yaml_data["language"][
227
- "python"
228
- ].get("paging"):
229
- next_link_yaml = operation.yaml_data["language"]["python"][
230
- "paging"
231
- ].get("nextLinkOperation")
232
- if isinstance(operation, PagingOperation) and next_link_yaml:
233
- next_operation = _lookup_operation(id(next_link_yaml))
234
- operation.next_operation = next_operation
235
- next_operations.append(next_operation)
236
-
237
- operation_group.operations = [
238
- operation
239
- for operation in operation_group.operations
240
- if operation not in next_operations
241
- ]
242
-
243
- @property
244
- def has_schemas(self):
245
- return self.schemas or self.enums
246
-
247
- @property
248
- def credential_model(self) -> CredentialModel:
249
- if not self._credential_model:
250
- raise ValueError(
251
- "You want to find the Credential Model, but have not given a value"
252
- )
253
- return self._credential_model
254
-
255
- @credential_model.setter
256
- def credential_model(self, val: CredentialModel) -> None:
257
- self._credential_model = val
258
-
259
- @staticmethod
260
- def _add_properties_from_inheritance_helper(schema, properties) -> List[Property]:
261
- if not schema.base_models:
262
- return properties
263
- if schema.base_models:
264
- for base_model in schema.base_models:
265
- parent = cast(ObjectSchema, base_model)
266
- # need to make sure that the properties we choose from our parent also don't contain
267
- # any of our own properties
268
- schema_property_names = set(
269
- [p.name for p in properties] + [p.name for p in schema.properties]
270
- )
271
- chosen_parent_properties = [
272
- p for p in parent.properties if p.name not in schema_property_names
273
- ]
274
- properties = (
275
- CodeModel._add_properties_from_inheritance_helper(
276
- parent, chosen_parent_properties
277
- )
278
- + properties
279
- )
280
-
281
- return properties
282
-
283
193
  @property
284
194
  def operations_folder_name(self) -> str:
195
+ """Get the name of the operations folder that holds operations."""
285
196
  name = "operations"
286
197
  if self.options["version_tolerant"] and not any(
287
- og for og in self.operation_groups if not og.is_empty_operation_group
198
+ og for og in self.operation_groups if not og.is_mixin
288
199
  ):
289
200
  name = f"_{name}"
290
201
  return name
291
202
 
292
- def _add_properties_from_inheritance(self) -> None:
293
- """Adds properties from base classes to schemas with parents.
294
-
295
- :return: None
296
- :rtype: None
297
- """
298
- for schema in self.schemas.values():
299
- schema.properties = CodeModel._add_properties_from_inheritance_helper(
300
- schema, schema.properties
301
- )
302
-
303
- @staticmethod
304
- def _add_exceptions_from_inheritance_helper(schema) -> bool:
305
- if schema.is_exception:
306
- return True
307
- parent_is_exception: List[bool] = []
308
- for base_model in schema.base_models:
309
- parent = cast(ObjectSchema, base_model)
310
- parent_is_exception.append(
311
- CodeModel._add_exceptions_from_inheritance_helper(parent)
312
- )
313
- return any(parent_is_exception)
314
-
315
- def _add_exceptions_from_inheritance(self) -> None:
316
- """Sets a class as an exception if it's parent is an exception.
317
-
318
- :return: None
319
- :rtype: None
320
- """
321
- for schema in self.schemas.values():
322
- schema.is_exception = CodeModel._add_exceptions_from_inheritance_helper(
323
- schema
324
- )
325
-
326
- def add_inheritance_to_models(self) -> None:
327
- """Adds base classes and properties from base classes to schemas with parents.
328
-
329
- :return: None
330
- :rtype: None
331
- """
332
- for schema in self.schemas.values():
333
- if schema.base_models:
334
- # right now, the base model property just holds the name of the parent class
335
- schema.base_models = [
336
- b for b in self.schemas.values() if b.id in schema.base_models
337
- ]
338
- self._add_properties_from_inheritance()
339
- self._add_exceptions_from_inheritance()
340
-
341
- def _populate_target_property(self, parameter: Parameter) -> None:
342
- for obj in self.schemas.values():
343
- for prop in obj.properties:
344
- if prop.id == parameter.target_property_name:
345
- parameter.target_property_name = prop.name
346
- return
347
- raise KeyError("Didn't find the target property")
348
-
349
- def generate_single_parameter_from_multiple_content_types_operation(self) -> None:
350
- for operation_group in self.operation_groups:
351
- for operation in operation_group.operations:
352
- if operation.multiple_content_type_parameters:
353
- operation.convert_multiple_content_type_parameters()
354
-
355
203
  def need_vendored_code(self, async_mode: bool) -> bool:
204
+ """Whether we need to vendor code in the _vendor.py file for this SDK"""
356
205
  if async_mode:
357
206
  return self.need_mixin_abc
358
207
  return (
@@ -361,6 +210,10 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
361
210
 
362
211
  @property
363
212
  def need_request_converter(self) -> bool:
213
+ """
214
+ Whether we need to convert our created azure.core.rest.HttpRequests to
215
+ azure.core.pipeline.transport.HttpRequests
216
+ """
364
217
  return (
365
218
  self.options["show_operations"]
366
219
  and bool(self.request_builders)
@@ -369,36 +222,31 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
369
222
 
370
223
  @property
371
224
  def need_format_url(self) -> bool:
225
+ """Whether we need to format urls. If so, we need to vendor core."""
372
226
  return any(rq for rq in self.request_builders if rq.parameters.path)
373
227
 
374
228
  @property
375
229
  def need_mixin_abc(self) -> bool:
230
+ """Do we want a mixin ABC class for typing purposes?"""
376
231
  return any(
377
232
  o
378
233
  for o in self.operation_groups
379
- if o.is_empty_operation_group and self.options["python3_only"]
234
+ if o.is_mixin and self.options["python3_only"]
380
235
  )
381
236
 
382
237
  @property
383
238
  def has_lro_operations(self) -> bool:
239
+ """Are there any LRO operations in this SDK?"""
384
240
  return any(
385
241
  [
386
- isinstance(operation, LROOperation)
242
+ operation.operation_type in ("lro", "lropaging")
387
243
  for operation_group in self.operation_groups
388
244
  for operation in operation_group.operations
389
245
  ]
390
246
  )
391
247
 
392
- def link_operation_to_request_builder(self) -> None:
393
- for operation_group in self.operation_groups:
394
- for operation in operation_group.operations:
395
- request_builder = operation.request_builder
396
- if isinstance(operation, LROOperation):
397
- request_builder.name = request_builder.name + "_initial"
398
- operation.request_builder = request_builder
399
- operation.link_body_kwargs_to_body_params()
400
-
401
248
  def get_models_filename(self, is_python3_file: bool) -> str:
249
+ """Get the names of the model file(s)"""
402
250
  if (
403
251
  self.options["version_tolerant"] or self.options["low_level_client"]
404
252
  ) and self.options["python3_only"]:
@@ -409,6 +257,12 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
409
257
 
410
258
  @property
411
259
  def enums_filename(self) -> str:
260
+ """The name of the enums file"""
412
261
  if self.options["version_tolerant"] or self.options["low_level_client"]:
413
262
  return "_enums"
414
263
  return f"_{self.module_name}_enums"
264
+
265
+ @property
266
+ def rest_layer_name(self) -> str:
267
+ """If we have a separate rest layer, what is its name?"""
268
+ return "rest" if self.options["builders_visibility"] == "public" else "_rest"
@@ -0,0 +1,107 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License.txt in the project root for
4
+ # license information.
5
+ # --------------------------------------------------------------------------
6
+ from typing import Any, Dict, List, Optional, TYPE_CHECKING
7
+
8
+ from autorest.codegen.models.imports import FileImport, ImportType
9
+ from .base_type import BaseType
10
+
11
+ if TYPE_CHECKING:
12
+ from .code_model import CodeModel
13
+
14
+
15
+ class CombinedType(BaseType):
16
+ """A type that consists of multiple different types.
17
+
18
+ Used by body parameters that have multiple types, i.e. one that can be
19
+ a stream body or a JSON body.
20
+ """
21
+
22
+ def __init__(
23
+ self, yaml_data: Dict[str, Any], code_model: "CodeModel", types: List[BaseType]
24
+ ) -> None:
25
+ super().__init__(yaml_data, code_model)
26
+ self.types = types # the types that this type is combining
27
+
28
+ @property
29
+ def serialization_type(self) -> str:
30
+ """The tag recognized by 'msrest' as a serialization/deserialization.
31
+
32
+ 'str', 'int', 'float', 'bool' or
33
+ https://github.com/Azure/msrest-for-python/blob/b505e3627b547bd8fdc38327e86c70bdb16df061/msrest/serialization.py#L407-L416
34
+
35
+ or the object schema name (e.g. DotSalmon).
36
+
37
+ If list: '[str]'
38
+ If dict: '{str}'
39
+ """
40
+ ...
41
+
42
+ @property
43
+ def client_default_value(self) -> Any:
44
+ return self.yaml_data.get("clientDefaultValue")
45
+
46
+ def description(
47
+ self, *, is_operation_file: bool # pylint: disable=unused-argument
48
+ ) -> str:
49
+ if len(self.types) == 2:
50
+ return (
51
+ f"Is either a {self.types[0].type} type or a {self.types[1].type} type."
52
+ )
53
+ return (
54
+ f"Is one of the following types: {', '.join([t.type for t in self.types])}"
55
+ )
56
+
57
+ def docstring_text(self, **kwargs: Any) -> str:
58
+ return " or ".join(t.docstring_text(**kwargs) for t in self.types)
59
+
60
+ def docstring_type(self, **kwargs: Any) -> str:
61
+ return " or ".join(t.docstring_type(**kwargs) for t in self.types)
62
+
63
+ def type_annotation(self, **kwargs: Any) -> str:
64
+ """The python type used for type annotation
65
+
66
+ Special case for enum, for instance: Union[str, "EnumName"]
67
+ """
68
+ kwargs["is_operation_file"] = True
69
+ return (
70
+ f'Union[{", ".join(type.type_annotation(**kwargs) for type in self.types)}]'
71
+ )
72
+
73
+ def get_json_template_representation(
74
+ self,
75
+ *,
76
+ optional: bool = True,
77
+ client_default_value_declaration: Optional[str] = None,
78
+ description: Optional[str] = None,
79
+ ) -> Any:
80
+ """Template of what this schema would look like as JSON input"""
81
+ raise ValueError(
82
+ "You shouldn't get a JSON template representation of multiple types"
83
+ )
84
+
85
+ @property
86
+ def instance_check_template(self) -> str:
87
+ """Template of what an instance check of a variable for this type would look like"""
88
+ raise ValueError("You shouldn't do instance checks on a multiple type")
89
+
90
+ def imports(self, **kwargs: Any) -> FileImport:
91
+ file_import = FileImport()
92
+ for type in self.types:
93
+ file_import.merge(type.imports(**kwargs))
94
+ file_import.add_submodule_import("typing", "Union", ImportType.STDLIB)
95
+ return file_import
96
+
97
+ @classmethod
98
+ def from_yaml(
99
+ cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
100
+ ) -> "BaseType":
101
+ from . import build_type
102
+
103
+ return cls(
104
+ yaml_data,
105
+ code_model,
106
+ [build_type(t, code_model) for t in yaml_data["types"]],
107
+ )