[py-svn] py-trunk commit be400218cdcc: - make importorskip static at py.test.importorskip because it's
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Thu Oct 15 21:01:27 CEST 2009
# HG changeset patch -- Bitbucket.org
# Project py-trunk
# URL http://bitbucket.org/hpk42/py-trunk/overview/
# User holger krekel <holger at merlinux.eu>
# Date 1255630206 -7200
# Node ID be400218cdccbab6c8dd57fc5dade0c2e77a56e1
# Parent 94601d28b6dd85f3afe5bde05d7850c6ae1ce34a
- make importorskip static at py.test.importorskip because it's
used for conditional plugin loading
- fix case where xfail is defined at module/class level
- fixes and improvements to docs, correct links to plugins
- use new skip facilities here and there
--- a/testing/pytest/plugin/test_pytest_runner.py
+++ b/testing/pytest/plugin/test_pytest_runner.py
@@ -218,9 +218,8 @@ class TestExecutionNonForked(BaseFunctio
py.test.fail("did not raise")
class TestExecutionForked(BaseFunctionalTests):
+ skipif = "not hasattr(os, 'fork')"
def getrunner(self):
- if not hasattr(py.std.os, 'fork'):
- py.test.skip("no os.fork available")
return runner.forked_run_report
def test_suicide(self, testdir):
@@ -262,10 +261,8 @@ class TestCollectionReports:
assert not rep.passed
assert rep.skipped
-
+ at py.test.mark.skipif("not hasattr(os, 'fork')")
def test_functional_boxed(testdir):
- if not hasattr(py.std.os, 'fork'):
- py.test.skip("needs os.fork")
p1 = testdir.makepyfile("""
import os
def test_function():
--- a/doc/test/plugin/links.txt
+++ b/doc/test/plugin/links.txt
@@ -1,38 +1,38 @@
.. _`helpconfig`: helpconfig.html
.. _`terminal`: terminal.html
-.. _`pytest_recwarn.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_recwarn.py
+.. _`pytest_recwarn.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_recwarn.py
.. _`unittest`: unittest.html
-.. _`pytest_monkeypatch.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_monkeypatch.py
-.. _`pytest_keyword.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_keyword.py
+.. _`pytest_monkeypatch.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_monkeypatch.py
+.. _`pytest_keyword.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_keyword.py
.. _`pastebin`: pastebin.html
.. _`skipping`: skipping.html
.. _`plugins`: index.html
-.. _`pytest_doctest.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_doctest.py
+.. _`pytest_doctest.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_doctest.py
.. _`capture`: capture.html
-.. _`pytest_nose.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_nose.py
-.. _`pytest_restdoc.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_restdoc.py
+.. _`pytest_nose.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_nose.py
+.. _`pytest_restdoc.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_restdoc.py
.. _`restdoc`: restdoc.html
-.. _`pytest_pastebin.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_pastebin.py
-.. _`pytest_figleaf.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_figleaf.py
-.. _`pytest_hooklog.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_hooklog.py
-.. _`pytest_skipping.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_skipping.py
+.. _`pytest_pastebin.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_pastebin.py
+.. _`pytest_figleaf.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_figleaf.py
+.. _`pytest_hooklog.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_hooklog.py
+.. _`pytest_skipping.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_skipping.py
.. _`checkout the py.test development version`: ../../download.html#checkout
-.. _`pytest_helpconfig.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_helpconfig.py
+.. _`pytest_helpconfig.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_helpconfig.py
.. _`oejskit`: oejskit.html
.. _`doctest`: doctest.html
.. _`get in contact`: ../../contact.html
-.. _`pytest_capture.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_capture.py
+.. _`pytest_capture.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_capture.py
.. _`figleaf`: figleaf.html
.. _`customize`: ../customize.html
.. _`hooklog`: hooklog.html
-.. _`pytest_terminal.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_terminal.py
+.. _`pytest_terminal.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_terminal.py
.. _`recwarn`: recwarn.html
-.. _`pytest_pdb.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_pdb.py
+.. _`pytest_pdb.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_pdb.py
.. _`monkeypatch`: monkeypatch.html
.. _`resultlog`: resultlog.html
.. _`keyword`: keyword.html
.. _`django`: django.html
-.. _`pytest_unittest.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_unittest.py
+.. _`pytest_unittest.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_unittest.py
.. _`nose`: nose.html
-.. _`pytest_resultlog.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/py/test/plugin/pytest_resultlog.py
+.. _`pytest_resultlog.py`: http://bitbucket.org/hpk42/py-trunk/raw/trunk/_py/test/plugin/pytest_resultlog.py
.. _`pdb`: pdb.html
--- a/testing/code/test_assertion.py
+++ b/testing/code/test_assertion.py
@@ -135,11 +135,7 @@ def test_assert_with_brokenrepr_arg():
class TestView:
def setup_class(cls):
- try:
- from _py.code._assertionold import View
- except ImportError:
- py.test.skip("requires the compile package")
- cls.View = View
+ cls.View = py.test.importorskip("_py.code._assertionold").View
def test_class_dispatch(self):
### Use a custom class hierarchy with existing instances
--- a/_py/test/plugin/pytest_skipping.py
+++ b/_py/test/plugin/pytest_skipping.py
@@ -1,13 +1,12 @@
"""
-mark python test functions, classes or modules for conditional
-skipping (skipif) or as expected-to-fail (xfail). Both declarations
-lead to special reporting and both can be systematically associated
-with functions, whole classes or modules. The difference between
-the two is that 'xfail' will still execute test functions
-but it will revert the outcome. A passing test is now
-a failure and failing test is expected. All skip conditions
-are reported at the end of test run through the terminal
-reporter.
+advanced conditional skipping for python test functions, classes or modules.
+
+You can mark functions, classes or modules for for conditional
+skipping (skipif) or as expected-to-fail (xfail). The difference
+between the two is that 'xfail' will still execute test functions
+but it will invert the outcome: a passing test becomes a failure and
+a failing test is a semi-passing one. All skip conditions are
+reported at the end of test run through the terminal reporter.
.. _skipif:
@@ -20,15 +19,18 @@ Here is an example for skipping a test f
def test_function():
...
-Conditions are specified as python expressions
-and can access the ``sys`` module. They can also
-access the config object and thus depend on command
-line or conftest options::
+The 'skipif' marker accepts an **arbitrary python expression**
+as a condition. When setting up the test function the condition
+is evaluated by calling ``eval(expr, namespace)``. The namespace
+contains the ``sys`` and ``os`` modules as well as the
+test ``config`` object. The latter allows you to skip based
+on a test configuration value e.g. like this::
- @py.test.mark.skipif("config.getvalue('db') is None")
+ @py.test.mark.skipif("not config.getvalue('db')")
def test_function(...):
...
+
conditionally mark a function as "expected to fail"
-------------------------------------------------------
@@ -53,7 +55,7 @@ skip/xfail a whole test class or module
-------------------------------------------
Instead of marking single functions you can skip
-a whole class of tests when runnign on a specific
+a whole class of tests when running on a specific
platform::
class TestSomething:
@@ -75,13 +77,12 @@ You can use a helper to skip on a failin
You can use this helper at module level or within
a test or setup function.
-You can aslo skip if a library does not have the right version::
+You can also skip if a library does not come with a high enough version::
docutils = py.test.importorskip("docutils", minversion="0.3")
The version will be read from the specified module's ``__version__`` attribute.
-
dynamically skip from within a test or setup
-------------------------------------------------
@@ -96,16 +97,11 @@ If you want to skip the execution of a t
.. _`funcarg factory`: ../funcargs.html#factory
"""
-# XXX not all skip-related code is contained in
-# this plugin yet, some remains in outcome.py and
-# the Skipped Exception is imported here and there.
-
+# XXX py.test.skip, .importorskip and the Skipped class
+# should also be defined in this plugin, requires thought/changes
import py
-def pytest_namespace():
- return {'importorskip': importorskip}
-
def pytest_runtest_setup(item):
expr, result = evalexpression(item, 'skipif')
if result:
@@ -117,14 +113,15 @@ def pytest_runtest_makereport(__multical
if hasattr(item, 'obj'):
expr, result = evalexpression(item, 'xfail')
if result:
- res = __multicall__.execute()
+ rep = __multicall__.execute()
if call.excinfo:
- res.skipped = True
- res.failed = res.passed = False
+ rep.skipped = True
+ rep.failed = rep.passed = False
else:
- res.skipped = res.passed = False
- res.failed = True
- return res
+ rep.skipped = rep.passed = False
+ rep.failed = True
+ rep.keywords['xfail'] = True # expr
+ return rep
def pytest_report_teststatus(report):
if 'xfail' in report.keywords:
@@ -157,24 +154,6 @@ def pytest_terminal_summary(terminalrepo
pos = "%s %s:%d: unexpectedly passing" %(modpath, fspath, lineno)
tr._tw.line(pos)
-def importorskip(modname, minversion=None):
- """ return imported module or perform a dynamic skip() """
- compile(modname, '', 'eval') # to catch syntaxerrors
- try:
- mod = __import__(modname)
- except ImportError:
- py.test.skip("could not import %r" %(modname,))
- if minversion is None:
- return mod
- verattr = getattr(mod, '__version__', None)
- if isinstance(minversion, str):
- minver = minversion.split(".")
- else:
- minver = list(minversion)
- if verattr is None or verattr.split(".") < minver:
- py.test.skip("module %r has __version__ %r, required is: %r" %(
- modname, verattr, minversion))
- return mod
def getexpression(item, keyword):
if isinstance(item, py.test.collect.Function):
@@ -193,7 +172,7 @@ def evalexpression(item, keyword):
result = None
if expr:
if isinstance(expr, str):
- d = {'sys': py.std.sys, 'config': item.config}
+ d = {'os': py.std.os, 'sys': py.std.sys, 'config': item.config}
result = eval(expr, d)
else:
result = expr
--- a/doc/test/plugin/skipping.txt
+++ b/doc/test/plugin/skipping.txt
@@ -2,19 +2,17 @@
pytest_skipping plugin
======================
-mark python test functions, classes or modules for conditional
+advanced conditional skipping for python test functions, classes or modules.
.. contents::
:local:
-skipping (skipif) or as expected-to-fail (xfail). Both declarations
-lead to special reporting and both can be systematically associated
-with functions, whole classes or modules. The difference between
-the two is that 'xfail' will still execute test functions
-but it will revert the outcome. A passing test is now
-a failure and failing test is expected. All skip conditions
-are reported at the end of test run through the terminal
-reporter.
+You can mark functions, classes or modules for for conditional
+skipping (skipif) or as expected-to-fail (xfail). The difference
+between the two is that 'xfail' will still execute test functions
+but it will invert the outcome: a passing test becomes a failure and
+a failing test is a semi-passing one. All skip conditions are
+reported at the end of test run through the terminal reporter.
.. _skipif:
@@ -27,15 +25,18 @@ Here is an example for skipping a test f
def test_function():
...
-Conditions are specified as python expressions
-and can access the ``sys`` module. They can also
-access the config object and thus depend on command
-line or conftest options::
+The 'skipif' marker accepts an **arbitrary python expression**
+as a condition. When setting up the test function the condition
+is evaluated by calling ``eval(expr, namespace)``. The namespace
+contains the ``sys`` and ``os`` modules as well as the
+test ``config`` object. The latter allows you to skip based
+on a test configuration value e.g. like this::
- @py.test.mark.skipif("config.getvalue('db') is None")
+ @py.test.mark.skipif("not config.getvalue('db')")
def test_function(...):
...
+
conditionally mark a function as "expected to fail"
-------------------------------------------------------
@@ -60,7 +61,7 @@ skip/xfail a whole test class or module
-------------------------------------------
Instead of marking single functions you can skip
-a whole class of tests when runnign on a specific
+a whole class of tests when running on a specific
platform::
class TestSomething:
@@ -82,13 +83,12 @@ You can use a helper to skip on a failin
You can use this helper at module level or within
a test or setup function.
-You can aslo skip if a library does not have the right version::
+You can also skip if a library does not come with a high enough version::
docutils = py.test.importorskip("docutils", minversion="0.3")
The version will be read from the specified module's ``__version__`` attribute.
-
dynamically skip from within a test or setup
-------------------------------------------------
--- a/testing/process/test_killproc.py
+++ b/testing/process/test_killproc.py
@@ -13,5 +13,4 @@ def test_kill():
if sys.platform == "win32" and ret == 0:
py.test.skip("XXX on win32, subprocess.Popen().wait() on a killed "
"process does not yield return value != 0")
-
assert ret != 0
--- a/testing/io_/test_terminalwriter.py
+++ b/testing/io_/test_terminalwriter.py
@@ -2,13 +2,6 @@ import py
import os, sys
from _py.io import terminalwriter
-def skip_win32():
- if sys.platform == 'win32':
- py.test.skip('Not relevant on win32')
-
-import os
-import py
-
def test_terminal_width_COLUMNS(monkeypatch):
""" Dummy test for get_terminal_width
"""
@@ -82,14 +75,14 @@ class BaseTests:
assert len(l) == 1
assert l[0] == "-" * 26 + " hello " + "-" * 27 + "\n"
+ @py.test.mark.skipif("sys.platform == 'win32'")
def test__escaped(self):
- skip_win32()
tw = self.getwriter()
text2 = tw._escaped("hello", (31))
assert text2.find("hello") != -1
+ @py.test.mark.skipif("sys.platform == 'win32'")
def test_markup(self):
- skip_win32()
tw = self.getwriter()
for bold in (True, False):
for color in ("red", "green"):
@@ -104,9 +97,9 @@ class BaseTests:
tw.line("x", bold=True)
tw.write("x\n", red=True)
l = self.getlines()
- skip_win32()
- assert len(l[0]) > 2, l
- assert len(l[1]) > 2, l
+ if sys.platform != "win32":
+ assert len(l[0]) > 2, l
+ assert len(l[1]) > 2, l
def test_attr_fullwidth(self):
tw = self.getwriter()
--- a/py/__init__.py
+++ b/py/__init__.py
@@ -53,6 +53,7 @@ _py.apipkg.initpkg(__name__, dict(
'_PluginManager' : '_py.test.pluginmanager:PluginManager',
'raises' : '_py.test.outcome:raises',
'skip' : '_py.test.outcome:skip',
+ 'importorskip' : '_py.test.outcome:importorskip',
'fail' : '_py.test.outcome:fail',
'exit' : '_py.test.outcome:exit',
# configuration/initialization related test api
--- a/testing/pytest/plugin/test_pytest_skipping.py
+++ b/testing/pytest/plugin/test_pytest_skipping.py
@@ -21,6 +21,21 @@ def test_xfail_decorator(testdir):
])
assert result.ret == 1
+def test_xfail_at_module(testdir):
+ p = testdir.makepyfile("""
+ xfail = 'True'
+
+ def test_intentional_xfail():
+ assert 0
+ """)
+ result = testdir.runpytest(p)
+ extra = result.stdout.fnmatch_lines([
+ "*expected failures*",
+ "*test_intentional_xfail*:4*",
+ "*1 xfailed*"
+ ])
+ assert result.ret == 0
+
def test_skipif_decorator(testdir):
p = testdir.makepyfile("""
import py
@@ -84,26 +99,3 @@ def test_evalexpression_cls_config_examp
x, y = evalexpression(item, 'skipif')
assert x == 'config._hackxyz'
assert y == 3
-
-def test_importorskip():
- from _py.test.outcome import Skipped
- from _py.test.plugin.pytest_skipping import importorskip
- assert importorskip == py.test.importorskip
- try:
- sys = importorskip("sys")
- assert sys == py.std.sys
- #path = py.test.importorskip("os.path")
- #assert path == py.std.os.path
- py.test.raises(Skipped, "py.test.importorskip('alskdj')")
- py.test.raises(SyntaxError, "py.test.importorskip('x y z')")
- py.test.raises(SyntaxError, "py.test.importorskip('x=y')")
- path = importorskip("py", minversion=".".join(py.__version__))
- mod = py.std.types.ModuleType("hello123")
- mod.__version__ = "1.3"
- py.test.raises(Skipped, """
- py.test.importorskip("hello123", minversion="5.0")
- """)
- except Skipped:
- print(py.code.ExceptionInfo())
- py.test.fail("spurious skip")
-
--- a/testing/pytest/test_outcome.py
+++ b/testing/pytest/test_outcome.py
@@ -29,3 +29,30 @@ def test_exception_printing_skip():
excinfo = py.code.ExceptionInfo()
s = excinfo.exconly(tryshort=True)
assert s.startswith("Skipped")
+
+def test_importorskip():
+ from _py.test.outcome import Skipped, importorskip
+ assert importorskip == py.test.importorskip
+ try:
+ sys = importorskip("sys")
+ assert sys == py.std.sys
+ #path = py.test.importorskip("os.path")
+ #assert path == py.std.os.path
+ py.test.raises(Skipped, "py.test.importorskip('alskdj')")
+ py.test.raises(SyntaxError, "py.test.importorskip('x y z')")
+ py.test.raises(SyntaxError, "py.test.importorskip('x=y')")
+ path = importorskip("py", minversion=".".join(py.__version__))
+ mod = py.std.types.ModuleType("hello123")
+ mod.__version__ = "1.3"
+ py.test.raises(Skipped, """
+ py.test.importorskip("hello123", minversion="5.0")
+ """)
+ except Skipped:
+ print(py.code.ExceptionInfo())
+ py.test.fail("spurious skip")
+
+def test_importorskip_imports_last_module_part():
+ import os
+ ospath = py.test.importorskip("os.path")
+ assert os.path == ospath
+
--- a/_py/test/plugin/pytest_figleaf.py
+++ b/_py/test/plugin/pytest_figleaf.py
@@ -4,7 +4,8 @@ write and report coverage data with 'fig
"""
import py
-figleaf = py.test.importorskip("figleaf.annotate_html")
+py.test.importorskip("figleaf.annotate_html")
+import figleaf
def pytest_addoption(parser):
group = parser.addgroup('figleaf options')
--- a/doc/test/plugin/index.txt
+++ b/doc/test/plugin/index.txt
@@ -2,7 +2,7 @@
plugins for Python test functions
=================================
-skipping_ mark python test functions, classes or modules for conditional
+skipping_ advanced conditional skipping for python test functions, classes or modules.
figleaf_ write and report coverage data with 'figleaf'.
--- a/doc/test/features.txt
+++ b/doc/test/features.txt
@@ -123,14 +123,14 @@ command line. Using the `--pdb`` option
a PDB `Python debugger`_ when a test fails.
advanced skipping of tests
--------------------------------
+======================================
-py.test has builtin support for skipping tests or expecting
+py.test has `advanced support for skipping tests`_ or expecting
failures on tests on certain platforms. Apart from the
minimal py.test style also unittest- and nose-style tests
can make use of this feature.
-
+.. _`advanced support for skipping tests`: plugin/skipping.html
.. _`funcargs mechanism`: funcargs.html
.. _`unittest.py`: http://docs.python.org/library/unittest.html
.. _`doctest.py`: http://docs.python.org/library/doctest.html
--- a/testing/process/test_forkedfunc.py
+++ b/testing/process/test_forkedfunc.py
@@ -1,9 +1,6 @@
import py, sys, os
-def setup_module(mod):
- if not hasattr(os, 'fork'):
- py.test.skip("forkedfunc requires os.fork")
- mod.tmpdir = py.test.ensuretemp(mod.__file__)
+skipif = "not hasattr(os, 'fork')"
def test_waitfinish_removes_tempdir():
ff = py.process.ForkedFunc(boxf1)
@@ -56,7 +53,7 @@ def test_forkedfunc_on_fds():
def test_forkedfunc_signal():
result = py.process.ForkedFunc(boxseg).waitfinish()
assert result.retval is None
- if py.std.sys.version_info < (2,4):
+ if sys.version_info < (2,4):
py.test.skip("signal detection does not work with python prior 2.4")
assert result.signal == 11
--- a/bin-for-dist/makepluginlist.py
+++ b/bin-for-dist/makepluginlist.py
@@ -21,11 +21,13 @@ plugins = [
]
externals = {
- 'oejskit': 'run javascript tests in real life browsers',
- 'django': 'support for testing django applications',
+ 'oejskit': "run javascript tests in real life browsers",
+ 'django': "support for testing django applications",
+# 'coverage': "support for using Ned's coverage module",
+# 'xmlresult': "support for generating xml reports "
+# "and CruiseControl integration",
+}
-}
-
def warn(*args):
msg = " ".join(map(str, args))
print >>sys.stderr, "WARN:", msg
@@ -123,7 +125,7 @@ class RestWriter:
self.out.close()
print "wrote", self.target
del self.out
-
+
class PluginOverview(RestWriter):
def makerest(self, config):
plugindir = py.path.local(py.__file__).dirpath("test", "plugin")
@@ -145,7 +147,6 @@ class PluginOverview(RestWriter):
self.Print()
class HookSpec(RestWriter):
-
def makerest(self, config):
module = config.pluginmanager.hook._hookspecs
source = py.code.Source(module)
@@ -212,7 +213,7 @@ class PluginDoc(RestWriter):
# "py/test/plugin/%s" %(hg_changeset, basename)))
self.links.append((basename,
"http://bitbucket.org/hpk42/py-trunk/raw/%s/"
- "py/test/plugin/%s" %(pyversion, basename)))
+ "_py/test/plugin/%s" %(pyversion, basename)))
self.links.append(('customize', '../customize.html'))
self.links.append(('plugins', 'index.html'))
self.links.append(('get in contact', '../../contact.html'))
--- a/_py/test/outcome.py
+++ b/_py/test/outcome.py
@@ -94,6 +94,25 @@ def raises(ExpectedException, *args, **k
raise ExceptionFailure(msg="DID NOT RAISE",
expr=args, expected=ExpectedException)
+def importorskip(modname, minversion=None):
+ """ return imported module or perform a dynamic skip() """
+ compile(modname, '', 'eval') # to catch syntaxerrors
+ try:
+ mod = __import__(modname, None, None, ['__doc__'])
+ except ImportError:
+ py.test.skip("could not import %r" %(modname,))
+ if minversion is None:
+ return mod
+ verattr = getattr(mod, '__version__', None)
+ if isinstance(minversion, str):
+ minver = minversion.split(".")
+ else:
+ minver = list(minversion)
+ if verattr is None or verattr.split(".") < minver:
+ py.test.skip("module %r has __version__ %r, required is: %r" %(
+ modname, verattr, minversion))
+ return mod
+
# exitcodes for the command line
EXIT_OK = 0
--- a/testing/code/test_source.py
+++ b/testing/code/test_source.py
@@ -191,9 +191,8 @@ class TestSourceParsingAndCompiling:
assert len(source) == 9
assert source.getstatementrange(5) == (0, 9)
+ @py.test.mark.skipif("sys.version_info < (2,6)")
def test_compile_to_ast(self):
- if sys.version_info < (2, 6):
- py.test.skip("requires Python 2.6")
import ast
source = Source("x = 4")
mod = source.compile(flag=ast.PyCF_ONLY_AST)
@@ -257,7 +256,6 @@ def test_getstartingblock_multiline():
assert len(l) == 4
def test_getline_finally():
- #py.test.skip("inner statements cannot be located yet.")
def c(): pass
excinfo = py.test.raises(TypeError, """
teardown = None
More information about the pytest-commit
mailing list