diff --git a/CHANGELOG b/CHANGELOG index 16ebfcf56..0d80a1229 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,10 +1,12 @@ Changes between 2.3.2 and 2.3.3.dev ----------------------------------- -- fix issue 214: gracefully handle proxy objects that - look like fixtures but raise exceptions on introspection +- fix issue214 - parse modules that contain special objects like e. g. + flask's request object which blows up on getattr access if no request + is active. - fix issue213 - allow to parametrize with values like numpy arrays that - do not support an __eq__ operator + do not support an __eq__ operator + Changes between 2.3.1 and 2.3.2 ----------------------------------- diff --git a/_pytest/__init__.py b/_pytest/__init__.py index ac0ad449a..bdac841d7 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '2.3.2' +__version__ = '2.3.3.dev1' diff --git a/_pytest/python.py b/_pytest/python.py index dcf2cccb0..45a914553 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1552,12 +1552,12 @@ class FixtureManager: # fixture functions have a pytest_funcarg__ prefix (pre-2.3 style) # or are "@pytest.fixture" marked try: - marker = getattr(obj, "_pytestfixturefunction", None) - except RuntimeError: - # some proxy objects raise RuntimeError - # flasks request globals are one example - # those aren't fixture functions, so we can ignore - # XXX: maybe trace it when it happens? + marker = obj._pytestfixturefunction + except KeyboardInterrupt: + raise + except Exception: + # some objects raise errors like request (from flask import request) + # we don't expect them to be fixture functions marker = None if marker is None: diff --git a/doc/en/example/nonpython/conftest.py b/doc/en/example/nonpython/conftest.py index dad316b75..f55089e53 100644 --- a/doc/en/example/nonpython/conftest.py +++ b/doc/en/example/nonpython/conftest.py @@ -2,10 +2,10 @@ import pytest -def pytest_collect_file(path, parent): +def pytest_collect_file(parent, path): if path.ext == ".yml" and path.basename.startswith("test"): return YamlFile(path, parent) - + class YamlFile(pytest.File): def collect(self): import yaml # we need a yaml parser, e.g. PyYAML @@ -17,7 +17,7 @@ class YamlItem(pytest.Item): def __init__(self, name, parent, spec): super(YamlItem, self).__init__(name, parent) self.spec = spec - + def runtest(self): for name, value in self.spec.items(): # some custom test execution (dumb example follows) diff --git a/setup.py b/setup.py index 843d67ece..1008aa0ae 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ def main(): name='pytest', description='py.test: simple powerful testing with Python', long_description = long_description, - version='2.3.2', + version='2.3.3.dev1', url='http://pytest.org', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], diff --git a/testing/test_python.py b/testing/test_python.py index 3a09570f8..92c77eaea 100644 --- a/testing/test_python.py +++ b/testing/test_python.py @@ -1612,33 +1612,6 @@ def test_funcarg_lookup_error(testdir): assert "INTERNAL" not in result.stdout.str() -def test_funcarg_fixture_discovery_failure_issue214(testdir): - # some proxy objects raise RuntimeError on getattr - # for example flask.request - p = testdir.makepyfile(""" - - class EvilObject(object): - def __call__(self): - #needed to trick discovery - pass - def __getattr__(self, arg): - raise RuntimeError('uhm ' + arg) - - - fixture = EvilObject() - - def test_1(): - pass - """) - result = testdir.runpytest('--fulltrace') - result.stdout.fnmatch_lines([ - '*1 passed*' - ]) - assert "INTERNAL" not in result.stdout.str() - assert "ERROR" not in result.stdout.str() - - - class TestReportInfo: def test_itemreport_reportinfo(self, testdir, linecomp): testdir.makeconftest(""" @@ -2145,6 +2118,20 @@ class TestFixtureManager: """) return testdir + def test_parsefactories_evil_objects_issue214(self, testdir): + testdir.makepyfile(""" + class A: + def __call__(self): + pass + def __getattr__(self, name): + raise RuntimeError() + a = A() + def test_hello(): + pass + """) + reprec = testdir.inline_run() + reprec.assertoutcome(passed=1, failed=0) + def test_parsefactories_conftest(self, testdir): testdir.makepyfile(""" def test_hello(item, fm):