diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2014-09-17 21:24:13 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2014-09-17 21:24:13 (GMT) |
commit | 1b38bc65ddc337101cf0b1b02c67a9a6742b0438 (patch) | |
tree | 653dfa5fa82fede35fef990fd08982c53760c3af | |
parent | 86c9e1877cc287b602e06f3627cda2d81cbd176a (diff) | |
download | cpython-1b38bc65ddc337101cf0b1b02c67a9a6742b0438.zip cpython-1b38bc65ddc337101cf0b1b02c67a9a6742b0438.tar.gz cpython-1b38bc65ddc337101cf0b1b02c67a9a6742b0438.tar.bz2 |
asyncio, Tulip issue 206: In debug mode, keep the callback in the
representation of Handle and TimerHandle after cancel().
-rw-r--r-- | Lib/asyncio/events.py | 32 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_events.py | 9 |
2 files changed, 24 insertions, 17 deletions
diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 3c7a36d..b7cc351 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -73,7 +73,7 @@ class Handle: """Object returned by callback registration methods.""" __slots__ = ('_callback', '_args', '_cancelled', '_loop', - '_source_traceback', '__weakref__') + '_source_traceback', '_repr', '__weakref__') def __init__(self, callback, args, loop): assert not isinstance(callback, Handle), 'A Handle is not a callback' @@ -81,12 +81,13 @@ class Handle: self._callback = callback self._args = args self._cancelled = False + self._repr = None if self._loop.get_debug(): self._source_traceback = traceback.extract_stack(sys._getframe(1)) else: self._source_traceback = None - def __repr__(self): + def _repr_info(self): info = [self.__class__.__name__] if self._cancelled: info.append('cancelled') @@ -95,10 +96,21 @@ class Handle: if self._source_traceback: frame = self._source_traceback[-1] info.append('created at %s:%s' % (frame[0], frame[1])) + return info + + def __repr__(self): + if self._repr is not None: + return self._repr + info = self._repr_info() return '<%s>' % ' '.join(info) def cancel(self): self._cancelled = True + if self._loop.get_debug(): + # Keep a representation in debug mode to keep callback and + # parameters. For example, to log the warning "Executing <Handle + # ...> took 2.5 second" + self._repr = repr(self) self._callback = None self._args = None @@ -131,17 +143,11 @@ class TimerHandle(Handle): del self._source_traceback[-1] self._when = when - def __repr__(self): - info = [] - if self._cancelled: - info.append('cancelled') - info.append('when=%s' % self._when) - if self._callback is not None: - info.append(_format_callback(self._callback, self._args)) - if self._source_traceback: - frame = self._source_traceback[-1] - info.append('created at %s:%s' % (frame[0], frame[1])) - return '<%s %s>' % (self.__class__.__name__, ' '.join(info)) + def _repr_info(self): + info = super()._repr_info() + pos = 2 if self._cancelled else 1 + info.insert(pos, 'when=%s' % self._when) + return info def __hash__(self): return hash(self._when) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 0cfc028..7ac845a 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1891,8 +1891,8 @@ class HandleTests(test_utils.TestCase): # cancelled handle h.cancel() self.assertEqual(repr(h), - '<Handle cancelled created at %s:%s>' - % (create_filename, create_lineno)) + '<Handle cancelled noop(1, 2) at %s:%s created at %s:%s>' + % (filename, lineno, create_filename, create_lineno)) def test_handle_source_traceback(self): loop = asyncio.get_event_loop_policy().new_event_loop() @@ -1987,8 +1987,9 @@ class TimerTests(unittest.TestCase): # cancelled handle h.cancel() self.assertEqual(repr(h), - '<TimerHandle cancelled when=123 created at %s:%s>' - % (create_filename, create_lineno)) + '<TimerHandle cancelled when=123 noop() ' + 'at %s:%s created at %s:%s>' + % (filename, lineno, create_filename, create_lineno)) def test_timer_comparison(self): |