@typespec/http-client-python 0.29.0 → 0.29.2
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.
- package/dist/emitter/types.js +1 -1
- package/dist/emitter/types.js.map +1 -1
- package/emitter/src/types.ts +1 -1
- package/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/eng/scripts/ci/regenerate-common.ts +21 -13
- package/eng/scripts/setup/__pycache__/package_manager.cpython-311.pyc +0 -0
- package/eng/scripts/setup/__pycache__/venvtools.cpython-311.pyc +0 -0
- package/generator/build/lib/pygen/codegen/models/response.py +15 -1
- package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +113 -1
- package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +329 -45
- package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +22 -1
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/codegen/models/response.py +15 -1
- package/generator/pygen/codegen/serializers/model_serializer.py +113 -1
- package/generator/pygen/codegen/templates/model_base.py.jinja2 +329 -45
- package/generator/pygen/codegen/templates/serialization.py.jinja2 +22 -1
- package/package.json +32 -32
|
@@ -612,6 +612,239 @@ def _create_value(rf: typing.Optional["_RestField"], value: typing.Any) -> typin
|
|
|
612
612
|
return _serialize(value, rf._format)
|
|
613
613
|
|
|
614
614
|
|
|
615
|
+
# ============================================================================
|
|
616
|
+
# Fast-path scalar deserializer functions for rest_field(deserializer=...)
|
|
617
|
+
# These are referenced from rest_field declarations to bypass the generic
|
|
618
|
+
# _deserialize -> _deserialize_with_callable chain.
|
|
619
|
+
# Only simple/primitive types — no models or container types.
|
|
620
|
+
# ============================================================================
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
def _xml_deser_str(value):
|
|
624
|
+
if isinstance(value, ET.Element):
|
|
625
|
+
return value.text or ""
|
|
626
|
+
return str(value) if value is not None else None
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
def _xml_deser_int(value):
|
|
630
|
+
if isinstance(value, ET.Element):
|
|
631
|
+
return int(value.text) if value.text else None
|
|
632
|
+
return int(value) if value is not None else None
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
def _xml_deser_float(value):
|
|
636
|
+
if isinstance(value, ET.Element):
|
|
637
|
+
return float(value.text) if value.text else None
|
|
638
|
+
return float(value) if value is not None else None
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
def _xml_deser_bool(value):
|
|
642
|
+
if isinstance(value, ET.Element):
|
|
643
|
+
text = value.text
|
|
644
|
+
else:
|
|
645
|
+
text = value
|
|
646
|
+
if text is None:
|
|
647
|
+
return None
|
|
648
|
+
if text in (True, False):
|
|
649
|
+
return text
|
|
650
|
+
return text.lower() == "true"
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
# pylint: disable=docstring-missing-param
|
|
654
|
+
def _xml_deser_bytes(value):
|
|
655
|
+
"""Deserialize bytes from XML (base64)."""
|
|
656
|
+
if isinstance(value, ET.Element):
|
|
657
|
+
text = value.text
|
|
658
|
+
else:
|
|
659
|
+
text = value
|
|
660
|
+
if text is None:
|
|
661
|
+
return None
|
|
662
|
+
return _deserialize_bytes(text)
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
def _xml_deser_bytes_base64url(value):
|
|
666
|
+
"""Deserialize bytes from XML (base64url)."""
|
|
667
|
+
if isinstance(value, ET.Element):
|
|
668
|
+
text = value.text
|
|
669
|
+
else:
|
|
670
|
+
text = value
|
|
671
|
+
if text is None:
|
|
672
|
+
return None
|
|
673
|
+
return _deserialize_bytes_base64(text)
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def _xml_deser_datetime(value):
|
|
677
|
+
"""Deserialize a datetime from XML (ISO 8601 / rfc3339)."""
|
|
678
|
+
if isinstance(value, ET.Element):
|
|
679
|
+
text = value.text
|
|
680
|
+
else:
|
|
681
|
+
text = value
|
|
682
|
+
if text is None:
|
|
683
|
+
return None
|
|
684
|
+
return _deserialize_datetime(text)
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
def _xml_deser_datetime_rfc7231(value):
|
|
688
|
+
"""Deserialize a datetime from XML (RFC7231 format)."""
|
|
689
|
+
if isinstance(value, ET.Element):
|
|
690
|
+
text = value.text
|
|
691
|
+
else:
|
|
692
|
+
text = value
|
|
693
|
+
if text is None:
|
|
694
|
+
return None
|
|
695
|
+
return _deserialize_datetime_rfc7231(text)
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
def _xml_deser_datetime_unix_timestamp(value):
|
|
699
|
+
"""Deserialize a datetime from XML (Unix timestamp)."""
|
|
700
|
+
if isinstance(value, ET.Element):
|
|
701
|
+
text = value.text
|
|
702
|
+
else:
|
|
703
|
+
text = value
|
|
704
|
+
if text is None:
|
|
705
|
+
return None
|
|
706
|
+
return _deserialize_datetime_unix_timestamp(float(text))
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
def _xml_deser_date(value):
|
|
710
|
+
"""Deserialize a date from XML (ISO 8601)."""
|
|
711
|
+
if isinstance(value, ET.Element):
|
|
712
|
+
text = value.text
|
|
713
|
+
else:
|
|
714
|
+
text = value
|
|
715
|
+
if text is None:
|
|
716
|
+
return None
|
|
717
|
+
return _deserialize_date(text)
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
def _xml_deser_time(value):
|
|
721
|
+
"""Deserialize a time from XML (ISO 8601)."""
|
|
722
|
+
if isinstance(value, ET.Element):
|
|
723
|
+
text = value.text
|
|
724
|
+
else:
|
|
725
|
+
text = value
|
|
726
|
+
if text is None:
|
|
727
|
+
return None
|
|
728
|
+
return _deserialize_time(text)
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
def _xml_deser_duration(value):
|
|
732
|
+
"""Deserialize a timedelta from XML (ISO 8601 duration)."""
|
|
733
|
+
if isinstance(value, ET.Element):
|
|
734
|
+
text = value.text
|
|
735
|
+
else:
|
|
736
|
+
text = value
|
|
737
|
+
if text is None:
|
|
738
|
+
return None
|
|
739
|
+
return _deserialize_duration(text)
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
def _xml_deser_decimal(value):
|
|
743
|
+
"""Deserialize a Decimal from XML."""
|
|
744
|
+
if isinstance(value, ET.Element):
|
|
745
|
+
text = value.text
|
|
746
|
+
else:
|
|
747
|
+
text = value
|
|
748
|
+
if text is None:
|
|
749
|
+
return None
|
|
750
|
+
return _deserialize_decimal(text)
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
def _xml_deser_enum_or_str(enum_cls, value):
|
|
754
|
+
"""Deserialize a Union[EnumType, str] from XML."""
|
|
755
|
+
text = value.text if isinstance(value, ET.Element) else value
|
|
756
|
+
if text is None:
|
|
757
|
+
return None
|
|
758
|
+
try:
|
|
759
|
+
return enum_cls(text)
|
|
760
|
+
except ValueError:
|
|
761
|
+
return text
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
def _extract_xml_model_type(rf_type):
|
|
765
|
+
"""Extract the concrete Model class from a resolved rf._type partial chain.
|
|
766
|
+
|
|
767
|
+
Unwraps ``Optional[Model]`` and ``_deserialize_model(Model, ...)``
|
|
768
|
+
wrappers. Only handles Model and Optional[Model] — other composite
|
|
769
|
+
types (List, Dict, Union, etc.) return None and fall through to the
|
|
770
|
+
generic ``_deserialize`` path at runtime.
|
|
771
|
+
"""
|
|
772
|
+
if rf_type is None:
|
|
773
|
+
return None
|
|
774
|
+
if isinstance(rf_type, type) and _is_model(rf_type):
|
|
775
|
+
return rf_type
|
|
776
|
+
if not isinstance(rf_type, functools.partial):
|
|
777
|
+
return None
|
|
778
|
+
func = rf_type.func
|
|
779
|
+
args = rf_type.args
|
|
780
|
+
if func is _deserialize_with_optional and args:
|
|
781
|
+
return _extract_xml_model_type(args[0])
|
|
782
|
+
if func is _deserialize_model and args:
|
|
783
|
+
cls = args[0]
|
|
784
|
+
return cls if isinstance(cls, type) and _is_model(cls) else None
|
|
785
|
+
return None
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
def _build_xml_field_plan( # pylint: disable=docstring-missing-return, docstring-missing-rtype, unused-variable
|
|
789
|
+
cls, attr_to_rest_field: dict
|
|
790
|
+
) -> list:
|
|
791
|
+
"""Build a precomputed XML field plan for fast _init_from_xml iteration.
|
|
792
|
+
|
|
793
|
+
Called once per model class in __new__. Returns a list of tuples:
|
|
794
|
+
(rest_name, xml_name, kind, deser, rf_type, is_optional, items_name)
|
|
795
|
+
|
|
796
|
+
kind: 0=wrapped, 1=attribute, 2=unwrapped, 3=text
|
|
797
|
+
|
|
798
|
+
For Model and Optional[Model] fields that lack a scalar
|
|
799
|
+
``_deserializer``, this function precomputes the Model class as the
|
|
800
|
+
deserializer so ``_init_from_xml`` can call ``ModelClass(element)``
|
|
801
|
+
directly instead of going through the expensive
|
|
802
|
+
``_get_deserialize_callable_from_annotation`` chain at runtime.
|
|
803
|
+
"""
|
|
804
|
+
model_meta = getattr(cls, "_xml", {})
|
|
805
|
+
model_ns = model_meta.get("ns") or model_meta.get("namespace")
|
|
806
|
+
plan = []
|
|
807
|
+
|
|
808
|
+
for rf in attr_to_rest_field.values():
|
|
809
|
+
prop_meta = getattr(rf, "_xml", {})
|
|
810
|
+
deser = rf._deserializer
|
|
811
|
+
|
|
812
|
+
xml_name = prop_meta.get("name", rf._rest_name)
|
|
813
|
+
xml_ns = _resolve_xml_ns(prop_meta, model_meta)
|
|
814
|
+
if xml_ns:
|
|
815
|
+
xml_name = "{" + xml_ns + "}" + xml_name
|
|
816
|
+
|
|
817
|
+
is_optional = rf._is_optional
|
|
818
|
+
|
|
819
|
+
# For Model / Optional[Model] fields without a scalar deserializer,
|
|
820
|
+
# precompute the Model class as the deserializer.
|
|
821
|
+
if deser is None and rf._type is not None:
|
|
822
|
+
model_cls = _extract_xml_model_type(rf._type)
|
|
823
|
+
if model_cls is not None:
|
|
824
|
+
deser = model_cls
|
|
825
|
+
|
|
826
|
+
if prop_meta.get("attribute", False):
|
|
827
|
+
plan.append((rf._rest_name, xml_name, 1, deser, rf._type, is_optional, None))
|
|
828
|
+
elif prop_meta.get("unwrapped", False):
|
|
829
|
+
items_name = prop_meta.get("itemsName")
|
|
830
|
+
if items_name:
|
|
831
|
+
items_ns = prop_meta.get("itemsNs")
|
|
832
|
+
if items_ns is not None:
|
|
833
|
+
xml_ns = items_ns
|
|
834
|
+
if xml_ns:
|
|
835
|
+
items_name = "{" + xml_ns + "}" + items_name
|
|
836
|
+
else:
|
|
837
|
+
items_name = xml_name
|
|
838
|
+
plan.append((rf._rest_name, xml_name, 2, deser, rf._type, is_optional, items_name))
|
|
839
|
+
elif prop_meta.get("text", False):
|
|
840
|
+
plan.append((rf._rest_name, xml_name, 3, deser, rf._type, is_optional, None))
|
|
841
|
+
else:
|
|
842
|
+
plan.append((rf._rest_name, xml_name, 0, deser, rf._type, is_optional, None))
|
|
843
|
+
|
|
844
|
+
return plan
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
# pylint: enable=docstring-missing-param
|
|
615
848
|
class Model(_MyMutableMapping):
|
|
616
849
|
_is_model = True
|
|
617
850
|
# label whether current class's _attr_to_rest_field has been calculated
|
|
@@ -652,7 +885,9 @@ class Model(_MyMutableMapping):
|
|
|
652
885
|
dict_to_pass[rf._rest_name] = _create_value(rf, rf._default)
|
|
653
886
|
super().__init__(dict_to_pass)
|
|
654
887
|
|
|
655
|
-
def _init_from_xml(
|
|
888
|
+
def _init_from_xml( # pylint: disable=too-many-branches, too-many-statements
|
|
889
|
+
self, element: ET.Element
|
|
890
|
+
) -> dict[str, typing.Any]:
|
|
656
891
|
"""Deserialize an XML element into a dict mapping rest field names to values.
|
|
657
892
|
|
|
658
893
|
:param ET.Element element: The XML element to deserialize from.
|
|
@@ -660,53 +895,89 @@ class Model(_MyMutableMapping):
|
|
|
660
895
|
:rtype: dict
|
|
661
896
|
"""
|
|
662
897
|
result: dict[str, typing.Any] = {}
|
|
663
|
-
model_meta = getattr(self, "_xml", {})
|
|
664
898
|
existed_attr_keys: list[str] = []
|
|
665
899
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
xml_name
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
900
|
+
field_plan = getattr(self, "_xml_field_plan", None)
|
|
901
|
+
if field_plan:
|
|
902
|
+
for rest_name, xml_name, kind, deser, rf_type, is_optional, items_name in field_plan:
|
|
903
|
+
if kind == 0: # wrapped element (most common)
|
|
904
|
+
item = element.find(xml_name)
|
|
905
|
+
if item is not None:
|
|
906
|
+
existed_attr_keys.append(xml_name)
|
|
907
|
+
if deser:
|
|
908
|
+
result[rest_name] = deser(item)
|
|
909
|
+
else:
|
|
910
|
+
result[rest_name] = _deserialize(rf_type, item)
|
|
911
|
+
elif kind == 1: # attribute
|
|
912
|
+
attr_val = element.get(xml_name)
|
|
913
|
+
if attr_val is not None:
|
|
914
|
+
existed_attr_keys.append(xml_name)
|
|
915
|
+
if deser:
|
|
916
|
+
result[rest_name] = deser(attr_val)
|
|
917
|
+
else:
|
|
918
|
+
result[rest_name] = attr_val
|
|
919
|
+
elif kind == 2: # unwrapped array
|
|
920
|
+
items = element.findall(items_name) # pyright: ignore
|
|
921
|
+
if len(items) > 0:
|
|
922
|
+
existed_attr_keys.append(items_name)
|
|
923
|
+
if deser:
|
|
924
|
+
result[rest_name] = deser(items)
|
|
925
|
+
else:
|
|
926
|
+
result[rest_name] = _deserialize(rf_type, items)
|
|
927
|
+
elif not is_optional:
|
|
928
|
+
existed_attr_keys.append(items_name)
|
|
929
|
+
result[rest_name] = []
|
|
930
|
+
elif kind == 3: # text
|
|
931
|
+
if element.text is not None:
|
|
932
|
+
if deser:
|
|
933
|
+
result[rest_name] = deser(element.text)
|
|
934
|
+
else:
|
|
935
|
+
result[rest_name] = element.text
|
|
936
|
+
else:
|
|
937
|
+
model_meta = getattr(self, "_xml", {})
|
|
938
|
+
for rf in self._attr_to_rest_field.values():
|
|
939
|
+
prop_meta = getattr(rf, "_xml", {})
|
|
940
|
+
xml_name = prop_meta.get("name", rf._rest_name)
|
|
941
|
+
xml_ns = _resolve_xml_ns(prop_meta, model_meta)
|
|
942
|
+
if xml_ns:
|
|
943
|
+
xml_name = "{" + xml_ns + "}" + xml_name
|
|
944
|
+
|
|
945
|
+
# attribute
|
|
946
|
+
if prop_meta.get("attribute", False) and element.get(xml_name) is not None:
|
|
692
947
|
existed_attr_keys.append(xml_name)
|
|
693
|
-
result[rf._rest_name] = _deserialize(rf._type,
|
|
694
|
-
|
|
948
|
+
result[rf._rest_name] = _deserialize(rf._type, element.get(xml_name))
|
|
949
|
+
continue
|
|
950
|
+
|
|
951
|
+
# unwrapped element is array
|
|
952
|
+
if prop_meta.get("unwrapped", False):
|
|
953
|
+
_items_name = prop_meta.get("itemsName")
|
|
954
|
+
if _items_name:
|
|
955
|
+
xml_name = _items_name
|
|
956
|
+
_items_ns = prop_meta.get("itemsNs")
|
|
957
|
+
if _items_ns is not None:
|
|
958
|
+
xml_ns = _items_ns
|
|
959
|
+
if xml_ns:
|
|
960
|
+
xml_name = "{" + xml_ns + "}" + xml_name
|
|
961
|
+
items = element.findall(xml_name) # pyright: ignore
|
|
962
|
+
if len(items) > 0:
|
|
963
|
+
existed_attr_keys.append(xml_name)
|
|
964
|
+
result[rf._rest_name] = _deserialize(rf._type, items)
|
|
965
|
+
elif not rf._is_optional:
|
|
966
|
+
existed_attr_keys.append(xml_name)
|
|
967
|
+
result[rf._rest_name] = []
|
|
968
|
+
continue
|
|
969
|
+
|
|
970
|
+
# text element is primitive type
|
|
971
|
+
if prop_meta.get("text", False):
|
|
972
|
+
if element.text is not None:
|
|
973
|
+
result[rf._rest_name] = _deserialize(rf._type, element.text)
|
|
974
|
+
continue
|
|
975
|
+
|
|
976
|
+
# wrapped element could be normal property or array
|
|
977
|
+
item = element.find(xml_name)
|
|
978
|
+
if item is not None:
|
|
695
979
|
existed_attr_keys.append(xml_name)
|
|
696
|
-
result[rf._rest_name] =
|
|
697
|
-
continue
|
|
698
|
-
|
|
699
|
-
# text element is primitive type
|
|
700
|
-
if prop_meta.get("text", False):
|
|
701
|
-
if element.text is not None:
|
|
702
|
-
result[rf._rest_name] = _deserialize(rf._type, element.text)
|
|
703
|
-
continue
|
|
704
|
-
|
|
705
|
-
# wrapped element could be normal property or array, it should only have one element
|
|
706
|
-
item = element.find(xml_name)
|
|
707
|
-
if item is not None:
|
|
708
|
-
existed_attr_keys.append(xml_name)
|
|
709
|
-
result[rf._rest_name] = _deserialize(rf._type, item)
|
|
980
|
+
result[rf._rest_name] = _deserialize(rf._type, item)
|
|
710
981
|
|
|
711
982
|
# rest thing is additional properties
|
|
712
983
|
for e in element:
|
|
@@ -745,6 +1016,9 @@ class Model(_MyMutableMapping):
|
|
|
745
1016
|
._attr_to_rest_field.items()
|
|
746
1017
|
}
|
|
747
1018
|
{% endif %}
|
|
1019
|
+
# Build XML field plan for fast _init_from_xml (only for XML models)
|
|
1020
|
+
if getattr(cls, "_xml", None):
|
|
1021
|
+
cls._xml_field_plan = _build_xml_field_plan(cls, attr_to_rest_field)
|
|
748
1022
|
cls._calculated.add(f"{cls.__module__}.{cls.__qualname__}")
|
|
749
1023
|
|
|
750
1024
|
return super().__new__(cls)
|
|
@@ -1132,6 +1406,7 @@ class _RestField:
|
|
|
1132
1406
|
format: typing.Optional[str] = None,
|
|
1133
1407
|
is_multipart_file_input: bool = False,
|
|
1134
1408
|
xml: typing.Optional[dict[str, typing.Any]] = None,
|
|
1409
|
+
deserializer: typing.Optional[typing.Callable] = None,
|
|
1135
1410
|
{% if code_model.has_padded_model_property %}
|
|
1136
1411
|
original_tsp_name: typing.Optional[str] = None,
|
|
1137
1412
|
{% endif %}
|
|
@@ -1147,6 +1422,7 @@ class _RestField:
|
|
|
1147
1422
|
self._format = format
|
|
1148
1423
|
self._is_multipart_file_input = is_multipart_file_input
|
|
1149
1424
|
self._xml = xml if xml is not None else {}
|
|
1425
|
+
self._deserializer = deserializer
|
|
1150
1426
|
{% if code_model.has_padded_model_property %}
|
|
1151
1427
|
self._original_tsp_name = original_tsp_name
|
|
1152
1428
|
{% endif %}
|
|
@@ -1185,7 +1461,11 @@ class _RestField:
|
|
|
1185
1461
|
# Return the value from _data directly (it's been deserialized in place)
|
|
1186
1462
|
return obj._data.get(self._rest_name)
|
|
1187
1463
|
|
|
1188
|
-
|
|
1464
|
+
# Fast path: use _deserializer directly (avoids _serialize/_deserialize chain)
|
|
1465
|
+
if self._deserializer:
|
|
1466
|
+
deserialized = self._deserializer(item)
|
|
1467
|
+
else:
|
|
1468
|
+
deserialized = _deserialize(self._type, _serialize(item, self._format), rf=self)
|
|
1189
1469
|
|
|
1190
1470
|
# For mutable types, store the deserialized value back in _data
|
|
1191
1471
|
# so mutations directly affect _data
|
|
@@ -1231,6 +1511,7 @@ def rest_field(
|
|
|
1231
1511
|
format: typing.Optional[str] = None,
|
|
1232
1512
|
is_multipart_file_input: bool = False,
|
|
1233
1513
|
xml: typing.Optional[dict[str, typing.Any]] = None,
|
|
1514
|
+
deserializer: typing.Optional[typing.Callable] = None,
|
|
1234
1515
|
{% if code_model.has_padded_model_property %}
|
|
1235
1516
|
original_tsp_name: typing.Optional[str] = None,
|
|
1236
1517
|
{% endif %}
|
|
@@ -1243,6 +1524,7 @@ def rest_field(
|
|
|
1243
1524
|
format=format,
|
|
1244
1525
|
is_multipart_file_input=is_multipart_file_input,
|
|
1245
1526
|
xml=xml,
|
|
1527
|
+
deserializer=deserializer,
|
|
1246
1528
|
{% if code_model.has_padded_model_property %}
|
|
1247
1529
|
original_tsp_name=original_tsp_name,
|
|
1248
1530
|
{% endif %}
|
|
@@ -1481,6 +1763,8 @@ def _deserialize_xml(
|
|
|
1481
1763
|
value: str,
|
|
1482
1764
|
) -> typing.Any:
|
|
1483
1765
|
element = ET.fromstring(value) # nosec
|
|
1766
|
+
if _is_model(deserializer):
|
|
1767
|
+
return deserializer._deserialize(element, [])
|
|
1484
1768
|
return _deserialize(deserializer, element)
|
|
1485
1769
|
|
|
1486
1770
|
|
|
@@ -1401,7 +1401,7 @@ class Deserializer:
|
|
|
1401
1401
|
# Otherwise, result are unexpected
|
|
1402
1402
|
self.additional_properties_detection = True
|
|
1403
1403
|
|
|
1404
|
-
def __call__(self, target_obj, response_data, content_type=None):
|
|
1404
|
+
def __call__(self, target_obj, response_data, content_type=None): # pylint: disable=too-many-return-statements
|
|
1405
1405
|
"""Call the deserializer to process a REST response.
|
|
1406
1406
|
|
|
1407
1407
|
:param str target_obj: Target data type to deserialize to.
|
|
@@ -1411,6 +1411,27 @@ class Deserializer:
|
|
|
1411
1411
|
:return: Deserialized object.
|
|
1412
1412
|
:rtype: object
|
|
1413
1413
|
"""
|
|
1414
|
+
# Fast path for header deserialization: response_data is a plain str or None
|
|
1415
|
+
# and target_obj is a simple scalar type. This avoids the expensive
|
|
1416
|
+
# _unpack_content → _deserialize → _classify_target → deserialize_data chain.
|
|
1417
|
+
if response_data is None:
|
|
1418
|
+
return None
|
|
1419
|
+
if target_obj == "str" and isinstance(response_data, str):
|
|
1420
|
+
return response_data
|
|
1421
|
+
if isinstance(response_data, str):
|
|
1422
|
+
if target_obj == "int":
|
|
1423
|
+
return int(response_data)
|
|
1424
|
+
if target_obj == "bool":
|
|
1425
|
+
if response_data in ("true", "1", "True"):
|
|
1426
|
+
return True
|
|
1427
|
+
if response_data in ("false", "0", "False"):
|
|
1428
|
+
return False
|
|
1429
|
+
return bool(response_data)
|
|
1430
|
+
if target_obj == "rfc-1123":
|
|
1431
|
+
return Deserializer.deserialize_rfc(response_data)
|
|
1432
|
+
if target_obj == "bytearray":
|
|
1433
|
+
return Deserializer.deserialize_bytearray(response_data)
|
|
1434
|
+
|
|
1414
1435
|
data = self._unpack_content(response_data, content_type)
|
|
1415
1436
|
return self._deserialize(target_obj, data)
|
|
1416
1437
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typespec/http-client-python",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.2",
|
|
4
4
|
"author": "Microsoft Corporation",
|
|
5
5
|
"description": "TypeSpec emitter for Python SDKs",
|
|
6
6
|
"homepage": "https://typespec.io",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"engines": {
|
|
29
|
-
"node": ">=
|
|
29
|
+
"node": ">=22.0.0"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"clean": "rimraf ./dist ./temp ./venv ./tests/generated",
|
|
@@ -60,20 +60,20 @@
|
|
|
60
60
|
"emitter"
|
|
61
61
|
],
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"@azure-tools/typespec-autorest": ">=0.
|
|
64
|
-
"@azure-tools/typespec-azure-core": ">=0.
|
|
65
|
-
"@azure-tools/typespec-azure-resource-manager": ">=0.
|
|
66
|
-
"@azure-tools/typespec-azure-rulesets": ">=0.
|
|
67
|
-
"@azure-tools/typespec-client-generator-core": ">=0.
|
|
68
|
-
"@typespec/compiler": "^1.
|
|
69
|
-
"@typespec/http": "^1.
|
|
70
|
-
"@typespec/openapi": "^1.
|
|
71
|
-
"@typespec/rest": ">=0.
|
|
72
|
-
"@typespec/versioning": ">=0.
|
|
73
|
-
"@typespec/events": ">=0.
|
|
74
|
-
"@typespec/sse": ">=0.
|
|
75
|
-
"@typespec/streams": ">=0.
|
|
76
|
-
"@typespec/xml": ">=0.
|
|
63
|
+
"@azure-tools/typespec-autorest": ">=0.68.0 <1.0.0",
|
|
64
|
+
"@azure-tools/typespec-azure-core": ">=0.68.0 <1.0.0",
|
|
65
|
+
"@azure-tools/typespec-azure-resource-manager": ">=0.68.0 <1.0.0",
|
|
66
|
+
"@azure-tools/typespec-azure-rulesets": ">=0.68.0 <1.0.0",
|
|
67
|
+
"@azure-tools/typespec-client-generator-core": ">=0.68.0 <1.0.0",
|
|
68
|
+
"@typespec/compiler": "^1.12.0",
|
|
69
|
+
"@typespec/http": "^1.12.0",
|
|
70
|
+
"@typespec/openapi": "^1.12.0",
|
|
71
|
+
"@typespec/rest": ">=0.82.0 <1.0.0",
|
|
72
|
+
"@typespec/versioning": ">=0.82.0 <1.0.0",
|
|
73
|
+
"@typespec/events": ">=0.82.0 <1.0.0",
|
|
74
|
+
"@typespec/sse": ">=0.82.0 <1.0.0",
|
|
75
|
+
"@typespec/streams": ">=0.82.0 <1.0.0",
|
|
76
|
+
"@typespec/xml": ">=0.82.0 <1.0.0"
|
|
77
77
|
},
|
|
78
78
|
"playgroundConfig": {
|
|
79
79
|
"assets": [
|
|
@@ -98,24 +98,24 @@
|
|
|
98
98
|
"tsx": "^4.21.0"
|
|
99
99
|
},
|
|
100
100
|
"devDependencies": {
|
|
101
|
-
"@azure-tools/typespec-autorest": "~0.
|
|
102
|
-
"@azure-tools/typespec-azure-core": "~0.
|
|
103
|
-
"@azure-tools/typespec-azure-resource-manager": "~0.
|
|
104
|
-
"@azure-tools/typespec-azure-rulesets": "~0.
|
|
105
|
-
"@azure-tools/typespec-client-generator-core": "~0.
|
|
106
|
-
"@azure-tools/azure-http-specs": "0.1.0-alpha.40
|
|
107
|
-
"@typespec/compiler": "^1.
|
|
108
|
-
"@typespec/http": "^1.
|
|
109
|
-
"@typespec/openapi": "^1.
|
|
110
|
-
"@typespec/rest": "~0.
|
|
111
|
-
"@typespec/versioning": "~0.
|
|
112
|
-
"@typespec/events": "~0.
|
|
101
|
+
"@azure-tools/typespec-autorest": "~0.68.0",
|
|
102
|
+
"@azure-tools/typespec-azure-core": "~0.68.0",
|
|
103
|
+
"@azure-tools/typespec-azure-resource-manager": "~0.68.0",
|
|
104
|
+
"@azure-tools/typespec-azure-rulesets": "~0.68.0",
|
|
105
|
+
"@azure-tools/typespec-client-generator-core": "~0.68.0",
|
|
106
|
+
"@azure-tools/azure-http-specs": "0.1.0-alpha.40",
|
|
107
|
+
"@typespec/compiler": "^1.12.0",
|
|
108
|
+
"@typespec/http": "^1.12.0",
|
|
109
|
+
"@typespec/openapi": "^1.12.0",
|
|
110
|
+
"@typespec/rest": "~0.82.0",
|
|
111
|
+
"@typespec/versioning": "~0.82.0",
|
|
112
|
+
"@typespec/events": "~0.82.0",
|
|
113
113
|
"@typespec/spector": "0.1.0-alpha.25",
|
|
114
114
|
"@typespec/spec-api": "0.1.0-alpha.14",
|
|
115
|
-
"@typespec/sse": "~0.
|
|
116
|
-
"@typespec/streams": "~0.
|
|
117
|
-
"@typespec/xml": "~0.
|
|
118
|
-
"@typespec/http-specs": "0.1.0-alpha.
|
|
115
|
+
"@typespec/sse": "~0.82.0",
|
|
116
|
+
"@typespec/streams": "~0.82.0",
|
|
117
|
+
"@typespec/xml": "~0.82.0",
|
|
118
|
+
"@typespec/http-specs": "0.1.0-alpha.37",
|
|
119
119
|
"@types/js-yaml": "~4.0.5",
|
|
120
120
|
"@types/node": "~25.0.2",
|
|
121
121
|
"@types/semver": "7.5.8",
|