# HG changeset patch # User "Denver Coneybeare" # Date 1363391909 14400 # Node ID 2541669778fe27dd036253582e6347de4c2821b7 # Parent b49971a1e70dca77cbd64e1ac3c256e719ef26ca Replaced the mutable argument defaults [] and {} in threading.Timer.__init__() to None, which is immutable diff -r b49971a1e70d -r 2541669778fe Doc/library/threading.rst --- a/Doc/library/threading.rst Wed Mar 13 02:27:53 2013 +0200 +++ b/Doc/library/threading.rst Fri Mar 15 19:58:29 2013 -0400 @@ -839,10 +839,12 @@ t.start() # after 30 seconds, "hello, world" will be printed -.. class:: Timer(interval, function, args=[], kwargs={}) +.. class:: Timer(interval, function, args=None, kwargs=None) Create a timer that will run *function* with arguments *args* and keyword arguments *kwargs*, after *interval* seconds have passed. + If *args* is None (the default) then an empty list will be used. + If *kwargs* is None (the default) then an empty dict will be used. .. versionchanged:: 3.3 changed from a factory function to a class. diff -r b49971a1e70d -r 2541669778fe Lib/test/test_threading.py --- a/Lib/test/test_threading.py Wed Mar 13 02:27:53 2013 +0200 +++ b/Lib/test/test_threading.py Fri Mar 15 19:58:29 2013 -0400 @@ -787,6 +787,29 @@ self.assertEqual(p.returncode, 0, "Unexpected error: " + stderr.decode()) self.assertEqual(data, expected_output) +class TimerTests(BaseTestCase): + + def setUp(self): + BaseTestCase.setUp(self) + self.callback_invocations = [] + self.callback_event = threading.Event() + + def test_init_immutable_default_args(self): + timer1 = threading.Timer(1, self._callback_spy) + timer1.args.append("blah") + timer1.kwargs["foo"] = "bar" + timer2 = threading.Timer(1, self._callback_spy) + timer2.start() + self.callback_event.wait() + self.assertEquals(len(self.callback_invocations), 1) + (invocation_args, invocation_kwargs) = self.callback_invocations[0] + self.assertEquals(invocation_args, ()) + self.assertEquals(invocation_kwargs, {}) + + def _callback_spy(self, *args, **kwargs): + self.callback_invocations.append((args, kwargs)) + self.callback_event.set() + class LockTests(lock_tests.LockTests): locktype = staticmethod(threading.Lock) diff -r b49971a1e70d -r 2541669778fe Lib/threading.py --- a/Lib/threading.py Wed Mar 13 02:27:53 2013 +0200 +++ b/Lib/threading.py Fri Mar 15 19:58:29 2013 -0400 @@ -808,17 +808,17 @@ class Timer(Thread): """Call a function after a specified number of seconds: - t = Timer(30.0, f, args=[], kwargs={}) + t = Timer(30.0, f, args=None, kwargs=None) t.start() t.cancel() # stop the timer's action if it's still waiting """ - def __init__(self, interval, function, args=[], kwargs={}): + def __init__(self, interval, function, args=None, kwargs=None): Thread.__init__(self) self.interval = interval self.function = function - self.args = args - self.kwargs = kwargs + self.args = args if args is not None else [] + self.kwargs = kwargs if kwargs is not None else {} self.finished = Event() def cancel(self):