1import os
2import types
3from collections.abc import MutableSequence
4from functools import total_ordering
5
6__version__ = "1.7.0"
7
8__all__ = ("FrozenList", "PyFrozenList") # type: Tuple[str, ...]
9
10
11NO_EXTENSIONS = bool(os.environ.get("FROZENLIST_NO_EXTENSIONS")) # type: bool
12
13
14@total_ordering
15class FrozenList(MutableSequence):
16 __slots__ = ("_frozen", "_items")
17 __class_getitem__ = classmethod(types.GenericAlias)
18
19 def __init__(self, items=None):
20 self._frozen = False
21 if items is not None:
22 items = list(items)
23 else:
24 items = []
25 self._items = items
26
27 @property
28 def frozen(self):
29 return self._frozen
30
31 def freeze(self):
32 self._frozen = True
33
34 def __getitem__(self, index):
35 return self._items[index]
36
37 def __setitem__(self, index, value):
38 if self._frozen:
39 raise RuntimeError("Cannot modify frozen list.")
40 self._items[index] = value
41
42 def __delitem__(self, index):
43 if self._frozen:
44 raise RuntimeError("Cannot modify frozen list.")
45 del self._items[index]
46
47 def __len__(self):
48 return self._items.__len__()
49
50 def __iter__(self):
51 return self._items.__iter__()
52
53 def __reversed__(self):
54 return self._items.__reversed__()
55
56 def __eq__(self, other):
57 return list(self) == other
58
59 def __le__(self, other):
60 return list(self) <= other
61
62 def insert(self, pos, item):
63 if self._frozen:
64 raise RuntimeError("Cannot modify frozen list.")
65 self._items.insert(pos, item)
66
67 def __repr__(self):
68 return f"<FrozenList(frozen={self._frozen}, {self._items!r})>"
69
70 def __hash__(self):
71 if self._frozen:
72 return hash(tuple(self))
73 else:
74 raise RuntimeError("Cannot hash unfrozen list.")
75
76
77PyFrozenList = FrozenList
78
79
80if not NO_EXTENSIONS:
81 try:
82 from ._frozenlist import FrozenList as CFrozenList # type: ignore
83 except ImportError: # pragma: no cover
84 pass
85 else:
86 FrozenList = CFrozenList # type: ignore