Skip to content

Commit 63dc71c

Browse files
committed
Fix regression when using importorskip at module level
Fix pytest-dev#1822
1 parent 3a200b7 commit 63dc71c

File tree

4 files changed

+33
-7
lines changed

4 files changed

+33
-7
lines changed

CHANGELOG.rst

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
3.0.1.dev
22
=========
33

4-
*
4+
* Fix regression when ``importorskip`` is used at module level (`#1822`_).
5+
Thanks `@jaraco`_ and `@The-Compiler`_ for the report and `@nicoddemus`_ for the PR.
56

67
*
78

@@ -11,6 +12,9 @@
1112

1213

1314

15+
.. _#1822: https://github.com/pytest-dev/pytest/issues/1822
16+
17+
1418
3.0.0
1519
=====
1620

_pytest/python.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,9 @@ def _importtestmodule(self):
431431
"Make sure your test modules/packages have valid Python names."
432432
% (self.fspath, exc or exc_class)
433433
)
434-
except _pytest.runner.Skipped:
434+
except _pytest.runner.Skipped as e:
435+
if e.allow_module_level:
436+
raise
435437
raise self.CollectError(
436438
"Using @pytest.skip outside a test (e.g. as a test function "
437439
"decorator) is not allowed. Use @pytest.mark.skip or "

_pytest/runner.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -492,10 +492,16 @@ class Skipped(OutcomeException):
492492
# in order to have Skipped exception printing shorter/nicer
493493
__module__ = 'builtins'
494494

495+
def __init__(self, msg=None, pytrace=True, allow_module_level=False):
496+
OutcomeException.__init__(self, msg=msg, pytrace=pytrace)
497+
self.allow_module_level = allow_module_level
498+
499+
495500
class Failed(OutcomeException):
496501
""" raised from an explicit call to pytest.fail() """
497502
__module__ = 'builtins'
498503

504+
499505
class Exit(KeyboardInterrupt):
500506
""" raised for immediate program exits (no tracebacks/summaries)"""
501507
def __init__(self, msg="unknown reason"):
@@ -546,7 +552,7 @@ def importorskip(modname, minversion=None):
546552
# Do not raise chained exception here(#1485)
547553
should_skip = True
548554
if should_skip:
549-
skip("could not import %r" %(modname,))
555+
raise Skipped("could not import %r" %(modname,), allow_module_level=True)
550556
mod = sys.modules[modname]
551557
if minversion is None:
552558
return mod
@@ -555,10 +561,11 @@ def importorskip(modname, minversion=None):
555561
try:
556562
from pkg_resources import parse_version as pv
557563
except ImportError:
558-
skip("we have a required version for %r but can not import "
559-
"no pkg_resources to parse version strings." %(modname,))
564+
raise Skipped("we have a required version for %r but can not import "
565+
"no pkg_resources to parse version strings." % (modname,),
566+
allow_module_level=True)
560567
if verattr is None or pv(verattr) < pv(minversion):
561-
skip("module %r has __version__ %r, required is: %r" %(
562-
modname, verattr, minversion))
568+
raise Skipped("module %r has __version__ %r, required is: %r" %(
569+
modname, verattr, minversion), allow_module_level=True)
563570
return mod
564571

testing/test_runner.py

+13
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,19 @@ def test_importorskip_dev_module(monkeypatch):
571571
pytest.fail("spurious skip")
572572

573573

574+
def test_importorskip_module_level(testdir):
575+
"""importorskip must be able to skip entire modules when used at module level"""
576+
testdir.makepyfile('''
577+
import pytest
578+
foobarbaz = pytest.importorskip("foobarbaz")
579+
580+
def test_foo():
581+
pass
582+
''')
583+
result = testdir.runpytest()
584+
result.stdout.fnmatch_lines(['*collected 0 items / 1 skipped*'])
585+
586+
574587
def test_pytest_cmdline_main(testdir):
575588
p = testdir.makepyfile("""
576589
import pytest

0 commit comments

Comments
 (0)