From 8bb589fc5dc4eafffe051d6a665c18d8c5f8c0d2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 9 Jun 2017 18:47:07 -0300 Subject: [PATCH] Fix internal error when trying to detect the start of a recursive traceback. Fix #2486 --- _pytest/_code/code.py | 7 +++++-- changelog/2486.bugfix | 1 + testing/code/test_excinfo.py | 23 +++++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 changelog/2486.bugfix diff --git a/_pytest/_code/code.py b/_pytest/_code/code.py index 9b3408dc4..5b7cc4191 100644 --- a/_pytest/_code/code.py +++ b/_pytest/_code/code.py @@ -640,8 +640,11 @@ class FormattedExcinfo(object): ).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] + if recursionindex is not None: + extraline = "!!! Recursion detected (same locals & position)" + traceback = traceback[:recursionindex + 1] + else: + extraline = None return traceback, extraline diff --git a/changelog/2486.bugfix b/changelog/2486.bugfix new file mode 100644 index 000000000..97917197c --- /dev/null +++ b/changelog/2486.bugfix @@ -0,0 +1 @@ +Fix internal error when trying to detect the start of a recursive traceback. diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 3128beff8..0b074d64a 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, division, print_function +import sys import operator import _pytest import py @@ -1173,3 +1174,25 @@ def test_exception_repr_extraction_error_on_recursion(): '*The following exception happened*', '*ValueError: The truth value of an array*', ]) + + +def test_no_recursion_index_on_recursion_error(): + """ + Ensure that we don't break in case we can't find the recursion index + during a recursion error (#2486). + """ + try: + class RecursionDepthError(object): + def __getattr__(self, attr): + return getattr(self, '_' + attr) + + RecursionDepthError().trigger + except: + from _pytest._code.code import ExceptionInfo + exc_info = ExceptionInfo() + if sys.version_info[:2] == (2, 6): + assert "'RecursionDepthError' object has no attribute '___" in str(exc_info.getrepr()) + else: + assert 'maximum recursion' in str(exc_info.getrepr()) + else: + assert 0