Joshua Bronson <[email protected]> added the comment:
Thanks so much, @oremanj! Indeed, merely subscripting the class triggers the
bug, and your 'del slots' workaround does the trick!
For completeness, there is an updated (yet more minimal) repro below/attached.
"""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()
>>> example
<__main__.MyGeneric object at ...>
>>> example._other
<__main__.MyGeneric object at ...>
>>> example._other._other
<weakref at ...; to 'MyGeneric' at ...>
>>> 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 = ref(self)
self._other = 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()
# Merely the following is enough to trigger the bug on Python 3.6:
MyGeneric[T]
# This works around the issue if run first (thanks @oremanj):
del MyGeneric.__slots__ # does not actually 'unslot' the class
if __name__ == "__main__":
import doctest
doctest.testmod(optionflags=doctest.ELLIPSIS)
----------
Added file: https://bugs.python.org/file49357/bpo41451-repro-min+workaround.py
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue41451>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com