diff --git a/frozenlist/__init__.py b/frozenlist/__init__.py index e83f9aa0..500ff6c7 100644 --- a/frozenlist/__init__.py +++ b/frozenlist/__init__.py @@ -2,17 +2,18 @@ import types from collections.abc import MutableSequence from functools import total_ordering +from typing import Any __version__ = "1.8.1.dev0" -__all__ = ("FrozenList", "PyFrozenList") # type: Tuple[str, ...] +__all__ = ("FrozenList", "PyFrozenList") # type: tuple[str, ...] NO_EXTENSIONS = bool(os.environ.get("FROZENLIST_NO_EXTENSIONS")) # type: bool @total_ordering -class FrozenList(MutableSequence): +class PyFrozenList(MutableSequence): __slots__ = ("_frozen", "_items") __class_getitem__ = classmethod(types.GenericAlias) @@ -73,14 +74,21 @@ def __hash__(self): else: raise RuntimeError("Cannot hash unfrozen list.") + def __reduce_ex__(self, protocol): + return type(self).__unreduce_ex__, (self._frozen, self._items) -PyFrozenList = FrozenList + @classmethod + def __unreduce_ex__(cls, frozen: bool, _items: list): + fl = cls(_items) + if frozen: + fl.freeze() + return fl if not NO_EXTENSIONS: try: from ._frozenlist import FrozenList as CFrozenList # type: ignore except ImportError: # pragma: no cover - pass + FrozenList = PyFrozenList else: FrozenList = CFrozenList # type: ignore diff --git a/frozenlist/_frozenlist.pyx b/frozenlist/_frozenlist.pyx index a82d8c8f..56f2e6a1 100644 --- a/frozenlist/_frozenlist.pyx +++ b/frozenlist/_frozenlist.pyx @@ -8,7 +8,14 @@ import copy import types from collections.abc import MutableSequence - +cimport cython + +<<<<<<< HEAD +@cython.auto_pickle(False) # disable cython from doing pickling with atomic variables. +======= +# Disable pickling due to atomic variable +@cython.auto_pickle(False) +>>>>>>> b834c960eaab2c665a3f4769ab02a93eb3a9c48d cdef class FrozenList: __class_getitem__ = classmethod(types.GenericAlias) @@ -144,5 +151,20 @@ cdef class FrozenList: return new_list +<<<<<<< HEAD + def __reduce_ex__(self, protocol): + return type(self).__unreduce_ex__, (self.frozen, self._items) + + @classmethod + def __unreduce_ex__(cls, frozen:bool, _items:list): + fl = cls(_items) + if frozen: + fl.freeze() + return fl +======= + def __reduce__(self): + return (self.__class__, (self._items, self.frozen)) +>>>>>>> b834c960eaab2c665a3f4769ab02a93eb3a9c48d + MutableSequence.register(FrozenList) diff --git a/tests/test_frozenlist.py b/tests/test_frozenlist.py index c37f5c0d..6b8d51ad 100644 --- a/tests/test_frozenlist.py +++ b/tests/test_frozenlist.py @@ -1,6 +1,7 @@ # FIXME: # mypy: disable-error-code="misc" +import pickle from collections.abc import MutableSequence from copy import deepcopy @@ -372,6 +373,17 @@ def test_deepcopy_multiple_references(self) -> None: assert len(copied[1]) == 3 # Should see the change assert len(shared) == 2 # Original unchanged + def test_pickling(self): + f = self.FrozenList([1, 2]) + result = pickle.loads(pickle.dumps(f)) + assert result == f + + def test_pickling_frozen(self): + f = self.FrozenList([1, 2]) + f.freeze() + result = pickle.loads(pickle.dumps(f)) + assert result.frozen == f.frozen + class TestFrozenList(FrozenListMixin): FrozenList = FrozenList # type: ignore[assignment] # FIXME