diff --git a/AUTHORS b/AUTHORS index 85d5c0c59..e076b53aa 100644 --- a/AUTHORS +++ b/AUTHORS @@ -62,6 +62,7 @@ Marc Schlaich Mark Abramowitz Markus Unterwaditzer Martijn Faassen +Martin Prusse Matt Bachmann Matt Williams Michael Aquilina diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 33104652a..42ed25f4c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -11,7 +11,7 @@ for a fixture (to solve the funcarg-shadowing-fixture problem). Thanks `@novas0x2a`_ for the complete PR (`#1444`_). -* New ``approx()`` function for easily comparing floating-point numbers in +* New ``approx()`` function for easily comparing floating-point numbers in tests. Thanks `@kalekundert`_ for the complete PR (`#1441`_). @@ -77,6 +77,10 @@ * +* Fix maximum recursion depth detection when raised error class is not aware + of unicode/encoded bytes. + Thanks `@prusse-martin`_ for the PR (`#1506`_). + * Fix ``pytest.mark.skip`` mark when used in strict mode. Thanks `@pquentin`_ for the PR and `@RonnyPfannschmidt`_ for showing how to fix the bug. @@ -85,6 +89,11 @@ Thanks `@omarkohl`_ for the PR. +.. _#1506: https://github.com/pytest-dev/pytest/pull/1506 + +.. _@prusse-martin: https://github.com/prusse-martin + + 2.9.1 ===== @@ -140,7 +149,7 @@ ``xfail_strict`` ini option that can be used to configure it project-wise. Thanks `@rabbbit`_ for the request and `@nicoddemus`_ for the PR (`#1355`_). -* ``Parser.addini`` now supports options of type ``bool``. +* ``Parser.addini`` now supports options of type ``bool``. Thanks `@nicoddemus`_ for the PR. * New ``ALLOW_BYTES`` doctest option. This strips ``b`` prefixes from byte strings @@ -151,25 +160,25 @@ Fixes `#1366`_. Thanks to `@hpk42`_ for the report and `@RonnyPfannschmidt`_ for the PR. -* Catch ``IndexError`` exceptions when getting exception source location. +* Catch ``IndexError`` exceptions when getting exception source location. Fixes a pytest internal error for dynamically generated code (fixtures and tests) where source lines are fake by intention. **Changes** * **Important**: `py.code `_ has been - merged into the ``pytest`` repository as ``pytest._code``. This decision - was made because ``py.code`` had very few uses outside ``pytest`` and the - fact that it was in a different repository made it difficult to fix bugs on + merged into the ``pytest`` repository as ``pytest._code``. This decision + was made because ``py.code`` had very few uses outside ``pytest`` and the + fact that it was in a different repository made it difficult to fix bugs on its code in a timely manner. The team hopes with this to be able to better refactor out and improve that code. This change shouldn't affect users, but it is useful to let users aware if they encounter any strange behavior. - - Keep in mind that the code for ``pytest._code`` is **private** and + + Keep in mind that the code for ``pytest._code`` is **private** and **experimental**, so you definitely should not import it explicitly! - Please note that the original ``py.code`` is still available in + Please note that the original ``py.code`` is still available in `pylib `_. * ``pytest_enter_pdb`` now optionally receives the pytest config object. @@ -238,7 +247,6 @@ .. _@RonnyPfannschmidt: https://github.com/RonnyPfannschmidt .. _@rabbbit: https://github.com/rabbbit .. _@hackebrot: https://github.com/hackebrot -.. _@omarkohl: https://github.com/omarkohl .. _@pquentin: https://github.com/pquentin 2.8.7 @@ -263,7 +271,7 @@ - fix #1292: monkeypatch calls (setattr, setenv, etc.) are now O(1). Thanks David R. MacIver for the report and Bruno Oliveira for the PR. -- fix #1223: captured stdout and stderr are now properly displayed before +- fix #1223: captured stdout and stderr are now properly displayed before entering pdb when ``--pdb`` is used instead of being thrown away. Thanks Cal Leeming for the PR. @@ -338,8 +346,8 @@ Thanks Gabriel Reis for the PR. - add more talks to the documentation -- extend documentation on the --ignore cli option -- use pytest-runner for setuptools integration +- extend documentation on the --ignore cli option +- use pytest-runner for setuptools integration - minor fixes for interaction with OS X El Capitan system integrity protection (thanks Florian) diff --git a/_pytest/_code/code.py b/_pytest/_code/code.py index feb69f9e6..8c3370f32 100644 --- a/_pytest/_code/code.py +++ b/_pytest/_code/code.py @@ -603,9 +603,8 @@ class FormattedExcinfo(object): if self.tbfilter: traceback = traceback.filter() recursionindex = None - if excinfo.errisinstance(RuntimeError): - if "maximum recursion depth exceeded" in str(excinfo.value): - recursionindex = traceback.recursionindex() + if is_recursion_error(excinfo): + recursionindex = traceback.recursionindex() last = traceback[-1] entries = [] extraline = None @@ -867,3 +866,14 @@ def getrawcode(obj, trycall=True): return x return obj +if sys.version_info[:2] >= (3, 5): # RecursionError introduced in 3.5 + def is_recursion_error(excinfo): + return excinfo.errisinstance(RecursionError) # noqa +else: + def is_recursion_error(excinfo): + if not excinfo.errisinstance(RuntimeError): + return False + try: + return "maximum recursion depth exceeded" in str(excinfo.value) + except UnicodeError: + return False diff --git a/_pytest/mark.py b/_pytest/mark.py index 1a7635402..d8b60def3 100644 --- a/_pytest/mark.py +++ b/_pytest/mark.py @@ -58,7 +58,7 @@ pytest_cmdline_main.tryfirst = True def pytest_collection_modifyitems(items, config): - keywordexpr = config.option.keyword + keywordexpr = config.option.keyword.lstrip() matchexpr = config.option.markexpr if not keywordexpr and not matchexpr: return diff --git a/doc/en/usage.rst b/doc/en/usage.rst index 9eeb3ec09..f9add12ab 100644 --- a/doc/en/usage.rst +++ b/doc/en/usage.rst @@ -158,7 +158,7 @@ To get a list of the slowest 10 test durations:: Creating JUnitXML format files ---------------------------------------------------- -To create result files which can be read by Hudson_ or other Continuous +To create result files which can be read by Jenkins_ or other Continuous integration servers, use this invocation:: py.test --junitxml=path diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 9c7fb4c88..0c9d58885 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -671,6 +671,11 @@ class TestDurations: "*call*test_1*", ]) + def test_with_not(self, testdir): + testdir.makepyfile(self.source) + result = testdir.runpytest("-k not 1") + assert result.ret == 0 + class TestDurationWithFixture: source = """ diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 1d15a852b..d519dc01e 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -4,8 +4,11 @@ import operator import _pytest import py import pytest -from _pytest._code.code import (FormattedExcinfo, ReprExceptionInfo, - ExceptionChainRepr) +from _pytest._code.code import ( + ExceptionInfo, + FormattedExcinfo, + ReprExceptionInfo, + ExceptionChainRepr) queue = py.builtin._tryimport('queue', 'Queue') @@ -1048,3 +1051,18 @@ raise ValueError() assert tw.lines[40] == "E AttributeError" assert tw.lines[41] == "" assert tw.lines[42].endswith("mod.py:15: AttributeError") + + +@pytest.mark.parametrize("style", ["short", "long"]) +@pytest.mark.parametrize("encoding", [None, "utf8", "utf16"]) +def test_repr_traceback_with_unicode(style, encoding): + msg = u'☹' + if encoding is not None: + msg = msg.encode(encoding) + try: + raise RuntimeError(msg) + except RuntimeError: + e_info = ExceptionInfo() + formatter = FormattedExcinfo(style=style) + repr_traceback = formatter.repr_traceback(e_info) + assert repr_traceback is not None