Merge remote-tracking branch 'upstream/master' into features
This commit is contained in:
commit
467c526307
|
@ -8,6 +8,38 @@
|
|||
|
||||
.. towncrier release notes start
|
||||
|
||||
Pytest 3.1.2 (2017-06-08)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- Required options added via ``pytest_addoption`` will no longer prevent using
|
||||
--help without passing them. (#1999)
|
||||
|
||||
- Respect ``python_files`` in assertion rewriting. (#2121)
|
||||
|
||||
- Fix recursion error detection when frames in the traceback contain objects
|
||||
that can't be compared (like ``numpy`` arrays). (#2459)
|
||||
|
||||
- ``UnicodeWarning`` is issued from the internal pytest warnings plugin only
|
||||
when the message contains non-ascii unicode (Python 2 only). (#2463)
|
||||
|
||||
- Added a workaround for Python 3.6 WindowsConsoleIO breaking due to Pytests's
|
||||
FDCapture. Other code using console handles might still be affected by the
|
||||
very same issue and might require further workarounds/fixes, i.e. colorama.
|
||||
(#2467)
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- Fix internal API links to ``pluggy`` objects. (#2331)
|
||||
|
||||
- Make it clear that ``pytest.xfail`` stops test execution at the calling point
|
||||
and improve overall flow of the ``skipping`` docs. (#810)
|
||||
|
||||
|
||||
Pytest 3.1.1 (2017-05-30)
|
||||
=========================
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import sys
|
|||
from inspect import CO_VARARGS, CO_VARKEYWORDS
|
||||
import re
|
||||
from weakref import ref
|
||||
from _pytest.compat import _PY2, _PY3, PY35
|
||||
from _pytest.compat import _PY2, _PY3, PY35, safe_str
|
||||
|
||||
import py
|
||||
builtin_repr = repr
|
||||
|
@ -602,21 +602,48 @@ class FormattedExcinfo(object):
|
|||
traceback = excinfo.traceback
|
||||
if self.tbfilter:
|
||||
traceback = traceback.filter()
|
||||
recursionindex = None
|
||||
|
||||
if is_recursion_error(excinfo):
|
||||
recursionindex = traceback.recursionindex()
|
||||
traceback, extraline = self._truncate_recursive_traceback(traceback)
|
||||
else:
|
||||
extraline = None
|
||||
|
||||
last = traceback[-1]
|
||||
entries = []
|
||||
extraline = None
|
||||
for index, entry in enumerate(traceback):
|
||||
einfo = (last == entry) and excinfo or None
|
||||
reprentry = self.repr_traceback_entry(entry, einfo)
|
||||
entries.append(reprentry)
|
||||
if index == recursionindex:
|
||||
extraline = "!!! Recursion detected (same locals & position)"
|
||||
break
|
||||
return ReprTraceback(entries, extraline, style=self.style)
|
||||
|
||||
def _truncate_recursive_traceback(self, traceback):
|
||||
"""
|
||||
Truncate the given recursive traceback trying to find the starting point
|
||||
of the recursion.
|
||||
|
||||
The detection is done by going through each traceback entry and finding the
|
||||
point in which the locals of the frame are equal to the locals of a previous frame (see ``recursionindex()``.
|
||||
|
||||
Handle the situation where the recursion process might raise an exception (for example
|
||||
comparing numpy arrays using equality raises a TypeError), in which case we do our best to
|
||||
warn the user of the error and show a limited traceback.
|
||||
"""
|
||||
try:
|
||||
recursionindex = traceback.recursionindex()
|
||||
except Exception as e:
|
||||
max_frames = 10
|
||||
extraline = (
|
||||
'!!! Recursion error detected, but an error occurred locating the origin of recursion.\n'
|
||||
' The following exception happened when comparing locals in the stack frame:\n'
|
||||
' {exc_type}: {exc_msg}\n'
|
||||
' Displaying first and last {max_frames} stack frames out of {total}.'
|
||||
).format(exc_type=type(e).__name__, exc_msg=safe_str(e), max_frames=max_frames, total=len(traceback))
|
||||
traceback = traceback[:max_frames] + traceback[-max_frames:]
|
||||
else:
|
||||
extraline = "!!! Recursion detected (same locals & position)"
|
||||
traceback = traceback[:recursionindex + 1]
|
||||
|
||||
return traceback, extraline
|
||||
|
||||
def repr_excinfo(self, excinfo):
|
||||
if _PY2:
|
||||
|
|
|
@ -66,8 +66,9 @@ def catch_warnings_for_item(item):
|
|||
unicode_warning = False
|
||||
|
||||
if compat._PY2 and any(isinstance(m, compat.UNICODE_TYPES) for m in warn_msg.args):
|
||||
warn_msg.args = [compat.safe_str(m) for m in warn_msg.args]
|
||||
unicode_warning = True
|
||||
new_args = [compat.safe_str(m) for m in warn_msg.args]
|
||||
unicode_warning = warn_msg.args != new_args
|
||||
warn_msg.args = new_args
|
||||
|
||||
msg = warnings.formatwarning(
|
||||
warn_msg, warning.category,
|
||||
|
@ -76,8 +77,8 @@ def catch_warnings_for_item(item):
|
|||
|
||||
if unicode_warning:
|
||||
warnings.warn(
|
||||
"This warning %s is broken as it's message is not a str instance"
|
||||
"(after all this is a stdlib problem workaround)" % msg,
|
||||
"Warning is using unicode non convertible to ascii, "
|
||||
"converting to a safe representation:\n %s" % msg,
|
||||
UnicodeWarning)
|
||||
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
Required options added via ``pytest_addoption`` will no longer prevent
|
||||
using --help without passing them.
|
|
@ -1 +0,0 @@
|
|||
Respect ``python_files`` in assertion rewriting.
|
|
@ -1 +0,0 @@
|
|||
Fix internal API links to ``pluggy`` objects.
|
|
@ -1,3 +0,0 @@
|
|||
Added a workaround for Python 3.6 WindowsConsoleIO breaking due to Pytests's
|
||||
FDCapture. Other code using console handles might still be affected by the
|
||||
very same issue and might require further workarounds/fixes, i.e. colorama.
|
|
@ -1 +0,0 @@
|
|||
Make it clear that ``pytest.xfail`` stops test execution at the calling point and improve overall flow of the ``skipping`` docs.
|
|
@ -6,6 +6,7 @@ Release announcements
|
|||
:maxdepth: 2
|
||||
|
||||
|
||||
release-3.1.2
|
||||
release-3.1.1
|
||||
release-3.1.0
|
||||
release-3.0.7
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
pytest-3.1.2
|
||||
=======================================
|
||||
|
||||
pytest 3.1.2 has just been released to PyPI.
|
||||
|
||||
This is a bug-fix release, being a drop-in replacement. To upgrade::
|
||||
|
||||
pip install --upgrade pytest
|
||||
|
||||
The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Andreas Pelme
|
||||
* ApaDoctor
|
||||
* Bruno Oliveira
|
||||
* Florian Bruhin
|
||||
* Ronny Pfannschmidt
|
||||
* Segev Finer
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
|
@ -322,8 +322,6 @@ Running it with the report-on-xfail option gives this output::
|
|||
|
||||
======= 7 xfailed in 0.12 seconds ========
|
||||
|
||||
|
||||
|
||||
.. _`skip/xfail with parametrize`:
|
||||
|
||||
Skip/xfail with parametrize
|
||||
|
|
|
@ -1140,3 +1140,36 @@ def test_cwd_deleted(testdir):
|
|||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['* 1 failed in *'])
|
||||
assert 'INTERNALERROR' not in result.stdout.str() + result.stderr.str()
|
||||
|
||||
|
||||
def test_exception_repr_extraction_error_on_recursion():
|
||||
"""
|
||||
Ensure we can properly detect a recursion error even
|
||||
if some locals raise error on comparision (#2459).
|
||||
"""
|
||||
class numpy_like(object):
|
||||
|
||||
def __eq__(self, other):
|
||||
if type(other) is numpy_like:
|
||||
raise ValueError('The truth value of an array '
|
||||
'with more than one element is ambiguous.')
|
||||
|
||||
def a(x):
|
||||
return b(numpy_like())
|
||||
|
||||
def b(x):
|
||||
return a(numpy_like())
|
||||
|
||||
try:
|
||||
a(numpy_like())
|
||||
except:
|
||||
from _pytest._code.code import ExceptionInfo
|
||||
from _pytest.pytester import LineMatcher
|
||||
exc_info = ExceptionInfo()
|
||||
|
||||
matcher = LineMatcher(str(exc_info.getrepr()).splitlines())
|
||||
matcher.fnmatch_lines([
|
||||
'!!! Recursion error detected, but an error occurred locating the origin of recursion.',
|
||||
'*The following exception happened*',
|
||||
'*ValueError: The truth value of an array*',
|
||||
])
|
||||
|
|
|
@ -161,7 +161,7 @@ def test_py2_unicode(testdir, pyfile_with_warnings):
|
|||
|
||||
'*test_py2_unicode.py:8: UserWarning: \u6d4b\u8bd5',
|
||||
'*warnings.warn(u"\u6d4b\u8bd5")',
|
||||
'*warnings.py:*: UnicodeWarning: This warning*\u6d4b\u8bd5',
|
||||
'*warnings.py:*: UnicodeWarning: Warning is using unicode non*',
|
||||
'* 1 passed, 2 warnings*',
|
||||
])
|
||||
|
||||
|
|
Loading…
Reference in New Issue