From 3d50903ceeb7170699c633cc3fc6684eac86d7bb Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 14 Jan 2020 14:39:43 +0100 Subject: [PATCH] Simplify CallbackRegistry pickling. The deleted comment was really only relevant to Py2. Preserving _cid_gen (which is picklable) is necessary to later enable careful pickling of select callbacks, such as 3d mouse handlers (otherwise, the same cid may be assigned twice, one before pickling and once after unpickling). --- lib/matplotlib/cbook/__init__.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py index 5b4fad44cecf..de0e810a7949 100644 --- a/lib/matplotlib/cbook/__init__.py +++ b/lib/matplotlib/cbook/__init__.py @@ -151,9 +151,8 @@ def h(exc): """ # We maintain two mappings: - # callbacks: signal -> {cid -> callback} - # _func_cid_map: signal -> {callback -> cid} - # (actually, callbacks are weakrefs to the actual callbacks). + # callbacks: signal -> {cid -> weakref-to-callback} + # _func_cid_map: signal -> {weakref-to-callback -> cid} def __init__(self, exception_handler=_exception_printer): self.exception_handler = exception_handler @@ -161,19 +160,9 @@ def __init__(self, exception_handler=_exception_printer): self._cid_gen = itertools.count() self._func_cid_map = {} - # In general, callbacks may not be pickled; thus, we simply recreate an - # empty dictionary at unpickling. In order to ensure that `__setstate__` - # (which just defers to `__init__`) is called, `__getstate__` must - # return a truthy value (for pickle protocol>=3, i.e. Py3, the - # *actual* behavior is that `__setstate__` will be called as long as - # `__getstate__` does not return `None`, but this is undocumented -- see - # http://bugs.python.org/issue12290). - def __getstate__(self): - return {'exception_handler': self.exception_handler} - - def __setstate__(self, state): - self.__init__(**state) + # In general, callbacks may not be pickled, so we just drop them. + return {**vars(self), "callbacks": {}, "_func_cid_map": {}} def connect(self, s, func): """Register *func* to be called when signal *s* is generated.