From caee5ce489e4f7058154bea1b4bc371bd384af20 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 13 Dec 2016 21:54:20 -0200 Subject: [PATCH] Avoid importing asyncio directly because that in turn initializes logging (#8) --- _pytest/compat.py | 19 +++++++++++-------- testing/test_compat.py | 5 +++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/_pytest/compat.py b/_pytest/compat.py index 7a3d0af8173..dc3e695454f 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -19,11 +19,6 @@ # Only available in Python 3.4+ or as a backport enum = None -try: - import asyncio -except ImportError: # pragma: no cover - # Only available in Python 3.4+ or as a backport - asyncio = None _PY3 = sys.version_info > (3, 0) _PY2 = not _PY3 @@ -49,9 +44,17 @@ def _format_args(func): def is_generator(func): genfunc = inspect.isgeneratorfunction(func) - if asyncio is not None: - return genfunc and not asyncio.iscoroutinefunction(func) - return genfunc + return genfunc and not iscoroutinefunction(func) + + +def iscoroutinefunction(func): + """Return True if func is a decorated coroutine function. + + Note: copied and modified from Python 3.5's builtin couroutines.py to avoid import asyncio directly, + which in turns also initializes the "logging" module as side-effect (see issue #8). + """ + return (getattr(func, '_is_coroutine', False) or + (hasattr(inspect, 'iscoroutinefunction') and inspect.iscoroutinefunction(func))) def getlocation(function, curdir): diff --git a/testing/test_compat.py b/testing/test_compat.py index d704bb80711..1fdd07e29c6 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -15,8 +15,8 @@ def foo(): assert not is_generator(foo) +@pytest.mark.skipif(sys.version_info < (3, 4), reason='asyncio available in Python 3.4+') def test_is_generator_asyncio(testdir): - pytest.importorskip('asyncio') testdir.makepyfile(""" from _pytest.compat import is_generator import asyncio @@ -27,7 +27,8 @@ def baz(): def test_is_generator_asyncio(): assert not is_generator(baz) """) - result = testdir.runpytest() + # avoid importing asyncio into pytest's own process, which in turn imports logging (#8) + result = testdir.runpytest_subprocess() result.stdout.fnmatch_lines(['*1 passed*'])