Skip to content

Commit bef9d16

Browse files
committed
Require calling a _BoundMethodProxy to get the underlying callable.
Code that used to call `_proxy(...)` now needs to call `_proxy()(...)`. Instead of catching a ReferenceError, that could be either raised by a failure to dereference the proxy, or by the underlying callable, one can now check that `_proxy()` does not return None (to distinguish between the two cases). This is the same design as the stdlib's WeakMethod.
1 parent bcc2f12 commit bef9d16

File tree

1 file changed

+20
-27
lines changed

1 file changed

+20
-27
lines changed

lib/matplotlib/cbook/__init__.py

+20-27
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,10 @@ def add_destroy_callback(self, callback):
183183
self._destroy_callbacks.append(_BoundMethodProxy(callback))
184184

185185
def _destroy(self, wk):
186-
for callback in self._destroy_callbacks:
187-
try:
188-
callback(self)
189-
except ReferenceError:
190-
pass
186+
for ref in self._destroy_callbacks:
187+
func = ref()
188+
if func is not None:
189+
func(self)
191190

192191
def __getstate__(self):
193192
d = self.__dict__.copy()
@@ -205,26 +204,19 @@ def __setstate__(self, statedict):
205204
self.inst = ref(inst)
206205

207206
def __call__(self, *args, **kwargs):
207+
"""Reconstructs the weakref'd callable, or None if the target is dead.
208208
"""
209-
Proxy for a call to the weak referenced object. Take
210-
arbitrary params to pass to the callable.
211-
212-
Raises `ReferenceError`: When the weak reference refers to
213-
a dead object
214-
"""
215-
if self.inst is not None and self.inst() is None:
216-
raise ReferenceError
217-
elif self.inst is not None:
218-
# build a new instance method with a strong reference to the
219-
# instance
220-
221-
mtd = types.MethodType(self.func, self.inst())
222-
209+
if self.inst:
210+
obj = self.inst()
211+
if obj is None:
212+
return None
213+
else:
214+
# build a new instance method with a strong reference to the
215+
# instance
216+
return types.MethodType(self.func, self.inst())
223217
else:
224218
# not a bound method, just return the func
225-
mtd = self.func
226-
# invoke the callable and return the result
227-
return mtd(*args, **kwargs)
219+
return self.func
228220

229221
def __eq__(self, other):
230222
"""
@@ -383,12 +375,13 @@ def process(self, s, *args, **kwargs):
383375
process signal `s`. All of the functions registered to receive
384376
callbacks on `s` will be called with ``**args`` and ``**kwargs``
385377
"""
386-
if s in self.callbacks:
387-
for cid, proxy in list(six.iteritems(self.callbacks[s])):
378+
for ref in list(self.callbacks.get(s, {}).values()):
379+
func = ref()
380+
if func is None:
381+
self._remove_proxy(ref)
382+
else:
388383
try:
389-
proxy(*args, **kwargs)
390-
except ReferenceError:
391-
self._remove_proxy(proxy)
384+
func(*args, **kwargs)
392385
# this does not capture KeyboardInterrupt, SystemExit,
393386
# and GeneratorExit
394387
except Exception as exc:

0 commit comments

Comments
 (0)