@autorest/python 6.45.0 → 6.45.1

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.
@@ -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})"
@@ -382,9 +382,39 @@ class _MyMutableMapping(MutableMapping[str, typing.Any]):
382
382
  return key in self._data
383
383
 
384
384
  def __getitem__(self, key: str) -> typing.Any:
385
+ # If this key has been deserialized (for mutable types), we need to handle serialization
386
+ if hasattr(self, "_attr_to_rest_field"):
387
+ cache_attr = f"_deserialized_{key}"
388
+ if hasattr(self, cache_attr):
389
+ rf = _get_rest_field(getattr(self, "_attr_to_rest_field"), key)
390
+ if rf:
391
+ value = self._data.get(key)
392
+ if isinstance(value, (dict, list, set)):
393
+ # For mutable types, serialize and return
394
+ # But also update _data with serialized form and clear flag
395
+ # so mutations via this returned value affect _data
396
+ serialized = _serialize(value, rf._format)
397
+ # If serialized form is same type (no transformation needed),
398
+ # return _data directly so mutations work
399
+ if isinstance(serialized, type(value)) and serialized == value:
400
+ return self._data.get(key)
401
+ # Otherwise return serialized copy and clear flag
402
+ try:
403
+ object.__delattr__(self, cache_attr)
404
+ except AttributeError:
405
+ pass
406
+ # Store serialized form back
407
+ self._data[key] = serialized
408
+ return serialized
385
409
  return self._data.__getitem__(key)
386
410
 
387
411
  def __setitem__(self, key: str, value: typing.Any) -> None:
412
+ # Clear any cached deserialized value when setting through dictionary access
413
+ cache_attr = f"_deserialized_{key}"
414
+ try:
415
+ object.__delattr__(self, cache_attr)
416
+ except AttributeError:
417
+ pass
388
418
  self._data.__setitem__(key, value)
389
419
 
390
420
  def __delitem__(self, key: str) -> None:
@@ -1093,14 +1123,37 @@ class _RestField:
1093
1123
  def __get__(self, obj: Model, type=None): # pylint: disable=redefined-builtin
1094
1124
  # by this point, type and rest_name will have a value bc we default
1095
1125
  # them in __new__ of the Model class
1096
- item = obj.get(self._rest_name)
1126
+ # Use _data.get() directly to avoid triggering __getitem__ which clears the cache
1127
+ item = obj._data.get(self._rest_name)
1097
1128
  if item is None:
1098
1129
  return item
1099
1130
  if self._is_model:
1100
1131
  return item
1101
- return _deserialize(self._type, _serialize(item, self._format), rf=self)
1132
+
1133
+ # For mutable types, we want mutations to directly affect _data
1134
+ # Check if we've already deserialized this value
1135
+ cache_attr = f"_deserialized_{self._rest_name}"
1136
+ if hasattr(obj, cache_attr):
1137
+ # Return the value from _data directly (it's been deserialized in place)
1138
+ return obj._data.get(self._rest_name)
1139
+
1140
+ deserialized = _deserialize(self._type, _serialize(item, self._format), rf=self)
1141
+
1142
+ # For mutable types, store the deserialized value back in _data
1143
+ # so mutations directly affect _data
1144
+ if isinstance(deserialized, (dict, list, set)):
1145
+ obj._data[self._rest_name] = deserialized
1146
+ object.__setattr__(obj, cache_attr, True) # Mark as deserialized
1147
+ return deserialized
1148
+
1149
+ return deserialized
1102
1150
 
1103
1151
  def __set__(self, obj: Model, value) -> None:
1152
+ # Clear the cached deserialized object when setting a new value
1153
+ cache_attr = f"_deserialized_{self._rest_name}"
1154
+ if hasattr(obj, cache_attr):
1155
+ object.__delattr__(obj, cache_attr)
1156
+
1104
1157
  if value is None:
1105
1158
  # we want to wipe out entries if users set attr to None
1106
1159
  try:
@@ -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):
@@ -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})"
@@ -382,9 +382,39 @@ class _MyMutableMapping(MutableMapping[str, typing.Any]):
382
382
  return key in self._data
383
383
 
384
384
  def __getitem__(self, key: str) -> typing.Any:
385
+ # If this key has been deserialized (for mutable types), we need to handle serialization
386
+ if hasattr(self, "_attr_to_rest_field"):
387
+ cache_attr = f"_deserialized_{key}"
388
+ if hasattr(self, cache_attr):
389
+ rf = _get_rest_field(getattr(self, "_attr_to_rest_field"), key)
390
+ if rf:
391
+ value = self._data.get(key)
392
+ if isinstance(value, (dict, list, set)):
393
+ # For mutable types, serialize and return
394
+ # But also update _data with serialized form and clear flag
395
+ # so mutations via this returned value affect _data
396
+ serialized = _serialize(value, rf._format)
397
+ # If serialized form is same type (no transformation needed),
398
+ # return _data directly so mutations work
399
+ if isinstance(serialized, type(value)) and serialized == value:
400
+ return self._data.get(key)
401
+ # Otherwise return serialized copy and clear flag
402
+ try:
403
+ object.__delattr__(self, cache_attr)
404
+ except AttributeError:
405
+ pass
406
+ # Store serialized form back
407
+ self._data[key] = serialized
408
+ return serialized
385
409
  return self._data.__getitem__(key)
386
410
 
387
411
  def __setitem__(self, key: str, value: typing.Any) -> None:
412
+ # Clear any cached deserialized value when setting through dictionary access
413
+ cache_attr = f"_deserialized_{key}"
414
+ try:
415
+ object.__delattr__(self, cache_attr)
416
+ except AttributeError:
417
+ pass
388
418
  self._data.__setitem__(key, value)
389
419
 
390
420
  def __delitem__(self, key: str) -> None:
@@ -1093,14 +1123,37 @@ class _RestField:
1093
1123
  def __get__(self, obj: Model, type=None): # pylint: disable=redefined-builtin
1094
1124
  # by this point, type and rest_name will have a value bc we default
1095
1125
  # them in __new__ of the Model class
1096
- item = obj.get(self._rest_name)
1126
+ # Use _data.get() directly to avoid triggering __getitem__ which clears the cache
1127
+ item = obj._data.get(self._rest_name)
1097
1128
  if item is None:
1098
1129
  return item
1099
1130
  if self._is_model:
1100
1131
  return item
1101
- return _deserialize(self._type, _serialize(item, self._format), rf=self)
1132
+
1133
+ # For mutable types, we want mutations to directly affect _data
1134
+ # Check if we've already deserialized this value
1135
+ cache_attr = f"_deserialized_{self._rest_name}"
1136
+ if hasattr(obj, cache_attr):
1137
+ # Return the value from _data directly (it's been deserialized in place)
1138
+ return obj._data.get(self._rest_name)
1139
+
1140
+ deserialized = _deserialize(self._type, _serialize(item, self._format), rf=self)
1141
+
1142
+ # For mutable types, store the deserialized value back in _data
1143
+ # so mutations directly affect _data
1144
+ if isinstance(deserialized, (dict, list, set)):
1145
+ obj._data[self._rest_name] = deserialized
1146
+ object.__setattr__(obj, cache_attr, True) # Mark as deserialized
1147
+ return deserialized
1148
+
1149
+ return deserialized
1102
1150
 
1103
1151
  def __set__(self, obj: Model, value) -> None:
1152
+ # Clear the cached deserialized object when setting a new value
1153
+ cache_attr = f"_deserialized_{self._rest_name}"
1154
+ if hasattr(obj, cache_attr):
1155
+ object.__delattr__(obj, cache_attr)
1156
+
1104
1157
  if value is None:
1105
1158
  # we want to wipe out entries if users set attr to None
1106
1159
  try:
@@ -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.45.1",
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.23.1",
23
23
  "@autorest/system-requirements": "~1.0.2",
24
24
  "fs-extra": "~11.2.0",
25
25
  "tsx": "~4.19.1"