@autorest/python 6.45.1 → 6.46.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 (33) hide show
  1. package/generator/build/lib/pygen/codegen/models/code_model.py +4 -0
  2. package/generator/build/lib/pygen/codegen/models/enum_type.py +8 -1
  3. package/generator/build/lib/pygen/codegen/models/list_type.py +6 -2
  4. package/generator/build/lib/pygen/codegen/models/model_type.py +2 -2
  5. package/generator/build/lib/pygen/codegen/models/operation.py +10 -1
  6. package/generator/build/lib/pygen/codegen/models/operation_group.py +3 -1
  7. package/generator/build/lib/pygen/codegen/models/request_builder.py +20 -3
  8. package/generator/build/lib/pygen/codegen/models/response.py +2 -2
  9. package/generator/build/lib/pygen/codegen/models/utils.py +7 -0
  10. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +20 -11
  11. package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +1 -2
  12. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +1 -1
  13. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +3 -0
  14. package/generator/build/lib/pygen/codegen/templates/enum.py.jinja2 +3 -1
  15. package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +10 -7
  16. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  17. package/generator/pygen/codegen/models/code_model.py +4 -0
  18. package/generator/pygen/codegen/models/enum_type.py +8 -1
  19. package/generator/pygen/codegen/models/list_type.py +6 -2
  20. package/generator/pygen/codegen/models/model_type.py +2 -2
  21. package/generator/pygen/codegen/models/operation.py +10 -1
  22. package/generator/pygen/codegen/models/operation_group.py +3 -1
  23. package/generator/pygen/codegen/models/request_builder.py +20 -3
  24. package/generator/pygen/codegen/models/response.py +2 -2
  25. package/generator/pygen/codegen/models/utils.py +7 -0
  26. package/generator/pygen/codegen/serializers/builder_serializer.py +20 -11
  27. package/generator/pygen/codegen/serializers/client_serializer.py +1 -2
  28. package/generator/pygen/codegen/serializers/general_serializer.py +1 -1
  29. package/generator/pygen/codegen/serializers/model_serializer.py +3 -0
  30. package/generator/pygen/codegen/templates/enum.py.jinja2 +3 -1
  31. package/generator/pygen/codegen/templates/model_base.py.jinja2 +10 -7
  32. package/package.json +2 -2
  33. package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
@@ -491,6 +491,10 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
491
491
  def has_operation_named_list(self) -> bool:
492
492
  return any(o.name.lower() == "list" for c in self.clients for og in c.operation_groups for o in og.operations)
493
493
 
494
+ @property
495
+ def has_property_named_list(self) -> bool:
496
+ return any(p.client_name.lower() == "list" for m in self.model_types for p in m.properties)
497
+
494
498
  @property
495
499
  def has_padded_model_property(self) -> bool:
496
500
  for model_type in self.model_types:
@@ -7,7 +7,8 @@ from typing import Any, TYPE_CHECKING, Optional, cast
7
7
 
8
8
  from .base import BaseType
9
9
  from .imports import FileImport, ImportType, TypingSection
10
- from .utils import NamespaceType
10
+ from .utils import NamespaceType, add_to_pylint_disable
11
+ from ...utils import NAME_LENGTH_LIMIT
11
12
 
12
13
 
13
14
  if TYPE_CHECKING:
@@ -189,6 +190,12 @@ class EnumType(BaseType):
189
190
  return f"Union[{self.value_type.type_annotation(**kwargs)}, {model_name}]"
190
191
  return self.value_type.type_annotation(**kwargs)
191
192
 
193
+ def pylint_disable(self) -> str:
194
+ retval: str = ""
195
+ if len(self.name) > NAME_LENGTH_LIMIT:
196
+ retval = add_to_pylint_disable(retval, "name-too-long")
197
+ return retval
198
+
192
199
  def get_declaration(self, value: Any) -> str:
193
200
  return self.value_type.get_declaration(value)
194
201
 
@@ -41,8 +41,12 @@ class ListType(BaseType):
41
41
  # this means we're version tolerant XML, we just return the XML element
42
42
  return self.element_type.type_annotation(**kwargs)
43
43
 
44
- # if there is a function named `list` we have to make sure there's no conflict with the built-in `list`
45
- list_type = "List" if self.code_model.has_operation_named_list and kwargs.get("is_operation_file") else "list"
44
+ # if there is a function/property named `list` we have to make sure there's no conflict with the built-in `list`
45
+ is_operation_file = kwargs.get("is_operation_file", False)
46
+ use_list_import = (self.code_model.has_operation_named_list and is_operation_file) or (
47
+ self.code_model.has_property_named_list and not is_operation_file
48
+ )
49
+ list_type = "List" if use_list_import else "list"
46
50
  return f"{list_type}[{self.element_type.type_annotation(**kwargs)}]"
47
51
 
48
52
  def description(self, *, is_operation_file: bool) -> str:
@@ -7,7 +7,7 @@ from enum import Enum
7
7
  from collections import OrderedDict
8
8
  from typing import Any, Optional, TYPE_CHECKING, cast
9
9
  import sys
10
- from .utils import add_to_pylint_disable, NamespaceType
10
+ from .utils import add_to_pylint_disable, NamespaceType, LOCALS_LENGTH_LIMIT
11
11
  from .base import BaseType
12
12
  from .constant_type import ConstantType
13
13
  from .property import Property
@@ -244,7 +244,7 @@ class ModelType(BaseType): # pylint: disable=too-many-instance-attributes, too-
244
244
  @property
245
245
  def init_pylint_disable(self) -> str:
246
246
  retval: str = ""
247
- if len(self.properties) > 23:
247
+ if len(self.properties) > LOCALS_LENGTH_LIMIT:
248
248
  retval = add_to_pylint_disable(retval, "too-many-locals")
249
249
  return retval
250
250
 
@@ -16,7 +16,7 @@ from typing import (
16
16
 
17
17
  from .request_builder_parameter import RequestBuilderParameter
18
18
 
19
- from .utils import OrderedSet, add_to_pylint_disable
19
+ from .utils import OrderedSet, add_to_pylint_disable, LOCALS_LENGTH_LIMIT, OPERATION_BODY_VARIABLES_LENGTH
20
20
  from .base_builder import BaseBuilder
21
21
  from .imports import FileImport, ImportType, TypingSection
22
22
  from .response import (
@@ -143,6 +143,12 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
143
143
  retval = add_to_pylint_disable(retval, "inconsistent-return-statements")
144
144
  if len(self.name) > NAME_LENGTH_LIMIT:
145
145
  retval = add_to_pylint_disable(retval, "name-too-long")
146
+ method_params = self.parameters.method
147
+ if self.is_overload and len(method_params) > LOCALS_LENGTH_LIMIT:
148
+ retval = add_to_pylint_disable(retval, "too-many-locals")
149
+ elif not self.is_overload and len(method_params) > (LOCALS_LENGTH_LIMIT - OPERATION_BODY_VARIABLES_LENGTH):
150
+ retval = add_to_pylint_disable(retval, "too-many-locals")
151
+
146
152
  return retval
147
153
 
148
154
  def cls_type_annotation(self, *, async_mode: bool, **kwargs: Any) -> str:
@@ -408,6 +414,9 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
408
414
  file_import.merge(self.get_request_builder_import(self.request_builder, async_mode, serialize_namespace))
409
415
  if self.overloads:
410
416
  file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
417
+ for overload in self.overloads:
418
+ if overload.parameters.has_body:
419
+ file_import.merge(overload.parameters.body_parameter.type.imports(**kwargs))
411
420
  if self.code_model.options["models-mode"] == "dpg":
412
421
  relative_path = self.code_model.get_relative_import_path(
413
422
  serialize_namespace, module_name="_utils.model_base"
@@ -93,7 +93,9 @@ class OperationGroup(BaseModel):
93
93
  @property
94
94
  def need_validation(self) -> bool:
95
95
  """Whether any of its operations need validation"""
96
- return any(o for o in self.operations if o.need_validation)
96
+ return any(o for o in self.operations if o.need_validation) or any(
97
+ og for og in self.operation_groups if og.need_validation
98
+ )
97
99
 
98
100
  def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
99
101
  file_import = FileImport(self.code_model)
@@ -16,11 +16,12 @@ from typing import (
16
16
  from abc import abstractmethod
17
17
 
18
18
  from .base_builder import BaseBuilder
19
- from .utils import add_to_pylint_disable
19
+ from .utils import add_to_pylint_disable, LOCALS_LENGTH_LIMIT, REQUEST_BUILDER_BODY_VARIABLES_LENGTH
20
20
  from .parameter_list import (
21
21
  RequestBuilderParameterList,
22
22
  OverloadedRequestBuilderParameterList,
23
23
  )
24
+ from .parameter import ParameterLocation
24
25
  from .imports import FileImport, ImportType, TypingSection, MsrestImportType
25
26
  from ...utils import NAME_LENGTH_LIMIT
26
27
 
@@ -67,9 +68,25 @@ class RequestBuilderBase(BaseBuilder[ParameterListType, Sequence["RequestBuilder
67
68
  return self.yaml_data.get("discriminator") in ("lro", "lropaging")
68
69
 
69
70
  def pylint_disable(self, async_mode: bool) -> str:
71
+ retval = ""
70
72
  if len(self.name) > NAME_LENGTH_LIMIT:
71
- return add_to_pylint_disable("", "name-too-long")
72
- return ""
73
+ retval = add_to_pylint_disable(retval, "name-too-long")
74
+ method_params = self.parameters.method
75
+ if len(method_params) > LOCALS_LENGTH_LIMIT - REQUEST_BUILDER_BODY_VARIABLES_LENGTH:
76
+ retval = add_to_pylint_disable(retval, "too-many-locals")
77
+ if (
78
+ len(
79
+ [
80
+ p
81
+ for p in method_params
82
+ if p.optional and p.location in [ParameterLocation.HEADER, ParameterLocation.QUERY]
83
+ ]
84
+ )
85
+ > LOCALS_LENGTH_LIMIT
86
+ ):
87
+ retval = add_to_pylint_disable(retval, "too-many-statements")
88
+ retval = add_to_pylint_disable(retval, "too-many-branches")
89
+ return retval
73
90
 
74
91
  def response_type_annotation(self, **kwargs) -> str:
75
92
  return "HttpRequest"
@@ -233,7 +233,7 @@ class LROResponse(Response):
233
233
 
234
234
  def get_no_polling_method(self, async_mode: bool) -> str:
235
235
  """Get the default no polling method"""
236
- return self.get_no_polling_method_path(async_mode).split(".")[-1]
236
+ return self.get_no_polling_method_path(async_mode).rsplit(".", maxsplit=1)[-1]
237
237
 
238
238
  @staticmethod
239
239
  def get_base_polling_method_path(async_mode: bool) -> str:
@@ -242,7 +242,7 @@ class LROResponse(Response):
242
242
 
243
243
  def get_base_polling_method(self, async_mode: bool) -> str:
244
244
  """Get the base polling method."""
245
- return self.get_base_polling_method_path(async_mode).split(".")[-1]
245
+ return self.get_base_polling_method_path(async_mode).rsplit(".", maxsplit=1)[-1]
246
246
 
247
247
  def type_annotation(self, **kwargs: Any) -> str:
248
248
  return f"{self.get_poller(kwargs.get('async_mode', False))}[{super().type_annotation(**kwargs)}]"
@@ -30,3 +30,10 @@ class NamespaceType(str, Enum):
30
30
  OPERATION = "operation"
31
31
  CLIENT = "client"
32
32
  TYPES_FILE = "types_file"
33
+
34
+
35
+ LOCALS_LENGTH_LIMIT = 25
36
+
37
+ REQUEST_BUILDER_BODY_VARIABLES_LENGTH = 6 # how many body variables are present in a request builder
38
+
39
+ OPERATION_BODY_VARIABLES_LENGTH = 14 # how many body variables are present in an operation
@@ -781,8 +781,14 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
781
781
  client_names = [
782
782
  overload.request_builder.parameters.body_parameter.client_name for overload in builder.overloads
783
783
  ]
784
- for v in sorted(set(client_names), key=client_names.index):
785
- retval.append(f"_{v} = None")
784
+ all_dpg_model_overloads = False
785
+ if self.code_model.options["models-mode"] == "dpg" and builder.overloads:
786
+ all_dpg_model_overloads = all(
787
+ isinstance(o.parameters.body_parameter.type, DPGModelType) for o in builder.overloads
788
+ )
789
+ if not all_dpg_model_overloads:
790
+ for v in sorted(set(client_names), key=client_names.index):
791
+ retval.append(f"_{v} = None")
786
792
  try:
787
793
  # if there is a binary overload, we do a binary check first.
788
794
  binary_overload = cast(
@@ -808,17 +814,20 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
808
814
  f'"{other_overload.parameters.body_parameter.default_content_type}"{check_body_suffix}'
809
815
  )
810
816
  except StopIteration:
811
- for idx, overload in enumerate(builder.overloads):
812
- if_statement = "if" if idx == 0 else "elif"
813
- body_param = overload.parameters.body_parameter
814
- retval.append(
815
- f"{if_statement} {body_param.type.instance_check_template.format(body_param.client_name)}:"
816
- )
817
- if body_param.default_content_type and not same_content_type:
817
+ if all_dpg_model_overloads:
818
+ retval.extend(f"{l}" for l in self._create_body_parameter(cast(OperationType, builder.overloads[0])))
819
+ else:
820
+ for idx, overload in enumerate(builder.overloads):
821
+ if_statement = "if" if idx == 0 else "elif"
822
+ body_param = overload.parameters.body_parameter
818
823
  retval.append(
819
- f' content_type = content_type or "{body_param.default_content_type}"{check_body_suffix}'
824
+ f"{if_statement} {body_param.type.instance_check_template.format(body_param.client_name)}:"
820
825
  )
821
- retval.extend(f" {l}" for l in self._create_body_parameter(cast(OperationType, overload)))
826
+ if body_param.default_content_type and not same_content_type:
827
+ retval.append(
828
+ f' content_type = content_type or "{body_param.default_content_type}"{check_body_suffix}'
829
+ )
830
+ retval.extend(f" {l}" for l in self._create_body_parameter(cast(OperationType, overload)))
822
831
  return retval
823
832
 
824
833
  def _create_request_builder_call(
@@ -182,11 +182,10 @@ class ClientSerializer:
182
182
  retval.append("self._serialize.client_side_validation = False")
183
183
  operation_groups = [og for og in self.client.operation_groups if not og.is_mixin]
184
184
  for og in operation_groups:
185
- api_version = ""
186
185
  retval.extend(
187
186
  [
188
187
  f"self.{og.property_name} = {og.class_name}(",
189
- f" self._client, self._config, self._serialize, self._deserialize{api_version}",
188
+ " self._client, self._config, self._serialize, self._deserialize",
190
189
  ")",
191
190
  ]
192
191
  )
@@ -23,7 +23,7 @@ VERSION_MAP = {
23
23
  "msrest": "0.7.1",
24
24
  "isodate": "0.6.1",
25
25
  "azure-mgmt-core": "1.6.0",
26
- "azure-core": "1.36.0",
26
+ "azure-core": "1.37.0",
27
27
  "typing-extensions": "4.6.0",
28
28
  "corehttp": "1.0.0b6",
29
29
  }
@@ -285,6 +285,9 @@ class DpgModelSerializer(_ModelSerializer):
285
285
  file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
286
286
  file_import.add_submodule_import("typing", "Mapping", ImportType.STDLIB)
287
287
  file_import.add_submodule_import("typing", "Any", ImportType.STDLIB)
288
+ # if there is a property named `list` we have to make sure there's no conflict with the built-in `list`
289
+ if self.code_model.has_property_named_list:
290
+ file_import.define_mypy_type("List", "list")
288
291
  return file_import
289
292
 
290
293
  def declare_model(self, model: ModelType) -> str:
@@ -1,5 +1,7 @@
1
1
 
2
- class {{ enum.name }}({{ enum.value_type.type_annotation(is_operation_file=False) }}, Enum, metaclass=CaseInsensitiveEnumMeta):
2
+ class {{ enum.name }}({{enum.pylint_disable()}}
3
+ {{ enum.value_type.type_annotation(is_operation_file=False) }}, Enum, metaclass=CaseInsensitiveEnumMeta
4
+ ):
3
5
  {% if enum.yaml_data.get("description") %}
4
6
  """{{ op_tools.wrap_string(enum.yaml_data["description"], "\n ") }}
5
7
  """
@@ -36,6 +36,7 @@ __all__ = ["SdkJSONEncoder", "Model", "rest_field", "rest_discriminator"]
36
36
 
37
37
  TZ_UTC = timezone.utc
38
38
  _T = typing.TypeVar("_T")
39
+ _NONE_TYPE = type(None)
39
40
 
40
41
  {% if code_model.has_external_type %}
41
42
  TYPE_HANDLER_REGISTRY = TypeHandlerRegistry()
@@ -223,7 +224,7 @@ def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime:
223
224
  test_utc = date_obj.utctimetuple()
224
225
  if test_utc.tm_year > 9999 or test_utc.tm_year < 1:
225
226
  raise OverflowError("Hit max or min date")
226
- return date_obj
227
+ return date_obj # type: ignore[no-any-return]
227
228
 
228
229
 
229
230
  def _deserialize_datetime_rfc7231(attr: typing.Union[str, datetime]) -> datetime:
@@ -277,7 +278,7 @@ def _deserialize_time(attr: typing.Union[str, time]) -> time:
277
278
  """
278
279
  if isinstance(attr, time):
279
280
  return attr
280
- return isodate.parse_time(attr)
281
+ return isodate.parse_time(attr) # type: ignore[no-any-return]
281
282
 
282
283
 
283
284
  def _deserialize_bytes(attr):
@@ -916,16 +917,16 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=too-many-retur
916
917
 
917
918
  # is it optional?
918
919
  try:
919
- if any(a for a in annotation.__args__ if a == type(None)): # pyright: ignore
920
+ if any(a is _NONE_TYPE for a in annotation.__args__): # pyright: ignore
920
921
  if len(annotation.__args__) <= 2: # pyright: ignore
921
922
  if_obj_deserializer = _get_deserialize_callable_from_annotation(
922
- next(a for a in annotation.__args__ if a != type(None)), module, rf # pyright: ignore
923
+ next(a for a in annotation.__args__ if a is not _NONE_TYPE), module, rf # pyright: ignore
923
924
  )
924
925
 
925
926
  return functools.partial(_deserialize_with_optional, if_obj_deserializer)
926
927
  # the type is Optional[Union[...]], we need to remove the None type from the Union
927
928
  annotation_copy = copy.copy(annotation)
928
- annotation_copy.__args__ = [a for a in annotation_copy.__args__ if a != type(None)] # pyright: ignore
929
+ annotation_copy.__args__ = [a for a in annotation_copy.__args__ if a is not _NONE_TYPE] # pyright: ignore
929
930
  return _get_deserialize_callable_from_annotation(annotation_copy, module, rf)
930
931
  except AttributeError:
931
932
  pass
@@ -1327,7 +1328,7 @@ def _get_wrapped_element(
1327
1328
  _get_element(v, exclude_readonly, meta, wrapped_element)
1328
1329
  else:
1329
1330
  wrapped_element.text = _get_primitive_type_value(v)
1330
- return wrapped_element
1331
+ return wrapped_element # type: ignore[no-any-return]
1331
1332
 
1332
1333
 
1333
1334
  def _get_primitive_type_value(v) -> str:
@@ -1340,7 +1341,9 @@ def _get_primitive_type_value(v) -> str:
1340
1341
  return str(v)
1341
1342
 
1342
1343
 
1343
- def _create_xml_element(tag, prefix=None, ns=None):
1344
+ def _create_xml_element(
1345
+ tag: typing.Any, prefix: typing.Optional[str] = None, ns: typing.Optional[str] = None
1346
+ ) -> ET.Element:
1344
1347
  if prefix and ns:
1345
1348
  ET.register_namespace(prefix, ns)
1346
1349
  if ns:
@@ -491,6 +491,10 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
491
491
  def has_operation_named_list(self) -> bool:
492
492
  return any(o.name.lower() == "list" for c in self.clients for og in c.operation_groups for o in og.operations)
493
493
 
494
+ @property
495
+ def has_property_named_list(self) -> bool:
496
+ return any(p.client_name.lower() == "list" for m in self.model_types for p in m.properties)
497
+
494
498
  @property
495
499
  def has_padded_model_property(self) -> bool:
496
500
  for model_type in self.model_types:
@@ -7,7 +7,8 @@ from typing import Any, TYPE_CHECKING, Optional, cast
7
7
 
8
8
  from .base import BaseType
9
9
  from .imports import FileImport, ImportType, TypingSection
10
- from .utils import NamespaceType
10
+ from .utils import NamespaceType, add_to_pylint_disable
11
+ from ...utils import NAME_LENGTH_LIMIT
11
12
 
12
13
 
13
14
  if TYPE_CHECKING:
@@ -189,6 +190,12 @@ class EnumType(BaseType):
189
190
  return f"Union[{self.value_type.type_annotation(**kwargs)}, {model_name}]"
190
191
  return self.value_type.type_annotation(**kwargs)
191
192
 
193
+ def pylint_disable(self) -> str:
194
+ retval: str = ""
195
+ if len(self.name) > NAME_LENGTH_LIMIT:
196
+ retval = add_to_pylint_disable(retval, "name-too-long")
197
+ return retval
198
+
192
199
  def get_declaration(self, value: Any) -> str:
193
200
  return self.value_type.get_declaration(value)
194
201
 
@@ -41,8 +41,12 @@ class ListType(BaseType):
41
41
  # this means we're version tolerant XML, we just return the XML element
42
42
  return self.element_type.type_annotation(**kwargs)
43
43
 
44
- # if there is a function named `list` we have to make sure there's no conflict with the built-in `list`
45
- list_type = "List" if self.code_model.has_operation_named_list and kwargs.get("is_operation_file") else "list"
44
+ # if there is a function/property named `list` we have to make sure there's no conflict with the built-in `list`
45
+ is_operation_file = kwargs.get("is_operation_file", False)
46
+ use_list_import = (self.code_model.has_operation_named_list and is_operation_file) or (
47
+ self.code_model.has_property_named_list and not is_operation_file
48
+ )
49
+ list_type = "List" if use_list_import else "list"
46
50
  return f"{list_type}[{self.element_type.type_annotation(**kwargs)}]"
47
51
 
48
52
  def description(self, *, is_operation_file: bool) -> str:
@@ -7,7 +7,7 @@ from enum import Enum
7
7
  from collections import OrderedDict
8
8
  from typing import Any, Optional, TYPE_CHECKING, cast
9
9
  import sys
10
- from .utils import add_to_pylint_disable, NamespaceType
10
+ from .utils import add_to_pylint_disable, NamespaceType, LOCALS_LENGTH_LIMIT
11
11
  from .base import BaseType
12
12
  from .constant_type import ConstantType
13
13
  from .property import Property
@@ -244,7 +244,7 @@ class ModelType(BaseType): # pylint: disable=too-many-instance-attributes, too-
244
244
  @property
245
245
  def init_pylint_disable(self) -> str:
246
246
  retval: str = ""
247
- if len(self.properties) > 23:
247
+ if len(self.properties) > LOCALS_LENGTH_LIMIT:
248
248
  retval = add_to_pylint_disable(retval, "too-many-locals")
249
249
  return retval
250
250
 
@@ -16,7 +16,7 @@ from typing import (
16
16
 
17
17
  from .request_builder_parameter import RequestBuilderParameter
18
18
 
19
- from .utils import OrderedSet, add_to_pylint_disable
19
+ from .utils import OrderedSet, add_to_pylint_disable, LOCALS_LENGTH_LIMIT, OPERATION_BODY_VARIABLES_LENGTH
20
20
  from .base_builder import BaseBuilder
21
21
  from .imports import FileImport, ImportType, TypingSection
22
22
  from .response import (
@@ -143,6 +143,12 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
143
143
  retval = add_to_pylint_disable(retval, "inconsistent-return-statements")
144
144
  if len(self.name) > NAME_LENGTH_LIMIT:
145
145
  retval = add_to_pylint_disable(retval, "name-too-long")
146
+ method_params = self.parameters.method
147
+ if self.is_overload and len(method_params) > LOCALS_LENGTH_LIMIT:
148
+ retval = add_to_pylint_disable(retval, "too-many-locals")
149
+ elif not self.is_overload and len(method_params) > (LOCALS_LENGTH_LIMIT - OPERATION_BODY_VARIABLES_LENGTH):
150
+ retval = add_to_pylint_disable(retval, "too-many-locals")
151
+
146
152
  return retval
147
153
 
148
154
  def cls_type_annotation(self, *, async_mode: bool, **kwargs: Any) -> str:
@@ -408,6 +414,9 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
408
414
  file_import.merge(self.get_request_builder_import(self.request_builder, async_mode, serialize_namespace))
409
415
  if self.overloads:
410
416
  file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
417
+ for overload in self.overloads:
418
+ if overload.parameters.has_body:
419
+ file_import.merge(overload.parameters.body_parameter.type.imports(**kwargs))
411
420
  if self.code_model.options["models-mode"] == "dpg":
412
421
  relative_path = self.code_model.get_relative_import_path(
413
422
  serialize_namespace, module_name="_utils.model_base"
@@ -93,7 +93,9 @@ class OperationGroup(BaseModel):
93
93
  @property
94
94
  def need_validation(self) -> bool:
95
95
  """Whether any of its operations need validation"""
96
- return any(o for o in self.operations if o.need_validation)
96
+ return any(o for o in self.operations if o.need_validation) or any(
97
+ og for og in self.operation_groups if og.need_validation
98
+ )
97
99
 
98
100
  def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
99
101
  file_import = FileImport(self.code_model)
@@ -16,11 +16,12 @@ from typing import (
16
16
  from abc import abstractmethod
17
17
 
18
18
  from .base_builder import BaseBuilder
19
- from .utils import add_to_pylint_disable
19
+ from .utils import add_to_pylint_disable, LOCALS_LENGTH_LIMIT, REQUEST_BUILDER_BODY_VARIABLES_LENGTH
20
20
  from .parameter_list import (
21
21
  RequestBuilderParameterList,
22
22
  OverloadedRequestBuilderParameterList,
23
23
  )
24
+ from .parameter import ParameterLocation
24
25
  from .imports import FileImport, ImportType, TypingSection, MsrestImportType
25
26
  from ...utils import NAME_LENGTH_LIMIT
26
27
 
@@ -67,9 +68,25 @@ class RequestBuilderBase(BaseBuilder[ParameterListType, Sequence["RequestBuilder
67
68
  return self.yaml_data.get("discriminator") in ("lro", "lropaging")
68
69
 
69
70
  def pylint_disable(self, async_mode: bool) -> str:
71
+ retval = ""
70
72
  if len(self.name) > NAME_LENGTH_LIMIT:
71
- return add_to_pylint_disable("", "name-too-long")
72
- return ""
73
+ retval = add_to_pylint_disable(retval, "name-too-long")
74
+ method_params = self.parameters.method
75
+ if len(method_params) > LOCALS_LENGTH_LIMIT - REQUEST_BUILDER_BODY_VARIABLES_LENGTH:
76
+ retval = add_to_pylint_disable(retval, "too-many-locals")
77
+ if (
78
+ len(
79
+ [
80
+ p
81
+ for p in method_params
82
+ if p.optional and p.location in [ParameterLocation.HEADER, ParameterLocation.QUERY]
83
+ ]
84
+ )
85
+ > LOCALS_LENGTH_LIMIT
86
+ ):
87
+ retval = add_to_pylint_disable(retval, "too-many-statements")
88
+ retval = add_to_pylint_disable(retval, "too-many-branches")
89
+ return retval
73
90
 
74
91
  def response_type_annotation(self, **kwargs) -> str:
75
92
  return "HttpRequest"
@@ -233,7 +233,7 @@ class LROResponse(Response):
233
233
 
234
234
  def get_no_polling_method(self, async_mode: bool) -> str:
235
235
  """Get the default no polling method"""
236
- return self.get_no_polling_method_path(async_mode).split(".")[-1]
236
+ return self.get_no_polling_method_path(async_mode).rsplit(".", maxsplit=1)[-1]
237
237
 
238
238
  @staticmethod
239
239
  def get_base_polling_method_path(async_mode: bool) -> str:
@@ -242,7 +242,7 @@ class LROResponse(Response):
242
242
 
243
243
  def get_base_polling_method(self, async_mode: bool) -> str:
244
244
  """Get the base polling method."""
245
- return self.get_base_polling_method_path(async_mode).split(".")[-1]
245
+ return self.get_base_polling_method_path(async_mode).rsplit(".", maxsplit=1)[-1]
246
246
 
247
247
  def type_annotation(self, **kwargs: Any) -> str:
248
248
  return f"{self.get_poller(kwargs.get('async_mode', False))}[{super().type_annotation(**kwargs)}]"
@@ -30,3 +30,10 @@ class NamespaceType(str, Enum):
30
30
  OPERATION = "operation"
31
31
  CLIENT = "client"
32
32
  TYPES_FILE = "types_file"
33
+
34
+
35
+ LOCALS_LENGTH_LIMIT = 25
36
+
37
+ REQUEST_BUILDER_BODY_VARIABLES_LENGTH = 6 # how many body variables are present in a request builder
38
+
39
+ OPERATION_BODY_VARIABLES_LENGTH = 14 # how many body variables are present in an operation
@@ -781,8 +781,14 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
781
781
  client_names = [
782
782
  overload.request_builder.parameters.body_parameter.client_name for overload in builder.overloads
783
783
  ]
784
- for v in sorted(set(client_names), key=client_names.index):
785
- retval.append(f"_{v} = None")
784
+ all_dpg_model_overloads = False
785
+ if self.code_model.options["models-mode"] == "dpg" and builder.overloads:
786
+ all_dpg_model_overloads = all(
787
+ isinstance(o.parameters.body_parameter.type, DPGModelType) for o in builder.overloads
788
+ )
789
+ if not all_dpg_model_overloads:
790
+ for v in sorted(set(client_names), key=client_names.index):
791
+ retval.append(f"_{v} = None")
786
792
  try:
787
793
  # if there is a binary overload, we do a binary check first.
788
794
  binary_overload = cast(
@@ -808,17 +814,20 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
808
814
  f'"{other_overload.parameters.body_parameter.default_content_type}"{check_body_suffix}'
809
815
  )
810
816
  except StopIteration:
811
- for idx, overload in enumerate(builder.overloads):
812
- if_statement = "if" if idx == 0 else "elif"
813
- body_param = overload.parameters.body_parameter
814
- retval.append(
815
- f"{if_statement} {body_param.type.instance_check_template.format(body_param.client_name)}:"
816
- )
817
- if body_param.default_content_type and not same_content_type:
817
+ if all_dpg_model_overloads:
818
+ retval.extend(f"{l}" for l in self._create_body_parameter(cast(OperationType, builder.overloads[0])))
819
+ else:
820
+ for idx, overload in enumerate(builder.overloads):
821
+ if_statement = "if" if idx == 0 else "elif"
822
+ body_param = overload.parameters.body_parameter
818
823
  retval.append(
819
- f' content_type = content_type or "{body_param.default_content_type}"{check_body_suffix}'
824
+ f"{if_statement} {body_param.type.instance_check_template.format(body_param.client_name)}:"
820
825
  )
821
- retval.extend(f" {l}" for l in self._create_body_parameter(cast(OperationType, overload)))
826
+ if body_param.default_content_type and not same_content_type:
827
+ retval.append(
828
+ f' content_type = content_type or "{body_param.default_content_type}"{check_body_suffix}'
829
+ )
830
+ retval.extend(f" {l}" for l in self._create_body_parameter(cast(OperationType, overload)))
822
831
  return retval
823
832
 
824
833
  def _create_request_builder_call(
@@ -182,11 +182,10 @@ class ClientSerializer:
182
182
  retval.append("self._serialize.client_side_validation = False")
183
183
  operation_groups = [og for og in self.client.operation_groups if not og.is_mixin]
184
184
  for og in operation_groups:
185
- api_version = ""
186
185
  retval.extend(
187
186
  [
188
187
  f"self.{og.property_name} = {og.class_name}(",
189
- f" self._client, self._config, self._serialize, self._deserialize{api_version}",
188
+ " self._client, self._config, self._serialize, self._deserialize",
190
189
  ")",
191
190
  ]
192
191
  )
@@ -23,7 +23,7 @@ VERSION_MAP = {
23
23
  "msrest": "0.7.1",
24
24
  "isodate": "0.6.1",
25
25
  "azure-mgmt-core": "1.6.0",
26
- "azure-core": "1.36.0",
26
+ "azure-core": "1.37.0",
27
27
  "typing-extensions": "4.6.0",
28
28
  "corehttp": "1.0.0b6",
29
29
  }
@@ -285,6 +285,9 @@ class DpgModelSerializer(_ModelSerializer):
285
285
  file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
286
286
  file_import.add_submodule_import("typing", "Mapping", ImportType.STDLIB)
287
287
  file_import.add_submodule_import("typing", "Any", ImportType.STDLIB)
288
+ # if there is a property named `list` we have to make sure there's no conflict with the built-in `list`
289
+ if self.code_model.has_property_named_list:
290
+ file_import.define_mypy_type("List", "list")
288
291
  return file_import
289
292
 
290
293
  def declare_model(self, model: ModelType) -> str:
@@ -1,5 +1,7 @@
1
1
 
2
- class {{ enum.name }}({{ enum.value_type.type_annotation(is_operation_file=False) }}, Enum, metaclass=CaseInsensitiveEnumMeta):
2
+ class {{ enum.name }}({{enum.pylint_disable()}}
3
+ {{ enum.value_type.type_annotation(is_operation_file=False) }}, Enum, metaclass=CaseInsensitiveEnumMeta
4
+ ):
3
5
  {% if enum.yaml_data.get("description") %}
4
6
  """{{ op_tools.wrap_string(enum.yaml_data["description"], "\n ") }}
5
7
  """
@@ -36,6 +36,7 @@ __all__ = ["SdkJSONEncoder", "Model", "rest_field", "rest_discriminator"]
36
36
 
37
37
  TZ_UTC = timezone.utc
38
38
  _T = typing.TypeVar("_T")
39
+ _NONE_TYPE = type(None)
39
40
 
40
41
  {% if code_model.has_external_type %}
41
42
  TYPE_HANDLER_REGISTRY = TypeHandlerRegistry()
@@ -223,7 +224,7 @@ def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime:
223
224
  test_utc = date_obj.utctimetuple()
224
225
  if test_utc.tm_year > 9999 or test_utc.tm_year < 1:
225
226
  raise OverflowError("Hit max or min date")
226
- return date_obj
227
+ return date_obj # type: ignore[no-any-return]
227
228
 
228
229
 
229
230
  def _deserialize_datetime_rfc7231(attr: typing.Union[str, datetime]) -> datetime:
@@ -277,7 +278,7 @@ def _deserialize_time(attr: typing.Union[str, time]) -> time:
277
278
  """
278
279
  if isinstance(attr, time):
279
280
  return attr
280
- return isodate.parse_time(attr)
281
+ return isodate.parse_time(attr) # type: ignore[no-any-return]
281
282
 
282
283
 
283
284
  def _deserialize_bytes(attr):
@@ -916,16 +917,16 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=too-many-retur
916
917
 
917
918
  # is it optional?
918
919
  try:
919
- if any(a for a in annotation.__args__ if a == type(None)): # pyright: ignore
920
+ if any(a is _NONE_TYPE for a in annotation.__args__): # pyright: ignore
920
921
  if len(annotation.__args__) <= 2: # pyright: ignore
921
922
  if_obj_deserializer = _get_deserialize_callable_from_annotation(
922
- next(a for a in annotation.__args__ if a != type(None)), module, rf # pyright: ignore
923
+ next(a for a in annotation.__args__ if a is not _NONE_TYPE), module, rf # pyright: ignore
923
924
  )
924
925
 
925
926
  return functools.partial(_deserialize_with_optional, if_obj_deserializer)
926
927
  # the type is Optional[Union[...]], we need to remove the None type from the Union
927
928
  annotation_copy = copy.copy(annotation)
928
- annotation_copy.__args__ = [a for a in annotation_copy.__args__ if a != type(None)] # pyright: ignore
929
+ annotation_copy.__args__ = [a for a in annotation_copy.__args__ if a is not _NONE_TYPE] # pyright: ignore
929
930
  return _get_deserialize_callable_from_annotation(annotation_copy, module, rf)
930
931
  except AttributeError:
931
932
  pass
@@ -1327,7 +1328,7 @@ def _get_wrapped_element(
1327
1328
  _get_element(v, exclude_readonly, meta, wrapped_element)
1328
1329
  else:
1329
1330
  wrapped_element.text = _get_primitive_type_value(v)
1330
- return wrapped_element
1331
+ return wrapped_element # type: ignore[no-any-return]
1331
1332
 
1332
1333
 
1333
1334
  def _get_primitive_type_value(v) -> str:
@@ -1340,7 +1341,9 @@ def _get_primitive_type_value(v) -> str:
1340
1341
  return str(v)
1341
1342
 
1342
1343
 
1343
- def _create_xml_element(tag, prefix=None, ns=None):
1344
+ def _create_xml_element(
1345
+ tag: typing.Any, prefix: typing.Optional[str] = None, ns: typing.Optional[str] = None
1346
+ ) -> ET.Element:
1344
1347
  if prefix and ns:
1345
1348
  ET.register_namespace(prefix, ns)
1346
1349
  if ns:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "6.45.1",
3
+ "version": "6.46.0",
4
4
  "description": "The Python extension for generators in AutoRest.",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "homepage": "https://github.com/Azure/autorest.python/blob/main/README.md",
21
21
  "dependencies": {
22
- "@typespec/http-client-python": "~0.23.1",
22
+ "@typespec/http-client-python": "~0.24.0",
23
23
  "@autorest/system-requirements": "~1.0.2",
24
24
  "fs-extra": "~11.2.0",
25
25
  "tsx": "~4.19.1"