Fixed `xonsh -DVAR=VAL` behavior: initiate env variables before shell initialization. (#5396)

### Before

Case 1:
```xsh
xonsh --no-rc --no-env -DCOLOR_OUTPUT 0  # space between -DVAR and VALUE
```
```xsh
Traceback (most recent call last):
  File "/Users/pc/.local/xonsh-env/lib/python3.12/site-packages/xonsh/main.py", line 478, in main
    args = premain(argv)
           ^^^^^^^^^^^^^
  File "/Users/pc/.local/xonsh-env/lib/python3.12/site-packages/xonsh/main.py", line 420, in premain
    env.update([x.split("=", 1) for x in args.defines])
  File "<frozen _collections_abc>", line 987, in update
ValueError: not enough values to unpack (expected 2, got 1)
Xonsh encountered an issue during launch
```
Case 2:
```xsh
xonsh --no-rc --no-env -DXONSH_HISTORY_BACKEND=dummy
history info
# json  # EXPECTED: dummy
```

### After
Case 1:
```xsh
xonsh --no-rc --no-env -DCOLOR_OUTPUT 0
# Wrong format for -DCOLOR_OUTPUT argument. Use -DVAR=VAL form.
```

Case 2:
```xsh
xonsh --no-rc --no-env -DXONSH_HISTORY_BACKEND=dummy
history info
# dummy
```

Closes #5395

## 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-06 14:09:10 +02:00 committed by GitHub
parent cdc1d602a2
commit b19a89b432
Failed to generate hash of commit
5 changed files with 61 additions and 4 deletions

23
news/main_d.rst Normal file
View file

@ -0,0 +1,23 @@
**Added:**
* <news item>
**Changed:**
* <news item>
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* Fixed ``xonsh -DVAR=VAL`` behavior: initiate env variables before shell initialization.
**Security:**
* <news item>

View file

@ -49,6 +49,7 @@ def run_xonsh(
single_command=False,
interactive=False,
path=None,
add_args: list = None,
):
env = dict(os.environ)
if path is None:
@ -69,7 +70,8 @@ def run_xonsh(
input = None
else:
input = cmd
if add_args:
args += add_args
proc = sp.Popen(
args,
env=env,
@ -1040,3 +1042,15 @@ def test_raise_subproc_error_with_show_traceback(monkeypatch, interactive):
)
assert ret != 0
assert re.match("ls.*No such file or directory\n", out)
def test_main_d():
out, err, ret = run_xonsh(cmd="print($XONSH_HISTORY_BACKEND)", single_command=True)
assert out == "json\n"
out, err, ret = run_xonsh(
add_args=["-DXONSH_HISTORY_BACKEND='dummy'"],
cmd="print($XONSH_HISTORY_BACKEND)",
single_command=True,
)
assert out == "dummy\n"

View file

@ -29,6 +29,7 @@ from xonsh.tools import (
print_color,
print_exception,
to_bool_or_int,
unquote,
)
from xonsh.xonfig import print_welcome_screen
from xonsh.xontribs import auto_load_xontribs_from_entrypoints, xontribs_load
@ -415,9 +416,21 @@ def premain(argv=None):
"XONSH_INTERACTIVE": args.force_interactive
or (args.mode == XonshMode.interactive),
}
env = start_services(shell_kwargs, args, pre_env=pre_env)
# Load -DVAR=VAL arguments.
if args.defines is not None:
env.update([x.split("=", 1) for x in args.defines])
for x in args.defines:
try:
var, val = x.split("=", 1)
pre_env[var] = unquote(val)
except Exception:
print(
f"Wrong format for -D{x} argument. Use -DVAR=VAL form.",
file=sys.stderr,
)
sys.exit(1)
start_services(shell_kwargs, args, pre_env=pre_env)
return args

View file

@ -306,7 +306,7 @@ def write_cache(filename):
d = os.path.dirname(filename)
os.makedirs(d, exist_ok=True)
s = pformat(CACHE)
with open(filename, "w") as f:
with open(filename, "w", encoding="utf-8") as f:
f.write(s)

View file

@ -2854,3 +2854,10 @@ def describe_waitpid_status(status):
]
for f in funcs:
print(f.__name__, "-", f(status), "-", f.__doc__)
def unquote(s: str, chars="'\""):
"""Strip paired quotes from string once."""
if len(s) >= 2 and s[0] == s[-1] and s[0] in chars:
return s[1:-1]
return s