From commits-noreply at bitbucket.org Thu Jun 3 15:47:09 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 3 Jun 2010 13:47:09 +0000 (UTC) Subject: [py-svn] py-trunk commit d1dd6aace54c: use tempdir.mkdtmp instead of mktmp + repeated tries for making tmpdirs Message-ID: <20100603134709.5142A7EF68@bitbucket.org> 404 - Not Found — bitbucket.org

404 - Not Found

We're sorry, but we couldn't find the page you were looking for.

You can perhaps find what you're looking for by doing a search in the list of public repositories.

If you feel that this is an error on our part, please send us an email with details about the error and what you were doing when it occurred.

-- The Bitbucket team

From commits-noreply at bitbucket.org Thu Jun 3 15:47:09 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 3 Jun 2010 13:47:09 +0000 (UTC) Subject: [py-svn] py-trunk commit 74f4fe2cbb02: add a CHANGELOG entry for ronny's changes Message-ID: <20100603134709.6EE517EF6F@bitbucket.org> 404 - Not Found — bitbucket.org

404 - Not Found

We're sorry, but we couldn't find the page you were looking for.

You can perhaps find what you're looking for by doing a search in the list of public repositories.

If you feel that this is an error on our part, please send us an email with details about the error and what you were doing when it occurred.

-- The Bitbucket team

From commits-noreply at bitbucket.org Thu Jun 3 15:47:09 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 3 Jun 2010 13:47:09 +0000 (UTC) Subject: [py-svn] py-trunk commit 4e195647cb21: add kwarg support to py.errpr.checked_call Message-ID: <20100603134709.491957EF49@bitbucket.org> 404 - Not Found — bitbucket.org

404 - Not Found

We're sorry, but we couldn't find the page you were looking for.

You can perhaps find what you're looking for by doing a search in the list of public repositories.

If you feel that this is an error on our part, please send us an email with details about the error and what you were doing when it occurred.

-- The Bitbucket team

From commits-noreply at bitbucket.org Thu Jun 3 15:47:09 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 3 Jun 2010 13:47:09 +0000 (UTC) Subject: [py-svn] py-trunk commit c15ececc1d8f: add a rootdir param to py.path.local.mkdtemp Message-ID: <20100603134709.61A787EF6E@bitbucket.org> 404 - Not Found — bitbucket.org

404 - Not Found

We're sorry, but we couldn't find the page you were looking for.

You can perhaps find what you're looking for by doing a search in the list of public repositories.

If you feel that this is an error on our part, please send us an email with details about the error and what you were doing when it occurred.

-- The Bitbucket team

From commits-noreply at bitbucket.org Sat Jun 5 16:06:30 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 5 Jun 2010 14:06:30 +0000 (UTC) Subject: [py-svn] py-trunk commit 50cff50a3d7a: adding a tox file and a note in changelog Message-ID: <20100605140630.5DE197EF74@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1275746351 -7200 # Node ID 50cff50a3d7a09d1df19da1e69f3dfc485a87df8 # Parent 59664dde5c237442f5464e8830ad63b2b3fde5a0 adding a tox file and a note in changelog --- a/.hgignore +++ b/.hgignore @@ -19,4 +19,6 @@ build/ dist/ py.egg-info issue/ +env/ 3rdparty/ +.tox --- /dev/null +++ b/tox.ini @@ -0,0 +1,29 @@ +[project] +distpaths= + py + setup.py + distribute_setup.py + README.txt + MANIFEST.in + LICENSE + doc + testing + conftest.py + +testpaths= + testing + conftest.py + +[test] +command=py.test --confcutdir=. --junitxml=junit-%(envname)s.xml testing/ +[testenv:py24] +python=python2.4 +[testenv:py25] +python=python2.5 +[testenv:py26] +python=python2.6 +[testenv:jython] +python=jython +command=py.test-jython --confcutdir=. --junitxml=junit-%(envname)s.xml testing/ +[testenv:py31] +python=python3.1 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ Bug fixes / Maintenance - fix issue57 -f|--looponfail to work with xpassing tests - fix pyimport() to work with directories - streamline py.path.local.mkdtemp implementation and usage +- don't print empty lines when showing junitxml-filename Changes between 1.3.0 and 1.3.1 ================================================== From commits-noreply at bitbucket.org Sat Jun 5 16:06:30 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 5 Jun 2010 14:06:30 +0000 (UTC) Subject: [py-svn] py-trunk commit 61ae0b502b07: fix python3 failure by making a relative import work Message-ID: <20100605140630.729DF7EF75@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1275747017 -7200 # Node ID 61ae0b502b07f25b441ea1fcdc39a64794daa15e # Parent 50cff50a3d7a09d1df19da1e69f3dfc485a87df8 fix python3 failure by making a relative import work --- a/testing/path/__init__.py +++ /dev/null @@ -1,1 +0,0 @@ -# From commits-noreply at bitbucket.org Sat Jun 5 16:06:30 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 5 Jun 2010 14:06:30 +0000 (UTC) Subject: [py-svn] py-trunk commit 3d1972d3dc86: don't print empty lines with junitxml file printing Message-ID: <20100605140630.244A77EF49@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1275604758 -7200 # Node ID 3d1972d3dc8691a2bc03de96e501678a321c0665 # Parent 74f4fe2cbb024dad5b172e7087250bc6fa17182e don't print empty lines with junitxml file printing --- a/py/_plugin/pytest_junitxml.py +++ b/py/_plugin/pytest_junitxml.py @@ -166,6 +166,7 @@ class LogXML(object): logfile.writelines(self.test_logs) logfile.write('') logfile.close() - tw = session.config.pluginmanager.getplugin("terminalreporter")._tw - tw.line() - tw.sep("-", "generated xml file: %s" %(self.logfile)) + + def pytest_terminal_summary(self, terminalreporter): + tw = terminalreporter._tw + terminalreporter.write_sep("-", "generated xml file: %s" %(self.logfile)) From commits-noreply at bitbucket.org Sat Jun 5 16:06:30 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 5 Jun 2010 14:06:30 +0000 (UTC) Subject: [py-svn] py-trunk commit 59664dde5c23: don't depend on (and don't actually use anymore) testing/__init__.py Message-ID: <20100605140630.4561F7EF73@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1275604798 -7200 # Node ID 59664dde5c237442f5464e8830ad63b2b3fde5a0 # Parent 3d1972d3dc8691a2bc03de96e501678a321c0665 don't depend on (and don't actually use anymore) testing/__init__.py --- a/testing/path/test_svnauth.py +++ b/testing/path/test_svnauth.py @@ -1,5 +1,5 @@ import py -from testing.path import svntestbase +import svntestbase from py.path import SvnAuth import time import sys --- a/testing/path/test_svnurl.py +++ b/testing/path/test_svnurl.py @@ -2,7 +2,7 @@ import py from py._path.svnurl import InfoSvnCommand import datetime import time -from testing.path.svntestbase import CommonSvnTests +from svntestbase import CommonSvnTests def pytest_funcarg__path1(request): repo, repourl, wc = request.getfuncargvalue("repowc1") --- a/testing/path/test_local.py +++ b/testing/path/test_local.py @@ -1,7 +1,7 @@ import py import sys from py.path import local -from testing.path import common +import common failsonjython = py.test.mark.xfail("sys.platform.startswith('java')") failsonjywin32 = py.test.mark.xfail("sys.platform.startswith('java') " --- a/testing/path/test_svnwc.py +++ b/testing/path/test_svnwc.py @@ -2,7 +2,7 @@ import py import os, sys from py._path.svnwc import InfoSvnWCCommand, XMLWCStatus, parse_wcinfotime from py._path import svnwc as svncommon -from testing.path.svntestbase import CommonSvnTests +from svntestbase import CommonSvnTests def test_make_repo(path1, tmpdir): repo = tmpdir.join("repo") --- a/testing/__init__.py +++ /dev/null @@ -1,1 +0,0 @@ -# --- a/testing/path/svntestbase.py +++ b/testing/path/svntestbase.py @@ -1,7 +1,7 @@ import sys import py from py._path import svnwc as svncommon -from testing.path.common import CommonFSTests +from common import CommonFSTests class CommonSvnTests(CommonFSTests): From commits-noreply at bitbucket.org Sun Jun 6 19:03:40 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 6 Jun 2010 17:03:40 +0000 (UTC) Subject: [py-svn] py-trunk commit eb9c9a4ba265: fix py.code.compile to generate unique filenames Message-ID: <20100606170340.79F717EFB6@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1275844102 -7200 # Node ID eb9c9a4ba265a25ef7ca9c0fc3a4a7da470b07e5 # Parent 61ae0b502b07f25b441ea1fcdc39a64794daa15e fix py.code.compile to generate unique filenames --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -151,6 +151,22 @@ class TestSourceParsingAndCompiling: source = py.code.Source(co) assert str(source) == "x=3" + def test_compile_and_getsource_through_same_function(self): + def gensource(source): + return py.code.compile(source) + co1 = gensource(""" + def f(): + raise KeyError() + """) + co2 = gensource(""" + def f(): + raise ValueError() + """) + source1 = py.std.inspect.getsource(co1) + assert 'KeyError' in source1 + source2 = py.std.inspect.getsource(co2) + assert 'ValueError' in source2 + def test_getstatement(self): #print str(self.source) ass = str(self.source[1:]) @@ -229,11 +245,11 @@ class TestSourceParsingAndCompiling: def check(comp, name): co = comp(self.source, name) if not name: - expected = "" %(mypath, mylineno+2+1) + expected = "codegen %s:%d>" %(mypath, mylineno+2+1) else: - expected = "" % (name, mypath, mylineno+2+1) + expected = "codegen %r %s:%d>" % (name, mypath, mylineno+2+1) fn = co.co_filename - assert fn == expected + assert fn.endswith(expected) mycode = py.code.Code(self.test_compilefuncs_and_path_sanity) mylineno = mycode.firstlineno --- a/py/_code/source.py +++ b/py/_code/source.py @@ -17,6 +17,7 @@ class Source(object): """ a immutable object holding a source code fragment, possibly deindenting it. """ + _compilecounter = 0 def __init__(self, *parts, **kwargs): self.lines = lines = [] de = kwargs.get('deindent', True) @@ -195,10 +196,12 @@ class Source(object): if _genframe is None: _genframe = sys._getframe(1) # the caller fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno + base = "<%d-codegen " % self._compilecounter + self.__class__._compilecounter += 1 if not filename: - filename = '' % (fn, lineno) + filename = base + '%s:%d>' % (fn, lineno) else: - filename = '' % (filename, fn, lineno) + filename = base + '%r %s:%d>' % (filename, fn, lineno) source = "\n".join(self.lines) + '\n' try: co = cpy_compile(source, filename, mode, flag) --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,7 @@ Bug fixes / Maintenance - fix pyimport() to work with directories - streamline py.path.local.mkdtemp implementation and usage - don't print empty lines when showing junitxml-filename +- fix py.code.compile(source) to generate unique filenames Changes between 1.3.0 and 1.3.1 ================================================== From commits-noreply at bitbucket.org Mon Jun 7 20:57:57 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 7 Jun 2010 18:57:57 +0000 (UTC) Subject: [py-svn] py-trunk commit 9fa2fbdcde2d: add ignore_errors to local.remove() Message-ID: <20100607185757.ADAB37EFB5@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1275936516 -7200 # Node ID 9fa2fbdcde2d52974731617c87da2f12f7923ae0 # Parent eb9c9a4ba265a25ef7ca9c0fc3a4a7da470b07e5 add ignore_errors to local.remove() --- a/py/_path/local.py +++ b/py/_path/local.py @@ -157,14 +157,18 @@ class LocalPath(FSBase): def __lt__(self, other): return str(self) < str(other) - def remove(self, rec=1): - """ remove a file or directory (or a directory tree if rec=1). """ + def remove(self, rec=1, ignore_errors=False): + """ remove a file or directory (or a directory tree if rec=1). + if ignore_errors is True, errors while removing directories will + be ignored. + """ if self.check(dir=1, link=0): if rec: # force remove of readonly files on windows if iswin32: self.chmod(448, rec=1) # octcal 0700 - py.error.checked_call(py.std.shutil.rmtree, self.strpath) + py.error.checked_call(py.std.shutil.rmtree, self.strpath, + ignore_errors=ignore_errors) else: py.error.checked_call(os.rmdir, self.strpath) else: --- a/testing/path/test_local.py +++ b/testing/path/test_local.py @@ -60,6 +60,17 @@ class TestLocalPath(common.CommonFSTests readonly_dir.remove() assert not readonly_dir.check(exists=1) + def test_remove_routes_ignore_errors(self, tmpdir, monkeypatch): + l = [] + monkeypatch.setattr(py.std.shutil, 'rmtree', + lambda *args, **kwargs: l.append(kwargs)) + tmpdir.remove() + assert not l[0]['ignore_errors'] + for val in (True, False): + l[:] = [] + tmpdir.remove(ignore_errors=val) + assert l[0]['ignore_errors'] == val + def test_initialize_curdir(self): assert str(local()) == py.std.os.getcwd() --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,7 @@ Bug fixes / Maintenance - streamline py.path.local.mkdtemp implementation and usage - don't print empty lines when showing junitxml-filename - fix py.code.compile(source) to generate unique filenames +- add optional boolean ignore_errors parameter to py.path.local.remove Changes between 1.3.0 and 1.3.1 ================================================== From commits-noreply at bitbucket.org Mon Jun 7 20:57:57 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 7 Jun 2010 18:57:57 +0000 (UTC) Subject: [py-svn] py-trunk commit 9b9583e84cfb: some adjustments to make py.test --basetemp=XYZ work where Message-ID: <20100607185757.C0BFE7EFB8@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1275937346 -7200 # Node ID 9b9583e84cfba77e3f48b86e1b69d89ab332d2fe # Parent 9fa2fbdcde2d52974731617c87da2f12f7923ae0 some adjustments to make py.test --basetemp=XYZ work where XYZ is a subdir the checkout which contains a conftest.py --- a/py/_plugin/pytest_pytester.py +++ b/py/_plugin/pytest_pytester.py @@ -347,6 +347,11 @@ class TmpTestdir: p = py.path.local.make_numbered_dir(prefix="runpytest-", keep=None, rootdir=self.tmpdir) args = ('--basetemp=%s' % p, ) + args + for x in args: + if '--confcutdir' in str(x): + break + else: + args = ('--confcutdir=.',) + args plugins = [x for x in self.plugins if isinstance(x, str)] if plugins: args = ('-p', plugins[0]) + args --- a/testing/test_conftesthandle.py +++ b/testing/test_conftesthandle.py @@ -31,7 +31,8 @@ class TestConftestValueAccessGlobal: def test_onimport(self, basedir): l = [] conftest = Conftest(onimport=l.append) - conftest.setinitial([basedir.join("adir")]) + conftest.setinitial([basedir.join("adir"), + '--confcutdir=%s' % basedir]) assert len(l) == 2 assert conftest.rget("a") == 1 assert conftest.rget("b", basedir.join("adir", "b")) == 2 @@ -145,7 +146,7 @@ def test_setinitial_conftest_subdirs(tes sub = testdir.mkdir(name) subconftest = sub.ensure("conftest.py") conftest = Conftest() - conftest.setinitial([sub.dirpath()]) + conftest.setinitial([sub.dirpath(), '--confcutdir=%s' % testdir.tmpdir]) if name != ".dotdir": assert subconftest in conftest._conftestpath2mod assert len(conftest._conftestpath2mod) == 1 From commits-noreply at bitbucket.org Mon Jun 7 23:18:47 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 7 Jun 2010 21:18:47 +0000 (UTC) Subject: [py-svn] py-trunk commit 97febc3fbe6e: fix tox.ini Message-ID: <20100607211847.979B57EFC8@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1275945804 -7200 # Node ID 97febc3fbe6ecf1a3c492030a06e9e690c5bf47b # Parent 9b9583e84cfba77e3f48b86e1b69d89ab332d2fe fix tox.ini --- a/tox.ini +++ b/tox.ini @@ -1,21 +1,7 @@ -[project] -distpaths= - py - setup.py - distribute_setup.py - README.txt - MANIFEST.in - LICENSE - doc - testing - conftest.py - -testpaths= - testing - conftest.py - [test] -command=py.test --confcutdir=. --junitxml=junit-%(envname)s.xml testing/ +changedir=testing +command=py.test -n3 --basetemp=%(envtmpdir)s --confcutdir=.. --junitxml=junit-%(envname)s.xml +deps=pytest-xdist [testenv:py24] python=python2.4 [testenv:py25] @@ -24,6 +10,6 @@ python=python2.5 python=python2.6 [testenv:jython] python=jython -command=py.test-jython --confcutdir=. --junitxml=junit-%(envname)s.xml testing/ +command=py.test-jython -n3 --basetemp=%(envtmpdir)s --confcutdir=.. --junitxml=junit-%(envname)s.xml [testenv:py31] python=python3.1 From commits-noreply at bitbucket.org Tue Jun 8 02:30:44 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Tue, 8 Jun 2010 00:30:44 +0000 (UTC) Subject: [py-svn] py-trunk commit 23865d304221: introduce a new request.applymarker() function and refactor Message-ID: <20100608003044.B66AB7EFD8@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1275957291 -7200 # Node ID 23865d3042213f7a6d4a8fd5ce6b5b71ac23a108 # Parent 97febc3fbe6ecf1a3c492030a06e9e690c5bf47b introduce a new request.applymarker() function and refactor internally to allow for dynamically adding keywords to test items. --- a/py/_plugin/pytest_runner.py +++ b/py/_plugin/pytest_runner.py @@ -134,7 +134,7 @@ class ItemTestReport(BaseReport): self.item = item self.when = when if item and when != "setup": - self.keywords = item.readkeywords() + self.keywords = item.keywords else: # if we fail during setup it might mean # we are not able to access the underlying object --- a/doc/test/plugin/skipping.txt +++ b/doc/test/plugin/skipping.txt @@ -81,6 +81,7 @@ apply the function will be skipped. .. _`whole class- or module level`: mark.html#scoped-marking +.. _xfail: mark a test function as **expected to fail** ------------------------------------------------------- --- a/testing/plugin/test_pytest_terminal.py +++ b/testing/plugin/test_pytest_terminal.py @@ -14,6 +14,7 @@ from py._plugin.pytest_terminal import T from py._plugin import pytest_runner as runner def basic_run_report(item): + runner.call_and_report(item, "setup", log=False) return runner.call_and_report(item, "call", log=False) class Option: --- a/py/_test/funcargs.py +++ b/py/_test/funcargs.py @@ -92,6 +92,16 @@ class FuncargRequest: if argname not in self._pyfuncitem.funcargs: self._pyfuncitem.funcargs[argname] = self.getfuncargvalue(argname) + + def applymarker(self, marker): + """ apply a marker to a test function invocation. + + The 'marker' must be created with py.test.mark.* XYZ. + """ + if not isinstance(marker, py.test.mark.XYZ.__class__): + raise ValueError("%r is not a py.test.mark.* object") + self._pyfuncitem.keywords[marker.markname] = marker + def cached_setup(self, setup, teardown=None, scope="module", extrakey=None): """ cache and return result of calling setup(). --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,17 @@ Changes between 1.3.1 and 1.3.x New features ++++++++++++++++++ +- Funcarg factories can now dynamically apply a marker to a + test invocation. This is particularly useful if a factory + provides parameters to a test which you expect-to-fail: + + def pytest_funcarg__arg(request): + request.applymarker(py.test.mark.xfail(reason="flaky config")) + ... + + def test_function(arg): + ... + Bug fixes / Maintenance ++++++++++++++++++++++++++ --- a/py/_plugin/pytest_skipping.py +++ b/py/_plugin/pytest_skipping.py @@ -159,8 +159,10 @@ class MarkEvaluator: def __init__(self, item, name): self.item = item self.name = name - self.holder = getattr(item.obj, name, None) + @property + def holder(self): + return self.item.keywords.get(self.name, None) def __bool__(self): return bool(self.holder) __nonzero__ = __bool__ @@ -204,10 +206,17 @@ def pytest_runtest_setup(item): if evalskip.istrue(): py.test.skip(evalskip.getexplanation()) item._evalxfail = MarkEvaluator(item, 'xfail') + check_xfail_no_run(item) + +def pytest_pyfunc_call(pyfuncitem): + check_xfail_no_run(pyfuncitem) + +def check_xfail_no_run(item): if not item.config.getvalue("runxfail"): - if item._evalxfail.istrue(): - if not item._evalxfail.get('run', True): - py.test.skip("xfail") + evalxfail = item._evalxfail + if evalxfail.istrue(): + if not evalxfail.get('run', True): + py.test.xfail("[NOTRUN] " + evalxfail.getexplanation()) def pytest_runtest_makereport(__multicall__, item, call): if not isinstance(item, py.test.collect.Function): @@ -224,16 +233,9 @@ def pytest_runtest_makereport(__multical rep.skipped = True rep.failed = False return rep - if call.when == "setup": + if call.when == "call": rep = __multicall__.execute() - if rep.skipped and evalxfail.istrue(): - expl = evalxfail.getexplanation() - if not evalxfail.get("run", True): - expl = "[NOTRUN] " + expl - rep.keywords['xfail'] = expl - return rep - elif call.when == "call": - rep = __multicall__.execute() + evalxfail = getattr(item, '_evalxfail') if not item.config.getvalue("runxfail") and evalxfail.istrue(): if call.excinfo: rep.skipped = True --- a/doc/test/funcargs.txt +++ b/doc/test/funcargs.txt @@ -160,6 +160,25 @@ like this: scope="session" ) +dynamically applying a marker +--------------------------------------------- + +.. sourcecode:: python + + def applymarker(self, marker): + """ apply a marker to a test function invocation. + + The 'marker' must be created with py.test.mark.* XYZ. + """ + +``request.applymarker(marker)`` will mark the test invocation +with the given marker. For example, if your funcarg factory provides +values which may cause a test function to fail you can call +``request.applymarker(py.test.mark.xfail(reason='flaky config'))`` +and this will cause the test to not show tracebacks. See xfail_ +for details. + +.. _`xfail`: plugin/skipping.html#xfail requesting values of other funcargs --------------------------------------------- --- a/testing/test_funcargs.py +++ b/testing/test_funcargs.py @@ -211,6 +211,23 @@ class TestRequest: req = funcargs.FuncargRequest(item) assert req.fspath == modcol.fspath +def test_applymarker(testdir): + item1,item2 = testdir.getitems(""" + class TestClass: + def test_func1(self, something): + pass + def test_func2(self, something): + pass + """) + req1 = funcargs.FuncargRequest(item1) + assert 'xfail' not in item1.keywords + req1.applymarker(py.test.mark.xfail) + assert 'xfail' in item1.keywords + assert 'skipif' not in item1.keywords + req1.applymarker(py.test.mark.skipif) + assert 'skipif' in item1.keywords + py.test.raises(ValueError, "req1.applymarker(42)") + class TestRequestCachedSetup: def test_request_cachedsetup(self, testdir): item1,item2 = testdir.getitems(""" --- a/testing/plugin/test_pytest_skipping.py +++ b/testing/plugin/test_pytest_skipping.py @@ -188,6 +188,21 @@ class TestXFail: "*1 passed*", ]) + def test_xfail_not_run_no_setup_run(self, testdir): + p = testdir.makepyfile(test_one=""" + import py + @py.test.mark.xfail(run=False, reason="hello") + def test_this(): + assert 0 + def setup_module(mod): + raise ValueError(42) + """) + result = testdir.runpytest(p, '--report=xfailed', ) + result.stdout.fnmatch_lines([ + "*test_one*test_this*NOTRUN*hello", + "*1 xfailed*", + ]) + def test_xfail_xpass(self, testdir): p = testdir.makepyfile(test_one=""" import py @@ -245,8 +260,47 @@ class TestXFail: "*py.test.xfail*", ]) + def xtest_dynamic_xfail_set_during_setup(self, testdir): + p = testdir.makepyfile(""" + import py + def setup_function(function): + py.test.mark.xfail(function) + def test_this(): + assert 0 + def test_that(): + assert 1 + """) + result = testdir.runpytest(p, '-rxX') + result.stdout.fnmatch_lines([ + "*XFAIL*test_this*", + "*XPASS*test_that*", + ]) + def test_dynamic_xfail_no_run(self, testdir): + p = testdir.makepyfile(""" + import py + def pytest_funcarg__arg(request): + request.applymarker(py.test.mark.xfail(run=False)) + def test_this(arg): + assert 0 + """) + result = testdir.runpytest(p, '-rxX') + result.stdout.fnmatch_lines([ + "*XFAIL*test_this*NOTRUN*", + ]) + def test_dynamic_xfail_set_during_funcarg_setup(self, testdir): + p = testdir.makepyfile(""" + import py + def pytest_funcarg__arg(request): + request.applymarker(py.test.mark.xfail) + def test_this2(arg): + assert 0 + """) + result = testdir.runpytest(p) + result.stdout.fnmatch_lines([ + "*1 xfailed*", + ]) class TestSkipif: --- a/py/_test/pycollect.py +++ b/py/_test/pycollect.py @@ -348,6 +348,7 @@ class Function(FunctionMixin, py.test.co if callobj is not _dummy: self._obj = callobj self.function = getattr(self.obj, 'im_func', self.obj) + self.keywords.update(py.builtin._getfuncdict(self.obj) or {}) def _getobj(self): name = self.name @@ -359,11 +360,6 @@ class Function(FunctionMixin, py.test.co def _isyieldedfunction(self): return self._args is not None - def readkeywords(self): - d = super(Function, self).readkeywords() - d.update(py.builtin._getfuncdict(self.obj)) - return d - def runtest(self): """ execute the underlying test function. """ self.ihook.pytest_pyfunc_call(pyfuncitem=self) --- a/py/_test/collect.py +++ b/py/_test/collect.py @@ -31,6 +31,7 @@ class Node(object): self.config = config or parent.config self.fspath = getattr(parent, 'fspath', None) self.ihook = HookProxy(self) + self.keywords = self.readkeywords() def _reraiseunpicklingproblem(self): if hasattr(self, '_unpickle_exc'): @@ -153,7 +154,7 @@ class Node(object): def _matchonekeyword(self, key, chain): elems = key.split(".") # XXX O(n^2), anyone cares? - chain = [item.readkeywords() for item in chain if item._keywords()] + chain = [item.keywords for item in chain if item.keywords] for start, _ in enumerate(chain): if start + len(elems) > len(chain): return False --- a/py/_plugin/pytest_mark.py +++ b/py/_plugin/pytest_mark.py @@ -171,4 +171,6 @@ def pytest_pycollect_makeitem(__multical for mark in marker: if isinstance(mark, MarkDecorator): mark(func) + item.keywords.update(py.builtin._getfuncdict(func) or {}) + return item --- a/testing/plugin/test_pytest_mark.py +++ b/testing/plugin/test_pytest_mark.py @@ -65,7 +65,7 @@ class TestFunctional: def test_func(): pass """) - keywords = item.readkeywords() + keywords = item.keywords assert 'hello' in keywords def test_marklist_per_class(self, testdir): @@ -79,7 +79,7 @@ class TestFunctional: """) clscol = modcol.collect()[0] item = clscol.collect()[0].collect()[0] - keywords = item.readkeywords() + keywords = item.keywords assert 'hello' in keywords def test_marklist_per_module(self, testdir): @@ -93,7 +93,7 @@ class TestFunctional: """) clscol = modcol.collect()[0] item = clscol.collect()[0].collect()[0] - keywords = item.readkeywords() + keywords = item.keywords assert 'hello' in keywords assert 'world' in keywords @@ -108,7 +108,7 @@ class TestFunctional: """) clscol = modcol.collect()[0] item = clscol.collect()[0].collect()[0] - keywords = item.readkeywords() + keywords = item.keywords assert 'hello' in keywords @py.test.mark.skipif("sys.version_info < (2,6)") @@ -124,7 +124,7 @@ class TestFunctional: """) clscol = modcol.collect()[0] item = clscol.collect()[0].collect()[0] - keywords = item.readkeywords() + keywords = item.keywords assert 'hello' in keywords assert 'world' in keywords @@ -141,7 +141,7 @@ class TestFunctional: """) items, rec = testdir.inline_genitems(p) item, = items - keywords = item.readkeywords() + keywords = item.keywords marker = keywords['hello'] assert marker.args == ["pos0", "pos1"] assert marker.kwargs == {'x': 3, 'y': 2, 'z': 4} @@ -154,4 +154,22 @@ class TestFunctional: def test_func(): pass """) - keywords = item.readkeywords() + keywords = item.keywords + + def test_mark_dynamically_in_funcarg(self, testdir): + testdir.makeconftest(""" + import py + def pytest_funcarg__arg(request): + request.applymarker(py.test.mark.hello) + def pytest_terminal_summary(terminalreporter): + l = terminalreporter.stats['passed'] + terminalreporter._tw.line("keyword: %s" % l[0].keywords) + """) + testdir.makepyfile(""" + def test_func(arg): + pass + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "keyword: *hello*" + ]) From commits-noreply at bitbucket.org Wed Jun 9 11:56:41 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 9 Jun 2010 09:56:41 +0000 (UTC) Subject: [py-svn] py-trunk commit 23b6bb2419bd: capture a concrete idea for easing platform-specific testing. Message-ID: <20100609095641.852D87EF78@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1275992955 -7200 # Node ID 23b6bb2419bdb865d9534b8c069edb61a08e552c # Parent 23865d3042213f7a6d4a8fd5ce6b5b71ac23a108 capture a concrete idea for easing platform-specific testing. --- a/ISSUES.txt +++ b/ISSUES.txt @@ -21,6 +21,23 @@ maybe also introduce a py.test.mark.test mark a function to become a tested one. Lookup JUnit ways of tagging tests. +introduce py.test.mark.platform +------------------------------------------------------- +tags: feature 1.4 + +Introduce nice-to-spell platform-skipping, examples: + + @py.test.mark.platform("python3") + @py.test.mark.platform("not python3") + @py.test.mark.platform("win32 and not python3") + @py.test.mark.platform("darwin") + @py.test.mark.platform("not (jython and win32)") + @py.test.mark.platform("not (jython and win32)", xfail=True) + +etc. Idea is to allow Python expressions which can operate +on common spellings for operating systems and python +interpreter versions. + introduce py.test.mark registration ----------------------------------------- tags: feature 1.3 From commits-noreply at bitbucket.org Wed Jun 9 11:56:41 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 9 Jun 2010 09:56:41 +0000 (UTC) Subject: [py-svn] py-trunk commit 0320df9af115: make terminal tests pass on win32/python2.4 and update tox.ini Message-ID: <20100609095641.A3AB37EF79@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276077673 -7200 # Node ID 0320df9af11576cd0eec9f871cda355563d558ee # Parent 23b6bb2419bdb865d9534b8c069edb61a08e552c make terminal tests pass on win32/python2.4 and update tox.ini --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,10 @@ [test] changedir=testing -command=py.test -n3 --basetemp=%(envtmpdir)s --confcutdir=.. --junitxml=junit-%(envname)s.xml +cmdargs=py.test + -n3 + --basetemp=%(envtmpdir)s + --confcutdir=.. + --junitxml=junit-%(envname)s.xml deps=pytest-xdist [testenv:py24] python=python2.4 @@ -8,8 +12,8 @@ python=python2.4 python=python2.5 [testenv:py26] python=python2.6 -[testenv:jython] -python=jython -command=py.test-jython -n3 --basetemp=%(envtmpdir)s --confcutdir=.. --junitxml=junit-%(envname)s.xml +#[testenv:jython] +#python=jython +#command=py.test-jython -n3 --basetemp=%(envtmpdir)s --confcutdir=.. --junitxml=junit-%(envname)s.xml [testenv:py31] python=python3.1 --- a/py/_io/terminalwriter.py +++ b/py/_io/terminalwriter.py @@ -8,64 +8,20 @@ Helper functions for writing to terminal import sys, os import py +win32_and_ctypes = False +if sys.platform == "win32": + try: + import ctypes + win32_and_ctypes = True + except ImportError: + pass + def _getdimensions(): import termios,fcntl,struct call = fcntl.ioctl(0,termios.TIOCGWINSZ,"\000"*8) height,width = struct.unpack( "hhhh", call ) [:2] return height, width -if sys.platform == 'win32': - # ctypes access to the Windows console - - STD_OUTPUT_HANDLE = -11 - STD_ERROR_HANDLE = -12 - FOREGROUND_BLUE = 0x0001 # text color contains blue. - FOREGROUND_GREEN = 0x0002 # text color contains green. - FOREGROUND_RED = 0x0004 # text color contains red. - FOREGROUND_WHITE = 0x0007 - FOREGROUND_INTENSITY = 0x0008 # text color is intensified. - BACKGROUND_BLUE = 0x0010 # background color contains blue. - BACKGROUND_GREEN = 0x0020 # background color contains green. - BACKGROUND_RED = 0x0040 # background color contains red. - BACKGROUND_WHITE = 0x0070 - BACKGROUND_INTENSITY = 0x0080 # background color is intensified. - - def GetStdHandle(kind): - import ctypes - return ctypes.windll.kernel32.GetStdHandle(kind) - - def SetConsoleTextAttribute(handle, attr): - import ctypes - ctypes.windll.kernel32.SetConsoleTextAttribute( - handle, attr) - - def _getdimensions(): - import ctypes - from ctypes import wintypes - - SHORT = ctypes.c_short - class COORD(ctypes.Structure): - _fields_ = [('X', SHORT), - ('Y', SHORT)] - class SMALL_RECT(ctypes.Structure): - _fields_ = [('Left', SHORT), - ('Top', SHORT), - ('Right', SHORT), - ('Bottom', SHORT)] - class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure): - _fields_ = [('dwSize', COORD), - ('dwCursorPosition', COORD), - ('wAttributes', wintypes.WORD), - ('srWindow', SMALL_RECT), - ('dwMaximumWindowSize', COORD)] - STD_OUTPUT_HANDLE = -11 - handle = GetStdHandle(STD_OUTPUT_HANDLE) - info = CONSOLE_SCREEN_BUFFER_INFO() - ctypes.windll.kernel32.GetConsoleScreenBufferInfo( - handle, ctypes.byref(info)) - # Substract one from the width, otherwise the cursor wraps - # and the ending \n causes an empty line to display. - return info.dwSize.Y, info.dwSize.X - 1 def get_terminal_width(): try: @@ -97,7 +53,7 @@ def ansi_print(text, esc, file=None, new if newline: text += '\n' - if esc and sys.platform == "win32" and file.isatty(): + if esc and win32_and_ctypes and file.isatty(): if 1 in esc: bold = True esc = tuple([x for x in esc if x != 1]) @@ -254,9 +210,6 @@ class Win32ConsoleWriter(TerminalWriter) def line(self, s="", **kw): self.write(s+"\n", **kw) -if sys.platform == 'win32': - TerminalWriter = Win32ConsoleWriter - class WriteFile(object): def __init__(self, writemethod, encoding=None): self.encoding = encoding @@ -271,3 +224,57 @@ class WriteFile(object): return +if win32_and_ctypes: + TerminalWriter = Win32ConsoleWriter + + # ctypes access to the Windows console + STD_OUTPUT_HANDLE = -11 + STD_ERROR_HANDLE = -12 + FOREGROUND_BLUE = 0x0001 # text color contains blue. + FOREGROUND_GREEN = 0x0002 # text color contains green. + FOREGROUND_RED = 0x0004 # text color contains red. + FOREGROUND_WHITE = 0x0007 + FOREGROUND_INTENSITY = 0x0008 # text color is intensified. + BACKGROUND_BLUE = 0x0010 # background color contains blue. + BACKGROUND_GREEN = 0x0020 # background color contains green. + BACKGROUND_RED = 0x0040 # background color contains red. + BACKGROUND_WHITE = 0x0070 + BACKGROUND_INTENSITY = 0x0080 # background color is intensified. + + def GetStdHandle(kind): + import ctypes + return ctypes.windll.kernel32.GetStdHandle(kind) + + def SetConsoleTextAttribute(handle, attr): + import ctypes + ctypes.windll.kernel32.SetConsoleTextAttribute( + handle, attr) + + def _getdimensions(): + import ctypes + from ctypes import wintypes + + SHORT = ctypes.c_short + class COORD(ctypes.Structure): + _fields_ = [('X', SHORT), + ('Y', SHORT)] + class SMALL_RECT(ctypes.Structure): + _fields_ = [('Left', SHORT), + ('Top', SHORT), + ('Right', SHORT), + ('Bottom', SHORT)] + class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure): + _fields_ = [('dwSize', COORD), + ('dwCursorPosition', COORD), + ('wAttributes', wintypes.WORD), + ('srWindow', SMALL_RECT), + ('dwMaximumWindowSize', COORD)] + STD_OUTPUT_HANDLE = -11 + handle = GetStdHandle(STD_OUTPUT_HANDLE) + info = CONSOLE_SCREEN_BUFFER_INFO() + ctypes.windll.kernel32.GetConsoleScreenBufferInfo( + handle, ctypes.byref(info)) + # Substract one from the width, otherwise the cursor wraps + # and the ending \n causes an empty line to display. + return info.dwSize.Y, info.dwSize.X - 1 + From commits-noreply at bitbucket.org Wed Jun 9 12:02:19 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 9 Jun 2010 10:02:19 +0000 (UTC) Subject: [py-svn] py-trunk commit 1c4ebc67d5f4: less imports at function level, add a CHANGELOG entry - i guess Message-ID: <20100609100219.6B7917EF13@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276078032 -7200 # Node ID 1c4ebc67d5f4ffcbec6a94606c1c975692069e18 # Parent 0320df9af11576cd0eec9f871cda355563d558ee less imports at function level, add a CHANGELOG entry - i guess there are not many win32/python2.4 users anymore these days. --- a/py/_io/terminalwriter.py +++ b/py/_io/terminalwriter.py @@ -226,6 +226,8 @@ class WriteFile(object): if win32_and_ctypes: TerminalWriter = Win32ConsoleWriter + import ctypes + from ctypes import wintypes # ctypes access to the Windows console STD_OUTPUT_HANDLE = -11 @@ -242,17 +244,13 @@ if win32_and_ctypes: BACKGROUND_INTENSITY = 0x0080 # background color is intensified. def GetStdHandle(kind): - import ctypes return ctypes.windll.kernel32.GetStdHandle(kind) def SetConsoleTextAttribute(handle, attr): - import ctypes ctypes.windll.kernel32.SetConsoleTextAttribute( handle, attr) def _getdimensions(): - import ctypes - from ctypes import wintypes SHORT = ctypes.c_short class COORD(ctypes.Structure): --- a/CHANGELOG +++ b/CHANGELOG @@ -24,6 +24,7 @@ Bug fixes / Maintenance - don't print empty lines when showing junitxml-filename - fix py.code.compile(source) to generate unique filenames - add optional boolean ignore_errors parameter to py.path.local.remove +- fix terminal writing on win32/python2.4 Changes between 1.3.0 and 1.3.1 ================================================== From commits-noreply at bitbucket.org Wed Jun 9 14:40:46 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 9 Jun 2010 12:40:46 +0000 (UTC) Subject: [py-svn] py-trunk commit ad700c1825d3: make py.test.raises as-VAR be an ExceptionInfo object Message-ID: <20100609124046.04E307EF7E@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276087541 -7200 # Node ID ad700c1825d31578cfb2e8db153d3d4e4e7b15ea # Parent c53778a0ed728a575f2c38066aa882b7e40b8e3a make py.test.raises as-VAR be an ExceptionInfo object but only initialize it after the block is finished. --- a/testing/plugin/test_pytest_runner.py +++ b/testing/plugin/test_pytest_runner.py @@ -347,12 +347,11 @@ class TestRaises: import py def test_simple(): - with py.test.raises(ZeroDivisionError) as ctx: + with py.test.raises(ZeroDivisionError) as excinfo: + assert isinstance(excinfo, py.code.ExceptionInfo) 1/0 - - print ctx.excinfo - assert ctx.excinfo.type is ZeroDivisionError - + print (excinfo) + assert excinfo.type == ZeroDivisionError def test_noraise(): with py.test.raises(py.test.raises.Exception): --- a/py/_plugin/pytest_runner.py +++ b/py/_plugin/pytest_runner.py @@ -411,7 +411,8 @@ class RaisesContext(object): self.excinfo = None def __enter__(self): - return self + self.excinfo = object.__new__(py.code.ExceptionInfo) + return self.excinfo def __exit__(self, *tp): __tracebackhide__ = True @@ -419,7 +420,7 @@ class RaisesContext(object): raise ExceptionFailure(msg="DID NOT RAISE", expr=(), expected=self.ExpectedException) - self.excinfo = py.code.ExceptionInfo(tp) + self.excinfo.__init__(tp) return issubclass(self.excinfo.type, self.ExpectedException) --- a/doc/test/features.txt +++ b/doc/test/features.txt @@ -136,6 +136,15 @@ In order to write assertions about excep with py.test.raises(ZeroDivisionError): 1 / 0 +and if you need to have access to the actual exception info you may use:: + + with py.test.raises(RuntimeError) as excinfo: + def f(): + f() + f() + + # do checks related to excinfo.type, excinfo.value, excinfo.traceback + If you want to write test code that works on Python2.4 as well, you may also use two other ways to test for an expected exception:: --- a/CHANGELOG +++ b/CHANGELOG @@ -4,12 +4,17 @@ Changes between 1.3.1 and 1.3.x New features ++++++++++++++++++ -- fix issue103: introduce additional "with py.test.raises(exc):" form, example:: +- fix issue103: introduce py.test.raises as context manager, examples:: - with py.test.raises(ZeroDivisionError): + with py.test.raises(ZeroDivisionError): x = 0 1 / x + with py.test.raises(RuntimeError) as excinfo: + call_something() + + # do extra checks on excinfo.value|type|traceback objects + (thanks Ronny Pfannschmidt) - Funcarg factories can now dynamically apply a marker to a From commits-noreply at bitbucket.org Wed Jun 9 15:23:19 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 9 Jun 2010 13:23:19 +0000 (UTC) Subject: [py-svn] py-trunk commit d634c75a4004: fix issue104 properly xml-escape names in junitxml files Message-ID: <20100609132319.E17817EF7C@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276090065 -7200 # Node ID d634c75a4004c1df0ce184be7bf6f1c7d46b2023 # Parent ad700c1825d31578cfb2e8db153d3d4e4e7b15ea fix issue104 properly xml-escape names in junitxml files --- a/testing/plugin/test_pytest_junitxml.py +++ b/testing/plugin/test_pytest_junitxml.py @@ -98,6 +98,27 @@ class TestPython: assert_attr(fnode, message="test failure") assert "ValueError" in fnode.toxml() + def test_failure_escape(self, testdir): + testdir.makepyfile(""" + def pytest_generate_tests(metafunc): + metafunc.addcall(id="<", funcargs=dict(arg1=42)) + metafunc.addcall(id="&", funcargs=dict(arg1=44)) + def test_func(arg1): + assert 0 + """) + result, dom = runandparse(testdir) + assert result.ret + node = dom.getElementsByTagName("testsuite")[0] + assert_attr(node, failures=2, tests=2) + tnode = node.getElementsByTagName("testcase")[0] + assert_attr(tnode, + classname="test_failure_escape.test_failure_escape", + name="test_func[<]") + tnode = node.getElementsByTagName("testcase")[1] + assert_attr(tnode, + classname="test_failure_escape.test_failure_escape", + name="test_func[&]") + def test_xfailure_function(self, testdir): testdir.makepyfile(""" import py --- a/py/_plugin/pytest_junitxml.py +++ b/py/_plugin/pytest_junitxml.py @@ -37,7 +37,7 @@ class LogXML(object): d = {'time': self._durations.pop(report.item, "0")} names = [x.replace(".py", "") for x in node.listnames() if x != "()"] d['classname'] = ".".join(names[:-1]) - d['name'] = names[-1] + d['name'] = py.xml.escape(names[-1]) attrs = ['%s="%s"' % item for item in sorted(d.items())] self.test_logs.append("\n" % " ".join(attrs)) @@ -71,7 +71,7 @@ class LogXML(object): d = {'time': '???'} names = [x.replace(".py", "") for x in node.listnames() if x != "()"] d['classname'] = ".".join(names[:-1]) - d['name'] = names[-1] + d['name'] = py.xml.escape(names[-1]) attrs = ['%s="%s"' % item for item in sorted(d.items())] self.test_logs.append("\n" % " ".join(attrs)) --- a/CHANGELOG +++ b/CHANGELOG @@ -31,6 +31,7 @@ New features Bug fixes / Maintenance ++++++++++++++++++++++++++ +- fix issue104 proper escaping for test names in junitxml plugin - fix issue57 -f|--looponfail to work with xpassing tests - fix pyimport() to work with directories - streamline py.path.local.mkdtemp implementation and usage From commits-noreply at bitbucket.org Wed Jun 9 16:14:21 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 9 Jun 2010 14:14:21 +0000 (UTC) Subject: [py-svn] py-trunk commit c2b75104d76b: introduce a new --junitprefix option to influence xml reporting. Message-ID: <20100609141421.009B27EE76@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276093127 -7200 # Node ID c2b75104d76b991f559f8f52d3e3909cf2c0e7b0 # Parent d634c75a4004c1df0ce184be7bf6f1c7d46b2023 introduce a new --junitprefix option to influence xml reporting. also internally avoid some redundant code. --- a/testing/plugin/test_pytest_junitxml.py +++ b/testing/plugin/test_pytest_junitxml.py @@ -119,6 +119,28 @@ class TestPython: classname="test_failure_escape.test_failure_escape", name="test_func[&]") + def test_junit_prefixing(self, testdir): + testdir.makepyfile(""" + def test_func(): + assert 0 + class TestHello: + def test_hello(self): + pass + """) + result, dom = runandparse(testdir, "--junitprefix=xyz") + assert result.ret + node = dom.getElementsByTagName("testsuite")[0] + assert_attr(node, failures=1, tests=2) + tnode = node.getElementsByTagName("testcase")[0] + assert_attr(tnode, + classname="xyz.test_junit_prefixing.test_junit_prefixing", + name="test_func") + tnode = node.getElementsByTagName("testcase")[1] + assert_attr(tnode, + classname="xyz.test_junit_prefixing.test_junit_prefixing." + "TestHello", + name="test_hello") + def test_xfailure_function(self, testdir): testdir.makepyfile(""" import py --- a/py/_plugin/pytest_junitxml.py +++ b/py/_plugin/pytest_junitxml.py @@ -11,11 +11,14 @@ def pytest_addoption(parser): group.addoption('--junitxml', action="store", dest="xmlpath", metavar="path", default=None, help="create junit-xml style report file at given path.") + group.addoption('--junitprefix', action="store", dest="junitprefix", + metavar="str", default=None, + help="prepend prefix to classnames in junit-xml output") def pytest_configure(config): xmlpath = config.option.xmlpath if xmlpath: - config._xml = LogXML(xmlpath) + config._xml = LogXML(xmlpath, config.option.junitprefix) config.pluginmanager.register(config._xml) def pytest_unconfigure(config): @@ -25,18 +28,25 @@ def pytest_unconfigure(config): config.pluginmanager.unregister(xml) class LogXML(object): - def __init__(self, logfile): + def __init__(self, logfile, prefix): self.logfile = logfile + self.prefix = prefix self.test_logs = [] self.passed = self.skipped = 0 self.failed = self.errors = 0 self._durations = {} def _opentestcase(self, report): - node = report.item - d = {'time': self._durations.pop(report.item, "0")} + if hasattr(report, 'item'): + node = report.item + else: + node = report.collector + d = {'time': self._durations.pop(node, "0")} names = [x.replace(".py", "") for x in node.listnames() if x != "()"] - d['classname'] = ".".join(names[:-1]) + classnames = names[:-1] + if self.prefix: + classnames.insert(0, self.prefix) + d['classname'] = ".".join(classnames) d['name'] = py.xml.escape(names[-1]) attrs = ['%s="%s"' % item for item in sorted(d.items())] self.test_logs.append("\n" % " ".join(attrs)) @@ -66,17 +76,8 @@ class LogXML(object): self.failed += 1 self._closetestcase() - def _opentestcase_collectfailure(self, report): - node = report.collector - d = {'time': '???'} - names = [x.replace(".py", "") for x in node.listnames() if x != "()"] - d['classname'] = ".".join(names[:-1]) - d['name'] = py.xml.escape(names[-1]) - attrs = ['%s="%s"' % item for item in sorted(d.items())] - self.test_logs.append("\n" % " ".join(attrs)) - def append_collect_failure(self, report): - self._opentestcase_collectfailure(report) + self._opentestcase(report) #msg = str(report.longrepr.reprtraceback.extraline) self.appendlog('%s', report.longrepr) @@ -84,7 +85,7 @@ class LogXML(object): self.errors += 1 def append_collect_skipped(self, report): - self._opentestcase_collectfailure(report) + self._opentestcase(report) #msg = str(report.longrepr.reprtraceback.extraline) self.appendlog('%s', report.longrepr) --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,9 @@ New features (thanks Ronny Pfannschmidt) +- introduce '--junitprefix=STR' option to prepend a prefix + to all reports in the junitxml file. + - Funcarg factories can now dynamically apply a marker to a test invocation. This is particularly useful if a factory provides parameters to a test which you expect-to-fail: From commits-noreply at bitbucket.org Wed Jun 9 16:31:08 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 9 Jun 2010 14:31:08 +0000 (UTC) Subject: [py-svn] py-trunk commit a08c18e10a49: use new --junitprefix option for tox reporting Message-ID: <20100609143108.773187EF72@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276094150 -7200 # Node ID a08c18e10a49ee9ce232a623054dab780d5a2e76 # Parent c2b75104d76b991f559f8f52d3e3909cf2c0e7b0 use new --junitprefix option for tox reporting --- a/tox.ini +++ b/tox.ini @@ -5,6 +5,7 @@ cmdargs=py.test --basetemp=%(envtmpdir)s --confcutdir=.. --junitxml=junit-%(envname)s.xml + --junitprefix=%(envname)s deps=pytest-xdist [testenv:py24] python=python2.4 @@ -15,5 +16,5 @@ python=python2.6 #[testenv:jython] #python=jython #command=py.test-jython -n3 --basetemp=%(envtmpdir)s --confcutdir=.. --junitxml=junit-%(envname)s.xml -[testenv:py31] -python=python3.1 +#[testenv:py31] +#python=python3.1 From commits-noreply at bitbucket.org Wed Jun 9 21:52:55 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 9 Jun 2010 19:52:55 +0000 (UTC) Subject: [py-svn] py-trunk commit 03efb9888f26: Interpret assignments while examining asserts corrects Message-ID: <20100609195255.9BD147EFA9@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User Benjamin Peterson # Date 1276113191 18000 # Node ID 03efb9888f2689bfd53f70fcf4b15a14493b3d05 # Parent a08c18e10a49ee9ce232a623054dab780d5a2e76 Interpret assignments while examining asserts corrects fixes #105 --- a/py/_code/_assertionnew.py +++ b/py/_code/_assertionnew.py @@ -324,10 +324,11 @@ class DebugInterpreter(ast.NodeVisitor): def visit_Assign(self, assign): value_explanation, value_result = self.visit(assign.value) explanation = "... = %s" % (value_explanation,) - name = ast.Name("__exprinfo_expr", ast.Load(), assign.value.lineno, - assign.value.col_offset) - new_assign = ast.Assign(assign.targets, name, assign.lineno, - assign.col_offset) + name = ast.Name("__exprinfo_expr", ast.Load(), + lineno=assign.value.lineno, + col_offset=assign.value.col_offset) + new_assign = ast.Assign(assign.targets, name, lineno=assign.lineno, + col_offset=assign.col_offset) mod = ast.Module([new_assign]) co = self._compile(mod, "exec") try: --- a/testing/code/test_assertion.py +++ b/testing/code/test_assertion.py @@ -139,6 +139,13 @@ def test_assert_with_brokenrepr_arg(): if e.msg.find("broken __repr__") == -1: py.test.fail("broken __repr__ not handle correctly") +def test_multiple_statements_per_line(): + try: + a = 1; assert a == 2 + except AssertionError: + e = exvalue() + assert "assert 1 == 2" in e.msg + class TestView: --- a/CHANGELOG +++ b/CHANGELOG @@ -34,6 +34,7 @@ New features Bug fixes / Maintenance ++++++++++++++++++++++++++ +- fix issue105 assignment on the same line as a failing assertion - fix issue104 proper escaping for test names in junitxml plugin - fix issue57 -f|--looponfail to work with xpassing tests - fix pyimport() to work with directories From commits-noreply at bitbucket.org Thu Jun 10 09:49:20 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 10 Jun 2010 07:49:20 +0000 (UTC) Subject: [py-svn] py-trunk commit f45d5a497d0d: defer compilation to frame.eval (pypy overrides frame.eval and has its own compilation Message-ID: <20100610074920.6D69A7EF80@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276156420 -7200 # Node ID f45d5a497d0d43bc31dcae3b6e2d66f736b66b28 # Parent 03efb9888f2689bfd53f70fcf4b15a14493b3d05 defer compilation to frame.eval (pypy overrides frame.eval and has its own compilation of source code to bytecode) --- a/py/_code/_assertionold.py +++ b/py/_code/_assertionold.py @@ -185,10 +185,9 @@ class Compare(Interpretable): expr2.eval(frame) self.explanation = "%s %s %s" % ( expr.explanation, operation, expr2.explanation) - co = compile("__exprinfo_left %s __exprinfo_right" % operation, - '?', 'eval') + source = "__exprinfo_left %s __exprinfo_right" % operation try: - self.result = frame.eval(co, __exprinfo_left=expr.result, + self.result = frame.eval(source, __exprinfo_left=expr.result, __exprinfo_right=expr2.result) except passthroughex: raise From commits-noreply at bitbucket.org Thu Jun 10 10:52:26 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 10 Jun 2010 08:52:26 +0000 (UTC) Subject: [py-svn] py-trunk commit 01bdefcb53f1: defer a number of other compiles to frame.eval (patch from Amaury on trunk/pypy fork, thanks) Message-ID: <20100610085226.D62A37EF80@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276160174 -7200 # Node ID 01bdefcb53f1050b9a742c71c69a295f30787560 # Parent f45d5a497d0d43bc31dcae3b6e2d66f736b66b28 defer a number of other compiles to frame.eval (patch from Amaury on trunk/pypy fork, thanks) --- a/py/_code/_assertionold.py +++ b/py/_code/_assertionold.py @@ -138,28 +138,28 @@ class Name(Interpretable): __view__ = ast.Name def is_local(self, frame): - co = compile('%r in locals() is not globals()' % self.name, '?', 'eval') + source = '%r in locals() is not globals()' % self.name try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: return False def is_global(self, frame): - co = compile('%r in globals()' % self.name, '?', 'eval') + source = '%r in globals()' % self.name try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: return False def is_builtin(self, frame): - co = compile('%r not in locals() and %r not in globals()' % ( - self.name, self.name), '?', 'eval') + source = '%r not in locals() and %r not in globals()' % ( + self.name, self.name) try: - return frame.is_true(frame.eval(co)) + return frame.is_true(frame.eval(source)) except passthroughex: raise except: @@ -187,8 +187,9 @@ class Compare(Interpretable): expr.explanation, operation, expr2.explanation) source = "__exprinfo_left %s __exprinfo_right" % operation try: - self.result = frame.eval(source, __exprinfo_left=expr.result, - __exprinfo_right=expr2.result) + self.result = frame.eval(source, + __exprinfo_left=expr.result, + __exprinfo_right=expr2.result) except passthroughex: raise except: @@ -234,14 +235,14 @@ for astclass, astpattern in { class UnaryArith(Interpretable): __view__ = astclass - def eval(self, frame, astpattern=astpattern, - co=compile(astpattern, '?', 'eval')): + def eval(self, frame, astpattern=astpattern): expr = Interpretable(self.expr) expr.eval(frame) self.explanation = astpattern.replace('__exprinfo_expr', expr.explanation) try: - self.result = frame.eval(co, __exprinfo_expr=expr.result) + self.result = frame.eval(astpattern, + __exprinfo_expr=expr.result) except passthroughex: raise except: @@ -262,8 +263,7 @@ for astclass, astpattern in { class BinaryArith(Interpretable): __view__ = astclass - def eval(self, frame, astpattern=astpattern, - co=compile(astpattern, '?', 'eval')): + def eval(self, frame, astpattern=astpattern): left = Interpretable(self.left) left.eval(frame) right = Interpretable(self.right) @@ -272,8 +272,9 @@ for astclass, astpattern in { .replace('__exprinfo_left', left .explanation) .replace('__exprinfo_right', right.explanation)) try: - self.result = frame.eval(co, __exprinfo_left=left.result, - __exprinfo_right=right.result) + self.result = frame.eval(astpattern, + __exprinfo_left=left.result, + __exprinfo_right=right.result) except passthroughex: raise except: @@ -286,9 +287,10 @@ class CallFunc(Interpretable): __view__ = ast.CallFunc def is_bool(self, frame): - co = compile('isinstance(__exprinfo_value, bool)', '?', 'eval') + source = 'isinstance(__exprinfo_value, bool)' try: - return frame.is_true(frame.eval(co, __exprinfo_value=self.result)) + return frame.is_true(frame.eval(source, + __exprinfo_value=self.result)) except passthroughex: raise except: @@ -335,9 +337,8 @@ class CallFunc(Interpretable): if source.endswith(','): source = source[:-1] source += ')' - co = compile(source, '?', 'eval') try: - self.result = frame.eval(co, **vars) + self.result = frame.eval(source, **vars) except passthroughex: raise except: @@ -352,21 +353,20 @@ class Getattr(Interpretable): def eval(self, frame): expr = Interpretable(self.expr) expr.eval(frame) - co = compile('__exprinfo_expr.%s' % self.attrname, '?', 'eval') + source = '__exprinfo_expr.%s' % self.attrname try: - self.result = frame.eval(co, __exprinfo_expr=expr.result) + self.result = frame.eval(source, __exprinfo_expr=expr.result) except passthroughex: raise except: raise Failure(self) self.explanation = '%s.%s' % (expr.explanation, self.attrname) # if the attribute comes from the instance, its value is interesting - co = compile('hasattr(__exprinfo_expr, "__dict__") and ' - '%r in __exprinfo_expr.__dict__' % self.attrname, - '?', 'eval') + source = ('hasattr(__exprinfo_expr, "__dict__") and ' + '%r in __exprinfo_expr.__dict__' % self.attrname) try: from_instance = frame.is_true( - frame.eval(co, __exprinfo_expr=expr.result)) + frame.eval(source, __exprinfo_expr=expr.result)) except passthroughex: raise except: --- a/CHANGELOG +++ b/CHANGELOG @@ -37,10 +37,12 @@ Bug fixes / Maintenance - fix issue105 assignment on the same line as a failing assertion - fix issue104 proper escaping for test names in junitxml plugin - fix issue57 -f|--looponfail to work with xpassing tests +- fix py.code.compile(source) to generate unique filenames +- fix assertion re-interp problems on PyPy, by defering code + compilation to the (overridable) Frame.eval class. - fix pyimport() to work with directories - streamline py.path.local.mkdtemp implementation and usage - don't print empty lines when showing junitxml-filename -- fix py.code.compile(source) to generate unique filenames - add optional boolean ignore_errors parameter to py.path.local.remove - fix terminal writing on win32/python2.4 From commits-noreply at bitbucket.org Thu Jun 10 20:49:46 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 10 Jun 2010 18:49:46 +0000 (UTC) Subject: [py-svn] py-trunk commit 9fae04a6b042: fix assertion interpretation when the operator is ** Message-ID: <20100610184946.66F6B7EEFC@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User Benjamin Peterson # Date 1276195807 18000 # Node ID 9fae04a6b042bacaf8579809eb043db788850134 # Parent 01bdefcb53f1050b9a742c71c69a295f30787560 fix assertion interpretation when the operator is ** --- a/py/_code/_assertionnew.py +++ b/py/_code/_assertionnew.py @@ -92,6 +92,7 @@ operator_map = { ast.LtE : "<=", ast.Gt : ">", ast.GtE : ">=", + ast.Pow : "**", ast.Is : "is", ast.IsNot : "is not", ast.In : "in", --- a/testing/code/test_assertion.py +++ b/testing/code/test_assertion.py @@ -146,6 +146,13 @@ def test_multiple_statements_per_line(): e = exvalue() assert "assert 1 == 2" in e.msg +def test_power(): + try: + assert 2**3 == 7 + except AssertionError: + e = exvalue() + assert "assert 8 == 7" in e.msg + class TestView: --- a/CHANGELOG +++ b/CHANGELOG @@ -34,6 +34,7 @@ New features Bug fixes / Maintenance ++++++++++++++++++++++++++ +- fix assertion interpretation with the ** operator - fix issue105 assignment on the same line as a failing assertion - fix issue104 proper escaping for test names in junitxml plugin - fix issue57 -f|--looponfail to work with xpassing tests From commits-noreply at bitbucket.org Thu Jun 10 21:04:47 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 10 Jun 2010 19:04:47 +0000 (UTC) Subject: [py-svn] py-trunk commit ea00c9bc110e: improve comment Message-ID: <20100610190447.D25B57EF77@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User Benjamin Peterson # Date 1276196740 18000 # Node ID ea00c9bc110e38f7595c56c667dffceb6f4c4c41 # Parent 9fae04a6b042bacaf8579809eb043db788850134 improve comment --- a/py/_code/_assertionnew.py +++ b/py/_code/_assertionnew.py @@ -1,6 +1,6 @@ """ -Like _assertion.py but using builtin AST. It should replace _assertionold.py -eventually. +Find intermediate evalutation results in assert statements through builtin AST. +This should replace _assertionold.py eventually. """ import sys From commits-noreply at bitbucket.org Mon Jun 14 15:47:22 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 14 Jun 2010 13:47:22 +0000 (UTC) Subject: [py-svn] py-trunk commit f2e8fa331127: adding a link to Floris' new post Message-ID: <20100614134722.1A4437EFBD@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276523131 -7200 # Node ID f2e8fa33112789a60fbe700c01d7c3db08777499 # Parent ea00c9bc110e38f7595c56c667dffceb6f4c4c41 adding a link to Floris' new post --- a/doc/test/talks.txt +++ b/doc/test/talks.txt @@ -24,6 +24,7 @@ function arguments: test parametrization: - `generating parametrized tests with funcargs`_ +- `test generators and cached setup`_ - `parametrizing tests, generalized`_ (blog post) - `putting test-hooks into local or global plugins`_ (blog post) @@ -47,6 +48,7 @@ plugin specific examples: .. _`putting test-hooks into local or global plugins`: http://tetamap.wordpress.com/2009/05/14/putting-test-hooks-into-local-and-global-plugins/ .. _`parametrizing tests, generalized`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/ .. _`generating parametrized tests with funcargs`: funcargs.html#test-generators +.. _`test generators and cached setup`: http://bruynooghe.blogspot.com/2010/06/pytest-test-generators-and-cached-setup.html conference talks and tutorials ---------------------------------------- From py-svn at codespeak.net Tue Jun 15 20:23:35 2010 From: py-svn at codespeak.net (Online BrandViagra Pharmacy) Date: Tue, 15 Jun 2010 20:23:35 +0200 (CEST) Subject: [py-svn] Sent to py-svn. -75% discounts notifier. Following until Message-ID: <20100615182335.F290136C231@codespeak.net> An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Wed Jun 16 12:32:45 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 16 Jun 2010 10:32:45 +0000 (UTC) Subject: [py-svn] py-trunk commit b6f591b81c20: fix --pdb to not drop interactive on xfailed tests Message-ID: <20100616103245.E82C27F002@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276684508 -7200 # Node ID b6f591b81c20dd0cfdb743f79e07954fc8710ad3 # Parent f2e8fa33112789a60fbe700c01d7c3db08777499 fix --pdb to not drop interactive on xfailed tests --- a/py/_plugin/pytest_pdb.py +++ b/py/_plugin/pytest_pdb.py @@ -15,19 +15,21 @@ def pytest_configure(config): config.pluginmanager.register(PdbInvoke(), 'pdb') class PdbInvoke: - def pytest_runtest_makereport(self, item, call): - if call.excinfo and not \ - call.excinfo.errisinstance(py.test.skip.Exception): - # play well with capturing, slightly hackish - capman = item.config.pluginmanager.getplugin('capturemanager') - capman.suspendcapture() - - tw = py.io.TerminalWriter() - repr = call.excinfo.getrepr() - repr.toterminal(tw) - post_mortem(call.excinfo._excinfo[2]) - - capman.resumecapture_item(item) + def pytest_runtest_makereport(self, item, call, __multicall__): + if not call.excinfo or \ + call.excinfo.errisinstance(py.test.skip.Exception): + return + rep = __multicall__.execute() + if "xfail" in rep.keywords: + return rep + # we assume that the above execute() suspended capturing + tw = py.io.TerminalWriter() + tw.line() + tw.sep(">", "traceback") + rep.toterminal(tw) + tw.sep(">", "entering PDB") + post_mortem(call.excinfo._excinfo[2]) + return rep class Pdb(py.std.pdb.Pdb): def do_list(self, arg): --- a/testing/plugin/test_pytest_pdb.py +++ b/testing/plugin/test_pytest_pdb.py @@ -20,6 +20,16 @@ class TestPDB: tb = py.code.Traceback(pdblist[0][0]) assert tb[-1].name == "test_func" + def test_pdb_on_xfail(self, testdir, pdblist): + rep = testdir.inline_runsource1('--pdb', """ + import py + @py.test.mark.xfail + def test_func(): + assert 0 + """) + assert "xfail" in rep.keywords + assert not pdblist + def test_pdb_on_skip(self, testdir, pdblist): rep = testdir.inline_runsource1('--pdb', """ import py --- a/py/_test/pluginmanager.py +++ b/py/_test/pluginmanager.py @@ -6,8 +6,8 @@ import inspect from py._plugin import hookspec default_plugins = ( - "default runner capture mark terminal skipping tmpdir monkeypatch " - "recwarn pdb pastebin unittest helpconfig nose assertion genscript " + "default runner pdb capture mark terminal skipping tmpdir monkeypatch " + "recwarn pastebin unittest helpconfig nose assertion genscript " "junitxml doctest").split() def check_old_use(mod, modname): --- a/testing/pip-reqs1.txt +++ b/testing/pip-reqs1.txt @@ -1,5 +1,4 @@ docutils pygments pexpect -figleaf hg+http://bitbucket.org/hpk42/execnet#egg=execnet --- a/CHANGELOG +++ b/CHANGELOG @@ -34,6 +34,7 @@ New features Bug fixes / Maintenance ++++++++++++++++++++++++++ +- fix --pdb to ignore xfailed tests and unify its TB-reporting - fix assertion interpretation with the ** operator - fix issue105 assignment on the same line as a failing assertion - fix issue104 proper escaping for test names in junitxml plugin From commits-noreply at bitbucket.org Thu Jun 17 12:49:50 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 17 Jun 2010 10:49:50 +0000 (UTC) Subject: [py-svn] py-trunk commit 1c942fce6eaa: refine reporting with --pdb some more Message-ID: <20100617104950.7F2A07EFE8@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276772009 -7200 # Node ID 1c942fce6eaabbaa0d9e43fb50d4d6307d2f2478 # Parent b6f591b81c20dd0cfdb743f79e07954fc8710ad3 refine reporting with --pdb some more --- a/py/_plugin/pytest_pdb.py +++ b/py/_plugin/pytest_pdb.py @@ -15,6 +15,9 @@ def pytest_configure(config): config.pluginmanager.register(PdbInvoke(), 'pdb') class PdbInvoke: + def pytest_sessionfinish(self, session): + # don't display failures again at the end + session.config.option.tbstyle = "no" def pytest_runtest_makereport(self, item, call, __multicall__): if not call.excinfo or \ call.excinfo.errisinstance(py.test.skip.Exception): --- a/testing/plugin/test_pytest_pdb.py +++ b/testing/plugin/test_pytest_pdb.py @@ -50,7 +50,9 @@ class TestPDB: child.expect(".*i = 0") child.expect("(Pdb)") child.sendeof() - child.expect("1 failed") + rest = child.read() + assert "1 failed" in rest + assert "def test_1" not in rest if child.isalive(): child.wait() --- a/CHANGELOG +++ b/CHANGELOG @@ -34,7 +34,8 @@ New features Bug fixes / Maintenance ++++++++++++++++++++++++++ -- fix --pdb to ignore xfailed tests and unify its TB-reporting +- refine --pdb: ignore xfailed tests, unify its TB-reporting and + don't display failures again at the end. - fix assertion interpretation with the ** operator - fix issue105 assignment on the same line as a failing assertion - fix issue104 proper escaping for test names in junitxml plugin From commits-noreply at bitbucket.org Thu Jun 17 18:01:07 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 17 Jun 2010 16:01:07 +0000 (UTC) Subject: [py-svn] py-trunk commit c366f6ebdbde: a fix from maciej who claims this fixes issues on some systems. Message-ID: <20100617160107.4448A7F00C@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276790676 -7200 # Node ID c366f6ebdbde0d0d1b56c189f3234cd7141f2eca # Parent a9febe68a28b0833ec722f122db8fc34c46e27e3 a fix from maciej who claims this fixes issues on some systems. passes all tests so i just apply it. --- a/py/_process/cmdexec.py +++ b/py/_process/cmdexec.py @@ -18,8 +18,8 @@ def cmdexec(cmd): universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() - out = py.builtin._totext(out, sys.getdefaultencoding()) - err = py.builtin._totext(err, sys.getdefaultencoding()) + out = py.builtin._totext(out, sys.stdout.encoding) + err = py.builtin._totext(err, sys.stderr.encoding) status = process.poll() if status: raise ExecutionFailed(status, status, cmd, out, err) From commits-noreply at bitbucket.org Thu Jun 17 18:01:06 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 17 Jun 2010 16:01:06 +0000 (UTC) Subject: [py-svn] py-trunk commit a9febe68a28b: remove tox.ini for now Message-ID: <20100617160107.003627F00B@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1276773928 -7200 # Node ID a9febe68a28b0833ec722f122db8fc34c46e27e3 # Parent 1c942fce6eaabbaa0d9e43fb50d4d6307d2f2478 remove tox.ini for now --- a/tox.ini +++ /dev/null @@ -1,20 +0,0 @@ -[test] -changedir=testing -cmdargs=py.test - -n3 - --basetemp=%(envtmpdir)s - --confcutdir=.. - --junitxml=junit-%(envname)s.xml - --junitprefix=%(envname)s -deps=pytest-xdist -[testenv:py24] -python=python2.4 -[testenv:py25] -python=python2.5 -[testenv:py26] -python=python2.6 -#[testenv:jython] -#python=jython -#command=py.test-jython -n3 --basetemp=%(envtmpdir)s --confcutdir=.. --junitxml=junit-%(envname)s.xml -#[testenv:py31] -#python=python3.1 From commits-noreply at bitbucket.org Sun Jun 20 05:55:40 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 20 Jun 2010 03:55:40 +0000 (UTC) Subject: [py-svn] py-trunk commit 5c9a85575454: correct expected message Message-ID: <20100620035540.2D5367EF7B@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User Benjamin Peterson # Date 1276919706 18000 # Node ID 5c9a855754547f6fdf5b26ad794523e78e5e8675 # Parent c366f6ebdbde0d0d1b56c189f3234cd7141f2eca correct expected message --- a/testing/code/test_assertion.py +++ b/testing/code/test_assertion.py @@ -151,7 +151,7 @@ def test_power(): assert 2**3 == 7 except AssertionError: e = exvalue() - assert "assert 8 == 7" in e.msg + assert "assert (2 ** 3) == 7" in e.msg class TestView: From commits-noreply at bitbucket.org Fri Jun 25 10:28:58 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 25 Jun 2010 08:28:58 +0000 (UTC) Subject: [py-svn] py-trunk commit 6005a1fe1408: refine py.process.cmdexec handling wrt unicode on all python versions Message-ID: <20100625082858.2CFA47EF72@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1277454615 -7200 # Node ID 6005a1fe140803d14f62dd33537277ad6fd7c8f9 # Parent 5c9a855754547f6fdf5b26ad794523e78e5e8675 refine py.process.cmdexec handling wrt unicode on all python versions --- a/py/_process/cmdexec.py +++ b/py/_process/cmdexec.py @@ -8,18 +8,25 @@ import py from subprocess import Popen, PIPE def cmdexec(cmd): - """ return output of executing 'cmd' in a separate process. + """ return unicode output of executing 'cmd' in a separate process. raise cmdexec.ExecutionFailed exeception if the command failed. the exception will provide an 'err' attribute containing the error-output from the command. + if the subprocess module does not provide a proper encoding/unicode strings + sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'. """ process = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() - out = py.builtin._totext(out, sys.stdout.encoding) - err = py.builtin._totext(err, sys.stderr.encoding) + if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not + try: + default_encoding = sys.getdefaultencoding() # jython may not have it + except AttributeError: + default_encoding = sys.stdout.encoding or 'UTF-8' + out = unicode(out, process.stdout.encoding or default_encoding) + err = unicode(err, process.stderr.encoding or default_encoding) status = process.poll() if status: raise ExecutionFailed(status, status, cmd, out, err) --- a/testing/process/test_cmdexec.py +++ b/testing/process/test_cmdexec.py @@ -8,11 +8,13 @@ class Test_exec_cmd: def test_simple(self): out = cmdexec('echo hallo') assert out.strip() == 'hallo' + assert py.builtin._istext(out) def test_simple_newline(self): import sys out = cmdexec(r"""%s -c "print ('hello')" """ % sys.executable) assert out == 'hello\n' + assert py.builtin._istext(out) def test_simple_error(self): py.test.raises (cmdexec.Error, cmdexec, 'exit 1') --- a/CHANGELOG +++ b/CHANGELOG @@ -48,6 +48,8 @@ Bug fixes / Maintenance - don't print empty lines when showing junitxml-filename - add optional boolean ignore_errors parameter to py.path.local.remove - fix terminal writing on win32/python2.4 +- py.process.cmdexec() now tries harder to return properly encoded unicode objects + on all python versions Changes between 1.3.0 and 1.3.1 ================================================== From commits-noreply at bitbucket.org Fri Jun 25 20:15:13 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 25 Jun 2010 18:15:13 +0000 (UTC) Subject: [py-svn] py-trunk commit e9de6deb4da5: remove uneeded exec Message-ID: <20100625181513.D1FC27EF88@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User Benjamin Peterson # Date 1277486691 18000 # Node ID e9de6deb4da5331fc728f2cd636f8f75fbdeaebe # Parent 5c9a855754547f6fdf5b26ad794523e78e5e8675 remove uneeded exec --- a/py/_builtin.py +++ b/py/_builtin.py @@ -189,12 +189,10 @@ else: exec2(obj, globals, locals) if sys.version_info >= (3,0): - exec (""" -def _reraise(cls, val, tb): - __tracebackhide__ = True - assert hasattr(val, '__traceback__') - raise val -""") + def _reraise(cls, val, tb): + __tracebackhide__ = True + assert hasattr(val, '__traceback__') + raise val else: exec (""" def _reraise(cls, val, tb): From commits-noreply at bitbucket.org Fri Jun 25 20:15:13 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 25 Jun 2010 18:15:13 +0000 (UTC) Subject: [py-svn] py-trunk commit ccea760d64fe: merge heads Message-ID: <20100625181513.C1C167EEFF@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User Benjamin Peterson # Date 1277486744 18000 # Node ID ccea760d64fe1b086f4fb3d8481f73b320af7e59 # Parent e9de6deb4da5331fc728f2cd636f8f75fbdeaebe # Parent 6005a1fe140803d14f62dd33537277ad6fd7c8f9 merge heads From commits-noreply at bitbucket.org Mon Jun 28 01:22:15 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 27 Jun 2010 23:22:15 +0000 (UTC) Subject: [py-svn] py-trunk commit 803fa9a79e67: name CollectOnlyReporter's output attribute "_tw" for consistency with TerminalReporter Message-ID: <20100627232215.7FC2A7EF79@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User Benjamin Peterson # Date 1277680667 18000 # Node ID 803fa9a79e67f26bdcb233227e573ff4dcf43b7c # Parent ccea760d64fe1b086f4fb3d8481f73b320af7e59 name CollectOnlyReporter's output attribute "_tw" for consistency with TerminalReporter This fixes #92. --- a/py/_plugin/pytest_terminal.py +++ b/py/_plugin/pytest_terminal.py @@ -448,16 +448,16 @@ class CollectonlyReporter: self.config = config if out is None: out = py.std.sys.stdout - self.out = py.io.TerminalWriter(out) + self._tw = py.io.TerminalWriter(out) self.indent = "" self._failed = [] def outindent(self, line): - self.out.line(self.indent + str(line)) + self._tw.line(self.indent + str(line)) def pytest_internalerror(self, excrepr): for line in str(excrepr).split("\n"): - self.out.line("INTERNALERROR> " + line) + self._tw.line("INTERNALERROR> " + line) def pytest_collectstart(self, collector): self.outindent(collector) @@ -474,9 +474,9 @@ class CollectonlyReporter: def pytest_sessionfinish(self, session, exitstatus): if self._failed: - self.out.sep("!", "collection failures") + self._tw.sep("!", "collection failures") for rep in self._failed: - rep.toterminal(self.out) + rep.toterminal(self._tw) def repr_pythonversion(v=None): From commits-noreply at bitbucket.org Mon Jun 28 11:26:46 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 28 Jun 2010 09:26:46 +0000 (UTC) Subject: [py-svn] py-trunk commit 10166d87c90a: adjust changelog, add fixed issue92 Message-ID: <20100628092646.DADF87EF11@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1277717179 -7200 # Node ID 10166d87c90ab42b0948c14619859b9d762487ef # Parent 803fa9a79e67f26bdcb233227e573ff4dcf43b7c adjust changelog, add fixed issue92 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,7 +13,7 @@ New features with py.test.raises(RuntimeError) as excinfo: call_something() - # do extra checks on excinfo.value|type|traceback objects + # you may do extra checks on excinfo.value|type|traceback here (thanks Ronny Pfannschmidt) @@ -21,8 +21,8 @@ New features to all reports in the junitxml file. - Funcarg factories can now dynamically apply a marker to a - test invocation. This is particularly useful if a factory - provides parameters to a test which you expect-to-fail: + test invocation. This is for example useful if a factory + provides parameters to a test which are expected-to-fail: def pytest_funcarg__arg(request): request.applymarker(py.test.mark.xfail(reason="flaky config")) @@ -40,6 +40,7 @@ Bug fixes / Maintenance - fix issue105 assignment on the same line as a failing assertion - fix issue104 proper escaping for test names in junitxml plugin - fix issue57 -f|--looponfail to work with xpassing tests +- fix issue92 collectonly reporter and --pastebin - fix py.code.compile(source) to generate unique filenames - fix assertion re-interp problems on PyPy, by defering code compilation to the (overridable) Frame.eval class. From commits-noreply at bitbucket.org Mon Jun 28 12:01:32 2010 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 28 Jun 2010 10:01:32 +0000 (UTC) Subject: [py-svn] py-trunk commit 08462a57259b: install plain py.test script also for jython Message-ID: <20100628100132.1FE677EF21@bitbucket.org> # HG changeset patch -- Bitbucket.org # Project py-trunk # URL http://bitbucket.org/hpk42/py-trunk/overview # User holger krekel # Date 1277719152 -7200 # Node ID 08462a57259b9a0ffc1431253f4b20d5f2cc2b6b # Parent 10166d87c90ab42b0948c14619859b9d762487ef install plain py.test script also for jython --- a/bin-for-dist/test_install.py +++ b/bin-for-dist/test_install.py @@ -166,7 +166,7 @@ def test_cmdline_entrypoints(monkeypatch expected = "%s-jython" % script assert expected in points for script in unversioned_scripts: - assert script not in points + assert script in points points = cmdline_entrypoints((2,5,1), "xyz", 'pypy-c-XYZ') for script in versioned_scripts: --- a/setup.py +++ b/setup.py @@ -71,9 +71,9 @@ def cmdline_entrypoints(versioninfo, pla 'py.test-%s.%s' % versioninfo[:2] : 'py.cmdline:pytest', 'py.which-%s.%s' % versioninfo[:2] : 'py.cmdline:pywhich' } - for x in ['py.cleanup', 'py.convert_unittest', 'py.countloc', - 'py.lookup', 'py.svnwcrevert', 'py.which', 'py.test']: - points[x] = "py.cmdline:%s" % x.replace('.','') + for x in ['py.cleanup', 'py.convert_unittest', 'py.countloc', + 'py.lookup', 'py.svnwcrevert', 'py.which', 'py.test']: + points[x] = "py.cmdline:%s" % x.replace('.','') return points def make_entry_points(): --- a/CHANGELOG +++ b/CHANGELOG @@ -51,6 +51,8 @@ Bug fixes / Maintenance - fix terminal writing on win32/python2.4 - py.process.cmdexec() now tries harder to return properly encoded unicode objects on all python versions +- install plain py.test/py.which scripts also for Jython, this helps to + get canonical script paths in virtualenv situations Changes between 1.3.0 and 1.3.1 ==================================================