1import sys 2import types 3from collections.abc import MutableSequence 4 5 6cdef class FrozenList: 7 8 if sys.version_info >= (3, 9): 9 __class_getitem__ = classmethod(types.GenericAlias) 10 else: 11 @classmethod 12 def __class_getitem__(cls): 13 return cls 14 15 cdef readonly bint frozen 16 cdef list _items 17 18 def __init__(self, items=None): 19 self.frozen = False 20 if items is not None: 21 items = list(items) 22 else: 23 items = [] 24 self._items = items 25 26 cdef object _check_frozen(self): 27 if self.frozen: 28 raise RuntimeError("Cannot modify frozen list.") 29 30 cdef inline object _fast_len(self): 31 return len(self._items) 32 33 def freeze(self): 34 self.frozen = True 35 36 def __getitem__(self, index): 37 return self._items[index] 38 39 def __setitem__(self, index, value): 40 self._check_frozen() 41 self._items[index] = value 42 43 def __delitem__(self, index): 44 self._check_frozen() 45 del self._items[index] 46 47 def __len__(self): 48 return self._fast_len() 49 50 def __iter__(self): 51 return self._items.__iter__() 52 53 def __reversed__(self): 54 return self._items.__reversed__() 55 56 def __richcmp__(self, other, op): 57 if op == 0: # < 58 return list(self) < other 59 if op == 1: # <= 60 return list(self) <= other 61 if op == 2: # == 62 return list(self) == other 63 if op == 3: # != 64 return list(self) != other 65 if op == 4: # > 66 return list(self) > other 67 if op == 5: # => 68 return list(self) >= other 69 70 def insert(self, pos, item): 71 self._check_frozen() 72 self._items.insert(pos, item) 73 74 def __contains__(self, item): 75 return item in self._items 76 77 def __iadd__(self, items): 78 self._check_frozen() 79 self._items += list(items) 80 return self 81 82 def index(self, item): 83 return self._items.index(item) 84 85 def remove(self, item): 86 self._check_frozen() 87 self._items.remove(item) 88 89 def clear(self): 90 self._check_frozen() 91 self._items.clear() 92 93 def extend(self, items): 94 self._check_frozen() 95 self._items += list(items) 96 97 def reverse(self): 98 self._check_frozen() 99 self._items.reverse() 100 101 def pop(self, index=-1): 102 self._check_frozen() 103 return self._items.pop(index) 104 105 def append(self, item): 106 self._check_frozen() 107 return self._items.append(item) 108 109 def count(self, item): 110 return self._items.count(item) 111 112 def __repr__(self): 113 return '<FrozenList(frozen={}, {!r})>'.format(self.frozen, 114 self._items) 115 116 def __hash__(self): 117 if self.frozen: 118 return hash(tuple(self._items)) 119 else: 120 raise RuntimeError("Cannot hash unfrozen list.") 121 122 123MutableSequence.register(FrozenList) 124