@autorest/python 5.12.6 → 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 (69) hide show
  1. package/ChangeLog.md +205 -125
  2. package/autorest/black/__init__.py +3 -0
  3. package/autorest/codegen/__init__.py +120 -48
  4. package/autorest/codegen/models/__init__.py +2 -1
  5. package/autorest/codegen/models/base_schema.py +2 -6
  6. package/autorest/codegen/models/client.py +6 -0
  7. package/autorest/codegen/models/code_model.py +43 -74
  8. package/autorest/codegen/models/constant_schema.py +7 -7
  9. package/autorest/codegen/models/credential_model.py +47 -0
  10. package/autorest/codegen/models/credential_schema.py +5 -4
  11. package/autorest/codegen/models/dictionary_schema.py +7 -7
  12. package/autorest/codegen/models/enum_schema.py +8 -39
  13. package/autorest/codegen/models/imports.py +3 -1
  14. package/autorest/codegen/models/list_schema.py +18 -8
  15. package/autorest/codegen/models/lro_operation.py +3 -3
  16. package/autorest/codegen/models/lro_paging_operation.py +3 -3
  17. package/autorest/codegen/models/object_schema.py +17 -13
  18. package/autorest/codegen/models/operation.py +38 -10
  19. package/autorest/codegen/models/operation_group.py +7 -2
  20. package/autorest/codegen/models/paging_operation.py +3 -3
  21. package/autorest/codegen/models/parameter.py +71 -22
  22. package/autorest/codegen/models/parameter_list.py +11 -5
  23. package/autorest/codegen/models/primitive_schemas.py +15 -25
  24. package/autorest/codegen/models/property.py +5 -5
  25. package/autorest/codegen/models/request_builder.py +4 -4
  26. package/autorest/codegen/models/request_builder_parameter.py +17 -5
  27. package/autorest/codegen/models/schema_response.py +23 -10
  28. package/autorest/codegen/models/utils.py +20 -0
  29. package/autorest/codegen/serializers/__init__.py +184 -87
  30. package/autorest/codegen/serializers/builder_serializer.py +113 -47
  31. package/autorest/codegen/serializers/client_serializer.py +16 -6
  32. package/autorest/codegen/serializers/general_serializer.py +28 -4
  33. package/autorest/codegen/serializers/import_serializer.py +1 -1
  34. package/autorest/codegen/serializers/metadata_serializer.py +1 -1
  35. package/autorest/codegen/serializers/model_base_serializer.py +8 -0
  36. package/autorest/codegen/serializers/model_python3_serializer.py +2 -2
  37. package/autorest/codegen/serializers/operation_groups_serializer.py +1 -0
  38. package/autorest/codegen/serializers/patch_serializer.py +12 -3
  39. package/autorest/codegen/serializers/utils.py +29 -4
  40. package/autorest/codegen/templates/CHANGELOG.md.jinja2 +6 -0
  41. package/autorest/codegen/templates/LICENSE.jinja2 +21 -0
  42. package/autorest/codegen/templates/MANIFEST.in.jinja2 +7 -0
  43. package/autorest/codegen/templates/README.md.jinja2 +105 -0
  44. package/autorest/codegen/templates/config.py.jinja2 +4 -4
  45. package/autorest/codegen/templates/dev_requirements.txt.jinja2 +10 -0
  46. package/autorest/codegen/templates/enum.py.jinja2 +1 -1
  47. package/autorest/codegen/templates/enum_container.py.jinja2 +0 -1
  48. package/autorest/codegen/templates/init.py.jinja2 +9 -6
  49. package/autorest/codegen/templates/keywords.jinja2 +14 -1
  50. package/autorest/codegen/templates/lro_operation.py.jinja2 +1 -1
  51. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +1 -1
  52. package/autorest/codegen/templates/metadata.json.jinja2 +3 -3
  53. package/autorest/codegen/templates/model.py.jinja2 +1 -6
  54. package/autorest/codegen/templates/model_init.py.jinja2 +7 -4
  55. package/autorest/codegen/templates/operation.py.jinja2 +2 -3
  56. package/autorest/codegen/templates/operation_group.py.jinja2 +20 -17
  57. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +0 -1
  58. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
  59. package/autorest/codegen/templates/paging_operation.py.jinja2 +1 -1
  60. package/autorest/codegen/templates/patch.py.jinja2 +18 -29
  61. package/autorest/codegen/templates/request_builder.py.jinja2 +4 -6
  62. package/autorest/codegen/templates/setup.py.jinja2 +79 -20
  63. package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
  64. package/autorest/multiapi/models/imports.py +21 -11
  65. package/autorest/multiapi/serializers/import_serializer.py +3 -1
  66. package/autorest/namer/name_converter.py +1 -1
  67. package/package.json +2 -2
  68. package/run-python3.js +1 -7
  69. package/venvtools.py +2 -2
@@ -6,6 +6,7 @@
6
6
  import logging
7
7
  import sys
8
8
  from typing import Dict, Any, Set, Union, List, Type
9
+ from pathlib import Path
9
10
  import yaml
10
11
 
11
12
  from .. import Plugin
@@ -17,7 +18,11 @@ from .models.parameter_list import GlobalParameterList
17
18
  from .models.rest import Rest
18
19
  from .serializers import JinjaSerializer
19
20
  from .models.credential_schema_policy import CredentialSchemaPolicy, get_credential_schema_policy_type
20
- 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"
21
26
 
22
27
  def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -> None:
23
28
  # Create operations
@@ -31,7 +36,6 @@ def _build_convenience_layer(yaml_data: Dict[str, Any], code_model: CodeModel) -
31
36
  code_model.sort_schemas()
32
37
 
33
38
  if code_model.options["show_operations"]:
34
- code_model.add_schema_link_to_operation()
35
39
  code_model.generate_single_parameter_from_multiple_content_types_operation()
36
40
  code_model.link_operation_to_request_builder()
37
41
  # LRO operation
@@ -70,12 +74,33 @@ def _validate_code_model_options(options: Dict[str, Any]) -> None:
70
74
  if options["basic_setup_py"] and not options["package_version"]:
71
75
  raise ValueError("--basic-setup-py must be used with --package-version")
72
76
 
77
+ if options["package_mode"] and not options["package_version"]:
78
+ raise ValueError("--package-mode must be used with --package-version")
79
+
73
80
  if not options["show_operations"] and options["combine_operation_files"]:
74
81
  raise ValueError(
75
82
  "Can not combine operation files if you are not showing operations. "
76
83
  "If you want operation files, pass in flag --show-operations"
77
84
  )
78
85
 
86
+ if options["package_mode"]:
87
+ if options["package_mode"] not in ("mgmtplane", "dataplane") and not Path(options["package_mode"]).exists():
88
+ raise ValueError(
89
+ "--package-mode can only be 'mgmtplane' or 'dataplane' or directory which contains template files"
90
+ )
91
+
92
+ if options["reformat_next_link"] and options["version_tolerant"]:
93
+ raise ValueError(
94
+ "--reformat-next-link can not be true for version tolerant generations. "
95
+ "Please remove --reformat-next-link from your call for version tolerant generations."
96
+ )
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
+
79
104
  _LOGGER = logging.getLogger(__name__)
80
105
  class CodeGenerator(Plugin):
81
106
  @staticmethod
@@ -111,28 +136,57 @@ class CodeGenerator(Plugin):
111
136
  exceptions_set.add(id(exception["schema"]))
112
137
  return exceptions_set
113
138
 
139
+ @staticmethod
140
+ def _build_package_dependency() -> Dict[str, str]:
141
+ return {
142
+ "dependency_azure_mgmt_core": "azure-mgmt-core<2.0.0,>=1.3.0",
143
+ "dependency_azure_core": "azure-core<2.0.0,>=1.23.0",
144
+ "dependency_msrest": "msrest>=0.6.21",
145
+ }
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
+
114
179
  def _create_code_model(self, yaml_data: Dict[str, Any], options: Dict[str, Union[str, bool]]) -> CodeModel:
115
180
  # Create a code model
116
181
 
117
182
  code_model = CodeModel(options=options)
118
- if code_model.options['credential']:
119
- self._handle_default_authentication_policy(code_model)
183
+ self._handle_credential_model(yaml_data, code_model)
120
184
  code_model.module_name = yaml_data["info"]["python_title"]
121
185
  code_model.class_name = yaml_data["info"]["pascal_case_title"]
122
186
  code_model.description = (
123
187
  yaml_data["info"]["description"] if yaml_data["info"].get("description") else ""
124
188
  )
125
189
 
126
- # Global parameters
127
- code_model.global_parameters = GlobalParameterList(
128
- code_model,
129
- [Parameter.from_yaml(param, code_model=code_model) for param in yaml_data.get("globalParameters", [])],
130
- )
131
- code_model.global_parameters.code_model = code_model
132
-
133
- # Custom URL
134
- code_model.setup_client_input_parameters(yaml_data)
135
-
136
190
  # Get my namespace
137
191
  namespace = self._autorestapi.get_value("namespace")
138
192
  _LOGGER.debug("Namespace parameter was %s", namespace)
@@ -140,21 +194,30 @@ class CodeGenerator(Plugin):
140
194
  namespace = yaml_data["info"]["python_title"]
141
195
  code_model.namespace = namespace
142
196
 
143
- code_model.rest = Rest.from_yaml(yaml_data, code_model=code_model)
144
197
  if yaml_data.get("schemas"):
145
198
  exceptions_set = CodeGenerator._build_exceptions_set(yaml_data=yaml_data["operationGroups"])
146
199
 
147
200
  for type_list in yaml_data["schemas"].values():
148
201
  for schema in type_list:
149
202
  build_schema(yaml_data=schema, exceptions_set=exceptions_set, code_model=code_model)
150
- code_model.add_schema_link_to_request_builder()
151
- code_model.add_schema_link_to_global_parameters()
152
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)
153
215
  _build_convenience_layer(yaml_data=yaml_data, code_model=code_model)
154
216
 
155
217
  if options["credential"]:
156
218
  code_model.global_parameters.add_credential_global_parameter()
157
219
 
220
+ code_model.package_dependency = self._build_package_dependency()
158
221
  return code_model
159
222
 
160
223
  def _get_credential_scopes(self, credential):
@@ -171,9 +234,13 @@ class CodeGenerator(Plugin):
171
234
  )
172
235
  return credential_scopes
173
236
 
174
- def _initialize_credential_schema_policy(
175
- self, code_model: CodeModel, credential_schema_policy: Type[CredentialSchemaPolicy]
176
- ) -> 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
177
244
  credential_scopes = self._get_credential_scopes(code_model.options['credential'])
178
245
  credential_key_header_name = self._autorestapi.get_value('credential-key-header-name')
179
246
  azure_arm = code_model.options['azure_arm']
@@ -202,38 +269,36 @@ class CodeGenerator(Plugin):
202
269
  "name is tied with AzureKeyCredentialPolicy. Instead, with this policy it is recommend you "
203
270
  "pass in --credential-scopes."
204
271
  )
205
- return credential_schema_policy(
206
- credential=TokenCredentialSchema(async_mode=False),
207
- credential_scopes=credential_scopes,
208
- )
209
- # currently the only other credential policy is AzureKeyCredentialPolicy
210
- if credential_scopes:
211
- raise ValueError(
212
- "You have passed in credential scopes with default credential policy type "
213
- "AzureKeyCredentialPolicy. This is not allowed, since credential scopes is tied with "
214
- f"{code_model.default_authentication_policy.name()}. Instead, with this policy you must pass in "
215
- "--credential-key-header-name."
216
- )
217
- if not credential_key_header_name:
218
- credential_key_header_name = "api-key"
219
- _LOGGER.info(
220
- "Defaulting the AzureKeyCredentialPolicy header's name to 'api-key'"
221
- )
222
- return credential_schema_policy(
223
- credential=AzureKeyCredentialSchema(),
224
- credential_key_header_name=credential_key_header_name,
225
- )
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
226
293
 
227
- def _handle_default_authentication_policy(self, code_model: CodeModel):
228
294
  credential_schema_policy_name = (
229
295
  self._autorestapi.get_value("credential-default-policy-type") or
230
- code_model.default_authentication_policy.name()
296
+ credential_model.default_authentication_policy.name()
231
297
  )
232
298
  credential_schema_policy_type = get_credential_schema_policy_type(credential_schema_policy_name)
233
- credential_schema_policy = self._initialize_credential_schema_policy(
234
- code_model, credential_schema_policy_type
299
+ self._update_with_credential_flags(
300
+ code_model, credential_schema_policy_type, credential_model
235
301
  )
236
- code_model.credential_schema_policy = credential_schema_policy
237
302
 
238
303
  def _build_code_model_options(self) -> Dict[str, Any]:
239
304
  """Build en options dict from the user input while running autorest.
@@ -289,6 +354,13 @@ class CodeGenerator(Plugin):
289
354
  "low_level_client": low_level_client,
290
355
  "combine_operation_files": self._autorestapi.get_boolean_value("combine-operation-files", version_tolerant),
291
356
  "python3_only": python3_only,
357
+ "package_mode": self._autorestapi.get_value("package-mode"),
358
+ "package_pprint_name": self._autorestapi.get_value("package-pprint-name"),
359
+ "package_configuration": self._autorestapi.get_value("package-configuration"),
360
+ "default_optional_constants_to_none": self._autorestapi.get_boolean_value(
361
+ "default-optional-constants-to-none", low_level_client or version_tolerant
362
+ ),
363
+ "reformat_next_link": self._autorestapi.get_boolean_value("reformat-next-link", not version_tolerant)
292
364
  }
293
365
 
294
366
  if options["builders_visibility"] is None:
@@ -327,8 +399,8 @@ class CodeGenerator(Plugin):
327
399
 
328
400
  code_model = self._create_code_model(yaml_data=yaml_data, options=options)
329
401
 
330
- serializer = JinjaSerializer(self._autorestapi)
331
- serializer.serialize(code_model)
402
+ serializer = JinjaSerializer(self._autorestapi, code_model)
403
+ serializer.serialize()
332
404
 
333
405
  return True
334
406
 
@@ -17,7 +17,7 @@ from .constant_schema import ConstantSchema
17
17
  from .imports import FileImport, ImportType, TypingSection
18
18
  from .lro_operation import LROOperation
19
19
  from .paging_operation import PagingOperation
20
- from .parameter import Parameter, ParameterStyle
20
+ from .parameter import Parameter, ParameterStyle, ParameterLocation
21
21
  from .operation import Operation
22
22
  from .property import Property
23
23
  from .operation_group import OperationGroup
@@ -50,6 +50,7 @@ __all__ = [
50
50
  "PagingOperation",
51
51
  "Parameter",
52
52
  "ParameterList",
53
+ "ParameterLocation",
53
54
  "OperationGroup",
54
55
  "Property",
55
56
  "RequestBuilder",
@@ -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
 
@@ -51,6 +45,10 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
51
45
  :type primitives: Dict[int, ~autorest.models.BaseSchema]
52
46
  :param operation_groups: The operation groups we are going to serialize
53
47
  :type operation_groups: list[~autorest.models.OperationGroup]
48
+ :param package_dependency: All the dependencies needed in setup.py
49
+ :type package_dependency: Dict[str, str]
50
+ :param credential_model: The class contains all the credential info
51
+ :type credential_model: CredentialMode
54
52
  """
55
53
 
56
54
  def __init__(
@@ -75,7 +73,8 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
75
73
  self.service_client: Client = Client(self, params)
76
74
  self._rest: Optional[Rest] = None
77
75
  self.request_builder_ids: Dict[int, RequestBuilder] = {}
78
- self._credential_schema_policy: Optional[CredentialSchemaPolicy] = None
76
+ self.package_dependency: Dict[str, str] = {}
77
+ self._credential_model: Optional[CredentialModel] = None
79
78
 
80
79
  @property
81
80
  def global_parameters(self) -> GlobalParameterList:
@@ -208,18 +207,14 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
208
207
  return self.schemas or self.enums
209
208
 
210
209
  @property
211
- def default_authentication_policy(self) -> Type[CredentialSchemaPolicy]:
212
- return ARMChallengeAuthenticationPolicy if self.options['azure_arm'] else BearerTokenCredentialPolicy
213
-
214
- @property
215
- def credential_schema_policy(self) -> CredentialSchemaPolicy:
216
- if not self._credential_schema_policy:
217
- raise ValueError("You want to find the Credential Schema Policy, but have not given a value")
218
- 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
219
214
 
220
- @credential_schema_policy.setter
221
- def credential_schema_policy(self, val: CredentialSchemaPolicy) -> None:
222
- self._credential_schema_policy = val
215
+ @credential_model.setter
216
+ def credential_model(self, val: CredentialModel) -> None:
217
+ self._credential_model = val
223
218
 
224
219
  @staticmethod
225
220
  def _add_properties_from_inheritance_helper(schema, properties) -> List[Property]:
@@ -300,74 +295,33 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
300
295
  return
301
296
  raise KeyError("Didn't find the target property")
302
297
 
303
- def _populate_schema(self, obj: Any) -> None:
304
- schema_obj = obj.schema
305
- if schema_obj and not isinstance(schema_obj, dict):
306
- return
307
-
308
- if schema_obj:
309
- schema_obj_id = id(obj.schema)
310
- _LOGGER.debug("Looking for id %s for member %s", schema_obj_id, obj)
311
- try:
312
- obj.schema = self.lookup_schema(schema_obj_id)
313
- except KeyError:
314
- _LOGGER.critical("Unable to ref the object")
315
- raise
316
- if isinstance(obj, Parameter) and obj.target_property_name:
317
- self._populate_target_property(obj)
318
- if isinstance(obj, SchemaResponse) and obj.is_stream_response:
319
- obj.schema = IOSchema(namespace=None, yaml_data={})
320
-
321
- def add_schema_link_to_operation(self) -> None:
322
- """Puts created schemas into operation classes `schema` property
323
-
324
- :return: None
325
- :rtype: None
326
- """
327
- # Index schemas
328
- for operation_group in self.operation_groups:
329
- for operation in operation_group.operations:
330
- for obj in chain(
331
- operation.parameters,
332
- operation.multiple_content_type_parameters or [],
333
- operation.responses,
334
- operation.exceptions,
335
- chain.from_iterable(response.headers for response in operation.responses),
336
- ):
337
- self._populate_schema(obj)
338
-
339
- def add_schema_link_to_request_builder(self) -> None:
340
- for request_builder in self.rest.request_builders:
341
- for obj in chain(
342
- request_builder.parameters,
343
- chain.from_iterable(request.parameters for request in request_builder.schema_requests),
344
- request_builder.responses,
345
- ):
346
- self._populate_schema(obj)
347
-
348
-
349
- def add_schema_link_to_global_parameters(self) -> None:
350
- for parameter in self.global_parameters:
351
- self._populate_schema(parameter)
352
-
353
298
  def generate_single_parameter_from_multiple_content_types_operation(self) -> None:
354
299
  for operation_group in self.operation_groups:
355
300
  for operation in operation_group.operations:
356
301
  if operation.multiple_content_type_parameters:
357
302
  operation.convert_multiple_content_type_parameters()
358
303
 
359
- @property
360
- def need_vendored_code(self) -> bool:
361
- 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
362
308
 
363
309
  @property
364
310
  def need_request_converter(self) -> bool:
365
- 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
+ )
366
316
 
367
317
  @property
368
318
  def need_format_url(self) -> bool:
369
319
  return any(rq for rq in self.rest.request_builders if rq.parameters.path)
370
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
+
371
325
  @property
372
326
  def has_lro_operations(self) -> bool:
373
327
  return any([
@@ -397,3 +351,18 @@ class CodeModel: # pylint: disable=too-many-instance-attributes, too-many-publi
397
351
  request_builder.name = request_builder.name + "_initial"
398
352
  operation.request_builder = request_builder
399
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"
@@ -39,10 +39,6 @@ class ConstantSchema(BaseSchema):
39
39
  return "None"
40
40
  return self.schema.get_declaration(self.value)
41
41
 
42
- @property
43
- def extra_description_information(self) -> str:
44
- return f"The default value is {self.get_declaration(self.value)}."
45
-
46
42
  @property
47
43
  def serialization_type(self) -> str:
48
44
  """Returns the serialization value for msrest.
@@ -64,9 +60,8 @@ class ConstantSchema(BaseSchema):
64
60
  """
65
61
  return self.schema.docstring_type
66
62
 
67
- @property
68
- def type_annotation(self) -> str:
69
- 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)
70
65
 
71
66
  @classmethod
72
67
  def from_yaml(cls, namespace: str, yaml_data: Dict[str, Any], **kwargs) -> "ConstantSchema":
@@ -99,3 +94,8 @@ class ConstantSchema(BaseSchema):
99
94
  file_import = FileImport()
100
95
  file_import.merge(self.schema.imports())
101
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