Remove globals (#4280)

* refactor: remove usage of global variables in abbrevs.py

* chore: add flake8-mutable to prevent mutable defaults

* fix: abbrevs expand test

* refactor: add xonsh session singleton

* refactor: fix circular errors when using xonshSession as singleton

* refactor: remove black magicked builtin attributes

* style: black format tests as well

* refactor: update tests to use xonsh-session singleton

* refactor: update abbrevs to not use builtins

* test: remove DummyCommandsCache and patch orig class

* fix: failing test_command_completers

* test: use monkeypatch to update xession fixture

* fix: failing test_pipelines

* fix: failing test_main

* chore: run test suit as single invocation

* test: fix tests/test_xonsh.xsh

* refactor: remove builtins from docs/conf.py

* fix: mypy error in jobs

* fix: test error from test_main

* test: close xession error in test_command_completers

* chore: use pytest-cov for reporting coverage

this will include subprocess calls, and will increase coverage

* style:
This commit is contained in:
Noorhteen Raja NJ 2021-05-20 15:44:26 +05:30 committed by GitHub
parent e02c7d76c4
commit 38295a1dd9
Failed to generate hash of commit
130 changed files with 2452 additions and 1824 deletions

View file

@ -27,22 +27,17 @@ from xonsh.environ import Env, Var, Xettings
if tp.TYPE_CHECKING: if tp.TYPE_CHECKING:
from xonsh.environ import VarKeyType from xonsh.environ import VarKeyType
from xonsh.built_ins import XSH
from xonsh.xontribs_meta import get_xontribs from xonsh.xontribs_meta import get_xontribs
from xonsh.commands_cache import CommandsCache from xonsh.commands_cache import CommandsCache
import rst_helpers import rst_helpers
if not hasattr(builtins, "__xonsh__"):
from argparse import Namespace
builtins.__xonsh__ = Namespace()
builtins.__xonsh__.load = lambda *a, **kw: None
builtins.__xonsh__.link_builtins = lambda *a, **kw: None
spec = importlib.util.find_spec("prompt_toolkit") spec = importlib.util.find_spec("prompt_toolkit")
if spec is not None: if spec is not None:
# hacky runaround to import PTK-specific events # hacky runaround to import PTK-specific events
builtins.__xonsh__.env = Env() XSH.env = Env()
from xonsh.ptk_shell.shell import events from xonsh.ptk_shell.shell import events
else: else:
from xonsh.events import events from xonsh.events import events
@ -452,9 +447,9 @@ def make_events():
make_xontribs() make_xontribs()
make_events() make_events()
builtins.__xonsh__.history = None XSH.history = None
builtins.__xonsh__.env = {} XSH.env = {}
builtins.__xonsh__.commands_cache = CommandsCache() XSH.commands_cache = CommandsCache()
def setup(app): def setup(app):

View file

@ -2,6 +2,7 @@ py
pytest>=6 pytest>=6
flake8 flake8
flake8-docstrings flake8-docstrings
flake8-mutable
pytest-cov pytest-cov
pytest-timeout pytest-timeout
prompt-toolkit>=3.0 prompt-toolkit>=3.0

View file

@ -24,42 +24,26 @@ def test(ns: argparse.Namespace):
`xonsh run-tests.xsh -- --junitxml=junit/test-results.%%d.xml` `xonsh run-tests.xsh -- --junitxml=junit/test-results.%%d.xml`
""" """
run_separately = [
'tests/test_main.py',
'tests/test_ptk_highlight.py',
]
ignores = []
for fname in run_separately:
ignores.append('--ignore')
ignores.append(fname)
args = ns.pytest_args args = ns.pytest_args
if ns.report_coverage: if ns.report_coverage:
![coverage run -m pytest @(_replace_args(args, 0)) @(ignores)] ![pytest @(_replace_args(args, 0)) --cov --cov-report=xml --cov-report=term]
for index, fname in enumerate(run_separately):
![coverage run --append -m pytest @(_replace_args(args, index+1)) @(fname)]
![coverage report -m]
![coverage xml]
else: else:
![pytest @(_replace_args(args, 0)) @(ignores)] ![pytest @(_replace_args(args, 0))]
for index, fname in enumerate(run_separately):
![pytest @(_replace_args(args, index + 1)) @(fname)]
def qa(ns: argparse.Namespace): def qa(ns: argparse.Namespace):
"""QA checks""" """QA checks"""
echo "---------- Check Black formatter -----------" echo "---------- Check Black formatter -----------"
black --check xonsh xontrib black --check xonsh xontrib tests
echo "---------- Running flake8 ----------" echo "---------- Running flake8 ----------"
python -m flake8 python -m flake8
echo "---------- Running mypy ----------" echo "---------- Running mypy ----------"
mypy --version mypy --version
# todo: add xontrib folder here
mypy xonsh --exclude xonsh/ply mypy xonsh --exclude xonsh/ply

View file

@ -48,12 +48,7 @@ ignore =
E402, # module level import not at top of file E402, # module level import not at top of file
W503, # line break before binary operators is a good thing W503, # line break before binary operators is a good thing
E731, # accept lambda assigned to a variable E731, # accept lambda assigned to a variable
# also acceptable in Xonsh project: reference to global names defined at runtime by black magic
builtins =
__xonsh__,
events,
aliases,
XonshError,
per-file-ignores = per-file-ignores =
# flake8 gives incorrect unused import errors, F401 # flake8 gives incorrect unused import errors, F401
tests/tools.py:E128, tests/tools.py:E128,

View file

@ -1,9 +1,10 @@
import os.path import os.path
import pytest import pytest
import builtins
from contextlib import contextmanager from contextlib import contextmanager
from unittest.mock import MagicMock from unittest.mock import MagicMock
from xonsh.aliases import source_alias, builtins from xonsh.aliases import source_alias
@pytest.fixture @pytest.fixture
@ -15,27 +16,26 @@ def mockopen(xonsh_builtins, monkeypatch):
monkeypatch.setattr(builtins, "open", mocked_open) monkeypatch.setattr(builtins, "open", mocked_open)
def test_source_current_dir(mockopen, monkeypatch): @pytest.fixture
def mocked_execx_checker(xession, monkeypatch):
checker = [] checker = []
def mocked_execx(src, *args, **kwargs): def mocked_execx(src, *args, **kwargs):
checker.append(src.strip()) checker.append(src.strip())
monkeypatch.setattr(builtins, "execx", mocked_execx) monkeypatch.setattr(xession.builtins, "execx", mocked_execx)
return checker
def test_source_current_dir(mockopen, monkeypatch, mocked_execx_checker):
monkeypatch.setattr(os.path, "isfile", lambda x: True) monkeypatch.setattr(os.path, "isfile", lambda x: True)
source_alias(["foo", "bar"]) source_alias(["foo", "bar"])
assert checker == ["foo", "bar"] assert mocked_execx_checker == ["foo", "bar"]
def test_source_path(mockopen, monkeypatch): def test_source_path(mockopen, mocked_execx_checker):
checker = []
def mocked_execx(src, *args, **kwargs):
checker.append(src.strip())
monkeypatch.setattr(builtins, "execx", mocked_execx)
source_alias(["foo", "bar"]) source_alias(["foo", "bar"])
path_foo = os.path.join("tests", "bin", "foo") path_foo = os.path.join("tests", "bin", "foo")
path_bar = os.path.join("tests", "bin", "bar") path_bar = os.path.join("tests", "bin", "bar")
assert checker[0].endswith(path_foo) assert mocked_execx_checker[0].endswith(path_foo)
assert checker[1].endswith(path_bar) assert mocked_execx_checker[1].endswith(path_bar)

View file

@ -10,20 +10,19 @@ from xonsh.parsers.completion_context import (
) )
CUR_DIR = "." if ON_WINDOWS else "./" # for some reason this is what happens in `complete_path` CUR_DIR = (
"." if ON_WINDOWS else "./"
) # for some reason this is what happens in `complete_path`
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def setup(xonsh_builtins, xonsh_execer, monkeypatch): def setup(xession, xonsh_execer, monkeypatch):
monkeypatch.setattr(xonsh_builtins.__xonsh__, "commands_cache", ["cool"]) monkeypatch.setattr(xession, "commands_cache", ["cool"])
def test_empty_line(): def test_empty_line():
completions = complete_base( completions = complete_base(
CompletionContext( CompletionContext(command=CommandContext((), 0), python=PythonContext("", 0))
command=CommandContext((), 0),
python=PythonContext("", 0)
)
) )
assert completions assert completions
for exp in ["cool", "abs"]: for exp in ["cool", "abs"]:
@ -33,8 +32,7 @@ def test_empty_line():
def test_empty_subexpr(): def test_empty_subexpr():
completions = complete_base( completions = complete_base(
CompletionContext( CompletionContext(
command=CommandContext((), 0, subcmd_opening="$("), command=CommandContext((), 0, subcmd_opening="$("), python=None
python=None
) )
) )
assert completions assert completions

View file

@ -4,70 +4,163 @@ from tests.tools import skip_if_on_windows, skip_if_on_darwin
from xonsh.completers.tools import RichCompletion from xonsh.completers.tools import RichCompletion
from xonsh.completers.bash import complete_from_bash from xonsh.completers.bash import complete_from_bash
from xonsh.parsers.completion_context import CompletionContext, CommandContext, CommandArg from xonsh.parsers.completion_context import (
CompletionContext,
CommandContext,
CommandArg,
)
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def setup(monkeypatch, tmp_path, xonsh_builtins): def setup(monkeypatch, tmp_path, xession):
if not xonsh_builtins.__xonsh__.env.get("BASH_COMPLETIONS"): if not xession.env.get("BASH_COMPLETIONS"):
monkeypatch.setitem(xonsh_builtins.__xonsh__.env, "BASH_COMPLETIONS", ["/usr/share/bash-completion/bash_completion"]) monkeypatch.setitem(
xession.env,
"BASH_COMPLETIONS",
["/usr/share/bash-completion/bash_completion"],
)
(tmp_path / "testdir").mkdir() (tmp_path / "testdir").mkdir()
(tmp_path / "spaced dir").mkdir() (tmp_path / "spaced dir").mkdir()
monkeypatch.chdir(str(tmp_path)) monkeypatch.chdir(str(tmp_path))
@skip_if_on_darwin @skip_if_on_darwin
@skip_if_on_windows @skip_if_on_windows
@pytest.mark.parametrize("command_context, completions, lprefix", ( @pytest.mark.parametrize(
(CommandContext(args=(CommandArg("bash"),), arg_index=1, prefix="--deb"), {"--debug", "--debugger"}, 5), "command_context, completions, lprefix",
(CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix=""), {"'testdir/'", "'spaced dir/'"}, 0), (
(CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="", opening_quote="'"), {"'testdir/'", "'spaced dir/'"}, 1), (
)) CommandContext(args=(CommandArg("bash"),), arg_index=1, prefix="--deb"),
{"--debug", "--debugger"},
5,
),
(
CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix=""),
{"'testdir/'", "'spaced dir/'"},
0,
),
(
CommandContext(
args=(CommandArg("ls"),), arg_index=1, prefix="", opening_quote="'"
),
{"'testdir/'", "'spaced dir/'"},
1,
),
),
)
def test_bash_completer(command_context, completions, lprefix): def test_bash_completer(command_context, completions, lprefix):
bash_completions, bash_lprefix = complete_from_bash(CompletionContext(command_context)) bash_completions, bash_lprefix = complete_from_bash(
CompletionContext(command_context)
)
assert bash_completions == completions and bash_lprefix == lprefix assert bash_completions == completions and bash_lprefix == lprefix
@skip_if_on_darwin @skip_if_on_darwin
@skip_if_on_windows @skip_if_on_windows
@pytest.mark.parametrize("command_context, completions, lprefix", ( @pytest.mark.parametrize(
"command_context, completions, lprefix",
(
# ls /pro<TAB> -> ls /proc/ # ls /pro<TAB> -> ls /proc/
(CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="/pro"), {"/proc/"}, 4), (
CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="/pro"),
{"/proc/"},
4,
),
# ls '/pro<TAB> -> ls '/proc/' # ls '/pro<TAB> -> ls '/proc/'
(CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="/pro", opening_quote="'"), {"'/proc/'"}, 5), (
CommandContext(
args=(CommandArg("ls"),), arg_index=1, prefix="/pro", opening_quote="'"
),
{"'/proc/'"},
5,
),
# ls '/pro<TAB>' -> ls '/proc/' # ls '/pro<TAB>' -> ls '/proc/'
(CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="/pro", opening_quote="'", closing_quote="'"), (
{"'/proc/"}, 5), CommandContext(
args=(CommandArg("ls"),),
arg_index=1,
prefix="/pro",
opening_quote="'",
closing_quote="'",
),
{"'/proc/"},
5,
),
# ls '/pro'<TAB> -> ls '/proc/' # ls '/pro'<TAB> -> ls '/proc/'
(CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="/pro", opening_quote="'", closing_quote="'", (
is_after_closing_quote=True), {"'/proc/'"}, 6), CommandContext(
args=(CommandArg("ls"),),
arg_index=1,
prefix="/pro",
opening_quote="'",
closing_quote="'",
is_after_closing_quote=True,
),
{"'/proc/'"},
6,
),
# ls """/pro"""<TAB> -> ls """/proc/""" # ls """/pro"""<TAB> -> ls """/proc/"""
(CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="/pro", opening_quote='"""', closing_quote='"""', (
is_after_closing_quote=True), {'"""/proc/"""'}, 10), CommandContext(
args=(CommandArg("ls"),),
arg_index=1,
prefix="/pro",
opening_quote='"""',
closing_quote='"""',
is_after_closing_quote=True,
),
{'"""/proc/"""'},
10,
),
# Completions that have to be quoted: # Completions that have to be quoted:
# ls ./sp -> ls './spaced dir/' # ls ./sp -> ls './spaced dir/'
(CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="./sp"), {"'./spaced dir/'"}, 4), (
CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="./sp"),
{"'./spaced dir/'"},
4,
),
# ls './sp<TAB> -> ls './spaced dir/' # ls './sp<TAB> -> ls './spaced dir/'
(CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="./sp", opening_quote="'"), {"'./spaced dir/'"}, 5), (
CommandContext(
args=(CommandArg("ls"),), arg_index=1, prefix="./sp", opening_quote="'"
),
{"'./spaced dir/'"},
5,
),
# ls './sp<TAB>' -> ls './spaced dir/' # ls './sp<TAB>' -> ls './spaced dir/'
(CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="./sp", opening_quote="'", closing_quote="'"), (
{"'./spaced dir/"}, 5), CommandContext(
args=(CommandArg("ls"),),
arg_index=1,
prefix="./sp",
opening_quote="'",
closing_quote="'",
),
{"'./spaced dir/"},
5,
),
# ls './sp'<TAB> -> ls './spaced dir/' # ls './sp'<TAB> -> ls './spaced dir/'
(CommandContext(args=(CommandArg("ls"),), arg_index=1, prefix="./sp", opening_quote="'", closing_quote="'", (
is_after_closing_quote=True), {"'./spaced dir/'"}, 6), CommandContext(
)) args=(CommandArg("ls"),),
arg_index=1,
prefix="./sp",
opening_quote="'",
closing_quote="'",
is_after_closing_quote=True,
),
{"'./spaced dir/'"},
6,
),
),
)
def test_quote_handling(command_context, completions, lprefix): def test_quote_handling(command_context, completions, lprefix):
bash_completions, bash_lprefix = complete_from_bash(CompletionContext(command_context)) bash_completions, bash_lprefix = complete_from_bash(
CompletionContext(command_context)
)
assert bash_completions == completions and bash_lprefix == lprefix assert bash_completions == completions and bash_lprefix == lprefix
assert all(isinstance(comp, RichCompletion) and not comp.append_closing_quote for comp in bash_completions) # make sure the completer handles the closing quote by itself assert all(
isinstance(comp, RichCompletion) and not comp.append_closing_quote
for comp in bash_completions
) # make sure the completer handles the closing quote by itself

View file

@ -1,6 +1,12 @@
from unittest.mock import Mock from unittest.mock import Mock
from xonsh.parsers.completion_context import CompletionContext, CommandArg, CommandContext import pytest
from xonsh.parsers.completion_context import (
CompletionContext,
CommandArg,
CommandContext,
)
from tests.tools import ON_WINDOWS, skip_if_on_windows, completions_from_result from tests.tools import ON_WINDOWS, skip_if_on_windows, completions_from_result
@ -8,6 +14,12 @@ from xonsh.completer import Completer
from xonsh.completers.commands import complete_command, complete_skipper from xonsh.completers.commands import complete_command, complete_skipper
@pytest.fixture(autouse=True)
def xs_orig_commands_cache(xession, monkeypatch, xonsh_execer):
xession.unload()
xession.load(execer=xonsh_execer)
def test_complete_command(completion_context_parse): def test_complete_command(completion_context_parse):
if ON_WINDOWS: if ON_WINDOWS:
command = "dir.exe" command = "dir.exe"
@ -15,29 +27,34 @@ def test_complete_command(completion_context_parse):
command = "grep" command = "grep"
assert command in complete_command( assert command in complete_command(
completion_context_parse(command[:-1], len(command) - 1).command) completion_context_parse(command[:-1], len(command) - 1).command
)
@skip_if_on_windows @skip_if_on_windows
def test_skipper_command(completion_context_parse): def test_skipper_command(completion_context_parse):
assert "grep" in completions_from_result( assert "grep" in completions_from_result(
complete_skipper(completion_context_parse("sudo gre", 8))) complete_skipper(completion_context_parse("sudo gre", 8))
)
@skip_if_on_windows @skip_if_on_windows
def test_skipper_arg(completion_context_parse, xonsh_builtins, monkeypatch): def test_skipper_arg(completion_context_parse, xession, monkeypatch):
monkeypatch.setattr(xonsh_builtins.__xonsh__.shell.shell, "completer", Completer(), raising=False) monkeypatch.setattr(xession.shell.shell, "completer", Completer(), raising=False)
bash_completer_mock = Mock() bash_completer_mock = Mock()
monkeypatch.setattr(xonsh_builtins.__xonsh__, "completers", {"bash": bash_completer_mock}) monkeypatch.setattr(xession, "completers", {"bash": bash_completer_mock})
bash_completer_mock.return_value = {"--count "} bash_completer_mock.return_value = {"--count "}
assert "--count " in completions_from_result( assert "--count " in completions_from_result(
complete_skipper(completion_context_parse(f"sudo grep --coun", 16))) complete_skipper(completion_context_parse(f"sudo grep --coun", 16))
)
call_args = bash_completer_mock.call_args[0] call_args = bash_completer_mock.call_args[0]
assert len(call_args) == 1 assert len(call_args) == 1
context = call_args[0] context = call_args[0]
assert isinstance(context, CompletionContext) assert isinstance(context, CompletionContext)
assert context.command == CommandContext(args=(CommandArg("grep"),), arg_index=1, prefix="--coun") assert context.command == CommandContext(
args=(CommandArg("grep"),), arg_index=1, prefix="--coun"
)

View file

@ -1,14 +1,34 @@
from xonsh.parsers.completion_context import CommandArg, CommandContext, CompletionContext from xonsh.parsers.completion_context import (
CommandArg,
CommandContext,
CompletionContext,
)
from xonsh.completers.completer import complete_completer from xonsh.completers.completer import complete_completer
def test_options(): def test_options():
assert complete_completer(CompletionContext(CommandContext( assert (
args=(CommandArg("completer"),), arg_index=1, complete_completer(
))) == {"add", "remove", "list", "help"} CompletionContext(
CommandContext(
args=(CommandArg("completer"),),
arg_index=1,
)
)
)
== {"add", "remove", "list", "help"}
)
def test_help_options(): def test_help_options():
assert complete_completer(CompletionContext(CommandContext( assert (
args=(CommandArg("completer"),CommandArg("help")), arg_index=2, complete_completer(
))) == {"add", "remove", "list"} CompletionContext(
CommandContext(
args=(CommandArg("completer"), CommandArg("help")),
arg_index=2,
)
)
)
== {"add", "remove", "list"}
)

View file

@ -6,7 +6,9 @@ from os import sep
from xonsh.completers.tools import RichCompletion from xonsh.completers.tools import RichCompletion
from xonsh.completers.dirs import complete_cd, complete_rmdir from xonsh.completers.dirs import complete_cd, complete_rmdir
from xonsh.parsers.completion_context import ( from xonsh.parsers.completion_context import (
CompletionContext, CommandContext, CommandArg, CompletionContext,
CommandContext,
CommandArg,
) )
from tests.tools import ON_WINDOWS from tests.tools import ON_WINDOWS
@ -19,11 +21,12 @@ COMPLETERS = {
CUR_DIR = "." if ON_WINDOWS else "./" CUR_DIR = "." if ON_WINDOWS else "./"
PARENT_DIR = ".." if ON_WINDOWS else "../" PARENT_DIR = ".." if ON_WINDOWS else "../"
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def setup(xonsh_builtins, xonsh_execer): def setup(xession, xonsh_execer):
with tempfile.TemporaryDirectory() as tmp: with tempfile.TemporaryDirectory() as tmp:
xonsh_builtins.__xonsh__.env["XONSH_DATA_DIR"] = tmp xession.env["XONSH_DATA_DIR"] = tmp
xonsh_builtins.__xonsh__.env["CDPATH"] = set() xession.env["CDPATH"] = set()
@pytest.fixture(params=list(COMPLETERS)) @pytest.fixture(params=list(COMPLETERS))
@ -33,20 +36,34 @@ def cmd(request):
def test_not_cmd(cmd): def test_not_cmd(cmd):
"""Ensure the cd completer doesn't complete other commands""" """Ensure the cd completer doesn't complete other commands"""
assert not COMPLETERS[cmd](CompletionContext(CommandContext( assert not COMPLETERS[cmd](
args=(CommandArg(f"not-{cmd}"),), arg_index=1, CompletionContext(
))) CommandContext(
args=(CommandArg(f"not-{cmd}"),),
arg_index=1,
)
)
)
def complete_cmd(cmd, prefix, opening_quote="", closing_quote=""): def complete_cmd(cmd, prefix, opening_quote="", closing_quote=""):
result = COMPLETERS[cmd](CompletionContext(CommandContext( result = COMPLETERS[cmd](
args=(CommandArg(cmd),), arg_index=1, prefix=prefix, CompletionContext(
opening_quote=opening_quote, closing_quote=closing_quote, CommandContext(
is_after_closing_quote=bool(closing_quote), args=(CommandArg(cmd),),
))) arg_index=1,
prefix=prefix,
opening_quote=opening_quote,
closing_quote=closing_quote,
is_after_closing_quote=bool(closing_quote),
)
)
)
assert result and len(result) == 2 assert result and len(result) == 2
completions, lprefix = result completions, lprefix = result
assert lprefix == len(opening_quote) + len(prefix) + len(closing_quote) # should override the quotes assert lprefix == len(opening_quote) + len(prefix) + len(
closing_quote
) # should override the quotes
return completions return completions
@ -92,24 +109,24 @@ def test_closing_quotes(cmd, dir_path):
assert completion.append_closing_quote is False assert completion.append_closing_quote is False
def test_complete_dots(xonsh_builtins): def test_complete_dots(xession):
with xonsh_builtins.__xonsh__.env.swap(COMPLETE_DOTS='never'): with xession.env.swap(COMPLETE_DOTS="never"):
dirs = complete_cmd_dirs('cd', '') dirs = complete_cmd_dirs("cd", "")
assert CUR_DIR not in dirs and PARENT_DIR not in dirs assert CUR_DIR not in dirs and PARENT_DIR not in dirs
dirs = complete_cmd_dirs('cd', '.') dirs = complete_cmd_dirs("cd", ".")
assert CUR_DIR not in dirs and PARENT_DIR not in dirs assert CUR_DIR not in dirs and PARENT_DIR not in dirs
with xonsh_builtins.__xonsh__.env.swap(COMPLETE_DOTS='matching'): with xession.env.swap(COMPLETE_DOTS="matching"):
dirs = complete_cmd_dirs('cd', '') dirs = complete_cmd_dirs("cd", "")
assert CUR_DIR not in dirs and PARENT_DIR not in dirs assert CUR_DIR not in dirs and PARENT_DIR not in dirs
dirs = complete_cmd_dirs('cd', '.') dirs = complete_cmd_dirs("cd", ".")
assert CUR_DIR in dirs and PARENT_DIR in dirs assert CUR_DIR in dirs and PARENT_DIR in dirs
with xonsh_builtins.__xonsh__.env.swap(COMPLETE_DOTS='always'): with xession.env.swap(COMPLETE_DOTS="always"):
dirs = complete_cmd_dirs('cd', '') dirs = complete_cmd_dirs("cd", "")
assert CUR_DIR in dirs and PARENT_DIR in dirs assert CUR_DIR in dirs and PARENT_DIR in dirs
dirs = complete_cmd_dirs('cd', '.') dirs = complete_cmd_dirs("cd", ".")
assert CUR_DIR in dirs and PARENT_DIR in dirs assert CUR_DIR in dirs and PARENT_DIR in dirs

View file

@ -9,13 +9,16 @@ def parser():
return CompletionContextParser() return CompletionContextParser()
@pytest.mark.parametrize("cmd", ( @pytest.mark.parametrize(
"ls $WO", "cmd",
"ls /home/$WO", (
"ls @('hi ' + $WO", "ls $WO",
)) "ls /home/$WO",
def test_simple(cmd, xonsh_builtins, monkeypatch, parser): "ls @('hi ' + $WO",
monkeypatch.setitem(xonsh_builtins.__xonsh__.env, "WOW", 1) ),
)
def test_simple(cmd, xession, monkeypatch, parser):
monkeypatch.setitem(xession.env, "WOW", 1)
context = parser.parse(cmd, len(cmd)) context = parser.parse(cmd, len(cmd))
assert complete_environment_vars(context) == ({"$WOW"}, 3) assert complete_environment_vars(context) == ({"$WOW"}, 3)

View file

@ -2,7 +2,11 @@ import pytest
from xonsh.completers.tools import RichCompletion from xonsh.completers.tools import RichCompletion
from xonsh.completers.pip import PIP_RE, complete_pip from xonsh.completers.pip import PIP_RE, complete_pip
from xonsh.parsers.completion_context import CompletionContext, CommandContext, CommandArg from xonsh.parsers.completion_context import (
CompletionContext,
CommandContext,
CommandArg,
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -31,10 +35,15 @@ def test_pip_list_re1(line):
def test_commands(): def test_commands():
comps = complete_pip(CompletionContext(CommandContext( comps = complete_pip(
args=(CommandArg("pip3"),), arg_index=1, CompletionContext(
prefix="c", CommandContext(
))) args=(CommandArg("pip3"),),
arg_index=1,
prefix="c",
)
)
)
assert comps.intersection({"cache", "check", "config"}) assert comps.intersection({"cache", "check", "config"})
for comp in comps: for comp in comps:
assert isinstance(comp, RichCompletion) assert isinstance(comp, RichCompletion)
@ -42,9 +51,14 @@ def test_commands():
def test_package_list(): def test_package_list():
comps = complete_pip(CompletionContext(CommandContext( comps = complete_pip(
args=(CommandArg("pip3"), CommandArg("show")), arg_index=2, CompletionContext(
))) CommandContext(
args=(CommandArg("pip3"), CommandArg("show")),
arg_index=2,
)
)
)
assert "Package" not in comps assert "Package" not in comps
assert "-----------------------------" not in comps assert "-----------------------------" not in comps
assert "pytest" in comps assert "pytest" in comps

View file

@ -1,21 +1,40 @@
from xonsh.parsers.completion_context import CommandArg, CommandContext, CompletionContext from xonsh.parsers.completion_context import (
CommandArg,
CommandContext,
CompletionContext,
)
from xonsh.completers.xompletions import complete_xonfig, complete_xontrib from xonsh.completers.xompletions import complete_xonfig, complete_xontrib
def test_xonfig(): def test_xonfig():
assert complete_xonfig(CompletionContext(CommandContext( assert complete_xonfig(
args=(CommandArg("xonfig"),), arg_index=1, prefix="-" CompletionContext(
))) == {"-h"} CommandContext(args=(CommandArg("xonfig"),), arg_index=1, prefix="-")
)
) == {"-h"}
def test_xonfig_colors(monkeypatch): def test_xonfig_colors(monkeypatch):
monkeypatch.setattr("xonsh.tools.color_style_names", lambda: ["blue", "brown", "other"]) monkeypatch.setattr(
assert complete_xonfig(CompletionContext(CommandContext( "xonsh.tools.color_style_names", lambda: ["blue", "brown", "other"]
args=(CommandArg("xonfig"), CommandArg("colors")), arg_index=2, prefix="b" )
))) == {"blue", "brown"} assert (
complete_xonfig(
CompletionContext(
CommandContext(
args=(CommandArg("xonfig"), CommandArg("colors")),
arg_index=2,
prefix="b",
)
)
)
== {"blue", "brown"}
)
def test_xontrib(): def test_xontrib():
assert complete_xontrib(CompletionContext(CommandContext( assert complete_xontrib(
args=(CommandArg("xontrib"),), arg_index=1, prefix="l" CompletionContext(
))) == {"list", "load"} CommandContext(args=(CommandArg("xontrib"),), arg_index=1, prefix="l")
)
) == {"list", "load"}

View file

@ -2,30 +2,21 @@ import builtins
import glob import glob
import os import os
import sys import sys
import types
import typing as tp
from unittest.mock import MagicMock
import pytest import pytest
from xonsh.built_ins import ( from xonsh.built_ins import XonshSession, XSH
ensure_list_of_strs,
XonshSession,
pathsearch,
globsearch,
regexsearch,
list_of_strs_or_callables,
list_of_list_of_strs_outer_product,
call_macro,
enter_macro,
path_literal,
_BuiltIns,
eval_fstring_field,
)
from xonsh.execer import Execer from xonsh.execer import Execer
from xonsh.jobs import tasks from xonsh.jobs import tasks
from xonsh.events import events from xonsh.events import events
from xonsh.platform import ON_WINDOWS from xonsh.platform import ON_WINDOWS
from xonsh.parsers.completion_context import CompletionContextParser from xonsh.parsers.completion_context import CompletionContextParser
from tools import DummyShell, sp, DummyCommandsCache, DummyEnv, DummyHistory from xonsh import commands_cache
from tools import DummyShell, sp, DummyEnv, DummyHistory
@pytest.fixture @pytest.fixture
@ -35,54 +26,26 @@ def source_path():
return os.path.dirname(pwd) return os.path.dirname(pwd)
def ensure_attached_session(monkeypatch, session):
for i in range(1, 11):
# next try to monkey patch with raising.
try:
monkeypatch.setattr(builtins, "__xonsh__", session, raising=True)
except AttributeError:
pass
if hasattr(builtins, "__xonsh__"):
break
# first try to monkey patch without raising.
try:
monkeypatch.setattr(builtins, "__xonsh__", session, raising=False)
except AttributeError:
pass
if hasattr(builtins, "__xonsh__"):
break
# now just try to apply it
builtins.__xonsh__ = session
if hasattr(builtins, "__xonsh__"):
break
# I have no idea why pytest fails to assign into the builtins module
# sometimes, but the following globals trick seems to work -scopatz
globals()["__builtins__"]["__xonsh__"] = session
if hasattr(builtins, "__xonsh__"):
break
else:
raise RuntimeError(
"Could not attach xonsh session to builtins " "after many tries!"
)
@pytest.fixture @pytest.fixture
def xonsh_execer(monkeypatch): def xonsh_execer(monkeypatch):
"""Initiate the Execer with a mocked nop `load_builtins`""" """Initiate the Execer with a mocked nop `load_builtins`"""
monkeypatch.setattr(
"xonsh.built_ins.load_builtins.__code__",
(lambda *args, **kwargs: None).__code__,
)
added_session = False
if not hasattr(builtins, "__xonsh__"):
added_session = True
ensure_attached_session(monkeypatch, XonshSession())
execer = Execer(unload=False) execer = Execer(unload=False)
builtins.__xonsh__.execer = execer monkeypatch.setattr(XSH, "execer", execer)
yield execer yield execer
if added_session:
monkeypatch.delattr(builtins, "__xonsh__", raising=False)
@pytest.fixture
def patch_commands_cache_bins(xession, tmp_path, monkeypatch):
def _factory(binaries: tp.List[str]):
if not xession.env.get("PATH"):
xession.env["PATH"] = [tmp_path]
exec_mock = MagicMock(return_value=binaries)
monkeypatch.setattr(commands_cache, "executables_in", exec_mock)
cc = commands_cache.CommandsCache()
xession.commands_cache = cc
return cc
return _factory
@pytest.fixture @pytest.fixture
@ -107,60 +70,60 @@ def xonsh_events():
def xonsh_builtins(monkeypatch, xonsh_events): def xonsh_builtins(monkeypatch, xonsh_events):
"""Mock out most of the builtins xonsh attributes.""" """Mock out most of the builtins xonsh attributes."""
old_builtins = set(dir(builtins)) old_builtins = set(dir(builtins))
execer = getattr(getattr(builtins, "__xonsh__", None), "execer", None) XSH.load(
session = XonshSession(execer=execer, ctx={}) execer=Execer(unload=False),
ensure_attached_session(monkeypatch, session) ctx={},
builtins.__xonsh__.env = DummyEnv()
if ON_WINDOWS:
builtins.__xonsh__.env["PATHEXT"] = [".EXE", ".BAT", ".CMD"]
builtins.__xonsh__.shell = DummyShell()
builtins.__xonsh__.help = lambda x: x
builtins.__xonsh__.glob = glob.glob
builtins.__xonsh__.exit = False
builtins.__xonsh__.superhelp = lambda x: x
builtins.__xonsh__.pathsearch = pathsearch
builtins.__xonsh__.globsearch = globsearch
builtins.__xonsh__.regexsearch = regexsearch
builtins.__xonsh__.regexpath = lambda x: []
builtins.__xonsh__.expand_path = lambda x: x
builtins.__xonsh__.subproc_captured = sp
builtins.__xonsh__.subproc_uncaptured = sp
builtins.__xonsh__.stdout_uncaptured = None
builtins.__xonsh__.stderr_uncaptured = None
builtins.__xonsh__.ensure_list_of_strs = ensure_list_of_strs
builtins.__xonsh__.commands_cache = DummyCommandsCache()
builtins.__xonsh__.all_jobs = {}
builtins.__xonsh__.list_of_strs_or_callables = list_of_strs_or_callables
builtins.__xonsh__.list_of_list_of_strs_outer_product = (
list_of_list_of_strs_outer_product
) )
builtins.__xonsh__.eval_fstring_field = eval_fstring_field if ON_WINDOWS:
builtins.__xonsh__.history = DummyHistory() XSH.env["PATHEXT"] = [".EXE", ".BAT", ".CMD"]
builtins.__xonsh__.subproc_captured_stdout = sp
builtins.__xonsh__.subproc_captured_inject = sp def locate_binary(self, name):
builtins.__xonsh__.subproc_captured_object = sp return os.path.join(os.path.dirname(__file__), "bin", name)
builtins.__xonsh__.subproc_captured_hiddenobject = sp
builtins.__xonsh__.enter_macro = enter_macro for attr, val in [
builtins.__xonsh__.completers = None ("env", DummyEnv()),
builtins.__xonsh__.call_macro = call_macro ("shell", DummyShell()),
builtins.__xonsh__.enter_macro = enter_macro ("help", lambda x: x),
builtins.__xonsh__.path_literal = path_literal ("aliases", {}),
builtins.__xonsh__.builtins = _BuiltIns(execer=execer) ("exit", False),
builtins.evalx = eval ("history", DummyHistory()),
builtins.execx = None # ("subproc_captured", sp),
builtins.compilex = None ("subproc_uncaptured", sp),
builtins.aliases = {} ("subproc_captured_stdout", sp),
# Unlike all the other stuff, this has to refer to the "real" one because all modules that would ("subproc_captured_inject", sp),
# be firing events on the global instance. ("subproc_captured_object", sp),
builtins.events = xonsh_events ("subproc_captured_hiddenobject", sp),
]:
monkeypatch.setattr(XSH, attr, val)
cc = XSH.commands_cache
monkeypatch.setattr(cc, "locate_binary", types.MethodType(locate_binary, cc))
for attr, val in [
("evalx", eval),
("execx", None),
("compilex", None),
# Unlike all the other stuff, this has to refer to the "real" one because all modules that would
# be firing events on the global instance.
("events", xonsh_events),
]:
# attributes to builtins are dynamicProxy and should pickup the following
monkeypatch.setattr(XSH.builtins, attr, val)
# todo: remove using builtins for tests at all
yield builtins yield builtins
monkeypatch.delattr(builtins, "__xonsh__", raising=False) XSH.unload()
for attr in set(dir(builtins)) - old_builtins: for attr in set(dir(builtins)) - old_builtins:
if hasattr(builtins, attr): if hasattr(builtins, attr):
delattr(builtins, attr) delattr(builtins, attr)
tasks.clear() # must to this to enable resetting all_jobs tasks.clear() # must to this to enable resetting all_jobs
@pytest.fixture
def xession(xonsh_builtins) -> XonshSession:
return XSH
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def completion_context_parse(): def completion_context_parse():
return CompletionContextParser().parse return CompletionContextParser().parse

View file

@ -13,8 +13,8 @@ from .tools import skip_if_on_windows
@skip_if_on_windows @skip_if_on_windows
def test_cmds_to_specs_thread_subproc(xonsh_builtins): def test_cmds_to_specs_thread_subproc(xession):
env = xonsh_builtins.__xonsh__.env env = xession.env
cmds = [["pwd"]] cmds = [["pwd"]]
# First check that threadable subprocs become threadable # First check that threadable subprocs become threadable
env["THREAD_SUBPROCS"] = True env["THREAD_SUBPROCS"] = True

View file

@ -7,7 +7,7 @@ from xonsh.prompt.base import PromptFormatter, PROMPT_FIELDS
@pytest.fixture @pytest.fixture
def formatter(xonsh_builtins): def formatter(xession):
return PromptFormatter() return PromptFormatter()
@ -75,8 +75,8 @@ def test_format_prompt_with_broken_template_in_func(inp, formatter):
assert "{user" in formatter(lambda: inp) assert "{user" in formatter(lambda: inp)
def test_format_prompt_with_invalid_func(formatter, xonsh_builtins): def test_format_prompt_with_invalid_func(formatter, xession):
xonsh_builtins.__xonsh__.env = Env() xession.env = Env()
def p(): def p():
foo = bar # raises exception # noqa foo = bar # raises exception # noqa
@ -85,8 +85,8 @@ def test_format_prompt_with_invalid_func(formatter, xonsh_builtins):
assert isinstance(formatter(p), str) assert isinstance(formatter(p), str)
def test_format_prompt_with_func_that_raises(formatter, capsys, xonsh_builtins): def test_format_prompt_with_func_that_raises(formatter, capsys, xession):
xonsh_builtins.__xonsh__.env = Env() xession.env = Env()
template = "tt {zerodiv} tt" template = "tt {zerodiv} tt"
exp = "tt {BACKGROUND_RED}{ERROR:zerodiv}{RESET} tt" exp = "tt {BACKGROUND_RED}{ERROR:zerodiv}{RESET} tt"
fields = {"zerodiv": lambda: 1 / 0} fields = {"zerodiv": lambda: 1 / 0}
@ -96,25 +96,23 @@ def test_format_prompt_with_func_that_raises(formatter, capsys, xonsh_builtins):
assert "prompt: error" in err assert "prompt: error" in err
def test_format_prompt_with_no_env(formatter, xonsh_builtins, live_fields): def test_format_prompt_with_no_env(formatter, xession, live_fields):
xonsh_builtins.__xonsh__.shell.prompt_formatter = formatter xession.shell.prompt_formatter = formatter
env = Env() env = Env()
env.pop("VIRTUAL_ENV", None) # For virtualenv env.pop("VIRTUAL_ENV", None) # For virtualenv
env.pop("CONDA_DEFAULT_ENV", None) # For conda/CircleCI env.pop("CONDA_DEFAULT_ENV", None) # For conda/CircleCI
xonsh_builtins.__xonsh__.env = env xession.env = env
assert formatter("{env_name}", fields=live_fields) == "" assert formatter("{env_name}", fields=live_fields) == ""
@pytest.mark.parametrize("envname", ["env", "foo", "bar"]) @pytest.mark.parametrize("envname", ["env", "foo", "bar"])
def test_format_prompt_with_various_envs( def test_format_prompt_with_various_envs(formatter, xession, live_fields, envname):
formatter, xonsh_builtins, live_fields, envname xession.shell.prompt_formatter = formatter
):
xonsh_builtins.__xonsh__.shell.prompt_formatter = formatter
env = Env(VIRTUAL_ENV=envname) env = Env(VIRTUAL_ENV=envname)
xonsh_builtins.__xonsh__.env = env xession.env = env
exp = live_fields["env_prefix"] + envname + live_fields["env_postfix"] exp = live_fields["env_prefix"] + envname + live_fields["env_postfix"]
assert formatter("{env_name}", fields=live_fields) == exp assert formatter("{env_name}", fields=live_fields) == exp
@ -122,13 +120,11 @@ def test_format_prompt_with_various_envs(
@pytest.mark.parametrize("pre", ["(", "[[", "", " "]) @pytest.mark.parametrize("pre", ["(", "[[", "", " "])
@pytest.mark.parametrize("post", [")", "]]", "", " "]) @pytest.mark.parametrize("post", [")", "]]", "", " "])
def test_format_prompt_with_various_prepost( def test_format_prompt_with_various_prepost(formatter, xession, live_fields, pre, post):
formatter, xonsh_builtins, live_fields, pre, post xession.shell.prompt_formatter = formatter
):
xonsh_builtins.__xonsh__.shell.prompt_formatter = formatter
env = Env(VIRTUAL_ENV="env") env = Env(VIRTUAL_ENV="env")
xonsh_builtins.__xonsh__.env = env xession.env = env
live_fields.update({"env_prefix": pre, "env_postfix": post}) live_fields.update({"env_prefix": pre, "env_postfix": post})
@ -136,26 +132,26 @@ def test_format_prompt_with_various_prepost(
assert formatter("{env_name}", fields=live_fields) == exp assert formatter("{env_name}", fields=live_fields) == exp
def test_noenv_with_disable_set(formatter, xonsh_builtins, live_fields): def test_noenv_with_disable_set(formatter, xession, live_fields):
xonsh_builtins.__xonsh__.shell.prompt_formatter = formatter xession.shell.prompt_formatter = formatter
env = Env(VIRTUAL_ENV="env", VIRTUAL_ENV_DISABLE_PROMPT=1) env = Env(VIRTUAL_ENV="env", VIRTUAL_ENV_DISABLE_PROMPT=1)
xonsh_builtins.__xonsh__.env = env xession.env = env
exp = "" exp = ""
assert formatter("{env_name}", fields=live_fields) == exp assert formatter("{env_name}", fields=live_fields) == exp
@pytest.mark.parametrize("disable", [0, 1]) @pytest.mark.parametrize("disable", [0, 1])
def test_custom_env_overrides_default(formatter, xonsh_builtins, live_fields, disable): def test_custom_env_overrides_default(formatter, xession, live_fields, disable):
xonsh_builtins.__xonsh__.shell.prompt_formatter = formatter xession.shell.prompt_formatter = formatter
prompt = "!venv active! " prompt = "!venv active! "
env = Env( env = Env(
VIRTUAL_ENV="env", VIRTUAL_ENV_PROMPT=prompt, VIRTUAL_ENV_DISABLE_PROMPT=disable VIRTUAL_ENV="env", VIRTUAL_ENV_PROMPT=prompt, VIRTUAL_ENV_DISABLE_PROMPT=disable
) )
xonsh_builtins.__xonsh__.env = env xession.env = env
exp = "" if disable else prompt exp = "" if disable else prompt
assert formatter("{env_name}", fields=live_fields) == exp assert formatter("{env_name}", fields=live_fields) == exp

View file

@ -53,14 +53,14 @@ def test_test_repo(test_repo):
assert test_file.exists() assert test_file.exists()
def test_no_repo(xonsh_builtins, tmpdir): def test_no_repo(xession, tmpdir):
xonsh_builtins.__xonsh__.env = Env(VC_BRANCH_TIMEOUT=2, PWD=tmpdir) xession.env = Env(VC_BRANCH_TIMEOUT=2, PWD=tmpdir)
assert vc.get_hg_branch() is None assert vc.get_hg_branch() is None
assert vc.get_git_branch() is None assert vc.get_git_branch() is None
def test_vc_get_branch(test_repo, xonsh_builtins): def test_vc_get_branch(test_repo, xession):
xonsh_builtins.__xonsh__.env = Env(VC_BRANCH_TIMEOUT=2, PWD=test_repo["dir"]) xession.env = Env(VC_BRANCH_TIMEOUT=2, PWD=test_repo["dir"])
# get corresponding function from vc module # get corresponding function from vc module
get_branch = "get_{}_branch".format(test_repo["vc"]) get_branch = "get_{}_branch".format(test_repo["vc"])
branch = getattr(vc, get_branch)() branch = getattr(vc, get_branch)()
@ -84,9 +84,9 @@ current = yellow reverse
assert not branch.startswith(u"\u001b[") assert not branch.startswith(u"\u001b[")
def test_current_branch_calls_locate_binary_for_empty_cmds_cache(xonsh_builtins): def test_current_branch_calls_locate_binary_for_empty_cmds_cache(xession):
cache = xonsh_builtins.__xonsh__.commands_cache cache = xession.commands_cache
xonsh_builtins.__xonsh__.env = DummyEnv(VC_BRANCH_TIMEOUT=1) xession.env = DummyEnv(VC_BRANCH_TIMEOUT=1)
cache.is_empty = Mock(return_value=True) cache.is_empty = Mock(return_value=True)
cache.locate_binary = Mock(return_value="") cache.locate_binary = Mock(return_value="")
vc.current_branch() vc.current_branch()
@ -94,10 +94,10 @@ def test_current_branch_calls_locate_binary_for_empty_cmds_cache(xonsh_builtins)
def test_current_branch_does_not_call_locate_binary_for_non_empty_cmds_cache( def test_current_branch_does_not_call_locate_binary_for_non_empty_cmds_cache(
xonsh_builtins, xession,
): ):
cache = xonsh_builtins.__xonsh__.commands_cache cache = xession.commands_cache
xonsh_builtins.__xonsh__.env = DummyEnv(VC_BRANCH_TIMEOUT=1) xession.env = DummyEnv(VC_BRANCH_TIMEOUT=1)
cache.is_empty = Mock(return_value=False) cache.is_empty = Mock(return_value=False)
cache.locate_binary = Mock(return_value="") cache.locate_binary = Mock(return_value="")
# make lazy locate return nothing to avoid running vc binaries # make lazy locate return nothing to avoid running vc binaries
@ -106,9 +106,9 @@ def test_current_branch_does_not_call_locate_binary_for_non_empty_cmds_cache(
assert not cache.locate_binary.called assert not cache.locate_binary.called
def test_dirty_working_directory(test_repo, xonsh_builtins): def test_dirty_working_directory(test_repo, xession):
get_dwd = "{}_dirty_working_directory".format(test_repo["vc"]) get_dwd = "{}_dirty_working_directory".format(test_repo["vc"])
xonsh_builtins.__xonsh__.env = Env(VC_BRANCH_TIMEOUT=2, PWD=test_repo["dir"]) xession.env = Env(VC_BRANCH_TIMEOUT=2, PWD=test_repo["dir"])
# By default, git / hg do not care about untracked files # By default, git / hg do not care about untracked files
Path("second-test-file").touch() Path("second-test-file").touch()
@ -120,9 +120,9 @@ def test_dirty_working_directory(test_repo, xonsh_builtins):
@pytest.mark.parametrize("include_untracked", [True, False]) @pytest.mark.parametrize("include_untracked", [True, False])
def test_git_dirty_working_directory_includes_untracked( def test_git_dirty_working_directory_includes_untracked(
xonsh_builtins, test_repo, include_untracked xession, test_repo, include_untracked
): ):
xonsh_builtins.__xonsh__.env = DummyEnv(VC_GIT_INCLUDE_UNTRACKED=include_untracked) xession.env = DummyEnv(VC_GIT_INCLUDE_UNTRACKED=include_untracked)
if test_repo["vc"] != "git": if test_repo["vc"] != "git":
return return

View file

@ -57,9 +57,9 @@ def test_eval_recursive(xonsh_execer, xonsh_builtins):
@skip_if_on_windows @skip_if_on_windows
def test_eval_recursive_callable_partial(xonsh_execer, xonsh_builtins): def test_eval_recursive_callable_partial(xonsh_execer, xession):
ales = make_aliases() ales = make_aliases()
xonsh_builtins.__xonsh__.env = Env(HOME=os.path.expanduser("~")) xession.env = Env(HOME=os.path.expanduser("~"))
assert ales.get("indirect_cd")(["arg2", "arg3"]) == ["..", "arg2", "arg3"] assert ales.get("indirect_cd")(["arg2", "arg3"]) == ["..", "arg2", "arg3"]
@ -151,44 +151,44 @@ def test_subprocess_io_operators(xonsh_execer, xonsh_builtins, alias):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"alias", "alias",
[ [
{'echocat': 'ls'}, {"echocat": "ls"},
], ],
) )
def test_dict_merging(xonsh_execer, xonsh_builtins, alias): def test_dict_merging(xonsh_execer, xonsh_builtins, alias):
ales = make_aliases() ales = make_aliases()
assert (ales | alias)['echocat'] == ['ls'] assert (ales | alias)["echocat"] == ["ls"]
assert (alias | ales)['echocat'] == ['ls'] assert (alias | ales)["echocat"] == ["ls"]
assert 'echocat' not in ales assert "echocat" not in ales
@pytest.mark.parametrize( @pytest.mark.parametrize(
"alias", "alias",
[ [
{'echocat': 'echo Why do people still use python2.7?'}, {"echocat": "echo Why do people still use python2.7?"},
{'echocat': 'echo Why?'}, {"echocat": "echo Why?"},
], ],
) )
def test_dict_merging_assignment(xonsh_execer, xonsh_builtins, alias): def test_dict_merging_assignment(xonsh_execer, xonsh_builtins, alias):
ales = make_aliases() ales = make_aliases()
ales |= alias ales |= alias
assert 'echocat' in ales assert "echocat" in ales
assert ' '.join(ales['echocat']) == alias['echocat'] assert " ".join(ales["echocat"]) == alias["echocat"]
ales = make_aliases() ales = make_aliases()
alias |= ales alias |= ales
assert 'o' in alias assert "o" in alias
assert alias['o'] == ales['o'] assert alias["o"] == ales["o"]
def test_exec_alias_args(xonsh_execer, xonsh_builtins): def test_exec_alias_args(xonsh_execer, xonsh_builtins):
stack = inspect.stack() stack = inspect.stack()
try: try:
ExecAlias('myargs = $args')(['arg0'], stack=stack) ExecAlias("myargs = $args")(["arg0"], stack=stack)
ExecAlias('myarg0 = $arg0')(['arg0'], stack=stack) ExecAlias("myarg0 = $arg0")(["arg0"], stack=stack)
except KeyError: except KeyError:
assert False assert False
assert stack[0][0].f_locals['myargs'] == ['arg0'] assert stack[0][0].f_locals["myargs"] == ["arg0"]
assert stack[0][0].f_locals['myarg0'] == 'arg0' assert stack[0][0].f_locals["myarg0"] == "arg0"

View file

@ -149,7 +149,7 @@ def test_ansi_color_name_to_escape_code_for_all_styles(color, style):
("monokai"), # defined in `ansi_colors.py` ("monokai"), # defined in `ansi_colors.py`
("rainbow_dash"), # not in `ansi_colors.py`, but in pygments ("rainbow_dash"), # not in `ansi_colors.py`, but in pygments
("foobar"), # invalid, should not fail ("foobar"), # invalid, should not fail
] ],
) )
def test_ansi_style_by_name(style_name): def test_ansi_style_by_name(style_name):
style = ansi_style_by_name(style_name) style = ansi_style_by_name(style_name)

View file

@ -7,10 +7,10 @@ from xonsh.base_shell import BaseShell
from xonsh.shell import transform_command from xonsh.shell import transform_command
def test_pwd_tracks_cwd(xonsh_builtins, xonsh_execer, tmpdir_factory, monkeypatch): def test_pwd_tracks_cwd(xession, xonsh_execer, tmpdir_factory, monkeypatch):
asubdir = str(tmpdir_factory.mktemp("asubdir")) asubdir = str(tmpdir_factory.mktemp("asubdir"))
cur_wd = os.getcwd() cur_wd = os.getcwd()
xonsh_builtins.__xonsh__.env = Env( xession.env = Env(
PWD=cur_wd, XONSH_CACHE_SCRIPTS=False, XONSH_CACHE_EVERYTHING=False PWD=cur_wd, XONSH_CACHE_SCRIPTS=False, XONSH_CACHE_EVERYTHING=False
) )
@ -22,17 +22,13 @@ def test_pwd_tracks_cwd(xonsh_builtins, xonsh_execer, tmpdir_factory, monkeypatc
bc.default('os.chdir(r"' + asubdir + '")') bc.default('os.chdir(r"' + asubdir + '")')
assert os.path.abspath(os.getcwd()) == os.path.abspath(asubdir) assert os.path.abspath(os.getcwd()) == os.path.abspath(asubdir)
assert os.path.abspath(os.getcwd()) == os.path.abspath( assert os.path.abspath(os.getcwd()) == os.path.abspath(xession.env["PWD"])
xonsh_builtins.__xonsh__.env["PWD"] assert "OLDPWD" in xession.env
) assert os.path.abspath(cur_wd) == os.path.abspath(xession.env["OLDPWD"])
assert "OLDPWD" in xonsh_builtins.__xonsh__.env
assert os.path.abspath(cur_wd) == os.path.abspath(
xonsh_builtins.__xonsh__.env["OLDPWD"]
)
def test_transform(xonsh_builtins): def test_transform(xession):
@xonsh_builtins.events.on_transform_command @xession.builtins.events.on_transform_command
def spam2egg(cmd, **_): def spam2egg(cmd, **_):
if cmd == "spam": if cmd == "spam":
return "egg" return "egg"

View file

@ -33,10 +33,10 @@ import pytest
(["aa 1 2", "ab 3 4"], "echo !ab >log", "echo ab 3 4 >log"), (["aa 1 2", "ab 3 4"], "echo !ab >log", "echo ab 3 4 >log"),
], ],
) )
def test_preproc(history, inp, exp, xonsh_builtins): def test_preproc(history, inp, exp, xession):
"""Test the bash preprocessor.""" """Test the bash preprocessor."""
from xontrib.bashisms import bash_preproc from xontrib.bashisms import bash_preproc
xonsh_builtins.__xonsh__.history.inps = history xession.history.inps = history
obs = bash_preproc(inp) obs = bash_preproc(inp)
assert exp == obs assert exp == obs

View file

@ -40,10 +40,10 @@ def test_reglob_tests(testfile):
@pytest.fixture @pytest.fixture
def home_env(xonsh_builtins): def home_env(xession):
"""Set `__xonsh__.env ` to a new Env instance on `xonsh_builtins`""" """Set `__xonsh__.env ` to a new Env instance on `xonsh_builtins`"""
xonsh_builtins.__xonsh__.env = Env(HOME=HOME_PATH) xession.env = Env(HOME=HOME_PATH)
return xonsh_builtins return xession
@skip_if_on_windows @skip_if_on_windows

View file

@ -1,5 +1,4 @@
import os import os
import builtins
import pickle import pickle
import time import time
from unittest.mock import MagicMock from unittest.mock import MagicMock
@ -13,7 +12,6 @@ from xonsh.commands_cache import (
predict_true, predict_true,
predict_false, predict_false,
) )
from xonsh import commands_cache
from tools import skip_if_on_windows from tools import skip_if_on_windows
@ -31,13 +29,10 @@ def test_predict_threadable_unknown_command(xonsh_builtins):
@pytest.fixture @pytest.fixture
def commands_cache_tmp(xonsh_builtins, tmp_path, monkeypatch): def commands_cache_tmp(xession, tmp_path, monkeypatch, patch_commands_cache_bins):
xonsh_builtins.__xonsh__.env["XONSH_DATA_DIR"] = tmp_path xession.env["XONSH_DATA_DIR"] = tmp_path
xonsh_builtins.__xonsh__.env["COMMANDS_CACHE_SAVE_INTERMEDIATE"] = True xession.env["COMMANDS_CACHE_SAVE_INTERMEDIATE"] = True
xonsh_builtins.__xonsh__.env["PATH"] = [tmp_path] return patch_commands_cache_bins(["bin1", "bin2"])
exec_mock = MagicMock(return_value=["bin1", "bin2"])
monkeypatch.setattr(commands_cache, "executables_in", exec_mock)
return commands_cache.CommandsCache()
def test_commands_cached_between_runs(commands_cache_tmp, tmp_path): def test_commands_cached_between_runs(commands_cache_tmp, tmp_path):
@ -158,9 +153,9 @@ def test_commands_cache_predictor_default(args, xonsh_builtins):
@skip_if_on_windows @skip_if_on_windows
def test_cd_is_only_functional_alias(xonsh_builtins): def test_cd_is_only_functional_alias(xession):
cc = CommandsCache() cc = CommandsCache()
builtins.aliases["cd"] = lambda args: os.chdir(args[0]) xession.aliases["cd"] = lambda args: os.chdir(args[0])
assert cc.is_only_functional_alias("cd") assert cc.is_only_functional_alias("cd")
@ -170,15 +165,15 @@ def test_non_exist_is_only_functional_alias(xonsh_builtins):
@skip_if_on_windows @skip_if_on_windows
def test_bash_is_only_functional_alias(xonsh_builtins): def test_bash_is_only_functional_alias(xession):
builtins.__xonsh__.env["PATH"] = os.environ["PATH"].split(os.pathsep) xession.env["PATH"] = os.environ["PATH"].split(os.pathsep)
cc = CommandsCache() cc = CommandsCache()
assert not cc.is_only_functional_alias("bash") assert not cc.is_only_functional_alias("bash")
@skip_if_on_windows @skip_if_on_windows
def test_bash_and_is_alias_is_only_functional_alias(xonsh_builtins): def test_bash_and_is_alias_is_only_functional_alias(xession):
builtins.__xonsh__.env["PATH"] = os.environ["PATH"].split(os.pathsep) xession.env["PATH"] = os.environ["PATH"].split(os.pathsep)
cc = CommandsCache() cc = CommandsCache()
builtins.aliases["bash"] = lambda args: os.chdir(args[0]) xession.aliases["bash"] = lambda args: os.chdir(args[0])
assert not cc.is_only_functional_alias("bash") assert not cc.is_only_functional_alias("bash")

View file

@ -1,7 +1,11 @@
"""Tests for the base completer's logic (xonsh/completer.py)""" """Tests for the base completer's logic (xonsh/completer.py)"""
import pytest import pytest
from xonsh.completers.tools import RichCompletion, contextual_command_completer, non_exclusive_completer from xonsh.completers.tools import (
RichCompletion,
contextual_command_completer,
non_exclusive_completer,
)
from xonsh.completer import Completer from xonsh.completer import Completer
from xonsh.parsers.completion_context import CommandContext from xonsh.parsers.completion_context import CommandContext
@ -13,9 +17,9 @@ def completer():
@pytest.fixture @pytest.fixture
def completers_mock(xonsh_builtins, monkeypatch): def completers_mock(xession, monkeypatch):
completers = {} completers = {}
monkeypatch.setattr(xonsh_builtins.__xonsh__, "completers", completers) monkeypatch.setattr(xession, "completers", completers)
return completers return completers
@ -34,33 +38,40 @@ def test_sanity(completer, completers_mock):
assert completer.complete("pre", "", 0, 0) == (("comp",), 2) assert completer.complete("pre", "", 0, 0) == (("comp",), 2)
# RichCompletion: # RichCompletion:
completers_mock["a"] = lambda *a: {RichCompletion("comp", prefix_len=5)} completers_mock["a"] = lambda *a: {RichCompletion("comp", prefix_len=5)}
assert completer.complete("pre", "", 0, 0) == ((RichCompletion("comp", prefix_len=5),), 3) assert completer.complete("pre", "", 0, 0) == (
(RichCompletion("comp", prefix_len=5),),
3,
)
def test_cursor_after_closing_quote(completer, completers_mock): def test_cursor_after_closing_quote(completer, completers_mock):
"""See ``Completer.complete`` in ``xonsh/completer.py``""" """See ``Completer.complete`` in ``xonsh/completer.py``"""
@contextual_command_completer @contextual_command_completer
def comp(context: CommandContext): def comp(context: CommandContext):
return {context.prefix + "1", context.prefix + "2"} return {context.prefix + "1", context.prefix + "2"}
completers_mock["a"] = comp completers_mock["a"] = comp
assert completer.complete("", "", 0, 0, {}, multiline_text="'test'", cursor_index=6) == ( assert completer.complete(
("test1'", "test2'"), 5 "", "", 0, 0, {}, multiline_text="'test'", cursor_index=6
) ) == (("test1'", "test2'"), 5)
assert completer.complete("", "", 0, 0, {}, multiline_text="'''test'''", cursor_index=10) == ( assert completer.complete(
("test1'''", "test2'''"), 7 "", "", 0, 0, {}, multiline_text="'''test'''", cursor_index=10
) ) == (("test1'''", "test2'''"), 7)
def test_cursor_after_closing_quote_override(completer, completers_mock): def test_cursor_after_closing_quote_override(completer, completers_mock):
"""Test overriding the default values""" """Test overriding the default values"""
@contextual_command_completer @contextual_command_completer
def comp(context: CommandContext): def comp(context: CommandContext):
return { return {
# replace the closing quote with "a" # replace the closing quote with "a"
RichCompletion("a", prefix_len=len(context.closing_quote), append_closing_quote=False), RichCompletion(
"a", prefix_len=len(context.closing_quote), append_closing_quote=False
),
# add text after the closing quote # add text after the closing quote
RichCompletion(context.prefix + "_no_quote", append_closing_quote=False), RichCompletion(context.prefix + "_no_quote", append_closing_quote=False),
# sanity # sanity
@ -69,66 +80,69 @@ def test_cursor_after_closing_quote_override(completer, completers_mock):
completers_mock["a"] = comp completers_mock["a"] = comp
assert completer.complete("", "", 0, 0, {}, multiline_text="'test'", cursor_index=6) == ( assert completer.complete(
"", "", 0, 0, {}, multiline_text="'test'", cursor_index=6
) == (
( (
"a", "a",
"test1'", "test1'",
"test_no_quote", "test_no_quote",
), 5 ),
5,
) )
assert completer.complete("", "", 0, 0, {}, multiline_text="'''test'''", cursor_index=10) == ( assert completer.complete(
"", "", 0, 0, {}, multiline_text="'''test'''", cursor_index=10
) == (
( (
"a", "a",
"test1'''", "test1'''",
"test_no_quote", "test_no_quote",
), 7 ),
7,
) )
def test_append_space(completer, completers_mock): def test_append_space(completer, completers_mock):
@contextual_command_completer @contextual_command_completer
def comp(context: CommandContext): def comp(context: CommandContext):
return { return {
RichCompletion(context.prefix + "a", append_space=True), RichCompletion(context.prefix + "a", append_space=True),
RichCompletion(context.prefix + " ", append_space=False), # bad usage RichCompletion(context.prefix + " ", append_space=False), # bad usage
RichCompletion(context.prefix + "b", append_space=True, append_closing_quote=False), RichCompletion(
context.prefix + "b", append_space=True, append_closing_quote=False
),
} }
completers_mock["a"] = comp completers_mock["a"] = comp
assert completer.complete("", "", 0, 0, {}, multiline_text="'test'", cursor_index=6) == ( assert completer.complete(
"", "", 0, 0, {}, multiline_text="'test'", cursor_index=6
) == (
( (
"test '", "test '",
"testa' ", "testa' ",
"testb ", "testb ",
), 5 ),
5,
) )
@pytest.mark.parametrize("middle_result, exp", ( @pytest.mark.parametrize(
"middle_result, exp",
( (
# stop at the first exclusive result
( (
{"b1", "b2"}, # stop at the first exclusive result
("a1", "a2", "b1", "b2") ({"b1", "b2"}, ("a1", "a2", "b1", "b2")),
), # pass empty exclusive results
# pass empty exclusive results ({}, ("a1", "a2", "c1", "c2")),
( # pass empty exclusive results
{}, (None, ("a1", "a2", "c1", "c2")),
("a1", "a2", "c1", "c2") # stop at StopIteration
), (StopIteration, ("a1", "a2")),
# pass empty exclusive results )
( ),
None, )
("a1", "a2", "c1", "c2")
),
# stop at StopIteration
(
StopIteration,
("a1", "a2")
),
)
))
def test_non_exclusive(completer, completers_mock, middle_result, exp): def test_non_exclusive(completer, completers_mock, middle_result, exp):
completers_mock["a"] = non_exclusive_completer(lambda *a: {"a1", "a2"}) completers_mock["a"] = non_exclusive_completer(lambda *a: {"a1", "a2"})

View file

@ -3,7 +3,12 @@ import typing as tp
import pytest import pytest
from xonsh.parsers.completion_context import CommandArg, CommandContext, CompletionContextParser, PythonContext from xonsh.parsers.completion_context import (
CommandArg,
CommandContext,
CompletionContextParser,
PythonContext,
)
DEBUG = False DEBUG = False
@ -24,7 +29,9 @@ def parse(command, inner_index):
return PARSER.parse(command, inner_index) return PARSER.parse(command, inner_index)
def assert_match(commandline, command_context=MISSING, python_context=MISSING, is_main_command=False): def assert_match(
commandline, command_context=MISSING, python_context=MISSING, is_main_command=False
):
if X in commandline: if X in commandline:
index = commandline.index(X) index = commandline.index(X)
commandline = commandline.replace(X, "") commandline = commandline.replace(X, "")
@ -32,7 +39,9 @@ def assert_match(commandline, command_context=MISSING, python_context=MISSING, i
index = len(commandline) index = len(commandline)
context = parse(commandline, index) context = parse(commandline, index)
if context is None: if context is None:
raise SyntaxError("Failed to parse the commandline - set DEBUG = True in this file to see the error") raise SyntaxError(
"Failed to parse the commandline - set DEBUG = True in this file to see the error"
)
if is_main_command and python_context is MISSING: if is_main_command and python_context is MISSING:
python_context = PythonContext(commandline, index) python_context = PythonContext(commandline, index)
if command_context is not MISSING: if command_context is not MISSING:
@ -48,17 +57,63 @@ COMMAND_EXAMPLES = (
(f"command {X}", CommandContext(args=(CommandArg("command"),), arg_index=1)), (f"command {X}", CommandContext(args=(CommandArg("command"),), arg_index=1)),
(f"{X} command", CommandContext(args=(CommandArg("command"),), arg_index=0)), (f"{X} command", CommandContext(args=(CommandArg("command"),), arg_index=0)),
(f" command {X}", CommandContext(args=(CommandArg("command"),), arg_index=1)), (f" command {X}", CommandContext(args=(CommandArg("command"),), arg_index=1)),
(f"command --{X}", CommandContext(args=(CommandArg("command"),), arg_index=1, prefix="--")), (
(f"command a {X}", CommandContext(args=(CommandArg("command"), CommandArg("a")), arg_index=2)), f"command --{X}",
(f"command a b{X}", CommandContext(args=(CommandArg("command"), CommandArg("a")), arg_index=2, prefix="b")), CommandContext(args=(CommandArg("command"),), arg_index=1, prefix="--"),
(f"command a b{X}", CommandContext(args=(CommandArg("command"), CommandArg("a")), arg_index=2, prefix="b")), ),
(f"command {X} a", CommandContext(args=(CommandArg("command"), CommandArg("a")), arg_index=1)), (
(f"command a {X} b", CommandContext(args=(CommandArg("command"), CommandArg("a"), CommandArg("b")), arg_index=2)), f"command a {X}",
(f"command -{X} b", CommandContext(args=(CommandArg("command"), CommandArg("b")), arg_index=1, prefix="-")), CommandContext(args=(CommandArg("command"), CommandArg("a")), arg_index=2),
(f"command a {X}b", CommandContext(args=(CommandArg("command"), CommandArg("a")), arg_index=2, suffix="b")), ),
(f"command a{X}b", CommandContext(args=(CommandArg("command"),), arg_index=1, prefix="a", suffix="b")), (
(f"'comm and' a{X}b", CommandContext( f"command a b{X}",
args=(CommandArg("comm and", opening_quote="'", closing_quote="'"),), arg_index=1, prefix="a", suffix="b")), CommandContext(
args=(CommandArg("command"), CommandArg("a")), arg_index=2, prefix="b"
),
),
(
f"command a b{X}",
CommandContext(
args=(CommandArg("command"), CommandArg("a")), arg_index=2, prefix="b"
),
),
(
f"command {X} a",
CommandContext(args=(CommandArg("command"), CommandArg("a")), arg_index=1),
),
(
f"command a {X} b",
CommandContext(
args=(CommandArg("command"), CommandArg("a"), CommandArg("b")), arg_index=2
),
),
(
f"command -{X} b",
CommandContext(
args=(CommandArg("command"), CommandArg("b")), arg_index=1, prefix="-"
),
),
(
f"command a {X}b",
CommandContext(
args=(CommandArg("command"), CommandArg("a")), arg_index=2, suffix="b"
),
),
(
f"command a{X}b",
CommandContext(
args=(CommandArg("command"),), arg_index=1, prefix="a", suffix="b"
),
),
(
f"'comm and' a{X}b",
CommandContext(
args=(CommandArg("comm and", opening_quote="'", closing_quote="'"),),
arg_index=1,
prefix="a",
suffix="b",
),
),
) )
EMPTY_COMMAND_EXAMPLES = ( EMPTY_COMMAND_EXAMPLES = (
@ -69,25 +124,100 @@ EMPTY_COMMAND_EXAMPLES = (
) )
STRING_ARGS_EXAMPLES = ( STRING_ARGS_EXAMPLES = (
(f"'comm an{X}d'", CommandContext( (
args=(), arg_index=0, prefix="comm an", suffix="d", opening_quote="'", closing_quote="'")), f"'comm an{X}d'",
(f"'comm and{X}'", CommandContext( CommandContext(
args=(), arg_index=0, prefix="comm and", suffix="", opening_quote="'", closing_quote="'")), args=(),
(f"'comm {X}'", CommandContext( arg_index=0,
args=(), arg_index=0, prefix="comm ", suffix="", opening_quote="'", closing_quote="'")), prefix="comm an",
(f"\"comm an{X}d\"", CommandContext( suffix="d",
args=(), arg_index=0, prefix="comm an", suffix="d", opening_quote="\"", closing_quote="\"")), opening_quote="'",
(f"'''comm an{X}d'''", CommandContext( closing_quote="'",
args=(), arg_index=0, prefix="comm an", suffix="d", opening_quote="'''", closing_quote="'''")), ),
(f"fr'comm an{X}d'", CommandContext( ),
args=(), arg_index=0, prefix="comm an", suffix="d", opening_quote="fr'", closing_quote="'")), (
(f"'()+{X}'", CommandContext( f"'comm and{X}'",
args=(), arg_index=0, prefix="()+", opening_quote="'", closing_quote="'")), CommandContext(
(f"'comm and'{X}", CommandContext( args=(),
args=(), arg_index=0, prefix="comm and", opening_quote="'", closing_quote="'", is_after_closing_quote=True)), arg_index=0,
(f"'''comm and'''{X}", CommandContext( prefix="comm and",
args=(), arg_index=0, prefix="comm and", suffix="",
opening_quote="'''", closing_quote="'''", is_after_closing_quote=True)), opening_quote="'",
closing_quote="'",
),
),
(
f"'comm {X}'",
CommandContext(
args=(),
arg_index=0,
prefix="comm ",
suffix="",
opening_quote="'",
closing_quote="'",
),
),
(
f'"comm an{X}d"',
CommandContext(
args=(),
arg_index=0,
prefix="comm an",
suffix="d",
opening_quote='"',
closing_quote='"',
),
),
(
f"'''comm an{X}d'''",
CommandContext(
args=(),
arg_index=0,
prefix="comm an",
suffix="d",
opening_quote="'''",
closing_quote="'''",
),
),
(
f"fr'comm an{X}d'",
CommandContext(
args=(),
arg_index=0,
prefix="comm an",
suffix="d",
opening_quote="fr'",
closing_quote="'",
),
),
(
f"'()+{X}'",
CommandContext(
args=(), arg_index=0, prefix="()+", opening_quote="'", closing_quote="'"
),
),
(
f"'comm and'{X}",
CommandContext(
args=(),
arg_index=0,
prefix="comm and",
opening_quote="'",
closing_quote="'",
is_after_closing_quote=True,
),
),
(
f"'''comm and'''{X}",
CommandContext(
args=(),
arg_index=0,
prefix="comm and",
opening_quote="'''",
closing_quote="'''",
is_after_closing_quote=True,
),
),
) )
COMMAND_EXAMPLES += STRING_ARGS_EXAMPLES COMMAND_EXAMPLES += STRING_ARGS_EXAMPLES
@ -99,10 +229,14 @@ def test_command(commandline, context):
assert_match(commandline, context, is_main_command=True) assert_match(commandline, context, is_main_command=True)
@pytest.mark.parametrize("commandline, context", tuple( @pytest.mark.parametrize(
(commandline, context) for commandline, context in STRING_ARGS_EXAMPLES "commandline, context",
if commandline.endswith("'") or commandline.endswith('"') tuple(
)) (commandline, context)
for commandline, context in STRING_ARGS_EXAMPLES
if commandline.endswith("'") or commandline.endswith('"')
),
)
def test_partial_string_arg(commandline, context): def test_partial_string_arg(commandline, context):
partial_commandline = commandline.rstrip("\"'") partial_commandline = commandline.rstrip("\"'")
partial_context = context._replace(closing_quote="") partial_context = context._replace(closing_quote="")
@ -112,50 +246,147 @@ def test_partial_string_arg(commandline, context):
CONT = "\\" "\n" CONT = "\\" "\n"
@pytest.mark.parametrize("commandline, context", ( @pytest.mark.parametrize(
"commandline, context",
(
# line continuations: # line continuations:
(f"echo {CONT}a {X}", CommandContext(args=(CommandArg("echo"), CommandArg("a")), arg_index=2)), (
(f"echo {CONT}{X}a {CONT} b", f"echo {CONT}a {X}",
CommandContext(args=(CommandArg("echo"), CommandArg("b")), arg_index=1, suffix="a")), CommandContext(args=(CommandArg("echo"), CommandArg("a")), arg_index=2),
(f"echo a{CONT}{X}b", ),
CommandContext(args=(CommandArg("echo"),), arg_index=1, prefix="a", suffix="b")), (
(f"echo a{X}{CONT}b", f"echo {CONT}{X}a {CONT} b",
CommandContext(args=(CommandArg("echo"),), arg_index=1, prefix="a", suffix="b")), CommandContext(
(f"echo ${CONT}(a) {CONT} {X}b", args=(CommandArg("echo"), CommandArg("b")), arg_index=1, suffix="a"
CommandContext(args=(CommandArg("echo"), CommandArg("$(a)")), arg_index=2, suffix="b")), ),
),
(
f"echo a{CONT}{X}b",
CommandContext(
args=(CommandArg("echo"),), arg_index=1, prefix="a", suffix="b"
),
),
(
f"echo a{X}{CONT}b",
CommandContext(
args=(CommandArg("echo"),), arg_index=1, prefix="a", suffix="b"
),
),
(
f"echo ${CONT}(a) {CONT} {X}b",
CommandContext(
args=(CommandArg("echo"), CommandArg("$(a)")), arg_index=2, suffix="b"
),
),
# line continuations in strings: # line continuations in strings:
(f"echo 'a{CONT}{X}b'", (
CommandContext(args=(CommandArg("echo"),), arg_index=1, prefix="a", suffix="b", opening_quote="'", f"echo 'a{CONT}{X}b'",
closing_quote="'")), CommandContext(
(f"echo '''a{CONT}{X}b'''", args=(CommandArg("echo"),),
CommandContext(args=(CommandArg("echo"),), arg_index=1, prefix="a", suffix="b", opening_quote="'''", arg_index=1,
closing_quote="'''")), prefix="a",
(f"echo 'a{CONT}{X}b", suffix="b",
CommandContext(args=(CommandArg("echo"),), arg_index=1, prefix="a", suffix="b", opening_quote="'")), opening_quote="'",
(f"echo '''a{CONT}{X}b", closing_quote="'",
CommandContext(args=(CommandArg("echo"),), arg_index=1, prefix="a", suffix="b", opening_quote="'''")), ),
(f"echo ''{CONT}'a{X}b", ),
CommandContext(args=(CommandArg("echo"),), arg_index=1, prefix="a", suffix="b", opening_quote="'''")), (
(f"echo '''a{CONT}{X} b", f"echo '''a{CONT}{X}b'''",
CommandContext(args=(CommandArg("echo"),), arg_index=1, prefix="a", suffix=" b", opening_quote="'''")), CommandContext(
args=(CommandArg("echo"),),
arg_index=1,
prefix="a",
suffix="b",
opening_quote="'''",
closing_quote="'''",
),
),
(
f"echo 'a{CONT}{X}b",
CommandContext(
args=(CommandArg("echo"),),
arg_index=1,
prefix="a",
suffix="b",
opening_quote="'",
),
),
(
f"echo '''a{CONT}{X}b",
CommandContext(
args=(CommandArg("echo"),),
arg_index=1,
prefix="a",
suffix="b",
opening_quote="'''",
),
),
(
f"echo ''{CONT}'a{X}b",
CommandContext(
args=(CommandArg("echo"),),
arg_index=1,
prefix="a",
suffix="b",
opening_quote="'''",
),
),
(
f"echo '''a{CONT}{X} b",
CommandContext(
args=(CommandArg("echo"),),
arg_index=1,
prefix="a",
suffix=" b",
opening_quote="'''",
),
),
# triple-quoted strings: # triple-quoted strings:
(f"echo '''a\nb{X}\nc'''", CommandContext( (
args=(CommandArg("echo"),), arg_index=1, f"echo '''a\nb{X}\nc'''",
prefix="a\nb", suffix="\nc", opening_quote="'''", closing_quote="'''")), CommandContext(
(f"echo '''a\n b{X} \n c'''", CommandContext( args=(CommandArg("echo"),),
args=(CommandArg("echo"),), arg_index=1, arg_index=1,
prefix="a\n b", suffix=" \n c", opening_quote="'''", closing_quote="'''")), prefix="a\nb",
suffix="\nc",
opening_quote="'''",
closing_quote="'''",
),
),
(
f"echo '''a\n b{X} \n c'''",
CommandContext(
args=(CommandArg("echo"),),
arg_index=1,
prefix="a\n b",
suffix=" \n c",
opening_quote="'''",
closing_quote="'''",
),
),
# partial triple-quoted strings: # partial triple-quoted strings:
(f"echo '''a\nb{X}\nc", CommandContext( (
args=(CommandArg("echo"),), arg_index=1, f"echo '''a\nb{X}\nc",
prefix="a\nb", suffix="\nc", opening_quote="'''")), CommandContext(
(f"echo '''a\n b{X} \n c", CommandContext( args=(CommandArg("echo"),),
args=(CommandArg("echo"),), arg_index=1, arg_index=1,
prefix="a\n b", suffix=" \n c", opening_quote="'''")), prefix="a\nb",
)) suffix="\nc",
opening_quote="'''",
),
),
(
f"echo '''a\n b{X} \n c",
CommandContext(
args=(CommandArg("echo"),),
arg_index=1,
prefix="a\n b",
suffix=" \n c",
opening_quote="'''",
),
),
),
)
def test_multiline_command(commandline, context): def test_multiline_command(commandline, context):
assert_match(commandline, context, is_main_command=True) assert_match(commandline, context, is_main_command=True)
@ -172,15 +403,34 @@ NESTING_EXAMPLES = (
) )
NESTED_SIMPLE_CMD_EXAMPLES = [ NESTED_SIMPLE_CMD_EXAMPLES = [
(nesting, f"simple {X}", CommandContext(args=(CommandArg("simple"),), arg_index=1, subcmd_opening=prefix)) (
for nesting, prefix in NESTING_EXAMPLES[1:]] nesting,
f"simple {X}",
CommandContext(
args=(CommandArg("simple"),), arg_index=1, subcmd_opening=prefix
),
)
for nesting, prefix in NESTING_EXAMPLES[1:]
]
@pytest.mark.parametrize("nesting, commandline, context", list(itertools.chain(( @pytest.mark.parametrize(
# complex subcommand in a simple nested expression "nesting, commandline, context",
(NESTING_EXAMPLES[0][0], commandline, context._replace(subcmd_opening=NESTING_EXAMPLES[0][1])) list(
for commandline, context in COMMAND_EXAMPLES itertools.chain(
), NESTED_SIMPLE_CMD_EXAMPLES))) (
# complex subcommand in a simple nested expression
(
NESTING_EXAMPLES[0][0],
commandline,
context._replace(subcmd_opening=NESTING_EXAMPLES[0][1]),
)
for commandline, context in COMMAND_EXAMPLES
),
NESTED_SIMPLE_CMD_EXAMPLES,
)
),
)
def test_nested_command(commandline, context, nesting): def test_nested_command(commandline, context, nesting):
nested_commandline = nesting.replace(X, commandline) nested_commandline = nesting.replace(X, commandline)
assert_match(nested_commandline, command_context=context, python_context=None) assert_match(nested_commandline, command_context=context, python_context=None)
@ -205,16 +455,17 @@ def test_malformed_subcmd(nesting, commandline, context, malformation):
MALFORMED_SUBCOMMANDS_NESTINGS = ( MALFORMED_SUBCOMMANDS_NESTINGS = (
# nesting, subcmd_opening # nesting, subcmd_opening
(f"echo $(a $({X}", "$("), (f"echo $(a $({X}", "$("),
(f"echo $(a $(b; {X}", ""), (f"echo $(a $(b; {X}", ""),
(f"$(echo $(a $({X}", "$("), (f"$(echo $(a $({X}", "$("),
(f"echo $[a $({X}]", "$("), (f"echo $[a $({X}]", "$("),
(f"echo $(a $[{X})", "$["), (f"echo $(a $[{X})", "$["),
(f"echo @(x = $({X}", "$("), (f"echo @(x = $({X}", "$("),
(f"echo @(a; x = $({X}", "$("), (f"echo @(a; x = $({X}", "$("),
(f"echo @(x = $(a; {X}", ""), (f"echo @(x = $(a; {X}", ""),
) )
@pytest.mark.parametrize("nesting, subcmd_opening", MALFORMED_SUBCOMMANDS_NESTINGS) @pytest.mark.parametrize("nesting, subcmd_opening", MALFORMED_SUBCOMMANDS_NESTINGS)
@pytest.mark.parametrize("commandline, context", COMMAND_EXAMPLES[:5]) @pytest.mark.parametrize("commandline, context", COMMAND_EXAMPLES[:5])
def test_multiple_malformed_subcmds(nesting, subcmd_opening, commandline, context): def test_multiple_malformed_subcmds(nesting, subcmd_opening, commandline, context):
@ -228,7 +479,7 @@ def test_other_subcommand_arg():
assert_match( assert_match(
command, command,
CommandContext((CommandArg("echo"), CommandArg("$(pwd)")), arg_index=2), CommandContext((CommandArg("echo"), CommandArg("$(pwd)")), arg_index=2),
is_main_command=True is_main_command=True,
) )
@ -236,12 +487,18 @@ def test_combined_subcommand_arg():
command = f"echo file=$(pwd{X})/x" command = f"echo file=$(pwd{X})/x"
# index inside the subproc # index inside the subproc
assert_match(command, CommandContext( assert_match(
(), arg_index=0, prefix="pwd", subcmd_opening="$("), python_context=None) command,
CommandContext((), arg_index=0, prefix="pwd", subcmd_opening="$("),
python_context=None,
)
# index at the end of the command # index at the end of the command
assert_match(command.replace(X, ""), CommandContext( assert_match(
(CommandArg("echo"),), arg_index=1, prefix="file=$(pwd)/x"), is_main_command=True) command.replace(X, ""),
CommandContext((CommandArg("echo"),), arg_index=1, prefix="file=$(pwd)/x"),
is_main_command=True,
)
SUBCMD_BORDER_EXAMPLES = ( SUBCMD_BORDER_EXAMPLES = (
@ -269,49 +526,71 @@ MULTIPLE_COMMAND_KEYWORDS = (
) )
MULTIPLE_CMD_SIMPLE_EXAMPLES = [ MULTIPLE_CMD_SIMPLE_EXAMPLES = [
(keyword, ("echo hi", f"simple {X}"), CommandContext(args=(CommandArg("simple"),), arg_index=1)) (
for keyword in MULTIPLE_COMMAND_KEYWORDS] keyword,
("echo hi", f"simple {X}"),
CommandContext(args=(CommandArg("simple"),), arg_index=1),
)
for keyword in MULTIPLE_COMMAND_KEYWORDS
]
EXTENSIVE_COMMAND_PAIRS = tuple(itertools.chain( EXTENSIVE_COMMAND_PAIRS = tuple(
zip(COMMAND_EXAMPLES, COMMAND_EXAMPLES[::-1]), itertools.chain(
zip(COMMAND_EXAMPLES, EMPTY_COMMAND_EXAMPLES), zip(COMMAND_EXAMPLES, COMMAND_EXAMPLES[::-1]),
zip(EMPTY_COMMAND_EXAMPLES, COMMAND_EXAMPLES), zip(COMMAND_EXAMPLES, EMPTY_COMMAND_EXAMPLES),
zip(EMPTY_COMMAND_EXAMPLES, EMPTY_COMMAND_EXAMPLES), zip(EMPTY_COMMAND_EXAMPLES, COMMAND_EXAMPLES),
)) zip(EMPTY_COMMAND_EXAMPLES, EMPTY_COMMAND_EXAMPLES),
)
)
MULTIPLE_COMMAND_EXTENSIVE_EXAMPLES = tuple(itertools.chain( MULTIPLE_COMMAND_EXTENSIVE_EXAMPLES = tuple(
( itertools.chain(
# cursor in first command (
((first, second.replace(X, "")), first_context) # cursor in first command
for (first, first_context), (second, second_context) in EXTENSIVE_COMMAND_PAIRS ((first, second.replace(X, "")), first_context)
), for (first, first_context), (
( second,
# cursor in second command second_context,
((first.replace(X, ""), second), second_context) ) in EXTENSIVE_COMMAND_PAIRS
for (first, first_context), (second, second_context) in EXTENSIVE_COMMAND_PAIRS ),
), (
( # cursor in second command
# cursor in middle command ((first.replace(X, ""), second), second_context)
((first.replace(X, ""), second, third.replace(X, "")), second_context) for (first, first_context), (
for (first, _1), (second, second_context), (third, _3) second,
in zip(COMMAND_EXAMPLES[:3], COMMAND_EXAMPLES[3:6], COMMAND_EXAMPLES[6:9]) second_context,
), ) in EXTENSIVE_COMMAND_PAIRS
( ),
# cursor in third command (
((first.replace(X, ""), second.replace(X, ""), third), third_context) # cursor in middle command
for (first, _1), (second, _2), (third, third_context) ((first.replace(X, ""), second, third.replace(X, "")), second_context)
in zip(COMMAND_EXAMPLES[:3], COMMAND_EXAMPLES[3:6], COMMAND_EXAMPLES[6:9]) for (first, _1), (second, second_context), (third, _3) in zip(
), COMMAND_EXAMPLES[:3], COMMAND_EXAMPLES[3:6], COMMAND_EXAMPLES[6:9]
)) )
),
(
# cursor in third command
((first.replace(X, ""), second.replace(X, ""), third), third_context)
for (first, _1), (second, _2), (third, third_context) in zip(
COMMAND_EXAMPLES[:3], COMMAND_EXAMPLES[3:6], COMMAND_EXAMPLES[6:9]
)
),
)
)
@pytest.mark.parametrize("keyword, commands, context", tuple(itertools.chain( @pytest.mark.parametrize(
( "keyword, commands, context",
(MULTIPLE_COMMAND_KEYWORDS[0], commands, context) tuple(
for commands, context in MULTIPLE_COMMAND_EXTENSIVE_EXAMPLES itertools.chain(
(
(MULTIPLE_COMMAND_KEYWORDS[0], commands, context)
for commands, context in MULTIPLE_COMMAND_EXTENSIVE_EXAMPLES
),
MULTIPLE_CMD_SIMPLE_EXAMPLES,
)
), ),
MULTIPLE_CMD_SIMPLE_EXAMPLES, )
)))
def test_multiple_commands(keyword, commands, context): def test_multiple_commands(keyword, commands, context):
joined_command = keyword.join(commands) joined_command = keyword.join(commands)
@ -320,7 +599,11 @@ def test_multiple_commands(keyword, commands, context):
relative_index = cursor_command.index(X) relative_index = cursor_command.index(X)
else: else:
absolute_index = joined_command.index(X) absolute_index = joined_command.index(X)
relative_index = absolute_index - joined_command.rindex(keyword, 0, absolute_index) - len(keyword) relative_index = (
absolute_index
- joined_command.rindex(keyword, 0, absolute_index)
- len(keyword)
)
if keyword.endswith(" "): if keyword.endswith(" "):
# the last space is part of the command # the last space is part of the command
relative_index += 1 relative_index += 1
@ -329,24 +612,35 @@ def test_multiple_commands(keyword, commands, context):
assert_match(joined_command, context, is_main_command=True) assert_match(joined_command, context, is_main_command=True)
@pytest.mark.parametrize("commandline", ( @pytest.mark.parametrize(
f"{X};", "commandline",
f"; {X}", (
f"{X};;", f"{X};",
f"; {X};", f"; {X}",
f";; {X}", f"{X};;",
f";;; {X}", f"; {X};",
)) f";; {X}",
f";;; {X}",
),
)
def test_multiple_empty_commands(commandline): def test_multiple_empty_commands(commandline):
assert_match(commandline, CommandContext((), 0), is_main_command=True) assert_match(commandline, CommandContext((), 0), is_main_command=True)
@pytest.mark.parametrize("nesting, keyword, commands, context", tuple( @pytest.mark.parametrize(
(nesting, keyword, commands, context) # no subcmd_opening in nested multi-commands "nesting, keyword, commands, context",
for nesting, prefix in NESTING_EXAMPLES tuple(
for keyword, commands, context in MULTIPLE_CMD_SIMPLE_EXAMPLES (
if keyword != "\n" # the lexer ignores newlines inside subcommands nesting,
)) keyword,
commands,
context,
) # no subcmd_opening in nested multi-commands
for nesting, prefix in NESTING_EXAMPLES
for keyword, commands, context in MULTIPLE_CMD_SIMPLE_EXAMPLES
if keyword != "\n" # the lexer ignores newlines inside subcommands
),
)
def test_nested_multiple_commands(nesting, keyword, commands, context): def test_nested_multiple_commands(nesting, keyword, commands, context):
joined_command = keyword.join(commands) joined_command = keyword.join(commands)
nested_joined = nesting.replace(X, joined_command) nested_joined = nesting.replace(X, joined_command)
@ -354,15 +648,21 @@ def test_nested_multiple_commands(nesting, keyword, commands, context):
def test_multiple_nested_commands(): def test_multiple_nested_commands():
assert_match(f"echo hi; echo $(ls{X})", assert_match(
CommandContext((), 0, prefix="ls", subcmd_opening="$("), f"echo hi; echo $(ls{X})",
python_context=None) CommandContext((), 0, prefix="ls", subcmd_opening="$("),
python_context=None,
)
@pytest.mark.parametrize("commandline, context", tuple( @pytest.mark.parametrize(
(commandline, context) for commandline, context in STRING_ARGS_EXAMPLES "commandline, context",
if commandline.endswith("'") or commandline.endswith('"') tuple(
)) (commandline, context)
for commandline, context in STRING_ARGS_EXAMPLES
if commandline.endswith("'") or commandline.endswith('"')
),
)
def test_multiple_partial_string_arg(commandline, context): def test_multiple_partial_string_arg(commandline, context):
partial_commandline = commandline.rstrip("\"'") partial_commandline = commandline.rstrip("\"'")
partial_context = context._replace(closing_quote="") partial_context = context._replace(closing_quote="")
@ -370,11 +670,14 @@ def test_multiple_partial_string_arg(commandline, context):
assert_match("echo $[a ;" + partial_commandline, partial_context) assert_match("echo $[a ;" + partial_commandline, partial_context)
@pytest.mark.parametrize("nesting, keyword, commands, context", tuple( @pytest.mark.parametrize(
(nesting, keyword, commands, context) "nesting, keyword, commands, context",
for nesting, prefix in NESTING_EXAMPLES[:1] tuple(
for keyword, commands, context in MULTIPLE_CMD_SIMPLE_EXAMPLES[:1] (nesting, keyword, commands, context)
)) for nesting, prefix in NESTING_EXAMPLES[:1]
for keyword, commands, context in MULTIPLE_CMD_SIMPLE_EXAMPLES[:1]
),
)
@pytest.mark.parametrize("malformation", NESTING_MALFORMATIONS) @pytest.mark.parametrize("malformation", NESTING_MALFORMATIONS)
def test_malformed_subcmd(malformation, nesting, keyword, commands, context): def test_malformed_subcmd(malformation, nesting, keyword, commands, context):
joined_command = keyword.join(commands) joined_command = keyword.join(commands)
@ -383,37 +686,70 @@ def test_malformed_subcmd(malformation, nesting, keyword, commands, context):
assert_match(malformed_commandline, context, python_context=None) assert_match(malformed_commandline, context, python_context=None)
MULTIPLE_COMMAND_BORDER_EXAMPLES = tuple(itertools.chain( MULTIPLE_COMMAND_BORDER_EXAMPLES = tuple(
itertools.chain(*( itertools.chain(
itertools.chain(
*(
(
(
f"ls{ws1}{X}{kwd}{ws2}echo",
CommandContext((CommandArg("ls"),), 1)
if ws1
else CommandContext((), 0, prefix="ls"),
),
)
for ws1, ws2, kwd in itertools.product(
("", " "), ("", " "), ("&&", ";")
)
)
),
# all keywords are treated as a normal arg if the cursor is at the edge
( (
(f"ls{ws1}{X}{kwd}{ws2}echo", (
CommandContext((CommandArg("ls"),), 1) if ws1 else CommandContext((), 0, prefix="ls")), f"ls {X}and echo",
) for ws1, ws2, kwd in itertools.product(("", " "), ("", " "), ("&&", ";")) CommandContext((CommandArg("ls"), CommandArg("echo")), 1, suffix="and"),
)), ),
(
# all keywords are treated as a normal arg if the cursor is at the edge f"ls and{X} echo",
( CommandContext((CommandArg("ls"), CommandArg("echo")), 1, prefix="and"),
(f"ls {X}and echo", CommandContext((CommandArg("ls"), CommandArg("echo")), 1, suffix="and")), ),
(f"ls and{X} echo", CommandContext((CommandArg("ls"), CommandArg("echo")), 1, prefix="and")), (
(f"ls ||{X} echo", CommandContext((CommandArg("ls"), CommandArg("echo")), 1, prefix="||")), f"ls ||{X} echo",
), CommandContext((CommandArg("ls"), CommandArg("echo")), 1, prefix="||"),
),
# if the cursor is inside the keyword, it's treated as a normal arg ),
( # if the cursor is inside the keyword, it's treated as a normal arg
(f"ls a{X}nd echo", CommandContext((CommandArg("ls"), CommandArg("echo")), 1, prefix="a", suffix="nd")), (
(f"ls &{X}& echo", CommandContext((CommandArg("ls"), CommandArg("echo")), 1, prefix="&", suffix="&")), (
f"ls a{X}nd echo",
CommandContext(
(CommandArg("ls"), CommandArg("echo")), 1, prefix="a", suffix="nd"
),
),
(
f"ls &{X}& echo",
CommandContext(
(CommandArg("ls"), CommandArg("echo")), 1, prefix="&", suffix="&"
),
),
),
) )
)) )
@pytest.mark.parametrize("commandline, context", tuple(itertools.chain( @pytest.mark.parametrize(
MULTIPLE_COMMAND_BORDER_EXAMPLES, "commandline, context",
( tuple(
# ensure these rules work with more than one command itertools.chain(
(f"cat | {commandline}", context) MULTIPLE_COMMAND_BORDER_EXAMPLES,
for commandline, context in MULTIPLE_COMMAND_BORDER_EXAMPLES (
# ensure these rules work with more than one command
(f"cat | {commandline}", context)
for commandline, context in MULTIPLE_COMMAND_BORDER_EXAMPLES
),
)
), ),
))) )
def test_cursor_in_multiple_keyword_borders(commandline, context): def test_cursor_in_multiple_keyword_borders(commandline, context):
assert_match(commandline, context) assert_match(commandline, context)
@ -433,52 +769,69 @@ PYTHON_NESTING_EXAMPLES = (
) )
@pytest.mark.parametrize("nesting, commandline, context", list(itertools.chain(( @pytest.mark.parametrize(
# complex subcommand in a simple nested expression "nesting, commandline, context",
(nesting, commandline, context._replace(is_sub_expression=True)) list(
for nesting in PYTHON_NESTING_EXAMPLES[:1] itertools.chain(
for commandline, context in PYTHON_EXAMPLES (
), ( # complex subcommand in a simple nested expression
# simple subcommand in a complex nested expression (nesting, commandline, context._replace(is_sub_expression=True))
(nesting, commandline, context._replace(is_sub_expression=True)) for nesting in PYTHON_NESTING_EXAMPLES[:1]
for nesting in PYTHON_NESTING_EXAMPLES for commandline, context in PYTHON_EXAMPLES
for commandline, context in PYTHON_EXAMPLES[:1] ),
)))) (
# simple subcommand in a complex nested expression
(nesting, commandline, context._replace(is_sub_expression=True))
for nesting in PYTHON_NESTING_EXAMPLES
for commandline, context in PYTHON_EXAMPLES[:1]
),
)
),
)
def test_nested_python(commandline, context, nesting): def test_nested_python(commandline, context, nesting):
nested_commandline = nesting.replace(X, commandline) nested_commandline = nesting.replace(X, commandline)
assert_match(nested_commandline, command_context=None, python_context=context) assert_match(nested_commandline, command_context=None, python_context=context)
@pytest.mark.parametrize("commandline, context", [ @pytest.mark.parametrize(
(commandline.replace("$", "@"), context._replace( "commandline, context",
prefix=context.prefix.replace("$", "@"), [
suffix=context.suffix.replace("$", "@"), (
)) commandline.replace("$", "@"),
for commandline, context in SUBCMD_BORDER_EXAMPLES context._replace(
]) prefix=context.prefix.replace("$", "@"),
suffix=context.suffix.replace("$", "@"),
),
)
for commandline, context in SUBCMD_BORDER_EXAMPLES
],
)
def test_cursor_in_sub_python_borders(commandline, context): def test_cursor_in_sub_python_borders(commandline, context):
assert_match(commandline, context, is_main_command=True) assert_match(commandline, context, is_main_command=True)
@pytest.mark.parametrize("code", ( @pytest.mark.parametrize(
f""" "code",
(
f"""
x = 3 x = 3
x.{X}""", x.{X}""",
f""" f"""
x = 3; x = 3;
y = 4; y = 4;
x.{X}""", x.{X}""",
f""" f"""
def func({X}): def func({X}):
return 100 return 100
""", """,
f""" f"""
class A: class A:
def a(): def a():
return "a{X}" return "a{X}"
pass pass
exit() exit()
""", """,
)) ),
)
def test_multiline_python(code): def test_multiline_python(code):
assert_match(code, is_main_command=True) assert_match(code, is_main_command=True)

View file

@ -23,24 +23,24 @@ def chdir(adir):
os.chdir(old_dir) os.chdir(old_dir)
def test_simple(xonsh_builtins): def test_simple(xession):
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=PARENT) xession.env = Env(CDPATH=PARENT, PWD=PARENT)
with chdir(PARENT): with chdir(PARENT):
assert os.getcwd() != HERE assert os.getcwd() != HERE
dirstack.cd(["tests"]) dirstack.cd(["tests"])
assert os.getcwd() == HERE assert os.getcwd() == HERE
def test_cdpath_simple(xonsh_builtins): def test_cdpath_simple(xession):
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE) xession.env = Env(CDPATH=PARENT, PWD=HERE)
with chdir(os.path.normpath("/")): with chdir(os.path.normpath("/")):
assert os.getcwd() != HERE assert os.getcwd() != HERE
dirstack.cd(["tests"]) dirstack.cd(["tests"])
assert os.getcwd() == HERE assert os.getcwd() == HERE
def test_cdpath_collision(xonsh_builtins): def test_cdpath_collision(xession):
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE) xession.env = Env(CDPATH=PARENT, PWD=HERE)
sub_tests = os.path.join(HERE, "tests") sub_tests = os.path.join(HERE, "tests")
if not os.path.exists(sub_tests): if not os.path.exists(sub_tests):
os.mkdir(sub_tests) os.mkdir(sub_tests)
@ -50,8 +50,8 @@ def test_cdpath_collision(xonsh_builtins):
assert os.getcwd() == os.path.join(HERE, "tests") assert os.getcwd() == os.path.join(HERE, "tests")
def test_cdpath_expansion(xonsh_builtins): def test_cdpath_expansion(xession):
xonsh_builtins.__xonsh__.env = Env(HERE=HERE, CDPATH=("~", "$HERE")) xession.env = Env(HERE=HERE, CDPATH=("~", "$HERE"))
test_dirs = ( test_dirs = (
os.path.join(HERE, "xonsh-test-cdpath-here"), os.path.join(HERE, "xonsh-test-cdpath-here"),
os.path.expanduser("~/xonsh-test-cdpath-home"), os.path.expanduser("~/xonsh-test-cdpath-home"),
@ -69,13 +69,13 @@ def test_cdpath_expansion(xonsh_builtins):
os.rmdir(d) os.rmdir(d)
def test_cdpath_events(xonsh_builtins, tmpdir): def test_cdpath_events(xession, tmpdir):
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=os.getcwd()) xession.env = Env(CDPATH=PARENT, PWD=os.getcwd())
target = str(tmpdir) target = str(tmpdir)
ev = None ev = None
@xonsh_builtins.events.on_chdir @xession.builtins.events.on_chdir
def handler(olddir, newdir, **kw): def handler(olddir, newdir, **kw):
nonlocal ev nonlocal ev
ev = olddir, newdir ev = olddir, newdir
@ -92,8 +92,8 @@ def test_cdpath_events(xonsh_builtins, tmpdir):
os.chdir(old_dir) os.chdir(old_dir)
def test_cd_autopush(xonsh_builtins, tmpdir): def test_cd_autopush(xession, tmpdir):
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=os.getcwd(), AUTO_PUSHD=True) xession.env = Env(CDPATH=PARENT, PWD=os.getcwd(), AUTO_PUSHD=True)
target = str(tmpdir) target = str(tmpdir)
old_dir = os.getcwd() old_dir = os.getcwd()

View file

@ -87,14 +87,13 @@ def shares_setup(tmpdir_factory):
# unless I wait > 10 sec. see http://stackoverflow.com/questions/38448413/access-denied-in-net-share-delete # unless I wait > 10 sec. see http://stackoverflow.com/questions/38448413/access-denied-in-net-share-delete
def test_pushdpopd(xonsh_builtins): def test_pushdpopd(xession):
"""Simple non-UNC push/pop to verify we didn't break nonUNC case. """Simple non-UNC push/pop to verify we didn't break nonUNC case."""
""" xession.env = Env(CDPATH=PARENT, PWD=HERE)
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE)
dirstack.cd([PARENT]) dirstack.cd([PARENT])
owd = os.getcwd() owd = os.getcwd()
assert owd.casefold() == xonsh_builtins.__xonsh__.env["PWD"].casefold() assert owd.casefold() == xession.env["PWD"].casefold()
dirstack.pushd([HERE]) dirstack.pushd([HERE])
wd = os.getcwd() wd = os.getcwd()
assert wd.casefold() == HERE.casefold() assert wd.casefold() == HERE.casefold()
@ -102,8 +101,8 @@ def test_pushdpopd(xonsh_builtins):
assert owd.casefold() == os.getcwd().casefold(), "popd returned cwd to expected dir" assert owd.casefold() == os.getcwd().casefold(), "popd returned cwd to expected dir"
def test_cd_dot(xonsh_builtins): def test_cd_dot(xession):
xonsh_builtins.__xonsh__.env = Env(PWD=os.getcwd()) xession.env = Env(PWD=os.getcwd())
owd = os.getcwd().casefold() owd = os.getcwd().casefold()
dirstack.cd(["."]) dirstack.cd(["."])
@ -111,13 +110,13 @@ def test_cd_dot(xonsh_builtins):
@pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality") @pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality")
def test_uncpushd_simple_push_pop(xonsh_builtins, shares_setup): def test_uncpushd_simple_push_pop(xession, shares_setup):
if shares_setup is None: if shares_setup is None:
return return
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE) xession.env = Env(CDPATH=PARENT, PWD=HERE)
dirstack.cd([PARENT]) dirstack.cd([PARENT])
owd = os.getcwd() owd = os.getcwd()
assert owd.casefold() == xonsh_builtins.__xonsh__.env["PWD"].casefold() assert owd.casefold() == xession.env["PWD"].casefold()
dirstack.pushd([r"\\localhost\uncpushd_test_HERE"]) dirstack.pushd([r"\\localhost\uncpushd_test_HERE"])
wd = os.getcwd() wd = os.getcwd()
assert os.path.splitdrive(wd)[0].casefold() == TEMP_DRIVE[0] assert os.path.splitdrive(wd)[0].casefold() == TEMP_DRIVE[0]
@ -128,14 +127,14 @@ def test_uncpushd_simple_push_pop(xonsh_builtins, shares_setup):
@pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality") @pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality")
def test_uncpushd_push_to_same_share(xonsh_builtins, shares_setup): def test_uncpushd_push_to_same_share(xession, shares_setup):
if shares_setup is None: if shares_setup is None:
return return
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE) xession.env = Env(CDPATH=PARENT, PWD=HERE)
dirstack.cd([PARENT]) dirstack.cd([PARENT])
owd = os.getcwd() owd = os.getcwd()
assert owd.casefold() == xonsh_builtins.__xonsh__.env["PWD"].casefold() assert owd.casefold() == xession.env["PWD"].casefold()
dirstack.pushd([r"\\localhost\uncpushd_test_HERE"]) dirstack.pushd([r"\\localhost\uncpushd_test_HERE"])
wd = os.getcwd() wd = os.getcwd()
assert os.path.splitdrive(wd)[0].casefold() == TEMP_DRIVE[0] assert os.path.splitdrive(wd)[0].casefold() == TEMP_DRIVE[0]
@ -160,16 +159,16 @@ def test_uncpushd_push_to_same_share(xonsh_builtins, shares_setup):
@pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality") @pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality")
def test_uncpushd_push_other_push_same(xonsh_builtins, shares_setup): def test_uncpushd_push_other_push_same(xession, shares_setup):
"""push to a, then to b. verify drive letter is TEMP_DRIVE[2], skipping already used TEMP_DRIVE[1] """push to a, then to b. verify drive letter is TEMP_DRIVE[2], skipping already used TEMP_DRIVE[1]
Then push to a again. Pop (check b unmapped and a still mapped), pop, pop (check a is unmapped)""" Then push to a again. Pop (check b unmapped and a still mapped), pop, pop (check a is unmapped)"""
if shares_setup is None: if shares_setup is None:
return return
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE) xession.env = Env(CDPATH=PARENT, PWD=HERE)
dirstack.cd([PARENT]) dirstack.cd([PARENT])
owd = os.getcwd() owd = os.getcwd()
assert owd.casefold() == xonsh_builtins.__xonsh__.env["PWD"].casefold() assert owd.casefold() == xession.env["PWD"].casefold()
dirstack.pushd([r"\\localhost\uncpushd_test_HERE"]) dirstack.pushd([r"\\localhost\uncpushd_test_HERE"])
assert os.getcwd().casefold() == TEMP_DRIVE[0] + "\\" assert os.getcwd().casefold() == TEMP_DRIVE[0] + "\\"
assert len(_unc_tempDrives) == 1 assert len(_unc_tempDrives) == 1
@ -209,7 +208,7 @@ def test_uncpushd_push_other_push_same(xonsh_builtins, shares_setup):
@pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality") @pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality")
def test_uncpushd_push_base_push_rempath(xonsh_builtins): def test_uncpushd_push_base_push_rempath(xession):
"""push to subdir under share, verify mapped path includes subdir""" """push to subdir under share, verify mapped path includes subdir"""
pass pass
@ -280,16 +279,16 @@ def with_unc_check_disabled(): # just like the above, but value is 1 to *disabl
@pytest.fixture() @pytest.fixture()
def xonsh_builtins_cd(xonsh_builtins): def xonsh_builtins_cd(xession):
xonsh_builtins.__xonsh__.env["CDPATH"] = PARENT xession.env["CDPATH"] = PARENT
xonsh_builtins.__xonsh__.env["PWD"] = os.getcwd() xession.env["PWD"] = os.getcwd()
xonsh_builtins.__xonsh__.env["DIRSTACK_SIZE"] = 20 xession.env["DIRSTACK_SIZE"] = 20
return xonsh_builtins return xession
@pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality") @pytest.mark.skipif(not ON_WINDOWS, reason="Windows-only UNC functionality")
def test_uncpushd_cd_unc_auto_pushd(xonsh_builtins_cd, with_unc_check_enabled): def test_uncpushd_cd_unc_auto_pushd(xonsh_builtins_cd, with_unc_check_enabled):
xonsh_builtins_cd.__xonsh__.env["AUTO_PUSHD"] = True xonsh_builtins_cd.env["AUTO_PUSHD"] = True
so, se, rc = dirstack.cd([r"\\localhost\uncpushd_test_PARENT"]) so, se, rc = dirstack.cd([r"\\localhost\uncpushd_test_PARENT"])
if rc != 0: if rc != 0:
return return

View file

@ -151,7 +151,7 @@ def test_swap_exception_replacement():
@skip_if_on_unix @skip_if_on_unix
def test_locate_binary_on_windows(xonsh_builtins): def test_locate_binary_on_windows(xession):
files = ("file1.exe", "FILE2.BAT", "file3.txt") files = ("file1.exe", "FILE2.BAT", "file3.txt")
with TemporaryDirectory() as tmpdir: with TemporaryDirectory() as tmpdir:
tmpdir = os.path.realpath(tmpdir) tmpdir = os.path.realpath(tmpdir)
@ -159,10 +159,8 @@ def test_locate_binary_on_windows(xonsh_builtins):
fpath = os.path.join(tmpdir, fname) fpath = os.path.join(tmpdir, fname)
with open(fpath, "w") as f: with open(fpath, "w") as f:
f.write(fpath) f.write(fpath)
xonsh_builtins.__xonsh__.env.update( xession.env.update({"PATH": [tmpdir], "PATHEXT": [".COM", ".EXE", ".BAT"]})
{"PATH": [tmpdir], "PATHEXT": [".COM", ".EXE", ".BAT"]} xession.commands_cache = CommandsCache()
)
xonsh_builtins.__xonsh__.commands_cache = CommandsCache()
assert locate_binary("file1") == os.path.join(tmpdir, "file1.exe") assert locate_binary("file1") == os.path.join(tmpdir, "file1.exe")
assert locate_binary("file1.exe") == os.path.join(tmpdir, "file1.exe") assert locate_binary("file1.exe") == os.path.join(tmpdir, "file1.exe")
assert locate_binary("file2") == os.path.join(tmpdir, "FILE2.BAT") assert locate_binary("file2") == os.path.join(tmpdir, "FILE2.BAT")
@ -170,13 +168,13 @@ def test_locate_binary_on_windows(xonsh_builtins):
assert locate_binary("file3") is None assert locate_binary("file3") is None
def test_event_on_envvar_change(xonsh_builtins): def test_event_on_envvar_change(xession):
env = Env(TEST=0) env = Env(TEST=0)
xonsh_builtins.__xonsh__.env = env xession.env = env
share = [] share = []
# register # register
@xonsh_builtins.events.on_envvar_change @xession.builtins.events.on_envvar_change
def handler(name, oldvalue, newvalue, **kwargs): def handler(name, oldvalue, newvalue, **kwargs):
share.extend((name, oldvalue, newvalue)) share.extend((name, oldvalue, newvalue))
@ -186,13 +184,13 @@ def test_event_on_envvar_change(xonsh_builtins):
assert share == ["TEST", 0, 1] assert share == ["TEST", 0, 1]
def test_event_on_envvar_new(xonsh_builtins): def test_event_on_envvar_new(xession):
env = Env() env = Env()
xonsh_builtins.__xonsh__.env = env xession.env = env
share = [] share = []
# register # register
@xonsh_builtins.events.on_envvar_new @xession.builtins.events.on_envvar_new
def handler(name, value, **kwargs): def handler(name, value, **kwargs):
share.extend((name, value)) share.extend((name, value))
@ -202,13 +200,13 @@ def test_event_on_envvar_new(xonsh_builtins):
assert share == ["TEST", 1] assert share == ["TEST", 1]
def test_event_on_envvar_change_from_none_value(xonsh_builtins): def test_event_on_envvar_change_from_none_value(xession):
env = Env(TEST=None) env = Env(TEST=None)
xonsh_builtins.__xonsh__.env = env xession.env = env
share = [] share = []
# register # register
@xonsh_builtins.events.on_envvar_change @xession.builtins.events.on_envvar_change
def handler(name, oldvalue, newvalue, **kwargs): def handler(name, oldvalue, newvalue, **kwargs):
share.extend((name, oldvalue, newvalue)) share.extend((name, oldvalue, newvalue))
@ -219,13 +217,13 @@ def test_event_on_envvar_change_from_none_value(xonsh_builtins):
@pytest.mark.parametrize("val", [1, None, True, "ok"]) @pytest.mark.parametrize("val", [1, None, True, "ok"])
def test_event_on_envvar_change_no_fire_when_value_is_same(val, xonsh_builtins): def test_event_on_envvar_change_no_fire_when_value_is_same(val, xession):
env = Env(TEST=val) env = Env(TEST=val)
xonsh_builtins.__xonsh__.env = env xession.env = env
share = [] share = []
# register # register
@xonsh_builtins.events.on_envvar_change @xession.builtins.events.on_envvar_change
def handler(name, oldvalue, newvalue, **kwargs): def handler(name, oldvalue, newvalue, **kwargs):
share.extend((name, oldvalue, newvalue)) share.extend((name, oldvalue, newvalue))
@ -235,17 +233,17 @@ def test_event_on_envvar_change_no_fire_when_value_is_same(val, xonsh_builtins):
assert share == [] assert share == []
def test_events_on_envvar_called_in_right_order(xonsh_builtins): def test_events_on_envvar_called_in_right_order(xession):
env = Env() env = Env()
xonsh_builtins.__xonsh__.env = env xession.env = env
share = [] share = []
# register # register
@xonsh_builtins.events.on_envvar_new @xession.builtins.events.on_envvar_new
def handler(name, value, **kwargs): def handler(name, value, **kwargs):
share[:] = ["new"] share[:] = ["new"]
@xonsh_builtins.events.on_envvar_change @xession.builtins.events.on_envvar_change
def handler1(name, oldvalue, newvalue, **kwargs): def handler1(name, oldvalue, newvalue, **kwargs):
share[:] = ["change"] share[:] = ["change"]
@ -320,13 +318,13 @@ def test_lscolors_target(xonsh_builtins):
("pi", ("BACKGROUND_BLACK", "YELLOW"), None, "delete existing key"), ("pi", ("BACKGROUND_BLACK", "YELLOW"), None, "delete existing key"),
], ],
) )
def test_lscolors_events(key_in, old_in, new_in, test, xonsh_builtins): def test_lscolors_events(key_in, old_in, new_in, test, xession):
lsc = LsColors.fromstring("fi=0:di=01;34:pi=40;33") lsc = LsColors.fromstring("fi=0:di=01;34:pi=40;33")
# corresponding colors: [('RESET',), ('BOLD_CYAN',), ('BOLD_CYAN',), ('BACKGROUND_BLACK', 'YELLOW')] # corresponding colors: [('RESET',), ('BOLD_CYAN',), ('BOLD_CYAN',), ('BACKGROUND_BLACK', 'YELLOW')]
event_fired = False event_fired = False
@xonsh_builtins.events.on_lscolors_change @xession.builtins.events.on_lscolors_change
def handler(key, oldvalue, newvalue, **kwargs): def handler(key, oldvalue, newvalue, **kwargs):
nonlocal old_in, new_in, key_in, event_fired nonlocal old_in, new_in, key_in, event_fired
assert ( assert (
@ -334,7 +332,7 @@ def test_lscolors_events(key_in, old_in, new_in, test, xonsh_builtins):
), "Old and new event values match" ), "Old and new event values match"
event_fired = True event_fired = True
xonsh_builtins.__xonsh__.env["LS_COLORS"] = lsc xession.env["LS_COLORS"] = lsc
if new_in is None: if new_in is None:
lsc.pop(key_in, "argle") lsc.pop(key_in, "argle")

View file

@ -156,8 +156,8 @@ def test_load_2nd_call(events):
assert called == 1 assert called == 1
def test_typos(xonsh_builtins): def test_typos(xession):
for name, ev in vars(xonsh_builtins.events).items(): for name, ev in vars(xession.builtins.events).items():
if "pytest" in name: if "pytest" in name:
continue continue
assert inspect.getdoc(ev) assert inspect.getdoc(ev)

View file

@ -5,16 +5,17 @@
from xonsh.history.dummy import DummyHistory from xonsh.history.dummy import DummyHistory
from xonsh.history.main import construct_history from xonsh.history.main import construct_history
def test_construct_history_str(xonsh_builtins):
xonsh_builtins.__xonsh__.env["XONSH_HISTORY_BACKEND"] = "dummy" def test_construct_history_str(xession):
xession.env["XONSH_HISTORY_BACKEND"] = "dummy"
assert isinstance(construct_history(), DummyHistory) assert isinstance(construct_history(), DummyHistory)
def test_construct_history_class(xonsh_builtins): def test_construct_history_class(xession):
xonsh_builtins.__xonsh__.env["XONSH_HISTORY_BACKEND"] = DummyHistory xession.env["XONSH_HISTORY_BACKEND"] = DummyHistory
assert isinstance(construct_history(), DummyHistory) assert isinstance(construct_history(), DummyHistory)
def test_construct_history_instance(xonsh_builtins): def test_construct_history_instance(xession):
xonsh_builtins.__xonsh__.env["XONSH_HISTORY_BACKEND"] = DummyHistory() xession.env["XONSH_HISTORY_BACKEND"] = DummyHistory()
assert isinstance(construct_history(), DummyHistory) assert isinstance(construct_history(), DummyHistory)

View file

@ -23,24 +23,22 @@ IGNORE_OPTS = ",".join(["ignoredups", "ignoreerr", "ignorespace"])
@pytest.fixture @pytest.fixture
def hist(): def hist(tmpdir, xession):
h = JsonHistory( file = tmpdir / "xonsh-HISTORY-TEST.json"
filename="xonsh-HISTORY-TEST.json", here="yup", sessionid="SESSIONID", gc=False h = JsonHistory(filename=str(file), here="yup", sessionid="SESSIONID", gc=False)
)
yield h yield h
os.remove(h.filename)
def test_hist_init(hist): def test_hist_init(hist, xession):
"""Test initialization of the shell history.""" """Test initialization of the shell history."""
with LazyJSON(hist.filename) as lj: with LazyJSON(hist.filename) as lj:
obs = lj["here"] obs = lj["here"]
assert "yup" == obs assert "yup" == obs
def test_hist_append(hist, xonsh_builtins): def test_hist_append(hist, xession):
"""Verify appending to the history works.""" """Verify appending to the history works."""
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
hf = hist.append({"inp": "still alive", "rtn": 0}) hf = hist.append({"inp": "still alive", "rtn": 0})
assert hf is None assert hf is None
assert "still alive" == hist.buffer[0]["inp"] assert "still alive" == hist.buffer[0]["inp"]
@ -56,11 +54,11 @@ def test_hist_append(hist, xonsh_builtins):
assert 0 == hist.rtns[-1] assert 0 == hist.rtns[-1]
def test_hist_flush(hist, xonsh_builtins): def test_hist_flush(hist, xession):
"""Verify explicit flushing of the history works.""" """Verify explicit flushing of the history works."""
hf = hist.flush() hf = hist.flush()
assert hf is None assert hf is None
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
hist.append({"inp": "still alive?", "rtn": 0, "out": "yes"}) hist.append({"inp": "still alive?", "rtn": 0, "out": "yes"})
hf = hist.flush() hf = hist.flush()
assert hf is not None assert hf is not None
@ -73,12 +71,12 @@ def test_hist_flush(hist, xonsh_builtins):
assert not cmd.get("out", None) assert not cmd.get("out", None)
def test_hist_flush_with_store_stdout(hist, xonsh_builtins): def test_hist_flush_with_store_stdout(hist, xession):
"""Verify explicit flushing of the history works.""" """Verify explicit flushing of the history works."""
hf = hist.flush() hf = hist.flush()
assert hf is None assert hf is None
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
xonsh_builtins.__xonsh__.env["XONSH_STORE_STDOUT"] = True xession.env["XONSH_STORE_STDOUT"] = True
hist.append({"inp": "still alive?", "rtn": 0, "out": "yes"}) hist.append({"inp": "still alive?", "rtn": 0, "out": "yes"})
hf = hist.flush() hf = hist.flush()
assert hf is not None assert hf is not None
@ -90,7 +88,7 @@ def test_hist_flush_with_store_stdout(hist, xonsh_builtins):
assert lj["cmds"][0]["out"].strip() == "yes" assert lj["cmds"][0]["out"].strip() == "yes"
def test_hist_flush_with_store_cwd(hist, xonsh_builtins): def test_hist_flush_with_store_cwd(hist, xession):
hf = hist.flush() hf = hist.flush()
assert hf is None assert hf is None
@ -109,14 +107,14 @@ def test_hist_flush_with_store_cwd(hist, xonsh_builtins):
with LazyJSON(hist.filename) as lj: with LazyJSON(hist.filename) as lj:
assert len(lj["cmds"]) == 2 assert len(lj["cmds"]) == 2
assert lj["cmds"][0]["cwd"] == "/tmp" assert lj["cmds"][0]["cwd"] == "/tmp"
assert "cwd" not in lj["cmds"][1] assert "cwd" not in lj["cmds"][1]
def test_hist_flush_with_hist_control(hist, xonsh_builtins): def test_hist_flush_with_hist_control(hist, xession):
"""Verify explicit flushing of the history works.""" """Verify explicit flushing of the history works."""
hf = hist.flush() hf = hist.flush()
assert hf is None assert hf is None
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = IGNORE_OPTS xession.env["HISTCONTROL"] = IGNORE_OPTS
hist.append({"inp": "ls foo1", "rtn": 0}) hist.append({"inp": "ls foo1", "rtn": 0})
hist.append({"inp": "ls foo1", "rtn": 1}) hist.append({"inp": "ls foo1", "rtn": 1})
hist.append({"inp": "ls foo1", "rtn": 0}) hist.append({"inp": "ls foo1", "rtn": 0})
@ -135,9 +133,9 @@ def test_hist_flush_with_hist_control(hist, xonsh_builtins):
assert [x["rtn"] for x in cmds] == [0, 0] assert [x["rtn"] for x in cmds] == [0, 0]
def test_cmd_field(hist, xonsh_builtins): def test_cmd_field(hist, xession):
# in-memory # in-memory
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
hf = hist.append({"inp": "ls foo", "rtn": 1}) hf = hist.append({"inp": "ls foo", "rtn": 1})
assert hf is None assert hf is None
assert 1 == hist.rtns[0] assert 1 == hist.rtns[0]
@ -166,11 +164,11 @@ def test_cmd_field(hist, xonsh_builtins):
("-4:-2", CMDS[-4:-2], (len(CMDS) - 4, 1)), ("-4:-2", CMDS[-4:-2], (len(CMDS) - 4, 1)),
], ],
) )
def test_show_cmd_numerate(inp, commands, offset, hist, xonsh_builtins, capsys): def test_show_cmd_numerate(inp, commands, offset, hist, xession, capsys):
"""Verify that CLI history commands work.""" """Verify that CLI history commands work."""
base_idx, step = offset base_idx, step = offset
xonsh_builtins.__xonsh__.history = hist xession.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
@ -185,10 +183,10 @@ def test_show_cmd_numerate(inp, commands, offset, hist, xonsh_builtins, capsys):
assert out.rstrip() == exp assert out.rstrip() == exp
def test_histcontrol(hist, xonsh_builtins): def test_histcontrol(hist, xession):
"""Test HISTCONTROL=ignoredups,ignoreerr,ignorespacee""" """Test HISTCONTROL=ignoredups,ignoreerr,ignorespacee"""
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = IGNORE_OPTS xession.env["HISTCONTROL"] = IGNORE_OPTS
assert len(hist.buffer) == 0 assert len(hist.buffer) == 0
# An error, buffer remains empty # An error, buffer remains empty
@ -324,8 +322,8 @@ def test_parser_show(args, exp):
), ),
], ],
) )
def test_history_getitem(index, exp, hist, xonsh_builtins): def test_history_getitem(index, exp, hist, xession):
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
attrs = ("inp", "out", "rtn", "ts") attrs = ("inp", "out", "rtn", "ts")
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
@ -391,8 +389,10 @@ SEC_PER_DAY = 24 * 60 * 60
# 11p every day. The smallest interval is thus ten hours (from 11p to 9a), so # 11p every day. The smallest interval is thus ten hours (from 11p to 9a), so
# we can't spend more than five hours executing the tests. # we can't spend more than five hours executing the tests.
MAX_RUNTIME = 30 * 60 MAX_RUNTIME = 30 * 60
MIN_DIFF = min(HISTORY_FILES_LIST[i+1][0] - HISTORY_FILES_LIST[i][0] MIN_DIFF = min(
for i in range(len(HISTORY_FILES_LIST) - 1)) HISTORY_FILES_LIST[i + 1][0] - HISTORY_FILES_LIST[i][0]
for i in range(len(HISTORY_FILES_LIST) - 1)
)
assert MAX_RUNTIME < MIN_DIFF / 2 assert MAX_RUNTIME < MIN_DIFF / 2
@ -493,9 +493,7 @@ assert MAX_RUNTIME < MIN_DIFF / 2
), ),
], ],
) )
def test__xhj_gc_xx_to_rmfiles( def test__xhj_gc_xx_to_rmfiles(fn, hsize, in_files, exp_size, exp_files, xession):
fn, hsize, in_files, exp_size, exp_files, xonsh_builtins
):
act_size, act_files = fn(hsize, in_files) act_size, act_files = fn(hsize, in_files)
@ -510,63 +508,63 @@ def test__xhj_gc_xx_to_rmfiles(
assert act_size == exp_size assert act_size == exp_size
def test_hist_clear_cmd(hist, xonsh_builtins, capsys, tmpdir): def test_hist_clear_cmd(hist, xession, capsys, tmpdir):
"""Verify that the CLI history clear command works.""" """Verify that the CLI history clear command works."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)}) xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist xession.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
assert len(xonsh_builtins.__xonsh__.history) == 6 assert len(xession.history) == 6
history_main(["clear"]) history_main(["clear"])
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert err.rstrip() == "History cleared" assert err.rstrip() == "History cleared"
assert len(xonsh_builtins.__xonsh__.history) == 0 assert len(xession.history) == 0
def test_hist_off_cmd(hist, xonsh_builtins, capsys, tmpdir): def test_hist_off_cmd(hist, xession, capsys, tmpdir):
"""Verify that the CLI history off command works.""" """Verify that the CLI history off command works."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)}) xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist xession.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
assert len(xonsh_builtins.__xonsh__.history) == 6 assert len(xession.history) == 6
history_main(["off"]) history_main(["off"])
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert err.rstrip() == "History off" assert err.rstrip() == "History off"
assert len(xonsh_builtins.__xonsh__.history) == 0 assert len(xession.history) == 0
for ts, cmd in enumerate(CMDS): # attempt to populate the shell history for ts, cmd in enumerate(CMDS): # attempt to populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
assert len(xonsh_builtins.__xonsh__.history) == 0 assert len(xession.history) == 0
def test_hist_on_cmd(hist, xonsh_builtins, capsys, tmpdir): def test_hist_on_cmd(hist, xession, capsys, tmpdir):
"""Verify that the CLI history on command works.""" """Verify that the CLI history on command works."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)}) xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist xession.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
assert len(xonsh_builtins.__xonsh__.history) == 6 assert len(xession.history) == 6
history_main(["off"]) history_main(["off"])
history_main(["on"]) history_main(["on"])
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert err.rstrip().endswith("History on") assert err.rstrip().endswith("History on")
assert len(xonsh_builtins.__xonsh__.history) == 0 assert len(xession.history) == 0
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
assert len(xonsh_builtins.__xonsh__.history) == 6 assert len(xession.history) == 6

View file

@ -19,9 +19,9 @@ def hist():
os.remove(h.filename) os.remove(h.filename)
def test_hist_append(hist, xonsh_builtins): def test_hist_append(hist, xession):
"""Verify appending to the history works.""" """Verify appending to the history works."""
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
hf = hist.append({"inp": "still alive", "rtn": 1}) hf = hist.append({"inp": "still alive", "rtn": 1})
assert hf is None assert hf is None
items = list(hist.items()) items = list(hist.items())
@ -36,8 +36,8 @@ def test_hist_append(hist, xonsh_builtins):
assert list(hist.all_items()) == items assert list(hist.all_items()) == items
def test_hist_attrs(hist, xonsh_builtins): def test_hist_attrs(hist, xession):
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
hf = hist.append({"inp": "ls foo", "rtn": 1}) hf = hist.append({"inp": "ls foo", "rtn": 1})
assert hf is None assert hf is None
assert "ls foo" == hist.inps[0] assert "ls foo" == hist.inps[0]
@ -73,11 +73,11 @@ CMDS = ["ls", "cat hello kitty", "abc", "def", "touch me", "grep from me"]
("-4:-2", CMDS[-4:-2], (len(CMDS) - 4, 1)), ("-4:-2", CMDS[-4:-2], (len(CMDS) - 4, 1)),
], ],
) )
def test_show_cmd_numerate(inp, commands, offset, hist, xonsh_builtins, capsys): def test_show_cmd_numerate(inp, commands, offset, hist, xession, capsys):
"""Verify that CLI history commands work.""" """Verify that CLI history commands work."""
base_idx, step = offset base_idx, step = offset
xonsh_builtins.__xonsh__.history = hist xession.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
@ -92,11 +92,11 @@ def test_show_cmd_numerate(inp, commands, offset, hist, xonsh_builtins, capsys):
assert out.rstrip() == exp assert out.rstrip() == exp
def test_histcontrol(hist, xonsh_builtins): def test_histcontrol(hist, xession):
"""Test HISTCONTROL=ignoredups,ignoreerr""" """Test HISTCONTROL=ignoredups,ignoreerr"""
ignore_opts = ",".join(["ignoredups", "ignoreerr", "ignorespace"]) ignore_opts = ",".join(["ignoredups", "ignoreerr", "ignorespace"])
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = ignore_opts xession.env["HISTCONTROL"] = ignore_opts
assert len(hist) == 0 assert len(hist) == 0
# An error, items() remains empty # An error, items() remains empty
@ -186,10 +186,10 @@ def test_histcontrol(hist, xonsh_builtins):
assert 0 == hist.rtns[-1] assert 0 == hist.rtns[-1]
def test_histcontrol_erase_dup(hist, xonsh_builtins): def test_histcontrol_erase_dup(hist, xession):
"""Test HISTCONTROL=erasedups""" """Test HISTCONTROL=erasedups"""
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = "erasedups" xession.env["HISTCONTROL"] = "erasedups"
assert len(hist) == 0 assert len(hist) == 0
hist.append({"inp": "ls foo", "rtn": 2}) hist.append({"inp": "ls foo", "rtn": 2})
@ -218,9 +218,9 @@ def test_histcontrol_erase_dup(hist, xonsh_builtins):
), ),
], ],
) )
def test_history_getitem(index, exp, hist, xonsh_builtins): def test_history_getitem(index, exp, hist, xession):
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
xonsh_builtins.__xonsh__.env["XONSH_STORE_STDOUT"] = True xession.env["XONSH_STORE_STDOUT"] = True
attrs = ("inp", "out", "rtn", "ts") attrs = ("inp", "out", "rtn", "ts")
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
@ -234,69 +234,69 @@ def test_history_getitem(index, exp, hist, xonsh_builtins):
assert (entry.cmd, entry.out, entry.rtn, entry.ts) == exp assert (entry.cmd, entry.out, entry.rtn, entry.ts) == exp
def test_hist_clear_cmd(hist, xonsh_builtins, capsys, tmpdir): def test_hist_clear_cmd(hist, xession, capsys, tmpdir):
"""Verify that the CLI history clear command works.""" """Verify that the CLI history clear command works."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)}) xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist xession.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
assert len(xonsh_builtins.__xonsh__.history) == 6 assert len(xession.history) == 6
history_main(["clear"]) history_main(["clear"])
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert err.rstrip() == "History cleared" assert err.rstrip() == "History cleared"
assert len(xonsh_builtins.__xonsh__.history) == 0 assert len(xession.history) == 0
def test_hist_off_cmd(hist, xonsh_builtins, capsys, tmpdir): def test_hist_off_cmd(hist, xession, capsys, tmpdir):
"""Verify that the CLI history off command works.""" """Verify that the CLI history off command works."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)}) xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist xession.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
assert len(xonsh_builtins.__xonsh__.history) == 6 assert len(xession.history) == 6
history_main(["off"]) history_main(["off"])
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert err.rstrip() == "History off" assert err.rstrip() == "History off"
assert len(xonsh_builtins.__xonsh__.history) == 0 assert len(xession.history) == 0
for ts, cmd in enumerate(CMDS): # attempt to populate the shell history for ts, cmd in enumerate(CMDS): # attempt to populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
assert len(xonsh_builtins.__xonsh__.history) == 0 assert len(xession.history) == 0
def test_hist_on_cmd(hist, xonsh_builtins, capsys, tmpdir): def test_hist_on_cmd(hist, xession, capsys, tmpdir):
"""Verify that the CLI history on command works.""" """Verify that the CLI history on command works."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)}) xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist xession.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set() xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
assert len(xonsh_builtins.__xonsh__.history) == 6 assert len(xession.history) == 6
history_main(["off"]) history_main(["off"])
history_main(["on"]) history_main(["on"])
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert err.rstrip().endswith("History on") assert err.rstrip().endswith("History on")
assert len(xonsh_builtins.__xonsh__.history) == 0 assert len(xession.history) == 0
for ts, cmd in enumerate(CMDS): # populate the shell history for ts, cmd in enumerate(CMDS): # populate the shell history
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)}) hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
assert len(xonsh_builtins.__xonsh__.history) == 6 assert len(xession.history) == 6
def test_hist_store_cwd(hist, xonsh_builtins): def test_hist_store_cwd(hist, xession):
hist.save_cwd = True hist.save_cwd = True
hist.append({"inp": "# saving with cwd", "rtn": 0, "out": "yes", "cwd": "/tmp"}) hist.append({"inp": "# saving with cwd", "rtn": 0, "out": "yes", "cwd": "/tmp"})
hist.save_cwd = False hist.save_cwd = False
@ -304,4 +304,4 @@ def test_hist_store_cwd(hist, xonsh_builtins):
cmds = [i for i in hist.all_items()] cmds = [i for i in hist.all_items()]
assert cmds[0]["cwd"] == "/tmp" assert cmds[0]["cwd"] == "/tmp"
assert cmds[1]["cwd"] is None assert cmds[1]["cwd"] is None

View file

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Testing xonsh import hooks""" """Testing xonsh import hooks"""
import os import os
import builtins
from importlib import import_module from importlib import import_module
import pytest import pytest
@ -9,17 +8,17 @@ import pytest
from xonsh import imphooks from xonsh import imphooks
from xonsh.execer import Execer from xonsh.execer import Execer
from xonsh.environ import Env from xonsh.environ import Env
from xonsh.built_ins import unload_builtins from xonsh.built_ins import XSH
imphooks.install_import_hooks() imphooks.install_import_hooks()
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def imp_env(xonsh_builtins): def imp_env(xession):
Execer(unload=False) Execer(unload=False)
builtins.__xonsh__.env = Env({"PATH": [], "PATHEXT": []}) xession.env = Env({"PATH": [], "PATHEXT": []})
yield yield
unload_builtins() XSH.unload()
def test_import(): def test_import():

View file

@ -506,6 +506,10 @@ first
), ),
] ]
if not ON_WINDOWS:
ALL_PLATFORMS = tuple(ALL_PLATFORMS) + tuple(UNIX_TESTS)
@skip_if_no_xonsh @skip_if_no_xonsh
@pytest.mark.parametrize("case", ALL_PLATFORMS) @pytest.mark.parametrize("case", ALL_PLATFORMS)
def test_script(case): def test_script(case):
@ -517,12 +521,6 @@ def test_script(case):
assert exp_out == out assert exp_out == out
assert exp_rtn == rtn assert exp_rtn == rtn
@skip_if_no_xonsh
@skip_if_on_windows
@pytest.mark.parametrize("case", UNIX_TESTS)
def test_unix_tests(case):
test_script(case)
ALL_PLATFORMS_STDERR = [ ALL_PLATFORMS_STDERR = [
# test redirecting a function alias # test redirecting a function alias
@ -557,7 +555,11 @@ def test_script_stderr(case):
("pwd", None, lambda: os.getcwd() + "\n"), ("pwd", None, lambda: os.getcwd() + "\n"),
("echo WORKING", None, "WORKING\n"), ("echo WORKING", None, "WORKING\n"),
("ls -f", lambda out: out.splitlines().sort(), os.listdir().sort()), ("ls -f", lambda out: out.splitlines().sort(), os.listdir().sort()),
("$FOO='foo' $BAR=2 xonsh -c r'echo -n $FOO$BAR'", None, "foo2",), (
"$FOO='foo' $BAR=2 xonsh -c r'echo -n $FOO$BAR'",
None,
"foo2",
),
], ],
) )
def test_single_command_no_windows(cmd, fmt, exp): def test_single_command_no_windows(cmd, fmt, exp):
@ -685,7 +687,9 @@ def test_xonsh_no_close_fds():
@skip_if_no_xonsh @skip_if_no_xonsh
@pytest.mark.parametrize( @pytest.mark.parametrize(
"cmd, fmt, exp", "cmd, fmt, exp",
[("cat tttt | wc", lambda x: x > "", True),], # noqa E231 (black removes space) [
("cat tttt | wc", lambda x: x > "", True),
], # noqa E231 (black removes space)
) )
def test_pipe_between_subprocs(cmd, fmt, exp): def test_pipe_between_subprocs(cmd, fmt, exp):
"verify pipe between subprocesses doesn't throw an exception" "verify pipe between subprocesses doesn't throw an exception"

View file

@ -9,6 +9,7 @@ from tests.test_ptk_completer import EXPANSION_CASES
XonshKernel = None XonshKernel = None
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def setup(monkeypatch): def setup(monkeypatch):
global XonshKernel global XonshKernel
@ -17,15 +18,17 @@ def setup(monkeypatch):
monkeypatch.setitem(sys.modules, "zmq.eventloop", MagicMock()) monkeypatch.setitem(sys.modules, "zmq.eventloop", MagicMock())
monkeypatch.setitem(sys.modules, "zmq.error", MagicMock()) monkeypatch.setitem(sys.modules, "zmq.error", MagicMock())
import xonsh.jupyter_kernel import xonsh.jupyter_kernel
XonshKernel = xonsh.jupyter_kernel.XonshKernel XonshKernel = xonsh.jupyter_kernel.XonshKernel
@pytest.mark.parametrize( @pytest.mark.parametrize("code, index, expected_args", EXPANSION_CASES)
"code, index, expected_args",
EXPANSION_CASES
)
def test_completion_alias_expansion( def test_completion_alias_expansion(
code, index, expected_args, monkeypatch, xonsh_builtins, code,
index,
expected_args,
monkeypatch,
xession,
): ):
xonsh_completer_mock = MagicMock(spec=Completer) xonsh_completer_mock = MagicMock(spec=Completer)
xonsh_completer_mock.complete.return_value = set(), 0 xonsh_completer_mock.complete.return_value = set(), 0
@ -33,12 +36,15 @@ def test_completion_alias_expansion(
kernel = MagicMock() kernel = MagicMock()
kernel.completer = xonsh_completer_mock kernel.completer = xonsh_completer_mock
monkeypatch.setattr("builtins.aliases", Aliases(gb=["git branch"])) monkeypatch.setattr(xession, "aliases", Aliases(gb=["git branch"]))
monkeypatch.setattr(xonsh_builtins.__xonsh__.shell, "ctx", None, raising=False) monkeypatch.setattr(xession.shell, "ctx", None, raising=False)
XonshKernel.do_complete(kernel, code, index) XonshKernel.do_complete(kernel, code, index)
mock_call = xonsh_completer_mock.complete.call_args mock_call = xonsh_completer_mock.complete.call_args
args, kwargs = mock_call args, kwargs = mock_call
expected_args["self"] = None expected_args["self"] = None
expected_args["ctx"] = None expected_args["ctx"] = None
assert signature(Completer.complete).bind(None, *args, **kwargs).arguments == expected_args assert (
signature(Completer.complete).bind(None, *args, **kwargs).arguments
== expected_args
)

View file

@ -462,18 +462,21 @@ def test_lexer_split(s, exp):
assert exp == obs assert exp == obs
@pytest.mark.parametrize("s", ( @pytest.mark.parametrize(
"()", # sanity "s",
"(", (
")", "()", # sanity
"))", "(",
"'string\nliteral", ")",
"'''string\nliteral", "))",
"string\nliteral'", "'string\nliteral",
"\"", "'''string\nliteral",
"'", "string\nliteral'",
"\"\"\"", '"',
)) "'",
'"""',
),
)
def test_tolerant_lexer(s): def test_tolerant_lexer(s):
lexer = Lexer(tolerant=True) lexer = Lexer(tolerant=True)
lexer.input(s) lexer.input(s)

View file

@ -20,59 +20,55 @@ def Shell(*args, **kwargs):
@pytest.fixture @pytest.fixture
def shell(xonsh_builtins, monkeypatch): def shell(xession, monkeypatch):
"""Xonsh Shell Mock""" """Xonsh Shell Mock"""
if hasattr(builtins, "__xonsh__"):
builtins.__xonsh__.unlink_builtins()
del builtins.__xonsh__
for xarg in dir(builtins):
if "__xonsh_" in xarg:
delattr(builtins, xarg)
gc.collect() gc.collect()
Shell.shell_type_aliases = {"rl": "readline"} Shell.shell_type_aliases = {"rl": "readline"}
monkeypatch.setattr(xonsh.main, "Shell", Shell) monkeypatch.setattr(xonsh.main, "Shell", Shell)
def test_premain_no_arg(shell, monkeypatch): def test_premain_no_arg(shell, monkeypatch, xession):
monkeypatch.setattr(sys.stdin, "isatty", lambda: True) monkeypatch.setattr(sys.stdin, "isatty", lambda: True)
xonsh.main.premain([]) xonsh.main.premain([])
assert builtins.__xonsh__.env.get("XONSH_LOGIN") assert xession.env.get("XONSH_LOGIN")
def test_premain_interactive(shell): def test_premain_interactive(shell, xession):
xonsh.main.premain(["-i"]) xonsh.main.premain(["-i"])
assert builtins.__xonsh__.env.get("XONSH_INTERACTIVE") assert xession.env.get("XONSH_INTERACTIVE")
def test_premain_login_command(shell): def test_premain_login_command(shell, xession):
xonsh.main.premain(["-l", "-c", 'echo "hi"']) xonsh.main.premain(["-l", "-c", 'echo "hi"'])
assert builtins.__xonsh__.env.get("XONSH_LOGIN") assert xession.env.get("XONSH_LOGIN")
def test_premain_login(shell): def test_premain_login(shell, xession):
xonsh.main.premain(["-l"]) xonsh.main.premain(["-l"])
assert builtins.__xonsh__.env.get("XONSH_LOGIN") assert xession.env.get("XONSH_LOGIN")
def test_premain_D(shell): def test_premain_D(shell, xession):
xonsh.main.premain(["-DTEST1=1616", "-DTEST2=LOL"]) xonsh.main.premain(["-DTEST1=1616", "-DTEST2=LOL"])
assert builtins.__xonsh__.env.get("TEST1") == "1616" assert xession.env.get("TEST1") == "1616"
assert builtins.__xonsh__.env.get("TEST2") == "LOL" assert xession.env.get("TEST2") == "LOL"
def test_premain_custom_rc(shell, tmpdir, monkeypatch): def test_premain_custom_rc(shell, tmpdir, monkeypatch, xession):
monkeypatch.setattr(sys.stdin, "isatty", lambda: True) monkeypatch.setattr(sys.stdin, "isatty", lambda: True)
monkeypatch.setitem(os.environ, "XONSH_CACHE_SCRIPTS", "False") monkeypatch.setitem(os.environ, "XONSH_CACHE_SCRIPTS", "False")
f = tmpdir.join("wakkawakka") f = tmpdir.join("wakkawakka")
f.write("print('hi')") f.write("print('hi')")
args = xonsh.main.premain(["--rc", f.strpath]) args = xonsh.main.premain(["--rc", f.strpath])
assert args.mode == XonshMode.interactive assert args.mode == XonshMode.interactive
assert f.strpath in builtins.__xonsh__.env.get("XONSHRC") assert f.strpath in xession.env.get("XONSHRC")
@pytest.mark.skipif( @pytest.mark.skipif(
ON_WINDOWS and sys.version[:3] == "3.8", reason="weird failure on py38+windows", ON_WINDOWS and sys.version[:3] == "3.8",
) reason="weird failure on py38+windows",
def test_rc_with_modules(shell, tmpdir, monkeypatch, capsys): )
def test_rc_with_modules(shell, tmpdir, monkeypatch, capsys, xession):
"""Test that an RC file can load modules inside the same folder it is located in.""" """Test that an RC file can load modules inside the same folder it is located in."""
monkeypatch.setattr(sys.stdin, "isatty", lambda: True) monkeypatch.setattr(sys.stdin, "isatty", lambda: True)
@ -84,11 +80,9 @@ def test_rc_with_modules(shell, tmpdir, monkeypatch, capsys):
rc.write("from my_python_module import *\nfrom my_xonsh_module import *") rc.write("from my_python_module import *\nfrom my_xonsh_module import *")
xonsh.main.premain(["--rc", rc.strpath]) xonsh.main.premain(["--rc", rc.strpath])
assert rc.strpath in builtins.__xonsh__.env.get("XONSHRC") assert rc.strpath in xession.env.get("XONSHRC")
assert ( assert (
builtins.__xonsh__.env.get("LOADED_RC_FILES")[ xession.env.get("LOADED_RC_FILES")[xession.env.get("XONSHRC").index(rc.strpath)]
builtins.__xonsh__.env.get("XONSHRC").index(rc.strpath)
]
is True is True
) )
@ -130,7 +124,10 @@ def test_rcdir_empty(shell, tmpdir, monkeypatch, capsys):
rcdir = tmpdir.join("rc.d") rcdir = tmpdir.join("rc.d")
rcdir.mkdir() rcdir.mkdir()
rc = tmpdir.join("rc.xsh")
rc.write_binary(b"")
monkeypatch.setattr(sys.stdin, "isatty", lambda: True) monkeypatch.setattr(sys.stdin, "isatty", lambda: True)
monkeypatch.setitem(os.environ, "XONSHRC", str(rc))
monkeypatch.setitem(os.environ, "XONSHRC_DIR", str(rcdir)) monkeypatch.setitem(os.environ, "XONSHRC_DIR", str(rcdir))
xonsh.main.premain([]) xonsh.main.premain([])
@ -241,7 +238,7 @@ def test_script_startup(shell, tmpdir, monkeypatch, capsys, args, expected):
assert xargs.file is not None assert xargs.file is not None
def test_rcdir_ignored_with_rc(shell, tmpdir, monkeypatch, capsys): def test_rcdir_ignored_with_rc(shell, tmpdir, monkeypatch, capsys, xession):
"""Test that --rc suppresses loading XONSHRC_DIRs""" """Test that --rc suppresses loading XONSHRC_DIRs"""
rcdir = tmpdir.join("rc.d") rcdir = tmpdir.join("rc.d")
@ -255,11 +252,11 @@ def test_rcdir_ignored_with_rc(shell, tmpdir, monkeypatch, capsys):
stdout, stderr = capsys.readouterr() stdout, stderr = capsys.readouterr()
assert "RCDIR" not in stdout assert "RCDIR" not in stdout
assert "RCFILE" in stdout assert "RCFILE" in stdout
assert not builtins.__xonsh__.env.get("XONSHRC_DIR") assert not xession.env.get("XONSHRC_DIR")
@pytest.mark.skipif(ON_WINDOWS, reason="See https://github.com/xonsh/xonsh/issues/3936") @pytest.mark.skipif(ON_WINDOWS, reason="See https://github.com/xonsh/xonsh/issues/3936")
def test_rc_with_modified_path(shell, tmpdir, monkeypatch, capsys): def test_rc_with_modified_path(shell, tmpdir, monkeypatch, capsys, xession):
"""Test that an RC file can edit the sys.path variable without losing those values.""" """Test that an RC file can edit the sys.path variable without losing those values."""
monkeypatch.setattr(sys.stdin, "isatty", lambda: True) monkeypatch.setattr(sys.stdin, "isatty", lambda: True)
@ -269,11 +266,9 @@ def test_rc_with_modified_path(shell, tmpdir, monkeypatch, capsys):
rc.write(f"import sys\nsys.path.append('{tmpdir.strpath}')\nprint('Hello, World!')") rc.write(f"import sys\nsys.path.append('{tmpdir.strpath}')\nprint('Hello, World!')")
xonsh.main.premain(["--rc", rc.strpath]) xonsh.main.premain(["--rc", rc.strpath])
assert rc.strpath in builtins.__xonsh__.env.get("XONSHRC") assert rc.strpath in xession.env.get("XONSHRC")
assert ( assert (
builtins.__xonsh__.env.get("LOADED_RC_FILES")[ xession.env.get("LOADED_RC_FILES")[xession.env.get("XONSHRC").index(rc.strpath)]
builtins.__xonsh__.env.get("XONSHRC").index(rc.strpath)
]
is True is True
) )
@ -285,7 +280,7 @@ def test_rc_with_modified_path(shell, tmpdir, monkeypatch, capsys):
assert tmpdir.strpath in sys.path assert tmpdir.strpath in sys.path
def test_rc_with_failing_module(shell, tmpdir, monkeypatch, capsys): def test_rc_with_failing_module(shell, tmpdir, monkeypatch, capsys, xession):
"""Test that an RC file which imports a module that throws an exception .""" """Test that an RC file which imports a module that throws an exception ."""
monkeypatch.setattr(sys.stdin, "isatty", lambda: True) monkeypatch.setattr(sys.stdin, "isatty", lambda: True)
@ -296,11 +291,9 @@ def test_rc_with_failing_module(shell, tmpdir, monkeypatch, capsys):
rc.write("from my_failing_module import *") rc.write("from my_failing_module import *")
xonsh.main.premain(["--rc", rc.strpath]) xonsh.main.premain(["--rc", rc.strpath])
assert rc.strpath in builtins.__xonsh__.env.get("XONSHRC") assert rc.strpath in xession.env.get("XONSHRC")
assert ( assert (
builtins.__xonsh__.env.get("LOADED_RC_FILES")[ xession.env.get("LOADED_RC_FILES")[xession.env.get("XONSHRC").index(rc.strpath)]
builtins.__xonsh__.env.get("XONSHRC").index(rc.strpath)
]
is False is False
) )
@ -317,12 +310,12 @@ def test_no_rc_with_script(shell, tmpdir):
assert not (args.mode == XonshMode.interactive) assert not (args.mode == XonshMode.interactive)
def test_force_interactive_rc_with_script(shell, tmpdir): def test_force_interactive_rc_with_script(shell, tmpdir, xession):
xonsh.main.premain(["-i", "tests/sample.xsh"]) xonsh.main.premain(["-i", "tests/sample.xsh"])
assert builtins.__xonsh__.env.get("XONSH_INTERACTIVE") assert xession.env.get("XONSH_INTERACTIVE")
def test_force_interactive_custom_rc_with_script(shell, tmpdir, monkeypatch): def test_force_interactive_custom_rc_with_script(shell, tmpdir, monkeypatch, xession):
"""Calling a custom RC file on a script-call with the interactive flag """Calling a custom RC file on a script-call with the interactive flag
should run interactively should run interactively
""" """
@ -331,7 +324,7 @@ def test_force_interactive_custom_rc_with_script(shell, tmpdir, monkeypatch):
f.write("print('hi')") f.write("print('hi')")
args = xonsh.main.premain(["-i", "--rc", f.strpath, "tests/sample.xsh"]) args = xonsh.main.premain(["-i", "--rc", f.strpath, "tests/sample.xsh"])
assert args.mode == XonshMode.interactive assert args.mode == XonshMode.interactive
assert f.strpath in builtins.__xonsh__.env.get("XONSHRC") assert f.strpath in xession.env.get("XONSHRC")
def test_custom_rc_with_script(shell, tmpdir): def test_custom_rc_with_script(shell, tmpdir):
@ -344,23 +337,23 @@ def test_custom_rc_with_script(shell, tmpdir):
assert not (args.mode == XonshMode.interactive) assert not (args.mode == XonshMode.interactive)
def test_premain_no_rc(shell, tmpdir): def test_premain_no_rc(shell, tmpdir, xession):
xonsh.main.premain(["--no-rc", "-i"]) xonsh.main.premain(["--no-rc", "-i"])
assert not builtins.__xonsh__.env.get("XONSHRC") assert not xession.env.get("XONSHRC")
assert not builtins.__xonsh__.env.get("XONSHRC_DIR") assert not xession.env.get("XONSHRC_DIR")
@pytest.mark.parametrize( @pytest.mark.parametrize(
"arg", ["", "-i", "-vERSION", "-hAALP", "TTTT", "-TT", "--TTT"] "arg", ["", "-i", "-vERSION", "-hAALP", "TTTT", "-TT", "--TTT"]
) )
def test_premain_with_file_argument(arg, shell): def test_premain_with_file_argument(arg, shell, xession):
xonsh.main.premain(["tests/sample.xsh", arg]) xonsh.main.premain(["tests/sample.xsh", arg])
assert not (builtins.__xonsh__.env.get("XONSH_INTERACTIVE")) assert not (xession.env.get("XONSH_INTERACTIVE"))
def test_premain_interactive__with_file_argument(shell): def test_premain_interactive__with_file_argument(shell, xession):
xonsh.main.premain(["-i", "tests/sample.xsh"]) xonsh.main.premain(["-i", "tests/sample.xsh"])
assert builtins.__xonsh__.env.get("XONSH_INTERACTIVE") assert xession.env.get("XONSH_INTERACTIVE")
@pytest.mark.parametrize("case", ["----", "--hep", "-TT", "--TTTT"]) @pytest.mark.parametrize("case", ["----", "--hep", "-TT", "--TTTT"])

View file

@ -5,18 +5,24 @@ from xonsh.completers.man import complete_from_man
from tools import skip_if_on_windows from tools import skip_if_on_windows
from xonsh.parsers.completion_context import CompletionContext, CommandContext, CommandArg from xonsh.parsers.completion_context import (
CompletionContext,
CommandContext,
CommandArg,
)
@skip_if_on_windows @skip_if_on_windows
def test_man_completion(monkeypatch, tmpdir, xonsh_builtins): def test_man_completion(monkeypatch, tmpdir, xession):
tempdir = tmpdir.mkdir("test_man") tempdir = tmpdir.mkdir("test_man")
monkeypatch.setitem( monkeypatch.setitem(
os.environ, "MANPATH", os.path.dirname(os.path.abspath(__file__)) os.environ, "MANPATH", os.path.dirname(os.path.abspath(__file__))
) )
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tempdir)}) xession.env.update({"XONSH_DATA_DIR": str(tempdir)})
completions = complete_from_man(CompletionContext( completions = complete_from_man(
CommandContext(args=(CommandArg("yes"),), arg_index=1, prefix="--") CompletionContext(
)) CommandContext(args=(CommandArg("yes"),), arg_index=1, prefix="--")
)
)
assert "--version" in completions assert "--version" in completions
assert "--help" in completions assert "--help" in completions

View file

@ -1,15 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Tests the xonsh parser.""" """Tests the xonsh parser."""
import ast import ast
import builtins
import logging
import textwrap import textwrap
import itertools import itertools
import traceback
import pytest import pytest
from xonsh.ast import AST, With, Pass, Str, Call from xonsh.ast import AST, With, Pass, Str, Call
from xonsh.built_ins import XSH
from xonsh.parser import Parser from xonsh.parser import Parser
from xonsh.parsers.fstring_adaptor import FStringAdaptor from xonsh.parsers.fstring_adaptor import FStringAdaptor
@ -45,7 +43,7 @@ def check_stmts(inp, run=True, mode="exec", debug_level=0):
def check_xonsh_ast(xenv, inp, run=True, mode="eval", debug_level=0, return_obs=False): def check_xonsh_ast(xenv, inp, run=True, mode="eval", debug_level=0, return_obs=False):
builtins.__xonsh__.env = xenv XSH.env = xenv
obs = PARSER.parse(inp, debug_level=debug_level) obs = PARSER.parse(inp, debug_level=debug_level)
if obs is None: if obs is None:
return # comment only return # comment only
@ -169,7 +167,7 @@ def test_fstring_adaptor(inp, exp):
assert isinstance(joined_str_node, ast.JoinedStr) assert isinstance(joined_str_node, ast.JoinedStr)
node = ast.Expression(body=joined_str_node) node = ast.Expression(body=joined_str_node)
code = compile(node, "<test_fstring_adaptor>", mode="eval") code = compile(node, "<test_fstring_adaptor>", mode="eval")
builtins.__xonsh__.env = {"HOME": "/foo/bar", "FOO": "HO", "BAR": "ME"} XSH.env = {"HOME": "/foo/bar", "FOO": "HO", "BAR": "ME"}
obs = eval(code) obs = eval(code)
assert exp == obs assert exp == obs

View file

@ -5,7 +5,7 @@ import xonsh.completers.path as xcp
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def xonsh_execer_autouse(xonsh_builtins, xonsh_execer): def xonsh_execer_autouse(xession, xonsh_execer):
return xonsh_execer return xonsh_execer
@ -14,8 +14,8 @@ def test_pattern_need_quotes():
xcp.PATTERN_NEED_QUOTES.match("") xcp.PATTERN_NEED_QUOTES.match("")
def test_complete_path(xonsh_builtins, completion_context_parse): def test_complete_path(xession, completion_context_parse):
xonsh_builtins.__xonsh__.env = { xession.env = {
"CASE_SENSITIVE_COMPLETIONS": False, "CASE_SENSITIVE_COMPLETIONS": False,
"GLOB_SORTED": True, "GLOB_SORTED": True,
"SUBSEQUENCE_PATH_COMPLETION": False, "SUBSEQUENCE_PATH_COMPLETION": False,
@ -27,8 +27,8 @@ def test_complete_path(xonsh_builtins, completion_context_parse):
@patch("xonsh.completers.path._add_cdpaths") @patch("xonsh.completers.path._add_cdpaths")
def test_cd_path_no_cd(mock_add_cdpaths, xonsh_builtins, completion_context_parse): def test_cd_path_no_cd(mock_add_cdpaths, xession, completion_context_parse):
xonsh_builtins.__xonsh__.env = { xession.env = {
"CASE_SENSITIVE_COMPLETIONS": False, "CASE_SENSITIVE_COMPLETIONS": False,
"GLOB_SORTED": True, "GLOB_SORTED": True,
"SUBSEQUENCE_PATH_COMPLETION": False, "SUBSEQUENCE_PATH_COMPLETION": False,
@ -41,8 +41,10 @@ def test_cd_path_no_cd(mock_add_cdpaths, xonsh_builtins, completion_context_pars
@pytest.mark.parametrize("quote", ('"', "'")) @pytest.mark.parametrize("quote", ('"', "'"))
def test_complete_path_when_prefix_is_raw_path_string(quote, xonsh_builtins, completion_context_parse): def test_complete_path_when_prefix_is_raw_path_string(
xonsh_builtins.__xonsh__.env = { quote, xession, completion_context_parse
):
xession.env = {
"CASE_SENSITIVE_COMPLETIONS": True, "CASE_SENSITIVE_COMPLETIONS": True,
"GLOB_SORTED": True, "GLOB_SORTED": True,
"SUBSEQUENCE_PATH_COMPLETION": False, "SUBSEQUENCE_PATH_COMPLETION": False,

View file

@ -4,41 +4,67 @@ Tests for command pipelines.
import os import os
import pytest import pytest
import builtins
from xonsh.platform import ON_WINDOWS from xonsh.platform import ON_WINDOWS
from xonsh.procs.pipelines import CommandPipeline from xonsh.procs.pipelines import CommandPipeline
from tests.tools import skip_if_on_windows, skip_if_on_unix from tests.tools import skip_if_on_windows, skip_if_on_unix
from xonsh.built_ins import XSH
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def patched_events(monkeypatch, xonsh_events, xonsh_execer): def patched_events(monkeypatch, xonsh_events, xonsh_execer):
from xonsh.jobs import tasks
tasks.clear()
# needed for ci tests # needed for ci tests
monkeypatch.setattr('builtins.events', xonsh_events, raising=False) monkeypatch.setitem(
monkeypatch.setitem(builtins.__xonsh__.env, 'RAISE_SUBPROC_ERROR', False) # for the failing `grep` commands XSH.env, "RAISE_SUBPROC_ERROR", False
) # for the failing `grep` commands
if ON_WINDOWS: if ON_WINDOWS:
monkeypatch.setattr('builtins.aliases', { monkeypatch.setattr(
"echo": "cmd /c echo".split(), XSH,
"grep": "cmd /c findstr".split(), "aliases",
}, raising=False) {
"echo": "cmd /c echo".split(),
"grep": "cmd /c findstr".split(),
},
raising=False,
)
@pytest.mark.parametrize("cmdline, stdout, stderr", ( @pytest.mark.parametrize(
"cmdline, stdout, stderr",
(
("!(echo hi)", "hi\n", ""), ("!(echo hi)", "hi\n", ""),
("!(echo hi o>e)", "", "hi\n"), ("!(echo hi o>e)", "", "hi\n"),
pytest.param(
pytest.param("![echo hi]", "hi\n", "", marks=pytest.mark.xfail( "![echo hi]",
ON_WINDOWS, reason="ConsoleParallelReader doesn't work without a real console")), "hi\n",
pytest.param("![echo hi o>e]", "", "hi\n", marks=pytest.mark.xfail( "",
ON_WINDOWS, reason="stderr isn't captured in ![] on windows")), marks=pytest.mark.xfail(
ON_WINDOWS,
pytest.param(r"!(echo 'hi\nho')", "hi\nho\n", "", marks=skip_if_on_windows), # won't work with cmd reason="ConsoleParallelReader doesn't work without a real console",
),
),
pytest.param(
"![echo hi o>e]",
"",
"hi\n",
marks=pytest.mark.xfail(
ON_WINDOWS, reason="stderr isn't captured in ![] on windows"
),
),
pytest.param(
r"!(echo 'hi\nho')", "hi\nho\n", "", marks=skip_if_on_windows
), # won't work with cmd
# for some reason cmd's echo adds an extra space: # for some reason cmd's echo adds an extra space:
pytest.param(r"!(cmd /c 'echo hi && echo ho')", "hi \nho\n", "", marks=skip_if_on_unix), pytest.param(
r"!(cmd /c 'echo hi && echo ho')", "hi \nho\n", "", marks=skip_if_on_unix
),
("!(echo hi | grep h)", "hi\n", ""), ("!(echo hi | grep h)", "hi\n", ""),
("!(echo hi | grep x)", "", ""), ("!(echo hi | grep x)", "", ""),
)) ),
)
def test_command_pipeline_capture(cmdline, stdout, stderr, xonsh_execer): def test_command_pipeline_capture(cmdline, stdout, stderr, xonsh_execer):
pipeline: CommandPipeline = xonsh_execer.eval(cmdline) pipeline: CommandPipeline = xonsh_execer.eval(cmdline)
assert pipeline.out == stdout assert pipeline.out == stdout
@ -47,12 +73,15 @@ def test_command_pipeline_capture(cmdline, stdout, stderr, xonsh_execer):
assert pipeline.raw_err == stderr.replace("\n", os.linesep).encode() assert pipeline.raw_err == stderr.replace("\n", os.linesep).encode()
@pytest.mark.parametrize("cmdline, output", ( @pytest.mark.parametrize(
"cmdline, output",
(
("echo hi", "hi\n"), ("echo hi", "hi\n"),
("echo hi | grep h", "hi\n"), ("echo hi | grep h", "hi\n"),
("echo hi | grep x", ""), ("echo hi | grep x", ""),
pytest.param("echo -n hi", "hi", marks=skip_if_on_windows), pytest.param("echo -n hi", "hi", marks=skip_if_on_windows),
)) ),
)
def test_simple_capture(cmdline, output, xonsh_execer): def test_simple_capture(cmdline, output, xonsh_execer):
assert xonsh_execer.eval(f"$({cmdline})") == output assert xonsh_execer.eval(f"$({cmdline})") == output
@ -61,19 +90,22 @@ def test_raw_substitution(xonsh_execer):
assert xonsh_execer.eval("$(echo @(b'bytes!'))") == "bytes!\n" assert xonsh_execer.eval("$(echo @(b'bytes!'))") == "bytes!\n"
@pytest.mark.parametrize("cmdline, result", ( @pytest.mark.parametrize(
"cmdline, result",
(
("bool(!(echo 1))", True), ("bool(!(echo 1))", True),
("bool(!(nocommand))", False), ("bool(!(nocommand))", False),
("int(!(echo 1))", 0), ("int(!(echo 1))", 0),
("int(!(nocommand))", 1), ("int(!(nocommand))", 1),
("hash(!(echo 1))", 0), ("hash(!(echo 1))", 0),
("hash(!(nocommand))", 1), ("hash(!(nocommand))", 1),
("str(!(echo 1))", '1\n'), ("str(!(echo 1))", "1\n"),
("str(!(nocommand))", ''), ("str(!(nocommand))", ""),
("!(echo 1) == 0", True), ("!(echo 1) == 0", True),
("!(nocommand) == 1", True), ("!(nocommand) == 1", True),
pytest.param("!(echo -n str) == 'str'", True, marks=skip_if_on_windows), pytest.param("!(echo -n str) == 'str'", True, marks=skip_if_on_windows),
("!(nocommand) == ''", True), ("!(nocommand) == ''", True),
)) ),
)
def test_casting(cmdline, result, xonsh_execer): def test_casting(cmdline, result, xonsh_execer):
assert xonsh_execer.eval(f"{cmdline}") == result assert xonsh_execer.eval(f"{cmdline}") == result

View file

@ -24,9 +24,7 @@ from xonsh.ptk_shell.completer import PromptToolkitCompleter
("x", 5, PTKCompletion("x", -5, "x")), ("x", 5, PTKCompletion("x", -5, "x")),
], ],
) )
def test_rich_completion( def test_rich_completion(completion, lprefix, ptk_completion, monkeypatch, xession):
completion, lprefix, ptk_completion, monkeypatch, xonsh_builtins
):
xonsh_completer_mock = MagicMock() xonsh_completer_mock = MagicMock()
xonsh_completer_mock.complete.return_value = {completion}, lprefix xonsh_completer_mock.complete.return_value = {completion}, lprefix
@ -39,7 +37,7 @@ def test_rich_completion(
document_mock.current_line = "" document_mock.current_line = ""
document_mock.cursor_position_col = 0 document_mock.cursor_position_col = 0
monkeypatch.setattr("builtins.aliases", Aliases()) monkeypatch.setattr(xession, "aliases", Aliases())
completions = list(ptk_completer.get_completions(document_mock, MagicMock())) completions = list(ptk_completer.get_completions(document_mock, MagicMock()))
if isinstance(completion, RichCompletion) and not ptk_completion: if isinstance(completion, RichCompletion) and not ptk_completion:
@ -57,7 +55,8 @@ def test_rich_completion(
EXPANSION_CASES = ( EXPANSION_CASES = (
( (
"sanity", 6, "sanity",
6,
dict( dict(
prefix="sanity", prefix="sanity",
line="sanity", line="sanity",
@ -68,7 +67,8 @@ EXPANSION_CASES = (
), ),
), ),
( (
"gb ", 3, "gb ",
3,
dict( dict(
prefix="", prefix="",
line="git branch ", line="git branch ",
@ -79,7 +79,8 @@ EXPANSION_CASES = (
), ),
), ),
( (
"gb ", 1, "gb ",
1,
dict( dict(
prefix="g", prefix="g",
line="gb ", line="gb ",
@ -90,7 +91,8 @@ EXPANSION_CASES = (
), ),
), ),
( (
"gb", 0, "gb",
0,
dict( dict(
prefix="", prefix="",
line="gb", line="gb",
@ -101,7 +103,8 @@ EXPANSION_CASES = (
), ),
), ),
( (
" gb ", 0, " gb ",
0,
dict( dict(
prefix="", prefix="",
line=" gb ", # the PTK completer `lstrip`s the line line=" gb ", # the PTK completer `lstrip`s the line
@ -112,7 +115,8 @@ EXPANSION_CASES = (
), ),
), ),
( (
"gb --", 5, "gb --",
5,
dict( dict(
prefix="--", prefix="--",
line="git branch --", line="git branch --",
@ -123,7 +127,8 @@ EXPANSION_CASES = (
), ),
), ),
( (
"nice\ngb --", 10, "nice\ngb --",
10,
dict( dict(
prefix="--", prefix="--",
line="git branch --", line="git branch --",
@ -134,7 +139,8 @@ EXPANSION_CASES = (
), ),
), ),
( (
"nice\n gb --", 11, "nice\n gb --",
11,
dict( dict(
prefix="--", prefix="--",
line=" git branch --", line=" git branch --",
@ -145,7 +151,8 @@ EXPANSION_CASES = (
), ),
), ),
( (
"gb -- wow", 5, "gb -- wow",
5,
dict( dict(
prefix="--", prefix="--",
line="git branch -- wow", line="git branch -- wow",
@ -156,7 +163,8 @@ EXPANSION_CASES = (
), ),
), ),
( (
"gb --wow", 5, "gb --wow",
5,
dict( dict(
prefix="--", prefix="--",
line="git branch --wow", line="git branch --wow",
@ -168,13 +176,9 @@ EXPANSION_CASES = (
), ),
) )
@pytest.mark.parametrize(
"code, index, expected_args", @pytest.mark.parametrize("code, index, expected_args", EXPANSION_CASES)
EXPANSION_CASES def test_alias_expansion(code, index, expected_args, monkeypatch, xession):
)
def test_alias_expansion(
code, index, expected_args, monkeypatch, xonsh_builtins
):
xonsh_completer_mock = MagicMock(spec=Completer) xonsh_completer_mock = MagicMock(spec=Completer)
xonsh_completer_mock.complete.return_value = set(), 0 xonsh_completer_mock.complete.return_value = set(), 0
@ -182,11 +186,14 @@ def test_alias_expansion(
ptk_completer.reserve_space = lambda: None ptk_completer.reserve_space = lambda: None
ptk_completer.suggestion_completion = lambda _, __: None ptk_completer.suggestion_completion = lambda _, __: None
monkeypatch.setattr("builtins.aliases", Aliases(gb=["git branch"])) monkeypatch.setattr(xession, "aliases", Aliases(gb=["git branch"]))
list(ptk_completer.get_completions(Document(code, index), MagicMock())) list(ptk_completer.get_completions(Document(code, index), MagicMock()))
mock_call = xonsh_completer_mock.complete.call_args mock_call = xonsh_completer_mock.complete.call_args
args, kwargs = mock_call args, kwargs = mock_call
expected_args["self"] = None expected_args["self"] = None
expected_args["ctx"] = None expected_args["ctx"] = None
assert signature(Completer.complete).bind(None, *args, **kwargs).arguments == expected_args assert (
signature(Completer.complete).bind(None, *args, **kwargs).arguments
== expected_args
)

View file

@ -2,7 +2,6 @@
"""Test XonshLexer for pygments""" """Test XonshLexer for pygments"""
import gc import gc
import builtins
import pytest import pytest
from pygments.token import ( from pygments.token import (
@ -19,7 +18,7 @@ from pygments.token import (
from tools import skip_if_on_windows from tools import skip_if_on_windows
from xonsh.platform import ON_WINDOWS from xonsh.platform import ON_WINDOWS
from xonsh.built_ins import load_builtins, unload_builtins from xonsh.built_ins import XSH
from xonsh.pyghooks import XonshLexer, Color, XonshStyle, on_lscolors_change from xonsh.pyghooks import XonshLexer, Color, XonshStyle, on_lscolors_change
from xonsh.environ import LsColors from xonsh.environ import LsColors
from xonsh.events import events, EventManager from xonsh.events import events, EventManager
@ -27,13 +26,13 @@ from tools import DummyShell
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def load_command_cache(xonsh_builtins): def load_command_cache(xession):
gc.collect() gc.collect()
unload_builtins() XSH.unload()
load_builtins() XSH.load()
if ON_WINDOWS: if ON_WINDOWS:
for key in ("cd", "bash"): for key in ("cd", "bash"):
builtins.aliases[key] = lambda *args, **kwargs: None xession.aliases[key] = lambda *args, **kwargs: None
def check_token(code, tokens): def check_token(code, tokens):
@ -149,18 +148,16 @@ def events_fxt():
@pytest.fixture @pytest.fixture
def xonsh_builtins_ls_colors(xonsh_builtins, events_fxt): def xonsh_builtins_ls_colors(xession, events_fxt):
x = xonsh_builtins.__xonsh__ xession.shell = DummyShell() # because load_command_cache zaps it.
xonsh_builtins.__xonsh__.shell = DummyShell() # because load_command_cache zaps it. xession.shell.shell_type = "prompt_toolkit"
xonsh_builtins.__xonsh__.shell.shell_type = "prompt_toolkit"
lsc = LsColors(LsColors.default_settings) lsc = LsColors(LsColors.default_settings)
xonsh_builtins.__xonsh__.env["LS_COLORS"] = lsc # establish LS_COLORS before style. xession.env["LS_COLORS"] = lsc # establish LS_COLORS before style.
xonsh_builtins.__xonsh__.shell.shell.styler = XonshStyle() # default style xession.shell.shell.styler = XonshStyle() # default style
events.on_lscolors_change(on_lscolors_change) events.on_lscolors_change(on_lscolors_change)
yield xonsh_builtins yield xession
xonsh_builtins.__xonsh__ = x
@skip_if_on_windows @skip_if_on_windows
@ -176,7 +173,7 @@ def test_path(tmpdir, xonsh_builtins_ls_colors):
) )
check_token("cd X={}".format(test_dir), [(Color.BOLD_BLUE, test_dir)]) check_token("cd X={}".format(test_dir), [(Color.BOLD_BLUE, test_dir)])
with builtins.__xonsh__.env.swap(AUTO_CD=True): with xonsh_builtins_ls_colors.env.swap(AUTO_CD=True):
check_token(test_dir, [(Name.Constant, test_dir)]) check_token(test_dir, [(Name.Constant, test_dir)])
@ -184,7 +181,7 @@ def test_path(tmpdir, xonsh_builtins_ls_colors):
def test_color_on_lscolors_change(tmpdir, xonsh_builtins_ls_colors): def test_color_on_lscolors_change(tmpdir, xonsh_builtins_ls_colors):
"""Verify colorizer returns Token.Text if file type not defined in LS_COLORS""" """Verify colorizer returns Token.Text if file type not defined in LS_COLORS"""
lsc = xonsh_builtins_ls_colors.__xonsh__.env["LS_COLORS"] lsc = xonsh_builtins_ls_colors.env["LS_COLORS"]
test_dir = str(tmpdir.mkdir("xonsh-test-highlight-path")) test_dir = str(tmpdir.mkdir("xonsh-test-highlight-path"))
lsc["di"] = ("GREEN",) lsc["di"] = ("GREEN",)

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Tests sample inputs to PTK multiline and checks parser response""" """Tests sample inputs to PTK multiline and checks parser response"""
import builtins
from collections import namedtuple from collections import namedtuple
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
@ -10,19 +9,14 @@ from prompt_toolkit.document import Document
from prompt_toolkit.buffer import Buffer from prompt_toolkit.buffer import Buffer
from xonsh.tools import ON_WINDOWS from xonsh.tools import ON_WINDOWS
from xonsh.built_ins import XonshSession
from tools import DummyEnv
Context = namedtuple("Context", ["indent", "buffer", "accept", "cli", "cr"]) Context = namedtuple("Context", ["indent", "buffer", "accept", "cli", "cr"])
@pytest.fixture(scope="module") @pytest.fixture
def ctx(): def ctx(xession):
"""Context in which the ptk multiline functionality will be tested.""" """Context in which the ptk multiline functionality will be tested."""
builtins.__xonsh__ = XonshSession() xession.env["INDENT"] = " "
builtins.__xonsh__.env = DummyEnv()
builtins.__xonsh__.env["INDENT"] = " "
from xonsh.ptk_shell.key_bindings import carriage_return from xonsh.ptk_shell.key_bindings import carriage_return
ptk_buffer = Buffer() ptk_buffer = Buffer()
@ -35,8 +29,6 @@ def ctx():
cli=cli, cli=cli,
cr=carriage_return, cr=carriage_return,
) )
del builtins.__xonsh__.env
del builtins.__xonsh__
def test_colon_indent(ctx): def test_colon_indent(ctx):

View file

@ -23,17 +23,17 @@ from xonsh.environ import LsColors
@pytest.fixture @pytest.fixture
def xonsh_builtins_LS_COLORS(xonsh_builtins): def xs_LS_COLORS(xession):
"""Xonsh environment including LS_COLORS""" """Xonsh environment including LS_COLORS"""
e = xonsh_builtins.__xonsh__.env e = xession.env
lsc = LsColors(LsColors.default_settings) lsc = LsColors(LsColors.default_settings)
xonsh_builtins.__xonsh__.env["LS_COLORS"] = lsc xession.env["LS_COLORS"] = lsc
xonsh_builtins.__xonsh__.shell.shell_type = "prompt_toolkit" xession.shell.shell_type = "prompt_toolkit"
xonsh_builtins.__xonsh__.shell.shell.styler = XonshStyle() # default style xession.shell.shell.styler = XonshStyle() # default style
yield xonsh_builtins yield xession
xonsh_builtins.__xonsh__.env = e xession.env = e
DEFAULT_STYLES = { DEFAULT_STYLES = {
@ -138,9 +138,7 @@ def test_code_by_name(name, exp):
), ),
], ],
) )
def test_color_token_by_name( def test_color_token_by_name(in_tuple, exp_ct, exp_ansi_colors, xs_LS_COLORS):
in_tuple, exp_ct, exp_ansi_colors, xonsh_builtins_LS_COLORS
):
from xonsh.pyghooks import XonshStyle, color_token_by_name from xonsh.pyghooks import XonshStyle, color_token_by_name
xs = XonshStyle() xs = XonshStyle()
@ -151,13 +149,11 @@ def test_color_token_by_name(
assert ansi_colors == exp_ansi_colors, "color token mapped to correct color string" assert ansi_colors == exp_ansi_colors, "color token mapped to correct color string"
def test_XonshStyle_init_file_color_tokens(xonsh_builtins_LS_COLORS): def test_XonshStyle_init_file_color_tokens(xs_LS_COLORS):
xs = XonshStyle() xs = XonshStyle()
assert xs.styles assert xs.styles
assert type(file_color_tokens) is dict assert type(file_color_tokens) is dict
assert set(file_color_tokens.keys()) == set( assert set(file_color_tokens.keys()) == set(xs_LS_COLORS.env["LS_COLORS"].keys())
xonsh_builtins_LS_COLORS.__xonsh__.env["LS_COLORS"].keys()
)
# parameterized tests for file colorization # parameterized tests for file colorization
@ -283,9 +279,10 @@ def colorizable_files():
@pytest.mark.parametrize( @pytest.mark.parametrize(
"key,file_path", [(key, file_path) for key, file_path in _cf.items() if file_path], "key,file_path",
[(key, file_path) for key, file_path in _cf.items() if file_path],
) )
def test_colorize_file(key, file_path, colorizable_files, xonsh_builtins_LS_COLORS): def test_colorize_file(key, file_path, colorizable_files, xs_LS_COLORS):
"""test proper file codes with symlinks colored normally""" """test proper file codes with symlinks colored normally"""
ffp = colorizable_files + "/" + file_path ffp = colorizable_files + "/" + file_path
stat_result = os.lstat(ffp) stat_result = os.lstat(ffp)
@ -295,13 +292,12 @@ def test_colorize_file(key, file_path, colorizable_files, xonsh_builtins_LS_COLO
@pytest.mark.parametrize( @pytest.mark.parametrize(
"key,file_path", [(key, file_path) for key, file_path in _cf.items() if file_path], "key,file_path",
[(key, file_path) for key, file_path in _cf.items() if file_path],
) )
def test_colorize_file_symlink( def test_colorize_file_symlink(key, file_path, colorizable_files, xs_LS_COLORS):
key, file_path, colorizable_files, xonsh_builtins_LS_COLORS
):
"""test proper file codes with symlinks colored target.""" """test proper file codes with symlinks colored target."""
xonsh_builtins_LS_COLORS.__xonsh__.env["LS_COLORS"]["ln"] = "target" xs_LS_COLORS.env["LS_COLORS"]["ln"] = "target"
ffp = colorizable_files + "/" + file_path + "_symlink" ffp = colorizable_files + "/" + file_path + "_symlink"
stat_result = os.lstat(ffp) stat_result = os.lstat(ffp)
assert stat.S_ISLNK(stat_result.st_mode) assert stat.S_ISLNK(stat_result.st_mode)
@ -325,7 +321,7 @@ def test_colorize_file_symlink(
import xonsh.lazyimps import xonsh.lazyimps
def test_colorize_file_ca(xonsh_builtins_LS_COLORS, monkeypatch): def test_colorize_file_ca(xs_LS_COLORS, monkeypatch):
def mock_os_listxattr(*args, **kwards): def mock_os_listxattr(*args, **kwards):
return ["security.capability"] return ["security.capability"]

View file

@ -1,13 +1,23 @@
import pytest import pytest
from tests.tools import skip_if_pre_3_8 from tests.tools import skip_if_pre_3_8
from xonsh.completers.python import python_signature_complete, complete_import, complete_python from xonsh.completers.python import (
from xonsh.parsers.completion_context import CommandArg, CommandContext, CompletionContext, CompletionContextParser, PythonContext python_signature_complete,
complete_import,
complete_python,
)
from xonsh.parsers.completion_context import (
CommandArg,
CommandContext,
CompletionContext,
CompletionContextParser,
PythonContext,
)
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def xonsh_execer_autouse(xonsh_builtins, xonsh_execer, monkeypatch): def xonsh_execer_autouse(xession, xonsh_execer, monkeypatch):
monkeypatch.setitem(xonsh_builtins.__xonsh__.env, "COMPLETIONS_BRACKETS", True) monkeypatch.setitem(xession.env, "COMPLETIONS_BRACKETS", True)
return xonsh_execer return xonsh_execer
@ -55,15 +65,20 @@ def test_complete_python_signatures(line, end, exp):
assert exp == obs assert exp == obs
@pytest.mark.parametrize("code, exp", ( @pytest.mark.parametrize(
("x = su", "sum"), "code, exp",
("imp", "import"), (
("{}.g", "{}.get("), ("x = su", "sum"),
# no signature for native builtins under 3.7: ("imp", "import"),
pytest.param("''.split(ma", "maxsplit=", marks=skip_if_pre_3_8), ("{}.g", "{}.get("),
)) # no signature for native builtins under 3.7:
pytest.param("''.split(ma", "maxsplit=", marks=skip_if_pre_3_8),
),
)
def test_complete_python(code, exp): def test_complete_python(code, exp):
res = complete_python(CompletionContext(python=PythonContext(code, len(code), ctx={}))) res = complete_python(
CompletionContext(python=PythonContext(code, len(code), ctx={}))
)
assert res and len(res) == 2 assert res and len(res) == 2
comps, _ = res comps, _ = res
assert exp in comps assert exp in comps
@ -71,31 +86,73 @@ def test_complete_python(code, exp):
def test_complete_python_ctx(): def test_complete_python_ctx():
class A: class A:
def wow(): def wow(self):
pass pass
a = A() a = A()
res = complete_python(CompletionContext(python=PythonContext("a.w", 2, ctx=locals()))) res = complete_python(
CompletionContext(python=PythonContext("a.w", 2, ctx=locals()))
)
assert res and len(res) == 2 assert res and len(res) == 2
comps, _ = res comps, _ = res
assert "a.wow(" in comps assert "a.wow(" in comps
@pytest.mark.parametrize("command, exp", ( @pytest.mark.parametrize(
(CommandContext(args=(CommandArg("import"),), arg_index=1, prefix="pathli"), {"pathlib"}), "command, exp",
(CommandContext(args=(CommandArg("from"),), arg_index=1, prefix="pathli"), {"pathlib "}), (
(CommandContext(args=(CommandArg("import"),), arg_index=1, prefix="os.pa"), {"os.path"}), (
(CommandContext(args=(CommandArg("from"), CommandArg("x"),), arg_index=2), {"import"}), CommandContext(args=(CommandArg("import"),), arg_index=1, prefix="pathli"),
(CommandContext(args=( {"pathlib"},
CommandArg("import"), CommandArg("os,"), ),
), arg_index=2, prefix="pathli"), {"pathlib"}), (
(CommandContext(args=( CommandContext(args=(CommandArg("from"),), arg_index=1, prefix="pathli"),
CommandArg("from"), CommandArg("pathlib"), CommandArg("import"), {"pathlib "},
), arg_index=3, prefix="PurePa"), {"PurePath"}), ),
)) (
CommandContext(args=(CommandArg("import"),), arg_index=1, prefix="os.pa"),
{"os.path"},
),
(
CommandContext(
args=(
CommandArg("from"),
CommandArg("x"),
),
arg_index=2,
),
{"import"},
),
(
CommandContext(
args=(
CommandArg("import"),
CommandArg("os,"),
),
arg_index=2,
prefix="pathli",
),
{"pathlib"},
),
(
CommandContext(
args=(
CommandArg("from"),
CommandArg("pathlib"),
CommandArg("import"),
),
arg_index=3,
prefix="PurePa",
),
{"PurePath"},
),
),
)
def test_complete_import(command, exp): def test_complete_import(command, exp):
result = complete_import(CompletionContext(command, result = complete_import(
python=PythonContext("", 0) # `complete_import` needs this CompletionContext(
)) command, python=PythonContext("", 0) # `complete_import` needs this
)
)
assert result == exp assert result == exp

View file

@ -9,61 +9,85 @@ from xonsh.history.sqlite import SqliteHistory
from xonsh.history.dummy import DummyHistory from xonsh.history.dummy import DummyHistory
def test_shell_with_json_history(xonsh_builtins, xonsh_execer, tmpdir_factory): def test_shell_with_json_history(xession, xonsh_execer, tmpdir_factory):
""" """
Check that shell successfully load JSON history from file. Check that shell successfully load JSON history from file.
""" """
tempdir = str(tmpdir_factory.mktemp("history")) tempdir = str(tmpdir_factory.mktemp("history"))
history_file = os.path.join(tempdir, 'history.json') history_file = os.path.join(tempdir, "history.json")
h = JsonHistory(filename=history_file) h = JsonHistory(filename=history_file)
h.append({"inp": "echo Hello world 1\n", "rtn": 0, "ts": [1615887820.7329783, 1615887820.7513437]}) h.append(
h.append({"inp": "echo Hello world 2\n", "rtn": 0, "ts": [1615887820.7329783, 1615887820.7513437]}) {
"inp": "echo Hello world 1\n",
"rtn": 0,
"ts": [1615887820.7329783, 1615887820.7513437],
}
)
h.append(
{
"inp": "echo Hello world 2\n",
"rtn": 0,
"ts": [1615887820.7329783, 1615887820.7513437],
}
)
h.flush() h.flush()
xonsh_builtins.__xonsh__.env = Env( xession.env = Env(
XONSH_DATA_DIR=tempdir, XONSH_DATA_DIR=tempdir,
XONSH_INTERACTIVE=True, XONSH_INTERACTIVE=True,
XONSH_HISTORY_BACKEND='json', XONSH_HISTORY_BACKEND="json",
XONSH_HISTORY_FILE=history_file, XONSH_HISTORY_FILE=history_file,
# XONSH_DEBUG=1 # to show errors # XONSH_DEBUG=1 # to show errors
) )
Shell(xonsh_execer, shell_type='none') Shell(xonsh_execer, shell_type="none")
assert len([i for i in xonsh_builtins.__xonsh__.history.all_items()]) == 2 assert len([i for i in xession.history.all_items()]) == 2
def test_shell_with_sqlite_history(xonsh_builtins, xonsh_execer, tmpdir_factory): def test_shell_with_sqlite_history(xession, xonsh_execer, tmpdir_factory):
""" """
Check that shell successfully load SQLite history from file. Check that shell successfully load SQLite history from file.
""" """
tempdir = str(tmpdir_factory.mktemp("history")) tempdir = str(tmpdir_factory.mktemp("history"))
history_file = os.path.join(tempdir, 'history.db') history_file = os.path.join(tempdir, "history.db")
h = SqliteHistory(filename=history_file) h = SqliteHistory(filename=history_file)
h.append({"inp": "echo Hello world 1\n", "rtn": 0, "ts": [1615887820.7329783, 1615887820.7513437]}) h.append(
h.append({"inp": "echo Hello world 2\n", "rtn": 0, "ts": [1615887820.7329783, 1615887820.7513437]}) {
"inp": "echo Hello world 1\n",
"rtn": 0,
"ts": [1615887820.7329783, 1615887820.7513437],
}
)
h.append(
{
"inp": "echo Hello world 2\n",
"rtn": 0,
"ts": [1615887820.7329783, 1615887820.7513437],
}
)
h.flush() h.flush()
xonsh_builtins.__xonsh__.env = Env( xession.env = Env(
XONSH_DATA_DIR=tempdir, XONSH_DATA_DIR=tempdir,
XONSH_INTERACTIVE=True, XONSH_INTERACTIVE=True,
XONSH_HISTORY_BACKEND='sqlite', XONSH_HISTORY_BACKEND="sqlite",
XONSH_HISTORY_FILE=history_file, XONSH_HISTORY_FILE=history_file,
# XONSH_DEBUG=1 # to show errors # XONSH_DEBUG=1 # to show errors
) )
Shell(xonsh_execer, shell_type='none') Shell(xonsh_execer, shell_type="none")
assert len([i for i in xonsh_builtins.__xonsh__.history.all_items()]) == 2 assert len([i for i in xession.history.all_items()]) == 2
def test_shell_with_dummy_history_in_not_interactive(xonsh_builtins, xonsh_execer): def test_shell_with_dummy_history_in_not_interactive(xession, xonsh_execer):
""" """
Check that shell use Dummy history in not interactive mode. Check that shell use Dummy history in not interactive mode.
""" """
xonsh_builtins.__xonsh__.env = Env(XONSH_INTERACTIVE=False) xession.env = Env(XONSH_INTERACTIVE=False)
xonsh_builtins.__xonsh__.history = None xession.history = None
Shell(xonsh_execer, shell_type='none') Shell(xonsh_execer, shell_type="none")
assert isinstance(xonsh_builtins.__xonsh__.history, DummyHistory) assert isinstance(xession.history, DummyHistory)

View file

@ -32,7 +32,6 @@ from xonsh.tools import (
env_path_to_str, env_path_to_str,
escape_windows_cmd_string, escape_windows_cmd_string,
executables_in, executables_in,
expand_case_matching,
expand_path, expand_path,
find_next_break, find_next_break,
is_bool, is_bool,
@ -66,7 +65,6 @@ from xonsh.tools import (
is_nonstring_seq_of_strings, is_nonstring_seq_of_strings,
pathsep_to_upper_seq, pathsep_to_upper_seq,
seq_to_upper_pathsep, seq_to_upper_pathsep,
expandvars,
is_int_as_str, is_int_as_str,
is_slice_as_str, is_slice_as_str,
ensure_timestamp, ensure_timestamp,
@ -89,6 +87,8 @@ from xonsh.tools import (
to_completion_mode, to_completion_mode,
is_completions_display_value, is_completions_display_value,
to_completions_display_value, to_completions_display_value,
expand_case_matching,
expandvars,
) )
from xonsh.environ import Env from xonsh.environ import Env
@ -934,8 +934,8 @@ def expand(path):
(b"~/../", "~/../"), (b"~/../", "~/../"),
], ],
) )
def test_env_path_getitem(inp, exp, xonsh_builtins, env): def test_env_path_getitem(inp, exp, xession, env):
xonsh_builtins.__xonsh__.env = env xession.env = env
obs = EnvPath(inp)[0] # call to __getitem__ obs = EnvPath(inp)[0] # call to __getitem__
if env.get("EXPAND_ENV_VARS"): if env.get("EXPAND_ENV_VARS"):
assert expand(exp) == obs assert expand(exp) == obs
@ -957,9 +957,9 @@ def test_env_path_getitem(inp, exp, xonsh_builtins, env):
), ),
], ],
) )
def test_env_path_multipath(inp, exp, xonsh_builtins, env): def test_env_path_multipath(inp, exp, xession, env):
# cases that involve path-separated strings # cases that involve path-separated strings
xonsh_builtins.__xonsh__.env = env xession.env = env
if env == TOOLS_ENV: if env == TOOLS_ENV:
obs = [i for i in EnvPath(inp)] obs = [i for i in EnvPath(inp)]
assert [expand(i) for i in exp] == obs assert [expand(i) for i in exp] == obs
@ -982,8 +982,8 @@ def test_env_path_multipath(inp, exp, xonsh_builtins, env):
(["/home/wakka", pathlib.Path("~/"), "~/"], ["/home/wakka", "~", "~/"]), (["/home/wakka", pathlib.Path("~/"), "~/"], ["/home/wakka", "~", "~/"]),
], ],
) )
def test_env_path_with_pathlib_path_objects(inp, exp, xonsh_builtins): def test_env_path_with_pathlib_path_objects(inp, exp, xession):
xonsh_builtins.__xonsh__.env = TOOLS_ENV xession.env = TOOLS_ENV
# iterate over EnvPath to acquire all expanded paths # iterate over EnvPath to acquire all expanded paths
obs = [i for i in EnvPath(inp)] obs = [i for i in EnvPath(inp)]
assert [expand(i) for i in exp] == obs assert [expand(i) for i in exp] == obs
@ -1474,7 +1474,7 @@ def test_partial_string(leaders, prefix, quote):
assert obs == exp assert obs == exp
def test_executables_in(xonsh_builtins): def test_executables_in(xession):
expected = set() expected = set()
types = ("file", "directory", "brokensymlink") types = ("file", "directory", "brokensymlink")
if ON_WINDOWS: if ON_WINDOWS:
@ -1507,7 +1507,7 @@ def test_executables_in(xonsh_builtins):
if executable and not _type == "brokensymlink": if executable and not _type == "brokensymlink":
os.chmod(path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) os.chmod(path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
if ON_WINDOWS: if ON_WINDOWS:
xonsh_builtins.__xonsh__.env = PATHEXT_ENV xession.env = PATHEXT_ENV
result = set(executables_in(test_path)) result = set(executables_in(test_path))
else: else:
result = set(executables_in(test_path)) result = set(executables_in(test_path))
@ -1562,12 +1562,12 @@ def test_expand_case_matching(inp, exp):
(b"${'unk'}${'foo'}bar", "${'unk'}barbar"), (b"${'unk'}${'foo'}bar", "${'unk'}barbar"),
], ],
) )
def test_expandvars(inp, exp, xonsh_builtins): def test_expandvars(inp, exp, xession):
"""Tweaked for xonsh cases from CPython `test_genericpath.py`""" """Tweaked for xonsh cases from CPython `test_genericpath.py`"""
env = Env( env = Env(
{"foo": "bar", "spam": "eggs", "a_bool": True, "an_int": 42, "none": None} {"foo": "bar", "spam": "eggs", "a_bool": True, "an_int": 42, "none": None}
) )
xonsh_builtins.__xonsh__.env = env xession.env = env
assert expandvars(inp) == exp assert expandvars(inp) == exp
@ -1589,8 +1589,8 @@ def test_expandvars(inp, exp, xonsh_builtins):
), ),
], ],
) )
def test_ensure_timestamp(inp, fmt, exp, xonsh_builtins): def test_ensure_timestamp(inp, fmt, exp, xession):
xonsh_builtins.__xonsh__.env["XONSH_DATETIME_FORMAT"] = "%Y-%m-%d %H:%M" xession.env["XONSH_DATETIME_FORMAT"] = "%Y-%m-%d %H:%M"
obs = ensure_timestamp(inp, fmt) obs = ensure_timestamp(inp, fmt)
assert exp == obs assert exp == obs
@ -1607,14 +1607,14 @@ def test_ensure_timestamp(inp, fmt, exp, xonsh_builtins):
("~/$foo", False, "/$foo"), ("~/$foo", False, "/$foo"),
], ],
) )
def test_expand_path(expand_user, inp, expand_env_vars, exp_end, xonsh_builtins): def test_expand_path(expand_user, inp, expand_env_vars, exp_end, xession):
if os.sep != "/": if os.sep != "/":
inp = inp.replace("/", os.sep) inp = inp.replace("/", os.sep)
exp_end = exp_end.replace("/", os.sep) exp_end = exp_end.replace("/", os.sep)
env = Env({"foo": "bar", "a_bool": True, "an_int": 42, "none": None}) env = Env({"foo": "bar", "a_bool": True, "an_int": 42, "none": None})
env["EXPAND_ENV_VARS"] = expand_env_vars env["EXPAND_ENV_VARS"] = expand_env_vars
xonsh_builtins.__xonsh__.env = env xession.env = env
path = expand_path(inp, expand_user=expand_user) path = expand_path(inp, expand_user=expand_user)
@ -1728,7 +1728,7 @@ def test_deprecated_past_expiry_raises_assertion_error(expired_version):
@skip_if_on_windows @skip_if_on_windows
def test_iglobpath_no_dotfiles(xonsh_builtins): def test_iglobpath_no_dotfiles(xession):
d = os.path.dirname(__file__) d = os.path.dirname(__file__)
g = d + "/*" g = d + "/*"
files = list(iglobpath(g, include_dotfiles=False)) files = list(iglobpath(g, include_dotfiles=False))
@ -1736,7 +1736,7 @@ def test_iglobpath_no_dotfiles(xonsh_builtins):
@skip_if_on_windows @skip_if_on_windows
def test_iglobpath_dotfiles(xonsh_builtins): def test_iglobpath_dotfiles(xession):
d = os.path.dirname(__file__) d = os.path.dirname(__file__)
g = d + "/*" g = d + "/*"
files = list(iglobpath(g, include_dotfiles=True)) files = list(iglobpath(g, include_dotfiles=True))
@ -1744,7 +1744,7 @@ def test_iglobpath_dotfiles(xonsh_builtins):
@skip_if_on_windows @skip_if_on_windows
def test_iglobpath_no_dotfiles_recursive(xonsh_builtins): def test_iglobpath_no_dotfiles_recursive(xession):
d = os.path.dirname(__file__) d = os.path.dirname(__file__)
g = d + "/**" g = d + "/**"
files = list(iglobpath(g, include_dotfiles=False)) files = list(iglobpath(g, include_dotfiles=False))
@ -1752,14 +1752,14 @@ def test_iglobpath_no_dotfiles_recursive(xonsh_builtins):
@skip_if_on_windows @skip_if_on_windows
def test_iglobpath_dotfiles_recursive(xonsh_builtins): def test_iglobpath_dotfiles_recursive(xession):
d = os.path.dirname(__file__) d = os.path.dirname(__file__)
g = d + "/**" g = d + "/**"
files = list(iglobpath(g, include_dotfiles=True)) files = list(iglobpath(g, include_dotfiles=True))
assert d + "/bin/.someotherdotfile" in files assert d + "/bin/.someotherdotfile" in files
def test_iglobpath_empty_str(monkeypatch, xonsh_builtins): def test_iglobpath_empty_str(monkeypatch, xession):
# makes sure that iglobpath works, even when os.scandir() and os.listdir() # makes sure that iglobpath works, even when os.scandir() and os.listdir()
# fail to return valid results, like an empty filename # fail to return valid results, like an empty filename
def mockscandir(path): def mockscandir(path):
@ -1812,7 +1812,11 @@ def test_all_permutations():
{"Literal.String.Single": "#ff0000"}, {"Literal.String.Single": "#ff0000"},
{"Token.Literal.String.Single": "#ff0000"}, {"Token.Literal.String.Single": "#ff0000"},
), # short str key ), # short str key
("test4", {"RED": "#ff0000"}, {"Token.Color.RED": "#ff0000"},), # color (
"test4",
{"RED": "#ff0000"},
{"Token.Color.RED": "#ff0000"},
), # color
], ],
) )
def test_register_custom_style(name, styles, refrules): def test_register_custom_style(name, styles, refrules):
@ -1855,7 +1859,15 @@ def test_to_completion_mode(val, exp):
assert to_completion_mode(val) == exp assert to_completion_mode(val) == exp
@pytest.mark.parametrize("val", ["de", "defa_ult", "men_", "menu_",]) @pytest.mark.parametrize(
"val",
[
"de",
"defa_ult",
"men_",
"menu_",
],
)
def test_to_completion_mode_fail(val): def test_to_completion_mode_fail(val):
with pytest.warns(RuntimeWarning): with pytest.warns(RuntimeWarning):
obs = to_completion_mode(val) obs = to_completion_mode(val)
@ -1884,14 +1896,14 @@ def test_is_completions_display_value(val, exp):
(False, "none"), (False, "none"),
("false", "none"), ("false", "none"),
("single", "single"), ("single", "single"),
("readline", "single"), ("readline", "readline"), # todo: check this
("multi", "multi"), ("multi", "multi"),
(True, "multi"), (True, "multi"),
("TRUE", "multi"), ("TRUE", "multi"),
], ],
) )
def test_to_completions_display_value(val, exp): def test_to_completions_display_value(val, exp):
to_completions_display_value(val) == exp assert to_completions_display_value(val) == exp
@pytest.mark.parametrize("val", [1, "", "argle"]) @pytest.mark.parametrize("val", [1, "", "argle"])

View file

@ -13,20 +13,20 @@ from xonsh.platform import ON_WINDOWS
@skip_if_on_msys @skip_if_on_msys
@skip_if_on_conda @skip_if_on_conda
def test_crud(xonsh_builtins, tmpdir): def test_crud(xession, tmpdir):
""" """
Creates a virtual environment, gets it, enumerates it, and then deletes it. Creates a virtual environment, gets it, enumerates it, and then deletes it.
""" """
xonsh_builtins.__xonsh__.env["VIRTUALENV_HOME"] = str(tmpdir) xession.env["VIRTUALENV_HOME"] = str(tmpdir)
last_event = None last_event = None
@xonsh_builtins.events.vox_on_create @xession.builtins.events.vox_on_create
def create(name, **_): def create(name, **_):
nonlocal last_event nonlocal last_event
last_event = "create", name last_event = "create", name
@xonsh_builtins.events.vox_on_delete @xession.builtins.events.vox_on_delete
def delete(name, **_): def delete(name, **_):
nonlocal last_event nonlocal last_event
last_event = "delete", name last_event = "delete", name
@ -51,22 +51,22 @@ def test_crud(xonsh_builtins, tmpdir):
@skip_if_on_msys @skip_if_on_msys
@skip_if_on_conda @skip_if_on_conda
def test_activate(xonsh_builtins, tmpdir): def test_activate(xession, tmpdir):
""" """
Creates a virtual environment, gets it, enumerates it, and then deletes it. Creates a virtual environment, gets it, enumerates it, and then deletes it.
""" """
xonsh_builtins.__xonsh__.env["VIRTUALENV_HOME"] = str(tmpdir) xession.env["VIRTUALENV_HOME"] = str(tmpdir)
# I consider the case that the user doesn't have a PATH set to be unreasonable # I consider the case that the user doesn't have a PATH set to be unreasonable
xonsh_builtins.__xonsh__.env.setdefault("PATH", []) xession.env.setdefault("PATH", [])
last_event = None last_event = None
@xonsh_builtins.events.vox_on_activate @xession.builtins.events.vox_on_activate
def activate(name, **_): def activate(name, **_):
nonlocal last_event nonlocal last_event
last_event = "activate", name last_event = "activate", name
@xonsh_builtins.events.vox_on_deactivate @xession.builtins.events.vox_on_deactivate
def deactivate(name, **_): def deactivate(name, **_):
nonlocal last_event nonlocal last_event
last_event = "deactivate", name last_event = "deactivate", name
@ -74,30 +74,30 @@ def test_activate(xonsh_builtins, tmpdir):
vox = Vox() vox = Vox()
vox.create("spam") vox.create("spam")
vox.activate("spam") vox.activate("spam")
assert xonsh_builtins.__xonsh__.env["VIRTUAL_ENV"] == vox["spam"].env assert xession.env["VIRTUAL_ENV"] == vox["spam"].env
assert last_event == ("activate", "spam") assert last_event == ("activate", "spam")
vox.deactivate() vox.deactivate()
assert "VIRTUAL_ENV" not in xonsh_builtins.__xonsh__.env assert "VIRTUAL_ENV" not in xession.env
assert last_event == ("deactivate", "spam") assert last_event == ("deactivate", "spam")
@skip_if_on_msys @skip_if_on_msys
@skip_if_on_conda @skip_if_on_conda
def test_activate_non_vox_venv(xonsh_builtins, tmpdir): def test_activate_non_vox_venv(xession, tmpdir):
""" """
Create a virtual environment using Python's built-in venv module Create a virtual environment using Python's built-in venv module
(not in VIRTUALENV_HOME) and verify that vox can activate it correctly. (not in VIRTUALENV_HOME) and verify that vox can activate it correctly.
""" """
xonsh_builtins.__xonsh__.env.setdefault("PATH", []) xession.env.setdefault("PATH", [])
last_event = None last_event = None
@xonsh_builtins.events.vox_on_activate @xession.builtins.events.vox_on_activate
def activate(name, path, **_): def activate(name, path, **_):
nonlocal last_event nonlocal last_event
last_event = "activate", name, path last_event = "activate", name, path
@xonsh_builtins.events.vox_on_deactivate @xession.builtins.events.vox_on_deactivate
def deactivate(name, path, **_): def deactivate(name, path, **_):
nonlocal last_event nonlocal last_event
last_event = "deactivate", name, path last_event = "deactivate", name, path
@ -109,7 +109,7 @@ def test_activate_non_vox_venv(xonsh_builtins, tmpdir):
vox.activate(venv_dirname) vox.activate(venv_dirname)
vxv = vox[venv_dirname] vxv = vox[venv_dirname]
env = xonsh_builtins.__xonsh__.env env = xession.env
assert os.path.isabs(vxv.bin) assert os.path.isabs(vxv.bin)
assert env["PATH"][0] == vxv.bin assert env["PATH"][0] == vxv.bin
assert os.path.isabs(vxv.env) assert os.path.isabs(vxv.env)
@ -132,34 +132,34 @@ def test_activate_non_vox_venv(xonsh_builtins, tmpdir):
@skip_if_on_msys @skip_if_on_msys
@skip_if_on_conda @skip_if_on_conda
def test_path(xonsh_builtins, tmpdir): def test_path(xession, tmpdir):
""" """
Test to make sure Vox properly activates and deactivates by examining $PATH Test to make sure Vox properly activates and deactivates by examining $PATH
""" """
xonsh_builtins.__xonsh__.env["VIRTUALENV_HOME"] = str(tmpdir) xession.env["VIRTUALENV_HOME"] = str(tmpdir)
# I consider the case that the user doesn't have a PATH set to be unreasonable # I consider the case that the user doesn't have a PATH set to be unreasonable
xonsh_builtins.__xonsh__.env.setdefault("PATH", []) xession.env.setdefault("PATH", [])
oldpath = list(xonsh_builtins.__xonsh__.env["PATH"]) oldpath = list(xession.env["PATH"])
vox = Vox() vox = Vox()
vox.create("eggs") vox.create("eggs")
vox.activate("eggs") vox.activate("eggs")
assert oldpath != xonsh_builtins.__xonsh__.env["PATH"] assert oldpath != xession.env["PATH"]
vox.deactivate() vox.deactivate()
assert oldpath == xonsh_builtins.__xonsh__.env["PATH"] assert oldpath == xession.env["PATH"]
@skip_if_on_msys @skip_if_on_msys
@skip_if_on_conda @skip_if_on_conda
def test_crud_subdir(xonsh_builtins, tmpdir): def test_crud_subdir(xession, tmpdir):
""" """
Creates a virtual environment, gets it, enumerates it, and then deletes it. Creates a virtual environment, gets it, enumerates it, and then deletes it.
""" """
xonsh_builtins.__xonsh__.env["VIRTUALENV_HOME"] = str(tmpdir) xession.env["VIRTUALENV_HOME"] = str(tmpdir)
vox = Vox() vox = Vox()
vox.create("spam/eggs") vox.create("spam/eggs")
@ -188,7 +188,7 @@ else:
@skip_if_on_msys @skip_if_on_msys
@skip_if_on_conda @skip_if_on_conda
def test_crud_path(xonsh_builtins, tmpdir): def test_crud_path(xession, tmpdir):
""" """
Creates a virtual environment, gets it, enumerates it, and then deletes it. Creates a virtual environment, gets it, enumerates it, and then deletes it.
""" """
@ -209,11 +209,11 @@ else:
@skip_if_on_msys @skip_if_on_msys
@skip_if_on_conda @skip_if_on_conda
def test_reserved_names(xonsh_builtins, tmpdir): def test_reserved_names(xession, tmpdir):
""" """
Tests that reserved words are disallowed. Tests that reserved words are disallowed.
""" """
xonsh_builtins.__xonsh__.env["VIRTUALENV_HOME"] = str(tmpdir) xession.env["VIRTUALENV_HOME"] = str(tmpdir)
vox = Vox() vox = Vox()
with pytest.raises(ValueError): with pytest.raises(ValueError):
@ -231,7 +231,7 @@ def test_reserved_names(xonsh_builtins, tmpdir):
@skip_if_on_msys @skip_if_on_msys
@skip_if_on_conda @skip_if_on_conda
def test_autovox(xonsh_builtins, tmpdir): def test_autovox(xession, tmpdir):
""" """
Tests that autovox works Tests that autovox works
""" """
@ -239,7 +239,7 @@ def test_autovox(xonsh_builtins, tmpdir):
import xonsh.dirstack import xonsh.dirstack
# Set up an isolated venv home # Set up an isolated venv home
xonsh_builtins.__xonsh__.env["VIRTUALENV_HOME"] = str(tmpdir) xession.env["VIRTUALENV_HOME"] = str(tmpdir)
# Makes sure that event handlers are registered # Makes sure that event handlers are registered
import xontrib.autovox import xontrib.autovox
@ -247,13 +247,13 @@ def test_autovox(xonsh_builtins, tmpdir):
importlib.reload(xontrib.autovox) importlib.reload(xontrib.autovox)
# Set up enough environment for xonsh to function # Set up enough environment for xonsh to function
xonsh_builtins.__xonsh__.env["PWD"] = os.getcwd() xession.env["PWD"] = os.getcwd()
xonsh_builtins.__xonsh__.env["DIRSTACK_SIZE"] = 10 xession.env["DIRSTACK_SIZE"] = 10
xonsh_builtins.__xonsh__.env["PATH"] = [] xession.env["PATH"] = []
xonsh_builtins.__xonsh__.env["XONSH_SHOW_TRACEBACK"] = True xession.env["XONSH_SHOW_TRACEBACK"] = True
@xonsh_builtins.events.autovox_policy @xession.builtins.events.autovox_policy
def policy(path, **_): def policy(path, **_):
print("Checking", repr(path), vox.active()) print("Checking", repr(path), vox.active())
if str(path) == str(tmpdir): if str(path) == str(tmpdir):
@ -261,16 +261,16 @@ def test_autovox(xonsh_builtins, tmpdir):
vox = Vox() vox = Vox()
print(xonsh_builtins.__xonsh__.env["PWD"]) print(xession.env["PWD"])
xonsh.dirstack.pushd([str(tmpdir)]) xonsh.dirstack.pushd([str(tmpdir)])
print(xonsh_builtins.__xonsh__.env["PWD"]) print(xession.env["PWD"])
assert vox.active() is None assert vox.active() is None
xonsh.dirstack.popd([]) xonsh.dirstack.popd([])
print(xonsh_builtins.__xonsh__.env["PWD"]) print(xession.env["PWD"])
vox.create("myenv") vox.create("myenv")
xonsh.dirstack.pushd([str(tmpdir)]) xonsh.dirstack.pushd([str(tmpdir)])
print(xonsh_builtins.__xonsh__.env["PWD"]) print(xession.env["PWD"])
assert vox.active() == "myenv" assert vox.active() == "myenv"
xonsh.dirstack.popd([]) xonsh.dirstack.popd([])
print(xonsh_builtins.__xonsh__.env["PWD"]) print(xession.env["PWD"])

View file

@ -30,7 +30,15 @@ def test_xonfg_help(capsys, xonsh_builtins):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"args", [([]), (["info",]),], # NOQA E231 "args",
[
([]),
(
[
"info",
]
),
], # NOQA E231
) )
def test_xonfig_info(args, xonsh_builtins): def test_xonfig_info(args, xonsh_builtins):
"""info works, and reports no jupyter if none in environment""" """info works, and reports no jupyter if none in environment"""
@ -53,8 +61,8 @@ def strip_sep(path: str) -> str:
@pytest.fixture @pytest.fixture
def fake_lib(monkeypatch): def fake_lib(monkeypatch):
"""insulate sys.modules from hacking test modules may do with it. """insulate sys.modules from hacking test modules may do with it.
Apparently, monkeypath.syspath_prepend() doesn't flush Apparently, monkeypath.syspath_prepend() doesn't flush
imported modules, so they're still visible in other test cases. imported modules, so they're still visible in other test cases.
""" """
# get absolute path to fake_lib, assuming this test file itself is in same folder. # get absolute path to fake_lib, assuming this test file itself is in same folder.

View file

@ -1,6 +1,3 @@
import builtins
def test_simple(): def test_simple():
assert 1 + 1 == 2 assert 1 + 1 == 2
@ -13,12 +10,13 @@ def test_envionment():
def test_xonsh_party(): def test_xonsh_party():
orig = builtins.__xonsh__.env.get('XONSH_INTERACTIVE') from xonsh.built_ins import XSH
builtins.__xonsh__.env['XONSH_INTERACTIVE'] = False orig = XSH.env.get('XONSH_INTERACTIVE')
XSH.env['XONSH_INTERACTIVE'] = False
try: try:
x = 'xonsh' x = 'xonsh'
y = 'party' y = 'party'
out = $(echo @(x + '-' + y)).strip() out = $(echo @(x + '-' + y)).strip()
assert out == 'xonsh-party', 'Out really was <' + out + '>, sorry.' assert out == 'xonsh-party', 'Out really was <' + out + '>, sorry.'
finally: finally:
builtins.__xonsh__.env['XONSH_INTERACTIVE'] = orig XSH.env['XONSH_INTERACTIVE'] = orig

View file

@ -107,11 +107,11 @@ def test_boottime():
@pytest.fixture @pytest.fixture
def cat_env_fixture(xonsh_builtins): def cat_env_fixture(xession):
with xonsh_builtins.__xonsh__.env.swap( with xession.env.swap(
XONSH_ENCODING=DEFAULT_ENCODING, XONSH_ENCODING_ERRORS="surrogateescape" XONSH_ENCODING=DEFAULT_ENCODING, XONSH_ENCODING_ERRORS="surrogateescape"
): ):
yield xonsh_builtins yield xession
class CatLimitedBuffer(io.BytesIO): class CatLimitedBuffer(io.BytesIO):

View file

@ -4,7 +4,6 @@ from __future__ import unicode_literals, print_function
import os import os
import sys import sys
import ast import ast
import builtins
import platform import platform
import subprocess import subprocess
import contextlib import contextlib
@ -13,6 +12,7 @@ from collections.abc import MutableMapping
import pytest import pytest
from xonsh.built_ins import XSH
from xonsh.environ import Env from xonsh.environ import Env
from xonsh.base_shell import BaseShell from xonsh.base_shell import BaseShell
@ -84,14 +84,6 @@ class DummyShell:
return self._shell return self._shell
class DummyCommandsCache:
def locate_binary(self, name):
return os.path.join(os.path.dirname(__file__), "bin", name)
def predict_threadable(self, cmd):
return True
class DummyHistory: class DummyHistory:
last_cmd_rtn = 0 last_cmd_rtn = 0
@ -168,12 +160,12 @@ class DummyEnv(MutableMapping):
def check_exec(input, **kwargs): def check_exec(input, **kwargs):
builtins.__xonsh__.execer.exec(input, **kwargs) XSH.execer.exec(input, **kwargs)
return True return True
def check_eval(input): def check_eval(input):
builtins.__xonsh__.env = Env( XSH.env = Env(
{ {
"AUTO_CD": False, "AUTO_CD": False,
"XONSH_ENCODING": "utf-8", "XONSH_ENCODING": "utf-8",
@ -182,13 +174,13 @@ def check_eval(input):
} }
) )
if ON_WINDOWS: if ON_WINDOWS:
builtins.__xonsh__.env["PATHEXT"] = [".COM", ".EXE", ".BAT", ".CMD"] XSH.env["PATHEXT"] = [".COM", ".EXE", ".BAT", ".CMD"]
builtins.__xonsh__.execer.eval(input) XSH.execer.eval(input)
return True return True
def check_parse(input): def check_parse(input):
tree = builtins.__xonsh__.execer.parse(input, ctx=None) tree = XSH.execer.parse(input, ctx=None)
return tree return tree
@ -204,22 +196,34 @@ def nodes_equal(x, y):
type(y), type(y),
) )
if isinstance(x, (ast.Expr, ast.FunctionDef, ast.ClassDef)): if isinstance(x, (ast.Expr, ast.FunctionDef, ast.ClassDef)):
assert x.lineno == y.lineno, ( assert (
"Ast nodes do not have the same line number : %s != %s" x.lineno == y.lineno
% (x.lineno, y.lineno,) ), "Ast nodes do not have the same line number : %s != %s" % (
x.lineno,
y.lineno,
) )
assert x.col_offset == y.col_offset, ( assert (
"Ast nodes do not have the same column offset number : %s != %s" x.col_offset == y.col_offset
% (x.col_offset, y.col_offset) ), "Ast nodes do not have the same column offset number : %s != %s" % (
x.col_offset,
y.col_offset,
) )
for (xname, xval), (yname, yval) in zip(ast.iter_fields(x), ast.iter_fields(y)): for (xname, xval), (yname, yval) in zip(ast.iter_fields(x), ast.iter_fields(y)):
assert xname == yname, ( assert (
"Ast nodes fields differ : %s (of type %s) != %s (of type %s)" xname == yname
% (xname, type(xval), yname, type(yval)) ), "Ast nodes fields differ : %s (of type %s) != %s (of type %s)" % (
xname,
type(xval),
yname,
type(yval),
) )
assert type(xval) == type(yval), ( assert type(xval) == type(
"Ast nodes fields differ : %s (of type %s) != %s (of type %s)" yval
% (xname, type(xval), yname, type(yval)) ), "Ast nodes fields differ : %s (of type %s) != %s (of type %s)" % (
xname,
type(xval),
yname,
type(yval),
) )
for xchild, ychild in zip(ast.iter_child_nodes(x), ast.iter_child_nodes(y)): for xchild, ychild in zip(ast.iter_child_nodes(x), ast.iter_child_nodes(y)):
assert nodes_equal(xchild, ychild), "Ast node children differs" assert nodes_equal(xchild, ychild), "Ast node children differs"

View file

@ -6,7 +6,6 @@ import sys
from prompt_toolkit.buffer import Buffer from prompt_toolkit.buffer import Buffer
from pytest import fixture, mark from pytest import fixture, mark
from xonsh.xontribs import find_xontrib from xonsh.xontribs import find_xontrib
import builtins
@fixture @fixture
@ -43,11 +42,13 @@ ps_special_expand = (
], ],
) )
def test_gets_expanded(abbr, val, expanded, cur, abbrevs_xontrib, _buffer): def test_gets_expanded(abbr, val, expanded, cur, abbrevs_xontrib, _buffer):
builtins.abbrevs[abbr] = val from xontrib import abbrevs
from xontrib.abbrevs import expand_abbrev
abbrevs.abbrevs[abbr] = val
abbrev = abbrevs.Abbreviation()
buf = _buffer(abbr) buf = _buffer(abbr)
expand_abbrev(buf) abbrev.expand(buf)
assert buf.text == expanded assert buf.text == expanded
if cur is not None: if cur is not None:
assert buf.cursor_position == cur assert buf.cursor_position == cur

View file

@ -1,7 +1,6 @@
"""Tests for the Jedi completer xontrib""" """Tests for the Jedi completer xontrib"""
import sys import sys
import pytest import pytest
import builtins
import importlib import importlib
from unittest.mock import MagicMock, call from unittest.mock import MagicMock, call
@ -23,14 +22,14 @@ def jedi_mock(monkeypatch):
@pytest.fixture @pytest.fixture
def completer_mock(monkeypatch): def completer_mock(monkeypatch, xession):
completer_mock = MagicMock() completer_mock = MagicMock()
# so that args will be passed # so that args will be passed
def comp(args): def comp(args):
completer_mock(args) completer_mock(args)
monkeypatch.setitem(builtins.aliases, "completer", comp) monkeypatch.setitem(xession.aliases, "completer", comp)
yield completer_mock yield completer_mock
@ -42,11 +41,11 @@ def jedi_xontrib(monkeypatch, source_path, jedi_mock, completer_mock):
del sys.modules[spec.name] del sys.modules[spec.name]
def test_completer_added(jedi_xontrib): def test_completer_added(jedi_xontrib, xession):
assert "xontrib.jedi" in sys.modules assert "xontrib.jedi" in sys.modules
assert "python" not in builtins.__xonsh__.completers assert "python" not in xession.completers
assert "python_mode" not in builtins.__xonsh__.completers assert "python_mode" not in xession.completers
assert "jedi_python" in builtins.__xonsh__.completers assert "jedi_python" in xession.completers
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -56,7 +55,7 @@ def test_completer_added(jedi_xontrib):
], ],
) )
@pytest.mark.parametrize("version", ["new", "old"]) @pytest.mark.parametrize("version", ["new", "old"])
def test_jedi_api(jedi_xontrib, jedi_mock, version, context): def test_jedi_api(jedi_xontrib, jedi_mock, version, context, xession):
if version == "old": if version == "old":
jedi_mock.__version__ = "0.15.0" jedi_mock.__version__ = "0.15.0"
jedi_mock.Interpreter().completions.return_value = [] jedi_mock.Interpreter().completions.return_value = []
@ -64,7 +63,7 @@ def test_jedi_api(jedi_xontrib, jedi_mock, version, context):
jedi_xontrib.complete_jedi(context) jedi_xontrib.complete_jedi(context)
extra_namespace = {"__xonsh__": builtins.__xonsh__} extra_namespace = {"__xonsh__": xession}
try: try:
extra_namespace["_"] = _ extra_namespace["_"] = _
except NameError: except NameError:
@ -109,12 +108,16 @@ def test_multiline(jedi_xontrib, jedi_mock, monkeypatch):
"int(x=None, /) -> int", "int(x=None, /) -> int",
("instance", "instance int"), ("instance", "instance int"),
), ),
RichCompletion("xx", display="xx", description="instance int", prefix_len=1), RichCompletion(
"xx", display="xx", description="instance int", prefix_len=1
),
), ),
( (
# from jedi when code is 'xx=3\nx' # from jedi when code is 'xx=3\nx'
("statement", "xx", "x", None, ("instance", "instance int")), ("statement", "xx", "x", None, ("instance", "instance int")),
RichCompletion("xx", display="xx", description="instance int", prefix_len=1), RichCompletion(
"xx", display="xx", description="instance int", prefix_len=1
),
), ),
( (
# from jedi when code is 'x.' and x=3 # from jedi when code is 'x.' and x=3
@ -139,18 +142,28 @@ def test_multiline(jedi_xontrib, jedi_mock, monkeypatch):
( (
# from '(3).from_bytes(byt' # from '(3).from_bytes(byt'
("param", "bytes=", "es=", None, ("instance", "instance Sequence")), ("param", "bytes=", "es=", None, ("instance", "instance Sequence")),
RichCompletion("bytes=", display="bytes=", description="instance Sequence", prefix_len=3), RichCompletion(
"bytes=",
display="bytes=",
description="instance Sequence",
prefix_len=3,
),
), ),
( (
# from 'x.from_bytes(byt' when x=3 # from 'x.from_bytes(byt' when x=3
("param", "bytes=", "es=", None, None), ("param", "bytes=", "es=", None, None),
RichCompletion("bytes=", display="bytes=", description="param", prefix_len=3), RichCompletion(
"bytes=", display="bytes=", description="param", prefix_len=3
),
), ),
( (
# from 'import colle' # from 'import colle'
("module", "collections", "ctions", None, ("module", "module collections")), ("module", "collections", "ctions", None, ("module", "module collections")),
RichCompletion( RichCompletion(
"collections", display="collections", description="module collections", prefix_len=5 "collections",
display="collections",
description="module collections",
prefix_len=5,
), ),
), ),
( (
@ -163,7 +176,10 @@ def test_multiline(jedi_xontrib, jedi_mock, monkeypatch):
("class", "class NameError"), ("class", "class NameError"),
), ),
RichCompletion( RichCompletion(
"NameError", display="NameError", description="NameError(*args: object)", prefix_len=7 "NameError",
display="NameError",
description="NameError(*args: object)",
prefix_len=7,
), ),
), ),
( (
@ -174,12 +190,16 @@ def test_multiline(jedi_xontrib, jedi_mock, monkeypatch):
( (
# from 'open("/etc/pass' # from 'open("/etc/pass'
("path", 'passwd"', 'wd"', None, None), ("path", 'passwd"', 'wd"', None, None),
RichCompletion('passwd"', display='passwd"', description="path", prefix_len=4), RichCompletion(
'passwd"', display='passwd"', description="path", prefix_len=4
),
), ),
( (
# from 'cla' # from 'cla'
("keyword", "class", "ss", None, None), ("keyword", "class", "ss", None, None),
RichCompletion("class", display="class", description="keyword", prefix_len=3), RichCompletion(
"class", display="class", description="keyword", prefix_len=3
),
), ),
], ],
) )
@ -218,10 +238,15 @@ def test_rich_completions(jedi_xontrib, jedi_mock, completion, rich_completion):
def test_special_tokens(jedi_xontrib): def test_special_tokens(jedi_xontrib):
assert jedi_xontrib.complete_jedi(CompletionContext(python=PythonContext("", 0))) \ assert jedi_xontrib.complete_jedi(
.issuperset(jedi_xontrib.XONSH_SPECIAL_TOKENS) CompletionContext(python=PythonContext("", 0))
assert jedi_xontrib.complete_jedi(CompletionContext(python=PythonContext( "@", 1))) == {"@", "@(", "@$("} ).issuperset(jedi_xontrib.XONSH_SPECIAL_TOKENS)
assert jedi_xontrib.complete_jedi(CompletionContext(python=PythonContext("$", 1))) == {"$[", "${", "$("} assert jedi_xontrib.complete_jedi(
CompletionContext(python=PythonContext("@", 1))
) == {"@", "@(", "@$("}
assert jedi_xontrib.complete_jedi(
CompletionContext(python=PythonContext("$", 1))
) == {"$[", "${", "$("}
@skip_if_on_darwin @skip_if_on_darwin
@ -230,4 +255,6 @@ def test_no_command_path_completion(jedi_xontrib, completion_context_parse):
assert jedi_xontrib.complete_jedi(completion_context_parse("./", 2)) is None assert jedi_xontrib.complete_jedi(completion_context_parse("./", 2)) is None
assert jedi_xontrib.complete_jedi(completion_context_parse("./e", 3)) is None assert jedi_xontrib.complete_jedi(completion_context_parse("./e", 3)) is None
assert jedi_xontrib.complete_jedi(completion_context_parse("/usr/bin/", 9)) is None assert jedi_xontrib.complete_jedi(completion_context_parse("/usr/bin/", 9)) is None
assert jedi_xontrib.complete_jedi(completion_context_parse("/usr/bin/e", 10)) is None assert (
jedi_xontrib.complete_jedi(completion_context_parse("/usr/bin/e", 10)) is None
)

View file

@ -5,9 +5,9 @@ import re
import sys import sys
import inspect import inspect
import argparse import argparse
import builtins
import collections.abc as cabc import collections.abc as cabc
from xonsh.built_ins import XSH
from xonsh.lazyasd import lazyobject from xonsh.lazyasd import lazyobject
from xonsh.dirstack import cd, pushd, popd, dirs, _get_cwd from xonsh.dirstack import cd, pushd, popd, dirs, _get_cwd
from xonsh.environ import locate_binary, make_args_env from xonsh.environ import locate_binary, make_args_env
@ -94,7 +94,7 @@ class Aliases(cabc.MutableMapping):
if callable(value): if callable(value):
return partial_eval_alias(value, acc_args=acc_args) return partial_eval_alias(value, acc_args=acc_args)
else: else:
expand_path = builtins.__xonsh__.expand_path expand_path = XSH.expand_path
token, *rest = map(expand_path, value) token, *rest = map(expand_path, value)
if token in seen_tokens or token not in self._raw: if token in seen_tokens or token not in self._raw:
# ^ Making sure things like `egrep=egrep --color=auto` works, # ^ Making sure things like `egrep=egrep --color=auto` works,
@ -115,7 +115,7 @@ class Aliases(cabc.MutableMapping):
The command won't be expanded if the cursor's inside/behind it. The command won't be expanded if the cursor's inside/behind it.
""" """
word = (line.split(maxsplit=1) or [""])[0] word = (line.split(maxsplit=1) or [""])[0]
if word in builtins.aliases and isinstance(self.get(word), cabc.Sequence): # type: ignore if word in XSH.aliases and isinstance(self.get(word), cabc.Sequence): # type: ignore
word_idx = line.find(word) word_idx = line.find(word)
word_edge = word_idx + len(word) word_edge = word_idx + len(word)
if cursor_index > word_edge: if cursor_index > word_edge:
@ -139,7 +139,7 @@ class Aliases(cabc.MutableMapping):
self._raw[key] = ExecAlias(val, filename=f) self._raw[key] = ExecAlias(val, filename=f)
elif isexpression(val): elif isexpression(val):
# expansion substitution # expansion substitution
lexer = builtins.__xonsh__.execer.parser.lexer lexer = XSH.execer.parser.lexer
self._raw[key] = list(map(strip_simple_quotes, lexer.split(val))) self._raw[key] = list(map(strip_simple_quotes, lexer.split(val)))
else: else:
# need to exec alias # need to exec alias
@ -204,14 +204,14 @@ class ExecAlias:
def __call__( def __call__(
self, args, stdin=None, stdout=None, stderr=None, spec=None, stack=None self, args, stdin=None, stdout=None, stderr=None, spec=None, stack=None
): ):
execer = builtins.__xonsh__.execer execer = XSH.execer
frame = stack[0][0] # execute as though we are at the call site frame = stack[0][0] # execute as though we are at the call site
alias_args = {"args": args} alias_args = {"args": args}
for i, a in enumerate(args): for i, a in enumerate(args):
alias_args[f"arg{i}"] = a alias_args[f"arg{i}"] = a
with builtins.__xonsh__.env.swap(alias_args): with XSH.env.swap(alias_args):
execer.exec( execer.exec(
self.src, self.src,
glbs=frame.f_globals, glbs=frame.f_globals,
@ -357,14 +357,14 @@ def xonsh_exit(args, stdin=None):
if not clean_jobs(): if not clean_jobs():
# Do not exit if jobs not cleaned up # Do not exit if jobs not cleaned up
return None, None return None, None
builtins.__xonsh__.exit = True XSH.exit = True
print() # gimme a newline print() # gimme a newline
return None, None return None, None
def xonsh_reset(args, stdin=None): def xonsh_reset(args, stdin=None):
"""Clears __xonsh__.ctx""" """Clears __xonsh__.ctx"""
builtins.__xonsh__.ctx.clear() XSH.ctx.clear()
@lazyobject @lazyobject
@ -496,7 +496,7 @@ def _SOURCE_FOREIGN_PARSER():
def source_foreign(args, stdin=None, stdout=None, stderr=None): def source_foreign(args, stdin=None, stdout=None, stderr=None):
"""Sources a file written in a foreign shell language.""" """Sources a file written in a foreign shell language."""
env = builtins.__xonsh__.env env = XSH.env
ns = _SOURCE_FOREIGN_PARSER.parse_args(args) ns = _SOURCE_FOREIGN_PARSER.parse_args(args)
ns.suppress_skip_message = ( ns.suppress_skip_message = (
env.get("FOREIGN_ALIASES_SUPPRESS_SKIP_MESSAGE") env.get("FOREIGN_ALIASES_SUPPRESS_SKIP_MESSAGE")
@ -547,7 +547,7 @@ def source_foreign(args, stdin=None, stdout=None, stderr=None):
if k not in fsenv: if k not in fsenv:
env.pop(k, None) env.pop(k, None)
# Update aliases # Update aliases
baliases = builtins.aliases baliases = XSH.aliases
for k, v in fsaliases.items(): for k, v in fsaliases.items():
if k in baliases and v == baliases[k]: if k in baliases and v == baliases[k]:
continue # no change from original continue # no change from original
@ -572,7 +572,7 @@ def source_alias(args, stdin=None):
If sourced file isn't found in cwd, search for file along $PATH to source If sourced file isn't found in cwd, search for file along $PATH to source
instead. instead.
""" """
env = builtins.__xonsh__.env env = XSH.env
encoding = env.get("XONSH_ENCODING") encoding = env.get("XONSH_ENCODING")
errors = env.get("XONSH_ENCODING_ERRORS") errors = env.get("XONSH_ENCODING_ERRORS")
for i, fname in enumerate(args): for i, fname in enumerate(args):
@ -599,11 +599,11 @@ def source_alias(args, stdin=None):
src = fp.read() src = fp.read()
if not src.endswith("\n"): if not src.endswith("\n"):
src += "\n" src += "\n"
ctx = builtins.__xonsh__.ctx ctx = XSH.ctx
updates = {"__file__": fpath, "__name__": os.path.abspath(fpath)} updates = {"__file__": fpath, "__name__": os.path.abspath(fpath)}
with env.swap(**make_args_env(args[i + 1 :])), swap_values(ctx, updates): with env.swap(**make_args_env(args[i + 1 :])), swap_values(ctx, updates):
try: try:
builtins.execx(src, "exec", ctx, filename=fpath) XSH.builtins.execx(src, "exec", ctx, filename=fpath)
except Exception: except Exception:
print_color( print_color(
"{RED}You may be attempting to source non-xonsh file! " "{RED}You may be attempting to source non-xonsh file! "
@ -633,7 +633,7 @@ def source_cmd(args, stdin=None):
args.append("--envcmd=set") args.append("--envcmd=set")
args.append("--seterrpostcmd=if errorlevel 1 exit 1") args.append("--seterrpostcmd=if errorlevel 1 exit 1")
args.append("--use-tmpfile=1") args.append("--use-tmpfile=1")
with builtins.__xonsh__.env.swap(PROMPT="$P$G"): with XSH.env.swap(PROMPT="$P$G"):
return source_foreign(args, stdin=stdin) return source_foreign(args, stdin=stdin)
@ -690,7 +690,7 @@ def xexec(args, stdin=None):
denv = {} denv = {}
if not args.clean: if not args.clean:
denv = builtins.__xonsh__.env.detype() denv = XSH.env.detype()
try: try:
os.execvpe(command, args.command, denv) os.execvpe(command, args.command, denv)

View file

@ -2,9 +2,9 @@
import re import re
import sys import sys
import warnings import warnings
import builtins
import typing as tp import typing as tp
from xonsh.built_ins import XSH
from xonsh.platform import HAS_PYGMENTS from xonsh.platform import HAS_PYGMENTS
from xonsh.lazyasd import LazyDict, lazyobject from xonsh.lazyasd import LazyDict, lazyobject
from xonsh.color_tools import ( from xonsh.color_tools import (
@ -49,7 +49,7 @@ def _ensure_color_map(style="default", cmap=None):
except Exception: except Exception:
msg = "Could not find color style {0!r}, using default." msg = "Could not find color style {0!r}, using default."
print(msg.format(style), file=sys.stderr) print(msg.format(style), file=sys.stderr)
builtins.__xonsh__.env["XONSH_COLOR_STYLE"] = "default" XSH.env["XONSH_COLOR_STYLE"] = "default"
cmap = ANSI_STYLES["default"] cmap = ANSI_STYLES["default"]
return cmap return cmap
@ -163,7 +163,7 @@ def ansi_partial_color_format(template, style="default", cmap=None, hide=False):
def _ansi_partial_color_format_main(template, style="default", cmap=None, hide=False): def _ansi_partial_color_format_main(template, style="default", cmap=None, hide=False):
cmap = _ensure_color_map(style=style, cmap=cmap) cmap = _ensure_color_map(style=style, cmap=cmap)
overrides = builtins.__xonsh__.env["XONSH_STYLE_OVERRIDES"] overrides = XSH.env["XONSH_STYLE_OVERRIDES"]
if overrides: if overrides:
cmap.update(_style_dict_to_ansi(overrides)) cmap.update(_style_dict_to_ansi(overrides))
esc = ("\001" if hide else "") + "\033[" esc = ("\001" if hide else "") + "\033["

View file

@ -3,7 +3,6 @@
# These are imported into our module namespace for the benefit of parser.py. # These are imported into our module namespace for the benefit of parser.py.
# pylint: disable=unused-import # pylint: disable=unused-import
import sys import sys
import builtins
from ast import ( from ast import (
Module, Module,
Num, Num,
@ -109,6 +108,7 @@ from ast import Ellipsis as EllipsisNode
import textwrap import textwrap
import itertools import itertools
from xonsh.built_ins import XSH
from xonsh.tools import subproc_toks, find_next_break, get_logical_line from xonsh.tools import subproc_toks, find_next_break, get_logical_line
from ast import ( from ast import (
@ -314,8 +314,8 @@ def isexpression(node, ctx=None, *args, **kwargs):
# parse string to AST # parse string to AST
if isinstance(node, str): if isinstance(node, str):
node = node if node.endswith("\n") else node + "\n" node = node if node.endswith("\n") else node + "\n"
ctx = builtins.__xonsh__.ctx if ctx is None else ctx ctx = XSH.ctx if ctx is None else ctx
node = builtins.__xonsh__.execer.parse(node, ctx, *args, **kwargs) node = XSH.execer.parse(node, ctx, *args, **kwargs)
# determin if expresission-like enough # determin if expresission-like enough
if isinstance(node, (Expr, Expression)): if isinstance(node, (Expr, Expression)):
isexpr = True isexpr = True

View file

@ -4,8 +4,8 @@ import io
import os import os
import sys import sys
import time import time
import builtins
from xonsh.built_ins import XSH
from xonsh.tools import ( from xonsh.tools import (
XonshError, XonshError,
print_exception, print_exception,
@ -66,7 +66,7 @@ class _TeeStdBuf(io.RawIOBase):
""" """
self.stdbuf = stdbuf self.stdbuf = stdbuf
self.membuf = membuf self.membuf = membuf
env = builtins.__xonsh__.env env = XSH.env
self.encoding = env.get("XONSH_ENCODING") if encoding is None else encoding self.encoding = env.get("XONSH_ENCODING") if encoding is None else encoding
self.errors = env.get("XONSH_ENCODING_ERRORS") if errors is None else errors self.errors = env.get("XONSH_ENCODING_ERRORS") if errors is None else errors
self.prestd = prestd self.prestd = prestd
@ -268,7 +268,7 @@ class Tee:
write_through=write_through, write_through=write_through,
) )
self.stdout = _TeeStd("stdout", self.memory) self.stdout = _TeeStd("stdout", self.memory)
env = builtins.__xonsh__.env env = XSH.env
prestderr = format_std_prepost(env.get("XONSH_STDERR_PREFIX")) prestderr = format_std_prepost(env.get("XONSH_STDERR_PREFIX"))
poststderr = format_std_prepost(env.get("XONSH_STDERR_POSTFIX")) poststderr = format_std_prepost(env.get("XONSH_STDERR_POSTFIX"))
self.stderr = _TeeStd( self.stderr = _TeeStd(
@ -324,7 +324,7 @@ class BaseShell(object):
if HAS_PYGMENTS: if HAS_PYGMENTS:
from xonsh.pyghooks import XonshStyle from xonsh.pyghooks import XonshStyle
env = builtins.__xonsh__.env env = XSH.env
self._styler = XonshStyle(env.get("XONSH_COLOR_STYLE")) self._styler = XonshStyle(env.get("XONSH_COLOR_STYLE"))
else: else:
self._styler = None self._styler = None
@ -367,8 +367,8 @@ class BaseShell(object):
events.on_precommand.fire(cmd=src) events.on_precommand.fire(cmd=src)
env = builtins.__xonsh__.env env = XSH.env
hist = builtins.__xonsh__.history # pylint: disable=no-member hist = XSH.history # pylint: disable=no-member
ts1 = None ts1 = None
enc = env.get("XONSH_ENCODING") enc = env.get("XONSH_ENCODING")
err = env.get("XONSH_ENCODING_ERRORS") err = env.get("XONSH_ENCODING_ERRORS")
@ -406,7 +406,7 @@ class BaseShell(object):
print(os.linesep, end="") print(os.linesep, end="")
tee.close() tee.close()
self._fix_cwd() self._fix_cwd()
if builtins.__xonsh__.exit: # pylint: disable=no-member if XSH.exit: # pylint: disable=no-member
return True return True
def _append_history(self, tee_out=None, **info): def _append_history(self, tee_out=None, **info):
@ -415,7 +415,7 @@ class BaseShell(object):
This also handles on_postcommand because this is the place where all the This also handles on_postcommand because this is the place where all the
information is available. information is available.
""" """
hist = builtins.__xonsh__.history # pylint: disable=no-member hist = XSH.history # pylint: disable=no-member
info["rtn"] = hist.last_cmd_rtn if hist is not None else None info["rtn"] = hist.last_cmd_rtn if hist is not None else None
tee_out = tee_out or None tee_out = tee_out or None
last_out = hist.last_cmd_out if hist is not None else None last_out = hist.last_cmd_out if hist is not None else None
@ -436,7 +436,7 @@ class BaseShell(object):
def _fix_cwd(self): def _fix_cwd(self):
"""Check if the cwd changed out from under us.""" """Check if the cwd changed out from under us."""
env = builtins.__xonsh__.env env = XSH.env
try: try:
cwd = os.getcwd() cwd = os.getcwd()
except (FileNotFoundError, OSError): except (FileNotFoundError, OSError):
@ -523,7 +523,7 @@ class BaseShell(object):
def settitle(self): def settitle(self):
"""Sets terminal title.""" """Sets terminal title."""
env = builtins.__xonsh__.env # pylint: disable=no-member env = XSH.env # pylint: disable=no-member
term = env.get("TERM", None) term = env.get("TERM", None)
# Shells running in emacs sets TERM to "dumb" or "eterm-color". # Shells running in emacs sets TERM to "dumb" or "eterm-color".
# Do not set title for these to avoid garbled prompt. # Do not set title for these to avoid garbled prompt.
@ -557,7 +557,7 @@ class BaseShell(object):
print_exception() print_exception()
self.mlprompt = "<multiline prompt error> " self.mlprompt = "<multiline prompt error> "
return self.mlprompt return self.mlprompt
env = builtins.__xonsh__.env # pylint: disable=no-member env = XSH.env # pylint: disable=no-member
p = env.get("PROMPT") p = env.get("PROMPT")
try: try:
p = self.prompt_formatter(p) p = self.prompt_formatter(p)
@ -570,7 +570,7 @@ class BaseShell(object):
"""Formats the colors in a string. ``BaseShell``'s default implementation """Formats the colors in a string. ``BaseShell``'s default implementation
of this method uses colors based on ANSI color codes. of this method uses colors based on ANSI color codes.
""" """
style = builtins.__xonsh__.env.get("XONSH_COLOR_STYLE") style = XSH.env.get("XONSH_COLOR_STYLE")
return ansi_partial_color_format(string, hide=hide, style=style) return ansi_partial_color_format(string, hide=hide, style=style)
def print_color(self, string, hide=False, **kwargs): def print_color(self, string, hide=False, **kwargs):
@ -583,7 +583,7 @@ class BaseShell(object):
s = self.format_color(string, hide=hide) s = self.format_color(string, hide=hide)
elif HAS_PYGMENTS: elif HAS_PYGMENTS:
# assume this is a list of (Token, str) tuples and format it # assume this is a list of (Token, str) tuples and format it
env = builtins.__xonsh__.env env = XSH.env
self.styler.style_name = env.get("XONSH_COLOR_STYLE") self.styler.style_name = env.get("XONSH_COLOR_STYLE")
style_proxy = pyghooks.xonsh_style_proxy(self.styler) style_proxy = pyghooks.xonsh_style_proxy(self.styler)
formatter = pyghooks.XonshTerminal256Formatter(style=style_proxy) formatter = pyghooks.XonshTerminal256Formatter(style=style_proxy)

View file

@ -18,11 +18,9 @@ import itertools
import contextlib import contextlib
import collections.abc as cabc import collections.abc as cabc
from xonsh.ast import AST from ast import AST
from xonsh.lazyasd import LazyObject, lazyobject from xonsh.lazyasd import lazyobject
from xonsh.inspectors import Inspector from xonsh.inspectors import Inspector
from xonsh.aliases import Aliases, make_default_aliases
from xonsh.environ import Env, default_env
from xonsh.platform import ON_POSIX, ON_WINDOWS from xonsh.platform import ON_POSIX, ON_WINDOWS
from xonsh.tools import ( from xonsh.tools import (
expand_path, expand_path,
@ -31,14 +29,8 @@ from xonsh.tools import (
XonshCalledProcessError, XonshCalledProcessError,
print_color, print_color,
) )
from xonsh.commands_cache import CommandsCache
from xonsh.events import events
import xonsh.procs.specs INSPECTOR = Inspector()
import xonsh.completers.init
BUILTINS_LOADED = False
INSPECTOR = LazyObject(Inspector, globals(), "INSPECTOR")
warnings.filterwarnings("once", category=DeprecationWarning) warnings.filterwarnings("once", category=DeprecationWarning)
@ -136,9 +128,9 @@ def regexsearch(s):
def globsearch(s): def globsearch(s):
csc = builtins.__xonsh__.env.get("CASE_SENSITIVE_COMPLETIONS") csc = XSH.env.get("CASE_SENSITIVE_COMPLETIONS")
glob_sorted = builtins.__xonsh__.env.get("GLOB_SORTED") glob_sorted = XSH.env.get("GLOB_SORTED")
dotglob = builtins.__xonsh__.env.get("DOTGLOB") dotglob = XSH.env.get("DOTGLOB")
return globpath( return globpath(
s, s,
ignore_case=(not csc), ignore_case=(not csc),
@ -168,6 +160,9 @@ def subproc_captured_stdout(*cmds, envs=None):
"""Runs a subprocess, capturing the output. Returns the stdout """Runs a subprocess, capturing the output. Returns the stdout
that was produced as a str. that was produced as a str.
""" """
import xonsh.procs.specs
return xonsh.procs.specs.run_subproc(cmds, captured="stdout", envs=envs) return xonsh.procs.specs.run_subproc(cmds, captured="stdout", envs=envs)
@ -177,12 +172,14 @@ def subproc_captured_inject(*cmds, envs=None):
The string is split using xonsh's lexer, rather than Python's str.split() The string is split using xonsh's lexer, rather than Python's str.split()
or shlex.split(). or shlex.split().
""" """
import xonsh.procs.specs
o = xonsh.procs.specs.run_subproc(cmds, captured="object", envs=envs) o = xonsh.procs.specs.run_subproc(cmds, captured="object", envs=envs)
o.end() o.end()
toks = [] toks = []
for line in o: for line in o:
line = line.rstrip(os.linesep) line = line.rstrip(os.linesep)
toks.extend(builtins.__xonsh__.execer.parser.lexer.split(line)) toks.extend(XSH.execer.parser.lexer.split(line))
return toks return toks
@ -191,6 +188,8 @@ def subproc_captured_object(*cmds, envs=None):
Runs a subprocess, capturing the output. Returns an instance of Runs a subprocess, capturing the output. Returns an instance of
CommandPipeline representing the completed command. CommandPipeline representing the completed command.
""" """
import xonsh.procs.specs
return xonsh.procs.specs.run_subproc(cmds, captured="object", envs=envs) return xonsh.procs.specs.run_subproc(cmds, captured="object", envs=envs)
@ -198,6 +197,8 @@ def subproc_captured_hiddenobject(*cmds, envs=None):
"""Runs a subprocess, capturing the output. Returns an instance of """Runs a subprocess, capturing the output. Returns an instance of
HiddenCommandPipeline representing the completed command. HiddenCommandPipeline representing the completed command.
""" """
import xonsh.procs.specs
return xonsh.procs.specs.run_subproc(cmds, captured="hiddenobject", envs=envs) return xonsh.procs.specs.run_subproc(cmds, captured="hiddenobject", envs=envs)
@ -205,6 +206,8 @@ def subproc_uncaptured(*cmds, envs=None):
"""Runs a subprocess, without capturing the output. Returns the stdout """Runs a subprocess, without capturing the output. Returns the stdout
that was produced as a str. that was produced as a str.
""" """
import xonsh.procs.specs
return xonsh.procs.specs.run_subproc(cmds, captured=False, envs=envs) return xonsh.procs.specs.run_subproc(cmds, captured=False, envs=envs)
@ -252,16 +255,16 @@ def list_of_list_of_strs_outer_product(x):
for los in itertools.product(*lolos): for los in itertools.product(*lolos):
s = "".join(los) s = "".join(los)
if "*" in s: if "*" in s:
rtn.extend(builtins.__xonsh__.glob(s)) rtn.extend(XSH.glob(s))
else: else:
rtn.append(builtins.__xonsh__.expand_path(s)) rtn.append(XSH.expand_path(s))
return rtn return rtn
def eval_fstring_field(field): def eval_fstring_field(field):
"""Evaluates the argument in Xonsh context.""" """Evaluates the argument in Xonsh context."""
res = __xonsh__.execer.eval( res = XSH.execer.eval(
field[0].strip(), glbs=globals(), locs=builtins.__xonsh__.ctx, filename=field[1] field[0].strip(), glbs=globals(), locs=XSH.ctx, filename=field[1]
) )
return res return res
@ -327,7 +330,7 @@ def convert_macro_arg(raw_arg, kind, glbs, locs, *, name="<arg>", macroname="<ma
if kind is str or kind is None: if kind is str or kind is None:
return raw_arg # short circuit since there is nothing else to do return raw_arg # short circuit since there is nothing else to do
# select from kind and convert # select from kind and convert
execer = builtins.__xonsh__.execer execer = XSH.execer
filename = macroname + "(" + name + ")" filename = macroname + "(" + name + ")"
if kind is AST: if kind is AST:
ctx = set(dir(builtins)) | set(glbs.keys()) ctx = set(dir(builtins)) | set(glbs.keys())
@ -440,7 +443,7 @@ def _eval_regular_args(raw_args, glbs, locs):
return [], {} return [], {}
arglist = list(itertools.takewhile(_starts_as_arg, raw_args)) arglist = list(itertools.takewhile(_starts_as_arg, raw_args))
kwarglist = raw_args[len(arglist) :] kwarglist = raw_args[len(arglist) :]
execer = builtins.__xonsh__.execer execer = XSH.execer
if not arglist: if not arglist:
args = arglist args = arglist
kwargstr = "dict({})".format(", ".join(kwarglist)) kwargstr = "dict({})".format(", ".join(kwarglist))
@ -498,44 +501,9 @@ def enter_macro(obj, raw_block, glbs, locs):
return obj return obj
def load_builtins(execer=None, ctx=None):
"""Loads the xonsh builtins into the Python builtins. Sets the
BUILTINS_LOADED variable to True.
"""
global BUILTINS_LOADED
if not hasattr(builtins, "__xonsh__"):
builtins.__xonsh__ = XonshSession(execer=execer, ctx=ctx)
builtins.__xonsh__.load(execer=execer, ctx=ctx)
builtins.__xonsh__.link_builtins(execer=execer)
BUILTINS_LOADED = True
def _lastflush(s=None, f=None): def _lastflush(s=None, f=None):
if hasattr(builtins, "__xonsh__"): if XSH.history is not None:
if builtins.__xonsh__.history is not None: XSH.history.flush(at_exit=True)
builtins.__xonsh__.history.flush(at_exit=True)
def unload_builtins():
"""Removes the xonsh builtins from the Python builtins, if the
BUILTINS_LOADED is True, sets BUILTINS_LOADED to False, and returns.
"""
global BUILTINS_LOADED
if not hasattr(builtins, "__xonsh__"):
BUILTINS_LOADED = False
return
env = getattr(builtins.__xonsh__, "env", None)
if isinstance(env, Env):
env.undo_replace_env()
if hasattr(builtins.__xonsh__, "pyexit"):
builtins.exit = builtins.__xonsh__.pyexit
if hasattr(builtins.__xonsh__, "pyquit"):
builtins.quit = builtins.__xonsh__.pyquit
if not BUILTINS_LOADED:
return
builtins.__xonsh__.unlink_builtins()
delattr(builtins, "__xonsh__")
BUILTINS_LOADED = False
@contextlib.contextmanager @contextlib.contextmanager
@ -543,9 +511,9 @@ def xonsh_builtins(execer=None):
"""A context manager for using the xonsh builtins only in a limited """A context manager for using the xonsh builtins only in a limited
scope. Likely useful in testing. scope. Likely useful in testing.
""" """
load_builtins(execer=execer) XSH.load(execer=execer)
yield yield
unload_builtins() XSH.unload()
class XonshSession: class XonshSession:
@ -562,8 +530,12 @@ class XonshSession:
""" """
self.execer = execer self.execer = execer
self.ctx = {} if ctx is None else ctx self.ctx = {} if ctx is None else ctx
self.builtins_loaded = False
self.history = None
self.shell = None
self.env = None
def load(self, execer=None, ctx=None): def load(self, execer=None, ctx=None, **kwargs):
"""Loads the session with default values. """Loads the session with default values.
Parameters Parameters
@ -573,10 +545,17 @@ class XonshSession:
ctx : Mapping, optional ctx : Mapping, optional
Context to start xonsh session with. Context to start xonsh session with.
""" """
from xonsh.environ import Env, default_env
from xonsh.commands_cache import CommandsCache
from xonsh.completers.init import default_completers
if not hasattr(builtins, "__xonsh__"):
builtins.__xonsh__ = self
if ctx is not None: if ctx is not None:
self.ctx = ctx self.ctx = ctx
self.env = Env(default_env())
self.help = helper self.env = kwargs.pop("env") if "env" in kwargs else Env(default_env())
self.help = kwargs.pop("help") if "help" in kwargs else helper
self.superhelp = superhelper self.superhelp = superhelper
self.pathsearch = pathsearch self.pathsearch = pathsearch
self.globsearch = globsearch self.globsearch = globsearch
@ -608,36 +587,45 @@ class XonshSession:
self.list_of_list_of_strs_outer_product = list_of_list_of_strs_outer_product self.list_of_list_of_strs_outer_product = list_of_list_of_strs_outer_product
self.eval_fstring_field = eval_fstring_field self.eval_fstring_field = eval_fstring_field
self.completers = xonsh.completers.init.default_completers() self.completers = default_completers()
self.call_macro = call_macro self.call_macro = call_macro
self.enter_macro = enter_macro self.enter_macro = enter_macro
self.path_literal = path_literal self.path_literal = path_literal
self.builtins = _BuiltIns(execer) self.builtins = _BuiltIns(execer)
self.history = None aliases_given = kwargs.pop("aliases", None)
self.shell = None for attr, value in kwargs.items():
if hasattr(self, attr):
setattr(self, attr, value)
self.link_builtins(aliases_given)
self.builtins_loaded = True
def link_builtins(self, aliases=None):
from xonsh.aliases import Aliases, make_default_aliases
def link_builtins(self, execer=None):
# public built-ins # public built-ins
proxy_mapping = { proxy_mapping = [
"XonshError": "__xonsh__.builtins.XonshError", "XonshError",
"XonshCalledProcessError": "__xonsh__.builtins.XonshCalledProcessError", "XonshCalledProcessError",
"evalx": "__xonsh__.builtins.evalx", "evalx",
"execx": "__xonsh__.builtins.execx", "execx",
"compilex": "__xonsh__.builtins.compilex", "compilex",
"events": "__xonsh__.builtins.events", "events",
"print_color": "__xonsh__.builtins.print_color", "print_color",
"printx": "__xonsh__.builtins.printx", "printx",
} ]
for refname, objname in proxy_mapping.items(): for refname in proxy_mapping:
objname = f"__xonsh__.builtins.{refname}"
proxy = DynamicAccessProxy(refname, objname) proxy = DynamicAccessProxy(refname, objname)
setattr(builtins, refname, proxy) setattr(builtins, refname, proxy)
# sneak the path search functions into the aliases # sneak the path search functions into the aliases
# Need this inline/lazy import here since we use locate_binary that # Need this inline/lazy import here since we use locate_binary that
# relies on __xonsh__.env in default aliases # relies on __xonsh__.env in default aliases
builtins.default_aliases = builtins.aliases = Aliases(make_default_aliases()) if aliases is None:
aliases = Aliases(make_default_aliases())
self.aliases = builtins.default_aliases = builtins.aliases = aliases
atexit.register(_lastflush) atexit.register(_lastflush)
for sig in AT_EXIT_SIGNALS: for sig in AT_EXIT_SIGNALS:
resetting_signal_handle(sig, _lastflush) resetting_signal_handle(sig, _lastflush)
@ -659,9 +647,28 @@ class XonshSession:
if hasattr(builtins, name): if hasattr(builtins, name):
delattr(builtins, name) delattr(builtins, name)
def unload(self):
if not hasattr(builtins, "__xonsh__"):
self.builtins_loaded = False
return
env = getattr(self, "env", None)
if hasattr(self.env, "undo_replace_env"):
env.undo_replace_env()
if hasattr(self, "pyexit"):
builtins.exit = self.pyexit
if hasattr(self, "pyquit"):
builtins.quit = self.pyquit
if not self.builtins_loaded:
return
self.unlink_builtins()
delattr(builtins, "__xonsh__")
self.builtins_loaded = False
class _BuiltIns: class _BuiltIns:
def __init__(self, execer=None): def __init__(self, execer=None):
from xonsh.events import events
# public built-ins # public built-ins
self.XonshError = XonshError self.XonshError = XonshError
self.XonshCalledProcessError = XonshCalledProcessError self.XonshCalledProcessError = XonshCalledProcessError
@ -721,3 +728,7 @@ class DynamicAccessProxy:
def __dir__(self): def __dir__(self):
return self.obj.__dir__() return self.obj.__dir__()
# singleton
XSH = XonshSession()

View file

@ -1,11 +1,11 @@
"""Tools for caching xonsh code.""" """Tools for caching xonsh code."""
import os
import sys
import hashlib import hashlib
import marshal import marshal
import builtins import os
import sys
from xonsh import __version__ as XONSH_VERSION from xonsh import __version__ as XONSH_VERSION
from xonsh.built_ins import XSH
from xonsh.lazyasd import lazyobject from xonsh.lazyasd import lazyobject
from xonsh.platform import PYTHON_VERSION_INFO_BYTES from xonsh.platform import PYTHON_VERSION_INFO_BYTES
@ -47,11 +47,10 @@ def should_use_cache(execer, mode):
""" """
if mode == "exec": if mode == "exec":
return (execer.scriptcache or execer.cacheall) and ( return (execer.scriptcache or execer.cacheall) and (
builtins.__xonsh__.env["XONSH_CACHE_SCRIPTS"] XSH.env["XONSH_CACHE_SCRIPTS"] or XSH.env["XONSH_CACHE_EVERYTHING"]
or builtins.__xonsh__.env["XONSH_CACHE_EVERYTHING"]
) )
else: else:
return execer.cacheall or builtins.__xonsh__.env["XONSH_CACHE_EVERYTHING"] return execer.cacheall or XSH.env["XONSH_CACHE_EVERYTHING"]
def run_compiled_code(code, glb, loc, mode): def run_compiled_code(code, glb, loc, mode):
@ -77,7 +76,7 @@ def get_cache_filename(fname, code=True):
The ``code`` switch should be true if we should use the code store rather The ``code`` switch should be true if we should use the code store rather
than the script store. than the script store.
""" """
datadir = builtins.__xonsh__.env["XONSH_DATA_DIR"] datadir = XSH.env["XONSH_DATA_DIR"]
cachedir = os.path.join( cachedir = os.path.join(
datadir, "xonsh_code_cache" if code else "xonsh_script_cache" datadir, "xonsh_code_cache" if code else "xonsh_script_cache"
) )

View file

@ -11,12 +11,12 @@ import pickle
import sys import sys
import threading import threading
import time import time
import builtins
import argparse import argparse
import collections.abc as cabc import collections.abc as cabc
import typing as tp import typing as tp
from pathlib import Path from pathlib import Path
from xonsh.built_ins import XSH
from xonsh.platform import ON_WINDOWS, ON_POSIX, pathbasename from xonsh.platform import ON_WINDOWS, ON_POSIX, pathbasename
from xonsh.tools import executables_in from xonsh.tools import executables_in
from xonsh.lazyasd import lazyobject from xonsh.lazyasd import lazyobject
@ -41,7 +41,7 @@ class CommandsCache(cabc.Mapping):
self._loaded_pickled = False self._loaded_pickled = False
# Path to the cache-file where all commands/aliases are cached for pre-loading""" # Path to the cache-file where all commands/aliases are cached for pre-loading"""
env = builtins.__xonsh__.env env = XSH.env
self.cache_file = ( self.cache_file = (
(Path(env["XONSH_DATA_DIR"]).joinpath(self.CACHE_FILE).resolve()) (Path(env["XONSH_DATA_DIR"]).joinpath(self.CACHE_FILE).resolve())
if "XONSH_DATA_DIR" in env and env.get("COMMANDS_CACHE_SAVE_INTERMEDIATE") if "XONSH_DATA_DIR" in env and env.get("COMMANDS_CACHE_SAVE_INTERMEDIATE")
@ -77,7 +77,7 @@ class CommandsCache(cabc.Mapping):
name on Windows as a list, conserving the ordering in `PATHEXT`. name on Windows as a list, conserving the ordering in `PATHEXT`.
Returns a list as `name` being the only item in it on other platforms.""" Returns a list as `name` being the only item in it on other platforms."""
if ON_WINDOWS: if ON_WINDOWS:
pathext = builtins.__xonsh__.env.get("PATHEXT", []) pathext = XSH.env.get("PATHEXT", [])
name = name.upper() name = name.upper()
return [name + ext for ext in ([""] + pathext)] return [name + ext for ext in ([""] + pathext)]
else: else:
@ -109,9 +109,9 @@ class CommandsCache(cabc.Mapping):
@property @property
def all_commands(self): def all_commands(self):
paths = CommandsCache.remove_dups(builtins.__xonsh__.env.get("PATH", [])) paths = CommandsCache.remove_dups(XSH.env.get("PATH", []))
path_immut = tuple(x for x in paths if os.path.isdir(x)) path_immut = tuple(x for x in paths if os.path.isdir(x))
alss = getattr(builtins, "aliases", dict()) alss = getattr(XSH, "aliases", dict())
( (
has_path_changed, has_path_changed,
has_alias_changed, has_alias_changed,
@ -150,7 +150,7 @@ class CommandsCache(cabc.Mapping):
self, paths: tp.Sequence[str], aliases: tp.Dict[str, str] self, paths: tp.Sequence[str], aliases: tp.Dict[str, str]
) -> tp.Dict[str, tp.Any]: ) -> tp.Dict[str, tp.Any]:
"""Update the cmds_cache variable in background without slowing down parseLexer""" """Update the cmds_cache variable in background without slowing down parseLexer"""
env = builtins.__xonsh__.env # type: ignore env = XSH.env # type: ignore
allcmds = {} allcmds = {}
for path in reversed(paths): for path in reversed(paths):
@ -330,7 +330,7 @@ class CommandsCache(cabc.Mapping):
""" """
# alias stuff # alias stuff
if not os.path.isabs(cmd0) and os.sep not in cmd0: if not os.path.isabs(cmd0) and os.sep not in cmd0:
alss = getattr(builtins, "aliases", dict()) alss = getattr(XSH, "aliases", dict())
if cmd0 in alss: if cmd0 in alss:
return self.default_predictor_alias(cmd0) return self.default_predictor_alias(cmd0)
@ -347,7 +347,7 @@ class CommandsCache(cabc.Mapping):
10 # this limit is se to handle infinite loops in aliases definition 10 # this limit is se to handle infinite loops in aliases definition
) )
first_args = [] # contains in reverse order args passed to the aliased command first_args = [] # contains in reverse order args passed to the aliased command
alss = getattr(builtins, "aliases", dict()) alss = getattr(XSH, "aliases", dict())
while cmd0 in alss: while cmd0 in alss:
alias_name = alss[cmd0] alias_name = alss[cmd0]
if isinstance(alias_name, (str, bytes)) or not isinstance( if isinstance(alias_name, (str, bytes)) or not isinstance(
@ -507,7 +507,7 @@ def predict_env(args):
if args[i] and args[i][0] != "-" and "=" not in args[i]: if args[i] and args[i][0] != "-" and "=" not in args[i]:
# args[i] is the command and the following is its arguments # args[i] is the command and the following is its arguments
# so args[i:] is used to predict if the command is threadable # so args[i:] is used to predict if the command is threadable
return builtins.__xonsh__.commands_cache.predict_threadable(args[i:]) return XSH.commands_cache.predict_threadable(args[i:])
return True return True

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""A (tab-)completer for xonsh.""" """A (tab-)completer for xonsh."""
import builtins
import typing as tp import typing as tp
import collections.abc as cabc import collections.abc as cabc
@ -11,6 +10,7 @@ from xonsh.completers.tools import (
apply_lprefix, apply_lprefix,
is_exclusive_completer, is_exclusive_completer,
) )
from xonsh.built_ins import XSH
from xonsh.parsers.completion_context import CompletionContext, CompletionContextParser from xonsh.parsers.completion_context import CompletionContext, CompletionContextParser
from xonsh.tools import print_exception from xonsh.tools import print_exception
@ -80,7 +80,7 @@ class Completer(object):
def complete_from_context(self, completion_context, old_completer_args=None): def complete_from_context(self, completion_context, old_completer_args=None):
lprefix = 0 lprefix = 0
completions = set() completions = set()
for func in builtins.__xonsh__.completers.values(): for func in XSH.completers.values():
try: try:
if is_contextual_completer(func): if is_contextual_completer(func):
if completion_context is None: if completion_context is None:

View file

@ -1,8 +1,8 @@
import argparse as ap import argparse as ap
import builtins
import xonsh.cli_utils as xcli import xonsh.cli_utils as xcli
import xonsh.lazyasd as xl import xonsh.lazyasd as xl
from xonsh.built_ins import XSH
from xonsh.completers.completer import ( from xonsh.completers.completer import (
list_completers, list_completers,
remove_completer, remove_completer,
@ -60,7 +60,7 @@ def _register_completer(name: str, func: str, pos="start", stack=None):
""" """
err = None err = None
func_name = func func_name = func
xsh = builtins.__xonsh__ # type: ignore xsh = XSH
if name in xsh.completers: if name in xsh.completers:
err = f"The name {name} is already a registered completer function." err = f"The name {name} is already a registered completer function."
else: else:

View file

@ -1,5 +1,4 @@
"""Xonsh hooks into bash completions.""" """Xonsh hooks into bash completions."""
import builtins
import xonsh.tools as xt import xonsh.tools as xt
import xonsh.platform as xp import xonsh.platform as xp
@ -7,13 +6,14 @@ from xonsh.completers.path import _quote_paths
from xonsh.completers.bash_completion import bash_completions from xonsh.completers.bash_completion import bash_completions
from xonsh.completers.tools import contextual_command_completer, RichCompletion from xonsh.completers.tools import contextual_command_completer, RichCompletion
from xonsh.parsers.completion_context import CommandContext from xonsh.parsers.completion_context import CommandContext
from xonsh.built_ins import XSH
@contextual_command_completer @contextual_command_completer
def complete_from_bash(context: CommandContext): def complete_from_bash(context: CommandContext):
"""Completes based on results from BASH completion.""" """Completes based on results from BASH completion."""
env = builtins.__xonsh__.env.detype() # type: ignore env = XSH.env.detype() # type: ignore
paths = builtins.__xonsh__.env.get("BASH_COMPLETIONS", ()) # type: ignore paths = XSH.env.get("BASH_COMPLETIONS", ()) # type: ignore
command = xp.bash_command() command = xp.bash_command()
args = [arg.value for arg in context.args] args = [arg.value for arg in context.args]
prefix = context.prefix # without the quotes prefix = context.prefix # without the quotes

View file

@ -1,5 +1,4 @@
import os import os
import builtins
import typing as tp import typing as tp
import xonsh.tools as xt import xonsh.tools as xt
@ -13,6 +12,8 @@ from xonsh.completers.tools import (
non_exclusive_completer, non_exclusive_completer,
) )
from xonsh.parsers.completion_context import CompletionContext, CommandContext from xonsh.parsers.completion_context import CompletionContext, CommandContext
from xonsh.built_ins import XSH
SKIP_TOKENS = {"sudo", "time", "timeit", "which", "showcmd", "man"} SKIP_TOKENS = {"sudo", "time", "timeit", "which", "showcmd", "man"}
END_PROC_TOKENS = ("|", ";", "&&") # includes || END_PROC_TOKENS = ("|", ";", "&&") # includes ||
@ -26,7 +27,7 @@ def complete_command(command: CommandContext):
cmd = command.prefix cmd = command.prefix
out: tp.Set[Completion] = { out: tp.Set[Completion] = {
RichCompletion(s, append_space=True) RichCompletion(s, append_space=True)
for s in builtins.__xonsh__.commands_cache # type: ignore for s in XSH.commands_cache # type: ignore
if get_filter_function()(s, cmd) if get_filter_function()(s, cmd)
} }
if xp.ON_WINDOWS: if xp.ON_WINDOWS:
@ -66,7 +67,7 @@ def complete_skipper(command_context: CommandContext):
# completing the command after a SKIP_TOKEN # completing the command after a SKIP_TOKEN
return complete_command(skipped_command_context) return complete_command(skipped_command_context)
completer: Completer = builtins.__xonsh__.shell.shell.completer # type: ignore completer: Completer = XSH.shell.shell.completer # type: ignore
return completer.complete_from_context(CompletionContext(skipped_command_context)) return completer.complete_from_context(CompletionContext(skipped_command_context))

View file

@ -1,15 +1,8 @@
import builtins
import collections import collections
from xonsh.parsers.completion_context import CommandContext from xonsh.parsers.completion_context import CommandContext
from xonsh.built_ins import XSH
from xonsh.completers.tools import contextual_command_completer_for, justify from xonsh.completers.tools import contextual_command_completer_for, justify
import xonsh.lazyasd as xla
@xla.lazyobject
def xsh_session():
"""return current xonshSession instance."""
return builtins.__xonsh__ # type: ignore
@contextual_command_completer_for("completer") @contextual_command_completer_for("completer")
@ -24,7 +17,7 @@ def complete_completer(command: CommandContext):
curix = command.arg_index curix = command.arg_index
compnames = set(xsh_session.completers.keys()) compnames = set(XSH.completers.keys())
if curix == 1: if curix == 1:
possible = {"list", "help", "add", "remove"} possible = {"list", "help", "add", "remove"}
elif curix == 2: elif curix == 2:
@ -39,7 +32,7 @@ def complete_completer(command: CommandContext):
if command.args[1].value != "add": if command.args[1].value != "add":
raise StopIteration raise StopIteration
if curix == 3: if curix == 3:
possible = {i for i, j in xsh_session.ctx.items() if callable(j)} possible = {i for i, j in XSH.ctx.items() if callable(j)}
elif curix == 4: elif curix == 4:
possible = ( possible = (
{"start", "end"} {"start", "end"}
@ -55,16 +48,16 @@ def add_one_completer(name, func, loc="end"):
new = collections.OrderedDict() new = collections.OrderedDict()
if loc == "start": if loc == "start":
new[name] = func new[name] = func
for (k, v) in xsh_session.completers.items(): for (k, v) in XSH.completers.items():
new[k] = v new[k] = v
elif loc == "end": elif loc == "end":
for (k, v) in xsh_session.completers.items(): for (k, v) in XSH.completers.items():
new[k] = v new[k] = v
new[name] = func new[name] = func
else: else:
direction, rel = loc[0], loc[1:] direction, rel = loc[0], loc[1:]
found = False found = False
for (k, v) in xsh_session.completers.items(): for (k, v) in XSH.completers.items():
if rel == k and direction == "<": if rel == k and direction == "<":
new[name] = func new[name] = func
found = True found = True
@ -74,14 +67,14 @@ def add_one_completer(name, func, loc="end"):
found = True found = True
if not found: if not found:
new[name] = func new[name] = func
xsh_session.completers.clear() XSH.completers.clear()
xsh_session.completers.update(new) XSH.completers.update(new)
def list_completers(): def list_completers():
"""List the active completers""" """List the active completers"""
o = "Registered Completer Functions: \n" o = "Registered Completer Functions: \n"
_comp = xsh_session.completers _comp = XSH.completers
ml = max((len(i) for i in _comp), default=0) ml = max((len(i) for i in _comp), default=0)
_strs = [] _strs = []
for c in _comp: for c in _comp:
@ -104,10 +97,10 @@ def remove_completer(name: str):
completers in order) completers in order)
""" """
err = None err = None
if name not in xsh_session.completers: if name not in XSH.completers:
err = f"The name {name} is not a registered completer function." err = f"The name {name} is not a registered completer function."
if err is None: if err is None:
del xsh_session.completers[name] del XSH.completers[name]
return return
else: else:
return None, err + "\n", 1 return None, err + "\n", 1

View file

@ -1,5 +1,4 @@
import builtins from xonsh.built_ins import XSH
from xonsh.parsers.completion_context import CompletionContext from xonsh.parsers.completion_context import CompletionContext
from xonsh.completers.tools import ( from xonsh.completers.tools import (
contextual_completer, contextual_completer,
@ -25,6 +24,6 @@ def complete_environment_vars(context: CompletionContext):
key = prefix[dollar_location + 1 :] key = prefix[dollar_location + 1 :]
lprefix = len(key) + 1 lprefix = len(key) + 1
filter_func = get_filter_function() filter_func = get_filter_function()
env_names = builtins.__xonsh__.env # type: ignore env_names = XSH.env
return {"$" + k for k in env_names if filter_func(k, key)}, lprefix return {"$" + k for k in env_names if filter_func(k, key)}, lprefix

View file

@ -1,12 +1,11 @@
import os import os
import re import re
import pickle import pickle
import builtins
import subprocess import subprocess
import typing as tp import typing as tp
from xonsh.parsers.completion_context import CommandContext from xonsh.parsers.completion_context import CommandContext
from xonsh.built_ins import XSH
import xonsh.lazyasd as xl import xonsh.lazyasd as xl
from xonsh.completers.tools import get_filter_function, contextual_command_completer from xonsh.completers.tools import get_filter_function, contextual_command_completer
@ -33,7 +32,7 @@ def complete_from_man(context: CommandContext):
""" """
global OPTIONS, OPTIONS_PATH global OPTIONS, OPTIONS_PATH
if OPTIONS is None: if OPTIONS is None:
datadir: str = builtins.__xonsh__.env["XONSH_DATA_DIR"] # type: ignore datadir: str = XSH.env["XONSH_DATA_DIR"] # type: ignore
OPTIONS_PATH = os.path.join(datadir, "man_completions_cache") OPTIONS_PATH = os.path.join(datadir, "man_completions_cache")
try: try:
with open(OPTIONS_PATH, "rb") as f: with open(OPTIONS_PATH, "rb") as f:

View file

@ -2,7 +2,8 @@ import os
import re import re
import ast import ast
import glob import glob
import builtins
from xonsh.built_ins import XSH
from xonsh.parsers.completion_context import CommandContext from xonsh.parsers.completion_context import CommandContext
import xonsh.tools as xt import xonsh.tools as xt
@ -26,7 +27,7 @@ def PATTERN_NEED_QUOTES():
def cd_in_command(line): def cd_in_command(line):
"""Returns True if "cd" is a token in the line, False otherwise.""" """Returns True if "cd" is a token in the line, False otherwise."""
lexer = builtins.__xonsh__.execer.parser.lexer lexer = XSH.execer.parser.lexer
lexer.reset() lexer.reset()
lexer.input(line) lexer.input(line)
have_cd = False have_cd = False
@ -80,7 +81,7 @@ def _path_from_partial_string(inp, pos=None):
except (SyntaxError, ValueError): except (SyntaxError, ValueError):
return None return None
if isinstance(val, bytes): if isinstance(val, bytes):
env = builtins.__xonsh__.env env = XSH.env
val = val.decode( val = val.decode(
encoding=env.get("XONSH_ENCODING"), errors=env.get("XONSH_ENCODING_ERRORS") encoding=env.get("XONSH_ENCODING"), errors=env.get("XONSH_ENCODING_ERRORS")
) )
@ -102,7 +103,7 @@ def _normpath(p):
p = os.path.join(os.curdir, p) p = os.path.join(os.curdir, p)
if trailing_slash: if trailing_slash:
p = os.path.join(p, "") p = os.path.join(p, "")
if xp.ON_WINDOWS and builtins.__xonsh__.env.get("FORCE_POSIX_PATHS"): if xp.ON_WINDOWS and XSH.env.get("FORCE_POSIX_PATHS"):
p = p.replace(os.sep, os.altsep) p = p.replace(os.sep, os.altsep)
return p return p
@ -118,7 +119,7 @@ def _startswithnorm(x, start, startlow=None):
def _dots(prefix): def _dots(prefix):
complete_dots = builtins.__xonsh__.env.get("COMPLETE_DOTS", "matching").lower() complete_dots = XSH.env.get("COMPLETE_DOTS", "matching").lower()
if complete_dots == "never": if complete_dots == "never":
return () return ()
slash = xt.get_sep() slash = xt.get_sep()
@ -137,7 +138,7 @@ def _dots(prefix):
def _add_cdpaths(paths, prefix): def _add_cdpaths(paths, prefix):
"""Completes current prefix using CDPATH""" """Completes current prefix using CDPATH"""
env = builtins.__xonsh__.env env = XSH.env
csc = env.get("CASE_SENSITIVE_COMPLETIONS") csc = env.get("CASE_SENSITIVE_COMPLETIONS")
glob_sorted = env.get("GLOB_SORTED") glob_sorted = env.get("GLOB_SORTED")
for cdp in env.get("CDPATH"): for cdp in env.get("CDPATH"):
@ -159,7 +160,7 @@ def _quote_to_use(x):
def _is_directory_in_cdpath(path): def _is_directory_in_cdpath(path):
env = builtins.__xonsh__.env env = XSH.env
for cdp in env.get("CDPATH"): for cdp in env.get("CDPATH"):
if os.path.isdir(os.path.join(cdp, path)): if os.path.isdir(os.path.join(cdp, path)):
return True return True
@ -167,7 +168,7 @@ def _is_directory_in_cdpath(path):
def _quote_paths(paths, start, end, append_end=True, cdpath=False): def _quote_paths(paths, start, end, append_end=True, cdpath=False):
expand_path = builtins.__xonsh__.expand_path expand_path = XSH.expand_path
out = set() out = set()
space = " " space = " "
backslash = "\\" backslash = "\\"
@ -274,7 +275,7 @@ def _subsequence_match_iter(ref, typed):
def _expand_one(sofar, nextone, csc): def _expand_one(sofar, nextone, csc):
out = set() out = set()
glob_sorted = builtins.__xonsh__.env.get("GLOB_SORTED") glob_sorted = XSH.env.get("GLOB_SORTED")
for i in sofar: for i in sofar:
_glob = os.path.join(_joinpath(i), "*") if i is not None else "*" _glob = os.path.join(_joinpath(i), "*") if i is not None else "*"
for j in xt.iglobpath(_glob, sort_result=glob_sorted): for j in xt.iglobpath(_glob, sort_result=glob_sorted):
@ -305,7 +306,7 @@ def _complete_path_raw(prefix, line, start, end, ctx, cdpath=True, filtfunc=None
append_end = False append_end = False
tilde = "~" tilde = "~"
paths = set() paths = set()
env = builtins.__xonsh__.env env = XSH.env
csc = env.get("CASE_SENSITIVE_COMPLETIONS") csc = env.get("CASE_SENSITIVE_COMPLETIONS")
glob_sorted = env.get("GLOB_SORTED") glob_sorted = env.get("GLOB_SORTED")
prefix = glob.escape(prefix) prefix = glob.escape(prefix)

View file

@ -10,6 +10,7 @@ from xonsh.parsers.completion_context import CompletionContext, PythonContext
import xonsh.tools as xt import xonsh.tools as xt
import xonsh.lazyasd as xl import xonsh.lazyasd as xl
from xonsh.built_ins import XSH
from xonsh.completers.tools import ( from xonsh.completers.tools import (
CompleterResult, CompleterResult,
@ -145,7 +146,7 @@ def complete_python(context: CompletionContext) -> CompleterResult:
# this can be a command (i.e. not a subexpression) # this can be a command (i.e. not a subexpression)
first = context.command.args[0].value first = context.command.args[0].value
ctx = context.python.ctx or {} ctx = context.python.ctx or {}
if first in builtins.__xonsh__.commands_cache and first not in ctx: # type: ignore if first in XSH.commands_cache and first not in ctx: # type: ignore
# this is a known command, so it won't be python code # this is a known command, so it won't be python code
return None return None
@ -206,7 +207,7 @@ def _safe_eval(expr, ctx):
a (None, None) tuple. a (None, None) tuple.
""" """
_ctx = None _ctx = None
xonsh_safe_eval = builtins.__xonsh__.execer.eval xonsh_safe_eval = XSH.execer.eval
try: try:
val = xonsh_safe_eval(expr, ctx, ctx, transform=False) val = xonsh_safe_eval(expr, ctx, ctx, transform=False)
_ctx = ctx _ctx = ctx
@ -245,7 +246,7 @@ def attr_complete(prefix, ctx, filter_func):
if _val_ is None and _ctx_ is None: if _val_ is None and _ctx_ is None:
continue continue
a = getattr(val, opt) a = getattr(val, opt)
if builtins.__xonsh__.env["COMPLETIONS_BRACKETS"]: if XSH.env["COMPLETIONS_BRACKETS"]:
if callable(a): if callable(a):
rpl = opt + "(" rpl = opt + "("
elif isinstance(a, (cabc.Sequence, cabc.Mapping)): elif isinstance(a, (cabc.Sequence, cabc.Mapping)):

View file

@ -1,9 +1,9 @@
"""Xonsh completer tools.""" """Xonsh completer tools."""
import builtins
import textwrap import textwrap
import typing as tp import typing as tp
from functools import wraps from functools import wraps
from xonsh.built_ins import XSH
from xonsh.parsers.completion_context import CompletionContext, CommandContext from xonsh.parsers.completion_context import CompletionContext, CommandContext
@ -20,7 +20,7 @@ def get_filter_function():
Return an appropriate filtering function for completions, given the valid Return an appropriate filtering function for completions, given the valid
of $CASE_SENSITIVE_COMPLETIONS of $CASE_SENSITIVE_COMPLETIONS
""" """
csc = builtins.__xonsh__.env.get("CASE_SENSITIVE_COMPLETIONS") csc = XSH.env.get("CASE_SENSITIVE_COMPLETIONS")
if csc: if csc:
return _filter_normal return _filter_normal
else: else:

View file

@ -1,9 +1,10 @@
"""Context management tools for xonsh.""" """Context management tools for xonsh."""
import sys import sys
import textwrap import textwrap
import builtins
from collections.abc import Mapping from collections.abc import Mapping
from xonsh.built_ins import XSH
class Block(object): class Block(object):
"""This is a context manager for obtaining a block of lines without actually """This is a context manager for obtaining a block of lines without actually
@ -28,7 +29,9 @@ class Block(object):
def __enter__(self): def __enter__(self):
if not hasattr(self, "macro_block"): if not hasattr(self, "macro_block"):
raise XonshError(self.__class__.__name__ + " must be entered as a macro!") raise XSH.builtins.XonshError(
self.__class__.__name__ + " must be entered as a macro!"
)
self.lines = self.macro_block.splitlines() self.lines = self.macro_block.splitlines()
self.glbs = self.macro_globals self.glbs = self.macro_globals
if self.macro_locals is not self.macro_globals: if self.macro_locals is not self.macro_globals:
@ -93,7 +96,7 @@ class Functor(Block):
fstr = fstr.format(name=name, sig=sig, body=body, rtn=rtn) fstr = fstr.format(name=name, sig=sig, body=body, rtn=rtn)
glbs = self.glbs glbs = self.glbs
locs = self.locs locs = self.locs
execer = builtins.__xonsh__.execer execer = XSH.execer
execer.exec(fstr, glbs=glbs, locs=locs) execer.exec(fstr, glbs=glbs, locs=locs)
if locs is not None and name in locs: if locs is not None and name in locs:
func = locs[name] func = locs[name]

View file

@ -1,12 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Directory stack and associated utilities for the xonsh shell.""" """Directory stack and associated utilities for the xonsh shell."""
import argparse import argparse
import builtins
import glob import glob
import os import os
import subprocess import subprocess
import typing as tp import typing as tp
from xonsh.built_ins import XSH
from xonsh.events import events from xonsh.events import events
from xonsh.lazyasd import lazyobject from xonsh.lazyasd import lazyobject
from xonsh.platform import ON_WINDOWS from xonsh.platform import ON_WINDOWS
@ -145,7 +145,7 @@ def _get_cwd():
def _change_working_directory(newdir, follow_symlinks=False): def _change_working_directory(newdir, follow_symlinks=False):
env = builtins.__xonsh__.env env = XSH.env
old = env["PWD"] old = env["PWD"]
new = os.path.join(old, newdir) new = os.path.join(old, newdir)
@ -180,10 +180,10 @@ def _try_cdpath(apath):
# a second $ cd xonsh has no effects, to move in the nested xonsh # a second $ cd xonsh has no effects, to move in the nested xonsh
# in bash a full $ cd ./xonsh is needed. # in bash a full $ cd ./xonsh is needed.
# In xonsh a relative folder is always preferred. # In xonsh a relative folder is always preferred.
env = builtins.__xonsh__.env env = XSH.env
cdpaths = env.get("CDPATH") cdpaths = env.get("CDPATH")
for cdp in cdpaths: for cdp in cdpaths:
globber = builtins.__xonsh__.expand_path(os.path.join(cdp, apath)) globber = XSH.expand_path(os.path.join(cdp, apath))
for cdpath_prefixed_path in glob.iglob(globber): for cdpath_prefixed_path in glob.iglob(globber):
return cdpath_prefixed_path return cdpath_prefixed_path
return apath return apath
@ -195,7 +195,7 @@ def cd(args, stdin=None):
If no directory is specified (i.e. if `args` is None) then this If no directory is specified (i.e. if `args` is None) then this
changes to the current user's home directory. changes to the current user's home directory.
""" """
env = builtins.__xonsh__.env env = XSH.env
oldpwd = env.get("OLDPWD", None) oldpwd = env.get("OLDPWD", None)
cwd = env["PWD"] cwd = env["PWD"]
@ -307,7 +307,7 @@ def pushd(args, stdin=None):
except SystemExit: except SystemExit:
return None, None, 1 return None, None, 1
env = builtins.__xonsh__.env env = XSH.env
pwd = env["PWD"] pwd = env["PWD"]
@ -406,7 +406,7 @@ def popd(args, stdin=None):
except SystemExit: except SystemExit:
return None, None, 1 return None, None, 1
env = builtins.__xonsh__.env env = XSH.env
if env.get("PUSHD_MINUS"): if env.get("PUSHD_MINUS"):
BACKWARD = "-" BACKWARD = "-"
@ -454,7 +454,7 @@ def popd(args, stdin=None):
if new_pwd is not None: if new_pwd is not None:
e = None e = None
if args.cd: if args.cd:
env = builtins.__xonsh__.env env = XSH.env
pwd = env["PWD"] pwd = env["PWD"]
_change_working_directory(new_pwd) _change_working_directory(new_pwd)
@ -515,7 +515,7 @@ def dirs(args, stdin=None):
except SystemExit: except SystemExit:
return None, None return None, None
env = builtins.__xonsh__.env env = XSH.env
dirstack = [os.path.expanduser(env["PWD"])] + DIRSTACK dirstack = [os.path.expanduser(env["PWD"])] + DIRSTACK
if env.get("PUSHD_MINUS"): if env.get("PUSHD_MINUS"):

View file

@ -1,6 +1,6 @@
"""A dumb shell for when $TERM == 'dumb', which usually happens in emacs.""" """A dumb shell for when $TERM == 'dumb', which usually happens in emacs."""
import builtins
from xonsh.built_ins import XSH
from xonsh.readline_shell import ReadlineShell from xonsh.readline_shell import ReadlineShell
@ -8,5 +8,5 @@ class DumbShell(ReadlineShell):
"""A dumb shell for when $TERM == 'dumb', which usually happens in emacs.""" """A dumb shell for when $TERM == 'dumb', which usually happens in emacs."""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
builtins.__xonsh__.env["XONSH_COLOR_STYLE"] = "emacs" XSH.env["XONSH_COLOR_STYLE"] = "emacs"
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)

View file

@ -7,7 +7,6 @@ import pprint
import textwrap import textwrap
import locale import locale
import glob import glob
import builtins
import warnings import warnings
import contextlib import contextlib
import collections.abc as cabc import collections.abc as cabc
@ -29,7 +28,7 @@ from xonsh.platform import (
ON_CYGWIN, ON_CYGWIN,
os_environ, os_environ,
) )
from xonsh.built_ins import XSH
from xonsh.tools import ( from xonsh.tools import (
always_true, always_true,
always_false, always_false,
@ -193,12 +192,8 @@ def to_debug(x):
execer's debug level. execer's debug level.
""" """
val = to_bool_or_int(x) val = to_bool_or_int(x)
if ( if XSH.execer is not None:
hasattr(builtins, "__xonsh__") XSH.execer.debug_level = val
and hasattr(builtins.__xonsh__, "execer")
and builtins.__xonsh__.execer is not None
):
builtins.__xonsh__.execer.debug_level = val
return val return val
@ -427,7 +422,7 @@ class LsColors(cabc.MutableMapping):
@property @property
def style_name(self): def style_name(self):
"""Current XONSH_COLOR_STYLE value""" """Current XONSH_COLOR_STYLE value"""
env = getattr(builtins.__xonsh__, "env", {}) env = getattr(XSH, "env", {})
env_style_name = env.get("XONSH_COLOR_STYLE", "default") env_style_name = env.get("XONSH_COLOR_STYLE", "default")
if self._style_name is None or self._style_name != env_style_name: if self._style_name is None or self._style_name != env_style_name:
self._style_name = env_style_name self._style_name = env_style_name
@ -479,8 +474,8 @@ class LsColors(cabc.MutableMapping):
if filename is not None: if filename is not None:
cmd.append(filename) cmd.append(filename)
# get env # get env
if hasattr(builtins, "__xonsh__") and hasattr(builtins.__xonsh__, "env"): if XSH.env:
denv = builtins.__xonsh__.env.detype() denv = XSH.env.detype()
else: else:
denv = None denv = None
# run dircolors # run dircolors
@ -519,7 +514,7 @@ def ensure_ls_colors_in_env(spec=None, **kwargs):
environment. This fires exactly once upon the first time the environment. This fires exactly once upon the first time the
ls command is called. ls command is called.
""" """
env = builtins.__xonsh__.env env = XSH.env
if "LS_COLORS" not in env._d: if "LS_COLORS" not in env._d:
# this adds it to the env too # this adds it to the env too
default_lscolors(env) default_lscolors(env)
@ -2148,7 +2143,7 @@ def _yield_executables(directory, name):
def locate_binary(name): def locate_binary(name):
"""Locates an executable on the file system.""" """Locates an executable on the file system."""
return builtins.__xonsh__.commands_cache.locate_binary(name) return XSH.commands_cache.locate_binary(name)
def xonshrc_context( def xonshrc_context(

View file

@ -1,17 +1,17 @@
""" """
Events for xonsh. Events for xonsh.
In all likelihood, you want builtins.events In all likelihood, you want xonsh.built_ins.XSH.events
The best way to "declare" an event is something like:: The best way to "declare" an event is something like::
events.doc('on_spam', "Comes with eggs") events.doc('on_spam', "Comes with eggs")
""" """
import abc import abc
import builtins
import collections.abc import collections.abc
import inspect import inspect
from xonsh.built_ins import XSH
from xonsh.tools import print_exception from xonsh.tools import print_exception
@ -22,8 +22,8 @@ def has_kwargs(func):
def debug_level(): def debug_level():
if hasattr(builtins, "__xonsh__") and hasattr(builtins.__xonsh__, "env"): if XSH.env:
return builtins.__xonsh__.env.get("XONSH_DEBUG") return XSH.env.get("XONSH_DEBUG")
# FIXME: Under py.test, return 1(?) # FIXME: Under py.test, return 1(?)
else: else:
return 0 # Optimize for speed, not guaranteed correctness return 0 # Optimize for speed, not guaranteed correctness

View file

@ -16,7 +16,7 @@ from xonsh.tools import (
balanced_parens, balanced_parens,
starting_whitespace, starting_whitespace,
) )
from xonsh.built_ins import load_builtins, unload_builtins from xonsh.built_ins import XSH
class Execer(object): class Execer(object):
@ -43,7 +43,7 @@ class Execer(object):
unload : bool, optional unload : bool, optional
Whether or not to unload xonsh builtins upon deletion. Whether or not to unload xonsh builtins upon deletion.
xonsh_ctx : dict or None, optional xonsh_ctx : dict or None, optional
Xonsh xontext to load as builtins.__xonsh__.ctx Xonsh xontext to load as xonsh.built_ins.XSH.ctx
scriptcache : bool, optional scriptcache : bool, optional
Whether or not to use a precompiled bytecode cache when execing Whether or not to use a precompiled bytecode cache when execing
code, default: True. code, default: True.
@ -60,11 +60,11 @@ class Execer(object):
self.scriptcache = scriptcache self.scriptcache = scriptcache
self.cacheall = cacheall self.cacheall = cacheall
self.ctxtransformer = CtxAwareTransformer(self.parser) self.ctxtransformer = CtxAwareTransformer(self.parser)
load_builtins(execer=self, ctx=xonsh_ctx) XSH.load(execer=self, ctx=xonsh_ctx)
def __del__(self): def __del__(self):
if self.unload: if self.unload:
unload_builtins() XSH.unload()
def parse(self, input, ctx, mode="exec", filename=None, transform=True): def parse(self, input, ctx, mode="exec", filename=None, transform=True):
"""Parses xonsh code in a context-aware fashion. For context-free """Parses xonsh code in a context-aware fashion. For context-free

View file

@ -6,12 +6,12 @@ import json
import shlex import shlex
import sys import sys
import tempfile import tempfile
import builtins
import subprocess import subprocess
import warnings import warnings
import functools import functools
import collections.abc as cabc import collections.abc as cabc
from xonsh.built_ins import XSH
from xonsh.lazyasd import lazyobject from xonsh.lazyasd import lazyobject
from xonsh.tools import to_bool, ensure_string from xonsh.tools import to_bool, ensure_string
from xonsh.platform import ON_WINDOWS, ON_CYGWIN, ON_MSYS from xonsh.platform import ON_WINDOWS, ON_CYGWIN, ON_MSYS
@ -275,8 +275,8 @@ def foreign_shell_data(
tmpfile.write(command.encode("utf8")) tmpfile.write(command.encode("utf8"))
tmpfile.close() tmpfile.close()
cmd.append(tmpfile.name) cmd.append(tmpfile.name)
if currenv is None and hasattr(builtins.__xonsh__, "env"): if currenv is None and XSH.env:
currenv = builtins.__xonsh__.env.detype() currenv = XSH.env.detype()
elif currenv is not None: elif currenv is not None:
currenv = dict(currenv) currenv = dict(currenv)
try: try:
@ -472,7 +472,7 @@ class ForeignShellBaseAlias(object):
args, streaming = self._is_streaming(args) args, streaming = self._is_streaming(args)
input = self.INPUT.format(args=" ".join(args), **self._input_kwargs()) input = self.INPUT.format(args=" ".join(args), **self._input_kwargs())
cmd = [self.shell] + list(self.extra_args) + ["-c", input] cmd = [self.shell] + list(self.extra_args) + ["-c", input]
env = builtins.__xonsh__.env env = XSH.env
denv = env.detype() denv = env.detype()
if streaming: if streaming:
subprocess.check_call(cmd, env=denv) subprocess.check_call(cmd, env=denv)
@ -699,15 +699,15 @@ def load_foreign_aliases(shells):
A dictionary of the merged aliases. A dictionary of the merged aliases.
""" """
aliases = {} aliases = {}
xonsh_aliases = builtins.aliases xonsh_aliases = XSH.aliases
for shell in shells: for shell in shells:
shell = ensure_shell(shell) shell = ensure_shell(shell)
_, shaliases = foreign_shell_data(**shell) _, shaliases = foreign_shell_data(**shell)
if not builtins.__xonsh__.env.get("FOREIGN_ALIASES_OVERRIDE"): if not XSH.env.get("FOREIGN_ALIASES_OVERRIDE"):
shaliases = {} if shaliases is None else shaliases shaliases = {} if shaliases is None else shaliases
for alias in set(shaliases) & set(xonsh_aliases): for alias in set(shaliases) & set(xonsh_aliases):
del shaliases[alias] del shaliases[alias]
if builtins.__xonsh__.env.get("XONSH_DEBUG") > 1: if XSH.env.get("XONSH_DEBUG") > 1:
print( print(
"aliases: ignoring alias {!r} of shell {!r} " "aliases: ignoring alias {!r} of shell {!r} "
"which tries to override xonsh alias." "which tries to override xonsh alias."

View file

@ -3,11 +3,12 @@
import os import os
import sys import sys
import time import time
import builtins
import collections import collections
import threading import threading
import collections.abc as cabc import collections.abc as cabc
from xonsh.built_ins import XSH
try: try:
import ujson as json import ujson as json
except ImportError: except ImportError:
@ -90,7 +91,7 @@ def _xhj_gc_bytes_to_rmfiles(hsize, files):
def _xhj_get_data_dir(): def _xhj_get_data_dir():
dir = xt.expanduser_abs_path( dir = xt.expanduser_abs_path(
os.path.join(builtins.__xonsh__.env.get("XONSH_DATA_DIR"), "history_json") os.path.join(XSH.env.get("XONSH_DATA_DIR"), "history_json")
) )
if not os.path.exists(dir): if not os.path.exists(dir):
os.makedirs(dir) os.makedirs(dir)
@ -103,9 +104,7 @@ def _xhj_get_history_files(sort=True, newest_first=False):
""" """
data_dirs = [ data_dirs = [
_xhj_get_data_dir(), _xhj_get_data_dir(),
builtins.__xonsh__.env.get( XSH.env.get("XONSH_DATA_DIR"), # backwards compatibility, remove in the future
"XONSH_DATA_DIR"
), # backwards compatibility, remove in the future
] ]
files = [] files = []
@ -118,14 +117,14 @@ def _xhj_get_history_files(sort=True, newest_first=False):
if f.startswith("xonsh-") and f.endswith(".json") if f.startswith("xonsh-") and f.endswith(".json")
] ]
except OSError: except OSError:
if builtins.__xonsh__.env.get("XONSH_DEBUG"): if XSH.env.get("XONSH_DEBUG"):
xt.print_exception( xt.print_exception(
f"Could not collect xonsh history json files from {data_dir}" f"Could not collect xonsh history json files from {data_dir}"
) )
if sort: if sort:
files.sort(key=lambda x: os.path.getmtime(x), reverse=newest_first) files.sort(key=lambda x: os.path.getmtime(x), reverse=newest_first)
custom_history_file = builtins.__xonsh__.env.get("XONSH_HISTORY_FILE", None) custom_history_file = XSH.env.get("XONSH_HISTORY_FILE", None)
if custom_history_file: if custom_history_file:
custom_history_file = xt.expanduser_abs_path(custom_history_file) custom_history_file = xt.expanduser_abs_path(custom_history_file)
if custom_history_file not in files: if custom_history_file not in files:
@ -157,7 +156,7 @@ class JsonHistoryGC(threading.Thread):
def run(self): def run(self):
while self.wait_for_shell: while self.wait_for_shell:
time.sleep(0.01) time.sleep(0.01)
env = builtins.__xonsh__.env # pylint: disable=no-member env = XSH.env # pylint: disable=no-member
xonsh_debug = env.get("XONSH_DEBUG", 0) xonsh_debug = env.get("XONSH_DEBUG", 0)
if self.size is None: if self.size is None:
hsize, units = env.get("XONSH_HISTORY_SIZE") hsize, units = env.get("XONSH_HISTORY_SIZE")
@ -169,7 +168,7 @@ class JsonHistoryGC(threading.Thread):
raise ValueError("Units type {0!r} not understood".format(units)) raise ValueError("Units type {0!r} not understood".format(units))
size_over, rm_files = rmfiles_fn(hsize, files) size_over, rm_files = rmfiles_fn(hsize, files)
hist = getattr(builtins.__xonsh__, "history", None) hist = getattr(XSH, "history", None)
if hist is not None: # remember last gc pass history size if hist is not None: # remember last gc pass history size
hist.hist_size = size_over + hsize hist.hist_size = size_over + hsize
hist.hist_units = units hist.hist_units = units
@ -201,7 +200,7 @@ class JsonHistoryGC(threading.Thread):
This is sorted by the last closed time. Returns a list of This is sorted by the last closed time. Returns a list of
(file_size, timestamp, number of cmds, file name) tuples. (file_size, timestamp, number of cmds, file name) tuples.
""" """
env = getattr(getattr(builtins, "__xonsh__", None), "env", None) env = XSH.env
if env is None: if env is None:
return [] return []
@ -283,7 +282,7 @@ class JsonHistoryFlusher(threading.Thread):
def dump(self): def dump(self):
"""Write the cached history to external storage.""" """Write the cached history to external storage."""
opts = builtins.__xonsh__.env.get("HISTCONTROL", "") opts = XSH.env.get("HISTCONTROL", "")
last_inp = None last_inp = None
cmds = [] cmds = []
for cmd in self.buffer: for cmd in self.buffer:
@ -305,9 +304,11 @@ class JsonHistoryFlusher(threading.Thread):
load_hist_len = len(hist["cmds"]) load_hist_len = len(hist["cmds"])
hist["cmds"].extend(cmds) hist["cmds"].extend(cmds)
if self.at_exit: if self.at_exit:
hist["ts"][1] = time.time() # apply end time # todo: check why this is here.
if "ts" in hist:
hist["ts"][1] = time.time() # apply end time
hist["locked"] = False hist["locked"] = False
if not builtins.__xonsh__.env.get("XONSH_STORE_STDOUT", False): if not XSH.env.get("XONSH_STORE_STDOUT", False):
[cmd.pop("out") for cmd in hist["cmds"][load_hist_len:] if "out" in cmd] [cmd.pop("out") for cmd in hist["cmds"][load_hist_len:] if "out" in cmd]
with open(self.filename, "w", newline="\n") as f: with open(self.filename, "w", newline="\n") as f:
xlj.ljdump(hist, f, sort_keys=True) xlj.ljdump(hist, f, sort_keys=True)
@ -445,7 +446,7 @@ class JsonHistory(History):
self.save_cwd = ( self.save_cwd = (
save_cwd save_cwd
if save_cwd is not None if save_cwd is not None
else builtins.__xonsh__.env.get("XONSH_HISTORY_SAVE_CWD", True) else XSH.env.get("XONSH_HISTORY_SAVE_CWD", True)
) )
def __len__(self): def __len__(self):
@ -472,7 +473,7 @@ class JsonHistory(History):
if not self.remember_history: if not self.remember_history:
return return
opts = builtins.__xonsh__.env.get("HISTCONTROL", "") opts = XSH.env.get("HISTCONTROL", "")
skipped_by_ignore_space = "ignorespace" in opts and cmd.get("spc") skipped_by_ignore_space = "ignorespace" in opts and cmd.get("spc")
if skipped_by_ignore_space: if skipped_by_ignore_space:
return None return None
@ -553,7 +554,7 @@ class JsonHistory(History):
commands = json_file.load()["cmds"] commands = json_file.load()["cmds"]
except (json.decoder.JSONDecodeError, ValueError): except (json.decoder.JSONDecodeError, ValueError):
# file is corrupted somehow # file is corrupted somehow
if builtins.__xonsh__.env.get("XONSH_DEBUG") > 0: if XSH.env.get("XONSH_DEBUG") > 0:
msg = "xonsh history file {0!r} is not valid JSON" msg = "xonsh history file {0!r} is not valid JSON"
print(msg.format(f), file=sys.stderr) print(msg.format(f), file=sys.stderr)
continue continue
@ -572,7 +573,7 @@ class JsonHistory(History):
data["length"] = len(self) data["length"] = len(self)
data["buffersize"] = self.buffersize data["buffersize"] = self.buffersize
data["bufferlength"] = len(self.buffer) data["bufferlength"] = len(self.buffer)
envs = builtins.__xonsh__.env envs = XSH.env
data["gc options"] = envs.get("XONSH_HISTORY_SIZE") data["gc options"] = envs.get("XONSH_HISTORY_SIZE")
data["gc_last_size"] = f"{(self.hist_size, self.hist_units)}" data["gc_last_size"] = f"{(self.hist_size, self.hist_units)}"
return data return data

View file

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Main entry points of the xonsh history.""" """Main entry points of the xonsh history."""
import argparse import argparse
import builtins
import datetime import datetime
import functools import functools
import json import json
@ -9,6 +8,7 @@ import os
import sys import sys
import threading import threading
from xonsh.built_ins import XSH
from xonsh.history.base import History from xonsh.history.base import History
from xonsh.history.dummy import DummyHistory from xonsh.history.dummy import DummyHistory
from xonsh.history.json import JsonHistory from xonsh.history.json import JsonHistory
@ -22,7 +22,7 @@ HISTORY_BACKENDS = {"dummy": DummyHistory, "json": JsonHistory, "sqlite": Sqlite
def construct_history(**kwargs): def construct_history(**kwargs):
"""Construct the history backend object.""" """Construct the history backend object."""
env = builtins.__xonsh__.env env = XSH.env
backend = env.get("XONSH_HISTORY_BACKEND") backend = env.get("XONSH_HISTORY_BACKEND")
if isinstance(backend, str) and backend in HISTORY_BACKENDS: if isinstance(backend, str) and backend in HISTORY_BACKENDS:
kls_history = HISTORY_BACKENDS[backend] kls_history = HISTORY_BACKENDS[backend]
@ -42,14 +42,14 @@ def construct_history(**kwargs):
def _xh_session_parser(hist=None, newest_first=False, **kwargs): def _xh_session_parser(hist=None, newest_first=False, **kwargs):
"""Returns history items of current session.""" """Returns history items of current session."""
if hist is None: if hist is None:
hist = builtins.__xonsh__.history hist = XSH.history
return hist.items() return hist.items()
def _xh_all_parser(hist=None, newest_first=False, **kwargs): def _xh_all_parser(hist=None, newest_first=False, **kwargs):
"""Returns all history items.""" """Returns all history items."""
if hist is None: if hist is None:
hist = builtins.__xonsh__.history hist = XSH.history
return hist.all_items(newest_first=newest_first) return hist.all_items(newest_first=newest_first)
@ -356,7 +356,7 @@ def _xh_create_parser():
help="makes the gc non-blocking, and thus return sooner", help="makes the gc non-blocking, and thus return sooner",
) )
hist = builtins.__xonsh__.history hist = XSH.history
if isinstance(hist, JsonHistory): if isinstance(hist, JsonHistory):
# add actions belong only to JsonHistory # add actions belong only to JsonHistory
diff = subp.add_parser("diff", help="diff two xonsh history files") diff = subp.add_parser("diff", help="diff two xonsh history files")
@ -408,7 +408,7 @@ def history_main(
args=None, stdin=None, stdout=None, stderr=None, spec=None, stack=None args=None, stdin=None, stdout=None, stderr=None, spec=None, stack=None
): ):
"""This is the history command entry point.""" """This is the history command entry point."""
hist = builtins.__xonsh__.history hist = XSH.history
ns = _xh_parse_args(args) ns = _xh_parse_args(args)
if not ns or not ns.action: if not ns or not ns.action:
return return

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Implements the xonsh history backend via sqlite3.""" """Implements the xonsh history backend via sqlite3."""
import builtins
import collections import collections
import json import json
import os import os
@ -9,6 +8,7 @@ import sys
import threading import threading
import time import time
from xonsh.built_ins import XSH
from xonsh.history.base import History from xonsh.history.base import History
import xonsh.tools as xt import xonsh.tools as xt
@ -18,7 +18,7 @@ XH_SQLITE_CREATED_SQL_TBL = "CREATED_SQL_TABLE"
def _xh_sqlite_get_file_name(): def _xh_sqlite_get_file_name():
envs = builtins.__xonsh__.env envs = XSH.env
file_name = envs.get("XONSH_HISTORY_SQLITE_FILE") file_name = envs.get("XONSH_HISTORY_SQLITE_FILE")
if not file_name: if not file_name:
data_dir = envs.get("XONSH_DATA_DIR") data_dir = envs.get("XONSH_DATA_DIR")
@ -235,7 +235,7 @@ class SqliteHistoryGC(threading.Thread):
if self.size is not None: if self.size is not None:
hsize, units = xt.to_history_tuple(self.size) hsize, units = xt.to_history_tuple(self.size)
else: else:
envs = builtins.__xonsh__.env envs = XSH.env
hsize, units = envs.get("XONSH_HISTORY_SIZE") hsize, units = envs.get("XONSH_HISTORY_SIZE")
if units != "commands": if units != "commands":
print( print(
@ -267,7 +267,7 @@ class SqliteHistory(History):
self.save_cwd = ( self.save_cwd = (
save_cwd save_cwd
if save_cwd is not None if save_cwd is not None
else builtins.__xonsh__.env.get("XONSH_HISTORY_SAVE_CWD", True) else XSH.env.get("XONSH_HISTORY_SAVE_CWD", True)
) )
if not os.path.exists(self.filename): if not os.path.exists(self.filename):
@ -285,7 +285,7 @@ class SqliteHistory(History):
def append(self, cmd): def append(self, cmd):
if not self.remember_history: if not self.remember_history:
return return
envs = builtins.__xonsh__.env envs = XSH.env
inp = cmd["inp"].rstrip() inp = cmd["inp"].rstrip()
self.inps.append(inp) self.inps.append(inp)
self.outs.append(cmd.get("out")) self.outs.append(cmd.get("out"))
@ -342,7 +342,7 @@ class SqliteHistory(History):
sessionid=self.sessionid, filename=self.filename sessionid=self.sessionid, filename=self.filename
) )
data["all items"] = xh_sqlite_get_count(filename=self.filename) data["all items"] = xh_sqlite_get_count(filename=self.filename)
envs = builtins.__xonsh__.env envs = XSH.env
data["gc options"] = envs.get("XONSH_HISTORY_SIZE") data["gc options"] = envs.get("XONSH_HISTORY_SIZE")
return data return data

View file

@ -3,7 +3,6 @@
This module registers the hooks it defines when it is imported. This module registers the hooks it defines when it is imported.
""" """
import builtins
import contextlib import contextlib
import importlib import importlib
import os import os
@ -13,6 +12,7 @@ import types
from importlib.abc import MetaPathFinder, SourceLoader, Loader from importlib.abc import MetaPathFinder, SourceLoader, Loader
from importlib.machinery import ModuleSpec from importlib.machinery import ModuleSpec
from xonsh.built_ins import XSH
from xonsh.events import events from xonsh.events import events
from xonsh.execer import Execer from xonsh.execer import Execer
from xonsh.lazyasd import lazyobject from xonsh.lazyasd import lazyobject
@ -57,12 +57,8 @@ class XonshImportHook(MetaPathFinder, SourceLoader):
@property @property
def execer(self): def execer(self):
if ( if XSH.execer is not None:
hasattr(builtins, "__xonsh__") execer = XSH.execer
and hasattr(builtins.__xonsh__, "execer")
and builtins.__xonsh__.execer is not None
):
execer = builtins.__xonsh__.execer
if self._execer is not None: if self._execer is not None:
self._execer = None self._execer = None
elif self._execer is None: elif self._execer is None:

View file

@ -5,18 +5,18 @@ import sys
import time import time
import ctypes import ctypes
import signal import signal
import builtins
import argparse import argparse
import subprocess import subprocess
import collections import collections
import typing as tp import typing as tp
from xonsh.built_ins import XSH
from xonsh.lazyasd import LazyObject from xonsh.lazyasd import LazyObject
from xonsh.platform import FD_STDERR, ON_DARWIN, ON_WINDOWS, ON_CYGWIN, ON_MSYS, LIBC from xonsh.platform import FD_STDERR, ON_DARWIN, ON_WINDOWS, ON_CYGWIN, ON_MSYS, LIBC
from xonsh.tools import unthreadable from xonsh.tools import unthreadable
# there is not much cost initing deque
tasks = LazyObject(collections.deque, globals(), "tasks") tasks: tp.Deque[int] = collections.deque()
# Track time stamp of last exit command, so that two consecutive attempts to # Track time stamp of last exit command, so that two consecutive attempts to
# exit can kill all jobs and exit. # exit can kill all jobs and exit.
_last_exit_time: tp.Optional[float] = None _last_exit_time: tp.Optional[float] = None
@ -259,7 +259,7 @@ def get_next_task():
def get_task(tid): def get_task(tid):
return builtins.__xonsh__.all_jobs[tid] return XSH.all_jobs[tid]
def _clear_dead_jobs(): def _clear_dead_jobs():
@ -270,13 +270,13 @@ def _clear_dead_jobs():
to_remove.add(tid) to_remove.add(tid)
for job in to_remove: for job in to_remove:
tasks.remove(job) tasks.remove(job)
del builtins.__xonsh__.all_jobs[job] del XSH.all_jobs[job]
def print_one_job(num, outfile=sys.stdout): def print_one_job(num, outfile=sys.stdout):
"""Print a line describing job number ``num``.""" """Print a line describing job number ``num``."""
try: try:
job = builtins.__xonsh__.all_jobs[num] job = XSH.all_jobs[num]
except KeyError: except KeyError:
return return
pos = "+" if tasks[0] == num else "-" if tasks[1] == num else " " pos = "+" if tasks[0] == num else "-" if tasks[1] == num else " "
@ -292,7 +292,7 @@ def get_next_job_number():
"""Get the lowest available unique job number (for the next job created).""" """Get the lowest available unique job number (for the next job created)."""
_clear_dead_jobs() _clear_dead_jobs()
i = 1 i = 1
while i in builtins.__xonsh__.all_jobs: while i in XSH.all_jobs:
i += 1 i += 1
return i return i
@ -303,8 +303,8 @@ def add_job(info):
info["started"] = time.time() info["started"] = time.time()
info["status"] = "running" info["status"] = "running"
tasks.appendleft(num) tasks.appendleft(num)
builtins.__xonsh__.all_jobs[num] = info XSH.all_jobs[num] = info
if info["bg"] and builtins.__xonsh__.env.get("XONSH_INTERACTIVE"): if info["bg"] and XSH.env.get("XONSH_INTERACTIVE"):
print_one_job(num) print_one_job(num)
@ -317,12 +317,12 @@ def clean_jobs():
warning if any exist, and return False. Otherwise, return True. warning if any exist, and return False. Otherwise, return True.
""" """
jobs_clean = True jobs_clean = True
if builtins.__xonsh__.env["XONSH_INTERACTIVE"]: if XSH.env["XONSH_INTERACTIVE"]:
_clear_dead_jobs() _clear_dead_jobs()
if builtins.__xonsh__.all_jobs: if XSH.all_jobs:
global _last_exit_time global _last_exit_time
hist = builtins.__xonsh__.history hist = XSH.history
if hist is not None and len(hist.tss) > 0: if hist is not None and len(hist.tss) > 0:
last_cmd_start = hist.tss[-1][0] last_cmd_start = hist.tss[-1][0]
else: else:
@ -335,12 +335,12 @@ def clean_jobs():
# unfinished jobs in this case. # unfinished jobs in this case.
kill_all_jobs() kill_all_jobs()
else: else:
if len(builtins.__xonsh__.all_jobs) > 1: if len(XSH.all_jobs) > 1:
msg = "there are unfinished jobs" msg = "there are unfinished jobs"
else: else:
msg = "there is an unfinished job" msg = "there is an unfinished job"
if builtins.__xonsh__.env["SHELL_TYPE"] != "prompt_toolkit": if XSH.env["SHELL_TYPE"] != "prompt_toolkit":
# The Ctrl+D binding for prompt_toolkit already inserts a # The Ctrl+D binding for prompt_toolkit already inserts a
# newline # newline
print() print()
@ -365,7 +365,7 @@ def kill_all_jobs():
Send SIGKILL to all child processes (called when exiting xonsh). Send SIGKILL to all child processes (called when exiting xonsh).
""" """
_clear_dead_jobs() _clear_dead_jobs()
for job in builtins.__xonsh__.all_jobs.values(): for job in XSH.all_jobs.values():
_kill(job) _kill(job)
@ -402,7 +402,7 @@ def resume_job(args, wording):
except (ValueError, IndexError): except (ValueError, IndexError):
return "", "Invalid job: {}\n".format(args[0]) return "", "Invalid job: {}\n".format(args[0])
if tid not in builtins.__xonsh__.all_jobs: if tid not in XSH.all_jobs:
return "", "Invalid job: {}\n".format(args[0]) return "", "Invalid job: {}\n".format(args[0])
else: else:
return "", "{} expects 0 or 1 arguments, not {}\n".format(wording, len(args)) return "", "{} expects 0 or 1 arguments, not {}\n".format(wording, len(args))
@ -414,7 +414,7 @@ def resume_job(args, wording):
job = get_task(tid) job = get_task(tid)
job["bg"] = False job["bg"] = False
job["status"] = "running" job["status"] = "running"
if builtins.__xonsh__.env.get("XONSH_INTERACTIVE"): if XSH.env.get("XONSH_INTERACTIVE"):
print_one_job(tid) print_one_job(tid)
pipeline = job["pipeline"] pipeline = job["pipeline"]
pipeline.resume(job) pipeline.resume(job)
@ -492,7 +492,7 @@ def disown(args, stdin=None):
except KeyError: except KeyError:
return "", f"'{tid}' is not a valid job ID" return "", f"'{tid}' is not a valid job ID"
auto_cont = builtins.__xonsh__.env.get("AUTO_CONTINUE", False) auto_cont = XSH.env.get("AUTO_CONTINUE", False)
if auto_cont or pargs.force_auto_continue: if auto_cont or pargs.force_auto_continue:
_continue(current_task) _continue(current_task)
elif current_task["status"] == "stopped": elif current_task["status"] == "stopped":
@ -504,7 +504,7 @@ def disown(args, stdin=None):
# Stop tracking this task # Stop tracking this task
tasks.remove(tid) tasks.remove(tid)
del builtins.__xonsh__.all_jobs[tid] del XSH.all_jobs[tid]
messages.append(f"Removed job {tid} ({current_task['status']})") messages.append(f"Removed job {tid} ({current_task['status']})")
if messages: if messages:

View file

@ -7,7 +7,6 @@ import uuid
import errno import errno
import hashlib import hashlib
import datetime import datetime
import builtins
import threading import threading
from pprint import pformat from pprint import pformat
from argparse import ArgumentParser from argparse import ArgumentParser
@ -18,6 +17,7 @@ from zmq.eventloop import ioloop, zmqstream
from zmq.error import ZMQError from zmq.error import ZMQError
from xonsh import __version__ as version from xonsh import __version__ as version
from xonsh.built_ins import XSH
from xonsh.main import setup from xonsh.main import setup
from xonsh.completer import Completer from xonsh.completer import Completer
from xonsh.commands_cache import predict_true from xonsh.commands_cache import predict_true
@ -362,8 +362,8 @@ class XonshKernel:
"payload": [], "payload": [],
"user_expressions": {}, "user_expressions": {},
} }
shell = builtins.__xonsh__.shell shell = XSH.shell
hist = builtins.__xonsh__.history hist = XSH.history
try: try:
shell.default(code, self, parent_header) shell.default(code, self, parent_header)
interrupted = False interrupted = False
@ -420,7 +420,7 @@ class XonshKernel:
def do_complete(self, code: str, pos: int): def do_complete(self, code: str, pos: int):
"""Get completions.""" """Get completions."""
shell = builtins.__xonsh__.shell # type: ignore shell = XSH.shell # type: ignore
line_start = code.rfind("\n", 0, pos) + 1 line_start = code.rfind("\n", 0, pos) + 1
line_stop = code.find("\n", pos) line_stop = code.find("\n", pos)
if line_stop == -1: if line_stop == -1:
@ -429,7 +429,7 @@ class XonshKernel:
line_stop += 1 line_stop += 1
line = code[line_start:line_stop] line = code[line_start:line_stop]
endidx = pos - line_start endidx = pos - line_start
line_ex: str = builtins.aliases.expand_alias(line, endidx) # type: ignore line_ex: str = XSH.aliases.expand_alias(line, endidx) # type: ignore
begidx = line[:endidx].rfind(" ") + 1 if line[:endidx].rfind(" ") >= 0 else 0 begidx = line[:endidx].rfind(" ") + 1 if line[:endidx].rfind(" ") >= 0 else 0
prefix = line[begidx:endidx] prefix = line[begidx:endidx]
@ -492,11 +492,11 @@ if __name__ == "__main__":
xontribs=["coreutils"], xontribs=["coreutils"],
threadable_predictors={"git": predict_true, "man": predict_true}, threadable_predictors={"git": predict_true, "man": predict_true},
) )
if builtins.__xonsh__.commands_cache.is_only_functional_alias("cat"): # type:ignore if XSH.commands_cache.is_only_functional_alias("cat"): # type:ignore
# this is needed if the underlying system doesn't have cat # this is needed if the underlying system doesn't have cat
# we supply our own, because we can # we supply our own, because we can
builtins.aliases["cat"] = "xonsh-cat" # type:ignore XSH.aliases["cat"] = "xonsh-cat" # type:ignore
builtins.__xonsh__.env["PAGER"] = "xonsh-cat" # type:ignore XSH.env["PAGER"] = "xonsh-cat" # type:ignore
shell = builtins.__xonsh__.shell # type:ignore shell = XSH.shell # type:ignore
kernel = shell.kernel = XonshKernel() kernel = shell.kernel = XonshKernel()
kernel.start() kernel.start()

View file

@ -1,9 +1,9 @@
"""An interactive shell for the Jupyter kernel.""" """An interactive shell for the Jupyter kernel."""
import io import io
import sys import sys
import builtins
from xonsh.base_shell import BaseShell from xonsh.base_shell import BaseShell
from xonsh.built_ins import XSH
class StdJupyterRedirectBuf(io.RawIOBase): class StdJupyterRedirectBuf(io.RawIOBase):
@ -61,13 +61,13 @@ class StdJupyterRedirect(io.TextIOBase):
@property @property
def encoding(self): def encoding(self):
"""The encoding of the stream""" """The encoding of the stream"""
env = builtins.__xonsh__.env env = XSH.env
return getattr(self.std, "encoding", env.get("XONSH_ENCODING")) return getattr(self.std, "encoding", env.get("XONSH_ENCODING"))
@property @property
def errors(self): def errors(self):
"""The encoding errors of the stream""" """The encoding errors of the stream"""
env = builtins.__xonsh__.env env = XSH.env
return getattr(self.std, "errors", env.get("XONSH_ENCODING_ERRORS")) return getattr(self.std, "errors", env.get("XONSH_ENCODING_ERRORS"))
@property @property

View file

@ -25,7 +25,7 @@ from xonsh.lazyimps import pygments, pyghooks
from xonsh.imphooks import install_import_hooks from xonsh.imphooks import install_import_hooks
from xonsh.events import events from xonsh.events import events
from xonsh.environ import xonshrc_context, make_args_env from xonsh.environ import xonshrc_context, make_args_env
from xonsh.built_ins import XonshSession, load_builtins from xonsh.built_ins import XSH
import xonsh.procs.pipelines as xpp import xonsh.procs.pipelines as xpp
@ -251,7 +251,7 @@ def _pprint_displayhook(value):
if isinstance(value, xpp.HiddenCommandPipeline): if isinstance(value, xpp.HiddenCommandPipeline):
builtins._ = value builtins._ = value
return return
env = builtins.__xonsh__.env env = XSH.env
printed_val = None printed_val = None
if env.get("PRETTY_PRINT_RESULTS"): if env.get("PRETTY_PRINT_RESULTS"):
printed_val = pretty(value) printed_val = pretty(value)
@ -294,7 +294,7 @@ def start_services(shell_kwargs, args, pre_env=None):
events.on_timingprobe.fire(name="post_execer_init") events.on_timingprobe.fire(name="post_execer_init")
# load rc files # load rc files
login = shell_kwargs.get("login", True) login = shell_kwargs.get("login", True)
env = builtins.__xonsh__.env env = XSH.env
for k, v in pre_env.items(): for k, v in pre_env.items():
env[k] = v env[k] = v
@ -325,7 +325,7 @@ def start_services(shell_kwargs, args, pre_env=None):
) )
events.on_post_rc.fire() events.on_post_rc.fire()
# create shell # create shell
builtins.__xonsh__.shell = Shell(execer=execer, **shell_kwargs) XSH.shell = Shell(execer=execer, **shell_kwargs)
ctx["__name__"] = "__main__" ctx["__name__"] = "__main__"
return env return env
@ -334,7 +334,6 @@ def premain(argv=None):
"""Setup for main xonsh entry point. Returns parsed arguments.""" """Setup for main xonsh entry point. Returns parsed arguments."""
if argv is None: if argv is None:
argv = sys.argv[1:] argv = sys.argv[1:]
builtins.__xonsh__ = XonshSession()
setup_timings(argv) setup_timings(argv)
setproctitle = get_setproctitle() setproctitle = get_setproctitle()
if setproctitle is not None: if setproctitle is not None:
@ -349,7 +348,7 @@ def premain(argv=None):
"login": False, "login": False,
"scriptcache": args.scriptcache, "scriptcache": args.scriptcache,
"cacheall": args.cacheall, "cacheall": args.cacheall,
"ctx": builtins.__xonsh__.ctx, "ctx": XSH.ctx,
} }
if args.login or sys.argv[0].startswith("-"): if args.login or sys.argv[0].startswith("-"):
args.login = True args.login = True
@ -455,9 +454,9 @@ def main_xonsh(args):
signal.signal(signal.SIGTTOU, func_sig_ttin_ttou) signal.signal(signal.SIGTTOU, func_sig_ttin_ttou)
events.on_post_init.fire() events.on_post_init.fire()
env = builtins.__xonsh__.env env = XSH.env
shell = builtins.__xonsh__.shell shell = XSH.shell
history = builtins.__xonsh__.history history = XSH.history
exit_code = 0 exit_code = 0
if shell and not env["XONSH_INTERACTIVE"]: if shell and not env["XONSH_INTERACTIVE"]:
@ -513,7 +512,7 @@ def main_xonsh(args):
def postmain(args=None): def postmain(args=None):
"""Teardown for main xonsh entry point, accepts parsed arguments.""" """Teardown for main xonsh entry point, accepts parsed arguments."""
builtins.__xonsh__.shell = None XSH.shell = None
@contextlib.contextmanager @contextlib.contextmanager
@ -523,7 +522,7 @@ def main_context(argv=None):
up the shell. up the shell.
""" """
args = premain(argv) args = premain(argv)
yield builtins.__xonsh__.shell yield XSH.shell
postmain(args) postmain(args)
@ -568,13 +567,13 @@ def setup(
# setup xonsh ctx and execer # setup xonsh ctx and execer
if not hasattr(builtins, "__xonsh__"): if not hasattr(builtins, "__xonsh__"):
execer = Execer(xonsh_ctx=ctx) execer = Execer(xonsh_ctx=ctx)
builtins.__xonsh__ = XonshSession(ctx=ctx, execer=execer) XSH.load(
load_builtins(ctx=ctx, execer=execer) ctx=ctx, execer=execer, shell=Shell(execer, ctx=ctx, shell_type=shell_type)
builtins.__xonsh__.shell = Shell(execer, ctx=ctx, shell_type=shell_type) )
builtins.__xonsh__.env.update(env) XSH.env.update(env)
install_import_hooks() install_import_hooks()
builtins.aliases.update(aliases) XSH.aliases.update(aliases)
if xontribs: if xontribs:
xontribs_load(xontribs) xontribs_load(xontribs)
tp = builtins.__xonsh__.commands_cache.threadable_predictors tp = XSH.commands_cache.threadable_predictors
tp.update(threadable_predictors) tp.update(threadable_predictors)

View file

@ -7,7 +7,6 @@ import sys
import ctypes # noqa import ctypes # noqa
import signal import signal
import pathlib import pathlib
import builtins
import platform import platform
import functools import functools
import subprocess import subprocess
@ -203,7 +202,9 @@ def ptk_below_max_supported():
@functools.lru_cache(1) @functools.lru_cache(1)
def best_shell_type(): def best_shell_type():
if builtins.__xonsh__.env.get("TERM", "") == "dumb": from xonsh.built_ins import XSH
if XSH.env.get("TERM", "") == "dumb":
return "dumb" return "dumb"
if has_prompt_toolkit(): if has_prompt_toolkit():
return "prompt_toolkit" return "prompt_toolkit"
@ -357,8 +358,10 @@ def windows_bash_command():
"""Determines the command for Bash on windows.""" """Determines the command for Bash on windows."""
# Check that bash is on path otherwise try the default directory # Check that bash is on path otherwise try the default directory
# used by Git for windows # used by Git for windows
from xonsh.built_ins import XSH
wbc = "bash" wbc = "bash"
cmd_cache = builtins.__xonsh__.commands_cache cmd_cache = XSH.commands_cache
bash_on_path = cmd_cache.lazy_locate_binary("bash", ignore_alias=True) bash_on_path = cmd_cache.lazy_locate_binary("bash", ignore_alias=True)
if bash_on_path: if bash_on_path:
try: try:

View file

@ -5,7 +5,6 @@ import io
import sys import sys
import time import time
import signal import signal
import builtins
import threading import threading
import subprocess import subprocess
@ -13,6 +12,7 @@ import xonsh.lazyasd as xl
import xonsh.tools as xt import xonsh.tools as xt
import xonsh.platform as xp import xonsh.platform as xp
import xonsh.jobs as xj import xonsh.jobs as xj
from xonsh.built_ins import XSH
from xonsh.procs.readers import NonBlockingFDReader, ConsoleParallelReader, safe_fdclose from xonsh.procs.readers import NonBlockingFDReader, ConsoleParallelReader, safe_fdclose
@ -83,7 +83,7 @@ def update_fg_process_group(pipeline_group, background):
return False return False
if not xp.ON_POSIX: if not xp.ON_POSIX:
return False return False
env = builtins.__xonsh__.env env = XSH.env
if not env.get("XONSH_INTERACTIVE"): if not env.get("XONSH_INTERACTIVE"):
return False return False
return xj.give_terminal_to(pipeline_group) return xj.give_terminal_to(pipeline_group)
@ -224,7 +224,7 @@ class CommandPipeline:
proc = self.proc proc = self.proc
if proc is None: if proc is None:
return return
timeout = builtins.__xonsh__.env.get("XONSH_PROC_FREQUENCY") timeout = XSH.env.get("XONSH_PROC_FREQUENCY")
# get the correct stdout # get the correct stdout
stdout = proc.stdout stdout = proc.stdout
if ( if (
@ -347,7 +347,7 @@ class CommandPipeline:
yields each line. This may optionally accept lines (in bytes) to iterate yields each line. This may optionally accept lines (in bytes) to iterate
over, in which case it does not call iterraw(). over, in which case it does not call iterraw().
""" """
env = builtins.__xonsh__.env env = XSH.env
enc = env.get("XONSH_ENCODING") enc = env.get("XONSH_ENCODING")
err = env.get("XONSH_ENCODING_ERRORS") err = env.get("XONSH_ENCODING_ERRORS")
lines = self.lines lines = self.lines
@ -387,7 +387,7 @@ class CommandPipeline:
"""Streams lines to sys.stderr and the errors attribute.""" """Streams lines to sys.stderr and the errors attribute."""
if not lines: if not lines:
return return
env = builtins.__xonsh__.env env = XSH.env
enc = env.get("XONSH_ENCODING") enc = env.get("XONSH_ENCODING")
err = env.get("XONSH_ENCODING_ERRORS") err = env.get("XONSH_ENCODING_ERRORS")
b = b"".join(lines) b = b"".join(lines)
@ -411,7 +411,7 @@ class CommandPipeline:
# do some munging of the line before we save it to the attr # do some munging of the line before we save it to the attr
b = b.replace(b"\r\n", b"\n").replace(b"\r", b"\n") b = b.replace(b"\r\n", b"\n").replace(b"\r", b"\n")
b = RE_HIDE_ESCAPE.sub(b"", b) b = RE_HIDE_ESCAPE.sub(b"", b)
env = builtins.__xonsh__.env env = XSH.env
s = b.decode( s = b.decode(
encoding=env.get("XONSH_ENCODING"), errors=env.get("XONSH_ENCODING_ERRORS") encoding=env.get("XONSH_ENCODING"), errors=env.get("XONSH_ENCODING_ERRORS")
) )
@ -426,7 +426,7 @@ class CommandPipeline:
if not b: if not b:
return "" return ""
if isinstance(b, bytes): if isinstance(b, bytes):
env = builtins.__xonsh__.env env = XSH.env
s = b.decode( s = b.decode(
encoding=env.get("XONSH_ENCODING"), encoding=env.get("XONSH_ENCODING"),
errors=env.get("XONSH_ENCODING_ERRORS"), errors=env.get("XONSH_ENCODING_ERRORS"),
@ -478,12 +478,12 @@ class CommandPipeline:
return return
if xj.give_terminal_to(pgid): # if gave term succeed if xj.give_terminal_to(pgid): # if gave term succeed
self.term_pgid = pgid self.term_pgid = pgid
if builtins.__xonsh__.shell is not None: if XSH.shell is not None:
# restoring sanity could probably be called whenever we return # restoring sanity could probably be called whenever we return
# control to the shell. But it only seems to matter after a # control to the shell. But it only seems to matter after a
# ^Z event. This *has* to be called after we give the terminal # ^Z event. This *has* to be called after we give the terminal
# back to the shell. # back to the shell.
builtins.__xonsh__.shell.shell.restore_tty_sanity() XSH.shell.shell.restore_tty_sanity()
def resume(self, job, tee_output=True): def resume(self, job, tee_output=True):
self.ended = False self.ended = False
@ -580,7 +580,7 @@ class CommandPipeline:
def _apply_to_history(self): def _apply_to_history(self):
"""Applies the results to the current history object.""" """Applies the results to the current history object."""
hist = builtins.__xonsh__.history hist = XSH.history
if hist is not None: if hist is not None:
hist.last_cmd_rtn = 1 if self.proc is None else self.proc.returncode hist.last_cmd_rtn = 1 if self.proc is None else self.proc.returncode
@ -588,11 +588,7 @@ class CommandPipeline:
"""Raises a subprocess error, if we are supposed to.""" """Raises a subprocess error, if we are supposed to."""
spec = self.spec spec = self.spec
rtn = self.returncode rtn = self.returncode
if ( if rtn is not None and rtn != 0 and XSH.env.get("RAISE_SUBPROC_ERROR"):
rtn is not None
and rtn != 0
and builtins.__xonsh__.env.get("RAISE_SUBPROC_ERROR")
):
try: try:
raise subprocess.CalledProcessError(rtn, spec.args, output=self.output) raise subprocess.CalledProcessError(rtn, spec.args, output=self.output)
finally: finally:
@ -724,7 +720,7 @@ class CommandPipeline:
"""Prefix to print in front of stderr, as bytes.""" """Prefix to print in front of stderr, as bytes."""
p = self._stderr_prefix p = self._stderr_prefix
if p is None: if p is None:
env = builtins.__xonsh__.env env = XSH.env
t = env.get("XONSH_STDERR_PREFIX") t = env.get("XONSH_STDERR_PREFIX")
s = xt.format_std_prepost(t, env=env) s = xt.format_std_prepost(t, env=env)
p = s.encode( p = s.encode(
@ -739,7 +735,7 @@ class CommandPipeline:
"""Postfix to print after stderr, as bytes.""" """Postfix to print after stderr, as bytes."""
p = self._stderr_postfix p = self._stderr_postfix
if p is None: if p is None:
env = builtins.__xonsh__.env env = XSH.env
t = env.get("XONSH_STDERR_POSTFIX") t = env.get("XONSH_STDERR_POSTFIX")
s = xt.format_std_prepost(t, env=env) s = xt.format_std_prepost(t, env=env)
p = s.encode( p = s.encode(
@ -811,7 +807,7 @@ class PrevProcCloser(threading.Thread):
return return
proc = pipeline.proc proc = pipeline.proc
prev_end_time = None prev_end_time = None
timeout = builtins.__xonsh__.env.get("XONSH_PROC_FREQUENCY") timeout = XSH.env.get("XONSH_PROC_FREQUENCY")
sleeptime = min(timeout * 1000, 0.1) sleeptime = min(timeout * 1000, 0.1)
while proc.poll() is None: while proc.poll() is None:
if not check_prev_done: if not check_prev_done:

View file

@ -5,7 +5,6 @@ import sys
import time import time
import array import array
import signal import signal
import builtins
import threading import threading
import subprocess import subprocess
@ -13,6 +12,7 @@ import xonsh.lazyasd as xl
import xonsh.platform as xp import xonsh.platform as xp
import xonsh.tools as xt import xonsh.tools as xt
import xonsh.lazyimps as xli import xonsh.lazyimps as xli
from xonsh.built_ins import XSH
from xonsh.procs.readers import ( from xonsh.procs.readers import (
BufferedFDParallelReader, BufferedFDParallelReader,
@ -56,7 +56,7 @@ class PopenThread(threading.Thread):
self.daemon = True self.daemon = True
self.lock = threading.RLock() self.lock = threading.RLock()
env = builtins.__xonsh__.env env = XSH.env
# stdin setup # stdin setup
self.orig_stdin = stdin self.orig_stdin = stdin
if stdin is None: if stdin is None:

View file

@ -12,7 +12,6 @@ import sys
import time import time
import signal import signal
import inspect import inspect
import builtins
import functools import functools
import threading import threading
import subprocess import subprocess
@ -21,6 +20,7 @@ import collections.abc as cabc
import xonsh.tools as xt import xonsh.tools as xt
import xonsh.platform as xp import xonsh.platform as xp
import xonsh.lazyimps as xli import xonsh.lazyimps as xli
from xonsh.built_ins import XSH
from xonsh.procs.readers import safe_fdclose from xonsh.procs.readers import safe_fdclose
@ -409,7 +409,7 @@ class ProcProxyThread(threading.Thread):
self.stdout = stdout self.stdout = stdout
self.stderr = stderr self.stderr = stderr
self.close_fds = close_fds self.close_fds = close_fds
self.env = env or builtins.__xonsh__.env self.env = env or XSH.env
self._interrupted = False self._interrupted = False
if xp.ON_WINDOWS: if xp.ON_WINDOWS:
@ -463,7 +463,7 @@ class ProcProxyThread(threading.Thread):
if last_in_pipeline: if last_in_pipeline:
capout = spec.captured_stdout # NOQA capout = spec.captured_stdout # NOQA
caperr = spec.captured_stderr # NOQA caperr = spec.captured_stderr # NOQA
env = builtins.__xonsh__.env env = XSH.env
enc = env.get("XONSH_ENCODING") enc = env.get("XONSH_ENCODING")
err = env.get("XONSH_ENCODING_ERRORS") err = env.get("XONSH_ENCODING_ERRORS")
if xp.ON_WINDOWS: if xp.ON_WINDOWS:
@ -500,7 +500,7 @@ class ProcProxyThread(threading.Thread):
sp_stderr = sys.stderr sp_stderr = sys.stderr
# run the function itself # run the function itself
try: try:
alias_stack = builtins.__xonsh__.env.get("__ALIAS_STACK", "") alias_stack = XSH.env.get("__ALIAS_STACK", "")
if self.env.get("__ALIAS_NAME"): if self.env.get("__ALIAS_NAME"):
alias_stack += ":" + self.env["__ALIAS_NAME"] alias_stack += ":" + self.env["__ALIAS_NAME"]
@ -508,7 +508,7 @@ class ProcProxyThread(threading.Thread):
sp_stderr sp_stderr
), xt.redirect_stdout(STDOUT_DISPATCHER), xt.redirect_stderr( ), xt.redirect_stdout(STDOUT_DISPATCHER), xt.redirect_stderr(
STDERR_DISPATCHER STDERR_DISPATCHER
), builtins.__xonsh__.env.swap( ), XSH.env.swap(
__ALIAS_STACK=alias_stack __ALIAS_STACK=alias_stack
): ):
r = self.f(self.args, sp_stdin, sp_stdout, sp_stderr, spec, spec.stack) r = self.f(self.args, sp_stdin, sp_stdout, sp_stderr, spec, spec.stack)
@ -791,7 +791,7 @@ class ProcProxy:
""" """
if self.f is None: if self.f is None:
return 0 return 0
env = builtins.__xonsh__.env env = XSH.env
enc = env.get("XONSH_ENCODING") enc = env.get("XONSH_ENCODING")
err = env.get("XONSH_ENCODING_ERRORS") err = env.get("XONSH_ENCODING_ERRORS")
spec = self._wait_and_getattr("spec") spec = self._wait_and_getattr("spec")

View file

@ -5,10 +5,10 @@ import sys
import time import time
import queue import queue
import ctypes import ctypes
import builtins
import threading import threading
import xonsh.lazyimps as xli import xonsh.lazyimps as xli
from xonsh.built_ins import XSH
class QueueReader: class QueueReader:
@ -382,7 +382,7 @@ class ConsoleParallelReader(QueueReader):
timeout : float, optional timeout : float, optional
The queue reading timeout. The queue reading timeout.
""" """
timeout = timeout or builtins.__xonsh__.env.get("XONSH_PROC_FREQUENCY") timeout = timeout or XSH.env.get("XONSH_PROC_FREQUENCY")
super().__init__(fd, timeout=timeout) super().__init__(fd, timeout=timeout)
self._buffer = buffer # this cannot be public self._buffer = buffer # this cannot be public
if buffer is None: if buffer is None:

View file

@ -7,10 +7,10 @@ import shlex
import signal import signal
import inspect import inspect
import pathlib import pathlib
import builtins
import subprocess import subprocess
import contextlib import contextlib
from xonsh.built_ins import XSH
import xonsh.tools as xt import xonsh.tools as xt
import xonsh.lazyasd as xl import xonsh.lazyasd as xl
import xonsh.platform as xp import xonsh.platform as xp
@ -101,7 +101,7 @@ def get_script_subproc_command(fname, args):
# Windows can execute various filetypes directly # Windows can execute various filetypes directly
# as given in PATHEXT # as given in PATHEXT
_, ext = os.path.splitext(fname) _, ext = os.path.splitext(fname)
if ext.upper() in builtins.__xonsh__.env.get("PATHEXT"): if ext.upper() in XSH.env.get("PATHEXT"):
return [fname] + args return [fname] + args
# find interpreter # find interpreter
with open(fname, "rb") as f: with open(fname, "rb") as f:
@ -356,7 +356,7 @@ class SubprocSpec:
self.args = list(cmd) self.args = list(cmd)
self.alias = None self.alias = None
self.alias_name = None self.alias_name = None
self.alias_stack = builtins.__xonsh__.env.get("__ALIAS_STACK", "").split(":") self.alias_stack = XSH.env.get("__ALIAS_STACK", "").split(":")
self.binary_loc = None self.binary_loc = None
self.is_proxy = False self.is_proxy = False
self.background = False self.background = False
@ -458,8 +458,8 @@ class SubprocSpec:
return p return p
def _run_binary(self, kwargs): def _run_binary(self, kwargs):
bufsize = 1
try: try:
bufsize = 1
p = self.cls(self.cmd, bufsize=bufsize, **kwargs) p = self.cls(self.cmd, bufsize=bufsize, **kwargs)
except PermissionError: except PermissionError:
e = "xonsh: subprocess mode: permission denied: {0}" e = "xonsh: subprocess mode: permission denied: {0}"
@ -472,16 +472,16 @@ class SubprocSpec:
["man", cmd0.rstrip("?")], bufsize=bufsize, **kwargs ["man", cmd0.rstrip("?")], bufsize=bufsize, **kwargs
) )
e = "xonsh: subprocess mode: command not found: {0}".format(cmd0) e = "xonsh: subprocess mode: command not found: {0}".format(cmd0)
env = builtins.__xonsh__.env env = XSH.env
sug = xt.suggest_commands(cmd0, env, builtins.aliases) sug = xt.suggest_commands(cmd0, env, XSH.aliases)
if len(sug.strip()) > 0: if len(sug.strip()) > 0:
e += "\n" + xt.suggest_commands(cmd0, env, builtins.aliases) e += "\n" + xt.suggest_commands(cmd0, env, XSH.aliases)
raise xt.XonshError(e) raise xt.XonshError(e)
return p return p
def prep_env(self, kwargs): def prep_env(self, kwargs):
"""Prepares the environment to use in the subprocess.""" """Prepares the environment to use in the subprocess."""
with builtins.__xonsh__.env.swap(self.env) as env: with XSH.env.swap(self.env) as env:
denv = env.detype() denv = env.detype()
if xp.ON_WINDOWS: if xp.ON_WINDOWS:
# Over write prompt variable as xonsh's $PROMPT does # Over write prompt variable as xonsh's $PROMPT does
@ -493,7 +493,7 @@ class SubprocSpec:
"""Prepares the 'preexec_fn' keyword argument""" """Prepares the 'preexec_fn' keyword argument"""
if not xp.ON_POSIX: if not xp.ON_POSIX:
return return
if not builtins.__xonsh__.env.get("XONSH_INTERACTIVE"): if not XSH.env.get("XONSH_INTERACTIVE"):
return return
if pipeline_group is None or xp.ON_WSL: if pipeline_group is None or xp.ON_WSL:
# If there is no pipeline group # If there is no pipeline group
@ -530,14 +530,14 @@ class SubprocSpec:
return os.path.basename(self.binary_loc) return os.path.basename(self.binary_loc)
def _pre_run_event_fire(self, name): def _pre_run_event_fire(self, name):
events = builtins.events events = XSH.builtins.events
event_name = "on_pre_spec_run_" + name event_name = "on_pre_spec_run_" + name
if events.exists(event_name): if events.exists(event_name):
event = getattr(events, event_name) event = getattr(events, event_name)
event.fire(spec=self) event.fire(spec=self)
def _post_run_event_fire(self, name, proc): def _post_run_event_fire(self, name, proc):
events = builtins.events events = XSH.builtins.events
event_name = "on_post_spec_run_" + name event_name = "on_post_spec_run_" + name
if events.exists(event_name): if events.exists(event_name):
event = getattr(events, event_name) event = getattr(events, event_name)
@ -602,7 +602,7 @@ class SubprocSpec:
if callable(cmd0): if callable(cmd0):
alias = cmd0 alias = cmd0
else: else:
alias = builtins.aliases.get(cmd0, None) alias = XSH.aliases.get(cmd0, None)
if alias is not None: if alias is not None:
self.alias_name = cmd0 self.alias_name = cmd0
self.alias = alias self.alias = alias
@ -627,12 +627,12 @@ class SubprocSpec:
self.alias is None self.alias is None
and self.binary_loc is None and self.binary_loc is None
and len(self.cmd) == 1 and len(self.cmd) == 1
and builtins.__xonsh__.env.get("AUTO_CD") and XSH.env.get("AUTO_CD")
and os.path.isdir(self.cmd[0]) and os.path.isdir(self.cmd[0])
): ):
return return
self.cmd.insert(0, "cd") self.cmd.insert(0, "cd")
self.alias = builtins.aliases.get("cd", None) self.alias = XSH.aliases.get("cd", None)
def resolve_executable_commands(self): def resolve_executable_commands(self):
"""Resolve command executables, if applicable.""" """Resolve command executables, if applicable."""
@ -663,7 +663,7 @@ class SubprocSpec:
if not callable(alias): if not callable(alias):
return return
self.is_proxy = True self.is_proxy = True
env = builtins.__xonsh__.env env = XSH.env
thable = env.get("THREAD_SUBPROCS") and getattr( thable = env.get("THREAD_SUBPROCS") and getattr(
alias, "__xonsh_threadable__", True alias, "__xonsh_threadable__", True
) )
@ -718,7 +718,7 @@ def _safe_pipe_properties(fd, use_tty=False):
def _update_last_spec(last): def _update_last_spec(last):
env = builtins.__xonsh__.env env = XSH.env
captured = last.captured captured = last.captured
last.last_in_pipeline = True last.last_in_pipeline = True
if not captured: if not captured:
@ -727,7 +727,7 @@ def _update_last_spec(last):
if callable_alias: if callable_alias:
pass pass
else: else:
cmds_cache = builtins.__xonsh__.commands_cache cmds_cache = XSH.commands_cache
thable = ( thable = (
env.get("THREAD_SUBPROCS") env.get("THREAD_SUBPROCS")
and cmds_cache.predict_threadable(last.args) and cmds_cache.predict_threadable(last.args)
@ -753,9 +753,9 @@ def _update_last_spec(last):
r, w = os.pipe() r, w = os.pipe()
last.stdout = safe_open(w, "wb") last.stdout = safe_open(w, "wb")
last.captured_stdout = safe_open(r, "rb") last.captured_stdout = safe_open(r, "rb")
elif builtins.__xonsh__.stdout_uncaptured is not None: elif XSH.stdout_uncaptured is not None:
last.universal_newlines = True last.universal_newlines = True
last.stdout = builtins.__xonsh__.stdout_uncaptured last.stdout = XSH.stdout_uncaptured
last.captured_stdout = last.stdout last.captured_stdout = last.stdout
elif xp.ON_WINDOWS and not callable_alias: elif xp.ON_WINDOWS and not callable_alias:
last.universal_newlines = True last.universal_newlines = True
@ -775,8 +775,8 @@ def _update_last_spec(last):
r, w = os.pipe() r, w = os.pipe()
last.stderr = safe_open(w, "w") last.stderr = safe_open(w, "w")
last.captured_stderr = safe_open(r, "r") last.captured_stderr = safe_open(r, "r")
elif builtins.__xonsh__.stderr_uncaptured is not None: elif XSH.stderr_uncaptured is not None:
last.stderr = builtins.__xonsh__.stderr_uncaptured last.stderr = XSH.stderr_uncaptured
last.captured_stderr = last.stderr last.captured_stderr = last.stderr
elif xp.ON_WINDOWS and not callable_alias: elif xp.ON_WINDOWS and not callable_alias:
last.universal_newlines = True last.universal_newlines = True
@ -832,12 +832,12 @@ def cmds_to_specs(cmds, captured=False, envs=None):
def _should_set_title(captured=False): def _should_set_title(captured=False):
env = builtins.__xonsh__.env env = XSH.env
return ( return (
env.get("XONSH_INTERACTIVE") env.get("XONSH_INTERACTIVE")
and not env.get("XONSH_STORE_STDOUT") and not env.get("XONSH_STORE_STDOUT")
and captured not in STDOUT_CAPTURE_KINDS and captured not in STDOUT_CAPTURE_KINDS
and builtins.__xonsh__.shell is not None and XSH.shell is not None
) )
@ -854,7 +854,7 @@ def run_subproc(cmds, captured=False, envs=None):
Lastly, the captured argument affects only the last real command. Lastly, the captured argument affects only the last real command.
""" """
if builtins.__xonsh__.env.get("XONSH_TRACE_SUBPROC"): if XSH.env.get("XONSH_TRACE_SUBPROC"):
print(f"TRACE SUBPROC: {cmds}, captured={captured}", file=sys.stderr) print(f"TRACE SUBPROC: {cmds}, captured={captured}", file=sys.stderr)
specs = cmds_to_specs(cmds, captured=captured, envs=envs) specs = cmds_to_specs(cmds, captured=captured, envs=envs)
@ -878,7 +878,7 @@ def run_subproc(cmds, captured=False, envs=None):
) )
if _should_set_title(captured=captured): if _should_set_title(captured=captured):
# set title here to get currently executing command # set title here to get currently executing command
pause_call_resume(proc, builtins.__xonsh__.shell.settitle) pause_call_resume(proc, XSH.shell.settitle)
else: else:
# for some reason, some programs are in a stopped state when the flow # for some reason, some programs are in a stopped state when the flow
# reaches this point, hence a SIGCONT should be sent to `proc` to make # reaches this point, hence a SIGCONT should be sent to `proc` to make

View file

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Base prompt, provides PROMPT_FIELDS and prompt related functions""" """Base prompt, provides PROMPT_FIELDS and prompt related functions"""
import builtins
import itertools import itertools
import os import os
import re import re
@ -13,6 +12,7 @@ import xonsh.lazyasd as xl
import xonsh.tools as xt import xonsh.tools as xt
import xonsh.platform as xp import xonsh.platform as xp
from xonsh.built_ins import XSH
from xonsh.prompt.cwd import ( from xonsh.prompt.cwd import (
_collapsed_pwd, _collapsed_pwd,
_replace_home_cwd, _replace_home_cwd,
@ -43,7 +43,7 @@ class ParsedTokens(tp.NamedTuple):
def process(self) -> str: def process(self) -> str:
"""Wrapper that gets formatter-function from environment and returns final prompt.""" """Wrapper that gets formatter-function from environment and returns final prompt."""
processor = builtins.__xonsh__.env.get( # type: ignore processor = XSH.env.get( # type: ignore
"PROMPT_TOKENS_FORMATTER", prompt_tokens_formatter_default "PROMPT_TOKENS_FORMATTER", prompt_tokens_formatter_default
) )
return processor(self) return processor(self)
@ -93,7 +93,7 @@ class PromptFormatter:
self.cache.clear() self.cache.clear()
if fields is None: if fields is None:
self.fields = builtins.__xonsh__.env.get("PROMPT_FIELDS", PROMPT_FIELDS) # type: ignore self.fields = XSH.env.get("PROMPT_FIELDS", PROMPT_FIELDS) # type: ignore
else: else:
self.fields = fields self.fields = fields
try: try:
@ -124,7 +124,7 @@ class PromptFormatter:
if field is None: if field is None:
return return
elif field.startswith("$"): elif field.startswith("$"):
val = builtins.__xonsh__.env[field[1:]] val = XSH.env[field[1:]]
return _format_value(val, spec, conv) return _format_value(val, spec, conv)
elif field in self.fields: elif field in self.fields:
val = self._get_field_value(field, spec=spec, conv=conv, **kwargs) val = self._get_field_value(field, spec=spec, conv=conv, **kwargs)
@ -226,7 +226,7 @@ def multiline_prompt(curr=""):
# tail is the trailing whitespace # tail is the trailing whitespace
tail = line if headlen == 0 else line.rsplit(head[-1], 1)[1] tail = line if headlen == 0 else line.rsplit(head[-1], 1)[1]
# now to construct the actual string # now to construct the actual string
dots = builtins.__xonsh__.env.get("MULTILINE_PROMPT") dots = XSH.env.get("MULTILINE_PROMPT")
dots = dots() if callable(dots) else dots dots = dots() if callable(dots) else dots
if dots is None or len(dots) == 0: if dots is None or len(dots) == 0:
return "" return ""
@ -272,7 +272,7 @@ def is_template_string(template, PROMPT_FIELDS=None):
return False return False
included_names.discard(None) included_names.discard(None)
if PROMPT_FIELDS is None: if PROMPT_FIELDS is None:
fmtter = builtins.__xonsh__.env.get("PROMPT_FIELDS", PROMPT_FIELDS) fmtter = XSH.env.get("PROMPT_FIELDS", PROMPT_FIELDS)
else: else:
fmtter = PROMPT_FIELDS fmtter = PROMPT_FIELDS
known_names = set(fmtter.keys()) known_names = set(fmtter.keys())

View file

@ -3,33 +3,31 @@
import os import os
import shutil import shutil
import builtins
import xonsh.tools as xt import xonsh.tools as xt
import xonsh.platform as xp import xonsh.platform as xp
from xonsh.built_ins import XSH
def _replace_home(x): def _replace_home(x):
if xp.ON_WINDOWS: if xp.ON_WINDOWS:
home = ( home = XSH.env["HOMEDRIVE"] + XSH.env["HOMEPATH"][0]
builtins.__xonsh__.env["HOMEDRIVE"] + builtins.__xonsh__.env["HOMEPATH"][0]
)
if x.startswith(home): if x.startswith(home):
x = x.replace(home, "~", 1) x = x.replace(home, "~", 1)
if builtins.__xonsh__.env.get("FORCE_POSIX_PATHS"): if XSH.env.get("FORCE_POSIX_PATHS"):
x = x.replace(os.sep, os.altsep) x = x.replace(os.sep, os.altsep)
return x return x
else: else:
home = builtins.__xonsh__.env["HOME"] home = XSH.env["HOME"]
if x.startswith(home): if x.startswith(home):
x = x.replace(home, "~", 1) x = x.replace(home, "~", 1)
return x return x
def _replace_home_cwd(): def _replace_home_cwd():
return _replace_home(builtins.__xonsh__.env["PWD"]) return _replace_home(XSH.env["PWD"])
def _collapsed_pwd(): def _collapsed_pwd():
@ -50,8 +48,8 @@ def _dynamically_collapsed_pwd():
environment variable DYNAMIC_CWD_WIDTH. environment variable DYNAMIC_CWD_WIDTH.
""" """
original_path = _replace_home_cwd() original_path = _replace_home_cwd()
target_width, units = builtins.__xonsh__.env["DYNAMIC_CWD_WIDTH"] target_width, units = XSH.env["DYNAMIC_CWD_WIDTH"]
elision_char = builtins.__xonsh__.env["DYNAMIC_CWD_ELISION_CHAR"] elision_char = XSH.env["DYNAMIC_CWD_ELISION_CHAR"]
if target_width == float("inf"): if target_width == float("inf"):
return original_path return original_path
if units == "%": if units == "%":

View file

@ -2,8 +2,8 @@
"""Prompt formatter for virtualenv and others""" """Prompt formatter for virtualenv and others"""
import os import os
import builtins
from xonsh.built_ins import XSH
import xonsh.platform as xp import xonsh.platform as xp
@ -11,9 +11,9 @@ def find_env_name():
"""Finds the current environment name from $VIRTUAL_ENV or """Finds the current environment name from $VIRTUAL_ENV or
$CONDA_DEFAULT_ENV if that is set. $CONDA_DEFAULT_ENV if that is set.
""" """
env_path = builtins.__xonsh__.env.get("VIRTUAL_ENV", "") env_path = XSH.env.get("VIRTUAL_ENV", "")
if len(env_path) == 0 and xp.ON_ANACONDA: if len(env_path) == 0 and xp.ON_ANACONDA:
env_path = builtins.__xonsh__.env.get("CONDA_DEFAULT_ENV", "") env_path = XSH.env.get("CONDA_DEFAULT_ENV", "")
env_name = os.path.basename(env_path) env_name = os.path.basename(env_path)
return env_name return env_name
@ -23,15 +23,15 @@ def env_name():
``{env_prefix}`` and ``{env_postfix}`` fields. ``{env_prefix}`` and ``{env_postfix}`` fields.
""" """
env_name = find_env_name() env_name = find_env_name()
if builtins.__xonsh__.env.get("VIRTUAL_ENV_DISABLE_PROMPT") or not env_name: if XSH.env.get("VIRTUAL_ENV_DISABLE_PROMPT") or not env_name:
# env name prompt printing disabled, or no environment; just return # env name prompt printing disabled, or no environment; just return
return return
venv_prompt = builtins.__xonsh__.env.get("VIRTUAL_ENV_PROMPT") venv_prompt = XSH.env.get("VIRTUAL_ENV_PROMPT")
if venv_prompt is not None: if venv_prompt is not None:
return venv_prompt return venv_prompt
else: else:
pf = builtins.__xonsh__.shell.prompt_formatter pf = XSH.shell.prompt_formatter
pre = pf._get_field_value("env_prefix") pre = pf._get_field_value("env_prefix")
post = pf._get_field_value("env_postfix") post = pf._get_field_value("env_postfix")
return pre + env_name + post return pre + env_name + post
@ -44,7 +44,7 @@ def vte_new_tab_cwd():
on startup. Note that this does not return a string, it simply prints on startup. Note that this does not return a string, it simply prints
and flushes the escape sequence to stdout directly. and flushes the escape sequence to stdout directly.
""" """
env = builtins.__xonsh__.env env = XSH.env
t = "\033]7;file://{}{}\007" t = "\033]7;file://{}{}\007"
s = t.format(env.get("HOSTNAME"), env.get("PWD")) s = t.format(env.get("HOSTNAME"), env.get("PWD"))
print(s, end="", flush=True) print(s, end="", flush=True)

View file

@ -1,13 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Informative git status prompt formatter""" """Informative git status prompt formatter"""
import builtins
import collections import collections
import os import os
import subprocess import subprocess
import xonsh.lazyasd as xl import xonsh.lazyasd as xl
from xonsh.built_ins import XSH
GitStatus = collections.namedtuple( GitStatus = collections.namedtuple(
"GitStatus", "GitStatus",
@ -31,13 +30,13 @@ GitStatus = collections.namedtuple(
def _check_output(*args, **kwargs): def _check_output(*args, **kwargs):
kwargs.update( kwargs.update(
dict( dict(
env=builtins.__xonsh__.env.detype(), env=XSH.env.detype(),
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
universal_newlines=True, universal_newlines=True,
) )
) )
timeout = builtins.__xonsh__.env["VC_BRANCH_TIMEOUT"] timeout = XSH.env["VC_BRANCH_TIMEOUT"]
# See https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate # See https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate
with subprocess.Popen(*args, **kwargs) as proc: with subprocess.Popen(*args, **kwargs) as proc:
try: try:
@ -86,7 +85,7 @@ def _DEFS():
def _get_def(key): def _get_def(key):
def_ = builtins.__xonsh__.env.get("XONSH_GITSTATUS_" + key) def_ = XSH.env.get("XONSH_GITSTATUS_" + key)
return def_ if def_ is not None else _DEFS[key] return def_ if def_ is not None else _DEFS[key]

View file

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""date & time related prompt formatter""" """date & time related prompt formatter"""
import time import time
import builtins
from xonsh.built_ins import XSH
def _localtime(): def _localtime():
pf = builtins.__xonsh__.env.get("PROMPT_FIELDS", {}) pf = XSH.env.get("PROMPT_FIELDS", {})
tf = pf.get("time_format", "%H:%M:%S") tf = pf.get("time_format", "%H:%M:%S")
return time.strftime(tf, time.localtime()) return time.strftime(tf, time.localtime())

View file

@ -3,15 +3,15 @@
# pylint:disable=no-member, invalid-name # pylint:disable=no-member, invalid-name
import os import os
import sys
import queue
import builtins
import threading
import subprocess
import re
import pathlib import pathlib
import queue
import re
import subprocess
import sys
import threading
import xonsh.tools as xt import xonsh.tools as xt
from xonsh.built_ins import XSH
from xonsh.lazyasd import LazyObject from xonsh.lazyasd import LazyObject
RE_REMOVE_ANSI = LazyObject( RE_REMOVE_ANSI = LazyObject(
@ -24,7 +24,7 @@ RE_REMOVE_ANSI = LazyObject(
def _run_git_cmd(cmd): def _run_git_cmd(cmd):
# create a safe detyped env dictionary and update with the additional git environment variables # create a safe detyped env dictionary and update with the additional git environment variables
# when running git status commands we do not want to acquire locks running command like git status # when running git status commands we do not want to acquire locks running command like git status
denv = dict(builtins.__xonsh__.env.detype()) denv = dict(XSH.env.detype())
denv.update({"GIT_OPTIONAL_LOCKS": "0"}) denv.update({"GIT_OPTIONAL_LOCKS": "0"})
return subprocess.check_output(cmd, env=denv, stderr=subprocess.DEVNULL) return subprocess.check_output(cmd, env=denv, stderr=subprocess.DEVNULL)
@ -44,7 +44,7 @@ def get_git_branch():
be determined (timeout, not in a git repo, etc.) then this returns None. be determined (timeout, not in a git repo, etc.) then this returns None.
""" """
branch = None branch = None
timeout = builtins.__xonsh__.env.get("VC_BRANCH_TIMEOUT") timeout = XSH.env.get("VC_BRANCH_TIMEOUT")
q = queue.Queue() q = queue.Queue()
t = threading.Thread(target=_get_git_branch, args=(q,)) t = threading.Thread(target=_get_git_branch, args=(q,))
@ -60,7 +60,7 @@ def get_git_branch():
def _get_hg_root(q): def _get_hg_root(q):
_curpwd = builtins.__xonsh__.env["PWD"] _curpwd = XSH.env["PWD"]
while True: while True:
if not os.path.isdir(_curpwd): if not os.path.isdir(_curpwd):
return False return False
@ -82,7 +82,7 @@ def get_hg_branch(root=None):
"""Try to get the mercurial branch of the current directory, """Try to get the mercurial branch of the current directory,
return None if not in a repo or subprocess.TimeoutExpired if timed out. return None if not in a repo or subprocess.TimeoutExpired if timed out.
""" """
env = builtins.__xonsh__.env env = XSH.env
timeout = env["VC_BRANCH_TIMEOUT"] timeout = env["VC_BRANCH_TIMEOUT"]
q = queue.Queue() q = queue.Queue()
t = threading.Thread(target=_get_hg_root, args=(q,)) t = threading.Thread(target=_get_hg_root, args=(q,))
@ -125,7 +125,7 @@ _FIRST_BRANCH_TIMEOUT = True
def _first_branch_timeout_message(): def _first_branch_timeout_message():
global _FIRST_BRANCH_TIMEOUT global _FIRST_BRANCH_TIMEOUT
sbtm = builtins.__xonsh__.env["SUPPRESS_BRANCH_TIMEOUT_MESSAGE"] sbtm = XSH.env["SUPPRESS_BRANCH_TIMEOUT_MESSAGE"]
if not _FIRST_BRANCH_TIMEOUT or sbtm: if not _FIRST_BRANCH_TIMEOUT or sbtm:
return return
_FIRST_BRANCH_TIMEOUT = False _FIRST_BRANCH_TIMEOUT = False
@ -143,7 +143,7 @@ def _first_branch_timeout_message():
def _vc_has(binary): def _vc_has(binary):
"""This allows us to locate binaries after git only if necessary""" """This allows us to locate binaries after git only if necessary"""
cmds = builtins.__xonsh__.commands_cache cmds = XSH.commands_cache
if cmds.is_empty(): if cmds.is_empty():
return bool(cmds.locate_binary(binary, ignore_alias=True)) return bool(cmds.locate_binary(binary, ignore_alias=True))
else: else:
@ -187,7 +187,7 @@ def git_dirty_working_directory():
"""Returns whether or not the git directory is dirty. If this could not """Returns whether or not the git directory is dirty. If this could not
be determined (timeout, file not found, etc.) then this returns None. be determined (timeout, file not found, etc.) then this returns None.
""" """
env = builtins.__xonsh__.env env = XSH.env
timeout = env.get("VC_BRANCH_TIMEOUT") timeout = env.get("VC_BRANCH_TIMEOUT")
include_untracked = env.get("VC_GIT_INCLUDE_UNTRACKED") include_untracked = env.get("VC_GIT_INCLUDE_UNTRACKED")
q = queue.Queue() q = queue.Queue()
@ -206,7 +206,7 @@ def hg_dirty_working_directory():
"""Computes whether or not the mercurial working directory is dirty or not. """Computes whether or not the mercurial working directory is dirty or not.
If this cannot be determined, None is returned. If this cannot be determined, None is returned.
""" """
env = builtins.__xonsh__.env env = XSH.env
cwd = env["PWD"] cwd = env["PWD"]
denv = env.detype() denv = env.detype()
vcbt = env["VC_BRANCH_TIMEOUT"] vcbt = env["VC_BRANCH_TIMEOUT"]

View file

@ -1,13 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Completer implementation to use with prompt_toolkit.""" """Completer implementation to use with prompt_toolkit."""
import os import os
import builtins
from prompt_toolkit.completion import Completer, Completion from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
from prompt_toolkit.application.current import get_app from prompt_toolkit.application.current import get_app
from xonsh.completers.tools import RichCompletion from xonsh.completers.tools import RichCompletion
from xonsh.built_ins import XSH
class PromptToolkitCompleter(Completer): class PromptToolkitCompleter(Completer):
@ -27,7 +27,7 @@ class PromptToolkitCompleter(Completer):
def get_completions(self, document, complete_event): def get_completions(self, document, complete_event):
"""Returns a generator for list of completions.""" """Returns a generator for list of completions."""
env = builtins.__xonsh__.env env = XSH.env
should_complete = complete_event.completion_requested or env.get( should_complete = complete_event.completion_requested or env.get(
"UPDATE_COMPLETIONS_ON_KEYPRESS" "UPDATE_COMPLETIONS_ON_KEYPRESS"
) )
@ -38,7 +38,7 @@ class PromptToolkitCompleter(Completer):
line = document.current_line line = document.current_line
endidx = document.cursor_position_col endidx = document.cursor_position_col
line_ex = builtins.aliases.expand_alias(line, endidx) line_ex = XSH.aliases.expand_alias(line, endidx)
begidx = line[:endidx].rfind(" ") + 1 if line[:endidx].rfind(" ") >= 0 else 0 begidx = line[:endidx].rfind(" ") + 1 if line[:endidx].rfind(" ") >= 0 else 0
prefix = line[begidx:endidx] prefix = line[begidx:endidx]
@ -135,7 +135,7 @@ class PromptToolkitCompleter(Completer):
if window and window.render_info: if window and window.render_info:
h = window.render_info.content_height h = window.render_info.content_height
r = builtins.__xonsh__.env.get("COMPLETIONS_MENU_ROWS") r = XSH.env.get("COMPLETIONS_MENU_ROWS")
size = h + r size = h + r
last_h = render._last_screen.height if render._last_screen else 0 last_h = render._last_screen.height if render._last_screen else 0
last_h = max(render._min_available_height, last_h) last_h = max(render._min_available_height, last_h)

Some files were not shown because too many files have changed in this diff Show more