Skip to content

Commit eeeef36

Browse files
committed
Fix Handle and TimerHandle repr in debug mode
Tulip issue python#206: In debug mode, keep the callback in the representation of Handle and TimerHandle after cancel().
1 parent 25a8408 commit eeeef36

File tree

2 files changed

+24
-17
lines changed

2 files changed

+24
-17
lines changed

asyncio/events.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -73,20 +73,21 @@ class Handle:
7373
"""Object returned by callback registration methods."""
7474

7575
__slots__ = ('_callback', '_args', '_cancelled', '_loop',
76-
'_source_traceback', '__weakref__')
76+
'_source_traceback', '_repr', '__weakref__')
7777

7878
def __init__(self, callback, args, loop):
7979
assert not isinstance(callback, Handle), 'A Handle is not a callback'
8080
self._loop = loop
8181
self._callback = callback
8282
self._args = args
8383
self._cancelled = False
84+
self._repr = None
8485
if self._loop.get_debug():
8586
self._source_traceback = traceback.extract_stack(sys._getframe(1))
8687
else:
8788
self._source_traceback = None
8889

89-
def __repr__(self):
90+
def _repr_info(self):
9091
info = [self.__class__.__name__]
9192
if self._cancelled:
9293
info.append('cancelled')
@@ -95,10 +96,21 @@ def __repr__(self):
9596
if self._source_traceback:
9697
frame = self._source_traceback[-1]
9798
info.append('created at %s:%s' % (frame[0], frame[1]))
99+
return info
100+
101+
def __repr__(self):
102+
if self._repr is not None:
103+
return self._repr
104+
info = self._repr_info()
98105
return '<%s>' % ' '.join(info)
99106

100107
def cancel(self):
101108
self._cancelled = True
109+
if self._loop.get_debug():
110+
# Keep a representation in debug mode to keep callback and
111+
# parameters. For example, to log the warning "Executing <Handle
112+
# ...> took 2.5 second"
113+
self._repr = repr(self)
102114
self._callback = None
103115
self._args = None
104116

@@ -131,17 +143,11 @@ def __init__(self, when, callback, args, loop):
131143
del self._source_traceback[-1]
132144
self._when = when
133145

134-
def __repr__(self):
135-
info = []
136-
if self._cancelled:
137-
info.append('cancelled')
138-
info.append('when=%s' % self._when)
139-
if self._callback is not None:
140-
info.append(_format_callback(self._callback, self._args))
141-
if self._source_traceback:
142-
frame = self._source_traceback[-1]
143-
info.append('created at %s:%s' % (frame[0], frame[1]))
144-
return '<%s %s>' % (self.__class__.__name__, ' '.join(info))
146+
def _repr_info(self):
147+
info = super()._repr_info()
148+
pos = 2 if self._cancelled else 1
149+
info.insert(pos, 'when=%s' % self._when)
150+
return info
145151

146152
def __hash__(self):
147153
return hash(self._when)

tests/test_events.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,8 +1891,8 @@ def test_handle_repr_debug(self):
18911891
# cancelled handle
18921892
h.cancel()
18931893
self.assertEqual(repr(h),
1894-
'<Handle cancelled created at %s:%s>'
1895-
% (create_filename, create_lineno))
1894+
'<Handle cancelled noop(1, 2) at %s:%s created at %s:%s>'
1895+
% (filename, lineno, create_filename, create_lineno))
18961896

18971897
def test_handle_source_traceback(self):
18981898
loop = asyncio.get_event_loop_policy().new_event_loop()
@@ -1987,8 +1987,9 @@ def test_timer_repr_debug(self):
19871987
# cancelled handle
19881988
h.cancel()
19891989
self.assertEqual(repr(h),
1990-
'<TimerHandle cancelled when=123 created at %s:%s>'
1991-
% (create_filename, create_lineno))
1990+
'<TimerHandle cancelled when=123 noop() '
1991+
'at %s:%s created at %s:%s>'
1992+
% (filename, lineno, create_filename, create_lineno))
19921993

19931994

19941995
def test_timer_comparison(self):

0 commit comments

Comments
 (0)