From aaa53d22b2f4d09fff19503c4f91992db1e7f1c0 Mon Sep 17 00:00:00 2001 From: Kodi Arfer Date: Tue, 4 Apr 2023 09:18:04 -0400 Subject: [PATCH 1/3] FormattedExcinfo.get_source: Avoid a crash when source.lines == 0 pytest could crash given pathological AST position attributes, which shouldn't happen when testing real Python code, but could happen when testing AST produced by e.g. Hylang. --- changelog/10840.improvement.rst | 1 + src/_pytest/_code/code.py | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 changelog/10840.improvement.rst diff --git a/changelog/10840.improvement.rst b/changelog/10840.improvement.rst new file mode 100644 index 00000000000..485f46cecd3 --- /dev/null +++ b/changelog/10840.improvement.rst @@ -0,0 +1 @@ +pytest should no longer crash on AST with pathological position attributes. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index e375fb70c44..032b83beb02 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -743,11 +743,13 @@ def get_source( ) -> List[str]: """Return formatted and marked up source lines.""" lines = [] - if source is None or line_index >= len(source.lines): + if source is not None and line_index < 0: + line_index += len(source) + if source is None or line_index >= len(source.lines) or line_index < 0: + # `line_index` could still be outside `range(len(source.lines))` if + # we're processing AST with pathological position attributes. source = Source("???") line_index = 0 - if line_index < 0: - line_index += len(source) space_prefix = " " if short: lines.append(space_prefix + source.lines[line_index].strip()) From cd97c110ca88a947dc5bd3af66bf110697f7d3e8 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 4 Apr 2023 11:53:21 -0300 Subject: [PATCH 2/3] Update changelog/10840.improvement.rst --- changelog/10840.improvement.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/10840.improvement.rst b/changelog/10840.improvement.rst index 485f46cecd3..17be0d07b06 100644 --- a/changelog/10840.improvement.rst +++ b/changelog/10840.improvement.rst @@ -1 +1 @@ -pytest should no longer crash on AST with pathological position attributes. +pytest should no longer crash on AST with pathological position attributes, for example testing AST produced by `Hylang __`. From c57a9527cf10f30418e6f4c5f2083972e453e9e4 Mon Sep 17 00:00:00 2001 From: Jake VanderPlas Date: Tue, 4 Apr 2023 16:58:56 -0700 Subject: [PATCH 3/3] Test when line number is out-of-bounds and negative --- AUTHORS | 1 + testing/code/test_excinfo.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/AUTHORS b/AUTHORS index 05823646188..1aa5265e62e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -163,6 +163,7 @@ Ionuț Turturică Itxaso Aizpurua Iwan Briquemont Jaap Broekhuizen +Jake VanderPlas Jakob van Santen Jakub Mitoraj James Bourbeau diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 3607501a84e..918c972762b 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -461,6 +461,24 @@ def f(x): assert lines[0] == "| def f(x):" assert lines[1] == " pass" + def test_repr_source_out_of_bounds(self): + pr = FormattedExcinfo() + source = _pytest._code.Source( + """\ + def f(x): + pass + """ + ).strip() + pr.flow_marker = "|" # type: ignore[misc] + + lines = pr.get_source(source, 100) + assert len(lines) == 1 + assert lines[0] == "| ???" + + lines = pr.get_source(source, -100) + assert len(lines) == 1 + assert lines[0] == "| ???" + def test_repr_source_excinfo(self) -> None: """Check if indentation is right.""" try: