diff --git a/news/fix-tracer-shutdown.rst b/news/fix-tracer-shutdown.rst new file mode 100644 index 000000000..befa0c34e --- /dev/null +++ b/news/fix-tracer-shutdown.rst @@ -0,0 +1,5 @@ +**Fixed:** + +* Using ``trace on`` with ``.xsh`` scripts could previously lead to + a spurious ignored exception showing up on stderr. This is now fixed. + diff --git a/tests/built_ins/test_tracer.py b/tests/built_ins/test_tracer.py index 7883015bf..eceba79f7 100644 --- a/tests/built_ins/test_tracer.py +++ b/tests/built_ins/test_tracer.py @@ -1,10 +1,18 @@ +import os import re +import subprocess +import sys +from pathlib import Path +from textwrap import dedent import pytest from xonsh.procs.specs import cmds_to_specs from xonsh.tracer import tracermain +# Minimum set of environment variables on Windows +W_ENV = "SYSTEMDRIVE SYSTEMROOT ALLUSERSPROFILE HOMEDRIVE HOMEPATH APPDATA LOCALAPPDATA" + def test_tracer_help(capsys, xsh_with_aliases): """verify can invoke it, and usage knows about all the options""" @@ -17,3 +25,31 @@ def test_tracer_help(capsys, xsh_with_aliases): assert m[1] verbs = {v.strip().lower() for v in m[1].split(",")} assert verbs == {"rm", "start", "add", "on", "off", "del", "color", "stop", "ls"} + + +def test_trace_in_script(): + CURRENT_DIR = Path(__file__).parent + cmd = [sys.executable, "-m", "xonsh", str(CURRENT_DIR / "tracer" / "example.xsh")] + env = {"XONSH_SHOW_TRACEBACK": "True"} + if sys.platform == "win32": + # required for an empty environment on Windows. see python/cpython#120836 + for ev in W_ENV.split(): + env[ev] = os.environ[ev] + expected = dedent( + """\ + Some output! + tests/built_ins/tracer/example.xsh:3:variable = "" + tests/built_ins/tracer/example.xsh:4:for part in parts: + tests/built_ins/tracer/example.xsh:5: variable += part + tests/built_ins/tracer/example.xsh:4:for part in parts: + tests/built_ins/tracer/example.xsh:5: variable += part + tests/built_ins/tracer/example.xsh:4:for part in parts: + tests/built_ins/tracer/example.xsh:5: variable += part + tests/built_ins/tracer/example.xsh:4:for part in parts: + tests/built_ins/tracer/example.xsh:6:echo Some @(variable) + """ + ).replace("/", os.sep) + proc = subprocess.run(cmd, capture_output=True, encoding="utf8", env=env) + assert proc.returncode == 0 + assert proc.stderr == "" + assert proc.stdout == expected diff --git a/tests/built_ins/tracer/example.xsh b/tests/built_ins/tracer/example.xsh new file mode 100755 index 000000000..4eed0cca6 --- /dev/null +++ b/tests/built_ins/tracer/example.xsh @@ -0,0 +1,6 @@ +parts = ["out", "put", "!"] +trace on +variable = "" +for part in parts: + variable += part +echo Some @(variable) \ No newline at end of file diff --git a/xonsh/tracer.py b/xonsh/tracer.py index e7d88703e..6023e1249 100644 --- a/xonsh/tracer.py +++ b/xonsh/tracer.py @@ -81,7 +81,7 @@ class TracerType: frame.f_trace = self.prev_tracer self.prev_tracer = DefaultNotGiven - def trace(self, frame, event, arg): + def trace(self, frame, event, arg, *, find_file=find_file, print_color=print_color): """Implements a line tracing function.""" if event not in self.valid_events: return self.trace