@autorest/python 5.14.0 → 5.15.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 (58) hide show
  1. package/ChangeLog.md +29 -0
  2. package/autorest/codegen/__init__.py +87 -47
  3. package/autorest/codegen/models/base_schema.py +2 -6
  4. package/autorest/codegen/models/client.py +6 -0
  5. package/autorest/codegen/models/code_model.py +40 -74
  6. package/autorest/codegen/models/constant_schema.py +7 -3
  7. package/autorest/codegen/models/credential_model.py +47 -0
  8. package/autorest/codegen/models/credential_schema.py +5 -4
  9. package/autorest/codegen/models/dictionary_schema.py +7 -7
  10. package/autorest/codegen/models/enum_schema.py +8 -39
  11. package/autorest/codegen/models/imports.py +3 -1
  12. package/autorest/codegen/models/list_schema.py +18 -8
  13. package/autorest/codegen/models/lro_operation.py +3 -3
  14. package/autorest/codegen/models/lro_paging_operation.py +3 -3
  15. package/autorest/codegen/models/object_schema.py +17 -13
  16. package/autorest/codegen/models/operation.py +27 -6
  17. package/autorest/codegen/models/operation_group.py +7 -2
  18. package/autorest/codegen/models/paging_operation.py +3 -3
  19. package/autorest/codegen/models/parameter.py +39 -15
  20. package/autorest/codegen/models/parameter_list.py +1 -1
  21. package/autorest/codegen/models/primitive_schemas.py +15 -25
  22. package/autorest/codegen/models/property.py +5 -5
  23. package/autorest/codegen/models/request_builder.py +4 -4
  24. package/autorest/codegen/models/request_builder_parameter.py +12 -5
  25. package/autorest/codegen/models/schema_response.py +23 -10
  26. package/autorest/codegen/models/utils.py +20 -0
  27. package/autorest/codegen/serializers/__init__.py +49 -25
  28. package/autorest/codegen/serializers/builder_serializer.py +79 -37
  29. package/autorest/codegen/serializers/client_serializer.py +16 -6
  30. package/autorest/codegen/serializers/general_serializer.py +24 -3
  31. package/autorest/codegen/serializers/import_serializer.py +1 -1
  32. package/autorest/codegen/serializers/metadata_serializer.py +1 -1
  33. package/autorest/codegen/serializers/model_base_serializer.py +8 -0
  34. package/autorest/codegen/serializers/model_python3_serializer.py +2 -2
  35. package/autorest/codegen/serializers/operation_groups_serializer.py +1 -0
  36. package/autorest/codegen/serializers/patch_serializer.py +12 -3
  37. package/autorest/codegen/serializers/utils.py +29 -4
  38. package/autorest/codegen/templates/config.py.jinja2 +4 -4
  39. package/autorest/codegen/templates/enum.py.jinja2 +1 -1
  40. package/autorest/codegen/templates/enum_container.py.jinja2 +0 -1
  41. package/autorest/codegen/templates/init.py.jinja2 +9 -6
  42. package/autorest/codegen/templates/keywords.jinja2 +14 -1
  43. package/autorest/codegen/templates/lro_operation.py.jinja2 +1 -1
  44. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +1 -1
  45. package/autorest/codegen/templates/metadata.json.jinja2 +3 -3
  46. package/autorest/codegen/templates/model.py.jinja2 +1 -6
  47. package/autorest/codegen/templates/model_init.py.jinja2 +7 -4
  48. package/autorest/codegen/templates/operation.py.jinja2 +2 -3
  49. package/autorest/codegen/templates/operation_group.py.jinja2 +12 -5
  50. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +0 -1
  51. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
  52. package/autorest/codegen/templates/paging_operation.py.jinja2 +1 -1
  53. package/autorest/codegen/templates/patch.py.jinja2 +18 -29
  54. package/autorest/codegen/templates/request_builder.py.jinja2 +4 -6
  55. package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
  56. package/autorest/multiapi/models/imports.py +21 -11
  57. package/autorest/multiapi/serializers/import_serializer.py +3 -1
  58. package/package.json +2 -2
package/ChangeLog.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Change Log
2
2
 
3
+ ### 2022-04-07 - 5.15.0
4
+
5
+ | Library | Min Version |
6
+ | ----------------------------------------------------------------------- | ----------- |
7
+ | `@autorest/core` | `3.6.2` |
8
+ | `@autorest/modelerfour` | `4.19.1` |
9
+ | `azure-core` dep of generated code | `1.23.0` |
10
+ | `msrest` dep of generated code | `0.6.21` |
11
+ | `azure-mgmt-core` dep of generated code (If generating mgmt plane code) | `1.3.0` |
12
+
13
+ **New Features**
14
+
15
+ - Add support for security configurations in the swagger. For more information, see https://github.com/Azure/autorest/blob/main/docs/generate/authentication.md #1161
16
+ - Add support for handwritten customizations of generated code. For more information, see https://aka.ms/azsdk/python/dpcodegen/python/customize #1153
17
+ - Allow `header` and `params` as kwargs in operation and request-build function to hand over REST Header and Query parameters case insensitively #1183
18
+
19
+ **Bug Fixes**
20
+
21
+ - Make `--version-tolerant` generated code mypy compatible in the `azure-sdk-for-python` repo. Tested only with the `--black` flag #1185
22
+ - Remove unnecessary vendored code in the `_vendor` file if the SDK has no operations #1196
23
+ - Fix the generation of the root `__init__` files for packages with only models #1195
24
+ - Add pylint and mypy support for `--version-tolerant` generations with `--models-mode=msrest` #1202
25
+
26
+ **Breaking Changes in Version Tolerant Generation**
27
+
28
+ - Change client filenames to `_client.py` #1206
29
+ - Change the models filename from `_models_py3.py` to `_models.py` #1204
30
+ - Change the enums filename to `_enums.py` #1204
31
+
3
32
  ### 2022-03-08 - 5.14.0
4
33
 
5
34
  | Library | Min Version |
@@ -18,7 +18,11 @@ from .models.parameter_list import GlobalParameterList
18
18
  from .models.rest import Rest
19
19
  from .serializers import JinjaSerializer
20
20
  from .models.credential_schema_policy import CredentialSchemaPolicy, get_credential_schema_policy_type
21
- from .models.credential_schema import AzureKeyCredentialSchema, TokenCredentialSchema
21
+ from .models.credential_schema_policy import BearerTokenCredentialPolicy, AzureKeyCredentialPolicy
22
+ from .models.credential_model import CredentialModel
23
+
24
+ _AAD_TYPE = "AADToken"
25
+ _KEY_TYPE = "AzureKey"
22
26
 
23
27
  def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -> None:
24
28
  # Create operations
@@ -32,7 +36,6 @@ def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -
32
36
  code_model.sort_schemas()
33
37
 
34
38
  if code_model.options["show_operations"]:
35
- code_model.add_schema_link_to_operation()
36
39
  code_model.generate_single_parameter_from_multiple_content_types_operation()
37
40
  code_model.link_operation_to_request_builder()
38
41
  # LRO operation
@@ -92,6 +95,12 @@ def _validate_code_model_options(options: Dict[str, Any]) -> None:
92
95
  "Please remove --reformat-next-link from your call for version tolerant generations."
93
96
  )
94
97
 
98
+ if options["multiapi"] and options["version_tolerant"]:
99
+ raise ValueError(
100
+ "Can not currently generate version tolerant multiapi SDKs. "
101
+ "We are working on creating a new multiapi SDK for version tolerant and it is not available yet."
102
+ )
103
+
95
104
  _LOGGER = logging.getLogger(__name__)
96
105
  class CodeGenerator(Plugin):
97
106
  @staticmethod
@@ -131,32 +140,53 @@ class CodeGenerator(Plugin):
131
140
  def _build_package_dependency() -> Dict[str, str]:
132
141
  return {
133
142
  "dependency_azure_mgmt_core": "azure-mgmt-core<2.0.0,>=1.3.0",
134
- "dependency_azure_core": "azure-core<2.0.0,>=1.20.1",
143
+ "dependency_azure_core": "azure-core<2.0.0,>=1.23.0",
135
144
  "dependency_msrest": "msrest>=0.6.21",
136
145
  }
137
146
 
147
+ @staticmethod
148
+ def _build_with_security_definition(yaml_data: Dict[str, Any], credential_model: CredentialModel):
149
+ security_yaml = yaml_data.get("security", {})
150
+ if security_yaml.get("authenticationRequired"):
151
+ for scheme in security_yaml.get("schemes"):
152
+ if _AAD_TYPE == scheme["type"]:
153
+ credential_model.credential_scopes.update(scheme["scopes"])
154
+ elif _KEY_TYPE == scheme["type"]:
155
+ # only accept the last one
156
+ credential_model.key_header_name = scheme["headerName"]
157
+
158
+ if credential_model.credential_scopes:
159
+ credential_model.policy_type = BearerTokenCredentialPolicy
160
+ elif credential_model.key_header_name:
161
+ credential_model.policy_type = AzureKeyCredentialPolicy
162
+
163
+ @staticmethod
164
+ def _build_credential_model(code_model: CodeModel, credential_model: CredentialModel):
165
+ if credential_model.policy_type:
166
+ code_model.options["credential"] = True
167
+ credential_model.build_authentication_policy()
168
+ code_model.credential_model = credential_model
169
+
170
+ def _handle_credential_model(self, yaml_data: Dict[str, Any], code_model: CodeModel):
171
+ credential_model = CredentialModel(code_model.options["azure_arm"])
172
+
173
+ # credential info with security definition will be overridded by credential flags
174
+ self._build_with_security_definition(yaml_data, credential_model)
175
+ self._build_with_credential_flags(code_model, credential_model)
176
+
177
+ self._build_credential_model(code_model, credential_model)
178
+
138
179
  def _create_code_model(self, yaml_data: Dict[str, Any], options: Dict[str, Union[str, bool]]) -> CodeModel:
139
180
  # Create a code model
140
181
 
141
182
  code_model = CodeModel(options=options)
142
- if code_model.options['credential']:
143
- self._handle_default_authentication_policy(code_model)
183
+ self._handle_credential_model(yaml_data, code_model)
144
184
  code_model.module_name = yaml_data["info"]["python_title"]
145
185
  code_model.class_name = yaml_data["info"]["pascal_case_title"]
146
186
  code_model.description = (
147
187
  yaml_data["info"]["description"] if yaml_data["info"].get("description") else ""
148
188
  )
149
189
 
150
- # Global parameters
151
- code_model.global_parameters = GlobalParameterList(
152
- code_model,
153
- [Parameter.from_yaml(param, code_model=code_model) for param in yaml_data.get("globalParameters", [])],
154
- )
155
- code_model.global_parameters.code_model = code_model
156
-
157
- # Custom URL
158
- code_model.setup_client_input_parameters(yaml_data)
159
-
160
190
  # Get my namespace
161
191
  namespace = self._autorestapi.get_value("namespace")
162
192
  _LOGGER.debug("Namespace parameter was %s", namespace)
@@ -164,16 +194,24 @@ class CodeGenerator(Plugin):
164
194
  namespace = yaml_data["info"]["python_title"]
165
195
  code_model.namespace = namespace
166
196
 
167
- code_model.rest = Rest.from_yaml(yaml_data, code_model=code_model)
168
197
  if yaml_data.get("schemas"):
169
198
  exceptions_set = CodeGenerator._build_exceptions_set(yaml_data=yaml_data["operationGroups"])
170
199
 
171
200
  for type_list in yaml_data["schemas"].values():
172
201
  for schema in type_list:
173
202
  build_schema(yaml_data=schema, exceptions_set=exceptions_set, code_model=code_model)
174
- code_model.add_schema_link_to_request_builder()
175
- code_model.add_schema_link_to_global_parameters()
176
203
 
204
+ # Global parameters
205
+ code_model.global_parameters = GlobalParameterList(
206
+ code_model,
207
+ [Parameter.from_yaml(param, code_model=code_model) for param in yaml_data.get("globalParameters", [])],
208
+ )
209
+ code_model.global_parameters.code_model = code_model
210
+
211
+ # Custom URL
212
+ code_model.setup_client_input_parameters(yaml_data)
213
+
214
+ code_model.rest = Rest.from_yaml(yaml_data, code_model=code_model)
177
215
  _build_convenience_layer(yaml_data=yaml_data, code_model=code_model)
178
216
 
179
217
  if options["credential"]:
@@ -196,9 +234,13 @@ class CodeGenerator(Plugin):
196
234
  )
197
235
  return credential_scopes
198
236
 
199
- def _initialize_credential_schema_policy(
200
- self, code_model: CodeModel, credential_schema_policy: Type[CredentialSchemaPolicy]
201
- ) -> CredentialSchemaPolicy:
237
+ def _update_with_credential_flags(
238
+ self,
239
+ code_model: CodeModel,
240
+ credential_schema_policy: Type[CredentialSchemaPolicy],
241
+ credential_model: CredentialModel
242
+ ):
243
+ credential_model.policy_type = credential_schema_policy
202
244
  credential_scopes = self._get_credential_scopes(code_model.options['credential'])
203
245
  credential_key_header_name = self._autorestapi.get_value('credential-key-header-name')
204
246
  azure_arm = code_model.options['azure_arm']
@@ -227,38 +269,36 @@ class CodeGenerator(Plugin):
227
269
  "name is tied with AzureKeyCredentialPolicy. Instead, with this policy it is recommend you "
228
270
  "pass in --credential-scopes."
229
271
  )
230
- return credential_schema_policy(
231
- credential=TokenCredentialSchema(async_mode=False),
232
- credential_scopes=credential_scopes,
233
- )
234
- # currently the only other credential policy is AzureKeyCredentialPolicy
235
- if credential_scopes:
236
- raise ValueError(
237
- "You have passed in credential scopes with default credential policy type "
238
- "AzureKeyCredentialPolicy. This is not allowed, since credential scopes is tied with "
239
- f"{code_model.default_authentication_policy.name()}. Instead, with this policy you must pass in "
240
- "--credential-key-header-name."
241
- )
242
- if not credential_key_header_name:
243
- credential_key_header_name = "api-key"
244
- _LOGGER.info(
245
- "Defaulting the AzureKeyCredentialPolicy header's name to 'api-key'"
246
- )
247
- return credential_schema_policy(
248
- credential=AzureKeyCredentialSchema(),
249
- credential_key_header_name=credential_key_header_name,
250
- )
272
+ credential_model.credential_scopes = set(credential_scopes)
273
+ else:
274
+ # currently the only other credential policy is AzureKeyCredentialPolicy
275
+ if credential_scopes:
276
+ raise ValueError(
277
+ "You have passed in credential scopes with default credential policy type "
278
+ "AzureKeyCredentialPolicy. This is not allowed, since credential scopes is tied with "
279
+ f"{credential_model.default_authentication_policy.name()}. Instead, with this policy "
280
+ "you must pass in --credential-key-header-name."
281
+ )
282
+ if not credential_key_header_name:
283
+ credential_key_header_name = "api-key"
284
+ _LOGGER.info(
285
+ "Defaulting the AzureKeyCredentialPolicy header's name to 'api-key'"
286
+ )
287
+
288
+ credential_model.key_header_name = credential_key_header_name
289
+
290
+ def _build_with_credential_flags(self, code_model: CodeModel, credential_model: CredentialModel):
291
+ if not code_model.options["credential"]:
292
+ return
251
293
 
252
- def _handle_default_authentication_policy(self, code_model: CodeModel):
253
294
  credential_schema_policy_name = (
254
295
  self._autorestapi.get_value("credential-default-policy-type") or
255
- code_model.default_authentication_policy.name()
296
+ credential_model.default_authentication_policy.name()
256
297
  )
257
298
  credential_schema_policy_type = get_credential_schema_policy_type(credential_schema_policy_name)
258
- credential_schema_policy = self._initialize_credential_schema_policy(
259
- code_model, credential_schema_policy_type
299
+ self._update_with_credential_flags(
300
+ code_model, credential_schema_policy_type, credential_model
260
301
  )
261
- code_model.credential_schema_policy = credential_schema_policy
262
302
 
263
303
  def _build_code_model_options(self) -> Dict[str, Any]:
264
304
  """Build en options dict from the user input while running autorest.
@@ -90,18 +90,14 @@ class BaseSchema(BaseModel, ABC):
90
90
  """
91
91
  ...
92
92
 
93
- @property
94
- def type_annotation(self) -> str:
93
+ @abstractmethod
94
+ def type_annotation(self, *, is_operation_file: bool = False) -> str:
95
95
  """The python type used for type annotation
96
96
 
97
97
  Special case for enum, for instance: Union[str, "EnumName"]
98
98
  """
99
99
  ...
100
100
 
101
- @property
102
- def operation_type_annotation(self) -> str:
103
- return self.type_annotation
104
-
105
101
  def get_declaration(self, value: Any) -> str: # pylint: disable=no-self-use
106
102
  """Return the current value from YAML as a Python string that represents the constant.
107
103
 
@@ -102,3 +102,9 @@ class Client:
102
102
  def send_request_signature(self, is_python3_file: bool) -> List[str]:
103
103
  request_signature = ["request: HttpRequest," if is_python3_file else "request, # type: HttpRequest"]
104
104
  return request_signature + self.parameters.method_signature_kwargs(is_python3_file)
105
+
106
+ @property
107
+ def filename(self) -> str:
108
+ if self.code_model.options["version_tolerant"] or self.code_model.options["low_level_client"]:
109
+ return "_client"
110
+ return f"_{self.code_model.module_name}"
@@ -3,14 +3,10 @@
3
3
  # Licensed under the MIT License. See License.txt in the project root for
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
- from itertools import chain
7
6
  import logging
8
- from typing import cast, List, Dict, Optional, Any, Set, Type
7
+ from typing import cast, List, Dict, Optional, Any, Set
9
8
 
10
9
  from .base_schema import BaseSchema
11
- from .credential_schema_policy import (
12
- ARMChallengeAuthenticationPolicy, BearerTokenCredentialPolicy, CredentialSchemaPolicy
13
- )
14
10
  from .enum_schema import EnumSchema
15
11
  from .object_schema import ObjectSchema
16
12
  from .operation_group import OperationGroup
@@ -20,12 +16,10 @@ from .paging_operation import PagingOperation
20
16
  from .parameter import Parameter
21
17
  from .client import Client
22
18
  from .parameter_list import GlobalParameterList
23
- from .schema_response import SchemaResponse
24
19
  from .property import Property
25
- from .primitive_schemas import IOSchema
26
20
  from .request_builder import RequestBuilder
27
21
  from .rest import Rest
28
-
22
+ from .credential_model import CredentialModel
29
23
 
30
24
  _LOGGER = logging.getLogger(__name__)
31
25
 
@@ -53,6 +47,8 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
53
47
  :type operation_groups: list[~autorest.models.OperationGroup]
54
48
  :param package_dependency: All the dependencies needed in setup.py
55
49
  :type package_dependency: Dict[str, str]
50
+ :param credential_model: The class contains all the credential info
51
+ :type credential_model: CredentialMode
56
52
  """
57
53
 
58
54
  def __init__(
@@ -77,8 +73,8 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
77
73
  self.service_client: Client = Client(self, params)
78
74
  self._rest: Optional[Rest] = None
79
75
  self.request_builder_ids: Dict[int, RequestBuilder] = {}
80
- self._credential_schema_policy: Optional[CredentialSchemaPolicy] = None
81
76
  self.package_dependency: Dict[str, str] = {}
77
+ self._credential_model: Optional[CredentialModel] = None
82
78
 
83
79
  @property
84
80
  def global_parameters(self) -> GlobalParameterList:
@@ -211,18 +207,14 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
211
207
  return self.schemas or self.enums
212
208
 
213
209
  @property
214
- def default_authentication_policy(self) -> Type[CredentialSchemaPolicy]:
215
- return ARMChallengeAuthenticationPolicy if self.options['azure_arm'] else BearerTokenCredentialPolicy
216
-
217
- @property
218
- def credential_schema_policy(self) -> CredentialSchemaPolicy:
219
- if not self._credential_schema_policy:
220
- raise ValueError("You want to find the Credential Schema Policy, but have not given a value")
221
- return self._credential_schema_policy
210
+ def credential_model(self) -> CredentialModel:
211
+ if not self._credential_model:
212
+ raise ValueError("You want to find the Credential Model, but have not given a value")
213
+ return self._credential_model
222
214
 
223
- @credential_schema_policy.setter
224
- def credential_schema_policy(self, val: CredentialSchemaPolicy) -> None:
225
- self._credential_schema_policy = val
215
+ @credential_model.setter
216
+ def credential_model(self, val: CredentialModel) -> None:
217
+ self._credential_model = val
226
218
 
227
219
  @staticmethod
228
220
  def _add_properties_from_inheritance_helper(schema, properties) -> List[Property]:
@@ -303,74 +295,33 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
303
295
  return
304
296
  raise KeyError("Didn't find the target property")
305
297
 
306
- def _populate_schema(self, obj: Any) -> None:
307
- schema_obj = obj.schema
308
- if schema_obj and not isinstance(schema_obj, dict):
309
- return
310
-
311
- if schema_obj:
312
- schema_obj_id = id(obj.schema)
313
- _LOGGER.debug("Looking for id %s for member %s", schema_obj_id, obj)
314
- try:
315
- obj.schema = self.lookup_schema(schema_obj_id)
316
- except KeyError:
317
- _LOGGER.critical("Unable to ref the object")
318
- raise
319
- if isinstance(obj, Parameter) and obj.target_property_name:
320
- self._populate_target_property(obj)
321
- if isinstance(obj, SchemaResponse) and obj.is_stream_response:
322
- obj.schema = IOSchema(namespace=None, yaml_data={})
323
-
324
- def add_schema_link_to_operation(self) -> None:
325
- """Puts created schemas into operation classes `schema` property
326
-
327
- :return: None
328
- :rtype: None
329
- """
330
- # Index schemas
331
- for operation_group in self.operation_groups:
332
- for operation in operation_group.operations:
333
- for obj in chain(
334
- operation.parameters,
335
- operation.multiple_content_type_parameters or [],
336
- operation.responses,
337
- operation.exceptions,
338
- chain.from_iterable(response.headers for response in operation.responses),
339
- ):
340
- self._populate_schema(obj)
341
-
342
- def add_schema_link_to_request_builder(self) -> None:
343
- for request_builder in self.rest.request_builders:
344
- for obj in chain(
345
- request_builder.parameters,
346
- chain.from_iterable(request.parameters for request in request_builder.schema_requests),
347
- request_builder.responses,
348
- ):
349
- self._populate_schema(obj)
350
-
351
-
352
- def add_schema_link_to_global_parameters(self) -> None:
353
- for parameter in self.global_parameters:
354
- self._populate_schema(parameter)
355
-
356
298
  def generate_single_parameter_from_multiple_content_types_operation(self) -> None:
357
299
  for operation_group in self.operation_groups:
358
300
  for operation in operation_group.operations:
359
301
  if operation.multiple_content_type_parameters:
360
302
  operation.convert_multiple_content_type_parameters()
361
303
 
362
- @property
363
- def need_vendored_code(self) -> bool:
364
- return self.need_request_converter or self.need_format_url
304
+ def need_vendored_code(self, async_mode: bool) -> bool:
305
+ if async_mode:
306
+ return self.need_mixin_abc
307
+ return self.need_request_converter or self.need_format_url or self.need_mixin_abc
365
308
 
366
309
  @property
367
310
  def need_request_converter(self) -> bool:
368
- return self.options["show_operations"] and not self.options["version_tolerant"]
311
+ return (
312
+ self.options["show_operations"] and
313
+ bool(self.rest.request_builders) and
314
+ not self.options["version_tolerant"]
315
+ )
369
316
 
370
317
  @property
371
318
  def need_format_url(self) -> bool:
372
319
  return any(rq for rq in self.rest.request_builders if rq.parameters.path)
373
320
 
321
+ @property
322
+ def need_mixin_abc(self) -> bool:
323
+ return any(o for o in self.operation_groups if o.is_empty_operation_group and self.options["python3_only"])
324
+
374
325
  @property
375
326
  def has_lro_operations(self) -> bool:
376
327
  return any([
@@ -400,3 +351,18 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
400
351
  request_builder.name = request_builder.name + "_initial"
401
352
  operation.request_builder = request_builder
402
353
  operation.link_body_kwargs_to_body_params()
354
+
355
+ def get_models_filename(self, is_python3_file: bool) -> str:
356
+ if (
357
+ self.options["version_tolerant"] or self.options["low_level_client"]
358
+ ) and self.options["python3_only"]:
359
+ return "_models"
360
+ if is_python3_file:
361
+ return "_models_py3"
362
+ return "_models"
363
+
364
+ @property
365
+ def enums_filename(self) -> str:
366
+ if self.options["version_tolerant"] or self.options["low_level_client"]:
367
+ return "_enums"
368
+ return f"_{self.module_name}_enums"
@@ -60,9 +60,8 @@ class ConstantSchema(BaseSchema):
60
60
  """
61
61
  return self.schema.docstring_type
62
62
 
63
- @property
64
- def type_annotation(self) -> str:
65
- return self.schema.type_annotation
63
+ def type_annotation(self, *, is_operation_file: bool = False) -> str:
64
+ return self.schema.type_annotation(is_operation_file=is_operation_file)
66
65
 
67
66
  @classmethod
68
67
  def from_yaml(cls, namespace: str, yaml_data: Dict[str, Any], **kwargs) -> "ConstantSchema":
@@ -95,3 +94,8 @@ class ConstantSchema(BaseSchema):
95
94
  file_import = FileImport()
96
95
  file_import.merge(self.schema.imports())
97
96
  return file_import
97
+
98
+ def model_file_imports(self) -> FileImport:
99
+ file_import = self.imports()
100
+ file_import.merge(self.schema.model_file_imports())
101
+ return file_import
@@ -0,0 +1,47 @@
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 Set, Optional, Type
7
+ from .credential_schema_policy import CredentialSchemaPolicy, BearerTokenCredentialPolicy
8
+ from .credential_schema_policy import ARMChallengeAuthenticationPolicy
9
+ from .credential_schema import TokenCredentialSchema, AzureKeyCredentialSchema
10
+
11
+
12
+ class CredentialModel:
13
+ """Store info about credential.
14
+ """
15
+
16
+ def __init__(
17
+ self,
18
+ azure_arm: bool
19
+ ) -> None:
20
+ self.azure_arm: bool = azure_arm
21
+ self.credential_scopes: Set[str] = set()
22
+ self.key_header_name: str = ""
23
+ self.policy_type: Optional[Type[CredentialSchemaPolicy]] = None
24
+ self._credential_schema_policy: Optional[CredentialSchemaPolicy] = None
25
+
26
+ @property
27
+ def default_authentication_policy(self) -> Type[CredentialSchemaPolicy]:
28
+ return ARMChallengeAuthenticationPolicy if self.azure_arm else BearerTokenCredentialPolicy
29
+
30
+ @property
31
+ def credential_schema_policy(self) -> CredentialSchemaPolicy:
32
+ if not self._credential_schema_policy:
33
+ raise ValueError(
34
+ "You want to find the Credential Schema Policy, but have not given a value")
35
+ return self._credential_schema_policy
36
+
37
+ def build_authentication_policy(self):
38
+ if hasattr(self.policy_type, "credential_scopes"):
39
+ self._credential_schema_policy = self.policy_type( # pylint: disable=not-callable
40
+ credential=TokenCredentialSchema(async_mode=False),
41
+ credential_scopes=list(self.credential_scopes),
42
+ )
43
+ elif hasattr(self.policy_type, "credential_key_header_name"):
44
+ self._credential_schema_policy = self.policy_type( # pylint: disable=not-callable
45
+ credential=AzureKeyCredentialSchema(),
46
+ credential_key_header_name=self.key_header_name
47
+ )
@@ -11,6 +11,9 @@ class CredentialSchema(BaseSchema):
11
11
  def __init__(self) -> None: # pylint: disable=super-init-not-called
12
12
  self.default_value = None
13
13
 
14
+ def type_annotation(self, *, is_operation_file: bool = False) -> str:
15
+ raise ValueError("Children classes should set their own type annotation")
16
+
14
17
  @property
15
18
  def docstring_type(self) -> str:
16
19
  return self.serialization_type
@@ -38,8 +41,7 @@ class AzureKeyCredentialSchema(CredentialSchema):
38
41
  def serialization_type(self) -> str:
39
42
  return "~azure.core.credentials.AzureKeyCredential"
40
43
 
41
- @property
42
- def type_annotation(self) -> str:
44
+ def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
43
45
  return "AzureKeyCredential"
44
46
 
45
47
  def imports(self) -> FileImport:
@@ -66,8 +68,7 @@ class TokenCredentialSchema(CredentialSchema):
66
68
  return self.async_type
67
69
  return self.sync_type
68
70
 
69
- @property
70
- def type_annotation(self) -> str:
71
+ def type_annotation(self, *, is_operation_file: bool = False) -> str: # pylint: disable=unused-argument
71
72
  if self.async_mode:
72
73
  return '"AsyncTokenCredential"'
73
74
  return '"TokenCredential"'
@@ -34,18 +34,13 @@ class DictionarySchema(BaseSchema):
34
34
  """
35
35
  return f"{{{self.element_type.serialization_type}}}"
36
36
 
37
- @property
38
- def type_annotation(self) -> str:
37
+ def type_annotation(self, *, is_operation_file: bool = False) -> str:
39
38
  """The python type used for type annotation
40
39
 
41
40
  :return: The type annotation for this schema
42
41
  :rtype: str
43
42
  """
44
- return f"Dict[str, {self.element_type.type_annotation}]"
45
-
46
- @property
47
- def operation_type_annotation(self) -> str:
48
- return f"Dict[str, {self.element_type.operation_type_annotation}]"
43
+ return f"Dict[str, {self.element_type.type_annotation(is_operation_file=is_operation_file)}]"
49
44
 
50
45
  @property
51
46
  def docstring_text(self) -> str:
@@ -101,3 +96,8 @@ class DictionarySchema(BaseSchema):
101
96
  file_import.add_submodule_import("typing", "Dict", ImportType.STDLIB, TypingSection.CONDITIONAL)
102
97
  file_import.merge(self.element_type.imports())
103
98
  return file_import
99
+
100
+ def model_file_imports(self) -> FileImport:
101
+ file_import = self.imports()
102
+ file_import.merge(self.element_type.model_file_imports())
103
+ return file_import