| 60 | # bootstrapping importlib. Many methods were simply deleting for simplicity, so if they |
| 61 | # are needed in the future they may work if simply copied back in. |
| 62 | class _WeakValueDictionary: |
| 63 | |
| 64 | def __init__(self): |
| 65 | self_weakref = _weakref.ref(self) |
| 66 | |
| 67 | # Inlined to avoid issues with inheriting from _weakref.ref before _weakref is |
| 68 | # set by _setup(). Since there's only one instance of this class, this is |
| 69 | # not expensive. |
| 70 | class KeyedRef(_weakref.ref): |
| 71 | |
| 72 | __slots__ = "key", |
| 73 | |
| 74 | def __new__(type, ob, key): |
| 75 | self = super().__new__(type, ob, type.remove) |
| 76 | self.key = key |
| 77 | return self |
| 78 | |
| 79 | def __init__(self, ob, key): |
| 80 | super().__init__(ob, self.remove) |
| 81 | |
| 82 | @staticmethod |
| 83 | def remove(wr): |
| 84 | nonlocal self_weakref |
| 85 | |
| 86 | self = self_weakref() |
| 87 | if self is not None: |
| 88 | if self._iterating: |
| 89 | self._pending_removals.append(wr.key) |
| 90 | else: |
| 91 | _weakref._remove_dead_weakref(self.data, wr.key) |
| 92 | |
| 93 | self._KeyedRef = KeyedRef |
| 94 | self.clear() |
| 95 | |
| 96 | def clear(self): |
| 97 | self._pending_removals = [] |
| 98 | self._iterating = set() |
| 99 | self.data = {} |
| 100 | |
| 101 | def _commit_removals(self): |
| 102 | pop = self._pending_removals.pop |
| 103 | d = self.data |
| 104 | while True: |
| 105 | try: |
| 106 | key = pop() |
| 107 | except IndexError: |
| 108 | return |
| 109 | _weakref._remove_dead_weakref(d, key) |
| 110 | |
| 111 | def get(self, key, default=None): |
| 112 | if self._pending_removals: |
| 113 | self._commit_removals() |
| 114 | try: |
| 115 | wr = self.data[key] |
| 116 | except KeyError: |
| 117 | return default |
| 118 | else: |
| 119 | if (o := wr()) is None: |
no outgoing calls
no test coverage detected
searching dependent graphs…