1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| def ref(obj, weak, _plain=0):
if not _plain and is_callable(obj):
return CallableReference(obj, weak)
if weak:
return WeakReference(obj)
else:
return StrongReference(obj)
def is_callable(obj):
if isinstance(obj, collections.Callable): return 1
try:
return isinstance(obj[1], collections.Callable)
except:
return 0
def ref_is(ref1,ref2):
if ref1 is ref2: return 1
o1 = ref1 and ref1()
o2 = ref2 and ref2()
# DEBUG:
print(repr(o1))
print(repr(o2))
#if o1 is None or o2 is None: return 0
return o1 is o2
class Reference:
def callback(self, obj):
for cb in self.callbacks:
cb(obj, self)
self.callbacks = []
def __init__(self, obj):
self.obj = self.ref(obj, self.callback)
self.callbacks = []
self.hash = generic_hash(obj)
def __call__(self):
return self.deref(self.obj)
def __hash__(self):
return self.hash
__eq__ = ref_is
class WeakReference(Reference):
def ref(self, obj, cb):
global weakref
if not weakref: import weakref
return weakref.ref(obj, cb)
def deref(self, obj):
return obj()
class StrongReference(Reference):
def ref(self, obj, cb):
return obj
def deref(self, obj):
return obj
class CallableWrapper:
def __init__(self, obj, func):
self.obj = obj
self.func = func
def __call__(self, *args, **kwds):
if self.obj is None:
return self.func(*args, **kwds)
else:
return self.func(self.obj, *args, **kwds)
def is_callable_instance(obj):
return type(obj) is object and hasattr(obj, '__call__')
def is_method(obj):
return hasattr(obj, 'im_self')
def unwrap(func):
try:
obj, func = func
except:
obj = None
if is_callable_instance(func):
func = func.__call__
if is_method(func):
if func.__self__ is not None:
if obj is None: obj = func.__self__
else: assert obj is func.__self__
func = func.__func__
return obj, func
class CallableReference:
# RefKeyDictionnary wants it...
callbacks = []
def __init__(self, func, weak):
obj, func = unwrap(func)
self.hash = hash((obj, func))
if obj is not None:
obj = ref(obj, weak, _plain=1)
self.obj = obj
self.func = ref(func, weak, _plain=1)
def is_dead(self):
return self.obj is not None and self.obj() is None \
or self.func() is None
def __call__(self):
if self.is_dead(): return None
obj = self.obj
if obj is not None: obj = obj()
func = self.func()
return CallableWrapper(obj, func)
def __eq__(self,other):
if self.__class__ != other.__class__: return 0
return (ref_is(self.obj,other.obj) and
ref_is(self.func,other.func))
def __hash__(self):
return self.hash
##############################################
class Test:
def func2(self):
print(self)
def __repr__(self):
return '<Test>'
def __call__(self, x):
print(x)
test = Test()
sc3 = ref(test.func2, weak=0)
wc3 = ref(test.func2, weak=1)
print(sc3==wc3) |
Partager