|
| 1 | +import _weakref |
| 2 | +import micropython |
| 3 | + |
| 4 | + |
| 5 | +class _weakref_entry: |
| 6 | + def __init__(self, parent, obj): |
| 7 | + self.parent = parent |
| 8 | + |
| 9 | + if not hasattr(obj, "__dict__") and not hasattr(obj, "__weakref__"): |
| 10 | + raise TypeError("cannot create weak reference to '{}' object".format(type(obj).__name__)) |
| 11 | + |
| 12 | + # linked list ensures this will always be part of the same cyclic isolate as the original object |
| 13 | + self.next = obj |
| 14 | + try: |
| 15 | + getattr(obj, "__weakref__").next = self |
| 16 | + except (KeyError, AttributeError): |
| 17 | + setattr(obj, "__weakref__", self) |
| 18 | + |
| 19 | + def __del__(self): |
| 20 | + p = self.parent |
| 21 | + p(None) |
| 22 | + if p.__callback__ is not None: |
| 23 | + micropython.schedule(p.__callback__, p) |
| 24 | + |
| 25 | +class ref(_weakref.ref): |
| 26 | + def __init__(self, obj, callback=None): |
| 27 | + super().__init__(obj) |
| 28 | + self.__callback__ = callback |
| 29 | + _weakref_entry(self, obj) |
| 30 | + |
| 31 | +class finalize: |
| 32 | + def __init__(self, obj, func, *args, **kwargs): |
| 33 | + self._func = func |
| 34 | + self._args = args |
| 35 | + self._kwargs = kwargs |
| 36 | + self._ref = ref(obj, self) |
| 37 | + |
| 38 | + @property |
| 39 | + def alive(self): |
| 40 | + return self._ref() is not None |
| 41 | + |
| 42 | + def peek(self): |
| 43 | + obj = self._ref() |
| 44 | + if obj is not None: |
| 45 | + return (obj, self._func, self._args, self._kwargs) |
| 46 | + |
| 47 | + def detach(self): |
| 48 | + ret = self.peek() |
| 49 | + self._ref(None) |
| 50 | + return ret |
| 51 | + |
| 52 | + def __call__(self, r=None): |
| 53 | + return self._func(*self._args, **self._kwargs) |
| 54 | + |
0 commit comments