Skip to content

Commit 7ce5873

Browse files
committed
Perform a "unicode aware" check for maximum recursion depth error
Avoid errors `UnicodeErrosr`s due non maximum recursion depth errors when checking for those errors.
1 parent 0eb80bc commit 7ce5873

File tree

4 files changed

+40
-4
lines changed

4 files changed

+40
-4
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Marc Schlaich
6161
Mark Abramowitz
6262
Markus Unterwaditzer
6363
Martijn Faassen
64+
Martin Prusse
6465
Matt Bachmann
6566
Michael Aquilina
6667
Michael Birtwell

CHANGELOG.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
*
99

10+
* Fix maximum recursion depth detection when raised error class is not aware
11+
of unicode/encoded bytes.
12+
Thanks `@prusse-martin`_ for the PR (`#1506`_).
13+
1014
* Fix ``pytest.mark.skip`` mark when used in strict mode.
1115
Thanks `@pquentin`_ for the PR and `@RonnyPfannschmidt`_ for
1216
showing how to fix the bug.
@@ -15,6 +19,11 @@
1519
Thanks `@omarkohl`_ for the PR.
1620

1721

22+
.. _#1506: https://github.com/pytest-dev/pytest/pull/1506
23+
24+
.. _@prusse-martin: https://github.com/prusse-martin
25+
26+
1827
2.9.1
1928
=====
2029

_pytest/_code/code.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -579,9 +579,8 @@ def repr_traceback(self, excinfo):
579579
if self.tbfilter:
580580
traceback = traceback.filter()
581581
recursionindex = None
582-
if excinfo.errisinstance(RuntimeError):
583-
if "maximum recursion depth exceeded" in str(excinfo.value):
584-
recursionindex = traceback.recursionindex()
582+
if is_recursion_error(excinfo):
583+
recursionindex = traceback.recursionindex()
585584
last = traceback[-1]
586585
entries = []
587586
extraline = None
@@ -793,3 +792,14 @@ def getrawcode(obj, trycall=True):
793792
return x
794793
return obj
795794

795+
if sys.version_info[:2] >= (3, 5): # RecursionError introduced in 3.5
796+
def is_recursion_error(excinfo):
797+
return excinfo.errisinstance(RecursionError) # noqa
798+
else:
799+
def is_recursion_error(excinfo):
800+
if not excinfo.errisinstance(RuntimeError):
801+
return False
802+
try:
803+
return "maximum recursion depth exceeded" in str(excinfo.value)
804+
except UnicodeError:
805+
return False

testing/code/test_excinfo.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import _pytest
44
import py
55
import pytest
6-
from _pytest._code.code import FormattedExcinfo, ReprExceptionInfo
6+
from _pytest._code.code import ExceptionInfo, FormattedExcinfo, ReprExceptionInfo
77

88
queue = py.builtin._tryimport('queue', 'Queue')
99

@@ -909,3 +909,19 @@ def i():
909909
assert tw.lines[14] == "E ValueError"
910910
assert tw.lines[15] == ""
911911
assert tw.lines[16].endswith("mod.py:9: ValueError")
912+
913+
914+
@pytest.mark.parametrize("style", ["short", "long"])
915+
@pytest.mark.parametrize("encoding", [None, "utf8", "utf16"])
916+
def test_repr_traceback_with_unicode(style, encoding):
917+
msg = u'☹'
918+
if encoding is not None:
919+
msg = msg.encode(encoding)
920+
try:
921+
raise RuntimeError(msg)
922+
except RuntimeError:
923+
e_info = ExceptionInfo()
924+
formatter = FormattedExcinfo(style=style)
925+
repr_traceback = formatter.repr_traceback(e_info)
926+
assert repr_traceback is not None
927+

0 commit comments

Comments
 (0)