Skip to content

Commit 7e7fe36

Browse files
authored
Merge pull request #13703 from meeseeksmachine/auto-backport-of-pr-12170-on-v3.1.x
Backport PR #12170 on branch v3.1.x (Deprecate considering *args, **kwargs in Timer.remove_callback.)
2 parents 6bcd43e + ea90e38 commit 7e7fe36

File tree

2 files changed

+58
-20
lines changed

2 files changed

+58
-20
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Timer.remove_callback won't consider ``*args, **kwargs`` in a future version
2+
````````````````````````````````````````````````````````````````````````````
3+
4+
Currently, ``Timer.remove_callback(func, *args, **kwargs)`` removes a callback
5+
previously added by ``Timer.add_callback(func, *args, **kwargs)``, but if
6+
``*args, **kwargs`` is not passed in (``Timer.remove_callback(func)``), then
7+
the first callback with a matching ``func`` is removed, regardless of whether
8+
it was added with or without ``*args, **kwargs``.
9+
10+
In a future version, ``Timer.remove_callback`` will always use the latter
11+
behavior (not consider ``*args, **kwargs``); to specifically consider them, add
12+
the callback as a `functools.partial` object ::
13+
14+
cb = timer.add_callback(functools.partial(func, *args, **kwargs))
15+
# ...
16+
# later
17+
timer.remove_callback(cb)
18+
19+
``Timer.add_callback`` was modified to return *func* to simplify the above
20+
usage (previously it returned None); this also allows using it as a decorator.
21+
22+
The new API is modelled after `atexit.register` / `atexit.unregister`.

lib/matplotlib/backend_bases.py

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,7 @@ def set_sketch_params(self, scale=None, length=None, randomness=None):
10401040

10411041

10421042
class TimerBase(object):
1043-
'''
1043+
"""
10441044
A base class for providing timer events, useful for things animations.
10451045
Backends need to implement a few specific methods in order to use their
10461046
own timing mechanisms so that the timer events are integrated into their
@@ -1083,8 +1083,7 @@ class TimerBase(object):
10831083
Stores list of (func, args, kwargs) tuples that will be called upon
10841084
timer events. This list can be manipulated directly, or the
10851085
functions `add_callback` and `remove_callback` can be used.
1086-
1087-
'''
1086+
"""
10881087
def __init__(self, interval=None, callbacks=None):
10891088
#Initialize empty callbacks list and setup default settings if necssary
10901089
if callbacks is None:
@@ -1103,22 +1102,25 @@ def __init__(self, interval=None, callbacks=None):
11031102
self._timer = None
11041103

11051104
def __del__(self):
1106-
'Need to stop timer and possibly disconnect timer.'
1105+
"""Need to stop timer and possibly disconnect timer."""
11071106
self._timer_stop()
11081107

11091108
def start(self, interval=None):
1110-
'''
1111-
Start the timer object. `interval` is optional and will be used
1112-
to reset the timer interval first if provided.
1113-
'''
1109+
"""
1110+
Start the timer object.
1111+
1112+
Parameters
1113+
----------
1114+
interval : int, optional
1115+
Timer interval in milliseconds; overrides a previously set interval
1116+
if provided.
1117+
"""
11141118
if interval is not None:
11151119
self._set_interval(interval)
11161120
self._timer_start()
11171121

11181122
def stop(self):
1119-
'''
1120-
Stop the timer.
1121-
'''
1123+
"""Stop the timer."""
11221124
self._timer_stop()
11231125

11241126
def _timer_start(self):
@@ -1149,19 +1151,33 @@ def single_shot(self, ss):
11491151
self._timer_set_single_shot()
11501152

11511153
def add_callback(self, func, *args, **kwargs):
1152-
'''
1154+
"""
11531155
Register *func* to be called by timer when the event fires. Any
11541156
additional arguments provided will be passed to *func*.
1155-
'''
1157+
1158+
This function returns *func*, which makes it possible to use it as a
1159+
decorator.
1160+
"""
11561161
self.callbacks.append((func, args, kwargs))
1162+
return func
11571163

11581164
def remove_callback(self, func, *args, **kwargs):
1159-
'''
1160-
Remove *func* from list of callbacks. *args* and *kwargs* are optional
1161-
and used to distinguish between copies of the same function registered
1162-
to be called with different arguments.
1163-
'''
1165+
"""
1166+
Remove *func* from list of callbacks.
1167+
1168+
*args* and *kwargs* are optional and used to distinguish between copies
1169+
of the same function registered to be called with different arguments.
1170+
This behavior is deprecated. In the future, `*args, **kwargs` won't be
1171+
considered anymore; to keep a specific callback removable by itself,
1172+
pass it to `add_callback` as a `functools.partial` object.
1173+
"""
11641174
if args or kwargs:
1175+
cbook.warn_deprecated(
1176+
"3.1", "In a future version, Timer.remove_callback will not "
1177+
"take *args, **kwargs anymore, but remove all callbacks where "
1178+
"the callable matches; to keep a specific callback removable "
1179+
"by itself, pass it to add_callback as a functools.partial "
1180+
"object.")
11651181
self.callbacks.remove((func, args, kwargs))
11661182
else:
11671183
funcs = [c[0] for c in self.callbacks]
@@ -1175,11 +1191,11 @@ def _timer_set_single_shot(self):
11751191
"""Used to set single shot on underlying timer object."""
11761192

11771193
def _on_timer(self):
1178-
'''
1194+
"""
11791195
Runs all function that have been registered as callbacks. Functions
11801196
can return False (or 0) if they should not be called any more. If there
11811197
are no callbacks, the timer is automatically stopped.
1182-
'''
1198+
"""
11831199
for func, args, kwargs in self.callbacks:
11841200
ret = func(*args, **kwargs)
11851201
# docstring above explains why we use `if ret == 0` here,

0 commit comments

Comments
 (0)