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:
from xonsh.environ import VarKeyType
from xonsh.built_ins import XSH
from xonsh.xontribs_meta import get_xontribs
from xonsh.commands_cache import CommandsCache
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")
if spec is not None:
# hacky runaround to import PTK-specific events
builtins.__xonsh__.env = Env()
XSH.env = Env()
from xonsh.ptk_shell.shell import events
else:
from xonsh.events import events
@ -452,9 +447,9 @@ def make_events():
make_xontribs()
make_events()
builtins.__xonsh__.history = None
builtins.__xonsh__.env = {}
builtins.__xonsh__.commands_cache = CommandsCache()
XSH.history = None
XSH.env = {}
XSH.commands_cache = CommandsCache()
def setup(app):

View file

@ -2,6 +2,7 @@ py
pytest>=6
flake8
flake8-docstrings
flake8-mutable
pytest-cov
pytest-timeout
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`
"""
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
if ns.report_coverage:
![coverage run -m pytest @(_replace_args(args, 0)) @(ignores)]
for index, fname in enumerate(run_separately):
![coverage run --append -m pytest @(_replace_args(args, index+1)) @(fname)]
![coverage report -m]
![coverage xml]
![pytest @(_replace_args(args, 0)) --cov --cov-report=xml --cov-report=term]
else:
![pytest @(_replace_args(args, 0)) @(ignores)]
for index, fname in enumerate(run_separately):
![pytest @(_replace_args(args, index + 1)) @(fname)]
![pytest @(_replace_args(args, 0))]
def qa(ns: argparse.Namespace):
"""QA checks"""
echo "---------- Check Black formatter -----------"
black --check xonsh xontrib
black --check xonsh xontrib tests
echo "---------- Running flake8 ----------"
python -m flake8
echo "---------- Running mypy ----------"
mypy --version
# todo: add xontrib folder here
mypy xonsh --exclude xonsh/ply

View file

@ -48,12 +48,7 @@ ignore =
E402, # module level import not at top of file
W503, # line break before binary operators is a good thing
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 =
# flake8 gives incorrect unused import errors, F401
tests/tools.py:E128,

View file

@ -1,9 +1,10 @@
import os.path
import pytest
import builtins
from contextlib import contextmanager
from unittest.mock import MagicMock
from xonsh.aliases import source_alias, builtins
from xonsh.aliases import source_alias
@pytest.fixture
@ -15,27 +16,26 @@ def mockopen(xonsh_builtins, monkeypatch):
monkeypatch.setattr(builtins, "open", mocked_open)
def test_source_current_dir(mockopen, monkeypatch):
@pytest.fixture
def mocked_execx_checker(xession, monkeypatch):
checker = []
def mocked_execx(src, *args, **kwargs):
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)
source_alias(["foo", "bar"])
assert checker == ["foo", "bar"]
assert mocked_execx_checker == ["foo", "bar"]
def test_source_path(mockopen, monkeypatch):
checker = []
def mocked_execx(src, *args, **kwargs):
checker.append(src.strip())
monkeypatch.setattr(builtins, "execx", mocked_execx)
def test_source_path(mockopen, mocked_execx_checker):
source_alias(["foo", "bar"])
path_foo = os.path.join("tests", "bin", "foo")
path_bar = os.path.join("tests", "bin", "bar")
assert checker[0].endswith(path_foo)
assert checker[1].endswith(path_bar)
assert mocked_execx_checker[0].endswith(path_foo)
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)
def setup(xonsh_builtins, xonsh_execer, monkeypatch):
monkeypatch.setattr(xonsh_builtins.__xonsh__, "commands_cache", ["cool"])
def setup(xession, xonsh_execer, monkeypatch):
monkeypatch.setattr(xession, "commands_cache", ["cool"])
def test_empty_line():
completions = complete_base(
CompletionContext(
command=CommandContext((), 0),
python=PythonContext("", 0)
)
CompletionContext(command=CommandContext((), 0), python=PythonContext("", 0))
)
assert completions
for exp in ["cool", "abs"]:
@ -33,8 +32,7 @@ def test_empty_line():
def test_empty_subexpr():
completions = complete_base(
CompletionContext(
command=CommandContext((), 0, subcmd_opening="$("),
python=None
command=CommandContext((), 0, subcmd_opening="$("), python=None
)
)
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.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)
def setup(monkeypatch, tmp_path, xonsh_builtins):
if not xonsh_builtins.__xonsh__.env.get("BASH_COMPLETIONS"):
monkeypatch.setitem(xonsh_builtins.__xonsh__.env, "BASH_COMPLETIONS", ["/usr/share/bash-completion/bash_completion"])
def setup(monkeypatch, tmp_path, xession):
if not xession.env.get("BASH_COMPLETIONS"):
monkeypatch.setitem(
xession.env,
"BASH_COMPLETIONS",
["/usr/share/bash-completion/bash_completion"],
)
(tmp_path / "testdir").mkdir()
(tmp_path / "spaced dir").mkdir()
monkeypatch.chdir(str(tmp_path))
@skip_if_on_darwin
@skip_if_on_windows
@pytest.mark.parametrize("command_context, completions, lprefix", (
(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),
))
@pytest.mark.parametrize(
"command_context, completions, lprefix",
(
(
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):
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
@skip_if_on_darwin
@skip_if_on_windows
@pytest.mark.parametrize("command_context, completions, lprefix", (
@pytest.mark.parametrize(
"command_context, completions, lprefix",
(
# 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/'
(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/'
(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/'
(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/"""
(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:
# 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/'
(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/'
(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/'
(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):
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 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 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
@ -8,6 +14,12 @@ from xonsh.completer import Completer
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):
if ON_WINDOWS:
command = "dir.exe"
@ -15,29 +27,34 @@ def test_complete_command(completion_context_parse):
command = "grep"
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
def test_skipper_command(completion_context_parse):
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
def test_skipper_arg(completion_context_parse, xonsh_builtins, monkeypatch):
monkeypatch.setattr(xonsh_builtins.__xonsh__.shell.shell, "completer", Completer(), raising=False)
def test_skipper_arg(completion_context_parse, xession, monkeypatch):
monkeypatch.setattr(xession.shell.shell, "completer", Completer(), raising=False)
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 "}
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]
assert len(call_args) == 1
context = call_args[0]
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
def test_options():
assert complete_completer(CompletionContext(CommandContext(
args=(CommandArg("completer"),), arg_index=1,
))) == {"add", "remove", "list", "help"}
assert (
complete_completer(
CompletionContext(
CommandContext(
args=(CommandArg("completer"),),
arg_index=1,
)
)
)
== {"add", "remove", "list", "help"}
)
def test_help_options():
assert complete_completer(CompletionContext(CommandContext(
args=(CommandArg("completer"),CommandArg("help")), arg_index=2,
))) == {"add", "remove", "list"}
assert (
complete_completer(
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.dirs import complete_cd, complete_rmdir
from xonsh.parsers.completion_context import (
CompletionContext, CommandContext, CommandArg,
CompletionContext,
CommandContext,
CommandArg,
)
from tests.tools import ON_WINDOWS
@ -19,11 +21,12 @@ COMPLETERS = {
CUR_DIR = "." if ON_WINDOWS else "./"
PARENT_DIR = ".." if ON_WINDOWS else "../"
@pytest.fixture(autouse=True)
def setup(xonsh_builtins, xonsh_execer):
def setup(xession, xonsh_execer):
with tempfile.TemporaryDirectory() as tmp:
xonsh_builtins.__xonsh__.env["XONSH_DATA_DIR"] = tmp
xonsh_builtins.__xonsh__.env["CDPATH"] = set()
xession.env["XONSH_DATA_DIR"] = tmp
xession.env["CDPATH"] = set()
@pytest.fixture(params=list(COMPLETERS))
@ -33,20 +36,34 @@ def cmd(request):
def test_not_cmd(cmd):
"""Ensure the cd completer doesn't complete other commands"""
assert not COMPLETERS[cmd](CompletionContext(CommandContext(
args=(CommandArg(f"not-{cmd}"),), arg_index=1,
)))
assert not COMPLETERS[cmd](
CompletionContext(
CommandContext(
args=(CommandArg(f"not-{cmd}"),),
arg_index=1,
)
)
)
def complete_cmd(cmd, prefix, opening_quote="", closing_quote=""):
result = COMPLETERS[cmd](CompletionContext(CommandContext(
args=(CommandArg(cmd),), arg_index=1, prefix=prefix,
opening_quote=opening_quote, closing_quote=closing_quote,
is_after_closing_quote=bool(closing_quote),
)))
result = COMPLETERS[cmd](
CompletionContext(
CommandContext(
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
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
@ -92,24 +109,24 @@ def test_closing_quotes(cmd, dir_path):
assert completion.append_closing_quote is False
def test_complete_dots(xonsh_builtins):
with xonsh_builtins.__xonsh__.env.swap(COMPLETE_DOTS='never'):
dirs = complete_cmd_dirs('cd', '')
def test_complete_dots(xession):
with xession.env.swap(COMPLETE_DOTS="never"):
dirs = complete_cmd_dirs("cd", "")
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
with xonsh_builtins.__xonsh__.env.swap(COMPLETE_DOTS='matching'):
dirs = complete_cmd_dirs('cd', '')
with xession.env.swap(COMPLETE_DOTS="matching"):
dirs = complete_cmd_dirs("cd", "")
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
with xonsh_builtins.__xonsh__.env.swap(COMPLETE_DOTS='always'):
dirs = complete_cmd_dirs('cd', '')
with xession.env.swap(COMPLETE_DOTS="always"):
dirs = complete_cmd_dirs("cd", "")
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

View file

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

View file

@ -2,7 +2,11 @@ import pytest
from xonsh.completers.tools import RichCompletion
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(
@ -31,10 +35,15 @@ def test_pip_list_re1(line):
def test_commands():
comps = complete_pip(CompletionContext(CommandContext(
args=(CommandArg("pip3"),), arg_index=1,
prefix="c",
)))
comps = complete_pip(
CompletionContext(
CommandContext(
args=(CommandArg("pip3"),),
arg_index=1,
prefix="c",
)
)
)
assert comps.intersection({"cache", "check", "config"})
for comp in comps:
assert isinstance(comp, RichCompletion)
@ -42,9 +51,14 @@ def test_commands():
def test_package_list():
comps = complete_pip(CompletionContext(CommandContext(
args=(CommandArg("pip3"), CommandArg("show")), arg_index=2,
)))
comps = complete_pip(
CompletionContext(
CommandContext(
args=(CommandArg("pip3"), CommandArg("show")),
arg_index=2,
)
)
)
assert "Package" not in comps
assert "-----------------------------" not 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
def test_xonfig():
assert complete_xonfig(CompletionContext(CommandContext(
args=(CommandArg("xonfig"),), arg_index=1, prefix="-"
))) == {"-h"}
assert complete_xonfig(
CompletionContext(
CommandContext(args=(CommandArg("xonfig"),), arg_index=1, prefix="-")
)
) == {"-h"}
def test_xonfig_colors(monkeypatch):
monkeypatch.setattr("xonsh.tools.color_style_names", lambda: ["blue", "brown", "other"])
assert complete_xonfig(CompletionContext(CommandContext(
args=(CommandArg("xonfig"), CommandArg("colors")), arg_index=2, prefix="b"
))) == {"blue", "brown"}
monkeypatch.setattr(
"xonsh.tools.color_style_names", lambda: ["blue", "brown", "other"]
)
assert (
complete_xonfig(
CompletionContext(
CommandContext(
args=(CommandArg("xonfig"), CommandArg("colors")),
arg_index=2,
prefix="b",
)
)
)
== {"blue", "brown"}
)
def test_xontrib():
assert complete_xontrib(CompletionContext(CommandContext(
args=(CommandArg("xontrib"),), arg_index=1, prefix="l"
))) == {"list", "load"}
assert complete_xontrib(
CompletionContext(
CommandContext(args=(CommandArg("xontrib"),), arg_index=1, prefix="l")
)
) == {"list", "load"}

View file

@ -2,30 +2,21 @@ import builtins
import glob
import os
import sys
import types
import typing as tp
from unittest.mock import MagicMock
import pytest
from xonsh.built_ins import (
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.built_ins import XonshSession, XSH
from xonsh.execer import Execer
from xonsh.jobs import tasks
from xonsh.events import events
from xonsh.platform import ON_WINDOWS
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
@ -35,54 +26,26 @@ def source_path():
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
def xonsh_execer(monkeypatch):
"""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)
builtins.__xonsh__.execer = execer
monkeypatch.setattr(XSH, "execer", 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
@ -107,60 +70,60 @@ def xonsh_events():
def xonsh_builtins(monkeypatch, xonsh_events):
"""Mock out most of the builtins xonsh attributes."""
old_builtins = set(dir(builtins))
execer = getattr(getattr(builtins, "__xonsh__", None), "execer", None)
session = XonshSession(execer=execer, ctx={})
ensure_attached_session(monkeypatch, session)
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
XSH.load(
execer=Execer(unload=False),
ctx={},
)
builtins.__xonsh__.eval_fstring_field = eval_fstring_field
builtins.__xonsh__.history = DummyHistory()
builtins.__xonsh__.subproc_captured_stdout = sp
builtins.__xonsh__.subproc_captured_inject = sp
builtins.__xonsh__.subproc_captured_object = sp
builtins.__xonsh__.subproc_captured_hiddenobject = sp
builtins.__xonsh__.enter_macro = enter_macro
builtins.__xonsh__.completers = None
builtins.__xonsh__.call_macro = call_macro
builtins.__xonsh__.enter_macro = enter_macro
builtins.__xonsh__.path_literal = path_literal
builtins.__xonsh__.builtins = _BuiltIns(execer=execer)
builtins.evalx = eval
builtins.execx = None
builtins.compilex = None
builtins.aliases = {}
# 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.
builtins.events = xonsh_events
if ON_WINDOWS:
XSH.env["PATHEXT"] = [".EXE", ".BAT", ".CMD"]
def locate_binary(self, name):
return os.path.join(os.path.dirname(__file__), "bin", name)
for attr, val in [
("env", DummyEnv()),
("shell", DummyShell()),
("help", lambda x: x),
("aliases", {}),
("exit", False),
("history", DummyHistory()),
# ("subproc_captured", sp),
("subproc_uncaptured", sp),
("subproc_captured_stdout", sp),
("subproc_captured_inject", sp),
("subproc_captured_object", sp),
("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
monkeypatch.delattr(builtins, "__xonsh__", raising=False)
XSH.unload()
for attr in set(dir(builtins)) - old_builtins:
if hasattr(builtins, attr):
delattr(builtins, attr)
tasks.clear() # must to this to enable resetting all_jobs
@pytest.fixture
def xession(xonsh_builtins) -> XonshSession:
return XSH
@pytest.fixture(scope="session")
def completion_context_parse():
return CompletionContextParser().parse

View file

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

View file

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

View file

@ -53,14 +53,14 @@ def test_test_repo(test_repo):
assert test_file.exists()
def test_no_repo(xonsh_builtins, tmpdir):
xonsh_builtins.__xonsh__.env = Env(VC_BRANCH_TIMEOUT=2, PWD=tmpdir)
def test_no_repo(xession, tmpdir):
xession.env = Env(VC_BRANCH_TIMEOUT=2, PWD=tmpdir)
assert vc.get_hg_branch() is None
assert vc.get_git_branch() is None
def test_vc_get_branch(test_repo, xonsh_builtins):
xonsh_builtins.__xonsh__.env = Env(VC_BRANCH_TIMEOUT=2, PWD=test_repo["dir"])
def test_vc_get_branch(test_repo, xession):
xession.env = Env(VC_BRANCH_TIMEOUT=2, PWD=test_repo["dir"])
# get corresponding function from vc module
get_branch = "get_{}_branch".format(test_repo["vc"])
branch = getattr(vc, get_branch)()
@ -84,9 +84,9 @@ current = yellow reverse
assert not branch.startswith(u"\u001b[")
def test_current_branch_calls_locate_binary_for_empty_cmds_cache(xonsh_builtins):
cache = xonsh_builtins.__xonsh__.commands_cache
xonsh_builtins.__xonsh__.env = DummyEnv(VC_BRANCH_TIMEOUT=1)
def test_current_branch_calls_locate_binary_for_empty_cmds_cache(xession):
cache = xession.commands_cache
xession.env = DummyEnv(VC_BRANCH_TIMEOUT=1)
cache.is_empty = Mock(return_value=True)
cache.locate_binary = Mock(return_value="")
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(
xonsh_builtins,
xession,
):
cache = xonsh_builtins.__xonsh__.commands_cache
xonsh_builtins.__xonsh__.env = DummyEnv(VC_BRANCH_TIMEOUT=1)
cache = xession.commands_cache
xession.env = DummyEnv(VC_BRANCH_TIMEOUT=1)
cache.is_empty = Mock(return_value=False)
cache.locate_binary = Mock(return_value="")
# 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
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"])
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
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])
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":
return

View file

@ -57,9 +57,9 @@ def test_eval_recursive(xonsh_execer, xonsh_builtins):
@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()
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"]
@ -151,44 +151,44 @@ def test_subprocess_io_operators(xonsh_execer, xonsh_builtins, alias):
@pytest.mark.parametrize(
"alias",
[
{'echocat': 'ls'},
{"echocat": "ls"},
],
)
def test_dict_merging(xonsh_execer, xonsh_builtins, alias):
ales = make_aliases()
assert (ales | alias)['echocat'] == ['ls']
assert (alias | ales)['echocat'] == ['ls']
assert 'echocat' not in ales
assert (ales | alias)["echocat"] == ["ls"]
assert (alias | ales)["echocat"] == ["ls"]
assert "echocat" not in ales
@pytest.mark.parametrize(
"alias",
[
{'echocat': 'echo Why do people still use python2.7?'},
{'echocat': 'echo Why?'},
{"echocat": "echo Why do people still use python2.7?"},
{"echocat": "echo Why?"},
],
)
def test_dict_merging_assignment(xonsh_execer, xonsh_builtins, alias):
ales = make_aliases()
ales |= alias
assert 'echocat' in ales
assert ' '.join(ales['echocat']) == alias['echocat']
assert "echocat" in ales
assert " ".join(ales["echocat"]) == alias["echocat"]
ales = make_aliases()
alias |= ales
assert 'o' in alias
assert alias['o'] == ales['o']
assert "o" in alias
assert alias["o"] == ales["o"]
def test_exec_alias_args(xonsh_execer, xonsh_builtins):
stack = inspect.stack()
try:
ExecAlias('myargs = $args')(['arg0'], stack=stack)
ExecAlias('myarg0 = $arg0')(['arg0'], stack=stack)
ExecAlias("myargs = $args")(["arg0"], stack=stack)
ExecAlias("myarg0 = $arg0")(["arg0"], stack=stack)
except KeyError:
assert False
assert stack[0][0].f_locals['myargs'] == ['arg0']
assert stack[0][0].f_locals['myarg0'] == 'arg0'
assert stack[0][0].f_locals["myargs"] == ["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`
("rainbow_dash"), # not in `ansi_colors.py`, but in pygments
("foobar"), # invalid, should not fail
]
],
)
def test_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
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"))
cur_wd = os.getcwd()
xonsh_builtins.__xonsh__.env = Env(
xession.env = Env(
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 + '")')
assert os.path.abspath(os.getcwd()) == os.path.abspath(asubdir)
assert os.path.abspath(os.getcwd()) == os.path.abspath(
xonsh_builtins.__xonsh__.env["PWD"]
)
assert "OLDPWD" in xonsh_builtins.__xonsh__.env
assert os.path.abspath(cur_wd) == os.path.abspath(
xonsh_builtins.__xonsh__.env["OLDPWD"]
)
assert os.path.abspath(os.getcwd()) == os.path.abspath(xession.env["PWD"])
assert "OLDPWD" in xession.env
assert os.path.abspath(cur_wd) == os.path.abspath(xession.env["OLDPWD"])
def test_transform(xonsh_builtins):
@xonsh_builtins.events.on_transform_command
def test_transform(xession):
@xession.builtins.events.on_transform_command
def spam2egg(cmd, **_):
if cmd == "spam":
return "egg"

View file

@ -33,10 +33,10 @@ import pytest
(["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."""
from xontrib.bashisms import bash_preproc
xonsh_builtins.__xonsh__.history.inps = history
xession.history.inps = history
obs = bash_preproc(inp)
assert exp == obs

View file

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

View file

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

View file

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

View file

@ -3,7 +3,12 @@ import typing as tp
import pytest
from xonsh.parsers.completion_context import CommandArg, CommandContext, CompletionContextParser, PythonContext
from xonsh.parsers.completion_context import (
CommandArg,
CommandContext,
CompletionContextParser,
PythonContext,
)
DEBUG = False
@ -24,7 +29,9 @@ def 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:
index = commandline.index(X)
commandline = commandline.replace(X, "")
@ -32,7 +39,9 @@ def assert_match(commandline, command_context=MISSING, python_context=MISSING, i
index = len(commandline)
context = parse(commandline, index)
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:
python_context = PythonContext(commandline, index)
if command_context is not MISSING:
@ -48,17 +57,63 @@ COMMAND_EXAMPLES = (
(f"command {X}", CommandContext(args=(CommandArg("command"),), arg_index=1)),
(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, prefix="--")),
(f"command a {X}", CommandContext(args=(CommandArg("command"), CommandArg("a")), arg_index=2)),
(f"command a b{X}", 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")),
(
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 a b{X}",
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 = (
@ -69,25 +124,100 @@ EMPTY_COMMAND_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 and{X}'", CommandContext(
args=(), arg_index=0, prefix="comm and", suffix="", 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)),
(
f"'comm an{X}d'",
CommandContext(
args=(),
arg_index=0,
prefix="comm an",
suffix="d",
opening_quote="'",
closing_quote="'",
),
),
(
f"'comm and{X}'",
CommandContext(
args=(),
arg_index=0,
prefix="comm and",
suffix="",
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
@ -99,10 +229,14 @@ def test_command(commandline, context):
assert_match(commandline, context, is_main_command=True)
@pytest.mark.parametrize("commandline, context", tuple(
(commandline, context) for commandline, context in STRING_ARGS_EXAMPLES
if commandline.endswith("'") or commandline.endswith('"')
))
@pytest.mark.parametrize(
"commandline, context",
tuple(
(commandline, context)
for commandline, context in STRING_ARGS_EXAMPLES
if commandline.endswith("'") or commandline.endswith('"')
),
)
def test_partial_string_arg(commandline, context):
partial_commandline = commandline.rstrip("\"'")
partial_context = context._replace(closing_quote="")
@ -112,50 +246,147 @@ def test_partial_string_arg(commandline, context):
CONT = "\\" "\n"
@pytest.mark.parametrize("commandline, context", (
@pytest.mark.parametrize(
"commandline, context",
(
# line continuations:
(f"echo {CONT}a {X}", CommandContext(args=(CommandArg("echo"), CommandArg("a")), arg_index=2)),
(f"echo {CONT}{X}a {CONT} b",
CommandContext(args=(CommandArg("echo"), CommandArg("b")), arg_index=1, suffix="a")),
(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")),
(
f"echo {CONT}a {X}",
CommandContext(args=(CommandArg("echo"), CommandArg("a")), arg_index=2),
),
(
f"echo {CONT}{X}a {CONT} b",
CommandContext(
args=(CommandArg("echo"), CommandArg("b")), arg_index=1, suffix="a"
),
),
(
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:
(f"echo 'a{CONT}{X}b'",
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="'''",
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="'''")),
(
f"echo 'a{CONT}{X}b'",
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="'''",
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:
(f"echo '''a\nb{X}\nc'''", CommandContext(
args=(CommandArg("echo"),), arg_index=1,
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="'''")),
(
f"echo '''a\nb{X}\nc'''",
CommandContext(
args=(CommandArg("echo"),),
arg_index=1,
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:
(f"echo '''a\nb{X}\nc", CommandContext(
args=(CommandArg("echo"),), arg_index=1,
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="'''")),
))
(
f"echo '''a\nb{X}\nc",
CommandContext(
args=(CommandArg("echo"),),
arg_index=1,
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):
assert_match(commandline, context, is_main_command=True)
@ -172,15 +403,34 @@ NESTING_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((
# 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)))
@pytest.mark.parametrize(
"nesting, commandline, context",
list(
itertools.chain(
(
# 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):
nested_commandline = nesting.replace(X, commandline)
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 = (
# nesting, subcmd_opening
(f"echo $(a $({X}", "$("),
(f"echo $(a $(b; {X}", ""),
(f"$(echo $(a $({X}", "$("),
(f"echo $[a $({X}]", "$("),
(f"echo $(a $[{X})", "$["),
(f"echo @(x = $({X}", "$("),
(f"echo @(a; x = $({X}", "$("),
(f"echo @(x = $(a; {X}", ""),
(f"echo $(a $({X}", "$("),
(f"echo $(a $(b; {X}", ""),
(f"$(echo $(a $({X}", "$("),
(f"echo $[a $({X}]", "$("),
(f"echo $(a $[{X})", "$["),
(f"echo @(x = $({X}", "$("),
(f"echo @(a; x = $({X}", "$("),
(f"echo @(x = $(a; {X}", ""),
)
@pytest.mark.parametrize("nesting, subcmd_opening", MALFORMED_SUBCOMMANDS_NESTINGS)
@pytest.mark.parametrize("commandline, context", COMMAND_EXAMPLES[:5])
def test_multiple_malformed_subcmds(nesting, subcmd_opening, commandline, context):
@ -228,7 +479,7 @@ def test_other_subcommand_arg():
assert_match(
command,
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"
# index inside the subproc
assert_match(command, CommandContext(
(), arg_index=0, prefix="pwd", subcmd_opening="$("), python_context=None)
assert_match(
command,
CommandContext((), arg_index=0, prefix="pwd", subcmd_opening="$("),
python_context=None,
)
# index at the end of the command
assert_match(command.replace(X, ""), CommandContext(
(CommandArg("echo"),), arg_index=1, prefix="file=$(pwd)/x"), is_main_command=True)
assert_match(
command.replace(X, ""),
CommandContext((CommandArg("echo"),), arg_index=1, prefix="file=$(pwd)/x"),
is_main_command=True,
)
SUBCMD_BORDER_EXAMPLES = (
@ -269,49 +526,71 @@ MULTIPLE_COMMAND_KEYWORDS = (
)
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(
zip(COMMAND_EXAMPLES, COMMAND_EXAMPLES[::-1]),
zip(COMMAND_EXAMPLES, EMPTY_COMMAND_EXAMPLES),
zip(EMPTY_COMMAND_EXAMPLES, COMMAND_EXAMPLES),
zip(EMPTY_COMMAND_EXAMPLES, EMPTY_COMMAND_EXAMPLES),
))
EXTENSIVE_COMMAND_PAIRS = tuple(
itertools.chain(
zip(COMMAND_EXAMPLES, COMMAND_EXAMPLES[::-1]),
zip(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(
(
# cursor in first command
((first, second.replace(X, "")), first_context)
for (first, first_context), (second, second_context) in EXTENSIVE_COMMAND_PAIRS
),
(
# cursor in second command
((first.replace(X, ""), second), second_context)
for (first, first_context), (second, second_context) in EXTENSIVE_COMMAND_PAIRS
),
(
# cursor in middle command
((first.replace(X, ""), second, third.replace(X, "")), second_context)
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])
),
))
MULTIPLE_COMMAND_EXTENSIVE_EXAMPLES = tuple(
itertools.chain(
(
# cursor in first command
((first, second.replace(X, "")), first_context)
for (first, first_context), (
second,
second_context,
) in EXTENSIVE_COMMAND_PAIRS
),
(
# cursor in second command
((first.replace(X, ""), second), second_context)
for (first, first_context), (
second,
second_context,
) in EXTENSIVE_COMMAND_PAIRS
),
(
# cursor in middle command
((first.replace(X, ""), second, third.replace(X, "")), second_context)
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(
(
(MULTIPLE_COMMAND_KEYWORDS[0], commands, context)
for commands, context in MULTIPLE_COMMAND_EXTENSIVE_EXAMPLES
@pytest.mark.parametrize(
"keyword, commands, context",
tuple(
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):
joined_command = keyword.join(commands)
@ -320,7 +599,11 @@ def test_multiple_commands(keyword, commands, context):
relative_index = cursor_command.index(X)
else:
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(" "):
# the last space is part of the command
relative_index += 1
@ -329,24 +612,35 @@ def test_multiple_commands(keyword, commands, context):
assert_match(joined_command, context, is_main_command=True)
@pytest.mark.parametrize("commandline", (
f"{X};",
f"; {X}",
f"{X};;",
f"; {X};",
f";; {X}",
f";;; {X}",
))
@pytest.mark.parametrize(
"commandline",
(
f"{X};",
f"; {X}",
f"{X};;",
f"; {X};",
f";; {X}",
f";;; {X}",
),
)
def test_multiple_empty_commands(commandline):
assert_match(commandline, CommandContext((), 0), is_main_command=True)
@pytest.mark.parametrize("nesting, keyword, commands, context", tuple(
(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
))
@pytest.mark.parametrize(
"nesting, keyword, commands, context",
tuple(
(
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):
joined_command = keyword.join(commands)
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():
assert_match(f"echo hi; echo $(ls{X})",
CommandContext((), 0, prefix="ls", subcmd_opening="$("),
python_context=None)
assert_match(
f"echo hi; echo $(ls{X})",
CommandContext((), 0, prefix="ls", subcmd_opening="$("),
python_context=None,
)
@pytest.mark.parametrize("commandline, context", tuple(
(commandline, context) for commandline, context in STRING_ARGS_EXAMPLES
if commandline.endswith("'") or commandline.endswith('"')
))
@pytest.mark.parametrize(
"commandline, context",
tuple(
(commandline, context)
for commandline, context in STRING_ARGS_EXAMPLES
if commandline.endswith("'") or commandline.endswith('"')
),
)
def test_multiple_partial_string_arg(commandline, context):
partial_commandline = commandline.rstrip("\"'")
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)
@pytest.mark.parametrize("nesting, keyword, commands, context", tuple(
(nesting, keyword, commands, context)
for nesting, prefix in NESTING_EXAMPLES[:1]
for keyword, commands, context in MULTIPLE_CMD_SIMPLE_EXAMPLES[:1]
))
@pytest.mark.parametrize(
"nesting, keyword, commands, context",
tuple(
(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)
def test_malformed_subcmd(malformation, nesting, keyword, commands, context):
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)
MULTIPLE_COMMAND_BORDER_EXAMPLES = tuple(itertools.chain(
itertools.chain(*(
MULTIPLE_COMMAND_BORDER_EXAMPLES = tuple(
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")),
) for ws1, ws2, kwd in itertools.product(("", " "), ("", " "), ("&&", ";"))
)),
# all keywords are treated as a normal arg if the cursor is at the edge
(
(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="||")),
),
# 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 {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="||"),
),
),
# 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="&"
),
),
),
)
))
)
@pytest.mark.parametrize("commandline, context", tuple(itertools.chain(
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
@pytest.mark.parametrize(
"commandline, context",
tuple(
itertools.chain(
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):
assert_match(commandline, context)
@ -433,52 +769,69 @@ PYTHON_NESTING_EXAMPLES = (
)
@pytest.mark.parametrize("nesting, commandline, context", list(itertools.chain((
# complex subcommand in a simple nested expression
(nesting, commandline, context._replace(is_sub_expression=True))
for nesting in PYTHON_NESTING_EXAMPLES[:1]
for commandline, context in PYTHON_EXAMPLES
), (
# 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]
))))
@pytest.mark.parametrize(
"nesting, commandline, context",
list(
itertools.chain(
(
# complex subcommand in a simple nested expression
(nesting, commandline, context._replace(is_sub_expression=True))
for nesting in PYTHON_NESTING_EXAMPLES[:1]
for commandline, context in PYTHON_EXAMPLES
),
(
# 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):
nested_commandline = nesting.replace(X, commandline)
assert_match(nested_commandline, command_context=None, python_context=context)
@pytest.mark.parametrize("commandline, context", [
(commandline.replace("$", "@"), context._replace(
prefix=context.prefix.replace("$", "@"),
suffix=context.suffix.replace("$", "@"),
))
for commandline, context in SUBCMD_BORDER_EXAMPLES
])
@pytest.mark.parametrize(
"commandline, context",
[
(
commandline.replace("$", "@"),
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):
assert_match(commandline, context, is_main_command=True)
@pytest.mark.parametrize("code", (
f"""
@pytest.mark.parametrize(
"code",
(
f"""
x = 3
x.{X}""",
f"""
f"""
x = 3;
y = 4;
x.{X}""",
f"""
f"""
def func({X}):
return 100
""",
f"""
f"""
class A:
def a():
return "a{X}"
pass
exit()
""",
))
),
)
def test_multiline_python(code):
assert_match(code, is_main_command=True)

View file

@ -23,24 +23,24 @@ def chdir(adir):
os.chdir(old_dir)
def test_simple(xonsh_builtins):
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=PARENT)
def test_simple(xession):
xession.env = Env(CDPATH=PARENT, PWD=PARENT)
with chdir(PARENT):
assert os.getcwd() != HERE
dirstack.cd(["tests"])
assert os.getcwd() == HERE
def test_cdpath_simple(xonsh_builtins):
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE)
def test_cdpath_simple(xession):
xession.env = Env(CDPATH=PARENT, PWD=HERE)
with chdir(os.path.normpath("/")):
assert os.getcwd() != HERE
dirstack.cd(["tests"])
assert os.getcwd() == HERE
def test_cdpath_collision(xonsh_builtins):
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE)
def test_cdpath_collision(xession):
xession.env = Env(CDPATH=PARENT, PWD=HERE)
sub_tests = os.path.join(HERE, "tests")
if not os.path.exists(sub_tests):
os.mkdir(sub_tests)
@ -50,8 +50,8 @@ def test_cdpath_collision(xonsh_builtins):
assert os.getcwd() == os.path.join(HERE, "tests")
def test_cdpath_expansion(xonsh_builtins):
xonsh_builtins.__xonsh__.env = Env(HERE=HERE, CDPATH=("~", "$HERE"))
def test_cdpath_expansion(xession):
xession.env = Env(HERE=HERE, CDPATH=("~", "$HERE"))
test_dirs = (
os.path.join(HERE, "xonsh-test-cdpath-here"),
os.path.expanduser("~/xonsh-test-cdpath-home"),
@ -69,13 +69,13 @@ def test_cdpath_expansion(xonsh_builtins):
os.rmdir(d)
def test_cdpath_events(xonsh_builtins, tmpdir):
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=os.getcwd())
def test_cdpath_events(xession, tmpdir):
xession.env = Env(CDPATH=PARENT, PWD=os.getcwd())
target = str(tmpdir)
ev = None
@xonsh_builtins.events.on_chdir
@xession.builtins.events.on_chdir
def handler(olddir, newdir, **kw):
nonlocal ev
ev = olddir, newdir
@ -92,8 +92,8 @@ def test_cdpath_events(xonsh_builtins, tmpdir):
os.chdir(old_dir)
def test_cd_autopush(xonsh_builtins, tmpdir):
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=os.getcwd(), AUTO_PUSHD=True)
def test_cd_autopush(xession, tmpdir):
xession.env = Env(CDPATH=PARENT, PWD=os.getcwd(), AUTO_PUSHD=True)
target = str(tmpdir)
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
def test_pushdpopd(xonsh_builtins):
"""Simple non-UNC push/pop to verify we didn't break nonUNC case.
"""
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE)
def test_pushdpopd(xession):
"""Simple non-UNC push/pop to verify we didn't break nonUNC case."""
xession.env = Env(CDPATH=PARENT, PWD=HERE)
dirstack.cd([PARENT])
owd = os.getcwd()
assert owd.casefold() == xonsh_builtins.__xonsh__.env["PWD"].casefold()
assert owd.casefold() == xession.env["PWD"].casefold()
dirstack.pushd([HERE])
wd = os.getcwd()
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"
def test_cd_dot(xonsh_builtins):
xonsh_builtins.__xonsh__.env = Env(PWD=os.getcwd())
def test_cd_dot(xession):
xession.env = Env(PWD=os.getcwd())
owd = os.getcwd().casefold()
dirstack.cd(["."])
@ -111,13 +110,13 @@ def test_cd_dot(xonsh_builtins):
@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:
return
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE)
xession.env = Env(CDPATH=PARENT, PWD=HERE)
dirstack.cd([PARENT])
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"])
wd = os.getcwd()
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")
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:
return
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE)
xession.env = Env(CDPATH=PARENT, PWD=HERE)
dirstack.cd([PARENT])
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"])
wd = os.getcwd()
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")
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]
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:
return
xonsh_builtins.__xonsh__.env = Env(CDPATH=PARENT, PWD=HERE)
xession.env = Env(CDPATH=PARENT, PWD=HERE)
dirstack.cd([PARENT])
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"])
assert os.getcwd().casefold() == TEMP_DRIVE[0] + "\\"
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")
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"""
pass
@ -280,16 +279,16 @@ def with_unc_check_disabled(): # just like the above, but value is 1 to *disabl
@pytest.fixture()
def xonsh_builtins_cd(xonsh_builtins):
xonsh_builtins.__xonsh__.env["CDPATH"] = PARENT
xonsh_builtins.__xonsh__.env["PWD"] = os.getcwd()
xonsh_builtins.__xonsh__.env["DIRSTACK_SIZE"] = 20
return xonsh_builtins
def xonsh_builtins_cd(xession):
xession.env["CDPATH"] = PARENT
xession.env["PWD"] = os.getcwd()
xession.env["DIRSTACK_SIZE"] = 20
return xession
@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):
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"])
if rc != 0:
return

View file

@ -151,7 +151,7 @@ def test_swap_exception_replacement():
@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")
with TemporaryDirectory() as tmpdir:
tmpdir = os.path.realpath(tmpdir)
@ -159,10 +159,8 @@ def test_locate_binary_on_windows(xonsh_builtins):
fpath = os.path.join(tmpdir, fname)
with open(fpath, "w") as f:
f.write(fpath)
xonsh_builtins.__xonsh__.env.update(
{"PATH": [tmpdir], "PATHEXT": [".COM", ".EXE", ".BAT"]}
)
xonsh_builtins.__xonsh__.commands_cache = CommandsCache()
xession.env.update({"PATH": [tmpdir], "PATHEXT": [".COM", ".EXE", ".BAT"]})
xession.commands_cache = CommandsCache()
assert locate_binary("file1") == 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")
@ -170,13 +168,13 @@ def test_locate_binary_on_windows(xonsh_builtins):
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)
xonsh_builtins.__xonsh__.env = env
xession.env = env
share = []
# register
@xonsh_builtins.events.on_envvar_change
@xession.builtins.events.on_envvar_change
def handler(name, oldvalue, newvalue, **kwargs):
share.extend((name, oldvalue, newvalue))
@ -186,13 +184,13 @@ def test_event_on_envvar_change(xonsh_builtins):
assert share == ["TEST", 0, 1]
def test_event_on_envvar_new(xonsh_builtins):
def test_event_on_envvar_new(xession):
env = Env()
xonsh_builtins.__xonsh__.env = env
xession.env = env
share = []
# register
@xonsh_builtins.events.on_envvar_new
@xession.builtins.events.on_envvar_new
def handler(name, value, **kwargs):
share.extend((name, value))
@ -202,13 +200,13 @@ def test_event_on_envvar_new(xonsh_builtins):
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)
xonsh_builtins.__xonsh__.env = env
xession.env = env
share = []
# register
@xonsh_builtins.events.on_envvar_change
@xession.builtins.events.on_envvar_change
def handler(name, oldvalue, newvalue, **kwargs):
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"])
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)
xonsh_builtins.__xonsh__.env = env
xession.env = env
share = []
# register
@xonsh_builtins.events.on_envvar_change
@xession.builtins.events.on_envvar_change
def handler(name, oldvalue, newvalue, **kwargs):
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 == []
def test_events_on_envvar_called_in_right_order(xonsh_builtins):
def test_events_on_envvar_called_in_right_order(xession):
env = Env()
xonsh_builtins.__xonsh__.env = env
xession.env = env
share = []
# register
@xonsh_builtins.events.on_envvar_new
@xession.builtins.events.on_envvar_new
def handler(name, value, **kwargs):
share[:] = ["new"]
@xonsh_builtins.events.on_envvar_change
@xession.builtins.events.on_envvar_change
def handler1(name, oldvalue, newvalue, **kwargs):
share[:] = ["change"]
@ -320,13 +318,13 @@ def test_lscolors_target(xonsh_builtins):
("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")
# corresponding colors: [('RESET',), ('BOLD_CYAN',), ('BOLD_CYAN',), ('BACKGROUND_BLACK', 'YELLOW')]
event_fired = False
@xonsh_builtins.events.on_lscolors_change
@xession.builtins.events.on_lscolors_change
def handler(key, oldvalue, newvalue, **kwargs):
nonlocal old_in, new_in, key_in, event_fired
assert (
@ -334,7 +332,7 @@ def test_lscolors_events(key_in, old_in, new_in, test, xonsh_builtins):
), "Old and new event values match"
event_fired = True
xonsh_builtins.__xonsh__.env["LS_COLORS"] = lsc
xession.env["LS_COLORS"] = lsc
if new_in is None:
lsc.pop(key_in, "argle")

View file

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

View file

@ -5,16 +5,17 @@
from xonsh.history.dummy import DummyHistory
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)
def test_construct_history_class(xonsh_builtins):
xonsh_builtins.__xonsh__.env["XONSH_HISTORY_BACKEND"] = DummyHistory
def test_construct_history_class(xession):
xession.env["XONSH_HISTORY_BACKEND"] = DummyHistory
assert isinstance(construct_history(), DummyHistory)
def test_construct_history_instance(xonsh_builtins):
xonsh_builtins.__xonsh__.env["XONSH_HISTORY_BACKEND"] = DummyHistory()
def test_construct_history_instance(xession):
xession.env["XONSH_HISTORY_BACKEND"] = DummyHistory()
assert isinstance(construct_history(), DummyHistory)

View file

@ -23,24 +23,22 @@ IGNORE_OPTS = ",".join(["ignoredups", "ignoreerr", "ignorespace"])
@pytest.fixture
def hist():
h = JsonHistory(
filename="xonsh-HISTORY-TEST.json", here="yup", sessionid="SESSIONID", gc=False
)
def hist(tmpdir, xession):
file = tmpdir / "xonsh-HISTORY-TEST.json"
h = JsonHistory(filename=str(file), here="yup", sessionid="SESSIONID", gc=False)
yield h
os.remove(h.filename)
def test_hist_init(hist):
def test_hist_init(hist, xession):
"""Test initialization of the shell history."""
with LazyJSON(hist.filename) as lj:
obs = lj["here"]
assert "yup" == obs
def test_hist_append(hist, xonsh_builtins):
def test_hist_append(hist, xession):
"""Verify appending to the history works."""
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.env["HISTCONTROL"] = set()
hf = hist.append({"inp": "still alive", "rtn": 0})
assert hf is None
assert "still alive" == hist.buffer[0]["inp"]
@ -56,11 +54,11 @@ def test_hist_append(hist, xonsh_builtins):
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."""
hf = hist.flush()
assert hf is None
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.env["HISTCONTROL"] = set()
hist.append({"inp": "still alive?", "rtn": 0, "out": "yes"})
hf = hist.flush()
assert hf is not None
@ -73,12 +71,12 @@ def test_hist_flush(hist, xonsh_builtins):
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."""
hf = hist.flush()
assert hf is None
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xonsh_builtins.__xonsh__.env["XONSH_STORE_STDOUT"] = True
xession.env["HISTCONTROL"] = set()
xession.env["XONSH_STORE_STDOUT"] = True
hist.append({"inp": "still alive?", "rtn": 0, "out": "yes"})
hf = hist.flush()
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"
def test_hist_flush_with_store_cwd(hist, xonsh_builtins):
def test_hist_flush_with_store_cwd(hist, xession):
hf = hist.flush()
assert hf is None
@ -109,14 +107,14 @@ def test_hist_flush_with_store_cwd(hist, xonsh_builtins):
with LazyJSON(hist.filename) as lj:
assert len(lj["cmds"]) == 2
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."""
hf = hist.flush()
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": 1})
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]
def test_cmd_field(hist, xonsh_builtins):
def test_cmd_field(hist, xession):
# in-memory
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.env["HISTCONTROL"] = set()
hf = hist.append({"inp": "ls foo", "rtn": 1})
assert hf is None
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)),
],
)
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."""
base_idx, step = offset
xonsh_builtins.__xonsh__.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.history = hist
xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history
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
def test_histcontrol(hist, xonsh_builtins):
def test_histcontrol(hist, xession):
"""Test HISTCONTROL=ignoredups,ignoreerr,ignorespacee"""
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = IGNORE_OPTS
xession.env["HISTCONTROL"] = IGNORE_OPTS
assert len(hist.buffer) == 0
# An error, buffer remains empty
@ -324,8 +322,8 @@ def test_parser_show(args, exp):
),
],
)
def test_history_getitem(index, exp, hist, xonsh_builtins):
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
def test_history_getitem(index, exp, hist, xession):
xession.env["HISTCONTROL"] = set()
attrs = ("inp", "out", "rtn", "ts")
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
# we can't spend more than five hours executing the tests.
MAX_RUNTIME = 30 * 60
MIN_DIFF = min(HISTORY_FILES_LIST[i+1][0] - HISTORY_FILES_LIST[i][0]
for i in range(len(HISTORY_FILES_LIST) - 1))
MIN_DIFF = min(
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
@ -493,9 +493,7 @@ assert MAX_RUNTIME < MIN_DIFF / 2
),
],
)
def test__xhj_gc_xx_to_rmfiles(
fn, hsize, in_files, exp_size, exp_files, xonsh_builtins
):
def test__xhj_gc_xx_to_rmfiles(fn, hsize, in_files, exp_size, exp_files, xession):
act_size, act_files = fn(hsize, in_files)
@ -510,63 +508,63 @@ def test__xhj_gc_xx_to_rmfiles(
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."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xession.history = hist
xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history
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"])
out, err = capsys.readouterr()
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."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xession.history = hist
xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history
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"])
out, err = capsys.readouterr()
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
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."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xession.history = hist
xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history
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(["on"])
out, err = capsys.readouterr()
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
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)
def test_hist_append(hist, xonsh_builtins):
def test_hist_append(hist, xession):
"""Verify appending to the history works."""
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.env["HISTCONTROL"] = set()
hf = hist.append({"inp": "still alive", "rtn": 1})
assert hf is None
items = list(hist.items())
@ -36,8 +36,8 @@ def test_hist_append(hist, xonsh_builtins):
assert list(hist.all_items()) == items
def test_hist_attrs(hist, xonsh_builtins):
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
def test_hist_attrs(hist, xession):
xession.env["HISTCONTROL"] = set()
hf = hist.append({"inp": "ls foo", "rtn": 1})
assert hf is None
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)),
],
)
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."""
base_idx, step = offset
xonsh_builtins.__xonsh__.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.history = hist
xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history
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
def test_histcontrol(hist, xonsh_builtins):
def test_histcontrol(hist, xession):
"""Test HISTCONTROL=ignoredups,ignoreerr"""
ignore_opts = ",".join(["ignoredups", "ignoreerr", "ignorespace"])
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = ignore_opts
xession.env["HISTCONTROL"] = ignore_opts
assert len(hist) == 0
# An error, items() remains empty
@ -186,10 +186,10 @@ def test_histcontrol(hist, xonsh_builtins):
assert 0 == hist.rtns[-1]
def test_histcontrol_erase_dup(hist, xonsh_builtins):
def test_histcontrol_erase_dup(hist, xession):
"""Test HISTCONTROL=erasedups"""
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = "erasedups"
xession.env["HISTCONTROL"] = "erasedups"
assert len(hist) == 0
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):
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xonsh_builtins.__xonsh__.env["XONSH_STORE_STDOUT"] = True
def test_history_getitem(index, exp, hist, xession):
xession.env["HISTCONTROL"] = set()
xession.env["XONSH_STORE_STDOUT"] = True
attrs = ("inp", "out", "rtn", "ts")
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
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."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xession.history = hist
xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history
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"])
out, err = capsys.readouterr()
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."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xession.history = hist
xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history
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"])
out, err = capsys.readouterr()
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
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."""
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xonsh_builtins.__xonsh__.history = hist
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = set()
xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
xession.history = hist
xession.env["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history
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(["on"])
out, err = capsys.readouterr()
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
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.append({"inp": "# saving with cwd", "rtn": 0, "out": "yes", "cwd": "/tmp"})
hist.save_cwd = False
@ -304,4 +304,4 @@ def test_hist_store_cwd(hist, xonsh_builtins):
cmds = [i for i in hist.all_items()]
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 -*-
"""Testing xonsh import hooks"""
import os
import builtins
from importlib import import_module
import pytest
@ -9,17 +8,17 @@ import pytest
from xonsh import imphooks
from xonsh.execer import Execer
from xonsh.environ import Env
from xonsh.built_ins import unload_builtins
from xonsh.built_ins import XSH
imphooks.install_import_hooks()
@pytest.fixture(autouse=True)
def imp_env(xonsh_builtins):
def imp_env(xession):
Execer(unload=False)
builtins.__xonsh__.env = Env({"PATH": [], "PATHEXT": []})
xession.env = Env({"PATH": [], "PATHEXT": []})
yield
unload_builtins()
XSH.unload()
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
@pytest.mark.parametrize("case", ALL_PLATFORMS)
def test_script(case):
@ -517,12 +521,6 @@ def test_script(case):
assert exp_out == out
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 = [
# test redirecting a function alias
@ -557,7 +555,11 @@ def test_script_stderr(case):
("pwd", None, lambda: os.getcwd() + "\n"),
("echo WORKING", None, "WORKING\n"),
("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):
@ -685,7 +687,9 @@ def test_xonsh_no_close_fds():
@skip_if_no_xonsh
@pytest.mark.parametrize(
"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):
"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
@pytest.fixture(autouse=True)
def setup(monkeypatch):
global XonshKernel
@ -17,15 +18,17 @@ def setup(monkeypatch):
monkeypatch.setitem(sys.modules, "zmq.eventloop", MagicMock())
monkeypatch.setitem(sys.modules, "zmq.error", MagicMock())
import xonsh.jupyter_kernel
XonshKernel = xonsh.jupyter_kernel.XonshKernel
@pytest.mark.parametrize(
"code, index, expected_args",
EXPANSION_CASES
)
@pytest.mark.parametrize("code, index, expected_args", EXPANSION_CASES)
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.complete.return_value = set(), 0
@ -33,12 +36,15 @@ def test_completion_alias_expansion(
kernel = MagicMock()
kernel.completer = xonsh_completer_mock
monkeypatch.setattr("builtins.aliases", Aliases(gb=["git branch"]))
monkeypatch.setattr(xonsh_builtins.__xonsh__.shell, "ctx", None, raising=False)
monkeypatch.setattr(xession, "aliases", Aliases(gb=["git branch"]))
monkeypatch.setattr(xession.shell, "ctx", None, raising=False)
XonshKernel.do_complete(kernel, code, index)
mock_call = xonsh_completer_mock.complete.call_args
args, kwargs = mock_call
expected_args["self"] = 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
@pytest.mark.parametrize("s", (
"()", # sanity
"(",
")",
"))",
"'string\nliteral",
"'''string\nliteral",
"string\nliteral'",
"\"",
"'",
"\"\"\"",
))
@pytest.mark.parametrize(
"s",
(
"()", # sanity
"(",
")",
"))",
"'string\nliteral",
"'''string\nliteral",
"string\nliteral'",
'"',
"'",
'"""',
),
)
def test_tolerant_lexer(s):
lexer = Lexer(tolerant=True)
lexer.input(s)

View file

@ -20,59 +20,55 @@ def Shell(*args, **kwargs):
@pytest.fixture
def shell(xonsh_builtins, monkeypatch):
def shell(xession, monkeypatch):
"""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()
Shell.shell_type_aliases = {"rl": "readline"}
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)
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"])
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"'])
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"])
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"])
assert builtins.__xonsh__.env.get("TEST1") == "1616"
assert builtins.__xonsh__.env.get("TEST2") == "LOL"
assert xession.env.get("TEST1") == "1616"
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.setitem(os.environ, "XONSH_CACHE_SCRIPTS", "False")
f = tmpdir.join("wakkawakka")
f.write("print('hi')")
args = xonsh.main.premain(["--rc", f.strpath])
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(
ON_WINDOWS and sys.version[:3] == "3.8", reason="weird failure on py38+windows",
)
def test_rc_with_modules(shell, tmpdir, monkeypatch, capsys):
ON_WINDOWS and sys.version[:3] == "3.8",
reason="weird failure on py38+windows",
)
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."""
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 *")
xonsh.main.premain(["--rc", rc.strpath])
assert rc.strpath in builtins.__xonsh__.env.get("XONSHRC")
assert rc.strpath in xession.env.get("XONSHRC")
assert (
builtins.__xonsh__.env.get("LOADED_RC_FILES")[
builtins.__xonsh__.env.get("XONSHRC").index(rc.strpath)
]
xession.env.get("LOADED_RC_FILES")[xession.env.get("XONSHRC").index(rc.strpath)]
is True
)
@ -130,7 +124,10 @@ def test_rcdir_empty(shell, tmpdir, monkeypatch, capsys):
rcdir = tmpdir.join("rc.d")
rcdir.mkdir()
rc = tmpdir.join("rc.xsh")
rc.write_binary(b"")
monkeypatch.setattr(sys.stdin, "isatty", lambda: True)
monkeypatch.setitem(os.environ, "XONSHRC", str(rc))
monkeypatch.setitem(os.environ, "XONSHRC_DIR", str(rcdir))
xonsh.main.premain([])
@ -241,7 +238,7 @@ def test_script_startup(shell, tmpdir, monkeypatch, capsys, args, expected):
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"""
rcdir = tmpdir.join("rc.d")
@ -255,11 +252,11 @@ def test_rcdir_ignored_with_rc(shell, tmpdir, monkeypatch, capsys):
stdout, stderr = capsys.readouterr()
assert "RCDIR" not 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")
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."""
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!')")
xonsh.main.premain(["--rc", rc.strpath])
assert rc.strpath in builtins.__xonsh__.env.get("XONSHRC")
assert rc.strpath in xession.env.get("XONSHRC")
assert (
builtins.__xonsh__.env.get("LOADED_RC_FILES")[
builtins.__xonsh__.env.get("XONSHRC").index(rc.strpath)
]
xession.env.get("LOADED_RC_FILES")[xession.env.get("XONSHRC").index(rc.strpath)]
is True
)
@ -285,7 +280,7 @@ def test_rc_with_modified_path(shell, tmpdir, monkeypatch, capsys):
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 ."""
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 *")
xonsh.main.premain(["--rc", rc.strpath])
assert rc.strpath in builtins.__xonsh__.env.get("XONSHRC")
assert rc.strpath in xession.env.get("XONSHRC")
assert (
builtins.__xonsh__.env.get("LOADED_RC_FILES")[
builtins.__xonsh__.env.get("XONSHRC").index(rc.strpath)
]
xession.env.get("LOADED_RC_FILES")[xession.env.get("XONSHRC").index(rc.strpath)]
is False
)
@ -317,12 +310,12 @@ def test_no_rc_with_script(shell, tmpdir):
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"])
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
should run interactively
"""
@ -331,7 +324,7 @@ def test_force_interactive_custom_rc_with_script(shell, tmpdir, monkeypatch):
f.write("print('hi')")
args = xonsh.main.premain(["-i", "--rc", f.strpath, "tests/sample.xsh"])
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):
@ -344,23 +337,23 @@ def test_custom_rc_with_script(shell, tmpdir):
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"])
assert not builtins.__xonsh__.env.get("XONSHRC")
assert not builtins.__xonsh__.env.get("XONSHRC_DIR")
assert not xession.env.get("XONSHRC")
assert not xession.env.get("XONSHRC_DIR")
@pytest.mark.parametrize(
"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])
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"])
assert builtins.__xonsh__.env.get("XONSH_INTERACTIVE")
assert xession.env.get("XONSH_INTERACTIVE")
@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 xonsh.parsers.completion_context import CompletionContext, CommandContext, CommandArg
from xonsh.parsers.completion_context import (
CompletionContext,
CommandContext,
CommandArg,
)
@skip_if_on_windows
def test_man_completion(monkeypatch, tmpdir, xonsh_builtins):
def test_man_completion(monkeypatch, tmpdir, xession):
tempdir = tmpdir.mkdir("test_man")
monkeypatch.setitem(
os.environ, "MANPATH", os.path.dirname(os.path.abspath(__file__))
)
xonsh_builtins.__xonsh__.env.update({"XONSH_DATA_DIR": str(tempdir)})
completions = complete_from_man(CompletionContext(
CommandContext(args=(CommandArg("yes"),), arg_index=1, prefix="--")
))
xession.env.update({"XONSH_DATA_DIR": str(tempdir)})
completions = complete_from_man(
CompletionContext(
CommandContext(args=(CommandArg("yes"),), arg_index=1, prefix="--")
)
)
assert "--version" in completions
assert "--help" in completions

View file

@ -1,15 +1,13 @@
# -*- coding: utf-8 -*-
"""Tests the xonsh parser."""
import ast
import builtins
import logging
import textwrap
import itertools
import traceback
import pytest
from xonsh.ast import AST, With, Pass, Str, Call
from xonsh.built_ins import XSH
from xonsh.parser import Parser
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):
builtins.__xonsh__.env = xenv
XSH.env = xenv
obs = PARSER.parse(inp, debug_level=debug_level)
if obs is None:
return # comment only
@ -169,7 +167,7 @@ def test_fstring_adaptor(inp, exp):
assert isinstance(joined_str_node, ast.JoinedStr)
node = ast.Expression(body=joined_str_node)
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)
assert exp == obs

View file

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

View file

@ -4,41 +4,67 @@ Tests for command pipelines.
import os
import pytest
import builtins
from xonsh.platform import ON_WINDOWS
from xonsh.procs.pipelines import CommandPipeline
from tests.tools import skip_if_on_windows, skip_if_on_unix
from xonsh.built_ins import XSH
@pytest.fixture(autouse=True)
def patched_events(monkeypatch, xonsh_events, xonsh_execer):
from xonsh.jobs import tasks
tasks.clear()
# needed for ci tests
monkeypatch.setattr('builtins.events', xonsh_events, raising=False)
monkeypatch.setitem(builtins.__xonsh__.env, 'RAISE_SUBPROC_ERROR', False) # for the failing `grep` commands
monkeypatch.setitem(
XSH.env, "RAISE_SUBPROC_ERROR", False
) # for the failing `grep` commands
if ON_WINDOWS:
monkeypatch.setattr('builtins.aliases', {
"echo": "cmd /c echo".split(),
"grep": "cmd /c findstr".split(),
}, raising=False)
monkeypatch.setattr(
XSH,
"aliases",
{
"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 o>e)", "", "hi\n"),
pytest.param("![echo hi]", "hi\n", "", marks=pytest.mark.xfail(
ON_WINDOWS, 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
pytest.param(
"![echo hi]",
"hi\n",
"",
marks=pytest.mark.xfail(
ON_WINDOWS,
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:
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 x)", "", ""),
))
),
)
def test_command_pipeline_capture(cmdline, stdout, stderr, xonsh_execer):
pipeline: CommandPipeline = xonsh_execer.eval(cmdline)
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()
@pytest.mark.parametrize("cmdline, output", (
@pytest.mark.parametrize(
"cmdline, output",
(
("echo hi", "hi\n"),
("echo hi | grep h", "hi\n"),
("echo hi | grep x", ""),
pytest.param("echo -n hi", "hi", marks=skip_if_on_windows),
))
),
)
def test_simple_capture(cmdline, output, xonsh_execer):
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"
@pytest.mark.parametrize("cmdline, result", (
@pytest.mark.parametrize(
"cmdline, result",
(
("bool(!(echo 1))", True),
("bool(!(nocommand))", False),
("int(!(echo 1))", 0),
("int(!(nocommand))", 1),
("hash(!(echo 1))", 0),
("hash(!(nocommand))", 1),
("str(!(echo 1))", '1\n'),
("str(!(nocommand))", ''),
("str(!(echo 1))", "1\n"),
("str(!(nocommand))", ""),
("!(echo 1) == 0", True),
("!(nocommand) == 1", True),
pytest.param("!(echo -n str) == 'str'", True, marks=skip_if_on_windows),
("!(nocommand) == ''", True),
))
),
)
def test_casting(cmdline, result, xonsh_execer):
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")),
],
)
def test_rich_completion(
completion, lprefix, ptk_completion, monkeypatch, xonsh_builtins
):
def test_rich_completion(completion, lprefix, ptk_completion, monkeypatch, xession):
xonsh_completer_mock = MagicMock()
xonsh_completer_mock.complete.return_value = {completion}, lprefix
@ -39,7 +37,7 @@ def test_rich_completion(
document_mock.current_line = ""
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()))
if isinstance(completion, RichCompletion) and not ptk_completion:
@ -57,7 +55,8 @@ def test_rich_completion(
EXPANSION_CASES = (
(
"sanity", 6,
"sanity",
6,
dict(
prefix="sanity",
line="sanity",
@ -68,7 +67,8 @@ EXPANSION_CASES = (
),
),
(
"gb ", 3,
"gb ",
3,
dict(
prefix="",
line="git branch ",
@ -79,7 +79,8 @@ EXPANSION_CASES = (
),
),
(
"gb ", 1,
"gb ",
1,
dict(
prefix="g",
line="gb ",
@ -90,7 +91,8 @@ EXPANSION_CASES = (
),
),
(
"gb", 0,
"gb",
0,
dict(
prefix="",
line="gb",
@ -101,7 +103,8 @@ EXPANSION_CASES = (
),
),
(
" gb ", 0,
" gb ",
0,
dict(
prefix="",
line=" gb ", # the PTK completer `lstrip`s the line
@ -112,7 +115,8 @@ EXPANSION_CASES = (
),
),
(
"gb --", 5,
"gb --",
5,
dict(
prefix="--",
line="git branch --",
@ -123,7 +127,8 @@ EXPANSION_CASES = (
),
),
(
"nice\ngb --", 10,
"nice\ngb --",
10,
dict(
prefix="--",
line="git branch --",
@ -134,7 +139,8 @@ EXPANSION_CASES = (
),
),
(
"nice\n gb --", 11,
"nice\n gb --",
11,
dict(
prefix="--",
line=" git branch --",
@ -145,7 +151,8 @@ EXPANSION_CASES = (
),
),
(
"gb -- wow", 5,
"gb -- wow",
5,
dict(
prefix="--",
line="git branch -- wow",
@ -156,7 +163,8 @@ EXPANSION_CASES = (
),
),
(
"gb --wow", 5,
"gb --wow",
5,
dict(
prefix="--",
line="git branch --wow",
@ -168,13 +176,9 @@ EXPANSION_CASES = (
),
)
@pytest.mark.parametrize(
"code, index, expected_args",
EXPANSION_CASES
)
def test_alias_expansion(
code, index, expected_args, monkeypatch, xonsh_builtins
):
@pytest.mark.parametrize("code, index, expected_args", EXPANSION_CASES)
def test_alias_expansion(code, index, expected_args, monkeypatch, xession):
xonsh_completer_mock = MagicMock(spec=Completer)
xonsh_completer_mock.complete.return_value = set(), 0
@ -182,11 +186,14 @@ def test_alias_expansion(
ptk_completer.reserve_space = 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()))
mock_call = xonsh_completer_mock.complete.call_args
args, kwargs = mock_call
expected_args["self"] = 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"""
import gc
import builtins
import pytest
from pygments.token import (
@ -19,7 +18,7 @@ from pygments.token import (
from tools import skip_if_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.environ import LsColors
from xonsh.events import events, EventManager
@ -27,13 +26,13 @@ from tools import DummyShell
@pytest.fixture(autouse=True)
def load_command_cache(xonsh_builtins):
def load_command_cache(xession):
gc.collect()
unload_builtins()
load_builtins()
XSH.unload()
XSH.load()
if ON_WINDOWS:
for key in ("cd", "bash"):
builtins.aliases[key] = lambda *args, **kwargs: None
xession.aliases[key] = lambda *args, **kwargs: None
def check_token(code, tokens):
@ -149,18 +148,16 @@ def events_fxt():
@pytest.fixture
def xonsh_builtins_ls_colors(xonsh_builtins, events_fxt):
x = xonsh_builtins.__xonsh__
xonsh_builtins.__xonsh__.shell = DummyShell() # because load_command_cache zaps it.
xonsh_builtins.__xonsh__.shell.shell_type = "prompt_toolkit"
def xonsh_builtins_ls_colors(xession, events_fxt):
xession.shell = DummyShell() # because load_command_cache zaps it.
xession.shell.shell_type = "prompt_toolkit"
lsc = LsColors(LsColors.default_settings)
xonsh_builtins.__xonsh__.env["LS_COLORS"] = lsc # establish LS_COLORS before style.
xonsh_builtins.__xonsh__.shell.shell.styler = XonshStyle() # default style
xession.env["LS_COLORS"] = lsc # establish LS_COLORS before style.
xession.shell.shell.styler = XonshStyle() # default style
events.on_lscolors_change(on_lscolors_change)
yield xonsh_builtins
xonsh_builtins.__xonsh__ = x
yield xession
@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)])
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)])
@ -184,7 +181,7 @@ def test_path(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"""
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"))
lsc["di"] = ("GREEN",)

View file

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

View file

@ -23,17 +23,17 @@ from xonsh.environ import LsColors
@pytest.fixture
def xonsh_builtins_LS_COLORS(xonsh_builtins):
def xs_LS_COLORS(xession):
"""Xonsh environment including LS_COLORS"""
e = xonsh_builtins.__xonsh__.env
e = xession.env
lsc = LsColors(LsColors.default_settings)
xonsh_builtins.__xonsh__.env["LS_COLORS"] = lsc
xonsh_builtins.__xonsh__.shell.shell_type = "prompt_toolkit"
xonsh_builtins.__xonsh__.shell.shell.styler = XonshStyle() # default style
xession.env["LS_COLORS"] = lsc
xession.shell.shell_type = "prompt_toolkit"
xession.shell.shell.styler = XonshStyle() # default style
yield xonsh_builtins
yield xession
xonsh_builtins.__xonsh__.env = e
xession.env = e
DEFAULT_STYLES = {
@ -138,9 +138,7 @@ def test_code_by_name(name, exp):
),
],
)
def test_color_token_by_name(
in_tuple, exp_ct, exp_ansi_colors, xonsh_builtins_LS_COLORS
):
def test_color_token_by_name(in_tuple, exp_ct, exp_ansi_colors, xs_LS_COLORS):
from xonsh.pyghooks import XonshStyle, color_token_by_name
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"
def test_XonshStyle_init_file_color_tokens(xonsh_builtins_LS_COLORS):
def test_XonshStyle_init_file_color_tokens(xs_LS_COLORS):
xs = XonshStyle()
assert xs.styles
assert type(file_color_tokens) is dict
assert set(file_color_tokens.keys()) == set(
xonsh_builtins_LS_COLORS.__xonsh__.env["LS_COLORS"].keys()
)
assert set(file_color_tokens.keys()) == set(xs_LS_COLORS.env["LS_COLORS"].keys())
# parameterized tests for file colorization
@ -283,9 +279,10 @@ def colorizable_files():
@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"""
ffp = colorizable_files + "/" + file_path
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(
"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(
key, file_path, colorizable_files, xonsh_builtins_LS_COLORS
):
def test_colorize_file_symlink(key, file_path, colorizable_files, xs_LS_COLORS):
"""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"
stat_result = os.lstat(ffp)
assert stat.S_ISLNK(stat_result.st_mode)
@ -325,7 +321,7 @@ def test_colorize_file_symlink(
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):
return ["security.capability"]

View file

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

View file

@ -9,61 +9,85 @@ from xonsh.history.sqlite import SqliteHistory
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.
"""
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.append({"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.append(
{
"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()
xonsh_builtins.__xonsh__.env = Env(
xession.env = Env(
XONSH_DATA_DIR=tempdir,
XONSH_INTERACTIVE=True,
XONSH_HISTORY_BACKEND='json',
XONSH_HISTORY_BACKEND="json",
XONSH_HISTORY_FILE=history_file,
# 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.
"""
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.append({"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.append(
{
"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()
xonsh_builtins.__xonsh__.env = Env(
xession.env = Env(
XONSH_DATA_DIR=tempdir,
XONSH_INTERACTIVE=True,
XONSH_HISTORY_BACKEND='sqlite',
XONSH_HISTORY_BACKEND="sqlite",
XONSH_HISTORY_FILE=history_file,
# 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.
"""
xonsh_builtins.__xonsh__.env = Env(XONSH_INTERACTIVE=False)
xonsh_builtins.__xonsh__.history = None
Shell(xonsh_execer, shell_type='none')
assert isinstance(xonsh_builtins.__xonsh__.history, DummyHistory)
xession.env = Env(XONSH_INTERACTIVE=False)
xession.history = None
Shell(xonsh_execer, shell_type="none")
assert isinstance(xession.history, DummyHistory)

View file

@ -32,7 +32,6 @@ from xonsh.tools import (
env_path_to_str,
escape_windows_cmd_string,
executables_in,
expand_case_matching,
expand_path,
find_next_break,
is_bool,
@ -66,7 +65,6 @@ from xonsh.tools import (
is_nonstring_seq_of_strings,
pathsep_to_upper_seq,
seq_to_upper_pathsep,
expandvars,
is_int_as_str,
is_slice_as_str,
ensure_timestamp,
@ -89,6 +87,8 @@ from xonsh.tools import (
to_completion_mode,
is_completions_display_value,
to_completions_display_value,
expand_case_matching,
expandvars,
)
from xonsh.environ import Env
@ -934,8 +934,8 @@ def expand(path):
(b"~/../", "~/../"),
],
)
def test_env_path_getitem(inp, exp, xonsh_builtins, env):
xonsh_builtins.__xonsh__.env = env
def test_env_path_getitem(inp, exp, xession, env):
xession.env = env
obs = EnvPath(inp)[0] # call to __getitem__
if env.get("EXPAND_ENV_VARS"):
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
xonsh_builtins.__xonsh__.env = env
xession.env = env
if env == TOOLS_ENV:
obs = [i for i in EnvPath(inp)]
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", "~", "~/"]),
],
)
def test_env_path_with_pathlib_path_objects(inp, exp, xonsh_builtins):
xonsh_builtins.__xonsh__.env = TOOLS_ENV
def test_env_path_with_pathlib_path_objects(inp, exp, xession):
xession.env = TOOLS_ENV
# iterate over EnvPath to acquire all expanded paths
obs = [i for i in EnvPath(inp)]
assert [expand(i) for i in exp] == obs
@ -1474,7 +1474,7 @@ def test_partial_string(leaders, prefix, quote):
assert obs == exp
def test_executables_in(xonsh_builtins):
def test_executables_in(xession):
expected = set()
types = ("file", "directory", "brokensymlink")
if ON_WINDOWS:
@ -1507,7 +1507,7 @@ def test_executables_in(xonsh_builtins):
if executable and not _type == "brokensymlink":
os.chmod(path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
if ON_WINDOWS:
xonsh_builtins.__xonsh__.env = PATHEXT_ENV
xession.env = PATHEXT_ENV
result = set(executables_in(test_path))
else:
result = set(executables_in(test_path))
@ -1562,12 +1562,12 @@ def test_expand_case_matching(inp, exp):
(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`"""
env = Env(
{"foo": "bar", "spam": "eggs", "a_bool": True, "an_int": 42, "none": None}
)
xonsh_builtins.__xonsh__.env = env
xession.env = env
assert expandvars(inp) == exp
@ -1589,8 +1589,8 @@ def test_expandvars(inp, exp, xonsh_builtins):
),
],
)
def test_ensure_timestamp(inp, fmt, exp, xonsh_builtins):
xonsh_builtins.__xonsh__.env["XONSH_DATETIME_FORMAT"] = "%Y-%m-%d %H:%M"
def test_ensure_timestamp(inp, fmt, exp, xession):
xession.env["XONSH_DATETIME_FORMAT"] = "%Y-%m-%d %H:%M"
obs = ensure_timestamp(inp, fmt)
assert exp == obs
@ -1607,14 +1607,14 @@ def test_ensure_timestamp(inp, fmt, exp, xonsh_builtins):
("~/$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 != "/":
inp = inp.replace("/", os.sep)
exp_end = exp_end.replace("/", os.sep)
env = Env({"foo": "bar", "a_bool": True, "an_int": 42, "none": None})
env["EXPAND_ENV_VARS"] = expand_env_vars
xonsh_builtins.__xonsh__.env = env
xession.env = env
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
def test_iglobpath_no_dotfiles(xonsh_builtins):
def test_iglobpath_no_dotfiles(xession):
d = os.path.dirname(__file__)
g = d + "/*"
files = list(iglobpath(g, include_dotfiles=False))
@ -1736,7 +1736,7 @@ def test_iglobpath_no_dotfiles(xonsh_builtins):
@skip_if_on_windows
def test_iglobpath_dotfiles(xonsh_builtins):
def test_iglobpath_dotfiles(xession):
d = os.path.dirname(__file__)
g = d + "/*"
files = list(iglobpath(g, include_dotfiles=True))
@ -1744,7 +1744,7 @@ def test_iglobpath_dotfiles(xonsh_builtins):
@skip_if_on_windows
def test_iglobpath_no_dotfiles_recursive(xonsh_builtins):
def test_iglobpath_no_dotfiles_recursive(xession):
d = os.path.dirname(__file__)
g = d + "/**"
files = list(iglobpath(g, include_dotfiles=False))
@ -1752,14 +1752,14 @@ def test_iglobpath_no_dotfiles_recursive(xonsh_builtins):
@skip_if_on_windows
def test_iglobpath_dotfiles_recursive(xonsh_builtins):
def test_iglobpath_dotfiles_recursive(xession):
d = os.path.dirname(__file__)
g = d + "/**"
files = list(iglobpath(g, include_dotfiles=True))
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()
# fail to return valid results, like an empty filename
def mockscandir(path):
@ -1812,7 +1812,11 @@ def test_all_permutations():
{"Literal.String.Single": "#ff0000"},
{"Token.Literal.String.Single": "#ff0000"},
), # 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):
@ -1855,7 +1859,15 @@ def test_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):
with pytest.warns(RuntimeWarning):
obs = to_completion_mode(val)
@ -1884,14 +1896,14 @@ def test_is_completions_display_value(val, exp):
(False, "none"),
("false", "none"),
("single", "single"),
("readline", "single"),
("readline", "readline"), # todo: check this
("multi", "multi"),
(True, "multi"),
("TRUE", "multi"),
],
)
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"])

View file

@ -13,20 +13,20 @@ from xonsh.platform import ON_WINDOWS
@skip_if_on_msys
@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.
"""
xonsh_builtins.__xonsh__.env["VIRTUALENV_HOME"] = str(tmpdir)
xession.env["VIRTUALENV_HOME"] = str(tmpdir)
last_event = None
@xonsh_builtins.events.vox_on_create
@xession.builtins.events.vox_on_create
def create(name, **_):
nonlocal last_event
last_event = "create", name
@xonsh_builtins.events.vox_on_delete
@xession.builtins.events.vox_on_delete
def delete(name, **_):
nonlocal last_event
last_event = "delete", name
@ -51,22 +51,22 @@ def test_crud(xonsh_builtins, tmpdir):
@skip_if_on_msys
@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.
"""
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
xonsh_builtins.__xonsh__.env.setdefault("PATH", [])
xession.env.setdefault("PATH", [])
last_event = None
@xonsh_builtins.events.vox_on_activate
@xession.builtins.events.vox_on_activate
def activate(name, **_):
nonlocal last_event
last_event = "activate", name
@xonsh_builtins.events.vox_on_deactivate
@xession.builtins.events.vox_on_deactivate
def deactivate(name, **_):
nonlocal last_event
last_event = "deactivate", name
@ -74,30 +74,30 @@ def test_activate(xonsh_builtins, tmpdir):
vox = Vox()
vox.create("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")
vox.deactivate()
assert "VIRTUAL_ENV" not in xonsh_builtins.__xonsh__.env
assert "VIRTUAL_ENV" not in xession.env
assert last_event == ("deactivate", "spam")
@skip_if_on_msys
@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
(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
@xonsh_builtins.events.vox_on_activate
@xession.builtins.events.vox_on_activate
def activate(name, path, **_):
nonlocal last_event
last_event = "activate", name, path
@xonsh_builtins.events.vox_on_deactivate
@xession.builtins.events.vox_on_deactivate
def deactivate(name, path, **_):
nonlocal last_event
last_event = "deactivate", name, path
@ -109,7 +109,7 @@ def test_activate_non_vox_venv(xonsh_builtins, tmpdir):
vox.activate(venv_dirname)
vxv = vox[venv_dirname]
env = xonsh_builtins.__xonsh__.env
env = xession.env
assert os.path.isabs(vxv.bin)
assert env["PATH"][0] == vxv.bin
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_conda
def test_path(xonsh_builtins, tmpdir):
def test_path(xession, tmpdir):
"""
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
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.create("eggs")
vox.activate("eggs")
assert oldpath != xonsh_builtins.__xonsh__.env["PATH"]
assert oldpath != xession.env["PATH"]
vox.deactivate()
assert oldpath == xonsh_builtins.__xonsh__.env["PATH"]
assert oldpath == xession.env["PATH"]
@skip_if_on_msys
@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.
"""
xonsh_builtins.__xonsh__.env["VIRTUALENV_HOME"] = str(tmpdir)
xession.env["VIRTUALENV_HOME"] = str(tmpdir)
vox = Vox()
vox.create("spam/eggs")
@ -188,7 +188,7 @@ else:
@skip_if_on_msys
@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.
"""
@ -209,11 +209,11 @@ else:
@skip_if_on_msys
@skip_if_on_conda
def test_reserved_names(xonsh_builtins, tmpdir):
def test_reserved_names(xession, tmpdir):
"""
Tests that reserved words are disallowed.
"""
xonsh_builtins.__xonsh__.env["VIRTUALENV_HOME"] = str(tmpdir)
xession.env["VIRTUALENV_HOME"] = str(tmpdir)
vox = Vox()
with pytest.raises(ValueError):
@ -231,7 +231,7 @@ def test_reserved_names(xonsh_builtins, tmpdir):
@skip_if_on_msys
@skip_if_on_conda
def test_autovox(xonsh_builtins, tmpdir):
def test_autovox(xession, tmpdir):
"""
Tests that autovox works
"""
@ -239,7 +239,7 @@ def test_autovox(xonsh_builtins, tmpdir):
import xonsh.dirstack
# 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
import xontrib.autovox
@ -247,13 +247,13 @@ def test_autovox(xonsh_builtins, tmpdir):
importlib.reload(xontrib.autovox)
# Set up enough environment for xonsh to function
xonsh_builtins.__xonsh__.env["PWD"] = os.getcwd()
xonsh_builtins.__xonsh__.env["DIRSTACK_SIZE"] = 10
xonsh_builtins.__xonsh__.env["PATH"] = []
xession.env["PWD"] = os.getcwd()
xession.env["DIRSTACK_SIZE"] = 10
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, **_):
print("Checking", repr(path), vox.active())
if str(path) == str(tmpdir):
@ -261,16 +261,16 @@ def test_autovox(xonsh_builtins, tmpdir):
vox = Vox()
print(xonsh_builtins.__xonsh__.env["PWD"])
print(xession.env["PWD"])
xonsh.dirstack.pushd([str(tmpdir)])
print(xonsh_builtins.__xonsh__.env["PWD"])
print(xession.env["PWD"])
assert vox.active() is None
xonsh.dirstack.popd([])
print(xonsh_builtins.__xonsh__.env["PWD"])
print(xession.env["PWD"])
vox.create("myenv")
xonsh.dirstack.pushd([str(tmpdir)])
print(xonsh_builtins.__xonsh__.env["PWD"])
print(xession.env["PWD"])
assert vox.active() == "myenv"
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(
"args", [([]), (["info",]),], # NOQA E231
"args",
[
([]),
(
[
"info",
]
),
], # NOQA E231
)
def test_xonfig_info(args, xonsh_builtins):
"""info works, and reports no jupyter if none in environment"""
@ -53,8 +61,8 @@ def strip_sep(path: str) -> str:
@pytest.fixture
def fake_lib(monkeypatch):
"""insulate sys.modules from hacking test modules may do with it.
Apparently, monkeypath.syspath_prepend() doesn't flush
imported modules, so they're still visible in other test cases.
Apparently, monkeypath.syspath_prepend() doesn't flush
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.

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,6 @@
"""Tests for the Jedi completer xontrib"""
import sys
import pytest
import builtins
import importlib
from unittest.mock import MagicMock, call
@ -23,14 +22,14 @@ def jedi_mock(monkeypatch):
@pytest.fixture
def completer_mock(monkeypatch):
def completer_mock(monkeypatch, xession):
completer_mock = MagicMock()
# so that args will be passed
def comp(args):
completer_mock(args)
monkeypatch.setitem(builtins.aliases, "completer", comp)
monkeypatch.setitem(xession.aliases, "completer", comp)
yield completer_mock
@ -42,11 +41,11 @@ def jedi_xontrib(monkeypatch, source_path, jedi_mock, completer_mock):
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 "python" not in builtins.__xonsh__.completers
assert "python_mode" not in builtins.__xonsh__.completers
assert "jedi_python" in builtins.__xonsh__.completers
assert "python" not in xession.completers
assert "python_mode" not in xession.completers
assert "jedi_python" in xession.completers
@pytest.mark.parametrize(
@ -56,7 +55,7 @@ def test_completer_added(jedi_xontrib):
],
)
@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":
jedi_mock.__version__ = "0.15.0"
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)
extra_namespace = {"__xonsh__": builtins.__xonsh__}
extra_namespace = {"__xonsh__": xession}
try:
extra_namespace["_"] = _
except NameError:
@ -109,12 +108,16 @@ def test_multiline(jedi_xontrib, jedi_mock, monkeypatch):
"int(x=None, /) -> 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'
("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
@ -139,18 +142,28 @@ def test_multiline(jedi_xontrib, jedi_mock, monkeypatch):
(
# from '(3).from_bytes(byt'
("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
("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'
("module", "collections", "ctions", None, ("module", "module collections")),
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"),
),
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'
("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'
("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):
assert jedi_xontrib.complete_jedi(CompletionContext(python=PythonContext("", 0))) \
.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("", 0))
).issuperset(jedi_xontrib.XONSH_SPECIAL_TOKENS)
assert jedi_xontrib.complete_jedi(
CompletionContext(python=PythonContext("@", 1))
) == {"@", "@(", "@$("}
assert jedi_xontrib.complete_jedi(
CompletionContext(python=PythonContext("$", 1))
) == {"$[", "${", "$("}
@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("./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/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 inspect
import argparse
import builtins
import collections.abc as cabc
from xonsh.built_ins import XSH
from xonsh.lazyasd import lazyobject
from xonsh.dirstack import cd, pushd, popd, dirs, _get_cwd
from xonsh.environ import locate_binary, make_args_env
@ -94,7 +94,7 @@ class Aliases(cabc.MutableMapping):
if callable(value):
return partial_eval_alias(value, acc_args=acc_args)
else:
expand_path = builtins.__xonsh__.expand_path
expand_path = XSH.expand_path
token, *rest = map(expand_path, value)
if token in seen_tokens or token not in self._raw:
# ^ 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.
"""
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_edge = word_idx + len(word)
if cursor_index > word_edge:
@ -139,7 +139,7 @@ class Aliases(cabc.MutableMapping):
self._raw[key] = ExecAlias(val, filename=f)
elif isexpression(val):
# expansion substitution
lexer = builtins.__xonsh__.execer.parser.lexer
lexer = XSH.execer.parser.lexer
self._raw[key] = list(map(strip_simple_quotes, lexer.split(val)))
else:
# need to exec alias
@ -204,14 +204,14 @@ class ExecAlias:
def __call__(
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
alias_args = {"args": args}
for i, a in enumerate(args):
alias_args[f"arg{i}"] = a
with builtins.__xonsh__.env.swap(alias_args):
with XSH.env.swap(alias_args):
execer.exec(
self.src,
glbs=frame.f_globals,
@ -357,14 +357,14 @@ def xonsh_exit(args, stdin=None):
if not clean_jobs():
# Do not exit if jobs not cleaned up
return None, None
builtins.__xonsh__.exit = True
XSH.exit = True
print() # gimme a newline
return None, None
def xonsh_reset(args, stdin=None):
"""Clears __xonsh__.ctx"""
builtins.__xonsh__.ctx.clear()
XSH.ctx.clear()
@lazyobject
@ -496,7 +496,7 @@ def _SOURCE_FOREIGN_PARSER():
def source_foreign(args, stdin=None, stdout=None, stderr=None):
"""Sources a file written in a foreign shell language."""
env = builtins.__xonsh__.env
env = XSH.env
ns = _SOURCE_FOREIGN_PARSER.parse_args(args)
ns.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:
env.pop(k, None)
# Update aliases
baliases = builtins.aliases
baliases = XSH.aliases
for k, v in fsaliases.items():
if k in baliases and v == baliases[k]:
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
instead.
"""
env = builtins.__xonsh__.env
env = XSH.env
encoding = env.get("XONSH_ENCODING")
errors = env.get("XONSH_ENCODING_ERRORS")
for i, fname in enumerate(args):
@ -599,11 +599,11 @@ def source_alias(args, stdin=None):
src = fp.read()
if not src.endswith("\n"):
src += "\n"
ctx = builtins.__xonsh__.ctx
ctx = XSH.ctx
updates = {"__file__": fpath, "__name__": os.path.abspath(fpath)}
with env.swap(**make_args_env(args[i + 1 :])), swap_values(ctx, updates):
try:
builtins.execx(src, "exec", ctx, filename=fpath)
XSH.builtins.execx(src, "exec", ctx, filename=fpath)
except Exception:
print_color(
"{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("--seterrpostcmd=if errorlevel 1 exit 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)
@ -690,7 +690,7 @@ def xexec(args, stdin=None):
denv = {}
if not args.clean:
denv = builtins.__xonsh__.env.detype()
denv = XSH.env.detype()
try:
os.execvpe(command, args.command, denv)

View file

@ -2,9 +2,9 @@
import re
import sys
import warnings
import builtins
import typing as tp
from xonsh.built_ins import XSH
from xonsh.platform import HAS_PYGMENTS
from xonsh.lazyasd import LazyDict, lazyobject
from xonsh.color_tools import (
@ -49,7 +49,7 @@ def _ensure_color_map(style="default", cmap=None):
except Exception:
msg = "Could not find color style {0!r}, using default."
print(msg.format(style), file=sys.stderr)
builtins.__xonsh__.env["XONSH_COLOR_STYLE"] = "default"
XSH.env["XONSH_COLOR_STYLE"] = "default"
cmap = ANSI_STYLES["default"]
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):
cmap = _ensure_color_map(style=style, cmap=cmap)
overrides = builtins.__xonsh__.env["XONSH_STYLE_OVERRIDES"]
overrides = XSH.env["XONSH_STYLE_OVERRIDES"]
if overrides:
cmap.update(_style_dict_to_ansi(overrides))
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.
# pylint: disable=unused-import
import sys
import builtins
from ast import (
Module,
Num,
@ -109,6 +108,7 @@ from ast import Ellipsis as EllipsisNode
import textwrap
import itertools
from xonsh.built_ins import XSH
from xonsh.tools import subproc_toks, find_next_break, get_logical_line
from ast import (
@ -314,8 +314,8 @@ def isexpression(node, ctx=None, *args, **kwargs):
# parse string to AST
if isinstance(node, str):
node = node if node.endswith("\n") else node + "\n"
ctx = builtins.__xonsh__.ctx if ctx is None else ctx
node = builtins.__xonsh__.execer.parse(node, ctx, *args, **kwargs)
ctx = XSH.ctx if ctx is None else ctx
node = XSH.execer.parse(node, ctx, *args, **kwargs)
# determin if expresission-like enough
if isinstance(node, (Expr, Expression)):
isexpr = True

View file

@ -4,8 +4,8 @@ import io
import os
import sys
import time
import builtins
from xonsh.built_ins import XSH
from xonsh.tools import (
XonshError,
print_exception,
@ -66,7 +66,7 @@ class _TeeStdBuf(io.RawIOBase):
"""
self.stdbuf = stdbuf
self.membuf = membuf
env = builtins.__xonsh__.env
env = XSH.env
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.prestd = prestd
@ -268,7 +268,7 @@ class Tee:
write_through=write_through,
)
self.stdout = _TeeStd("stdout", self.memory)
env = builtins.__xonsh__.env
env = XSH.env
prestderr = format_std_prepost(env.get("XONSH_STDERR_PREFIX"))
poststderr = format_std_prepost(env.get("XONSH_STDERR_POSTFIX"))
self.stderr = _TeeStd(
@ -324,7 +324,7 @@ class BaseShell(object):
if HAS_PYGMENTS:
from xonsh.pyghooks import XonshStyle
env = builtins.__xonsh__.env
env = XSH.env
self._styler = XonshStyle(env.get("XONSH_COLOR_STYLE"))
else:
self._styler = None
@ -367,8 +367,8 @@ class BaseShell(object):
events.on_precommand.fire(cmd=src)
env = builtins.__xonsh__.env
hist = builtins.__xonsh__.history # pylint: disable=no-member
env = XSH.env
hist = XSH.history # pylint: disable=no-member
ts1 = None
enc = env.get("XONSH_ENCODING")
err = env.get("XONSH_ENCODING_ERRORS")
@ -406,7 +406,7 @@ class BaseShell(object):
print(os.linesep, end="")
tee.close()
self._fix_cwd()
if builtins.__xonsh__.exit: # pylint: disable=no-member
if XSH.exit: # pylint: disable=no-member
return True
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
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
tee_out = tee_out or 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):
"""Check if the cwd changed out from under us."""
env = builtins.__xonsh__.env
env = XSH.env
try:
cwd = os.getcwd()
except (FileNotFoundError, OSError):
@ -523,7 +523,7 @@ class BaseShell(object):
def settitle(self):
"""Sets terminal title."""
env = builtins.__xonsh__.env # pylint: disable=no-member
env = XSH.env # pylint: disable=no-member
term = env.get("TERM", None)
# Shells running in emacs sets TERM to "dumb" or "eterm-color".
# Do not set title for these to avoid garbled prompt.
@ -557,7 +557,7 @@ class BaseShell(object):
print_exception()
self.mlprompt = "<multiline prompt error> "
return self.mlprompt
env = builtins.__xonsh__.env # pylint: disable=no-member
env = XSH.env # pylint: disable=no-member
p = env.get("PROMPT")
try:
p = self.prompt_formatter(p)
@ -570,7 +570,7 @@ class BaseShell(object):
"""Formats the colors in a string. ``BaseShell``'s default implementation
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)
def print_color(self, string, hide=False, **kwargs):
@ -583,7 +583,7 @@ class BaseShell(object):
s = self.format_color(string, hide=hide)
elif HAS_PYGMENTS:
# 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")
style_proxy = pyghooks.xonsh_style_proxy(self.styler)
formatter = pyghooks.XonshTerminal256Formatter(style=style_proxy)

View file

@ -18,11 +18,9 @@ import itertools
import contextlib
import collections.abc as cabc
from xonsh.ast import AST
from xonsh.lazyasd import LazyObject, lazyobject
from ast import AST
from xonsh.lazyasd import lazyobject
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.tools import (
expand_path,
@ -31,14 +29,8 @@ from xonsh.tools import (
XonshCalledProcessError,
print_color,
)
from xonsh.commands_cache import CommandsCache
from xonsh.events import events
import xonsh.procs.specs
import xonsh.completers.init
BUILTINS_LOADED = False
INSPECTOR = LazyObject(Inspector, globals(), "INSPECTOR")
INSPECTOR = Inspector()
warnings.filterwarnings("once", category=DeprecationWarning)
@ -136,9 +128,9 @@ def regexsearch(s):
def globsearch(s):
csc = builtins.__xonsh__.env.get("CASE_SENSITIVE_COMPLETIONS")
glob_sorted = builtins.__xonsh__.env.get("GLOB_SORTED")
dotglob = builtins.__xonsh__.env.get("DOTGLOB")
csc = XSH.env.get("CASE_SENSITIVE_COMPLETIONS")
glob_sorted = XSH.env.get("GLOB_SORTED")
dotglob = XSH.env.get("DOTGLOB")
return globpath(
s,
ignore_case=(not csc),
@ -168,6 +160,9 @@ def subproc_captured_stdout(*cmds, envs=None):
"""Runs a subprocess, capturing the output. Returns the stdout
that was produced as a str.
"""
import xonsh.procs.specs
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()
or shlex.split().
"""
import xonsh.procs.specs
o = xonsh.procs.specs.run_subproc(cmds, captured="object", envs=envs)
o.end()
toks = []
for line in o:
line = line.rstrip(os.linesep)
toks.extend(builtins.__xonsh__.execer.parser.lexer.split(line))
toks.extend(XSH.execer.parser.lexer.split(line))
return toks
@ -191,6 +188,8 @@ def subproc_captured_object(*cmds, envs=None):
Runs a subprocess, capturing the output. Returns an instance of
CommandPipeline representing the completed command.
"""
import xonsh.procs.specs
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
HiddenCommandPipeline representing the completed command.
"""
import xonsh.procs.specs
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
that was produced as a str.
"""
import xonsh.procs.specs
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):
s = "".join(los)
if "*" in s:
rtn.extend(builtins.__xonsh__.glob(s))
rtn.extend(XSH.glob(s))
else:
rtn.append(builtins.__xonsh__.expand_path(s))
rtn.append(XSH.expand_path(s))
return rtn
def eval_fstring_field(field):
"""Evaluates the argument in Xonsh context."""
res = __xonsh__.execer.eval(
field[0].strip(), glbs=globals(), locs=builtins.__xonsh__.ctx, filename=field[1]
res = XSH.execer.eval(
field[0].strip(), glbs=globals(), locs=XSH.ctx, filename=field[1]
)
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:
return raw_arg # short circuit since there is nothing else to do
# select from kind and convert
execer = builtins.__xonsh__.execer
execer = XSH.execer
filename = macroname + "(" + name + ")"
if kind is AST:
ctx = set(dir(builtins)) | set(glbs.keys())
@ -440,7 +443,7 @@ def _eval_regular_args(raw_args, glbs, locs):
return [], {}
arglist = list(itertools.takewhile(_starts_as_arg, raw_args))
kwarglist = raw_args[len(arglist) :]
execer = builtins.__xonsh__.execer
execer = XSH.execer
if not arglist:
args = arglist
kwargstr = "dict({})".format(", ".join(kwarglist))
@ -498,44 +501,9 @@ def enter_macro(obj, raw_block, glbs, locs):
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):
if hasattr(builtins, "__xonsh__"):
if builtins.__xonsh__.history is not None:
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
if XSH.history is not None:
XSH.history.flush(at_exit=True)
@contextlib.contextmanager
@ -543,9 +511,9 @@ def xonsh_builtins(execer=None):
"""A context manager for using the xonsh builtins only in a limited
scope. Likely useful in testing.
"""
load_builtins(execer=execer)
XSH.load(execer=execer)
yield
unload_builtins()
XSH.unload()
class XonshSession:
@ -562,8 +530,12 @@ class XonshSession:
"""
self.execer = execer
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.
Parameters
@ -573,10 +545,17 @@ class XonshSession:
ctx : Mapping, optional
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:
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.pathsearch = pathsearch
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.eval_fstring_field = eval_fstring_field
self.completers = xonsh.completers.init.default_completers()
self.completers = default_completers()
self.call_macro = call_macro
self.enter_macro = enter_macro
self.path_literal = path_literal
self.builtins = _BuiltIns(execer)
self.history = None
self.shell = None
aliases_given = kwargs.pop("aliases", 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
proxy_mapping = {
"XonshError": "__xonsh__.builtins.XonshError",
"XonshCalledProcessError": "__xonsh__.builtins.XonshCalledProcessError",
"evalx": "__xonsh__.builtins.evalx",
"execx": "__xonsh__.builtins.execx",
"compilex": "__xonsh__.builtins.compilex",
"events": "__xonsh__.builtins.events",
"print_color": "__xonsh__.builtins.print_color",
"printx": "__xonsh__.builtins.printx",
}
for refname, objname in proxy_mapping.items():
proxy_mapping = [
"XonshError",
"XonshCalledProcessError",
"evalx",
"execx",
"compilex",
"events",
"print_color",
"printx",
]
for refname in proxy_mapping:
objname = f"__xonsh__.builtins.{refname}"
proxy = DynamicAccessProxy(refname, objname)
setattr(builtins, refname, proxy)
# sneak the path search functions into the aliases
# Need this inline/lazy import here since we use locate_binary that
# 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)
for sig in AT_EXIT_SIGNALS:
resetting_signal_handle(sig, _lastflush)
@ -659,9 +647,28 @@ class XonshSession:
if hasattr(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:
def __init__(self, execer=None):
from xonsh.events import events
# public built-ins
self.XonshError = XonshError
self.XonshCalledProcessError = XonshCalledProcessError
@ -721,3 +728,7 @@ class DynamicAccessProxy:
def __dir__(self):
return self.obj.__dir__()
# singleton
XSH = XonshSession()

View file

@ -1,11 +1,11 @@
"""Tools for caching xonsh code."""
import os
import sys
import hashlib
import marshal
import builtins
import os
import sys
from xonsh import __version__ as XONSH_VERSION
from xonsh.built_ins import XSH
from xonsh.lazyasd import lazyobject
from xonsh.platform import PYTHON_VERSION_INFO_BYTES
@ -47,11 +47,10 @@ def should_use_cache(execer, mode):
"""
if mode == "exec":
return (execer.scriptcache or execer.cacheall) and (
builtins.__xonsh__.env["XONSH_CACHE_SCRIPTS"]
or builtins.__xonsh__.env["XONSH_CACHE_EVERYTHING"]
XSH.env["XONSH_CACHE_SCRIPTS"] or XSH.env["XONSH_CACHE_EVERYTHING"]
)
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):
@ -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
than the script store.
"""
datadir = builtins.__xonsh__.env["XONSH_DATA_DIR"]
datadir = XSH.env["XONSH_DATA_DIR"]
cachedir = os.path.join(
datadir, "xonsh_code_cache" if code else "xonsh_script_cache"
)

View file

@ -11,12 +11,12 @@ import pickle
import sys
import threading
import time
import builtins
import argparse
import collections.abc as cabc
import typing as tp
from pathlib import Path
from xonsh.built_ins import XSH
from xonsh.platform import ON_WINDOWS, ON_POSIX, pathbasename
from xonsh.tools import executables_in
from xonsh.lazyasd import lazyobject
@ -41,7 +41,7 @@ class CommandsCache(cabc.Mapping):
self._loaded_pickled = False
# Path to the cache-file where all commands/aliases are cached for pre-loading"""
env = builtins.__xonsh__.env
env = XSH.env
self.cache_file = (
(Path(env["XONSH_DATA_DIR"]).joinpath(self.CACHE_FILE).resolve())
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`.
Returns a list as `name` being the only item in it on other platforms."""
if ON_WINDOWS:
pathext = builtins.__xonsh__.env.get("PATHEXT", [])
pathext = XSH.env.get("PATHEXT", [])
name = name.upper()
return [name + ext for ext in ([""] + pathext)]
else:
@ -109,9 +109,9 @@ class CommandsCache(cabc.Mapping):
@property
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))
alss = getattr(builtins, "aliases", dict())
alss = getattr(XSH, "aliases", dict())
(
has_path_changed,
has_alias_changed,
@ -150,7 +150,7 @@ class CommandsCache(cabc.Mapping):
self, paths: tp.Sequence[str], aliases: tp.Dict[str, str]
) -> tp.Dict[str, tp.Any]:
"""Update the cmds_cache variable in background without slowing down parseLexer"""
env = builtins.__xonsh__.env # type: ignore
env = XSH.env # type: ignore
allcmds = {}
for path in reversed(paths):
@ -330,7 +330,7 @@ class CommandsCache(cabc.Mapping):
"""
# alias stuff
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:
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
)
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:
alias_name = alss[cmd0]
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]:
# args[i] is the command and the following is its arguments
# 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

View file

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

View file

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

View file

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

View file

@ -1,5 +1,4 @@
import os
import builtins
import typing as tp
import xonsh.tools as xt
@ -13,6 +12,8 @@ from xonsh.completers.tools import (
non_exclusive_completer,
)
from xonsh.parsers.completion_context import CompletionContext, CommandContext
from xonsh.built_ins import XSH
SKIP_TOKENS = {"sudo", "time", "timeit", "which", "showcmd", "man"}
END_PROC_TOKENS = ("|", ";", "&&") # includes ||
@ -26,7 +27,7 @@ def complete_command(command: CommandContext):
cmd = command.prefix
out: tp.Set[Completion] = {
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 xp.ON_WINDOWS:
@ -66,7 +67,7 @@ def complete_skipper(command_context: CommandContext):
# completing the command after a SKIP_TOKEN
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))

View file

@ -1,15 +1,8 @@
import builtins
import collections
from xonsh.parsers.completion_context import CommandContext
from xonsh.built_ins import XSH
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")
@ -24,7 +17,7 @@ def complete_completer(command: CommandContext):
curix = command.arg_index
compnames = set(xsh_session.completers.keys())
compnames = set(XSH.completers.keys())
if curix == 1:
possible = {"list", "help", "add", "remove"}
elif curix == 2:
@ -39,7 +32,7 @@ def complete_completer(command: CommandContext):
if command.args[1].value != "add":
raise StopIteration
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:
possible = (
{"start", "end"}
@ -55,16 +48,16 @@ def add_one_completer(name, func, loc="end"):
new = collections.OrderedDict()
if loc == "start":
new[name] = func
for (k, v) in xsh_session.completers.items():
for (k, v) in XSH.completers.items():
new[k] = v
elif loc == "end":
for (k, v) in xsh_session.completers.items():
for (k, v) in XSH.completers.items():
new[k] = v
new[name] = func
else:
direction, rel = loc[0], loc[1:]
found = False
for (k, v) in xsh_session.completers.items():
for (k, v) in XSH.completers.items():
if rel == k and direction == "<":
new[name] = func
found = True
@ -74,14 +67,14 @@ def add_one_completer(name, func, loc="end"):
found = True
if not found:
new[name] = func
xsh_session.completers.clear()
xsh_session.completers.update(new)
XSH.completers.clear()
XSH.completers.update(new)
def list_completers():
"""List the active completers"""
o = "Registered Completer Functions: \n"
_comp = xsh_session.completers
_comp = XSH.completers
ml = max((len(i) for i in _comp), default=0)
_strs = []
for c in _comp:
@ -104,10 +97,10 @@ def remove_completer(name: str):
completers in order)
"""
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."
if err is None:
del xsh_session.completers[name]
del XSH.completers[name]
return
else:
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.completers.tools import (
contextual_completer,
@ -25,6 +24,6 @@ def complete_environment_vars(context: CompletionContext):
key = prefix[dollar_location + 1 :]
lprefix = len(key) + 1
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

View file

@ -1,12 +1,11 @@
import os
import re
import pickle
import builtins
import subprocess
import typing as tp
from xonsh.parsers.completion_context import CommandContext
from xonsh.built_ins import XSH
import xonsh.lazyasd as xl
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
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")
try:
with open(OPTIONS_PATH, "rb") as f:

View file

@ -2,7 +2,8 @@ import os
import re
import ast
import glob
import builtins
from xonsh.built_ins import XSH
from xonsh.parsers.completion_context import CommandContext
import xonsh.tools as xt
@ -26,7 +27,7 @@ def PATTERN_NEED_QUOTES():
def cd_in_command(line):
"""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.input(line)
have_cd = False
@ -80,7 +81,7 @@ def _path_from_partial_string(inp, pos=None):
except (SyntaxError, ValueError):
return None
if isinstance(val, bytes):
env = builtins.__xonsh__.env
env = XSH.env
val = val.decode(
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)
if trailing_slash:
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)
return p
@ -118,7 +119,7 @@ def _startswithnorm(x, start, startlow=None):
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":
return ()
slash = xt.get_sep()
@ -137,7 +138,7 @@ def _dots(prefix):
def _add_cdpaths(paths, prefix):
"""Completes current prefix using CDPATH"""
env = builtins.__xonsh__.env
env = XSH.env
csc = env.get("CASE_SENSITIVE_COMPLETIONS")
glob_sorted = env.get("GLOB_SORTED")
for cdp in env.get("CDPATH"):
@ -159,7 +160,7 @@ def _quote_to_use(x):
def _is_directory_in_cdpath(path):
env = builtins.__xonsh__.env
env = XSH.env
for cdp in env.get("CDPATH"):
if os.path.isdir(os.path.join(cdp, path)):
return True
@ -167,7 +168,7 @@ def _is_directory_in_cdpath(path):
def _quote_paths(paths, start, end, append_end=True, cdpath=False):
expand_path = builtins.__xonsh__.expand_path
expand_path = XSH.expand_path
out = set()
space = " "
backslash = "\\"
@ -274,7 +275,7 @@ def _subsequence_match_iter(ref, typed):
def _expand_one(sofar, nextone, csc):
out = set()
glob_sorted = builtins.__xonsh__.env.get("GLOB_SORTED")
glob_sorted = XSH.env.get("GLOB_SORTED")
for i in sofar:
_glob = os.path.join(_joinpath(i), "*") if i is not None else "*"
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
tilde = "~"
paths = set()
env = builtins.__xonsh__.env
env = XSH.env
csc = env.get("CASE_SENSITIVE_COMPLETIONS")
glob_sorted = env.get("GLOB_SORTED")
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.lazyasd as xl
from xonsh.built_ins import XSH
from xonsh.completers.tools import (
CompleterResult,
@ -145,7 +146,7 @@ def complete_python(context: CompletionContext) -> CompleterResult:
# this can be a command (i.e. not a subexpression)
first = context.command.args[0].value
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
return None
@ -206,7 +207,7 @@ def _safe_eval(expr, ctx):
a (None, None) tuple.
"""
_ctx = None
xonsh_safe_eval = builtins.__xonsh__.execer.eval
xonsh_safe_eval = XSH.execer.eval
try:
val = xonsh_safe_eval(expr, ctx, ctx, transform=False)
_ctx = ctx
@ -245,7 +246,7 @@ def attr_complete(prefix, ctx, filter_func):
if _val_ is None and _ctx_ is None:
continue
a = getattr(val, opt)
if builtins.__xonsh__.env["COMPLETIONS_BRACKETS"]:
if XSH.env["COMPLETIONS_BRACKETS"]:
if callable(a):
rpl = opt + "("
elif isinstance(a, (cabc.Sequence, cabc.Mapping)):

View file

@ -1,9 +1,9 @@
"""Xonsh completer tools."""
import builtins
import textwrap
import typing as tp
from functools import wraps
from xonsh.built_ins import XSH
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
of $CASE_SENSITIVE_COMPLETIONS
"""
csc = builtins.__xonsh__.env.get("CASE_SENSITIVE_COMPLETIONS")
csc = XSH.env.get("CASE_SENSITIVE_COMPLETIONS")
if csc:
return _filter_normal
else:

View file

@ -1,9 +1,10 @@
"""Context management tools for xonsh."""
import sys
import textwrap
import builtins
from collections.abc import Mapping
from xonsh.built_ins import XSH
class Block(object):
"""This is a context manager for obtaining a block of lines without actually
@ -28,7 +29,9 @@ class Block(object):
def __enter__(self):
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.glbs = 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)
glbs = self.glbs
locs = self.locs
execer = builtins.__xonsh__.execer
execer = XSH.execer
execer.exec(fstr, glbs=glbs, locs=locs)
if locs is not None and name in locs:
func = locs[name]

View file

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

View file

@ -1,6 +1,6 @@
"""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
@ -8,5 +8,5 @@ class DumbShell(ReadlineShell):
"""A dumb shell for when $TERM == 'dumb', which usually happens in emacs."""
def __init__(self, *args, **kwargs):
builtins.__xonsh__.env["XONSH_COLOR_STYLE"] = "emacs"
XSH.env["XONSH_COLOR_STYLE"] = "emacs"
super().__init__(*args, **kwargs)

View file

@ -7,7 +7,6 @@ import pprint
import textwrap
import locale
import glob
import builtins
import warnings
import contextlib
import collections.abc as cabc
@ -29,7 +28,7 @@ from xonsh.platform import (
ON_CYGWIN,
os_environ,
)
from xonsh.built_ins import XSH
from xonsh.tools import (
always_true,
always_false,
@ -193,12 +192,8 @@ def to_debug(x):
execer's debug level.
"""
val = to_bool_or_int(x)
if (
hasattr(builtins, "__xonsh__")
and hasattr(builtins.__xonsh__, "execer")
and builtins.__xonsh__.execer is not None
):
builtins.__xonsh__.execer.debug_level = val
if XSH.execer is not None:
XSH.execer.debug_level = val
return val
@ -427,7 +422,7 @@ class LsColors(cabc.MutableMapping):
@property
def style_name(self):
"""Current XONSH_COLOR_STYLE value"""
env = getattr(builtins.__xonsh__, "env", {})
env = getattr(XSH, "env", {})
env_style_name = env.get("XONSH_COLOR_STYLE", "default")
if self._style_name is None or 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:
cmd.append(filename)
# get env
if hasattr(builtins, "__xonsh__") and hasattr(builtins.__xonsh__, "env"):
denv = builtins.__xonsh__.env.detype()
if XSH.env:
denv = XSH.env.detype()
else:
denv = None
# 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
ls command is called.
"""
env = builtins.__xonsh__.env
env = XSH.env
if "LS_COLORS" not in env._d:
# this adds it to the env too
default_lscolors(env)
@ -2148,7 +2143,7 @@ def _yield_executables(directory, name):
def locate_binary(name):
"""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(

View file

@ -1,17 +1,17 @@
"""
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::
events.doc('on_spam', "Comes with eggs")
"""
import abc
import builtins
import collections.abc
import inspect
from xonsh.built_ins import XSH
from xonsh.tools import print_exception
@ -22,8 +22,8 @@ def has_kwargs(func):
def debug_level():
if hasattr(builtins, "__xonsh__") and hasattr(builtins.__xonsh__, "env"):
return builtins.__xonsh__.env.get("XONSH_DEBUG")
if XSH.env:
return XSH.env.get("XONSH_DEBUG")
# FIXME: Under py.test, return 1(?)
else:
return 0 # Optimize for speed, not guaranteed correctness

View file

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

View file

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

View file

@ -3,11 +3,12 @@
import os
import sys
import time
import builtins
import collections
import threading
import collections.abc as cabc
from xonsh.built_ins import XSH
try:
import ujson as json
except ImportError:
@ -90,7 +91,7 @@ def _xhj_gc_bytes_to_rmfiles(hsize, files):
def _xhj_get_data_dir():
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):
os.makedirs(dir)
@ -103,9 +104,7 @@ def _xhj_get_history_files(sort=True, newest_first=False):
"""
data_dirs = [
_xhj_get_data_dir(),
builtins.__xonsh__.env.get(
"XONSH_DATA_DIR"
), # backwards compatibility, remove in the future
XSH.env.get("XONSH_DATA_DIR"), # backwards compatibility, remove in the future
]
files = []
@ -118,14 +117,14 @@ def _xhj_get_history_files(sort=True, newest_first=False):
if f.startswith("xonsh-") and f.endswith(".json")
]
except OSError:
if builtins.__xonsh__.env.get("XONSH_DEBUG"):
if XSH.env.get("XONSH_DEBUG"):
xt.print_exception(
f"Could not collect xonsh history json files from {data_dir}"
)
if sort:
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:
custom_history_file = xt.expanduser_abs_path(custom_history_file)
if custom_history_file not in files:
@ -157,7 +156,7 @@ class JsonHistoryGC(threading.Thread):
def run(self):
while self.wait_for_shell:
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)
if self.size is None:
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))
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
hist.hist_size = size_over + hsize
hist.hist_units = units
@ -201,7 +200,7 @@ class JsonHistoryGC(threading.Thread):
This is sorted by the last closed time. Returns a list of
(file_size, timestamp, number of cmds, file name) tuples.
"""
env = getattr(getattr(builtins, "__xonsh__", None), "env", None)
env = XSH.env
if env is None:
return []
@ -283,7 +282,7 @@ class JsonHistoryFlusher(threading.Thread):
def dump(self):
"""Write the cached history to external storage."""
opts = builtins.__xonsh__.env.get("HISTCONTROL", "")
opts = XSH.env.get("HISTCONTROL", "")
last_inp = None
cmds = []
for cmd in self.buffer:
@ -305,9 +304,11 @@ class JsonHistoryFlusher(threading.Thread):
load_hist_len = len(hist["cmds"])
hist["cmds"].extend(cmds)
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
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]
with open(self.filename, "w", newline="\n") as f:
xlj.ljdump(hist, f, sort_keys=True)
@ -445,7 +446,7 @@ class JsonHistory(History):
self.save_cwd = (
save_cwd
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):
@ -472,7 +473,7 @@ class JsonHistory(History):
if not self.remember_history:
return
opts = builtins.__xonsh__.env.get("HISTCONTROL", "")
opts = XSH.env.get("HISTCONTROL", "")
skipped_by_ignore_space = "ignorespace" in opts and cmd.get("spc")
if skipped_by_ignore_space:
return None
@ -553,7 +554,7 @@ class JsonHistory(History):
commands = json_file.load()["cmds"]
except (json.decoder.JSONDecodeError, ValueError):
# 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"
print(msg.format(f), file=sys.stderr)
continue
@ -572,7 +573,7 @@ class JsonHistory(History):
data["length"] = len(self)
data["buffersize"] = self.buffersize
data["bufferlength"] = len(self.buffer)
envs = builtins.__xonsh__.env
envs = XSH.env
data["gc options"] = envs.get("XONSH_HISTORY_SIZE")
data["gc_last_size"] = f"{(self.hist_size, self.hist_units)}"
return data

View file

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
"""Main entry points of the xonsh history."""
import argparse
import builtins
import datetime
import functools
import json
@ -9,6 +8,7 @@ import os
import sys
import threading
from xonsh.built_ins import XSH
from xonsh.history.base import History
from xonsh.history.dummy import DummyHistory
from xonsh.history.json import JsonHistory
@ -22,7 +22,7 @@ HISTORY_BACKENDS = {"dummy": DummyHistory, "json": JsonHistory, "sqlite": Sqlite
def construct_history(**kwargs):
"""Construct the history backend object."""
env = builtins.__xonsh__.env
env = XSH.env
backend = env.get("XONSH_HISTORY_BACKEND")
if isinstance(backend, str) and backend in HISTORY_BACKENDS:
kls_history = HISTORY_BACKENDS[backend]
@ -42,14 +42,14 @@ def construct_history(**kwargs):
def _xh_session_parser(hist=None, newest_first=False, **kwargs):
"""Returns history items of current session."""
if hist is None:
hist = builtins.__xonsh__.history
hist = XSH.history
return hist.items()
def _xh_all_parser(hist=None, newest_first=False, **kwargs):
"""Returns all history items."""
if hist is None:
hist = builtins.__xonsh__.history
hist = XSH.history
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",
)
hist = builtins.__xonsh__.history
hist = XSH.history
if isinstance(hist, JsonHistory):
# add actions belong only to JsonHistory
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
):
"""This is the history command entry point."""
hist = builtins.__xonsh__.history
hist = XSH.history
ns = _xh_parse_args(args)
if not ns or not ns.action:
return

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -7,7 +7,6 @@ import sys
import ctypes # noqa
import signal
import pathlib
import builtins
import platform
import functools
import subprocess
@ -203,7 +202,9 @@ def ptk_below_max_supported():
@functools.lru_cache(1)
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"
if has_prompt_toolkit():
return "prompt_toolkit"
@ -357,8 +358,10 @@ def windows_bash_command():
"""Determines the command for Bash on windows."""
# Check that bash is on path otherwise try the default directory
# used by Git for windows
from xonsh.built_ins import XSH
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)
if bash_on_path:
try:

View file

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

View file

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

View file

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

View file

@ -5,10 +5,10 @@ import sys
import time
import queue
import ctypes
import builtins
import threading
import xonsh.lazyimps as xli
from xonsh.built_ins import XSH
class QueueReader:
@ -382,7 +382,7 @@ class ConsoleParallelReader(QueueReader):
timeout : float, optional
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)
self._buffer = buffer # this cannot be public
if buffer is None:

View file

@ -7,10 +7,10 @@ import shlex
import signal
import inspect
import pathlib
import builtins
import subprocess
import contextlib
from xonsh.built_ins import XSH
import xonsh.tools as xt
import xonsh.lazyasd as xl
import xonsh.platform as xp
@ -101,7 +101,7 @@ def get_script_subproc_command(fname, args):
# Windows can execute various filetypes directly
# as given in PATHEXT
_, 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
# find interpreter
with open(fname, "rb") as f:
@ -356,7 +356,7 @@ class SubprocSpec:
self.args = list(cmd)
self.alias = 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.is_proxy = False
self.background = False
@ -458,8 +458,8 @@ class SubprocSpec:
return p
def _run_binary(self, kwargs):
bufsize = 1
try:
bufsize = 1
p = self.cls(self.cmd, bufsize=bufsize, **kwargs)
except PermissionError:
e = "xonsh: subprocess mode: permission denied: {0}"
@ -472,16 +472,16 @@ class SubprocSpec:
["man", cmd0.rstrip("?")], bufsize=bufsize, **kwargs
)
e = "xonsh: subprocess mode: command not found: {0}".format(cmd0)
env = builtins.__xonsh__.env
sug = xt.suggest_commands(cmd0, env, builtins.aliases)
env = XSH.env
sug = xt.suggest_commands(cmd0, env, XSH.aliases)
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)
return p
def prep_env(self, kwargs):
"""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()
if xp.ON_WINDOWS:
# Over write prompt variable as xonsh's $PROMPT does
@ -493,7 +493,7 @@ class SubprocSpec:
"""Prepares the 'preexec_fn' keyword argument"""
if not xp.ON_POSIX:
return
if not builtins.__xonsh__.env.get("XONSH_INTERACTIVE"):
if not XSH.env.get("XONSH_INTERACTIVE"):
return
if pipeline_group is None or xp.ON_WSL:
# If there is no pipeline group
@ -530,14 +530,14 @@ class SubprocSpec:
return os.path.basename(self.binary_loc)
def _pre_run_event_fire(self, name):
events = builtins.events
events = XSH.builtins.events
event_name = "on_pre_spec_run_" + name
if events.exists(event_name):
event = getattr(events, event_name)
event.fire(spec=self)
def _post_run_event_fire(self, name, proc):
events = builtins.events
events = XSH.builtins.events
event_name = "on_post_spec_run_" + name
if events.exists(event_name):
event = getattr(events, event_name)
@ -602,7 +602,7 @@ class SubprocSpec:
if callable(cmd0):
alias = cmd0
else:
alias = builtins.aliases.get(cmd0, None)
alias = XSH.aliases.get(cmd0, None)
if alias is not None:
self.alias_name = cmd0
self.alias = alias
@ -627,12 +627,12 @@ class SubprocSpec:
self.alias is None
and self.binary_loc is None
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])
):
return
self.cmd.insert(0, "cd")
self.alias = builtins.aliases.get("cd", None)
self.alias = XSH.aliases.get("cd", None)
def resolve_executable_commands(self):
"""Resolve command executables, if applicable."""
@ -663,7 +663,7 @@ class SubprocSpec:
if not callable(alias):
return
self.is_proxy = True
env = builtins.__xonsh__.env
env = XSH.env
thable = env.get("THREAD_SUBPROCS") and getattr(
alias, "__xonsh_threadable__", True
)
@ -718,7 +718,7 @@ def _safe_pipe_properties(fd, use_tty=False):
def _update_last_spec(last):
env = builtins.__xonsh__.env
env = XSH.env
captured = last.captured
last.last_in_pipeline = True
if not captured:
@ -727,7 +727,7 @@ def _update_last_spec(last):
if callable_alias:
pass
else:
cmds_cache = builtins.__xonsh__.commands_cache
cmds_cache = XSH.commands_cache
thable = (
env.get("THREAD_SUBPROCS")
and cmds_cache.predict_threadable(last.args)
@ -753,9 +753,9 @@ def _update_last_spec(last):
r, w = os.pipe()
last.stdout = safe_open(w, "wb")
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.stdout = builtins.__xonsh__.stdout_uncaptured
last.stdout = XSH.stdout_uncaptured
last.captured_stdout = last.stdout
elif xp.ON_WINDOWS and not callable_alias:
last.universal_newlines = True
@ -775,8 +775,8 @@ def _update_last_spec(last):
r, w = os.pipe()
last.stderr = safe_open(w, "w")
last.captured_stderr = safe_open(r, "r")
elif builtins.__xonsh__.stderr_uncaptured is not None:
last.stderr = builtins.__xonsh__.stderr_uncaptured
elif XSH.stderr_uncaptured is not None:
last.stderr = XSH.stderr_uncaptured
last.captured_stderr = last.stderr
elif xp.ON_WINDOWS and not callable_alias:
last.universal_newlines = True
@ -832,12 +832,12 @@ def cmds_to_specs(cmds, captured=False, envs=None):
def _should_set_title(captured=False):
env = builtins.__xonsh__.env
env = XSH.env
return (
env.get("XONSH_INTERACTIVE")
and not env.get("XONSH_STORE_STDOUT")
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.
"""
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)
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):
# set title here to get currently executing command
pause_call_resume(proc, builtins.__xonsh__.shell.settitle)
pause_call_resume(proc, XSH.shell.settitle)
else:
# 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

View file

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
"""Base prompt, provides PROMPT_FIELDS and prompt related functions"""
import builtins
import itertools
import os
import re
@ -13,6 +12,7 @@ import xonsh.lazyasd as xl
import xonsh.tools as xt
import xonsh.platform as xp
from xonsh.built_ins import XSH
from xonsh.prompt.cwd import (
_collapsed_pwd,
_replace_home_cwd,
@ -43,7 +43,7 @@ class ParsedTokens(tp.NamedTuple):
def process(self) -> str:
"""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
)
return processor(self)
@ -93,7 +93,7 @@ class PromptFormatter:
self.cache.clear()
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:
self.fields = fields
try:
@ -124,7 +124,7 @@ class PromptFormatter:
if field is None:
return
elif field.startswith("$"):
val = builtins.__xonsh__.env[field[1:]]
val = XSH.env[field[1:]]
return _format_value(val, spec, conv)
elif field in self.fields:
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 = line if headlen == 0 else line.rsplit(head[-1], 1)[1]
# 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
if dots is None or len(dots) == 0:
return ""
@ -272,7 +272,7 @@ def is_template_string(template, PROMPT_FIELDS=None):
return False
included_names.discard(None)
if PROMPT_FIELDS is None:
fmtter = builtins.__xonsh__.env.get("PROMPT_FIELDS", PROMPT_FIELDS)
fmtter = XSH.env.get("PROMPT_FIELDS", PROMPT_FIELDS)
else:
fmtter = PROMPT_FIELDS
known_names = set(fmtter.keys())

View file

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

View file

@ -2,8 +2,8 @@
"""Prompt formatter for virtualenv and others"""
import os
import builtins
from xonsh.built_ins import XSH
import xonsh.platform as xp
@ -11,9 +11,9 @@ def find_env_name():
"""Finds the current environment name from $VIRTUAL_ENV or
$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:
env_path = builtins.__xonsh__.env.get("CONDA_DEFAULT_ENV", "")
env_path = XSH.env.get("CONDA_DEFAULT_ENV", "")
env_name = os.path.basename(env_path)
return env_name
@ -23,15 +23,15 @@ def env_name():
``{env_prefix}`` and ``{env_postfix}`` fields.
"""
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
return
venv_prompt = builtins.__xonsh__.env.get("VIRTUAL_ENV_PROMPT")
venv_prompt = XSH.env.get("VIRTUAL_ENV_PROMPT")
if venv_prompt is not None:
return venv_prompt
else:
pf = builtins.__xonsh__.shell.prompt_formatter
pf = XSH.shell.prompt_formatter
pre = pf._get_field_value("env_prefix")
post = pf._get_field_value("env_postfix")
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
and flushes the escape sequence to stdout directly.
"""
env = builtins.__xonsh__.env
env = XSH.env
t = "\033]7;file://{}{}\007"
s = t.format(env.get("HOSTNAME"), env.get("PWD"))
print(s, end="", flush=True)

View file

@ -1,13 +1,12 @@
# -*- coding: utf-8 -*-
"""Informative git status prompt formatter"""
import builtins
import collections
import os
import subprocess
import xonsh.lazyasd as xl
from xonsh.built_ins import XSH
GitStatus = collections.namedtuple(
"GitStatus",
@ -31,13 +30,13 @@ GitStatus = collections.namedtuple(
def _check_output(*args, **kwargs):
kwargs.update(
dict(
env=builtins.__xonsh__.env.detype(),
env=XSH.env.detype(),
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
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
with subprocess.Popen(*args, **kwargs) as proc:
try:
@ -86,7 +85,7 @@ def _DEFS():
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]

View file

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

View file

@ -3,15 +3,15 @@
# pylint:disable=no-member, invalid-name
import os
import sys
import queue
import builtins
import threading
import subprocess
import re
import pathlib
import queue
import re
import subprocess
import sys
import threading
import xonsh.tools as xt
from xonsh.built_ins import XSH
from xonsh.lazyasd import LazyObject
RE_REMOVE_ANSI = LazyObject(
@ -24,7 +24,7 @@ RE_REMOVE_ANSI = LazyObject(
def _run_git_cmd(cmd):
# 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
denv = dict(builtins.__xonsh__.env.detype())
denv = dict(XSH.env.detype())
denv.update({"GIT_OPTIONAL_LOCKS": "0"})
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.
"""
branch = None
timeout = builtins.__xonsh__.env.get("VC_BRANCH_TIMEOUT")
timeout = XSH.env.get("VC_BRANCH_TIMEOUT")
q = queue.Queue()
t = threading.Thread(target=_get_git_branch, args=(q,))
@ -60,7 +60,7 @@ def get_git_branch():
def _get_hg_root(q):
_curpwd = builtins.__xonsh__.env["PWD"]
_curpwd = XSH.env["PWD"]
while True:
if not os.path.isdir(_curpwd):
return False
@ -82,7 +82,7 @@ def get_hg_branch(root=None):
"""Try to get the mercurial branch of the current directory,
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"]
q = queue.Queue()
t = threading.Thread(target=_get_hg_root, args=(q,))
@ -125,7 +125,7 @@ _FIRST_BRANCH_TIMEOUT = True
def _first_branch_timeout_message():
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:
return
_FIRST_BRANCH_TIMEOUT = False
@ -143,7 +143,7 @@ def _first_branch_timeout_message():
def _vc_has(binary):
"""This allows us to locate binaries after git only if necessary"""
cmds = builtins.__xonsh__.commands_cache
cmds = XSH.commands_cache
if cmds.is_empty():
return bool(cmds.locate_binary(binary, ignore_alias=True))
else:
@ -187,7 +187,7 @@ def git_dirty_working_directory():
"""Returns whether or not the git directory is dirty. If this could not
be determined (timeout, file not found, etc.) then this returns None.
"""
env = builtins.__xonsh__.env
env = XSH.env
timeout = env.get("VC_BRANCH_TIMEOUT")
include_untracked = env.get("VC_GIT_INCLUDE_UNTRACKED")
q = queue.Queue()
@ -206,7 +206,7 @@ def hg_dirty_working_directory():
"""Computes whether or not the mercurial working directory is dirty or not.
If this cannot be determined, None is returned.
"""
env = builtins.__xonsh__.env
env = XSH.env
cwd = env["PWD"]
denv = env.detype()
vcbt = env["VC_BRANCH_TIMEOUT"]

View file

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