4 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/f68e78b14a3e/ Changeset: f68e78b14a3e User: schlamar Date: 2014-03-14 14:04:54 Summary: Fixed race condition with SkipTest when module not in sys.modules on collection. Affected #: 4 files
diff -r 023c92172a302236917be115087636faf72a03b5 -r f68e78b14a3e1be86d65262a74a8868532e45e0c _pytest/main.py --- a/_pytest/main.py +++ b/_pytest/main.py @@ -408,10 +408,6 @@ and thus iteratively build a tree. """ - # the set of exceptions to interpret as "Skip the whole module" during - # collection - skip_exceptions = (Skipped,) - class CollectError(Exception): """ an error during collection, contains a custom message. """ diff -r 023c92172a302236917be115087636faf72a03b5 -r f68e78b14a3e1be86d65262a74a8868532e45e0c _pytest/nose.py --- a/_pytest/nose.py +++ b/_pytest/nose.py @@ -1,17 +1,32 @@ """ run test suites written for nose. """ -import pytest, py import sys + +import py +import pytest from _pytest import unittest + +def get_skip_exceptions(): + skip_classes = set() + for module_name in ('unittest', 'unittest2', 'nose'): + mod = sys.modules.get(module_name) + if hasattr(mod, 'SkipTest'): + skip_classes.add(mod.SkipTest) + return tuple(skip_classes) + + def pytest_runtest_makereport(__multicall__, item, call): - SkipTest = getattr(sys.modules.get('nose', None), 'SkipTest', None) - if SkipTest: - if call.excinfo and call.excinfo.errisinstance(SkipTest): + if not call.excinfo: + return + + for skip_exc in get_skip_exceptions(): + if call.excinfo.errisinstance(skip_exc): # let's substitute the excinfo with a pytest.skip one call2 = call.__class__(lambda: pytest.skip(str(call.excinfo.value)), call.when) call.excinfo = call2.excinfo + return @pytest.mark.trylast @@ -38,13 +53,8 @@ # #call_optional(item._nosegensetup, 'teardown') # del item.parent._nosegensetup + def pytest_make_collect_report(collector): - SkipTest = getattr(sys.modules.get('unittest', None), 'SkipTest', None) - if SkipTest is not None: - collector.skip_exceptions += (SkipTest,) - SkipTest = getattr(sys.modules.get('nose', None), 'SkipTest', None) - if SkipTest is not None: - collector.skip_exceptions += (SkipTest,) if isinstance(collector, pytest.Generator): call_optional(collector.obj, 'setup') diff -r 023c92172a302236917be115087636faf72a03b5 -r f68e78b14a3e1be86d65262a74a8868532e45e0c _pytest/runner.py --- a/_pytest/runner.py +++ b/_pytest/runner.py @@ -267,7 +267,9 @@ if not call.excinfo: outcome = "passed" else: - if call.excinfo.errisinstance(collector.skip_exceptions): + from _pytest import nose + skip_exceptions = (Skipped,) + nose.get_skip_exceptions() + if call.excinfo.errisinstance(skip_exceptions): outcome = "skipped" r = collector._repr_failure_py(call.excinfo, "line").reprcrash longrepr = (str(r.path), r.lineno, r.message) diff -r 023c92172a302236917be115087636faf72a03b5 -r f68e78b14a3e1be86d65262a74a8868532e45e0c testing/test_nose.py --- a/testing/test_nose.py +++ b/testing/test_nose.py @@ -330,12 +330,26 @@ reprec = testdir.inline_run() reprec.assertoutcome(passed=1, skipped=1) + def test_SkipTest_during_collection(testdir): - testdir.makepyfile(""" + p = testdir.makepyfile(""" import nose raise nose.SkipTest("during collection") def test_failing(): assert False """) + result = testdir.runpytest(p) + outcome = result.parseoutcomes() + outcome.pop('seconds') + assert outcome == dict(skipped=1) + + +def test_SkipTest_in_test(testdir): + testdir.makepyfile(""" + import nose + + def test_skipping(): + raise nose.SkipTest("in test") + """) reprec = testdir.inline_run() reprec.assertoutcome(skipped=1) https://bitbucket.org/hpk42/pytest/commits/28862c400f1a/ Changeset: 28862c400f1a User: schlamar Date: 2014-03-14 14:25:36 Summary: Fixed pyflakes errors. Affected #: 2 files diff -r f68e78b14a3e1be86d65262a74a8868532e45e0c -r 28862c400f1a82ff9a2a565b772853a6f4cbd5fb _pytest/main.py --- a/_pytest/main.py +++ b/_pytest/main.py @@ -8,7 +8,7 @@ except ImportError: from UserDict import DictMixin as MappingMixin -from _pytest.runner import collect_one_node, Skipped +from _pytest.runner import collect_one_node tracebackcutdir = py.path.local(_pytest.__file__).dirpath() diff -r f68e78b14a3e1be86d65262a74a8868532e45e0c -r 28862c400f1a82ff9a2a565b772853a6f4cbd5fb testing/python/collect.py --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -277,7 +277,7 @@ assert hasattr(modcol.obj, 'test_func') def test_function_as_object_instance_ignored(self, testdir): - item = testdir.makepyfile(""" + testdir.makepyfile(""" class A: def __call__(self, tmpdir): 0/0 https://bitbucket.org/hpk42/pytest/commits/ac3dba0858b9/ Changeset: ac3dba0858b9 User: schlamar Date: 2014-03-14 15:29:42 Summary: Removed unnecessary iteration in nose.pytest_runtest_makereport. Affected #: 1 file diff -r 28862c400f1a82ff9a2a565b772853a6f4cbd5fb -r ac3dba0858b9c36873c363feb12a5bfa8b58ec1f _pytest/nose.py --- a/_pytest/nose.py +++ b/_pytest/nose.py @@ -17,16 +17,11 @@ def pytest_runtest_makereport(__multicall__, item, call): - if not call.excinfo: - return - - for skip_exc in get_skip_exceptions(): - if call.excinfo.errisinstance(skip_exc): - # let's substitute the excinfo with a pytest.skip one - call2 = call.__class__(lambda: - pytest.skip(str(call.excinfo.value)), call.when) - call.excinfo = call2.excinfo - return + if call.excinfo and call.excinfo.errisinstance(get_skip_exceptions()): + # let's substitute the excinfo with a pytest.skip one + call2 = call.__class__(lambda: + pytest.skip(str(call.excinfo.value)), call.when) + call.excinfo = call2.excinfo @pytest.mark.trylast https://bitbucket.org/hpk42/pytest/commits/78d209d1deef/ Changeset: 78d209d1deef User: hpk42 Date: 2014-03-14 15:39:01 Summary: Merged in schlamar/pytest (pull request #129) Fixed race condition with SkipTest when module not in sys.modules on collection. Affected #: 5 files diff -r 9cf35e3fc17a98820f0c0fd247573d9f3d064f0f -r 78d209d1deef275a3ffbbb68004d6b377840ace1 _pytest/main.py --- a/_pytest/main.py +++ b/_pytest/main.py @@ -8,7 +8,7 @@ except ImportError: from UserDict import DictMixin as MappingMixin -from _pytest.runner import collect_one_node, Skipped +from _pytest.runner import collect_one_node tracebackcutdir = py.path.local(_pytest.__file__).dirpath() @@ -408,10 +408,6 @@ and thus iteratively build a tree. """ - # the set of exceptions to interpret as "Skip the whole module" during - # collection - skip_exceptions = (Skipped,) - class CollectError(Exception): """ an error during collection, contains a custom message. """ diff -r 9cf35e3fc17a98820f0c0fd247573d9f3d064f0f -r 78d209d1deef275a3ffbbb68004d6b377840ace1 _pytest/nose.py --- a/_pytest/nose.py +++ b/_pytest/nose.py @@ -1,17 +1,27 @@ """ run test suites written for nose. """ -import pytest, py import sys + +import py +import pytest from _pytest import unittest + +def get_skip_exceptions(): + skip_classes = set() + for module_name in ('unittest', 'unittest2', 'nose'): + mod = sys.modules.get(module_name) + if hasattr(mod, 'SkipTest'): + skip_classes.add(mod.SkipTest) + return tuple(skip_classes) + + def pytest_runtest_makereport(__multicall__, item, call): - SkipTest = getattr(sys.modules.get('nose', None), 'SkipTest', None) - if SkipTest: - if call.excinfo and call.excinfo.errisinstance(SkipTest): - # let's substitute the excinfo with a pytest.skip one - call2 = call.__class__(lambda: - pytest.skip(str(call.excinfo.value)), call.when) - call.excinfo = call2.excinfo + if call.excinfo and call.excinfo.errisinstance(get_skip_exceptions()): + # let's substitute the excinfo with a pytest.skip one + call2 = call.__class__(lambda: + pytest.skip(str(call.excinfo.value)), call.when) + call.excinfo = call2.excinfo @pytest.mark.trylast @@ -38,13 +48,8 @@ # #call_optional(item._nosegensetup, 'teardown') # del item.parent._nosegensetup + def pytest_make_collect_report(collector): - SkipTest = getattr(sys.modules.get('unittest', None), 'SkipTest', None) - if SkipTest is not None: - collector.skip_exceptions += (SkipTest,) - SkipTest = getattr(sys.modules.get('nose', None), 'SkipTest', None) - if SkipTest is not None: - collector.skip_exceptions += (SkipTest,) if isinstance(collector, pytest.Generator): call_optional(collector.obj, 'setup') diff -r 9cf35e3fc17a98820f0c0fd247573d9f3d064f0f -r 78d209d1deef275a3ffbbb68004d6b377840ace1 _pytest/runner.py --- a/_pytest/runner.py +++ b/_pytest/runner.py @@ -267,7 +267,9 @@ if not call.excinfo: outcome = "passed" else: - if call.excinfo.errisinstance(collector.skip_exceptions): + from _pytest import nose + skip_exceptions = (Skipped,) + nose.get_skip_exceptions() + if call.excinfo.errisinstance(skip_exceptions): outcome = "skipped" r = collector._repr_failure_py(call.excinfo, "line").reprcrash longrepr = (str(r.path), r.lineno, r.message) diff -r 9cf35e3fc17a98820f0c0fd247573d9f3d064f0f -r 78d209d1deef275a3ffbbb68004d6b377840ace1 testing/python/collect.py --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -277,7 +277,7 @@ assert hasattr(modcol.obj, 'test_func') def test_function_as_object_instance_ignored(self, testdir): - item = testdir.makepyfile(""" + testdir.makepyfile(""" class A: def __call__(self, tmpdir): 0/0 diff -r 9cf35e3fc17a98820f0c0fd247573d9f3d064f0f -r 78d209d1deef275a3ffbbb68004d6b377840ace1 testing/test_nose.py --- a/testing/test_nose.py +++ b/testing/test_nose.py @@ -330,12 +330,26 @@ reprec = testdir.inline_run() reprec.assertoutcome(passed=1, skipped=1) + def test_SkipTest_during_collection(testdir): - testdir.makepyfile(""" + p = testdir.makepyfile(""" import nose raise nose.SkipTest("during collection") def test_failing(): assert False """) + result = testdir.runpytest(p) + outcome = result.parseoutcomes() + outcome.pop('seconds') + assert outcome == dict(skipped=1) + + +def test_SkipTest_in_test(testdir): + testdir.makepyfile(""" + import nose + + def test_skipping(): + raise nose.SkipTest("in test") + """) reprec = testdir.inline_run() reprec.assertoutcome(skipped=1) Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. _______________________________________________ pytest-commit mailing list pytest-commit@python.org https://mail.python.org/mailman/listinfo/pytest-commit