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

Skip to content

Commit 920a6d2

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 b629ff8 commit 920a6d2

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.
@@ -203,23 +203,21 @@ def __setstate__(self, state):
203203
for cid, func in d.items()}
204204
for s, d in self.callbacks.items()}
205205
self._func_cid_map = {
206-
s: {proxy: cid for cid, proxy in d.items()}
207-
for s, d in self.callbacks.items()}
206+
(s, proxy): cid
207+
for s, d in self.callbacks.items() for cid, proxy in d.items()}
208208
self._cid_gen = itertools.count(cid_count)
209209

210210
def connect(self, signal, func):
211211
"""Register *func* to be called when signal *signal* is generated."""
212212
if self._signals is not None:
213213
_api.check_in_list(self._signals, signal=signal)
214-
self._func_cid_map.setdefault(signal, {})
215214
proxy = _weak_or_strong_ref(func, functools.partial(self._remove_proxy, signal))
216-
if proxy in self._func_cid_map[signal]:
217-
return self._func_cid_map[signal][proxy]
218-
cid = next(self._cid_gen)
219-
self._func_cid_map[signal][proxy] = cid
220-
self.callbacks.setdefault(signal, {})
221-
self.callbacks[signal][cid] = proxy
222-
return cid
215+
try:
216+
return self._func_cid_map[signal, proxy]
217+
except KeyError:
218+
cid = self._func_cid_map[signal, proxy] = next(self._cid_gen)
219+
self.callbacks.setdefault(signal, {})[cid] = proxy
220+
return cid
223221

224222
def _connect_picklable(self, signal, func):
225223
"""
@@ -237,16 +235,14 @@ def _remove_proxy(self, signal, proxy, *, _is_finalizing=sys.is_finalizing):
237235
if _is_finalizing():
238236
# Weakrefs can't be properly torn down at that point anymore.
239237
return
240-
cid = self._func_cid_map[signal].pop(proxy, None)
238+
cid = self._func_cid_map.pop((signal, proxy), None)
241239
if cid is not None:
242240
del self.callbacks[signal][cid]
243241
self._pickled_cids.discard(cid)
244242
else: # Not found
245243
return
246-
# Clean up empty dicts
247-
if len(self.callbacks[signal]) == 0:
244+
if len(self.callbacks[signal]) == 0: # Clean up empty dicts
248245
del self.callbacks[signal]
249-
del self._func_cid_map[signal]
250246

251247
def disconnect(self, cid):
252248
"""
@@ -255,22 +251,16 @@ def disconnect(self, cid):
255251
No error is raised if such a callback does not exist.
256252
"""
257253
self._pickled_cids.discard(cid)
258-
# Clean up callbacks
259-
for signal, cid_to_proxy in list(self.callbacks.items()):
260-
proxy = cid_to_proxy.pop(cid, None)
261-
if proxy is not None:
254+
for signal, proxy in self._func_cid_map:
255+
if self._func_cid_map[signal, proxy] == cid:
262256
break
263257
else: # Not found
264258
return
265-
proxy_to_cid = self._func_cid_map[signal]
266-
for current_proxy, current_cid in list(proxy_to_cid.items()):
267-
if current_cid == cid:
268-
assert proxy is current_proxy
269-
del proxy_to_cid[current_proxy]
270-
# Clean up empty dicts
271-
if len(self.callbacks[signal]) == 0:
259+
assert self.callbacks[signal][cid] == proxy
260+
del self.callbacks[signal][cid]
261+
del self._func_cid_map[signal, proxy]
262+
if len(self.callbacks[signal]) == 0: # Clean up empty dicts
272263
del self.callbacks[signal]
273-
del self._func_cid_map[signal]
274264

275265
def process(self, s, *args, **kwargs):
276266
"""

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)