Skip to content

Commit d85b447

Browse files
committed
preserve model input ownership during deserialization
1 parent e62645c commit d85b447

1 file changed

Lines changed: 35 additions & 4 deletions

File tree

packages/http-client-python/generator/pygen/codegen/templates/model_base.py.jinja2

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,31 @@ def _create_value(rf: typing.Optional["_RestField"], value: typing.Any) -> typin
662662
return _serialize(value, rf._format)
663663

664664

665+
def _clone_wire_value(value: typing.Any) -> typing.Any:
666+
if isinstance(value, list):
667+
return [_clone_wire_value(entry) for entry in value]
668+
if isinstance(value, dict):
669+
return {key: _clone_wire_value(entry) for key, entry in value.items()}
670+
if isinstance(value, set):
671+
return {_clone_wire_value(entry) for entry in value}
672+
if isinstance(value, tuple):
673+
return tuple(_clone_wire_value(entry) for entry in value)
674+
return value
675+
676+
677+
def _create_public_value(rf: typing.Optional["_RestField"], value: typing.Any) -> typing.Any:
678+
if rf and rf._is_model:
679+
value = _clone_wire_value(value)
680+
return _create_value(rf, value)
681+
682+
683+
class _OwnedWireValue:
684+
__slots__ = ("value",)
685+
686+
def __init__(self, value: typing.Mapping[str, typing.Any]) -> None:
687+
self.value = value
688+
689+
665690
def _create_value_from_wire(rf: typing.Optional["_RestField"], value: typing.Any) -> typing.Any:
666691
"""Build a stored value from an already-serialized (wire/JSON) payload.
667692

@@ -935,10 +960,16 @@ class Model(_MyMutableMapping):
935960
dict_to_pass.update(self._init_from_xml(args[0]))
936961
else:
937962
rest_field_by_rest_name = self._rest_field_by_rest_name
963+
mapping = args[0]
964+
if isinstance(mapping, _OwnedWireValue):
965+
mapping = mapping.value
966+
create_value = _create_value_from_wire
967+
else:
968+
create_value = _create_public_value
938969
dict_to_pass.update(
939970
{
940-
k: _create_value_from_wire(rest_field_by_rest_name.get(k), v)
941-
for k, v in args[0].items()
971+
k: create_value(rest_field_by_rest_name.get(k), v)
972+
for k, v in mapping.items()
942973
}
943974
)
944975
else:
@@ -1134,10 +1165,10 @@ class Model(_MyMutableMapping):
11341165
@classmethod
11351166
def _deserialize(cls, data, exist_discriminators):
11361167
if not hasattr(cls, "__mapping__"):
1137-
return cls(data)
1168+
return cls(data) if isinstance(data, ET.Element) else cls(_OwnedWireValue(data))
11381169
discriminator = cls._get_discriminator(exist_discriminators)
11391170
if discriminator is None:
1140-
return cls(data)
1171+
return cls(data) if isinstance(data, ET.Element) else cls(_OwnedWireValue(data))
11411172
exist_discriminators.append(discriminator._rest_name)
11421173
if isinstance(data, ET.Element):
11431174
model_meta = getattr(cls, "_xml", {})

0 commit comments

Comments
 (0)