@autorest/python 6.45.0 → 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 (35) 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 +26 -12
  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 +65 -9
  16. package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +14 -3
  17. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  18. package/generator/pygen/codegen/models/code_model.py +4 -0
  19. package/generator/pygen/codegen/models/enum_type.py +8 -1
  20. package/generator/pygen/codegen/models/list_type.py +6 -2
  21. package/generator/pygen/codegen/models/model_type.py +2 -2
  22. package/generator/pygen/codegen/models/operation.py +10 -1
  23. package/generator/pygen/codegen/models/operation_group.py +3 -1
  24. package/generator/pygen/codegen/models/request_builder.py +20 -3
  25. package/generator/pygen/codegen/models/response.py +2 -2
  26. package/generator/pygen/codegen/models/utils.py +7 -0
  27. package/generator/pygen/codegen/serializers/builder_serializer.py +26 -12
  28. package/generator/pygen/codegen/serializers/client_serializer.py +1 -2
  29. package/generator/pygen/codegen/serializers/general_serializer.py +1 -1
  30. package/generator/pygen/codegen/serializers/model_serializer.py +3 -0
  31. package/generator/pygen/codegen/templates/enum.py.jinja2 +3 -1
  32. package/generator/pygen/codegen/templates/model_base.py.jinja2 +65 -9
  33. package/generator/pygen/codegen/templates/serialization.py.jinja2 +14 -3
  34. package/package.json +2 -2
  35. 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
@@ -403,7 +403,12 @@ class RequestBuilderSerializer(_BuilderBaseSerializer[RequestBuilderType]):
403
403
  builder: RequestBuilderType,
404
404
  ) -> list[str]:
405
405
  def _get_value(param):
406
- declaration = param.get_declaration() if param.constant else None
406
+ if param.constant:
407
+ declaration = param.get_declaration()
408
+ elif param.client_default_value_declaration is not None:
409
+ declaration = param.client_default_value_declaration
410
+ else:
411
+ declaration = None
407
412
  if param.location in [ParameterLocation.HEADER, ParameterLocation.QUERY]:
408
413
  kwarg_dict = "headers" if param.location == ParameterLocation.HEADER else "params"
409
414
  return f"_{kwarg_dict}.pop('{param.wire_name}', {declaration})"
@@ -776,8 +781,14 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
776
781
  client_names = [
777
782
  overload.request_builder.parameters.body_parameter.client_name for overload in builder.overloads
778
783
  ]
779
- for v in sorted(set(client_names), key=client_names.index):
780
- 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")
781
792
  try:
782
793
  # if there is a binary overload, we do a binary check first.
783
794
  binary_overload = cast(
@@ -803,17 +814,20 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
803
814
  f'"{other_overload.parameters.body_parameter.default_content_type}"{check_body_suffix}'
804
815
  )
805
816
  except StopIteration:
806
- for idx, overload in enumerate(builder.overloads):
807
- if_statement = "if" if idx == 0 else "elif"
808
- body_param = overload.parameters.body_parameter
809
- retval.append(
810
- f"{if_statement} {body_param.type.instance_check_template.format(body_param.client_name)}:"
811
- )
812
- 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
813
823
  retval.append(
814
- 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)}:"
815
825
  )
816
- 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)))
817
831
  return retval
818
832
 
819
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):
@@ -382,9 +383,39 @@ class _MyMutableMapping(MutableMapping[str, typing.Any]):
382
383
  return key in self._data
383
384
 
384
385
  def __getitem__(self, key: str) -> typing.Any:
386
+ # If this key has been deserialized (for mutable types), we need to handle serialization
387
+ if hasattr(self, "_attr_to_rest_field"):
388
+ cache_attr = f"_deserialized_{key}"
389
+ if hasattr(self, cache_attr):
390
+ rf = _get_rest_field(getattr(self, "_attr_to_rest_field"), key)
391
+ if rf:
392
+ value = self._data.get(key)
393
+ if isinstance(value, (dict, list, set)):
394
+ # For mutable types, serialize and return
395
+ # But also update _data with serialized form and clear flag
396
+ # so mutations via this returned value affect _data
397
+ serialized = _serialize(value, rf._format)
398
+ # If serialized form is same type (no transformation needed),
399
+ # return _data directly so mutations work
400
+ if isinstance(serialized, type(value)) and serialized == value:
401
+ return self._data.get(key)
402
+ # Otherwise return serialized copy and clear flag
403
+ try:
404
+ object.__delattr__(self, cache_attr)
405
+ except AttributeError:
406
+ pass
407
+ # Store serialized form back
408
+ self._data[key] = serialized
409
+ return serialized
385
410
  return self._data.__getitem__(key)
386
411
 
387
412
  def __setitem__(self, key: str, value: typing.Any) -> None:
413
+ # Clear any cached deserialized value when setting through dictionary access
414
+ cache_attr = f"_deserialized_{key}"
415
+ try:
416
+ object.__delattr__(self, cache_attr)
417
+ except AttributeError:
418
+ pass
388
419
  self._data.__setitem__(key, value)
389
420
 
390
421
  def __delitem__(self, key: str) -> None:
@@ -886,16 +917,16 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=too-many-retur
886
917
 
887
918
  # is it optional?
888
919
  try:
889
- 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
890
921
  if len(annotation.__args__) <= 2: # pyright: ignore
891
922
  if_obj_deserializer = _get_deserialize_callable_from_annotation(
892
- 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
893
924
  )
894
925
 
895
926
  return functools.partial(_deserialize_with_optional, if_obj_deserializer)
896
927
  # the type is Optional[Union[...]], we need to remove the None type from the Union
897
928
  annotation_copy = copy.copy(annotation)
898
- 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
899
930
  return _get_deserialize_callable_from_annotation(annotation_copy, module, rf)
900
931
  except AttributeError:
901
932
  pass
@@ -1093,14 +1124,37 @@ class _RestField:
1093
1124
  def __get__(self, obj: Model, type=None): # pylint: disable=redefined-builtin
1094
1125
  # by this point, type and rest_name will have a value bc we default
1095
1126
  # them in __new__ of the Model class
1096
- item = obj.get(self._rest_name)
1127
+ # Use _data.get() directly to avoid triggering __getitem__ which clears the cache
1128
+ item = obj._data.get(self._rest_name)
1097
1129
  if item is None:
1098
1130
  return item
1099
1131
  if self._is_model:
1100
1132
  return item
1101
- return _deserialize(self._type, _serialize(item, self._format), rf=self)
1133
+
1134
+ # For mutable types, we want mutations to directly affect _data
1135
+ # Check if we've already deserialized this value
1136
+ cache_attr = f"_deserialized_{self._rest_name}"
1137
+ if hasattr(obj, cache_attr):
1138
+ # Return the value from _data directly (it's been deserialized in place)
1139
+ return obj._data.get(self._rest_name)
1140
+
1141
+ deserialized = _deserialize(self._type, _serialize(item, self._format), rf=self)
1142
+
1143
+ # For mutable types, store the deserialized value back in _data
1144
+ # so mutations directly affect _data
1145
+ if isinstance(deserialized, (dict, list, set)):
1146
+ obj._data[self._rest_name] = deserialized
1147
+ object.__setattr__(obj, cache_attr, True) # Mark as deserialized
1148
+ return deserialized
1149
+
1150
+ return deserialized
1102
1151
 
1103
1152
  def __set__(self, obj: Model, value) -> None:
1153
+ # Clear the cached deserialized object when setting a new value
1154
+ cache_attr = f"_deserialized_{self._rest_name}"
1155
+ if hasattr(obj, cache_attr):
1156
+ object.__delattr__(obj, cache_attr)
1157
+
1104
1158
  if value is None:
1105
1159
  # we want to wipe out entries if users set attr to None
1106
1160
  try:
@@ -1274,7 +1328,7 @@ def _get_wrapped_element(
1274
1328
  _get_element(v, exclude_readonly, meta, wrapped_element)
1275
1329
  else:
1276
1330
  wrapped_element.text = _get_primitive_type_value(v)
1277
- return wrapped_element
1331
+ return wrapped_element # type: ignore[no-any-return]
1278
1332
 
1279
1333
 
1280
1334
  def _get_primitive_type_value(v) -> str:
@@ -1287,7 +1341,9 @@ def _get_primitive_type_value(v) -> str:
1287
1341
  return str(v)
1288
1342
 
1289
1343
 
1290
- 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:
1291
1347
  if prefix and ns:
1292
1348
  ET.register_namespace(prefix, ns)
1293
1349
  if ns:
@@ -817,13 +817,20 @@ class Serializer: # pylint: disable=too-many-public-methods
817
817
  :param str data_type: Type of object in the iterable.
818
818
  :rtype: str, int, float, bool
819
819
  :return: serialized object
820
+ :raises TypeError: raise if data_type is not one of str, int, float, bool.
820
821
  """
821
822
  custom_serializer = cls._get_custom_serializers(data_type, **kwargs)
822
823
  if custom_serializer:
823
824
  return custom_serializer(data)
824
825
  if data_type == "str":
825
826
  return cls.serialize_unicode(data)
826
- return eval(data_type)(data) # nosec # pylint: disable=eval-used
827
+ if data_type == "int":
828
+ return int(data)
829
+ if data_type == "float":
830
+ return float(data)
831
+ if data_type == "bool":
832
+ return bool(data)
833
+ raise TypeError("Unknown basic data type: {}".format(data_type))
827
834
 
828
835
  @classmethod
829
836
  def serialize_unicode(cls, data):
@@ -1753,7 +1760,7 @@ class Deserializer:
1753
1760
  :param str data_type: deserialization data type.
1754
1761
  :return: Deserialized basic type.
1755
1762
  :rtype: str, int, float or bool
1756
- :raises TypeError: if string format is not valid.
1763
+ :raises TypeError: if string format is not valid or data_type is not one of str, int, float, bool.
1757
1764
  """
1758
1765
  # If we're here, data is supposed to be a basic type.
1759
1766
  # If it's still an XML node, take the text
@@ -1779,7 +1786,11 @@ class Deserializer:
1779
1786
 
1780
1787
  if data_type == "str":
1781
1788
  return self.deserialize_unicode(attr)
1782
- return eval(data_type)(attr) # nosec # pylint: disable=eval-used
1789
+ if data_type == "int":
1790
+ return int(attr)
1791
+ if data_type == "float":
1792
+ return float(attr)
1793
+ raise TypeError("Unknown basic data type: {}".format(data_type))
1783
1794
 
1784
1795
  @staticmethod
1785
1796
  def deserialize_unicode(data):
@@ -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
@@ -403,7 +403,12 @@ class RequestBuilderSerializer(_BuilderBaseSerializer[RequestBuilderType]):
403
403
  builder: RequestBuilderType,
404
404
  ) -> list[str]:
405
405
  def _get_value(param):
406
- declaration = param.get_declaration() if param.constant else None
406
+ if param.constant:
407
+ declaration = param.get_declaration()
408
+ elif param.client_default_value_declaration is not None:
409
+ declaration = param.client_default_value_declaration
410
+ else:
411
+ declaration = None
407
412
  if param.location in [ParameterLocation.HEADER, ParameterLocation.QUERY]:
408
413
  kwarg_dict = "headers" if param.location == ParameterLocation.HEADER else "params"
409
414
  return f"_{kwarg_dict}.pop('{param.wire_name}', {declaration})"
@@ -776,8 +781,14 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
776
781
  client_names = [
777
782
  overload.request_builder.parameters.body_parameter.client_name for overload in builder.overloads
778
783
  ]
779
- for v in sorted(set(client_names), key=client_names.index):
780
- 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")
781
792
  try:
782
793
  # if there is a binary overload, we do a binary check first.
783
794
  binary_overload = cast(
@@ -803,17 +814,20 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
803
814
  f'"{other_overload.parameters.body_parameter.default_content_type}"{check_body_suffix}'
804
815
  )
805
816
  except StopIteration:
806
- for idx, overload in enumerate(builder.overloads):
807
- if_statement = "if" if idx == 0 else "elif"
808
- body_param = overload.parameters.body_parameter
809
- retval.append(
810
- f"{if_statement} {body_param.type.instance_check_template.format(body_param.client_name)}:"
811
- )
812
- 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
813
823
  retval.append(
814
- 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)}:"
815
825
  )
816
- 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)))
817
831
  return retval
818
832
 
819
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):
@@ -382,9 +383,39 @@ class _MyMutableMapping(MutableMapping[str, typing.Any]):
382
383
  return key in self._data
383
384
 
384
385
  def __getitem__(self, key: str) -> typing.Any:
386
+ # If this key has been deserialized (for mutable types), we need to handle serialization
387
+ if hasattr(self, "_attr_to_rest_field"):
388
+ cache_attr = f"_deserialized_{key}"
389
+ if hasattr(self, cache_attr):
390
+ rf = _get_rest_field(getattr(self, "_attr_to_rest_field"), key)
391
+ if rf:
392
+ value = self._data.get(key)
393
+ if isinstance(value, (dict, list, set)):
394
+ # For mutable types, serialize and return
395
+ # But also update _data with serialized form and clear flag
396
+ # so mutations via this returned value affect _data
397
+ serialized = _serialize(value, rf._format)
398
+ # If serialized form is same type (no transformation needed),
399
+ # return _data directly so mutations work
400
+ if isinstance(serialized, type(value)) and serialized == value:
401
+ return self._data.get(key)
402
+ # Otherwise return serialized copy and clear flag
403
+ try:
404
+ object.__delattr__(self, cache_attr)
405
+ except AttributeError:
406
+ pass
407
+ # Store serialized form back
408
+ self._data[key] = serialized
409
+ return serialized
385
410
  return self._data.__getitem__(key)
386
411
 
387
412
  def __setitem__(self, key: str, value: typing.Any) -> None:
413
+ # Clear any cached deserialized value when setting through dictionary access
414
+ cache_attr = f"_deserialized_{key}"
415
+ try:
416
+ object.__delattr__(self, cache_attr)
417
+ except AttributeError:
418
+ pass
388
419
  self._data.__setitem__(key, value)
389
420
 
390
421
  def __delitem__(self, key: str) -> None:
@@ -886,16 +917,16 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=too-many-retur
886
917
 
887
918
  # is it optional?
888
919
  try:
889
- 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
890
921
  if len(annotation.__args__) <= 2: # pyright: ignore
891
922
  if_obj_deserializer = _get_deserialize_callable_from_annotation(
892
- 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
893
924
  )
894
925
 
895
926
  return functools.partial(_deserialize_with_optional, if_obj_deserializer)
896
927
  # the type is Optional[Union[...]], we need to remove the None type from the Union
897
928
  annotation_copy = copy.copy(annotation)
898
- 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
899
930
  return _get_deserialize_callable_from_annotation(annotation_copy, module, rf)
900
931
  except AttributeError:
901
932
  pass
@@ -1093,14 +1124,37 @@ class _RestField:
1093
1124
  def __get__(self, obj: Model, type=None): # pylint: disable=redefined-builtin
1094
1125
  # by this point, type and rest_name will have a value bc we default
1095
1126
  # them in __new__ of the Model class
1096
- item = obj.get(self._rest_name)
1127
+ # Use _data.get() directly to avoid triggering __getitem__ which clears the cache
1128
+ item = obj._data.get(self._rest_name)
1097
1129
  if item is None:
1098
1130
  return item
1099
1131
  if self._is_model:
1100
1132
  return item
1101
- return _deserialize(self._type, _serialize(item, self._format), rf=self)
1133
+
1134
+ # For mutable types, we want mutations to directly affect _data
1135
+ # Check if we've already deserialized this value
1136
+ cache_attr = f"_deserialized_{self._rest_name}"
1137
+ if hasattr(obj, cache_attr):
1138
+ # Return the value from _data directly (it's been deserialized in place)
1139
+ return obj._data.get(self._rest_name)
1140
+
1141
+ deserialized = _deserialize(self._type, _serialize(item, self._format), rf=self)
1142
+
1143
+ # For mutable types, store the deserialized value back in _data
1144
+ # so mutations directly affect _data
1145
+ if isinstance(deserialized, (dict, list, set)):
1146
+ obj._data[self._rest_name] = deserialized
1147
+ object.__setattr__(obj, cache_attr, True) # Mark as deserialized
1148
+ return deserialized
1149
+
1150
+ return deserialized
1102
1151
 
1103
1152
  def __set__(self, obj: Model, value) -> None:
1153
+ # Clear the cached deserialized object when setting a new value
1154
+ cache_attr = f"_deserialized_{self._rest_name}"
1155
+ if hasattr(obj, cache_attr):
1156
+ object.__delattr__(obj, cache_attr)
1157
+
1104
1158
  if value is None:
1105
1159
  # we want to wipe out entries if users set attr to None
1106
1160
  try:
@@ -1274,7 +1328,7 @@ def _get_wrapped_element(
1274
1328
  _get_element(v, exclude_readonly, meta, wrapped_element)
1275
1329
  else:
1276
1330
  wrapped_element.text = _get_primitive_type_value(v)
1277
- return wrapped_element
1331
+ return wrapped_element # type: ignore[no-any-return]
1278
1332
 
1279
1333
 
1280
1334
  def _get_primitive_type_value(v) -> str:
@@ -1287,7 +1341,9 @@ def _get_primitive_type_value(v) -> str:
1287
1341
  return str(v)
1288
1342
 
1289
1343
 
1290
- 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:
1291
1347
  if prefix and ns:
1292
1348
  ET.register_namespace(prefix, ns)
1293
1349
  if ns:
@@ -817,13 +817,20 @@ class Serializer: # pylint: disable=too-many-public-methods
817
817
  :param str data_type: Type of object in the iterable.
818
818
  :rtype: str, int, float, bool
819
819
  :return: serialized object
820
+ :raises TypeError: raise if data_type is not one of str, int, float, bool.
820
821
  """
821
822
  custom_serializer = cls._get_custom_serializers(data_type, **kwargs)
822
823
  if custom_serializer:
823
824
  return custom_serializer(data)
824
825
  if data_type == "str":
825
826
  return cls.serialize_unicode(data)
826
- return eval(data_type)(data) # nosec # pylint: disable=eval-used
827
+ if data_type == "int":
828
+ return int(data)
829
+ if data_type == "float":
830
+ return float(data)
831
+ if data_type == "bool":
832
+ return bool(data)
833
+ raise TypeError("Unknown basic data type: {}".format(data_type))
827
834
 
828
835
  @classmethod
829
836
  def serialize_unicode(cls, data):
@@ -1753,7 +1760,7 @@ class Deserializer:
1753
1760
  :param str data_type: deserialization data type.
1754
1761
  :return: Deserialized basic type.
1755
1762
  :rtype: str, int, float or bool
1756
- :raises TypeError: if string format is not valid.
1763
+ :raises TypeError: if string format is not valid or data_type is not one of str, int, float, bool.
1757
1764
  """
1758
1765
  # If we're here, data is supposed to be a basic type.
1759
1766
  # If it's still an XML node, take the text
@@ -1779,7 +1786,11 @@ class Deserializer:
1779
1786
 
1780
1787
  if data_type == "str":
1781
1788
  return self.deserialize_unicode(attr)
1782
- return eval(data_type)(attr) # nosec # pylint: disable=eval-used
1789
+ if data_type == "int":
1790
+ return int(attr)
1791
+ if data_type == "float":
1792
+ return float(attr)
1793
+ raise TypeError("Unknown basic data type: {}".format(data_type))
1783
1794
 
1784
1795
  @staticmethod
1785
1796
  def deserialize_unicode(data):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "6.45.0",
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.0",
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"