codekingpro/portable-devtools
114k
1# cython: freethreading_compatible = True2# distutils: language = c++3 4from cpython.bool cimport PyBool_FromLong5from libcpp.atomic cimport atomic6 7import copy8import types9from collections.abc import MutableSequence10 11 12cdef class FrozenList:13 __class_getitem__ = classmethod(types.GenericAlias)14 15 cdef atomic[bint] _frozen16 cdef list _items17 18 def __init__(self, items=None):19 self._frozen.store(False)20 if items is not None:21 items = list(items)22 else:23 items = []24 self._items = items25 26 @property27 def frozen(self):28 return PyBool_FromLong(self._frozen.load())29 30 cdef object _check_frozen(self):31 if self._frozen.load():32 raise RuntimeError("Cannot modify frozen list.")33 34 cdef inline object _fast_len(self):35 return len(self._items)36 37 def freeze(self):38 self._frozen.store(True)39 40 def __getitem__(self, index):41 return self._items[index]42 43 def __setitem__(self, index, value):44 self._check_frozen()45 self._items[index] = value46 47 def __delitem__(self, index):48 self._check_frozen()49 del self._items[index]50 51 def __len__(self):52 return self._fast_len()53 54 def __iter__(self):55 return self._items.__iter__()56 57 def __reversed__(self):58 return self._items.__reversed__()59 60 def __richcmp__(self, other, op):61 if op == 0: # <62 return list(self) < other63 if op == 1: # <=64 return list(self) <= other65 if op == 2: # ==66 return list(self) == other67 if op == 3: # !=68 return list(self) != other69 if op == 4: # >70 return list(self) > other71 if op == 5: # =>72 return list(self) >= other73 74 def insert(self, pos, item):75 self._check_frozen()76 self._items.insert(pos, item)77 78 def __contains__(self, item):79 return item in self._items80 81 def __iadd__(self, items):82 self._check_frozen()83 self._items += list(items)84 return self85 86 def index(self, item):87 return self._items.index(item)88 89 def remove(self, item):90 self._check_frozen()91 self._items.remove(item)92 93 def clear(self):94 self._check_frozen()95 self._items.clear()96 97 def extend(self, items):98 self._check_frozen()99 self._items += list(items)100 101 def reverse(self):102 self._check_frozen()103 self._items.reverse()104 105 def pop(self, index=-1):106 self._check_frozen()107 return self._items.pop(index)108 109 def append(self, item):110 self._check_frozen()111 return self._items.append(item)112 113 def count(self, item):114 return self._items.count(item)115 116 def __repr__(self):117 return '<FrozenList(frozen={}, {!r})>'.format(self._frozen.load(),118 self._items)119 120 def __hash__(self):121 if self._frozen.load():122 return hash(tuple(self._items))123 else:124 raise RuntimeError("Cannot hash unfrozen list.")125 126 def __deepcopy__(self, memo):127 cdef FrozenList new_list128 obj_id = id(self)129 130 # Return existing copy if already processed (circular reference)131 if obj_id in memo:132 return memo[obj_id]133 134 # Create new instance and register immediately135 new_list = self.__class__([])136 memo[obj_id] = new_list137 138 # Deep copy items139 new_list._items[:] = [copy.deepcopy(item, memo) for item in self._items]140 141 # Preserve frozen state142 if self._frozen.load():143 new_list.freeze()144 145 return new_list146 147 148MutableSequence.register(FrozenList)149 