[Python-checkins] cpython (merge 3.4 -> default): Asyncio issue 222 / PR 231 (Victor Stinner) -- fix @coroutine functions without
guido.van.rossum
python-checkins at python.org
Sun May 3 03:46:18 CEST 2015
https://hg.python.org/cpython/rev/352d1fb2a8e4
changeset: 95856:352d1fb2a8e4
parent: 95854:02e3bf65b2f8
parent: 95855:3795daceff85
user: Guido van Rossum <guido at python.org>
date: Sat May 02 18:45:51 2015 -0700
summary:
Asyncio issue 222 / PR 231 (Victor Stinner) -- fix @coroutine functions without __name__. (Merged from 3.4 branch.)
files:
Lib/asyncio/coroutines.py | 18 +++-
Lib/asyncio/events.py | 14 ++-
Lib/asyncio/futures.py | 2 +-
Lib/test/test_asyncio/test_tasks.py | 65 +++++++++++-----
Misc/NEWS | 27 +++++++
5 files changed, 94 insertions(+), 32 deletions(-)
diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py
--- a/Lib/asyncio/coroutines.py
+++ b/Lib/asyncio/coroutines.py
@@ -151,7 +151,8 @@
w = CoroWrapper(coro(*args, **kwds), func)
if w._source_traceback:
del w._source_traceback[-1]
- w.__name__ = func.__name__
+ if hasattr(func, '__name__'):
+ w.__name__ = func.__name__
if hasattr(func, '__qualname__'):
w.__qualname__ = func.__qualname__
w.__doc__ = func.__doc__
@@ -175,25 +176,30 @@
def _format_coroutine(coro):
assert iscoroutine(coro)
- coro_name = getattr(coro, '__qualname__', coro.__name__)
+
+ if isinstance(coro, CoroWrapper):
+ func = coro.func
+ else:
+ func = coro
+ coro_name = events._format_callback(func, ())
filename = coro.gi_code.co_filename
if (isinstance(coro, CoroWrapper)
and not inspect.isgeneratorfunction(coro.func)):
filename, lineno = events._get_function_source(coro.func)
if coro.gi_frame is None:
- coro_repr = ('%s() done, defined at %s:%s'
+ coro_repr = ('%s done, defined at %s:%s'
% (coro_name, filename, lineno))
else:
- coro_repr = ('%s() running, defined at %s:%s'
+ coro_repr = ('%s running, defined at %s:%s'
% (coro_name, filename, lineno))
elif coro.gi_frame is not None:
lineno = coro.gi_frame.f_lineno
- coro_repr = ('%s() running at %s:%s'
+ coro_repr = ('%s running at %s:%s'
% (coro_name, filename, lineno))
else:
lineno = coro.gi_code.co_firstlineno
- coro_repr = ('%s() done, defined at %s:%s'
+ coro_repr = ('%s done, defined at %s:%s'
% (coro_name, filename, lineno))
return coro_repr
diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py
--- a/Lib/asyncio/events.py
+++ b/Lib/asyncio/events.py
@@ -54,15 +54,21 @@
suffix = _format_args(args) + suffix
return _format_callback(func.func, func.args, suffix)
- func_repr = getattr(func, '__qualname__', None)
- if not func_repr:
+ if hasattr(func, '__qualname__'):
+ func_repr = getattr(func, '__qualname__')
+ elif hasattr(func, '__name__'):
+ func_repr = getattr(func, '__name__')
+ else:
func_repr = repr(func)
if args is not None:
func_repr += _format_args(args)
if suffix:
func_repr += suffix
+ return func_repr
+def _format_callback_source(func, args):
+ func_repr = _format_callback(func, args)
source = _get_function_source(func)
if source:
func_repr += ' at %s:%s' % source
@@ -92,7 +98,7 @@
if self._cancelled:
info.append('cancelled')
if self._callback is not None:
- info.append(_format_callback(self._callback, self._args))
+ info.append(_format_callback_source(self._callback, self._args))
if self._source_traceback:
frame = self._source_traceback[-1]
info.append('created at %s:%s' % (frame[0], frame[1]))
@@ -119,7 +125,7 @@
try:
self._callback(*self._args)
except Exception as exc:
- cb = _format_callback(self._callback, self._args)
+ cb = _format_callback_source(self._callback, self._args)
msg = 'Exception in callback {}'.format(cb)
context = {
'message': msg,
diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py
--- a/Lib/asyncio/futures.py
+++ b/Lib/asyncio/futures.py
@@ -162,7 +162,7 @@
cb = ''
def format_cb(callback):
- return events._format_callback(callback, ())
+ return events._format_callback_source(callback, ())
if size == 1:
cb = format_cb(cb[0])
diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py
--- a/Lib/test/test_asyncio/test_tasks.py
+++ b/Lib/test/test_asyncio/test_tasks.py
@@ -1,5 +1,7 @@
"""Tests for tasks.py."""
+import contextlib
+import functools
import os
import re
import sys
@@ -28,6 +30,19 @@
pass
+ at contextlib.contextmanager
+def set_coroutine_debug(enabled):
+ coroutines = asyncio.coroutines
+
+ old_debug = coroutines._DEBUG
+ try:
+ coroutines._DEBUG = enabled
+ yield
+ finally:
+ coroutines._DEBUG = old_debug
+
+
+
def format_coroutine(qualname, state, src, source_traceback, generator=False):
if generator:
state = '%s' % state
@@ -279,6 +294,29 @@
fut.set_result(None)
self.loop.run_until_complete(task)
+ def test_task_repr_partial_corowrapper(self):
+ # Issue #222: repr(CoroWrapper) must not fail in debug mode if the
+ # coroutine is a partial function
+ with set_coroutine_debug(True):
+ self.loop.set_debug(True)
+
+ @asyncio.coroutine
+ def func(x, y):
+ yield from asyncio.sleep(0)
+
+ partial_func = asyncio.coroutine(functools.partial(func, 1))
+ task = self.loop.create_task(partial_func(2))
+
+ # make warnings quiet
+ task._log_destroy_pending = False
+ self.addCleanup(task._coro.close)
+
+ coro_repr = repr(task._coro)
+ expected = ('<CoroWrapper TaskTests.test_task_repr_partial_corowrapper'
+ '.<locals>.func(1)() running, ')
+ self.assertTrue(coro_repr.startswith(expected),
+ coro_repr)
+
def test_task_basics(self):
@asyncio.coroutine
def outer():
@@ -1555,25 +1593,16 @@
# The frame should have changed.
self.assertIsNone(gen.gi_frame)
- # Save debug flag.
- old_debug = asyncio.coroutines._DEBUG
- try:
- # Test with debug flag cleared.
- asyncio.coroutines._DEBUG = False
+ # Test with debug flag cleared.
+ with set_coroutine_debug(False):
check()
- # Test with debug flag set.
- asyncio.coroutines._DEBUG = True
+ # Test with debug flag set.
+ with set_coroutine_debug(True):
check()
- finally:
- # Restore original debug flag.
- asyncio.coroutines._DEBUG = old_debug
-
def test_yield_from_corowrapper(self):
- old_debug = asyncio.coroutines._DEBUG
- asyncio.coroutines._DEBUG = True
- try:
+ with set_coroutine_debug(True):
@asyncio.coroutine
def t1():
return (yield from t2())
@@ -1591,8 +1620,6 @@
task = asyncio.Task(t1(), loop=self.loop)
val = self.loop.run_until_complete(task)
self.assertEqual(val, (1, 2, 3))
- finally:
- asyncio.coroutines._DEBUG = old_debug
def test_yield_from_corowrapper_send(self):
def foo():
@@ -1663,14 +1690,10 @@
@mock.patch('asyncio.coroutines.logger')
def test_coroutine_never_yielded(self, m_log):
- debug = asyncio.coroutines._DEBUG
- try:
- asyncio.coroutines._DEBUG = True
+ with set_coroutine_debug(True):
@asyncio.coroutine
def coro_noop():
pass
- finally:
- asyncio.coroutines._DEBUG = debug
tb_filename = __file__
tb_lineno = sys._getframe().f_lineno + 2
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -101,6 +101,7 @@
Library
-------
+<<<<<<< local
- Issue #16914: new debuglevel 2 in smtplib adds timestamps to debug output.
- Issue #7159: urllib.request now supports sending auth credentials
@@ -125,6 +126,32 @@
- Issue #21217: inspect.getsourcelines() now tries to compute the start and end
lines from the code object, fixing an issue when a lambda function is used as
decorator argument. Patch by Thomas Ballinger and Allison Kaptur.
+=======
+- Asyncio issue 222 / PR 231 (Victor Stinner) -- fix @coroutine
+ functions without __name__.
+
+- Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes.
+ Patch written by William Orr.
+
+- Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup
+ and siftdown functions.
+
+- Backport collections.deque fixes from Python 3.5. Prevents reentrant badness
+ during deletion by deferring the decref until the container has been restored
+ to a consistent state.
+
+- Issue #23008: Fixed resolving attributes with boolean value is False in pydoc.
+
+- Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't
+ increment unfinished tasks (this bug was introduced in 3.4.3 when
+ JoinableQueue was merged with Queue).
+
+- Issue #23908: os functions now reject paths with embedded null character
+ on Windows instead of silently truncate them.
+
+- Issue #23728: binascii.crc_hqx() could return an integer outside of the range
+ 0-0xffff for empty data.
+>>>>>>> other
- Issue #23811: Add missing newline to the PyCompileError error message.
Patch by Alex Shkop.
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list