"""Repro for Python 3.6 slots + weakref + typing.Generic subclass bug.""" from typing import Generic, TypeVar from weakref import ref T = TypeVar("T") class MyGeneric(Generic[T]): """MyGeneric works as expected. >>> example = MyGeneric() >>> from pickle import dumps, loads >>> pickled = dumps(example) >>> roundtripped = loads(pickled) >>> roundtripped <__main__.MyGeneric object at ...> """ __slots__ = ("_other", "__weakref__") def __init__(self) -> None: self._init_other() def _init_other(self) -> None: other = self.__class__.__new__(self.__class__) other._other = self self._other = ref(other) def __getstate__(self) -> dict: """Needed to enable pickling due to use of __slots__ and weakrefs.""" return {} def __setstate__(self, _) -> None: """Needed because use of __slots__ would prevent unpickling otherwise.""" self._init_other() # So far so good, but now let's make a subclass. # The following class definition works on Python > 3.6, but fails on 3.6 with # TypeError: __weakref__ slot disallowed: either we already got one, or __itemsize__ != 0 class FailsInPy36(MyGeneric[T]): """Minimal repro. >>> repro = FailsInPy36() >>> repro <__main__.FailsInPy36 object at ...> """ if __name__ == "__main__": import doctest doctest.testmod(optionflags=doctest.ELLIPSIS)