@autorest/python 6.44.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.
@@ -40,6 +40,7 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
40
40
  self.is_multipart_file_input: bool = yaml_data.get("isMultipartFileInput", False)
41
41
  self.flatten = self.yaml_data.get("flatten", False) and not getattr(self.type, "flattened_property", False)
42
42
  self.original_tsp_name: Optional[str] = self.yaml_data.get("originalTspName")
43
+ self.encode: Optional[str] = self.yaml_data.get("encode")
43
44
 
44
45
  def pylint_disable(self) -> str:
45
46
  retval: str = ""
@@ -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})"
@@ -329,6 +329,8 @@ class DpgModelSerializer(_ModelSerializer):
329
329
  args.append("is_multipart_file_input=True")
330
330
  elif hasattr(prop.type, "encode") and prop.type.encode: # type: ignore
331
331
  args.append(f'format="{prop.type.encode}"') # type: ignore
332
+ elif prop.encode:
333
+ args.append(f'format="{prop.encode}"')
332
334
 
333
335
  if prop.xml_metadata:
334
336
  args.append(f"xml={prop.xml_metadata}")
@@ -5,21 +5,28 @@
5
5
  {% set enable_custom_handling = "\n* " in doc_string or doc_string.startswith("* ") %}
6
6
  {%- if enable_custom_handling -%}
7
7
  {%- set lines = doc_string.split('\n') -%}
8
+ {%- set base_indent = wrap_string.lstrip('\n') -%}
8
9
  {%- set result_lines = [] -%}
9
10
  {%- for line in lines -%}
10
11
  {%- if line.startswith('* ') -%}
11
12
  {# Handle bullet points with proper continuation alignment #}
12
13
  {%- set bullet_content = line[2:] -%}
13
- {%- set base_indent = wrap_string.lstrip('\n') -%}
14
14
  {%- set bullet_line = base_indent + ' * ' + bullet_content -%}
15
15
  {%- set continuation_spaces = base_indent + ' ' -%}
16
16
  {%- set wrapped = bullet_line | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring='\n' + continuation_spaces) -%}
17
17
  {%- set _ = result_lines.append(wrapped) -%}
18
18
  {%- elif line.strip() -%}
19
- {%- set wrapped = line.strip() | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring=wrap_string) -%}
20
- {%- set _ = result_lines.append(wrapped) -%}
19
+ {%- set line_indent = '' if line.strip().startswith(':') or loop.index == 1 else (base_indent + ' ') -%}
20
+ {%- set wrapped = (line_indent + line) | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring=wrap_string) -%}
21
+ {%- for line in wrapped.split('\n') -%}
22
+ {%- set prefix = "" if loop.index == 1 else " " -%}
23
+ {%- set _ = result_lines.append(prefix + line) -%}
24
+ {%- endfor -%}
21
25
  {%- else -%}
22
- {%- set _ = result_lines.append('') -%}
26
+ {# Do not add continuous blank lines #}
27
+ {%- if (result_lines and result_lines[-1] != '') or not result_lines -%}
28
+ {%- set _ = result_lines.append('') -%}
29
+ {%- endif -%}
23
30
  {%- endif -%}
24
31
  {%- endfor -%}
25
32
  {%- set original_result = result_lines | join('\n') -%}
@@ -37,4 +44,4 @@
37
44
  {% set suffix = suffix_string if list_result | length == loop.index %}
38
45
  {{ prefix }}{{ line }}{{ suffix }}
39
46
  {% endfor %}
40
- {% endmacro %}
47
+ {% endmacro %}
@@ -179,6 +179,19 @@ _VALID_RFC7231 = re.compile(
179
179
  r"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT"
180
180
  )
181
181
 
182
+ _ARRAY_ENCODE_MAPPING = {
183
+ "pipeDelimited": "|",
184
+ "spaceDelimited": " ",
185
+ "commaDelimited": ",",
186
+ "newlineDelimited": "\n",
187
+ }
188
+
189
+ def _deserialize_array_encoded(delimit: str, attr):
190
+ if isinstance(attr, str):
191
+ if attr == "":
192
+ return []
193
+ return attr.split(delimit)
194
+ return attr
182
195
 
183
196
  def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime:
184
197
  """Deserialize ISO-8601 formatted string into Datetime object.
@@ -323,6 +336,8 @@ _DESERIALIZE_MAPPING_WITHFORMAT = {
323
336
  def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None):
324
337
  if annotation is int and rf and rf._format == "str":
325
338
  return _deserialize_int_as_str
339
+ if annotation is str and rf and rf._format in _ARRAY_ENCODE_MAPPING:
340
+ return functools.partial(_deserialize_array_encoded, _ARRAY_ENCODE_MAPPING[rf._format])
326
341
  if rf and rf._format:
327
342
  return _DESERIALIZE_MAPPING_WITHFORMAT.get(rf._format)
328
343
  {% if code_model.has_external_type %}
@@ -367,9 +382,39 @@ class _MyMutableMapping(MutableMapping[str, typing.Any]):
367
382
  return key in self._data
368
383
 
369
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
370
409
  return self._data.__getitem__(key)
371
410
 
372
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
373
418
  self._data.__setitem__(key, value)
374
419
 
375
420
  def __delitem__(self, key: str) -> None:
@@ -497,6 +542,8 @@ def _is_model(obj: typing.Any) -> bool:
497
542
 
498
543
  def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-many-return-statements
499
544
  if isinstance(o, list):
545
+ if format in _ARRAY_ENCODE_MAPPING and all(isinstance(x, str) for x in o):
546
+ return _ARRAY_ENCODE_MAPPING[format].join(o)
500
547
  return [_serialize(x, format) for x in o]
501
548
  if isinstance(o, dict):
502
549
  return {k: _serialize(v, format) for k, v in o.items()}
@@ -809,6 +856,17 @@ def _deserialize_sequence(
809
856
  return obj
810
857
  if isinstance(obj, ET.Element):
811
858
  obj = list(obj)
859
+ try:
860
+ if (
861
+ isinstance(obj, str)
862
+ and isinstance(deserializer, functools.partial)
863
+ and isinstance(deserializer.args[0], functools.partial)
864
+ and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
865
+ ):
866
+ # encoded string may be deserialized to sequence
867
+ return deserializer(obj)
868
+ except: # pylint: disable=bare-except
869
+ pass
812
870
  return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
813
871
 
814
872
 
@@ -1065,14 +1123,37 @@ class _RestField:
1065
1123
  def __get__(self, obj: Model, type=None): # pylint: disable=redefined-builtin
1066
1124
  # by this point, type and rest_name will have a value bc we default
1067
1125
  # them in __new__ of the Model class
1068
- 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)
1069
1128
  if item is None:
1070
1129
  return item
1071
1130
  if self._is_model:
1072
1131
  return item
1073
- 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
1074
1150
 
1075
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
+
1076
1157
  if value is None:
1077
1158
  # we want to wipe out entries if users set attr to None
1078
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):
@@ -40,6 +40,7 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
40
40
  self.is_multipart_file_input: bool = yaml_data.get("isMultipartFileInput", False)
41
41
  self.flatten = self.yaml_data.get("flatten", False) and not getattr(self.type, "flattened_property", False)
42
42
  self.original_tsp_name: Optional[str] = self.yaml_data.get("originalTspName")
43
+ self.encode: Optional[str] = self.yaml_data.get("encode")
43
44
 
44
45
  def pylint_disable(self) -> str:
45
46
  retval: str = ""
@@ -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})"
@@ -329,6 +329,8 @@ class DpgModelSerializer(_ModelSerializer):
329
329
  args.append("is_multipart_file_input=True")
330
330
  elif hasattr(prop.type, "encode") and prop.type.encode: # type: ignore
331
331
  args.append(f'format="{prop.type.encode}"') # type: ignore
332
+ elif prop.encode:
333
+ args.append(f'format="{prop.encode}"')
332
334
 
333
335
  if prop.xml_metadata:
334
336
  args.append(f"xml={prop.xml_metadata}")
@@ -5,21 +5,28 @@
5
5
  {% set enable_custom_handling = "\n* " in doc_string or doc_string.startswith("* ") %}
6
6
  {%- if enable_custom_handling -%}
7
7
  {%- set lines = doc_string.split('\n') -%}
8
+ {%- set base_indent = wrap_string.lstrip('\n') -%}
8
9
  {%- set result_lines = [] -%}
9
10
  {%- for line in lines -%}
10
11
  {%- if line.startswith('* ') -%}
11
12
  {# Handle bullet points with proper continuation alignment #}
12
13
  {%- set bullet_content = line[2:] -%}
13
- {%- set base_indent = wrap_string.lstrip('\n') -%}
14
14
  {%- set bullet_line = base_indent + ' * ' + bullet_content -%}
15
15
  {%- set continuation_spaces = base_indent + ' ' -%}
16
16
  {%- set wrapped = bullet_line | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring='\n' + continuation_spaces) -%}
17
17
  {%- set _ = result_lines.append(wrapped) -%}
18
18
  {%- elif line.strip() -%}
19
- {%- set wrapped = line.strip() | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring=wrap_string) -%}
20
- {%- set _ = result_lines.append(wrapped) -%}
19
+ {%- set line_indent = '' if line.strip().startswith(':') or loop.index == 1 else (base_indent + ' ') -%}
20
+ {%- set wrapped = (line_indent + line) | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring=wrap_string) -%}
21
+ {%- for line in wrapped.split('\n') -%}
22
+ {%- set prefix = "" if loop.index == 1 else " " -%}
23
+ {%- set _ = result_lines.append(prefix + line) -%}
24
+ {%- endfor -%}
21
25
  {%- else -%}
22
- {%- set _ = result_lines.append('') -%}
26
+ {# Do not add continuous blank lines #}
27
+ {%- if (result_lines and result_lines[-1] != '') or not result_lines -%}
28
+ {%- set _ = result_lines.append('') -%}
29
+ {%- endif -%}
23
30
  {%- endif -%}
24
31
  {%- endfor -%}
25
32
  {%- set original_result = result_lines | join('\n') -%}
@@ -37,4 +44,4 @@
37
44
  {% set suffix = suffix_string if list_result | length == loop.index %}
38
45
  {{ prefix }}{{ line }}{{ suffix }}
39
46
  {% endfor %}
40
- {% endmacro %}
47
+ {% endmacro %}
@@ -179,6 +179,19 @@ _VALID_RFC7231 = re.compile(
179
179
  r"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT"
180
180
  )
181
181
 
182
+ _ARRAY_ENCODE_MAPPING = {
183
+ "pipeDelimited": "|",
184
+ "spaceDelimited": " ",
185
+ "commaDelimited": ",",
186
+ "newlineDelimited": "\n",
187
+ }
188
+
189
+ def _deserialize_array_encoded(delimit: str, attr):
190
+ if isinstance(attr, str):
191
+ if attr == "":
192
+ return []
193
+ return attr.split(delimit)
194
+ return attr
182
195
 
183
196
  def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime:
184
197
  """Deserialize ISO-8601 formatted string into Datetime object.
@@ -323,6 +336,8 @@ _DESERIALIZE_MAPPING_WITHFORMAT = {
323
336
  def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None):
324
337
  if annotation is int and rf and rf._format == "str":
325
338
  return _deserialize_int_as_str
339
+ if annotation is str and rf and rf._format in _ARRAY_ENCODE_MAPPING:
340
+ return functools.partial(_deserialize_array_encoded, _ARRAY_ENCODE_MAPPING[rf._format])
326
341
  if rf and rf._format:
327
342
  return _DESERIALIZE_MAPPING_WITHFORMAT.get(rf._format)
328
343
  {% if code_model.has_external_type %}
@@ -367,9 +382,39 @@ class _MyMutableMapping(MutableMapping[str, typing.Any]):
367
382
  return key in self._data
368
383
 
369
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
370
409
  return self._data.__getitem__(key)
371
410
 
372
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
373
418
  self._data.__setitem__(key, value)
374
419
 
375
420
  def __delitem__(self, key: str) -> None:
@@ -497,6 +542,8 @@ def _is_model(obj: typing.Any) -> bool:
497
542
 
498
543
  def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-many-return-statements
499
544
  if isinstance(o, list):
545
+ if format in _ARRAY_ENCODE_MAPPING and all(isinstance(x, str) for x in o):
546
+ return _ARRAY_ENCODE_MAPPING[format].join(o)
500
547
  return [_serialize(x, format) for x in o]
501
548
  if isinstance(o, dict):
502
549
  return {k: _serialize(v, format) for k, v in o.items()}
@@ -809,6 +856,17 @@ def _deserialize_sequence(
809
856
  return obj
810
857
  if isinstance(obj, ET.Element):
811
858
  obj = list(obj)
859
+ try:
860
+ if (
861
+ isinstance(obj, str)
862
+ and isinstance(deserializer, functools.partial)
863
+ and isinstance(deserializer.args[0], functools.partial)
864
+ and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
865
+ ):
866
+ # encoded string may be deserialized to sequence
867
+ return deserializer(obj)
868
+ except: # pylint: disable=bare-except
869
+ pass
812
870
  return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
813
871
 
814
872
 
@@ -1065,14 +1123,37 @@ class _RestField:
1065
1123
  def __get__(self, obj: Model, type=None): # pylint: disable=redefined-builtin
1066
1124
  # by this point, type and rest_name will have a value bc we default
1067
1125
  # them in __new__ of the Model class
1068
- 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)
1069
1128
  if item is None:
1070
1129
  return item
1071
1130
  if self._is_model:
1072
1131
  return item
1073
- 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
1074
1150
 
1075
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
+
1076
1157
  if value is None:
1077
1158
  # we want to wipe out entries if users set attr to None
1078
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.44.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.22.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"