@autorest/python 5.13.0 → 5.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/ChangeLog.md +67 -0
  2. package/autorest/__init__.py +1 -2
  3. package/autorest/black/__init__.py +12 -5
  4. package/autorest/codegen/__init__.py +239 -105
  5. package/autorest/codegen/models/__init__.py +29 -18
  6. package/autorest/codegen/models/base_builder.py +48 -11
  7. package/autorest/codegen/models/base_model.py +6 -4
  8. package/autorest/codegen/models/base_schema.py +21 -24
  9. package/autorest/codegen/models/client.py +70 -20
  10. package/autorest/codegen/models/code_model.py +144 -129
  11. package/autorest/codegen/models/constant_schema.py +32 -16
  12. package/autorest/codegen/models/credential_model.py +55 -0
  13. package/autorest/codegen/models/credential_schema.py +21 -16
  14. package/autorest/codegen/models/credential_schema_policy.py +11 -15
  15. package/autorest/codegen/models/dictionary_schema.py +27 -24
  16. package/autorest/codegen/models/enum_schema.py +41 -62
  17. package/autorest/codegen/models/imports.py +72 -41
  18. package/autorest/codegen/models/list_schema.py +40 -18
  19. package/autorest/codegen/models/lro_operation.py +61 -25
  20. package/autorest/codegen/models/lro_paging_operation.py +5 -6
  21. package/autorest/codegen/models/object_schema.py +113 -59
  22. package/autorest/codegen/models/operation.py +251 -111
  23. package/autorest/codegen/models/operation_group.py +67 -32
  24. package/autorest/codegen/models/paging_operation.py +48 -21
  25. package/autorest/codegen/models/parameter.py +182 -90
  26. package/autorest/codegen/models/parameter_list.py +184 -163
  27. package/autorest/codegen/models/primitive_schemas.py +89 -70
  28. package/autorest/codegen/models/property.py +49 -31
  29. package/autorest/codegen/models/request_builder.py +67 -32
  30. package/autorest/codegen/models/request_builder_parameter.py +54 -23
  31. package/autorest/codegen/models/request_builder_parameter_list.py +77 -108
  32. package/autorest/codegen/models/schema_request.py +16 -6
  33. package/autorest/codegen/models/schema_response.py +35 -17
  34. package/autorest/codegen/models/utils.py +24 -1
  35. package/autorest/codegen/serializers/__init__.py +273 -89
  36. package/autorest/codegen/serializers/builder_serializer.py +711 -333
  37. package/autorest/codegen/serializers/client_serializer.py +114 -43
  38. package/autorest/codegen/serializers/general_serializer.py +84 -25
  39. package/autorest/codegen/serializers/import_serializer.py +93 -31
  40. package/autorest/codegen/serializers/metadata_serializer.py +73 -24
  41. package/autorest/codegen/serializers/model_base_serializer.py +42 -14
  42. package/autorest/codegen/serializers/model_generic_serializer.py +1 -4
  43. package/autorest/codegen/serializers/model_init_serializer.py +5 -1
  44. package/autorest/codegen/serializers/model_python3_serializer.py +9 -8
  45. package/autorest/codegen/serializers/operation_groups_serializer.py +20 -8
  46. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  47. package/autorest/codegen/serializers/patch_serializer.py +14 -2
  48. package/autorest/codegen/serializers/{rest_serializer.py → request_builders_serializer.py} +29 -12
  49. package/autorest/codegen/serializers/utils.py +60 -21
  50. package/autorest/codegen/templates/CHANGELOG.md.jinja2 +6 -0
  51. package/autorest/codegen/templates/LICENSE.jinja2 +21 -0
  52. package/autorest/codegen/templates/MANIFEST.in.jinja2 +7 -0
  53. package/autorest/codegen/templates/README.md.jinja2 +105 -0
  54. package/autorest/codegen/templates/config.py.jinja2 +4 -4
  55. package/autorest/codegen/templates/dev_requirements.txt.jinja2 +10 -0
  56. package/autorest/codegen/templates/enum.py.jinja2 +1 -1
  57. package/autorest/codegen/templates/enum_container.py.jinja2 +0 -1
  58. package/autorest/codegen/templates/init.py.jinja2 +9 -6
  59. package/autorest/codegen/templates/keywords.jinja2 +14 -1
  60. package/autorest/codegen/templates/lro_operation.py.jinja2 +5 -7
  61. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +5 -7
  62. package/autorest/codegen/templates/metadata.json.jinja2 +10 -9
  63. package/autorest/codegen/templates/model.py.jinja2 +1 -6
  64. package/autorest/codegen/templates/model_init.py.jinja2 +7 -4
  65. package/autorest/codegen/templates/operation.py.jinja2 +8 -11
  66. package/autorest/codegen/templates/operation_group.py.jinja2 +15 -18
  67. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
  68. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
  69. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  70. package/autorest/codegen/templates/patch.py.jinja2 +18 -29
  71. package/autorest/codegen/templates/request_builder.py.jinja2 +19 -14
  72. package/autorest/codegen/templates/setup.py.jinja2 +79 -20
  73. package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
  74. package/autorest/jsonrpc/__init__.py +7 -12
  75. package/autorest/jsonrpc/localapi.py +4 -3
  76. package/autorest/jsonrpc/server.py +13 -6
  77. package/autorest/jsonrpc/stdstream.py +13 -6
  78. package/autorest/m2r/__init__.py +5 -8
  79. package/autorest/multiapi/__init__.py +24 -14
  80. package/autorest/multiapi/models/client.py +21 -11
  81. package/autorest/multiapi/models/code_model.py +23 -10
  82. package/autorest/multiapi/models/config.py +4 -1
  83. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  84. package/autorest/multiapi/models/global_parameter.py +2 -1
  85. package/autorest/multiapi/models/global_parameters.py +14 -8
  86. package/autorest/multiapi/models/imports.py +35 -18
  87. package/autorest/multiapi/models/mixin_operation.py +5 -5
  88. package/autorest/multiapi/models/operation_group.py +2 -1
  89. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  90. package/autorest/multiapi/serializers/__init__.py +18 -23
  91. package/autorest/multiapi/serializers/import_serializer.py +47 -15
  92. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  93. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +1 -1
  94. package/autorest/multiapi/utils.py +3 -3
  95. package/autorest/namer/__init__.py +2 -4
  96. package/autorest/namer/name_converter.py +200 -103
  97. package/autorest/namer/python_mappings.py +10 -22
  98. package/package.json +3 -3
  99. package/run-python3.js +2 -3
  100. package/venvtools.py +1 -1
  101. package/autorest/codegen/models/rest.py +0 -42
@@ -4,8 +4,10 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  from typing import List
7
+
7
8
  from . import utils
8
9
  from ..models import CodeModel
10
+ from ..models.parameter import ParameterMethodLocation
9
11
 
10
12
 
11
13
  class ClientSerializer:
@@ -32,13 +34,20 @@ class ClientSerializer:
32
34
  )
33
35
 
34
36
  def pop_kwargs_from_signature(self, async_mode: bool) -> List[str]:
35
- return utils.pop_kwargs_from_signature(self.code_model.service_client.parameters.kwargs_to_pop(
36
- async_mode or self.is_python3_file
37
- ))
37
+ return utils.pop_kwargs_from_signature(
38
+ self.code_model.service_client.parameters.kwargs_to_pop(
39
+ async_mode or self.is_python3_file,
40
+ ),
41
+ check_kwarg_dict=False,
42
+ pop_headers_kwarg=utils.PopKwargType.NO,
43
+ pop_params_kwarg=utils.PopKwargType.NO,
44
+ )
38
45
 
39
46
  def class_definition(self, async_mode) -> str:
40
47
  class_name = self.code_model.class_name
41
- has_mixin_og = any(og for og in self.code_model.operation_groups if og.is_empty_operation_group)
48
+ has_mixin_og = any(
49
+ og for og in self.code_model.operation_groups if og.is_empty_operation_group
50
+ )
42
51
  base_class = ""
43
52
  if has_mixin_og:
44
53
  base_class = f"{class_name}OperationsMixin"
@@ -54,12 +63,22 @@ class ClientSerializer:
54
63
  def property_descriptions(self, async_mode: bool) -> List[str]:
55
64
  retval: List[str] = []
56
65
  operations_folder = ".aio.operations." if async_mode else ".operations."
57
- for og in [og for og in self.code_model.operation_groups if not og.is_empty_operation_group]:
66
+ for og in [
67
+ og
68
+ for og in self.code_model.operation_groups
69
+ if not og.is_empty_operation_group
70
+ ]:
58
71
  retval.append(f":ivar {og.name}: {og.class_name} operations")
59
- retval.append(f":vartype {og.name}: {self.code_model.namespace}{operations_folder}{og.class_name}")
72
+ retval.append(
73
+ f":vartype {og.name}: {self.code_model.namespace}{operations_folder}{og.class_name}"
74
+ )
60
75
  for param in self.code_model.service_client.parameters.client_method:
61
- retval.append(f":{param.description_keyword} {param.serialized_name}: {param.description}")
62
- retval.append(f":{param.docstring_type_keyword} {param.serialized_name}: {param.docstring_type}")
76
+ retval.append(
77
+ f":{param.description_keyword} {param.serialized_name}: {param.description}"
78
+ )
79
+ retval.append(
80
+ f":{param.docstring_type_keyword} {param.serialized_name}: {param.docstring_type}"
81
+ )
63
82
  if self.code_model.has_lro_operations:
64
83
  retval.append(
65
84
  ":keyword int polling_interval: Default waiting time between two polls for LRO operations "
@@ -74,38 +93,57 @@ class ClientSerializer:
74
93
  [
75
94
  f"{p.serialized_name}={p.serialized_name}"
76
95
  for p in self.code_model.service_client.parameters.config_method
77
- if not p.is_kwarg
78
- ] + [
79
- "**kwargs"
80
- ])
96
+ if not p.method_location
97
+ in (ParameterMethodLocation.KWARG, ParameterMethodLocation.HIDDEN_KWARG)
98
+ ]
99
+ + ["**kwargs"]
100
+ )
81
101
  return f"self._config = {config_name}({config_call})"
82
102
 
83
103
  def initialize_pipeline_client(self, async_mode: bool) -> str:
84
- host_variable_name = self.code_model.service_client.parameters.host_variable_name
104
+ host_variable_name = (
105
+ self.code_model.service_client.parameters.host_variable_name
106
+ )
85
107
  if self.code_model.service_client.has_parameterized_host:
86
- host_variable_name = "_" + host_variable_name # we don't want potential conflicts with input params
108
+ host_variable_name = (
109
+ "_" + host_variable_name
110
+ ) # we don't want potential conflicts with input params
87
111
  pipeline_client_name = self.code_model.service_client.pipeline_class(async_mode)
88
112
  return f"self._client = {pipeline_client_name}(base_url={host_variable_name}, config=self._config, **kwargs)"
89
113
 
90
114
  def serializers_and_operation_groups_properties(self) -> List[str]:
91
115
  retval = []
92
116
  if self.code_model.sorted_schemas:
93
- client_models_value = "{k: v for k, v in models.__dict__.items() if isinstance(v, type)}"
117
+ client_models_value = (
118
+ "{k: v for k, v in models.__dict__.items() if isinstance(v, type)}"
119
+ )
94
120
  else:
95
121
  client_models_value = "{} # type: Dict[str, Any]"
96
122
  if self.code_model.options["models_mode"]:
97
123
  retval.append(f"client_models = {client_models_value}")
98
- client_models_str = "client_models" if self.code_model.options["models_mode"] else ""
124
+ client_models_str = (
125
+ "client_models" if self.code_model.options["models_mode"] else ""
126
+ )
99
127
  retval.append(f"self._serialize = Serializer({client_models_str})")
100
128
  retval.append(f"self._deserialize = Deserializer({client_models_str})")
101
129
  if not self.code_model.options["client_side_validation"]:
102
130
  retval.append("self._serialize.client_side_validation = False")
103
- operation_groups = [og for og in self.code_model.operation_groups if not og.is_empty_operation_group]
104
- if operation_groups:
131
+ operation_groups = [
132
+ og
133
+ for og in self.code_model.operation_groups
134
+ if not og.is_empty_operation_group
135
+ ]
136
+ for og in operation_groups:
137
+ disable_check = (
138
+ " # type: ignore # pylint: disable=abstract-class-instantiated"
139
+ if og.has_abstract_operations
140
+ else ""
141
+ )
105
142
  retval.extend(
106
143
  [
107
- f"self.{og.name} = {og.class_name}(self._client, self._config, self._serialize, self._deserialize)"
108
- for og in operation_groups
144
+ f"self.{og.name} = {og.class_name}({disable_check}",
145
+ " self._client, self._config, self._serialize, self._deserialize",
146
+ ")",
109
147
  ]
110
148
  )
111
149
  return retval
@@ -120,12 +158,16 @@ class ClientSerializer:
120
158
  ),
121
159
  )
122
160
 
123
- def send_request_signature_and_response_type_annotation(self, async_mode: bool) -> str:
161
+ def send_request_signature_and_response_type_annotation(
162
+ self, async_mode: bool
163
+ ) -> str:
124
164
  send_request_signature = self._send_request_signature(async_mode)
125
165
  return utils.method_signature_and_response_type_annotation_template(
126
166
  is_python3_file=async_mode or self.is_python3_file,
127
167
  method_signature=send_request_signature,
128
- response_type_annotation="Awaitable[AsyncHttpResponse]" if async_mode else "HttpResponse",
168
+ response_type_annotation="Awaitable[AsyncHttpResponse]"
169
+ if async_mode
170
+ else "HttpResponse",
129
171
  )
130
172
 
131
173
  def _example_make_call(self, async_mode: bool) -> List[str]:
@@ -138,23 +180,35 @@ class ClientSerializer:
138
180
 
139
181
  def _request_builder_example(self, async_mode: bool) -> List[str]:
140
182
  retval = [
141
- "We have helper methods to create requests specific to this service in " +
142
- f"`{self.code_model.namespace}.{self.code_model.rest_layer_name}`."
183
+ "We have helper methods to create requests specific to this service in "
184
+ + f"`{self.code_model.namespace}.{self.code_model.rest_layer_name}`."
143
185
  ]
144
- retval.append("Use these helper methods to create the request you pass to this method.")
186
+ retval.append(
187
+ "Use these helper methods to create the request you pass to this method."
188
+ )
145
189
  retval.append("")
146
190
 
147
- request_builder = self.code_model.rest.request_builders[0]
148
- request_builder_signature = ", ".join(request_builder.parameters.call)
191
+ request_builder = self.code_model.request_builders[0]
192
+ request_builder_signature = ", ".join(
193
+ request_builder.parameters.call(async_mode)
194
+ )
149
195
  if request_builder.builder_group_name:
150
196
  rest_imported = request_builder.builder_group_name
151
- request_builder_name = f"{request_builder.builder_group_name}.{request_builder.name}"
197
+ request_builder_name = (
198
+ f"{request_builder.builder_group_name}.{request_builder.name}"
199
+ )
152
200
  else:
153
201
  rest_imported = request_builder.name
154
202
  request_builder_name = request_builder.name
155
- retval.append(f">>> from {self.code_model.namespace}.{self.code_model.rest_layer_name} import {rest_imported}")
156
- retval.append(f">>> request = {request_builder_name}({request_builder_signature})")
157
- retval.append(f"<HttpRequest [{request_builder.method}], url: '{request_builder.url}'>")
203
+ retval.append(
204
+ f">>> from {self.code_model.namespace}.{self.code_model.rest_layer_name} import {rest_imported}"
205
+ )
206
+ retval.append(
207
+ f">>> request = {request_builder_name}({request_builder_signature})"
208
+ )
209
+ retval.append(
210
+ f"<HttpRequest [{request_builder.method}], url: '{request_builder.url}'>"
211
+ )
158
212
  retval.extend(self._example_make_call(async_mode))
159
213
  return retval
160
214
 
@@ -173,22 +227,30 @@ class ClientSerializer:
173
227
  else:
174
228
  retval.extend(self._rest_request_example(async_mode))
175
229
  retval.append("")
176
- retval.append("For more information on this code flow, see https://aka.ms/azsdk/python/protocol/quickstart")
230
+ retval.append(
231
+ "For more information on this code flow, see https://aka.ms/azsdk/python/protocol/quickstart"
232
+ )
177
233
  retval.append(f"")
178
234
  retval.append(":param request: The network request you want to make. Required.")
179
235
  retval.append(f":type request: ~azure.core.rest.HttpRequest")
180
- retval.append(":keyword bool stream: Whether the response payload will be streamed. Defaults to False.")
181
- retval.append(":return: The response of your network call. Does not do error handling on your response.")
236
+ retval.append(
237
+ ":keyword bool stream: Whether the response payload will be streamed. Defaults to False."
238
+ )
239
+ retval.append(
240
+ ":return: The response of your network call. Does not do error handling on your response."
241
+ )
182
242
  http_response = "AsyncHttpResponse" if async_mode else "HttpResponse"
183
243
  retval.append(f":rtype: ~azure.core.rest.{http_response}")
184
244
  retval.append('"""')
185
245
  return retval
186
246
 
187
247
  def serialize_path(self) -> List[str]:
188
- return utils.serialize_path(self.code_model.global_parameters.path, "self._serialize")
248
+ return utils.serialize_path(
249
+ self.code_model.global_parameters.path, "self._serialize"
250
+ )
189
251
 
190
- class ConfigSerializer:
191
252
 
253
+ class ConfigSerializer:
192
254
  def __init__(self, code_model: CodeModel, is_python3_file: bool) -> None:
193
255
  self.code_model = code_model
194
256
  self.is_python3_file = is_python3_file
@@ -212,9 +274,14 @@ class ConfigSerializer:
212
274
  )
213
275
 
214
276
  def pop_kwargs_from_signature(self, async_mode: bool) -> List[str]:
215
- return utils.pop_kwargs_from_signature(self.code_model.global_parameters.config_kwargs_to_pop(
216
- async_mode or self.is_python3_file
217
- ))
277
+ return utils.pop_kwargs_from_signature(
278
+ self.code_model.global_parameters.config_kwargs_to_pop(
279
+ async_mode or self.is_python3_file
280
+ ),
281
+ check_kwarg_dict=False,
282
+ pop_headers_kwarg=utils.PopKwargType.NO,
283
+ pop_params_kwarg=utils.PopKwargType.NO,
284
+ )
218
285
 
219
286
  def set_constants(self) -> List[str]:
220
287
  return [
@@ -225,8 +292,8 @@ class ConfigSerializer:
225
292
 
226
293
  def check_required_parameters(self) -> List[str]:
227
294
  return [
228
- f'if {p.serialized_name} is None:\n'
229
- f' raise ValueError("Parameter \'{p.serialized_name}\' must not be None.")'
295
+ f"if {p.serialized_name} is None:\n"
296
+ f" raise ValueError(\"Parameter '{p.serialized_name}' must not be None.\")"
230
297
  for p in self.code_model.global_parameters.config_method
231
298
  if p.required and not p.constant
232
299
  ]
@@ -234,7 +301,11 @@ class ConfigSerializer:
234
301
  def property_descriptions(self) -> List[str]:
235
302
  retval: List[str] = []
236
303
  for p in self.code_model.global_parameters.config_method:
237
- retval.append(f":{p.description_keyword} {p.serialized_name}: {p.description}")
238
- retval.append(f":{p.docstring_type_keyword} {p.serialized_name}: {p.docstring_type}")
304
+ retval.append(
305
+ f":{p.description_keyword} {p.serialized_name}: {p.description}"
306
+ )
307
+ retval.append(
308
+ f":{p.docstring_type_keyword} {p.serialized_name}: {p.docstring_type}"
309
+ )
239
310
  retval.append('"""')
240
311
  return retval
@@ -5,27 +5,54 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from jinja2 import Environment
7
7
  from .import_serializer import FileImportSerializer, TypingSection
8
- from ..models import FileImport, ImportType, CodeModel, TokenCredentialSchema, ParameterList
8
+ from ..models import (
9
+ FileImport,
10
+ ImportType,
11
+ CodeModel,
12
+ TokenCredentialSchema,
13
+ ParameterList,
14
+ )
9
15
  from .client_serializer import ClientSerializer, ConfigSerializer
10
16
 
11
- def config_imports(code_model, global_parameters: ParameterList, async_mode: bool) -> FileImport:
17
+
18
+ def config_imports(
19
+ code_model, global_parameters: ParameterList, async_mode: bool
20
+ ) -> FileImport:
12
21
  file_import = FileImport()
13
- file_import.add_submodule_import("azure.core.configuration", "Configuration", ImportType.AZURECORE)
14
- file_import.add_submodule_import("azure.core.pipeline", "policies", ImportType.AZURECORE)
15
- file_import.add_submodule_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
22
+ file_import.add_submodule_import(
23
+ "azure.core.configuration", "Configuration", ImportType.AZURECORE
24
+ )
25
+ file_import.add_submodule_import(
26
+ "azure.core.pipeline", "policies", ImportType.AZURECORE
27
+ )
28
+ file_import.add_submodule_import(
29
+ "typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
30
+ )
16
31
  if code_model.options["package_version"]:
17
- file_import.add_submodule_import(".._version" if async_mode else "._version", "VERSION", ImportType.LOCAL)
32
+ file_import.add_submodule_import(
33
+ ".._version" if async_mode else "._version", "VERSION", ImportType.LOCAL
34
+ )
18
35
  for gp in global_parameters:
19
36
  file_import.merge(gp.imports())
20
37
  if code_model.options["azure_arm"]:
21
- policy = "AsyncARMChallengeAuthenticationPolicy" if async_mode else "ARMChallengeAuthenticationPolicy"
22
- file_import.add_submodule_import("azure.mgmt.core.policies", "ARMHttpLoggingPolicy", ImportType.AZURECORE)
23
- file_import.add_submodule_import("azure.mgmt.core.policies", policy, ImportType.AZURECORE)
38
+ policy = (
39
+ "AsyncARMChallengeAuthenticationPolicy"
40
+ if async_mode
41
+ else "ARMChallengeAuthenticationPolicy"
42
+ )
43
+ file_import.add_submodule_import(
44
+ "azure.mgmt.core.policies", "ARMHttpLoggingPolicy", ImportType.AZURECORE
45
+ )
46
+ file_import.add_submodule_import(
47
+ "azure.mgmt.core.policies", policy, ImportType.AZURECORE
48
+ )
24
49
  return file_import
25
50
 
26
51
 
27
52
  class GeneralSerializer:
28
- def __init__(self, code_model: CodeModel, env: Environment, async_mode: bool) -> None:
53
+ def __init__(
54
+ self, code_model: CodeModel, env: Environment, async_mode: bool
55
+ ) -> None:
29
56
  self.code_model = code_model
30
57
  self.env = env
31
58
  self.async_mode = async_mode
@@ -40,7 +67,9 @@ class GeneralSerializer:
40
67
 
41
68
  def _correct_credential_parameter(self):
42
69
  credential_param = [
43
- gp for gp in self.code_model.global_parameters.parameters if isinstance(gp.schema, TokenCredentialSchema)
70
+ gp
71
+ for gp in self.code_model.global_parameters.parameters
72
+ if isinstance(gp.schema, TokenCredentialSchema)
44
73
  ][0]
45
74
  credential_param.schema = TokenCredentialSchema(async_mode=self.async_mode)
46
75
 
@@ -48,9 +77,9 @@ class GeneralSerializer:
48
77
 
49
78
  template = self.env.get_template("service_client.py.jinja2")
50
79
 
51
- if (
52
- self.code_model.options['credential'] and
53
- isinstance(self.code_model.credential_schema_policy.credential, TokenCredentialSchema)
80
+ if self.code_model.options["credential"] and isinstance(
81
+ self.code_model.credential_model.credential_schema_policy.credential,
82
+ TokenCredentialSchema,
54
83
  ):
55
84
  self._correct_credential_parameter()
56
85
 
@@ -61,7 +90,7 @@ class GeneralSerializer:
61
90
  serializer=ClientSerializer(self.code_model, is_python3_file=python3_only),
62
91
  imports=FileImportSerializer(
63
92
  self.code_model.service_client.imports(self.async_mode),
64
- is_python3_file=self.async_mode or python3_only
93
+ is_python3_file=self.async_mode or python3_only,
65
94
  ),
66
95
  )
67
96
 
@@ -77,25 +106,51 @@ class GeneralSerializer:
77
106
  ImportType.AZURECORE,
78
107
  )
79
108
 
109
+ if self.code_model.need_mixin_abc:
110
+ file_import.add_submodule_import(
111
+ "abc",
112
+ "ABC",
113
+ ImportType.STDLIB,
114
+ )
115
+ file_import.add_submodule_import(
116
+ "azure.core",
117
+ f"{'Async' if self.async_mode else ''}PipelineClient",
118
+ ImportType.AZURECORE,
119
+ TypingSection.TYPING,
120
+ )
121
+ file_import.add_submodule_import(
122
+ "._configuration",
123
+ f"{self.code_model.class_name}Configuration",
124
+ ImportType.LOCAL,
125
+ )
126
+ file_import.add_submodule_import(
127
+ "msrest", "Serializer", ImportType.THIRDPARTY, TypingSection.TYPING
128
+ )
129
+ file_import.add_submodule_import(
130
+ "msrest", "Deserializer", ImportType.THIRDPARTY, TypingSection.TYPING
131
+ )
132
+
80
133
  return template.render(
81
134
  code_model=self.code_model,
82
135
  imports=FileImportSerializer(
83
136
  file_import,
84
137
  is_python3_file=self.async_mode,
85
- )
138
+ ),
139
+ async_mode=self.async_mode,
86
140
  )
87
141
 
88
-
89
142
  def serialize_config_file(self) -> str:
90
143
 
91
- package_name = self.code_model.options['package_name']
144
+ package_name = self.code_model.options["package_name"]
92
145
  if package_name and package_name.startswith("azure-"):
93
- package_name = package_name[len("azure-"):]
94
- sdk_moniker = package_name if package_name else self.code_model.class_name.lower()
146
+ package_name = package_name[len("azure-") :]
147
+ sdk_moniker = (
148
+ package_name if package_name else self.code_model.class_name.lower()
149
+ )
95
150
 
96
- if (
97
- self.code_model.options['credential'] and
98
- isinstance(self.code_model.credential_schema_policy.credential, TokenCredentialSchema)
151
+ if self.code_model.options["credential"] and isinstance(
152
+ self.code_model.credential_model.credential_schema_policy.credential,
153
+ TokenCredentialSchema,
99
154
  ):
100
155
  self._correct_credential_parameter()
101
156
 
@@ -107,7 +162,8 @@ class GeneralSerializer:
107
162
  imports=FileImportSerializer(
108
163
  config_imports(
109
164
  self.code_model, self.code_model.global_parameters, self.async_mode
110
- ), is_python3_file=self.async_mode or python3_only
165
+ ),
166
+ is_python3_file=self.async_mode or python3_only,
111
167
  ),
112
168
  serializer=ConfigSerializer(self.code_model, is_python3_file=python3_only),
113
169
  sdk_moniker=sdk_moniker,
@@ -119,4 +175,7 @@ class GeneralSerializer:
119
175
 
120
176
  def serialize_setup_file(self) -> str:
121
177
  template = self.env.get_template("setup.py.jinja2")
122
- return template.render(code_model=self.code_model)
178
+ params = {}
179
+ params.update(self.code_model.options)
180
+ params.update(self.code_model.package_dependency)
181
+ return template.render(code_model=self.code_model, **params)
@@ -5,49 +5,68 @@
5
5
  # --------------------------------------------------------------------------
6
6
  from copy import deepcopy
7
7
  from typing import List
8
- from ..models.imports import ImportType, FileImport, ImportModel, TypingSection
8
+ from ..models.imports import (
9
+ ImportType,
10
+ FileImport,
11
+ ImportModel,
12
+ TypingSection,
13
+ TypeDefinition,
14
+ )
9
15
 
10
- def _serialize_package(
11
- imports: List[ImportModel], delimiter: str
12
- ) -> str:
16
+
17
+ def _serialize_package(imports: List[ImportModel], delimiter: str) -> str:
13
18
  buffer = []
14
19
  if any(i for i in imports if i.submodule_name is None):
15
- buffer.append(f"import {imports[0].module_name}")
20
+ buffer.append(
21
+ f"import {imports[0].module_name}{f' as {imports[0].alias}' if imports[0].alias else ''}"
22
+ )
16
23
  else:
17
- import_str = ", ".join(sorted([
18
- f"{i.submodule_name} as {i.alias}" if i.alias else i.submodule_name for i in imports # type: ignore
19
- ]))
24
+ import_str = ", ".join(
25
+ sorted(
26
+ [
27
+ f"{i.submodule_name} as {i.alias}" if i.alias else i.submodule_name for i in imports # type: ignore
28
+ ]
29
+ )
30
+ )
20
31
  buffer.append(f"from {imports[0].module_name} import {import_str}")
21
32
  return delimiter.join(buffer)
22
33
 
34
+
23
35
  def _serialize_import_type(imports: List[ImportModel], delimiter: str) -> str:
24
36
  """Serialize a given import type."""
25
37
  import_list = []
26
38
  for module_name in sorted(set(i.module_name for i in imports)):
27
39
 
28
- import_list.append(_serialize_package([
29
- i for i in imports if i.module_name == module_name
30
- ], delimiter))
40
+ import_list.append(
41
+ _serialize_package(
42
+ [i for i in imports if i.module_name == module_name], delimiter
43
+ )
44
+ )
31
45
  return delimiter.join(import_list)
32
46
 
33
- def _get_import_clauses(
34
- imports: List[ImportModel], delimiter: str
35
- ) -> List[str]:
47
+
48
+ def _get_import_clauses(imports: List[ImportModel], delimiter: str) -> List[str]:
36
49
  import_clause = []
37
50
  for import_type in ImportType:
38
51
  imports_with_import_type = [i for i in imports if i.import_type == import_type]
39
52
  if imports_with_import_type:
40
- import_clause.append(_serialize_import_type(imports_with_import_type, delimiter))
53
+ import_clause.append(
54
+ _serialize_import_type(imports_with_import_type, delimiter)
55
+ )
41
56
  return import_clause
42
57
 
43
58
 
44
59
  class FileImportSerializer:
45
- def __init__(self, file_import: FileImport, is_python3_file: bool, async_mode: bool = False) -> None:
60
+ def __init__(
61
+ self, file_import: FileImport, is_python3_file: bool, async_mode: bool = False
62
+ ) -> None:
46
63
  self.file_import = file_import
47
64
  self.is_python3_file = is_python3_file
48
65
  self.async_mode = async_mode
49
66
 
50
- def _get_imports_list(self, baseline_typing_section: TypingSection, add_conditional_typing: bool):
67
+ def _get_imports_list(
68
+ self, baseline_typing_section: TypingSection, add_conditional_typing: bool
69
+ ):
51
70
  # If this is a python 3 file, our regular imports include the CONDITIONAL category
52
71
  # If this is not a python 3 file, our typing imports include the CONDITIONAL category
53
72
  file_import_copy = deepcopy(self.file_import)
@@ -62,33 +81,73 @@ class FileImportSerializer:
62
81
  return file_import_copy.get_imports_from_section(baseline_typing_section)
63
82
 
64
83
  def _add_type_checking_import(self):
65
- any_typing = any(self.file_import.get_imports_from_section(TypingSection.TYPING))
84
+ any_typing = any(
85
+ self.file_import.get_imports_from_section(TypingSection.TYPING)
86
+ )
66
87
  conditional_and_not_py3 = not self.is_python3_file and any(
67
88
  self.file_import.get_imports_from_section(TypingSection.CONDITIONAL)
68
89
  )
69
90
  if any_typing or conditional_and_not_py3:
70
- self.file_import.add_submodule_import("typing", "TYPE_CHECKING", ImportType.STDLIB)
91
+ self.file_import.add_submodule_import(
92
+ "typing", "TYPE_CHECKING", ImportType.STDLIB
93
+ )
71
94
 
72
95
  def _get_typing_definitions(self) -> str:
96
+ def declare_defintion(
97
+ spacing: str, type_name: str, type_definition: TypeDefinition
98
+ ) -> List[str]:
99
+ ret: List[str] = []
100
+ definition_value = (
101
+ type_definition.async_definition
102
+ if self.async_mode
103
+ else type_definition.sync_definition
104
+ )
105
+ if type_definition.version_imports is not None:
106
+ versions = type_definition.version_imports.keys()
107
+ for i, version in enumerate(
108
+ sorted(
109
+ versions, key=lambda x: x if x is not None else (), reverse=True
110
+ )
111
+ ):
112
+ if version is not None:
113
+ ret.append(
114
+ "{}{} sys.version_info >= {}:".format(
115
+ spacing, "if" if i == 0 else "elif", version
116
+ )
117
+ )
118
+ elif i > 0:
119
+ ret.append("{}else:".format(spacing))
120
+ for import_clause in _get_import_clauses(
121
+ [type_definition.version_imports[version]], "\n"
122
+ ):
123
+ ret.append(
124
+ "{}{}{}".format(
125
+ " "
126
+ if len(versions) > 1 or version is not None
127
+ else "",
128
+ spacing,
129
+ import_clause,
130
+ )
131
+ )
132
+ if i > 0:
133
+ ret[-1] += " # type: ignore"
134
+ ret.append("{}{} = {}".format(spacing, type_name, definition_value))
135
+ return ret
136
+
73
137
  if not self.file_import.type_definitions:
74
138
  return ""
75
139
  spacing = "" if self.is_python3_file else " "
76
- declarations: List[str] = [f"\n{spacing}T = TypeVar('T')"]
77
- declarations.extend([
78
- "{}{} = {}".format(
79
- spacing,
80
- type_name,
81
- values[1] if self.async_mode else values[0]
82
- )
83
- for type_name, values in self.file_import.type_definitions.items()
84
- ])
140
+ declarations: List[str] = [""]
141
+ for type_name, value in self.file_import.type_definitions.items():
142
+ declarations.extend(declare_defintion(spacing, type_name, value))
85
143
  return "\n".join(declarations)
86
144
 
87
145
  def __str__(self) -> str:
88
146
  self._add_type_checking_import()
89
147
  regular_imports = ""
90
148
  regular_imports_list = self._get_imports_list(
91
- baseline_typing_section=TypingSection.REGULAR, add_conditional_typing=self.is_python3_file
149
+ baseline_typing_section=TypingSection.REGULAR,
150
+ add_conditional_typing=self.is_python3_file,
92
151
  )
93
152
 
94
153
  if regular_imports_list:
@@ -98,9 +157,12 @@ class FileImportSerializer:
98
157
 
99
158
  typing_imports = ""
100
159
  typing_imports_list = self._get_imports_list(
101
- baseline_typing_section=TypingSection.TYPING, add_conditional_typing=not self.is_python3_file
160
+ baseline_typing_section=TypingSection.TYPING,
161
+ add_conditional_typing=not self.is_python3_file,
102
162
  )
103
163
  if typing_imports_list:
104
164
  typing_imports += "\n\nif TYPE_CHECKING:\n # pylint: disable=unused-import,ungrouped-imports\n "
105
- typing_imports += "\n\n ".join(_get_import_clauses(typing_imports_list, "\n "))
165
+ typing_imports += "\n\n ".join(
166
+ _get_import_clauses(typing_imports_list, "\n ")
167
+ )
106
168
  return regular_imports + typing_imports + self._get_typing_definitions()