From eb73db56c7b8da17f5291fe0f096f6b3ceafd64c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 18 Jun 2015 21:04:47 -0300 Subject: [PATCH 1/6] Fix issue where pytest.raises() doesn't always return Exception instance in py26 Fixes #767 --- CHANGELOG | 4 ++++ _pytest/python.py | 7 +++++++ testing/python/raises.py | 1 + 3 files changed, 12 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 74fb004f6..8aa3e75d3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,10 @@ 2.7.2 (compared to 2.7.1) ----------------------------- +- fix issue767: pytest.raises value attribute does not contain the exception + instance on Python 2.6. Thanks Eric Siegerman for providing the test + case and Bruno Oliveira for PR. + - Automatically create directory for junitxml and results log. Thanks Aron Curzon. diff --git a/_pytest/python.py b/_pytest/python.py index b5f21aac7..2fa4af373 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1099,6 +1099,13 @@ class RaisesContext(object): __tracebackhide__ = True if tp[0] is None: pytest.fail("DID NOT RAISE") + if sys.version_info < (2, 7): + # py26: on __exit__() exc_value often does not contain the + # exception value. + # http://bugs.python.org/issue7853 + if not isinstance(tp[1], BaseException): + exc_type, value, traceback = tp + tp = exc_type, exc_type(value), traceback self.excinfo.__init__(tp) return issubclass(self.excinfo.type, self.ExpectedException) diff --git a/testing/python/raises.py b/testing/python/raises.py index 5caa810e2..5ba56bb71 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -46,6 +46,7 @@ class TestRaises: 1/0 print (excinfo) assert excinfo.type == ZeroDivisionError + assert isinstance(excinfo.value, ZeroDivisionError) def test_noraise(): with pytest.raises(pytest.raises.Exception): From 48d91def7e630abce1b156ee752091efa19f780a Mon Sep 17 00:00:00 2001 From: Edison Gustavo Muenz Date: Wed, 17 Jun 2015 17:31:31 -0300 Subject: [PATCH 2/6] Added workaround to still show the diff on containers with unsortable elements. fix issue #718 --- AUTHORS | 1 + CHANGELOG | 3 +++ _pytest/assertion/util.py | 16 ++++++++++++---- testing/test_assertion.py | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index bb5fec0d6..be4cd290d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -24,6 +24,7 @@ Daniel Grana Daniel Nuri Dave Hunt David Mohr +Edison Gustavo Muenz Floris Bruynooghe Graham Horler Grig Gheorghiu diff --git a/CHANGELOG b/CHANGELOG index 052454d2f..c2ac4bfa3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,9 @@ - fix issue748: unittest.SkipTest reports to internal pytest unittest plugin. Thanks Thomas De Schampheleire for reporting and Bruno Oliveira for the PR. +- fix issue718: failed to create representation of sets containing unsortable + elements in python 2. Thanks Edison Gustavo Muenz + 2.7.1 (compared to 2.7.0) ----------------------------- diff --git a/_pytest/assertion/util.py b/_pytest/assertion/util.py index 07389e781..fb5f9be0e 100644 --- a/_pytest/assertion/util.py +++ b/_pytest/assertion/util.py @@ -225,10 +225,18 @@ def _compare_eq_iterable(left, right, verbose=False): # dynamic import to speedup pytest import difflib - left = pprint.pformat(left).splitlines() - right = pprint.pformat(right).splitlines() - explanation = [u('Full diff:')] - explanation.extend(line.strip() for line in difflib.ndiff(left, right)) + try: + left_formatting = pprint.pformat(left).splitlines() + right_formatting = pprint.pformat(right).splitlines() + explanation = [u('Full diff:')] + except Exception: + # hack: PrettyPrinter.pformat() in python 2 fails when formatting items that can't be sorted(), ie, calling + # sorted() on a list would raise. See issue #718. + # As a workaround, the full diff is generated by using the repr() string of each item of each container. + left_formatting = sorted(repr(x) for x in left) + right_formatting = sorted(repr(x) for x in right) + explanation = [u('Full diff (fallback to calling repr on each item):')] + explanation.extend(line.strip() for line in difflib.ndiff(left_formatting, right_formatting)) return explanation diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 1cf00dfed..e8063f0d3 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -569,3 +569,39 @@ def test_AssertionError_message(testdir): *assert 0, (x,y)* *AssertionError: (1, 2)* """) + +@pytest.mark.skipif(PY3, reason='This bug does not exist on PY3') +def test_set_with_unsortable_elements(): + # issue #718 + class UnsortableKey(object): + def __init__(self, name): + self.name = name + + def __lt__(self, other): + raise RuntimeError() + + def __repr__(self): + return 'repr({0})'.format(self.name) + + def __eq__(self, other): + return self.name == other.name + + def __hash__(self): + return hash(self.name) + + left_set = set(UnsortableKey(str(i)) for i in range(1, 3)) + right_set = set(UnsortableKey(str(i)) for i in range(2, 4)) + expl = callequal(left_set, right_set, verbose=True) + # skip first line because it contains the "construction" of the set, which does not have a guaranteed order + expl = expl[1:] + dedent = textwrap.dedent(""" + Extra items in the left set: + repr(1) + Extra items in the right set: + repr(3) + Full diff (fallback to calling repr on each item): + - repr(1) + repr(2) + + repr(3) + """).strip() + assert '\n'.join(expl) == dedent From 898b63b6656cbf150fb397118a6ad8a27572e232 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 22 Jun 2015 11:34:00 +0200 Subject: [PATCH 3/6] change spelling, thanks Maciej Maciaszek --- doc/en/goodpractises.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/goodpractises.txt b/doc/en/goodpractises.txt index 31979618a..ecb938078 100644 --- a/doc/en/goodpractises.txt +++ b/doc/en/goodpractises.txt @@ -1,7 +1,7 @@ .. highlightlang:: python .. _`goodpractises`: -Good Integration Practises +Good Integration Practices ================================================= Work with virtual environments From cdd25c951272227c324f0b8560e44d38d4a88ebf Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 22 Jun 2015 23:53:41 +0200 Subject: [PATCH 4/6] bump version to 2.7, depend on py-1.4.29 --- CHANGELOG | 4 ++++ _pytest/__init__.py | 2 +- setup.py | 10 +++++----- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 73c34dafa..1023fd95f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -23,6 +23,10 @@ - fix issue718: failed to create representation of sets containing unsortable elements in python 2. Thanks Edison Gustavo Muenz +- fix issue756, fix issue752 (and similar issues): depend on py-1.4.29 + which has a refined algorithm for traceback generation. + + 2.7.1 (compared to 2.7.0) ----------------------------- diff --git a/_pytest/__init__.py b/_pytest/__init__.py index 6cf1b5e15..a521e0f8a 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '2.7.1' +__version__ = '2.7.2' diff --git a/setup.py b/setup.py index 5af27b1f5..9cf1ed72a 100644 --- a/setup.py +++ b/setup.py @@ -31,12 +31,12 @@ def get_version(): def has_environment_marker_support(): """ Tests that setuptools has support for PEP-426 environment marker support. - - The first known release to support it is 0.7 (and the earliest on PyPI seems to be 0.7.2 + + The first known release to support it is 0.7 (and the earliest on PyPI seems to be 0.7.2 so we're using that), see: http://pythonhosted.org/setuptools/history.html#id142 - + References: - + * https://wheel.readthedocs.org/en/latest/index.html#defining-conditional-dependencies * https://www.python.org/dev/peps/pep-0426/#environment-markers """ @@ -48,7 +48,7 @@ def has_environment_marker_support(): def main(): - install_requires = ['py>=1.4.25'] + install_requires = ['py>=1.4.29'] extras_require = {} if has_environment_marker_support(): extras_require[':python_version=="2.6" or python_version=="3.0" or python_version=="3.1"'] = ['argparse'] From 01d067ec2b2142782b7102aa73fe8c095a2e269a Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 23 Jun 2015 09:56:25 +0200 Subject: [PATCH 5/6] Check conftest.py is not loaded with --confcutdir. The test creates a conftest.py with "assert 0" which never should be loaded. However, if it were loaded, the test would still pass as it never checks if it was loaded or not. See #799. --- testing/test_conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/test_conftest.py b/testing/test_conftest.py index bff68e6d2..82ed00b3b 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -171,6 +171,7 @@ def test_conftest_confcutdir(testdir): """)) result = testdir.runpytest("-h", "--confcutdir=%s" % x, x) result.stdout.fnmatch_lines(["*--xyz*"]) + assert 'warning: could not load initial' not in result.stdout.str() def test_conftest_existing_resultlog(testdir): x = testdir.mkdir("tests") From e84c00efae4fc8841cf5974c0fa68fc043e50a22 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 23 Jun 2015 16:31:24 +0200 Subject: [PATCH 6/6] finish pytest-2.7.2 release --- doc/en/announce/release-2.7.2.txt | 58 +++++++++++++++++++++++++ testing/conftest.py | 6 ++- tox.ini | 71 ++++++++++--------------------- 3 files changed, 85 insertions(+), 50 deletions(-) create mode 100644 doc/en/announce/release-2.7.2.txt diff --git a/doc/en/announce/release-2.7.2.txt b/doc/en/announce/release-2.7.2.txt new file mode 100644 index 000000000..69130ad62 --- /dev/null +++ b/doc/en/announce/release-2.7.2.txt @@ -0,0 +1,58 @@ +pytest-2.7.2: bug fixes +======================= + +pytest is a mature Python testing tool with more than a 1100 tests +against itself, passing on many different interpreters and platforms. +This release is supposed to be drop-in compatible to 2.7.1. + +See below for the changes and see docs at: + + http://pytest.org + +As usual, you can upgrade from pypi via:: + + pip install -U pytest + +Thanks to all who contributed to this release, among them: + + Bruno Oliveira + Floris Bruynooghe + Punyashloka Biswal + Aron Curzon + Benjamin Peterson + Thomas De Schampheleire + Edison Gustavo Muenz + Holger Krekel + +Happy testing, +The py.test Development Team + + +2.7.2 (compared to 2.7.1) +----------------------------- + +- fix issue767: pytest.raises value attribute does not contain the exception + instance on Python 2.6. Thanks Eric Siegerman for providing the test + case and Bruno Oliveira for PR. + +- Automatically create directory for junitxml and results log. + Thanks Aron Curzon. + +- fix issue713: JUnit XML reports for doctest failures. + Thanks Punyashloka Biswal. + +- fix issue735: assertion failures on debug versions of Python 3.4+ + Thanks Benjamin Peterson. + +- fix issue114: skipif marker reports to internal skipping plugin; + Thanks Floris Bruynooghe for reporting and Bruno Oliveira for the PR. + +- fix issue748: unittest.SkipTest reports to internal pytest unittest plugin. + Thanks Thomas De Schampheleire for reporting and Bruno Oliveira for the PR. + +- fix issue718: failed to create representation of sets containing unsortable + elements in python 2. Thanks Edison Gustavo Muenz + +- fix issue756, fix issue752 (and similar issues): depend on py-1.4.29 + which has a refined algorithm for traceback generation. + diff --git a/testing/conftest.py b/testing/conftest.py index 8bf467866..7ebfccd79 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -3,17 +3,19 @@ import sys pytest_plugins = "pytester", -import os, py +import os, py, gc class LsofFdLeakChecker(object): def get_open_files(self): + gc.collect() out = self._exec_lsof() open_files = self._parse_lsof_output(out) return open_files def _exec_lsof(self): pid = os.getpid() - return py.process.cmdexec("lsof -Ffn0 -p %d" % pid) + #return py.process.cmdexec("lsof -Ffn0 -p %d" % pid) + return py.process.cmdexec("lsof -p %d" % pid) def _parse_lsof_output(self, out): def isopen(line): diff --git a/tox.ini b/tox.ini index 0e315c03b..b0afd479a 100644 --- a/tox.ini +++ b/tox.ini @@ -1,84 +1,71 @@ [tox] +minversion=2.0 distshare={homedir}/.tox/distshare -envlist=flakes,py26,py27,py34,pypy,py27-pexpect,py33-pexpect,py27-nobyte,py33,py27-xdist,py33-xdist,py27-trial,py33-trial,doctesting,py27-cxfreeze +envlist= + flakes,py26,py27,py33,py34,pypy, + {py27,py34}-{pexpect,xdist,trial}, + py27-nobyte,doctesting,py27-cxfreeze [testenv] -changedir=testing -commands= py.test --lsof -rfsxX --junitxml={envlogdir}/junit-{envname}.xml [] +commands= py.test --lsof -rfsxX {posargs:testing} deps= nose mock [testenv:genscript] -changedir=. commands= py.test --genscript=pytest1 [testenv:flakes] -changedir= deps = pytest-flakes>=0.2 commands = py.test --flakes -m flakes _pytest testing [testenv:py27-xdist] -changedir=. -basepython=python2.7 deps=pytest-xdist mock nose commands= - py.test -n1 -rfsxX \ - --junitxml={envlogdir}/junit-{envname}.xml {posargs:testing} + py.test -n1 -rfsxX {posargs:testing} -[testenv:py33-xdist] -changedir=. -basepython=python3.3 +[testenv:py34-xdist] deps={[testenv:py27-xdist]deps} commands= - py.test -n3 -rfsxX \ - --junitxml={envlogdir}/junit-{envname}.xml testing + py.test -n3 -rfsxX testing [testenv:py27-pexpect] changedir=testing -basepython=python2.7 +platform=linux|darwin deps=pexpect commands= py.test -rfsxX test_pdb.py test_terminal.py test_unittest.py -[testenv:py33-pexpect] +[testenv:py34-pexpect] changedir=testing -basepython=python3.3 +platform=linux|darwin deps={[testenv:py27-pexpect]deps} commands= py.test -rfsxX test_pdb.py test_terminal.py test_unittest.py [testenv:py27-nobyte] -changedir=. -basepython=python2.7 deps=pytest-xdist distribute=true setenv= PYTHONDONTWRITEBYTECODE=1 commands= - py.test -n3 -rfsxX \ - --junitxml={envlogdir}/junit-{envname}.xml {posargs:testing} + py.test -n3 -rfsxX {posargs:testing} [testenv:py27-trial] -changedir=. -basepython=python2.7 deps=twisted commands= - py.test -rsxf \ - --junitxml={envlogdir}/junit-{envname}.xml {posargs:testing/test_unittest.py} + py.test -rsxf {posargs:testing/test_unittest.py} -[testenv:py33-trial] -changedir=. -basepython=python3.3 +[testenv:py34-trial] +# py34-trial does not work +platform=linux|darwin deps={[testenv:py27-trial]deps} commands= - py.test -rsxf \ - --junitxml={envlogdir}/junit-{envname}.xml {posargs:testing/test_unittest.py} + py.test -rsxf {posargs:testing/test_unittest.py} [testenv:doctest] -changedir=. commands=py.test --doctest-modules _pytest deps= @@ -94,13 +81,11 @@ commands= make html [testenv:doctesting] -basepython=python3.3 changedir=doc/en deps=PyYAML -commands= py.test -rfsxX --junitxml={envlogdir}/junit-{envname}.xml [] +commands= py.test -rfsxX {posargs} [testenv:regen] -basepython=python3.4 changedir=doc/en deps=sphinx PyYAML @@ -109,32 +94,22 @@ commands= #pip install pytest==2.3.4 make regen -[testenv:py31] -deps=nose>=1.0 - -[testenv:py31-xdist] -deps=pytest-xdist -commands= - py.test -n3 -rfsxX \ - --junitxml={envlogdir}/junit-{envname}.xml [] - [testenv:jython] changedir=testing commands= - {envpython} {envbindir}/py.test-jython \ - -rfsxX --junitxml={envlogdir}/junit-{envname}2.xml [] + {envpython} {envbindir}/py.test-jython -rfsxX {posargs} [testenv:py27-cxfreeze] changedir=testing/cx_freeze -basepython=python2.7 +platform=linux|darwin commands= {envpython} install_cx_freeze.py {envpython} runtests_setup.py build --build-exe build {envpython} tox_run.py + [testenv:coveralls] changedir=testing -basepython=python3.4 deps = {[testenv]deps} coveralls @@ -154,4 +129,4 @@ python_files=test_*.py *_test.py testing/*/*.py python_classes=Test Acceptance python_functions=test pep8ignore = E401 E225 E261 E128 E124 E302 -norecursedirs = .tox ja .hg +norecursedirs = .tox ja .hg cx_freeze_source