@@ -104,6 +104,16 @@ def __hash__(self):
104104 return hash (self ._obj )
105105
106106
107+ def _weak_or_strong_ref (func , callback ):
108+ """
109+ Return a `WeakMethod` wrapping *func* if possible, else a `_StrongRef`.
110+ """
111+ try :
112+ return weakref .WeakMethod (func , callback )
113+ except TypeError :
114+ return _StrongRef (func )
115+
116+
107117class CallbackRegistry :
108118 """
109119 Handle registering and disconnecting for a set of signals and callbacks:
@@ -157,21 +167,37 @@ def __init__(self, exception_handler=_exception_printer):
157167 self .callbacks = {}
158168 self ._cid_gen = itertools .count ()
159169 self ._func_cid_map = {}
170+ # A hidden variable that marks cids that need to be pickled.
171+ self ._pickled_cids = set ()
160172
161173 def __getstate__ (self ):
162- # In general, callbacks may not be pickled, so we just drop them.
163- return {** vars (self ), "callbacks" : {}, "_func_cid_map" : {}}
174+ return {
175+ ** vars (self ),
176+ # In general, callbacks may not be pickled, so we just drop them,
177+ # unless directed otherwise by self._pickled_cids.
178+ "callbacks" : {s : {cid : proxy () for cid , proxy in d .items ()
179+ if cid in self ._pickled_cids }
180+ for s , d in self .callbacks .items ()},
181+ # It is simpler to reconstruct this from callbacks in __setstate__.
182+ "_func_cid_map" : None ,
183+ }
184+
185+ def __setstate__ (self , state ):
186+ vars (self ).update (state )
187+ self .callbacks = {
188+ s : {cid : _weak_or_strong_ref (func , self ._remove_proxy )
189+ for cid , func in d .items ()}
190+ for s , d in self .callbacks .items ()}
191+ self ._func_cid_map = {
192+ s : {proxy : cid for cid , proxy in d .items ()}
193+ for s , d in self .callbacks .items ()}
164194
165195 def connect (self , s , func ):
166196 """Register *func* to be called when signal *s* is generated."""
167197 self ._func_cid_map .setdefault (s , {})
168- try :
169- proxy = weakref .WeakMethod (func , self ._remove_proxy )
170- except TypeError :
171- proxy = _StrongRef (func )
198+ proxy = _weak_or_strong_ref (func , self ._remove_proxy )
172199 if proxy in self ._func_cid_map [s ]:
173200 return self ._func_cid_map [s ][proxy ]
174-
175201 cid = next (self ._cid_gen )
176202 self ._func_cid_map [s ][proxy ] = cid
177203 self .callbacks .setdefault (s , {})
0 commit comments