Fixed empty stacktrace for CalledProcessError (#5391)

Fixed #5387

### Before

```xsh
$XONSH_SHOW_TRACEBACK = False
$RAISE_SUBPROC_ERROR = True

ls nofile
# ls: nofile: No such file or directory
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
#
```

### After 

```xsh
$RAISE_SUBPROC_ERROR = False
$XONSH_SHOW_TRACEBACK = False
ls nofile
# ls: nofile: No such file or directory

$RAISE_SUBPROC_ERROR = True
$XONSH_SHOW_TRACEBACK = False
ls nofile
# ls: nofile: No such file or directory
# subprocess.CalledProcessError: Command '['ls', 'nofile']' returned non-zero exit status 1.

$RAISE_SUBPROC_ERROR = True
$XONSH_SHOW_TRACEBACK = True
ls nofile
# ls: nofile: No such file or directory
# Traceback (most recent call last):
# ...
# subprocess.CalledProcessError: Command '['ls', 'nofile']' returned non-zero exit status 1.

$RAISE_SUBPROC_ERROR = False
$XONSH_SHOW_TRACEBACK = True
ls nofile
# ls: nofile: No such file or directory
```

## For community
⬇️ **Please click the 👍 reaction instead of leaving a `+1` or 👍
comment**

---------

Co-authored-by: a <1@1.1>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Andy Kipp 2024-05-04 11:50:32 +02:00 committed by GitHub
parent c3cd47e1da
commit cdc1d602a2
Failed to generate hash of commit
3 changed files with 70 additions and 3 deletions

View file

@ -0,0 +1,23 @@
**Added:**
* <news item>
**Changed:**
* <news item>
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* Fixed empty stacktrace for CalledProcessError.
**Security:**
* <news item>

View file

@ -3,6 +3,7 @@ This requires Xonsh installed in venv or otherwise available on PATH
"""
import os
import re
import shutil
import subprocess as sp
import tempfile
@ -995,3 +996,47 @@ def test_run_fail_not_on_path():
cmd = "hello_world.bat"
out, _, _ = run_xonsh(cmd, stdout=sp.PIPE, stderr=sp.PIPE, path=os.environ["PATH"])
assert out != "Hello world"
@skip_if_on_windows
@pytest.mark.parametrize("interactive", [True, False])
def test_raise_subproc_error_with_show_traceback(monkeypatch, interactive):
out, err, ret = run_xonsh(
"$COLOR_RESULTS=False\n$RAISE_SUBPROC_ERROR=False\n$XONSH_SHOW_TRACEBACK=False\nls nofile",
interactive=interactive,
single_command=True,
)
assert ret != 0
assert re.match("ls.*No such file or directory\n", out)
out, err, ret = run_xonsh(
"$COLOR_RESULTS=False\n$RAISE_SUBPROC_ERROR=True\n$XONSH_SHOW_TRACEBACK=False\nls nofile",
interactive=interactive,
single_command=True,
)
assert ret != 0
assert re.match(
"ls:.*No such file or directory\nsubprocess.CalledProcessError: Command '\\['ls', 'nofile'\\]' returned non-zero exit status .*",
out,
re.MULTILINE | re.DOTALL,
)
out, err, ret = run_xonsh(
"$COLOR_RESULTS=False\n$RAISE_SUBPROC_ERROR=True\n$XONSH_SHOW_TRACEBACK=True\nls nofile",
interactive=interactive,
single_command=True,
)
assert ret != 0
assert re.match(
"ls.*No such file or directory.*Traceback .*\nsubprocess.CalledProcessError: Command '\\['ls', 'nofile'\\]' returned non-zero exit status .*",
out,
re.MULTILINE | re.DOTALL,
)
out, err, ret = run_xonsh(
"$COLOR_RESULTS=False\n$RAISE_SUBPROC_ERROR=False\n$XONSH_SHOW_TRACEBACK=True\nls nofile",
interactive=interactive,
single_command=True,
)
assert ret != 0
assert re.match("ls.*No such file or directory\n", out)

View file

@ -1119,10 +1119,9 @@ def display_colored_error_message(exc_info, strip_xonsh_error_types=True, limit=
no_trace_and_raise_subproc_error
and "subprocess.CalledProcessError:" in content[-1]
):
content = content[:-1]
content = [content[-1].rstrip()]
traceback_str = "".join([v for v in content])
traceback_str += "" if traceback_str.endswith("\n") else "\n"
# color the traceback if available
_, interactive = _get_manual_env_var("XONSH_INTERACTIVE", 0)
@ -1137,7 +1136,7 @@ def display_colored_error_message(exc_info, strip_xonsh_error_types=True, limit=
lexer = pygments.lexers.python.PythonTracebackLexer()
tokens = list(pygments.lex(traceback_str, lexer=lexer))
# this goes to stdout, but since we are interactive it doesn't matter
print_color(tokens, end="\n", file=sys.stderr)
print_color(tokens, end="", file=sys.stderr)
return