File fix-traceback.patch of Package python-pytest-examples

From 3fe64dc479d318fa58fd1952bd37ce9db2beb23f Mon Sep 17 00:00:00 2001
From: Alex Hall <alex.mojaki@gmail.com>
Date: Sun, 17 Sep 2023 17:35:21 +0200
Subject: [PATCH 1/4] Use tb_lineno to point to correct line in traceback

---
 pytest_examples/traceback.py | 14 +++++++-------
 tests/test_run_examples.py   |  9 ++++++---
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/pytest_examples/traceback.py b/pytest_examples/traceback.py
index 7dedfa1..591f995 100644
--- a/pytest_examples/traceback.py
+++ b/pytest_examples/traceback.py
@@ -1,7 +1,6 @@
 from __future__ import annotations as _annotations
 
 import sys
-import traceback
 from types import CodeType, FrameType, TracebackType
 from typing import TYPE_CHECKING
 
@@ -21,16 +20,17 @@ def create_example_traceback(exc: Exception, module_path: str, example: CodeExam
         # f_code.co_posonlyargcount was added in 3.8
         return None
     frames = []
-    for frame, _ in traceback.walk_tb(exc.__traceback__):
+    tb = exc.__traceback__
+    while tb is not None:
+        frame = tb.tb_frame
         if frame.f_code.co_filename == module_path:
-            frames.append(create_custom_frame(frame, example))
+            frames.append((create_custom_frame(frame, example), tb.tb_lasti, tb.tb_lineno + example.start_line))
+        tb = tb.tb_next
 
     frames.reverse()
     new_tb = None
-    for altered_frame in frames:
-        new_tb = TracebackType(
-            tb_next=new_tb, tb_frame=altered_frame, tb_lasti=altered_frame.f_lasti, tb_lineno=altered_frame.f_lineno
-        )
+    for altered_frame, lasti, lineno in frames:
+        new_tb = TracebackType(tb_next=new_tb, tb_frame=altered_frame, tb_lasti=lasti, tb_lineno=lineno)
     return new_tb
 
 
diff --git a/tests/test_run_examples.py b/tests/test_run_examples.py
index 6943329..9f077d7 100644
--- a/tests/test_run_examples.py
+++ b/tests/test_run_examples.py
@@ -224,7 +224,10 @@ def test_run_directly(tmp_path, eval_example):
 x = 4
 
 def div(y):
-    return x / y
+    try:
+        return x / y
+    finally:
+        str(y)
 
 div(2)
 div(0)"""
@@ -244,10 +247,10 @@ def div(y):
 
     # debug(exc_info.traceback)
     assert exc_info.traceback[-1].frame.code.path == md_file
-    assert exc_info.traceback[-1].lineno == 6
+    assert exc_info.traceback[-1].lineno == 7
 
     assert exc_info.traceback[-2].frame.code.path == md_file
-    assert exc_info.traceback[-2].lineno == 9
+    assert exc_info.traceback[-2].lineno == 12
 
 
 def test_print_sub(pytester: pytest.Pytester):

From e07b1538df6eb662c2b92b9da9b768a2cc1f3ed3 Mon Sep 17 00:00:00 2001
From: Alex Hall <alex.mojaki@gmail.com>
Date: Sun, 17 Sep 2023 19:08:32 +0200
Subject: [PATCH 2/4] Keep the original co_firstlineno

---
 pytest_examples/traceback.py | 10 ++++------
 tests/test_run_examples.py   |  2 +-
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/pytest_examples/traceback.py b/pytest_examples/traceback.py
index 591f995..9e797ed 100644
--- a/pytest_examples/traceback.py
+++ b/pytest_examples/traceback.py
@@ -36,12 +36,10 @@ def create_example_traceback(exc: Exception, module_path: str, example: CodeExam
 
 def create_custom_frame(frame: FrameType, example: CodeExample) -> FrameType:
     """
-    Create a new frame that mostly matches `frame` but with a filename from `example` and line number
-    altered to match the example.
+    Create a new frame that mostly matches `frame` but with a filename from `example`.
 
     Taken mostly from https://naleraphael.github.io/blog/posts/devlog_create_a_builtin_frame_object/
-    With the CodeType creation inspired by https://stackoverflow.com/a/16123158/949890. However, we use
-    `frame.f_lineno` for the line number instead of `f_code.co_firstlineno` as that seems to work.
+    With the CodeType creation inspired by https://stackoverflow.com/a/16123158/949890.
     """
     import ctypes
 
@@ -77,7 +75,7 @@ def create_custom_frame(frame: FrameType, example: CodeExample) -> FrameType:
             str(example.path),
             f_code.co_name,
             f_code.co_qualname,
-            frame.f_lineno + example.start_line,
+            f_code.co_firstlineno,
             f_code.co_lnotab,
             f_code.co_exceptiontable,
         )
@@ -95,7 +93,7 @@ def create_custom_frame(frame: FrameType, example: CodeExample) -> FrameType:
             f_code.co_varnames,
             str(example.path),
             f_code.co_name,
-            frame.f_lineno + example.start_line,
+            f_code.co_firstlineno,
             f_code.co_lnotab,
         )
 
diff --git a/tests/test_run_examples.py b/tests/test_run_examples.py
index 9f077d7..9bf3dcc 100644
--- a/tests/test_run_examples.py
+++ b/tests/test_run_examples.py
@@ -54,7 +54,7 @@ def test_find_run_examples(example: CodeExample, eval_example: EvalExample):
 
     # assert 'my_file_9_13.py:12: AssertionError' in '\n'.join(result.outlines)
     assert result.outlines[-8:-3] == [
-        '',
+        '    b = 2',
         '>   assert a + b == 4',
         'E   AssertionError',
         '',

From 089cf8a4f0a91a5b85108205d0f58cf603af3ac5 Mon Sep 17 00:00:00 2001
From: Alex Hall <alex.mojaki@gmail.com>
Date: Wed, 20 Sep 2023 15:46:34 +0200
Subject: [PATCH 3/4] Adjust co_firstlineno so that the pytest includes the
 correct context.

---
 pytest_examples/traceback.py | 8 +++++---
 tests/test_run_examples.py   | 6 ++++--
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/pytest_examples/traceback.py b/pytest_examples/traceback.py
index 9e797ed..94ede45 100644
--- a/pytest_examples/traceback.py
+++ b/pytest_examples/traceback.py
@@ -36,7 +36,9 @@ def create_example_traceback(exc: Exception, module_path: str, example: CodeExam
 
 def create_custom_frame(frame: FrameType, example: CodeExample) -> FrameType:
     """
-    Create a new frame that mostly matches `frame` but with a filename from `example`.
+    Create a new frame that mostly matches `frame` but with a code object that has
+    a filename from `example` and adjusted an adjusted first line number
+    so that pytest shows the correct code context in the traceback.
 
     Taken mostly from https://naleraphael.github.io/blog/posts/devlog_create_a_builtin_frame_object/
     With the CodeType creation inspired by https://stackoverflow.com/a/16123158/949890.
@@ -75,7 +77,7 @@ def create_custom_frame(frame: FrameType, example: CodeExample) -> FrameType:
             str(example.path),
             f_code.co_name,
             f_code.co_qualname,
-            f_code.co_firstlineno,
+            f_code.co_firstlineno + example.start_line,
             f_code.co_lnotab,
             f_code.co_exceptiontable,
         )
@@ -93,7 +95,7 @@ def create_custom_frame(frame: FrameType, example: CodeExample) -> FrameType:
             f_code.co_varnames,
             str(example.path),
             f_code.co_name,
-            f_code.co_firstlineno,
+            f_code.co_firstlineno + example.start_line,
             f_code.co_lnotab,
         )
 
diff --git a/tests/test_run_examples.py b/tests/test_run_examples.py
index 9bf3dcc..ad878ea 100644
--- a/tests/test_run_examples.py
+++ b/tests/test_run_examples.py
@@ -52,8 +52,10 @@ def test_find_run_examples(example: CodeExample, eval_example: EvalExample):
     result = pytester.runpytest('-p', 'no:pretty', '-v')
     result.assert_outcomes(passed=1, failed=1)
 
-    # assert 'my_file_9_13.py:12: AssertionError' in '\n'.join(result.outlines)
-    assert result.outlines[-8:-3] == [
+    assert result.outlines[-11:-3] == [
+        '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ',
+        '',
+        '    a = 1',
         '    b = 2',
         '>   assert a + b == 4',
         'E   AssertionError',

From e07ec3de414c00afa11a94bd136b33f77608c767 Mon Sep 17 00:00:00 2001
From: Alex Hall <alex.mojaki@gmail.com>
Date: Sat, 23 Sep 2023 12:08:07 +0200
Subject: [PATCH 4/4] Loosen testing result.outlines

---
 tests/test_run_examples.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/test_run_examples.py b/tests/test_run_examples.py
index ad878ea..1dcfba1 100644
--- a/tests/test_run_examples.py
+++ b/tests/test_run_examples.py
@@ -52,8 +52,8 @@ def test_find_run_examples(example: CodeExample, eval_example: EvalExample):
     result = pytester.runpytest('-p', 'no:pretty', '-v')
     result.assert_outcomes(passed=1, failed=1)
 
-    assert result.outlines[-11:-3] == [
-        '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ',
+    assert result.outlines[-11].startswith('_ _ _ _ ')
+    assert result.outlines[-10:-3] == [
         '',
         '    a = 1',
         '    b = 2',
openSUSE Build Service is sponsored by