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