summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-09-17 21:24:13 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-09-17 21:24:13 (GMT)
commit1b38bc65ddc337101cf0b1b02c67a9a6742b0438 (patch)
tree653dfa5fa82fede35fef990fd08982c53760c3af
parent86c9e1877cc287b602e06f3627cda2d81cbd176a (diff)
downloadcpython-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.py32
-rw-r--r--Lib/test/test_asyncio/test_events.py9
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):