| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| from pyfory import Fory |
| |
| |
| # Test class with __getstate__ and __setstate__ |
| class StatefulObject: |
| def __init__(self, value, secret=None): |
| self.value = value |
| self.secret = secret or "default_secret" |
| self.computed = self.value * 2 |
| |
| def __getstate__(self): |
| # Only serialize value, not secret or computed |
| return {"value": self.value} |
| |
| def __setstate__(self, state): |
| self.value = state["value"] |
| self.secret = "restored_secret" |
| self.computed = self.value * 2 |
| |
| def __eq__(self, other): |
| return isinstance(other, StatefulObject) and self.value == other.value and self.computed == other.computed |
| # Note: secret is expected to be different after deserialization |
| |
| def __repr__(self): |
| return f"StatefulObject(value={self.value}, secret={self.secret}, computed={self.computed})" |
| |
| |
| # Test class with getnewargs_ex |
| class ImmutableWithArgs: |
| def __init__(self, x, y, name="default"): |
| self._x = x |
| self._y = y |
| self._name = name |
| |
| def __getnewargs_ex__(self): |
| return (self._x, self._y), {"name": self._name} |
| |
| def __getstate__(self): |
| return {"extra_data": "some_extra"} |
| |
| def __setstate__(self, state): |
| self._extra = state.get("extra_data", "none") |
| |
| def __eq__(self, other): |
| return ( |
| isinstance(other, ImmutableWithArgs) |
| and self._x == other._x |
| and self._y == other._y |
| and self._name == other._name |
| and getattr(self, "_extra", None) == getattr(other, "_extra", None) |
| ) |
| |
| def __repr__(self): |
| return f"ImmutableWithArgs(x={self._x}, y={self._y}, name={self._name}, extra={getattr(self, '_extra', None)})" |
| |
| |
| # Test class with getnewargs (older style) |
| class ImmutableOldStyle: |
| def __init__(self, a, b): |
| self._a = a |
| self._b = b |
| |
| def __getnewargs__(self): |
| return self._a, self._b |
| |
| def __getstate__(self): |
| return {"metadata": "old_style"} |
| |
| def __setstate__(self, state): |
| self._metadata = state.get("metadata", "none") |
| |
| def __eq__(self, other): |
| return ( |
| isinstance(other, ImmutableOldStyle) |
| and self._a == other._a |
| and self._b == other._b |
| and getattr(self, "_metadata", None) == getattr(other, "_metadata", None) |
| ) |
| |
| def __repr__(self): |
| return f"ImmutableOldStyle(a={self._a}, b={self._b}, metadata={getattr(self, '_metadata', None)})" |
| |
| |
| def test_current_behavior(): |
| print("Testing current behavior with stateful objects...") |
| |
| fory = Fory(xlang=False, ref=True, strict=False) |
| |
| # Test basic stateful object |
| obj1 = StatefulObject(42, "original_secret") |
| print(f"Original: {obj1}") |
| |
| serialized = fory.serialize(obj1) |
| deserialized = fory.deserialize(serialized) |
| print(f"Deserialized: {deserialized}") |
| print(f"Equal: {obj1 == deserialized}") |
| print() |
| |
| # Test with getnewargs_ex |
| obj2 = ImmutableWithArgs(10, 20, "test") |
| print(f"Original: {obj2}") |
| |
| serialized2 = fory.serialize(obj2) |
| deserialized2 = fory.deserialize(serialized2) |
| print(f"Deserialized attributes: {dir(deserialized2)}") |
| print(f"Deserialized vars: {vars(deserialized2)}") |
| try: |
| print(f"Deserialized: {deserialized2}") |
| print(f"Equal: {obj2 == deserialized2}") |
| except Exception as e: |
| print(f"Error in repr/comparison: {e}") |
| print() |
| |
| # Test with getnewargs (old style) |
| obj3 = ImmutableOldStyle(100, 200) |
| print(f"Original: {obj3}") |
| |
| serialized3 = fory.serialize(obj3) |
| deserialized3 = fory.deserialize(serialized3) |
| print(f"Deserialized: {deserialized3}") |
| print(f"Equal: {obj3 == deserialized3}") |
| print() |
| |
| # Check what serializer is being used |
| serializer1 = fory.type_resolver.get_serializer(StatefulObject) |
| serializer2 = fory.type_resolver.get_serializer(ImmutableWithArgs) |
| serializer3 = fory.type_resolver.get_serializer(ImmutableOldStyle) |
| |
| print(f"StatefulObject serializer: {type(serializer1)}") |
| print(f"ImmutableWithArgs serializer: {type(serializer2)}") |
| print(f"ImmutableOldStyle serializer: {type(serializer3)}") |
| |
| |
| if __name__ == "__main__": |
| test_current_behavior() |