Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ef71b49

Browse files
committed
Flatten CallbackRegistry._func_cid_map.
It is easier to manipulate a flat (signal, proxy) -> cid map rather than a nested signal -> (proxy -> cid) map.
1 parent 683e7bd commit ef71b49

File tree

2 files changed

+18
-28
lines changed

2 files changed

+18
-28
lines changed

lib/matplotlib/cbook.py

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class CallbackRegistry:
171171

172172
# We maintain two mappings:
173173
# callbacks: signal -> {cid -> weakref-to-callback}
174-
# _func_cid_map: signal -> {weakref-to-callback -> cid}
174+
# _func_cid_map: {(signal, weakref-to-callback) -> cid}
175175

176176
def __init__(self, exception_handler=_exception_printer, *, signals=None):
177177
self._signals = None if signals is None else list(signals) # Copy it.
@@ -201,22 +201,20 @@ def __setstate__(self, state):
201201
for cid, func in d.items()}
202202
for s, d in self.callbacks.items()}
203203
self._func_cid_map = {
204-
s: {proxy: cid for cid, proxy in d.items()}
205-
for s, d in self.callbacks.items()}
204+
(s, proxy): cid
205+
for s, d in self.callbacks.items() for cid, proxy in d.items()}
206206

207207
def connect(self, signal, func):
208208
"""Register *func* to be called when signal *signal* is generated."""
209209
if self._signals is not None:
210210
_api.check_in_list(self._signals, signal=signal)
211-
self._func_cid_map.setdefault(signal, {})
212211
proxy = _weak_or_strong_ref(func, functools.partial(self._remove_proxy, signal))
213-
if proxy in self._func_cid_map[signal]:
214-
return self._func_cid_map[signal][proxy]
215-
cid = next(self._cid_gen)
216-
self._func_cid_map[signal][proxy] = cid
217-
self.callbacks.setdefault(signal, {})
218-
self.callbacks[signal][cid] = proxy
219-
return cid
212+
try:
213+
return self._func_cid_map[signal, proxy]
214+
except KeyError:
215+
cid = self._func_cid_map[signal, proxy] = next(self._cid_gen)
216+
self.callbacks.setdefault(signal, {})[cid] = proxy
217+
return cid
220218

221219
def _connect_picklable(self, signal, func):
222220
"""
@@ -234,16 +232,14 @@ def _remove_proxy(self, signal, proxy, *, _is_finalizing=sys.is_finalizing):
234232
if _is_finalizing():
235233
# Weakrefs can't be properly torn down at that point anymore.
236234
return
237-
cid = self._func_cid_map[signal].pop(proxy, None)
235+
cid = self._func_cid_map.pop((signal, proxy), None)
238236
if cid is not None:
239237
del self.callbacks[signal][cid]
240238
self._pickled_cids.discard(cid)
241239
else: # Not found
242240
return
243-
# Clean up empty dicts
244-
if len(self.callbacks[signal]) == 0:
241+
if len(self.callbacks[signal]) == 0: # Clean up empty dicts
245242
del self.callbacks[signal]
246-
del self._func_cid_map[signal]
247243

248244
def disconnect(self, cid):
249245
"""
@@ -252,22 +248,16 @@ def disconnect(self, cid):
252248
No error is raised if such a callback does not exist.
253249
"""
254250
self._pickled_cids.discard(cid)
255-
# Clean up callbacks
256-
for signal, cid_to_proxy in list(self.callbacks.items()):
257-
proxy = cid_to_proxy.pop(cid, None)
258-
if proxy is not None:
251+
for signal, proxy in self._func_cid_map:
252+
if self._func_cid_map[signal, proxy] == cid:
259253
break
260254
else: # Not found
261255
return
262-
proxy_to_cid = self._func_cid_map[signal]
263-
for current_proxy, current_cid in list(proxy_to_cid.items()):
264-
if current_cid == cid:
265-
assert proxy is current_proxy
266-
del proxy_to_cid[current_proxy]
267-
# Clean up empty dicts
268-
if len(self.callbacks[signal]) == 0:
256+
assert self.callbacks[signal][cid] == proxy
257+
del self.callbacks[signal][cid]
258+
del self._func_cid_map[signal, proxy]
259+
if len(self.callbacks[signal]) == 0: # Clean up empty dicts
269260
del self.callbacks[signal]
270-
del self._func_cid_map[signal]
271261

272262
def process(self, s, *args, **kwargs):
273263
"""

lib/matplotlib/tests/test_cbook.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ def disconnect(self, cid):
193193
return self.callbacks.disconnect(cid)
194194

195195
def count(self):
196-
count1 = len(self.callbacks._func_cid_map.get(self.signal, []))
196+
count1 = sum(s == self.signal for s, p in self.callbacks._func_cid_map)
197197
count2 = len(self.callbacks.callbacks.get(self.signal))
198198
assert count1 == count2
199199
return count1

0 commit comments

Comments
 (0)