Skip to content

Commit

Permalink
Use inspect to properly detect generators. Fixes pytest-dev#2129
Browse files Browse the repository at this point in the history
  • Loading branch information
malinoff committed Dec 11, 2016
1 parent da40bcf commit 3a59acf
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 5 deletions.
15 changes: 10 additions & 5 deletions _pytest/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
# 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

Expand All @@ -42,11 +48,10 @@ def _format_args(func):


def is_generator(func):
try:
return _pytest._code.getrawcode(func).co_flags & 32 # generator function
except AttributeError: # builtin functions have no bytecode
# assume them to not be generators
return False
genfunc = inspect.isgeneratorfunction(func)
if asyncio is not None:
return genfunc and not asyncio.iscoroutinefunction(func)
return genfunc


def getlocation(function, curdir):
Expand Down
7 changes: 7 additions & 0 deletions testing/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import sys

collect_ignore = []
if sys.version_info[0] < 3:
collect_ignore.append("test_compat_3.py")
if sys.version_info < (3, 5):
collect_ignore.append("test_compat_35.py")
12 changes: 12 additions & 0 deletions testing/test_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from _pytest.compat import is_generator


def test_is_generator():
def zap():
yield

def foo():
pass

assert is_generator(zap)
assert not is_generator(foo)
15 changes: 15 additions & 0 deletions testing/test_compat_3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import pytest
from _pytest.compat import is_generator
try:
import asyncio
except ImportError:
asyncio = None


@pytest.mark.skipif(asyncio is None, reason='asyncio is not installed')
def test_is_generator():
@asyncio.coroutine
def baz():
yield from [1,2,3]

assert not is_generator(baz)
12 changes: 12 additions & 0 deletions testing/test_compat_35.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from _pytest.compat import is_generator


def test_is_generator_py35():
async def foo():
await foo()

async def bar():
pass

assert not is_generator(foo)
assert not is_generator(bar)

0 comments on commit 3a59acf

Please sign in to comment.