@autorest/python 5.12.2 → 5.12.6

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 (42) hide show
  1. package/ChangeLog.md +60 -0
  2. package/autorest/black/__init__.py +4 -1
  3. package/autorest/codegen/models/client.py +22 -19
  4. package/autorest/codegen/models/credential_schema.py +3 -3
  5. package/autorest/codegen/models/dictionary_schema.py +1 -1
  6. package/autorest/codegen/models/enum_schema.py +2 -2
  7. package/autorest/codegen/models/imports.py +90 -50
  8. package/autorest/codegen/models/list_schema.py +1 -1
  9. package/autorest/codegen/models/lro_operation.py +15 -9
  10. package/autorest/codegen/models/object_schema.py +2 -2
  11. package/autorest/codegen/models/operation.py +28 -26
  12. package/autorest/codegen/models/operation_group.py +5 -14
  13. package/autorest/codegen/models/paging_operation.py +9 -9
  14. package/autorest/codegen/models/parameter.py +6 -7
  15. package/autorest/codegen/models/parameter_list.py +1 -0
  16. package/autorest/codegen/models/primitive_schemas.py +2 -2
  17. package/autorest/codegen/models/property.py +1 -1
  18. package/autorest/codegen/models/request_builder.py +7 -6
  19. package/autorest/codegen/models/request_builder_parameter.py +0 -2
  20. package/autorest/codegen/models/request_builder_parameter_list.py +1 -0
  21. package/autorest/codegen/models/schema_response.py +1 -1
  22. package/autorest/codegen/serializers/builder_serializer.py +33 -26
  23. package/autorest/codegen/serializers/client_serializer.py +14 -3
  24. package/autorest/codegen/serializers/general_serializer.py +7 -7
  25. package/autorest/codegen/serializers/import_serializer.py +44 -46
  26. package/autorest/codegen/serializers/metadata_serializer.py +12 -10
  27. package/autorest/codegen/serializers/model_base_serializer.py +6 -6
  28. package/autorest/codegen/serializers/utils.py +5 -1
  29. package/autorest/codegen/templates/config.py.jinja2 +2 -7
  30. package/autorest/codegen/templates/lro_operation.py.jinja2 +3 -1
  31. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +2 -0
  32. package/autorest/codegen/templates/metadata.json.jinja2 +3 -3
  33. package/autorest/codegen/templates/operation.py.jinja2 +8 -2
  34. package/autorest/codegen/templates/operation_group.py.jinja2 +2 -1
  35. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -0
  36. package/autorest/codegen/templates/operation_tools.jinja2 +3 -2
  37. package/autorest/codegen/templates/paging_operation.py.jinja2 +3 -1
  38. package/autorest/codegen/templates/request_builder.py.jinja2 +2 -7
  39. package/autorest/codegen/templates/service_client.py.jinja2 +1 -1
  40. package/autorest/multiapi/models/imports.py +1 -1
  41. package/autorest/multiapi/serializers/import_serializer.py +1 -1
  42. package/package.json +2 -2
@@ -125,9 +125,9 @@ class PagingOperation(Operation):
125
125
  def _imports_shared(self, async_mode: bool) -> FileImport:
126
126
  file_import = super()._imports_shared(async_mode)
127
127
  if async_mode:
128
- file_import.add_from_import("typing", "AsyncIterable", ImportType.STDLIB, TypingSection.CONDITIONAL)
128
+ file_import.add_submodule_import("typing", "AsyncIterable", ImportType.STDLIB, TypingSection.CONDITIONAL)
129
129
  else:
130
- file_import.add_from_import("typing", "Iterable", ImportType.STDLIB, TypingSection.CONDITIONAL)
130
+ file_import.add_submodule_import("typing", "Iterable", ImportType.STDLIB, TypingSection.CONDITIONAL)
131
131
  if (
132
132
  self.next_request_builder and
133
133
  self.code_model.options["builders_visibility"] == "embedded"
@@ -141,26 +141,26 @@ class PagingOperation(Operation):
141
141
  pager_import_path = ".".join(self.get_pager_path(async_mode).split(".")[:-1])
142
142
  pager = self.get_pager(async_mode)
143
143
 
144
- file_import.add_from_import(pager_import_path, pager, ImportType.AZURECORE, TypingSection.CONDITIONAL)
144
+ file_import.add_submodule_import(pager_import_path, pager, ImportType.AZURECORE, TypingSection.CONDITIONAL)
145
145
 
146
146
  return file_import
147
147
 
148
148
  def imports(self, async_mode: bool) -> FileImport:
149
149
  file_import = super(PagingOperation, self).imports(async_mode)
150
+ # operation adds an import for distributed_trace_async, we don't want it
151
+ file_import.imports = [i for i in file_import.imports if not i.submodule_name == "distributed_trace_async"]
150
152
 
151
153
  pager_import_path = ".".join(self.get_pager_path(async_mode).split(".")[:-1])
152
154
  pager = self.get_pager(async_mode)
153
155
 
154
- file_import.add_from_import(pager_import_path, pager, ImportType.AZURECORE)
156
+ file_import.add_submodule_import(pager_import_path, pager, ImportType.AZURECORE)
155
157
 
156
158
  if async_mode:
157
- file_import.add_from_import("azure.core.async_paging", "AsyncList", ImportType.AZURECORE)
159
+ file_import.add_submodule_import("azure.core.async_paging", "AsyncList", ImportType.AZURECORE)
158
160
 
159
- if self.code_model.options["tracing"]:
160
- file_import.add_from_import(
161
+ if self.code_model.options["tracing"] and self.want_tracing:
162
+ file_import.add_submodule_import(
161
163
  "azure.core.tracing.decorator", "distributed_trace", ImportType.AZURECORE,
162
164
  )
163
- if not self.code_model.options["models_mode"]:
164
- file_import.add_from_import("json", "loads", ImportType.STDLIB, alias="_loads")
165
165
 
166
166
  return file_import
@@ -98,6 +98,7 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
98
98
  self.content_types = content_types or []
99
99
  self.body_kwargs: List[Parameter] = []
100
100
  self.is_body_kwarg = False
101
+ self.need_import = True
101
102
 
102
103
  def __hash__(self) -> int:
103
104
  return hash(self.serialized_name)
@@ -177,8 +178,6 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
177
178
  return not(
178
179
  # don't put accept in signature
179
180
  self.rest_api_name == "Accept"
180
- # if i'm multiapi, don't add constants
181
- or (self.code_model.options["multiapi"] and self.constant)
182
181
  # If i'm not in the method code, no point in being in signature
183
182
  or not self.in_method_code
184
183
  # If I'm grouped, my grouper will be on signature, not me
@@ -302,8 +301,6 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
302
301
  @property
303
302
  def is_kwarg(self) -> bool:
304
303
  # this means "am I in **kwargs?"
305
- if self.code_model.options["multiapi"]:
306
- return self.rest_api_name == "Content-Type"
307
304
  return self.rest_api_name == "Content-Type" or (self.constant and self.rest_api_name != "Accept")
308
305
 
309
306
  @property
@@ -313,7 +310,9 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
313
310
 
314
311
  @property
315
312
  def is_hidden(self) -> bool:
316
- return self.serialized_name in _HIDDEN_KWARGS
313
+ return self.serialized_name in _HIDDEN_KWARGS or (
314
+ self.yaml_data["implementation"] == "Client" and self.constant
315
+ )
317
316
 
318
317
  @property
319
318
  def is_positional(self) -> bool:
@@ -356,9 +355,9 @@ class Parameter(BaseModel): # pylint: disable=too-many-instance-attributes, too
356
355
  def imports(self) -> FileImport:
357
356
  file_import = self.schema.imports()
358
357
  if not self.required:
359
- file_import.add_from_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
358
+ file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
360
359
  if self.has_multiple_content_types or self._is_io_json:
361
- file_import.add_from_import("typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL)
360
+ file_import.add_submodule_import("typing", "Union", ImportType.STDLIB, TypingSection.CONDITIONAL)
362
361
 
363
362
  return file_import
364
363
 
@@ -275,6 +275,7 @@ class ParameterList(MutableSequence): # pylint: disable=too-many-public-methods
275
275
  def _create_files_or_data_param(
276
276
  params: List[Parameter], serialized_name: str, description: str
277
277
  ) -> Parameter:
278
+ params[0].need_import = False
278
279
  param = copy(params[0])
279
280
  param.serialized_name = serialized_name
280
281
  param.schema = DictionarySchema(
@@ -116,7 +116,7 @@ class IOSchema(PrimitiveSchema):
116
116
 
117
117
  def imports(self) -> FileImport:
118
118
  file_import = FileImport()
119
- file_import.add_from_import("typing", "IO", ImportType.STDLIB, TypingSection.CONDITIONAL)
119
+ file_import.add_submodule_import("typing", "IO", ImportType.STDLIB, TypingSection.CONDITIONAL)
120
120
  return file_import
121
121
 
122
122
  class AnySchema(PrimitiveSchema):
@@ -138,7 +138,7 @@ class AnySchema(PrimitiveSchema):
138
138
 
139
139
  def imports(self) -> FileImport:
140
140
  file_import = FileImport()
141
- file_import.add_from_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
141
+ file_import.add_submodule_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
142
142
  return file_import
143
143
 
144
144
  class JSONSchema(AnySchema):
@@ -170,5 +170,5 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
170
170
  def model_file_imports(self) -> FileImport:
171
171
  file_import = self.schema.model_file_imports()
172
172
  if not self.required:
173
- file_import.add_from_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
173
+ file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB, TypingSection.CONDITIONAL)
174
174
  return file_import
@@ -66,9 +66,10 @@ class RequestBuilder(BaseBuilder):
66
66
  def imports(self) -> FileImport:
67
67
  file_import = FileImport()
68
68
  for parameter in self.parameters:
69
- file_import.merge(parameter.imports())
69
+ if parameter.need_import:
70
+ file_import.merge(parameter.imports())
70
71
 
71
- file_import.add_from_import(
72
+ file_import.add_submodule_import(
72
73
  "azure.core.rest",
73
74
  "HttpRequest",
74
75
  ImportType.AZURECORE,
@@ -77,17 +78,17 @@ class RequestBuilder(BaseBuilder):
77
78
  relative_path = ".."
78
79
  if not self.code_model.options["builders_visibility"] == "embedded" and self.operation_group_name:
79
80
  relative_path = "..." if self.operation_group_name else ".."
80
- file_import.add_from_import(
81
+ file_import.add_submodule_import(
81
82
  f"{relative_path}_vendor", "_format_url_section", ImportType.LOCAL
82
83
  )
83
84
  if self.parameters.headers or self.parameters.query:
84
- file_import.add_from_import(
85
+ file_import.add_submodule_import(
85
86
  "typing", "Dict", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
86
87
  )
87
- file_import.add_from_import(
88
+ file_import.add_submodule_import(
88
89
  "typing", "Any", ImportType.STDLIB, typing_section=TypingSection.CONDITIONAL
89
90
  )
90
- file_import.add_from_import("msrest", "Serializer", ImportType.AZURECORE)
91
+ file_import.add_submodule_import("msrest", "Serializer", ImportType.THIRDPARTY)
91
92
  if self.parameters.has_body and (
92
93
  self.code_model.options["builders_visibility"] != "embedded" or
93
94
  self.code_model.options["add_python3_operation_files"]
@@ -18,8 +18,6 @@ class RequestBuilderParameter(ParameterOnlyPathAndBodyPositional):
18
18
  return not(
19
19
  # don't put accept in method signature
20
20
  self.rest_api_name == "Accept"
21
- # if i'm multiapi, don't add constants
22
- or (self.code_model.options["multiapi"] and self.constant)
23
21
  # If i'm not in the method code, no point in being in signature
24
22
  or not self.in_method_code
25
23
  # If I'm a flattened property of a body, don't want me, want the body param
@@ -198,6 +198,7 @@ class RequestBuilderParameterList(ParameterList):
198
198
  else:
199
199
  for kwarg in body_kwargs_added:
200
200
  kwarg.required = False
201
+ first_body_param.need_import = False
201
202
  self.parameters = body_kwargs_added + self.parameters
202
203
 
203
204
  @property
@@ -99,7 +99,7 @@ class SchemaResponse(BaseModel):
99
99
  def imports(self, code_model) -> FileImport:
100
100
  file_import = FileImport()
101
101
  if not code_model.options["models_mode"] and self.is_xml:
102
- file_import.add_from_import("xml.etree", "ElementTree", ImportType.STDLIB, alias="ET")
102
+ file_import.add_submodule_import("xml.etree", "ElementTree", ImportType.STDLIB, alias="ET")
103
103
  return file_import
104
104
 
105
105
  @classmethod
@@ -33,6 +33,9 @@ from . import utils
33
33
  T = TypeVar("T")
34
34
  OrderedSet = Dict[T, None]
35
35
 
36
+ def _escape_str(input_str: str) -> str:
37
+ replace = input_str.replace("'", "\\'")
38
+ return f'"{replace}"'
36
39
 
37
40
  def _improve_json_string(template_representation: str) -> Any:
38
41
  origin = template_representation.split('\n')
@@ -110,7 +113,7 @@ def _pop_parameters_kwarg(
110
113
  function_name: str,
111
114
  kwarg_name: str,
112
115
  ) -> str:
113
- return f'{function_name}_parameters = kwargs.pop("{kwarg_name}", {{}}) # type: Dict[str, Any]'
116
+ return f'_{function_name}_parameters = kwargs.pop("{kwarg_name}", {{}}) # type: Dict[str, Any]'
114
117
 
115
118
  def _serialize_grouped_body(builder) -> List[str]:
116
119
  retval: List[str] = []
@@ -180,11 +183,6 @@ class _BuilderSerializerProtocol(ABC):
180
183
  """Whether you want inline type hints. If false, your type hints will be commented'"""
181
184
  ...
182
185
 
183
- @abstractmethod
184
- def _method_signature(self, builder) -> str:
185
- """Signature of the builder. Does not include return type annotation"""
186
- ...
187
-
188
186
  @abstractmethod
189
187
  def _response_type_annotation(self, builder, modify_if_head_as_boolean: bool = True) -> str:
190
188
  """The mypy type annotation for the response"""
@@ -266,20 +264,22 @@ class _BuilderBaseSerializer(_BuilderSerializerProtocol): # pylint: disable=abs
266
264
  def _cls_docstring_rtype(self) -> str:
267
265
  return "" if self.code_model.options["version_tolerant"] else " or the result of cls(response)"
268
266
 
269
- def _method_signature(self, builder) -> str:
267
+ def _method_signature(self, builder: Operation, response_type_annotation: str) -> str:
270
268
  return utils.serialize_method(
271
269
  function_def=self._function_definition,
272
270
  method_name=builder.name,
273
271
  is_in_class=self._is_in_class,
274
272
  method_param_signatures=builder.parameters.method_signature(self._want_inline_type_hints),
273
+ ignore_inconsistent_return_statements=(response_type_annotation == "None")
275
274
  )
276
275
 
277
276
  def _response_type_annotation_wrapper(self, builder) -> List[str]:
278
277
  return []
279
278
 
280
279
  def method_signature_and_response_type_annotation(self, builder) -> str:
281
- method_signature = self._method_signature(builder)
282
280
  response_type_annotation = self._response_type_annotation(builder)
281
+ # want pre-wrapped response type. As long as it's None, pylint will get mad about inconsistent return types
282
+ method_signature = self._method_signature(builder, response_type_annotation)
283
283
  for wrapper in self._response_type_annotation_wrapper(builder)[::-1]:
284
284
  response_type_annotation = f"{wrapper}[{response_type_annotation}]"
285
285
  return self._method_signature_and_response_type_annotation_template(method_signature, response_type_annotation)
@@ -402,7 +402,7 @@ class _BuilderBaseSerializer(_BuilderSerializerProtocol): # pylint: disable=abs
402
402
  def _serialize_parameter(
403
403
  self, param: Parameter, function_name: str
404
404
  ) -> List[str]:
405
- set_parameter = "{}_parameters['{}'] = {}".format(
405
+ set_parameter = "_{}_parameters['{}'] = {}".format(
406
406
  function_name,
407
407
  param.rest_api_name,
408
408
  utils.build_serialize_data_call(param, function_name, self.serializer_name)
@@ -499,11 +499,11 @@ class _RequestBuilderBaseSerializer(_BuilderBaseSerializer): # pylint: disable=
499
499
  def create_http_request(self, builder) -> List[str]:
500
500
  retval = ["return HttpRequest("]
501
501
  retval.append(f' method="{builder.method}",')
502
- retval.append(" url=url,")
502
+ retval.append(" url=_url,")
503
503
  if builder.parameters.query:
504
- retval.append(" params=query_parameters,")
504
+ retval.append(" params=_query_parameters,")
505
505
  if builder.parameters.headers:
506
- retval.append(" headers=header_parameters,")
506
+ retval.append(" headers=_header_parameters,")
507
507
  if builder.parameters.has_body:
508
508
  retval.extend([
509
509
  f" {body_kwarg}={body_kwarg},"
@@ -533,6 +533,13 @@ class _RequestBuilderBaseSerializer(_BuilderBaseSerializer): # pylint: disable=
533
533
  ))
534
534
  return retval
535
535
 
536
+ def construct_url(self, builder) -> str:
537
+ if any(o for o in ["low_level_client", "version_tolerant"] if self.code_model.options.get(o)):
538
+ url_value = _escape_str(builder.url)
539
+ else:
540
+ url_value = f'kwargs.pop("template_url", {_escape_str(builder.url)})'
541
+ return f"_url = {url_value}{' # pylint: disable=line-too-long' if len(url_value) > 114 else ''}"
542
+
536
543
  class RequestBuilderGenericSerializer(_RequestBuilderBaseSerializer):
537
544
  @property
538
545
  def _want_inline_type_hints(self) -> bool:
@@ -711,7 +718,7 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
711
718
  )
712
719
  ser_ctxt_name = "serialization_ctxt"
713
720
  ser_ctxt = builder.parameters.body[0].xml_serialization_ctxt if send_xml else None
714
- if ser_ctxt:
721
+ if ser_ctxt and self.code_model.options["models_mode"]:
715
722
  retval.append(f'{ser_ctxt_name} = {{"xml": {{{ser_ctxt}}}}}')
716
723
  serialize_body_call = self._serialize_body_call(
717
724
  builder,
@@ -986,7 +993,8 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
986
993
 
987
994
  @staticmethod
988
995
  def get_metadata_url(builder) -> str:
989
- return f"{builder.python_name}.metadata = {{'url': '{ builder.request_builder.url }'}} # type: ignore"
996
+ url = _escape_str(builder.request_builder.url)
997
+ return f"{builder.python_name}.metadata = {{'url': { url }}} # type: ignore"
990
998
 
991
999
  class _SyncOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=abstract-method
992
1000
  @property
@@ -1114,7 +1122,7 @@ class _PagingOperationBaseSerializer(_OperationBaseSerializer): # pylint: disab
1114
1122
  deserialized = (
1115
1123
  f'self._deserialize("{response.serialization_type}", pipeline_response)'
1116
1124
  if self.code_model.options["models_mode"] else
1117
- "_loads(pipeline_response.http_response.body())"
1125
+ "pipeline_response.http_response.json()"
1118
1126
  )
1119
1127
  retval.append(f" deserialized = {deserialized}")
1120
1128
  item_name = builder.item_name(self.code_model)
@@ -1137,10 +1145,11 @@ class _PagingOperationBaseSerializer(_OperationBaseSerializer): # pylint: disab
1137
1145
  retval = [f"{self._def} get_next(next_link=None):"]
1138
1146
  retval.append(" request = prepare_request(next_link)")
1139
1147
  retval.append("")
1140
- retval.append(
1141
- f" pipeline_response = {self._call_method}self._client._pipeline.run(request, "
1142
- f"stream={builder.is_stream_response}, **kwargs)"
1143
- )
1148
+ retval.append(f" pipeline_response = {self._call_method}self._client._pipeline.run( # pylint: disable=protected-access")
1149
+ retval.append(" request,")
1150
+ retval.append(f" stream={builder.is_stream_response},")
1151
+ retval.append(" **kwargs")
1152
+ retval.append(" )")
1144
1153
  retval.append(" response = pipeline_response.http_response")
1145
1154
  retval.append("")
1146
1155
  retval.extend([
@@ -1234,7 +1243,7 @@ class _LROOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=
1234
1243
  "Pass in False for this operation to not poll, or pass in your own initialized polling object for a"
1235
1244
  " personal polling strategy."
1236
1245
  )
1237
- retval.append(f":paramtype polling: bool or ~{self._polling_method_type}")
1246
+ retval.append(f":paramtype polling: bool or ~azure.core.polling.{self._polling_method_type}")
1238
1247
  retval.append(
1239
1248
  ":keyword int polling_interval: Default waiting time between two polls for LRO operations "
1240
1249
  "if no Retry-After header is present."
@@ -1287,9 +1296,8 @@ class _LROOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=
1287
1296
  retval.append(" client=self._client,")
1288
1297
  retval.append(" deserialization_callback=get_long_running_output")
1289
1298
  retval.append(" )")
1290
- retval.append("else:")
1291
1299
  retval.append(
1292
- f" return {self._poller(builder)}"
1300
+ f"return {self._poller(builder)}"
1293
1301
  "(self._client, raw_result, get_long_running_output, polling_method)"
1294
1302
  )
1295
1303
  return retval
@@ -1335,7 +1343,7 @@ class _SyncLROOperationBaseSerializer(_LROOperationBaseSerializer, _SyncOperatio
1335
1343
 
1336
1344
  @property
1337
1345
  def _polling_method_type(self):
1338
- return "azure.core.polling.PollingMethod"
1346
+ return "PollingMethod"
1339
1347
 
1340
1348
  def _poller(self, builder) -> str:
1341
1349
  return builder.get_poller(async_mode=False)
@@ -1368,7 +1376,7 @@ class AsyncLROOperationSerializer(_LROOperationBaseSerializer, AsyncOperationSer
1368
1376
 
1369
1377
  @property
1370
1378
  def _polling_method_type(self):
1371
- return "azure.core.polling.AsyncPollingMethod"
1379
+ return "AsyncPollingMethod"
1372
1380
 
1373
1381
  def _poller(self, builder) -> str:
1374
1382
  return builder.get_poller(async_mode=True)
@@ -1383,8 +1391,7 @@ class _LROPagingOperationBaseSerializer(_LROOperationBaseSerializer, _PagingOper
1383
1391
  retval.append(f" {self._def} internal_get_next(next_link=None):")
1384
1392
  retval.append(" if next_link is None:")
1385
1393
  retval.append(" return pipeline_response")
1386
- retval.append(" else:")
1387
- retval.append(f" return {self._call_method}get_next(next_link)")
1394
+ retval.append(f" return {self._call_method}get_next(next_link)")
1388
1395
  retval.append("")
1389
1396
  retval.append(f" return {self._pager(builder)}(")
1390
1397
  retval.append(" internal_get_next, extract_data")
@@ -44,9 +44,12 @@ class ClientSerializer:
44
44
  base_class = f"{class_name}OperationsMixin"
45
45
  elif not (async_mode or self.is_python3_file):
46
46
  base_class = "object"
47
+ disable = ""
48
+ if len(self.code_model.operation_groups) > 6:
49
+ disable = " # pylint: disable=too-many-instance-attributes"
47
50
  if base_class:
48
- return f"class {class_name}({base_class}):"
49
- return f"class {class_name}:"
51
+ return f"class {class_name}({base_class}):{disable}"
52
+ return f"class {class_name}:{disable}"
50
53
 
51
54
  def property_descriptions(self, async_mode: bool) -> List[str]:
52
55
  retval: List[str] = []
@@ -113,7 +116,7 @@ class ClientSerializer:
113
116
  method_name=self.code_model.send_request_name,
114
117
  is_in_class=True,
115
118
  method_param_signatures=self.code_model.service_client.send_request_signature(
116
- async_mode, async_mode or self.is_python3_file
119
+ async_mode or self.is_python3_file
117
120
  ),
118
121
  )
119
122
 
@@ -227,3 +230,11 @@ class ConfigSerializer:
227
230
  for p in self.code_model.global_parameters.config_method
228
231
  if p.required and not p.constant
229
232
  ]
233
+
234
+ def property_descriptions(self) -> List[str]:
235
+ retval: List[str] = []
236
+ 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}")
239
+ retval.append('"""')
240
+ return retval
@@ -10,17 +10,17 @@ from .client_serializer import ClientSerializer, ConfigSerializer
10
10
 
11
11
  def config_imports(code_model, global_parameters: ParameterList, async_mode: bool) -> FileImport:
12
12
  file_import = FileImport()
13
- file_import.add_from_import("azure.core.configuration", "Configuration", ImportType.AZURECORE)
14
- file_import.add_from_import("azure.core.pipeline", "policies", ImportType.AZURECORE)
15
- file_import.add_from_import("typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL)
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)
16
16
  if code_model.options["package_version"]:
17
- file_import.add_from_import(".._version" if async_mode else "._version", "VERSION", ImportType.LOCAL)
17
+ file_import.add_submodule_import(".._version" if async_mode else "._version", "VERSION", ImportType.LOCAL)
18
18
  for gp in global_parameters:
19
19
  file_import.merge(gp.imports())
20
20
  if code_model.options["azure_arm"]:
21
21
  policy = "AsyncARMChallengeAuthenticationPolicy" if async_mode else "ARMChallengeAuthenticationPolicy"
22
- file_import.add_from_import("azure.mgmt.core.policies", "ARMHttpLoggingPolicy", ImportType.AZURECORE)
23
- file_import.add_from_import("azure.mgmt.core.policies", policy, ImportType.AZURECORE)
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)
24
24
  return file_import
25
25
 
26
26
 
@@ -71,7 +71,7 @@ class GeneralSerializer:
71
71
  # configure imports
72
72
  file_import = FileImport()
73
73
  if self.code_model.need_request_converter:
74
- file_import.add_from_import(
74
+ file_import.add_submodule_import(
75
75
  "azure.core.pipeline.transport",
76
76
  "HttpRequest",
77
77
  ImportType.AZURECORE,
@@ -4,75 +4,73 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
  from copy import deepcopy
7
- from typing import Dict, Set, Optional, List, Tuple, Union
8
- from ..models.imports import ImportType, FileImport, TypingSection
7
+ from typing import List
8
+ from ..models.imports import ImportType, FileImport, ImportModel, TypingSection
9
9
 
10
10
  def _serialize_package(
11
- package_name: str, module_list: Set[Optional[Union[str, Tuple[str, str]]]], delimiter: str
11
+ imports: List[ImportModel], delimiter: str
12
12
  ) -> str:
13
13
  buffer = []
14
- if None in module_list:
15
- buffer.append(f"import {package_name}")
16
- if module_list != {None}:
17
- buffer.append(
18
- "from {} import {}".format(
19
- package_name, ", ".join(sorted([
20
- mod if isinstance(mod, str) else f"{mod[0]} as {mod[1]}" for mod in module_list if mod is not None
21
- ]))
22
- )
23
- )
14
+ if any(i for i in imports if i.submodule_name is None):
15
+ buffer.append(f"import {imports[0].module_name}")
16
+ 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
+ ]))
20
+ buffer.append(f"from {imports[0].module_name} import {import_str}")
24
21
  return delimiter.join(buffer)
25
22
 
26
- def _serialize_type(import_type_dict: Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]], delimiter: str) -> str:
23
+ def _serialize_import_type(imports: List[ImportModel], delimiter: str) -> str:
27
24
  """Serialize a given import type."""
28
25
  import_list = []
29
- for package_name in sorted(list(import_type_dict.keys())):
30
- module_list = import_type_dict[package_name]
31
- import_list.append(_serialize_package(package_name, module_list, delimiter))
26
+ for module_name in sorted(set(i.module_name for i in imports)):
27
+
28
+ import_list.append(_serialize_package([
29
+ i for i in imports if i.module_name == module_name
30
+ ], delimiter))
32
31
  return delimiter.join(import_list)
33
32
 
34
33
  def _get_import_clauses(
35
- imports: Dict[ImportType, Dict[str, Set[Optional[Union[str, Tuple[str, str]]]]]], delimiter: str
34
+ imports: List[ImportModel], delimiter: str
36
35
  ) -> List[str]:
37
36
  import_clause = []
38
37
  for import_type in ImportType:
39
- if import_type in imports:
40
- import_clause.append(_serialize_type(imports[import_type], delimiter))
38
+ imports_with_import_type = [i for i in imports if i.import_type == import_type]
39
+ if imports_with_import_type:
40
+ import_clause.append(_serialize_import_type(imports_with_import_type, delimiter))
41
41
  return import_clause
42
42
 
43
43
 
44
44
  class FileImportSerializer:
45
45
  def __init__(self, file_import: FileImport, is_python3_file: bool, async_mode: bool = False) -> None:
46
- self._file_import = file_import
46
+ self.file_import = file_import
47
47
  self.is_python3_file = is_python3_file
48
48
  self.async_mode = async_mode
49
49
 
50
- def _switch_typing_section_key(self, new_key: TypingSection):
51
- switched_dictionary = {}
52
- switched_dictionary[new_key] = self._file_import.imports[TypingSection.CONDITIONAL]
53
- return switched_dictionary
54
-
55
- def _get_imports_dict(self, baseline_typing_section: TypingSection, add_conditional_typing: bool):
50
+ def _get_imports_list(self, baseline_typing_section: TypingSection, add_conditional_typing: bool):
56
51
  # If this is a python 3 file, our regular imports include the CONDITIONAL category
57
52
  # If this is not a python 3 file, our typing imports include the CONDITIONAL category
58
- file_import_copy = deepcopy(self._file_import)
59
- if add_conditional_typing and self._file_import.imports.get(TypingSection.CONDITIONAL):
53
+ file_import_copy = deepcopy(self.file_import)
54
+ if add_conditional_typing and any(
55
+ self.file_import.get_imports_from_section(TypingSection.CONDITIONAL)
56
+ ):
60
57
  # we switch the TypingSection key for the CONDITIONAL typing imports so we can merge
61
58
  # the imports together
62
- switched_imports_dictionary = self._switch_typing_section_key(baseline_typing_section)
63
- switched_imports = FileImport(switched_imports_dictionary)
64
- file_import_copy.merge(switched_imports)
65
- return file_import_copy.imports.get(baseline_typing_section, {})
59
+ for i in file_import_copy.imports:
60
+ if i.typing_section == TypingSection.CONDITIONAL:
61
+ i.typing_section = baseline_typing_section
62
+ return file_import_copy.get_imports_from_section(baseline_typing_section)
66
63
 
67
64
  def _add_type_checking_import(self):
68
- if (
69
- self._file_import.imports.get(TypingSection.TYPING) or
70
- (not self.is_python3_file and self._file_import.imports.get(TypingSection.CONDITIONAL))
71
- ):
72
- self._file_import.add_from_import("typing", "TYPE_CHECKING", ImportType.STDLIB)
65
+ any_typing = any(self.file_import.get_imports_from_section(TypingSection.TYPING))
66
+ conditional_and_not_py3 = not self.is_python3_file and any(
67
+ self.file_import.get_imports_from_section(TypingSection.CONDITIONAL)
68
+ )
69
+ if any_typing or conditional_and_not_py3:
70
+ self.file_import.add_submodule_import("typing", "TYPE_CHECKING", ImportType.STDLIB)
73
71
 
74
72
  def _get_typing_definitions(self) -> str:
75
- if not self._file_import.type_definitions:
73
+ if not self.file_import.type_definitions:
76
74
  return ""
77
75
  spacing = "" if self.is_python3_file else " "
78
76
  declarations: List[str] = [f"\n{spacing}T = TypeVar('T')"]
@@ -82,27 +80,27 @@ class FileImportSerializer:
82
80
  type_name,
83
81
  values[1] if self.async_mode else values[0]
84
82
  )
85
- for type_name, values in self._file_import.type_definitions.items()
83
+ for type_name, values in self.file_import.type_definitions.items()
86
84
  ])
87
85
  return "\n".join(declarations)
88
86
 
89
87
  def __str__(self) -> str:
90
88
  self._add_type_checking_import()
91
89
  regular_imports = ""
92
- regular_imports_dict = self._get_imports_dict(
90
+ regular_imports_list = self._get_imports_list(
93
91
  baseline_typing_section=TypingSection.REGULAR, add_conditional_typing=self.is_python3_file
94
92
  )
95
93
 
96
- if regular_imports_dict:
94
+ if regular_imports_list:
97
95
  regular_imports = "\n\n".join(
98
- _get_import_clauses(regular_imports_dict, "\n")
96
+ _get_import_clauses(regular_imports_list, "\n")
99
97
  )
100
98
 
101
99
  typing_imports = ""
102
- typing_imports_dict = self._get_imports_dict(
100
+ typing_imports_list = self._get_imports_list(
103
101
  baseline_typing_section=TypingSection.TYPING, add_conditional_typing=not self.is_python3_file
104
102
  )
105
- if typing_imports_dict:
103
+ if typing_imports_list:
106
104
  typing_imports += "\n\nif TYPE_CHECKING:\n # pylint: disable=unused-import,ungrouped-imports\n "
107
- typing_imports += "\n\n ".join(_get_import_clauses(typing_imports_dict, "\n "))
105
+ typing_imports += "\n\n ".join(_get_import_clauses(typing_imports_list, "\n "))
108
106
  return regular_imports + typing_imports + self._get_typing_definitions()