diff --git a/tests/test_eval.cpp b/tests/test_eval.cpp index cd2903f0ab..6fdf7a81a5 100644 --- a/tests/test_eval.cpp +++ b/tests/test_eval.cpp @@ -87,6 +87,31 @@ TEST_SUBMODULE(eval_, m) { return false; }); + // Line numbers reported from evaluated source must match the source as given; + // before #6089 a prepended coding cookie shifted them by one. + m.def("test_eval_line_numbers", []() { + int syntax_lineno = -1; + try { + py::exec("x = 1\nx = = 2\n"); + throw std::runtime_error("py::exec did not raise SyntaxError"); + } catch (py::error_already_set &e) { + syntax_lineno = e.value().attr("lineno").cast(); + } + int traceback_lineno = -1; + try { + py::exec("x = 1\nraise RuntimeError('line two')\n"); + throw std::runtime_error("py::exec did not raise RuntimeError"); + } catch (py::error_already_set &e) { + py::object tb = e.trace(); + for (py::object next = tb.attr("tb_next"); !next.is_none(); + next = tb.attr("tb_next")) { + tb = std::move(next); + } + traceback_lineno = tb.attr("tb_lineno").cast(); + } + return py::make_tuple(syntax_lineno, traceback_lineno); + }); + // test_eval_empty_globals m.def("eval_empty_globals", [](py::object global) { if (global.is_none()) { diff --git a/tests/test_eval.py b/tests/test_eval.py index 8ac1907c7a..db6cec8e95 100644 --- a/tests/test_eval.py +++ b/tests/test_eval.py @@ -27,6 +27,10 @@ def test_eval_file(): assert m.test_eval_file_failure() +def test_eval_line_numbers(): + assert m.test_eval_line_numbers() == (2, 2) + + def test_eval_empty_globals(): assert "__builtins__" in m.eval_empty_globals(None)