Skip to content
Snippets Groups Projects
Commit 3e613117 authored by Frederik Hennig's avatar Frederik Hennig
Browse files

Weakened type uniquing: Pickle may now create its own instances

parent f59ccfeb
No related branches found
No related tags found
2 merge requests!379Type System Refactor,!374Uniqueness of Data Type Instances
...@@ -27,7 +27,7 @@ For this to work, all instantiable subclasses of `PsType` must implement the fol ...@@ -27,7 +27,7 @@ For this to work, all instantiable subclasses of `PsType` must implement the fol
arguments in their canonical order. This method is used by `PsTypeMeta` to identify instances, arguments in their canonical order. This method is used by `PsTypeMeta` to identify instances,
and to catch the various different possibilities Python offers for passing function arguments. and to catch the various different possibilities Python offers for passing function arguments.
- The ``__args__`` method, when called on an instance of the type, must return a tuple containing the constructor - The ``__args__`` method, when called on an instance of the type, must return a tuple containing the constructor
arguments required to create that exact instance. This is used for pickling and unpickling of type objects, arguments required to create that exact instance. This is used for comparing type objects
as well as const-conversion. as well as const-conversion.
As a rule, ``MyType.__canonical_args__(< arguments >)`` and ``MyType(< arguments >).__args__()`` must always return As a rule, ``MyType.__canonical_args__(< arguments >)`` and ``MyType(< arguments >).__args__()`` must always return
...@@ -81,27 +81,11 @@ class PsType(metaclass=PsTypeMeta): ...@@ -81,27 +81,11 @@ class PsType(metaclass=PsTypeMeta):
# Internals: Object creation, pickling and unpickling # Internals: Object creation, pickling and unpickling
# ------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------
def __new__(cls, *args, _pickle=False, **kwargs):
if _pickle:
# force unpickler to use metaclass uniquing mechanism
return cls(*args, **kwargs)
else:
return super().__new__(cls)
def __getnewargs_ex__(self):
args = self.__args__()
kwargs = {"const": self._const, "_pickle": True}
return args, kwargs
def __getstate__(self):
# To make sure pickle does not unnecessarily override the instance dictionary
return None
@abstractmethod @abstractmethod
def __args__(self) -> tuple[Any, ...]: def __args__(self) -> tuple[Any, ...]:
"""Return the arguments used to create this instance, in canonical order, excluding the const-qualifier. """Return the arguments used to create this instance, in canonical order, excluding the const-qualifier.
The tuple returned by this method is used to serialize, deserialize, and const-convert types. The tuple returned by this method is used to identify, check equality, and const-convert types.
For each instantiable subclass ``MyType`` of ``PsType``, the following must hold:: For each instantiable subclass ``MyType`` of ``PsType``, the following must hold::
t = MyType(< arguments >) t = MyType(< arguments >)
...@@ -115,7 +99,18 @@ class PsType(metaclass=PsTypeMeta): ...@@ -115,7 +99,18 @@ class PsType(metaclass=PsTypeMeta):
"""Return a tuple containing the positional and keyword arguments of ``__init__`` """Return a tuple containing the positional and keyword arguments of ``__init__``
in their canonical order.""" in their canonical order."""
# __eq__ and __hash__ unimplemented because due to uniquing, types are equal iff their instances are equal def __eq__(self, other: object) -> bool:
if self is other:
return True
if type(self) is not type(other):
return False
other = cast(PsType, other)
return self.const == other.const and self.__args__() == other.__args__()
def __hash__(self) -> int:
return hash((type(self), self.const, self.__args__()))
# ------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------
# Constructor and properties # Constructor and properties
......
...@@ -163,4 +163,3 @@ def test_pickle(): ...@@ -163,4 +163,3 @@ def test_pickle():
for t1, t2 in zip(types, restored): for t1, t2 in zip(types, restored):
assert t1 == t2 assert t1 == t2
assert t1 is t2
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment