mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 00:14:41 +01:00
Callable alias: fixed capturing stdout in case of redirect (#5527)
### Motivation Closes #5512. The issue was introduced in #4445. It's needed to add checking the redirect case. ### Before ```xsh cd /tmp @aliases.register('a') def _a(): print("1-hello") echo 2-hello a > o.txt # 2-hello cat o.txt # 1-hello ``` ### After ```xsh cd /tmp @aliases.register('a') def _a(): print("1-hello") echo 2-hello a > o.txt cat o.txt # 1-hello # 2-hello ``` ## 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:
parent
6b30c3aae3
commit
61a77ac3ce
3 changed files with 61 additions and 8 deletions
23
news/callias_capture_redirect.rst
Normal file
23
news/callias_capture_redirect.rst
Normal file
|
@ -0,0 +1,23 @@
|
|||
**Added:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Changed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Removed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Fixed:**
|
||||
|
||||
* Callable alias: fixed capturing stdout in case of redirect e.g. `a > file` (#5527).
|
||||
|
||||
**Security:**
|
||||
|
||||
* <news item>
|
|
@ -150,6 +150,25 @@ def test_capture_always(
|
|||
assert exp in capfd.readouterr().out
|
||||
|
||||
|
||||
@skip_if_on_windows
|
||||
@pytest.mark.flaky(reruns=3, reruns_delay=2)
|
||||
def test_callias_captured_redirect(xonsh_session, tmpdir):
|
||||
@xonsh_session.aliases.register("a")
|
||||
def _a(a, i, o, e):
|
||||
print("print_stdout")
|
||||
xonsh_session.subproc_captured_stdout(["echo", "cap_stdout"])
|
||||
xonsh_session.subproc_captured_object(["echo", "cap_object"])
|
||||
xonsh_session.subproc_captured_hiddenobject(["echo", "hiddenobject"])
|
||||
xonsh_session.subproc_uncaptured(["echo", "uncaptured"])
|
||||
print("print_error", file=e)
|
||||
|
||||
f = tmpdir / "capture.txt"
|
||||
cmd = (["a", (">", str(f))],)
|
||||
specs = cmds_to_specs(cmd, captured="hiddenobject")
|
||||
_run_command_pipeline(specs, cmd).end()
|
||||
assert f.read_text(encoding="utf-8") == "print_stdout\nhiddenobject\n"
|
||||
|
||||
|
||||
@skip_if_on_windows
|
||||
@pytest.mark.parametrize("captured", ["stdout", "object"])
|
||||
@pytest.mark.parametrize("interactive", [True, False])
|
||||
|
|
|
@ -1021,19 +1021,30 @@ def cmds_to_specs(cmds, captured=False, envs=None):
|
|||
|
||||
# Apply boundary conditions
|
||||
if not XSH.env.get("XONSH_CAPTURE_ALWAYS"):
|
||||
# Make sure sub-specs are always captured.
|
||||
# I.e. ![some_alias | grep x] $(some_alias)
|
||||
specs_to_capture = specs if captured in STDOUT_CAPTURE_KINDS else specs[:-1]
|
||||
for spec in specs_to_capture:
|
||||
if spec.env is None:
|
||||
spec.env = {"XONSH_CAPTURE_ALWAYS": True}
|
||||
else:
|
||||
spec.env.setdefault("XONSH_CAPTURE_ALWAYS", True)
|
||||
# Make sure sub-specs are always captured in case:
|
||||
# `![some_alias | grep x]`, `$(some_alias)`, `some_alias > file`.
|
||||
last = spec
|
||||
is_redirected_stdout = bool(last.stdout)
|
||||
specs_to_capture = (
|
||||
specs
|
||||
if captured in STDOUT_CAPTURE_KINDS or is_redirected_stdout
|
||||
else specs[:-1]
|
||||
)
|
||||
_set_specs_capture_always(specs_to_capture)
|
||||
|
||||
_update_last_spec(specs[-1])
|
||||
return specs
|
||||
|
||||
|
||||
def _set_specs_capture_always(specs_to_capture):
|
||||
"""Set XONSH_CAPTURE_ALWAYS for all specs."""
|
||||
for spec in specs_to_capture:
|
||||
if spec.env is None:
|
||||
spec.env = {"XONSH_CAPTURE_ALWAYS": True}
|
||||
else:
|
||||
spec.env.setdefault("XONSH_CAPTURE_ALWAYS", True)
|
||||
|
||||
|
||||
def _shell_set_title(cmds):
|
||||
if XSH.env.get("XONSH_INTERACTIVE") and XSH.shell is not None:
|
||||
# context manager updates the command information that gets
|
||||
|
|
Loading…
Add table
Reference in a new issue