xonsh/tests/test_environ.py

344 lines
9.3 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
2015-05-14 18:18:46 -05:00
"""Tests the xonsh environment."""
from __future__ import unicode_literals, print_function
import os
import itertools
from tempfile import TemporaryDirectory
from xonsh.tools import always_true
import pytest
2016-09-25 15:54:31 -04:00
from xonsh.commands_cache import CommandsCache
2018-08-30 09:18:49 -05:00
from xonsh.environ import (
Env,
2019-02-13 19:12:53 -05:00
Ensurer,
2018-08-30 09:18:49 -05:00
locate_binary,
DEFAULT_ENSURERS,
DEFAULT_VALUES,
default_env,
make_args_env,
2019-08-06 14:39:11 -04:00
LsColors,
2018-08-30 09:18:49 -05:00
)
2015-05-14 18:18:46 -05:00
from tools import skip_if_on_unix
2016-05-16 02:02:24 -04:00
2018-08-30 09:18:49 -05:00
2015-05-14 18:18:46 -05:00
def test_env_normal():
2018-08-30 09:18:49 -05:00
env = Env(VAR="wakka")
assert "wakka" == env["VAR"]
2015-05-14 18:18:46 -05:00
def test_env_contains():
2018-08-30 09:18:49 -05:00
env = Env(VAR="wakka")
assert "VAR" in env
2018-08-30 09:18:49 -05:00
@pytest.mark.parametrize("path", [["/home/wakka"], ["wakka"]])
2016-07-01 12:42:07 +03:00
def test_env_path_list(path):
env = Env(MYPATH=path)
2018-08-30 09:18:49 -05:00
assert path == env["MYPATH"].paths
2016-07-01 12:42:07 +03:00
2018-08-30 09:18:49 -05:00
@pytest.mark.parametrize(
"path",
[["/home/wakka" + os.pathsep + "/home/jawaka"], ["wakka" + os.pathsep + "jawaka"]],
)
2016-07-01 12:42:07 +03:00
def test_env_path_str(path):
env = Env(MYPATH=path)
2018-08-30 09:18:49 -05:00
assert path == env["MYPATH"].paths
2015-05-14 18:18:46 -05:00
def test_env_detype():
2018-08-30 09:18:49 -05:00
env = Env(MYPATH=["wakka", "jawaka"])
assert "wakka" + os.pathsep + "jawaka" == env.detype()["MYPATH"]
2015-05-14 18:18:46 -05:00
2018-08-30 09:18:49 -05:00
@pytest.mark.parametrize(
"path1, path2",
[(["/home/wakka", "/home/jawaka"], "/home/woah"), (["wakka", "jawaka"], "woah")],
)
2016-07-01 12:42:07 +03:00
def test_env_detype_mutable_access_clear(path1, path2):
env = Env(MYPATH=path1)
2018-08-30 09:18:49 -05:00
assert path1[0] + os.pathsep + path1[1] == env.detype()["MYPATH"]
env["MYPATH"][0] = path2
2016-06-22 17:14:27 -04:00
assert env._detyped is None
2018-08-30 09:18:49 -05:00
assert path2 + os.pathsep + path1[1] == env.detype()["MYPATH"]
2015-05-14 18:18:46 -05:00
def test_env_detype_no_dict():
2018-08-30 09:18:49 -05:00
env = Env(YO={"hey": 42})
2019-03-06 23:08:26 -08:00
env.set_ensurer("YO", Ensurer(always_true, None, None))
2015-05-14 18:18:46 -05:00
det = env.detype()
2018-08-30 09:18:49 -05:00
assert "YO" not in det
2015-05-14 18:18:46 -05:00
2016-07-03 22:03:06 +03:00
def test_histcontrol_none():
2015-11-28 16:12:41 -07:00
env = Env(HISTCONTROL=None)
2018-08-30 09:18:49 -05:00
assert isinstance(env["HISTCONTROL"], set)
assert len(env["HISTCONTROL"]) == 0
2015-11-28 16:12:41 -07:00
2016-07-01 12:42:07 +03:00
def test_HISTCONTROL_empty():
2018-08-30 09:18:49 -05:00
env = Env(HISTCONTROL="")
assert isinstance(env["HISTCONTROL"], set)
assert len(env["HISTCONTROL"]) == 0
2015-11-28 16:12:41 -07:00
2016-07-03 22:03:06 +03:00
def test_histcontrol_ignoredups():
2018-08-30 09:18:49 -05:00
env = Env(HISTCONTROL="ignoredups")
assert isinstance(env["HISTCONTROL"], set)
assert len(env["HISTCONTROL"]) == 1
assert "ignoredups" in env["HISTCONTROL"]
assert "ignoreerr" not in env["HISTCONTROL"]
2015-11-28 16:12:41 -07:00
2016-07-03 22:03:06 +03:00
def test_histcontrol_ignoreerr_ignoredups():
2018-08-30 09:18:49 -05:00
env = Env(HISTCONTROL="ignoreerr,ignoredups,ignoreerr")
assert len(env["HISTCONTROL"]) == 2
assert "ignoreerr" in env["HISTCONTROL"]
assert "ignoredups" in env["HISTCONTROL"]
2015-11-28 16:12:41 -07:00
def test_histcontrol_ignoreerr_ignoredups_erase_dups():
env = Env(HISTCONTROL="ignoreerr,ignoredups,ignoreerr,erasedups")
assert len(env["HISTCONTROL"]) == 3
assert "ignoreerr" in env["HISTCONTROL"]
assert "ignoredups" in env["HISTCONTROL"]
assert "erasedups" in env["HISTCONTROL"]
def test_swap():
2018-08-30 09:18:49 -05:00
env = Env(VAR="wakka")
assert env["VAR"] == "wakka"
# positional arg
2018-08-30 09:18:49 -05:00
with env.swap({"VAR": "foo"}):
assert env["VAR"] == "foo"
# make sure the environment goes back outside the context manager
2018-08-30 09:18:49 -05:00
assert env["VAR"] == "wakka"
# kwargs only
2018-08-30 09:18:49 -05:00
with env.swap(VAR1="foo", VAR2="bar"):
assert env["VAR1"] == "foo"
assert env["VAR2"] == "bar"
# positional and kwargs
2018-08-30 09:18:49 -05:00
with env.swap({"VAR3": "baz"}, VAR1="foo", VAR2="bar"):
assert env["VAR1"] == "foo"
assert env["VAR2"] == "bar"
assert env["VAR3"] == "baz"
# make sure the environment goes back outside the context manager
2018-08-30 09:18:49 -05:00
assert env["VAR"] == "wakka"
assert "VAR1" not in env
assert "VAR2" not in env
assert "VAR3" not in env
2018-08-21 15:21:46 -04:00
def test_swap_exception_replacement():
2018-08-30 09:18:49 -05:00
env = Env(VAR="original value")
2018-08-21 15:21:46 -04:00
try:
2018-08-30 09:18:49 -05:00
with env.swap(VAR="inner value"):
assert env["VAR"] == "inner value"
2018-08-21 15:21:46 -04:00
raise Exception()
except Exception:
2018-08-30 09:18:49 -05:00
assert env["VAR"] == "original value"
assert env["VAR"] == "original value"
2018-08-21 15:21:46 -04:00
@skip_if_on_unix
2016-07-01 12:42:07 +03:00
def test_locate_binary_on_windows(xonsh_builtins):
2018-08-30 09:18:49 -05:00
files = ("file1.exe", "FILE2.BAT", "file3.txt")
with TemporaryDirectory() as tmpdir:
for fname in files:
fpath = os.path.join(tmpdir, fname)
2018-08-30 09:18:49 -05:00
with open(fpath, "w") as f:
f.write(fpath)
2018-09-13 14:03:35 -04:00
xonsh_builtins.__xonsh__.env.update(
2018-08-30 09:18:49 -05:00
{"PATH": [tmpdir], "PATHEXT": [".COM", ".EXE", ".BAT"]}
)
2018-09-13 14:03:35 -04:00
xonsh_builtins.__xonsh__.commands_cache = CommandsCache()
2018-08-30 09:18:49 -05:00
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")
assert locate_binary("file2.bat") == os.path.join(tmpdir, "FILE2.BAT")
assert locate_binary("file3") is None
2017-01-30 14:45:35 +02:00
def test_event_on_envvar_change(xonsh_builtins):
2017-01-30 14:45:35 +02:00
env = Env(TEST=0)
2018-09-13 14:03:35 -04:00
xonsh_builtins.__xonsh__.env = env
2017-01-30 14:45:35 +02:00
share = []
# register
@xonsh_builtins.events.on_envvar_change
2017-01-30 14:45:35 +02:00
def handler(name, oldvalue, newvalue, **kwargs):
share.extend((name, oldvalue, newvalue))
2017-01-30 14:45:35 +02:00
# trigger
2018-08-30 09:18:49 -05:00
env["TEST"] = 1
2017-01-30 14:45:35 +02:00
2018-08-30 09:18:49 -05:00
assert share == ["TEST", 0, 1]
2017-01-30 15:41:48 +02:00
def test_event_on_envvar_new(xonsh_builtins):
env = Env()
2018-09-13 14:03:35 -04:00
xonsh_builtins.__xonsh__.env = env
2017-01-30 15:41:48 +02:00
share = []
# register
@xonsh_builtins.events.on_envvar_new
def handler(name, value, **kwargs):
share.extend((name, value))
# trigger
2018-08-30 09:18:49 -05:00
env["TEST"] = 1
assert share == ["TEST", 1]
def test_event_on_envvar_change_from_none_value(xonsh_builtins):
env = Env(TEST=None)
2018-09-13 14:03:35 -04:00
xonsh_builtins.__xonsh__.env = env
share = []
# register
@xonsh_builtins.events.on_envvar_change
2017-01-30 15:41:48 +02:00
def handler(name, oldvalue, newvalue, **kwargs):
share.extend((name, oldvalue, newvalue))
2017-01-30 15:41:48 +02:00
# trigger
2018-08-30 09:18:49 -05:00
env["TEST"] = 1
2017-01-30 15:41:48 +02:00
2018-08-30 09:18:49 -05:00
assert share == ["TEST", None, 1]
2018-08-30 09:18:49 -05:00
@pytest.mark.parametrize("val", [1, None, True, "ok"])
def test_event_on_envvar_change_no_fire_when_value_is_same(val, xonsh_builtins):
env = Env(TEST=val)
2018-09-13 14:03:35 -04:00
xonsh_builtins.__xonsh__.env = env
share = []
# register
@xonsh_builtins.events.on_envvar_change
def handler(name, oldvalue, newvalue, **kwargs):
share.extend((name, oldvalue, newvalue))
# trigger
2018-08-30 09:18:49 -05:00
env["TEST"] = val
assert share == []
2017-01-31 12:51:26 +02:00
def test_events_on_envvar_called_in_right_order(xonsh_builtins):
env = Env()
2018-09-13 14:03:35 -04:00
xonsh_builtins.__xonsh__.env = env
2017-01-31 12:51:26 +02:00
share = []
# register
@xonsh_builtins.events.on_envvar_new
def handler(name, value, **kwargs):
2018-08-30 09:18:49 -05:00
share[:] = ["new"]
2017-01-31 12:51:26 +02:00
@xonsh_builtins.events.on_envvar_change
2020-01-04 13:56:02 -05:00
def handler1(name, oldvalue, newvalue, **kwargs):
2018-08-30 09:18:49 -05:00
share[:] = ["change"]
2017-01-31 12:51:26 +02:00
# trigger new
2018-08-30 09:18:49 -05:00
env["TEST"] = 1
2017-01-31 12:51:26 +02:00
2018-08-30 09:18:49 -05:00
assert share == ["new"]
2017-01-31 12:51:26 +02:00
# trigger change
2018-08-30 09:18:49 -05:00
env["TEST"] = 2
2017-01-31 12:51:26 +02:00
2018-08-30 09:18:49 -05:00
assert share == ["change"]
2017-01-31 12:51:26 +02:00
def test_int_bool_envvars_have_ensurers():
bool_ints = [type(envvar) in [bool, int] for envvar in DEFAULT_VALUES.values()]
key_mask = set(itertools.compress(DEFAULT_VALUES.keys(), bool_ints))
ensurer_keys = set(DEFAULT_ENSURERS.keys())
assert len(key_mask.intersection(ensurer_keys)) == len(key_mask)
def test_no_lines_columns():
2018-08-30 09:18:49 -05:00
os.environ["LINES"] = "spam"
os.environ["COLUMNS"] = "eggs"
try:
env = default_env()
2018-08-30 09:18:49 -05:00
assert "LINES" not in env
assert "COLUMNS" not in env
finally:
2018-08-30 09:18:49 -05:00
del os.environ["LINES"]
del os.environ["COLUMNS"]
2018-07-20 20:41:00 -04:00
def test_make_args_env():
2018-08-30 09:18:49 -05:00
obs = make_args_env(["script", "1", "2", "3"])
2018-07-20 20:41:00 -04:00
exp = {
2018-08-30 09:18:49 -05:00
"ARGS": ["script", "1", "2", "3"],
"ARG0": "script",
"ARG1": "1",
"ARG2": "2",
"ARG3": "3",
2018-07-20 20:41:00 -04:00
}
assert exp == obs
2019-04-26 20:27:45 +02:00
2019-04-26 20:27:45 +02:00
def test_delitem():
env = Env(VAR="a value")
assert env["VAR"] == "a value"
del env["VAR"]
2019-04-26 20:27:45 +02:00
with pytest.raises(Exception):
env["VAR"]
2019-04-26 20:27:45 +02:00
def test_delitem_default():
env = Env()
a_key, a_value = next(
(k, v) for (k, v) in env._defaults.items() if isinstance(v, str)
)
2019-04-26 20:27:45 +02:00
del env[a_key]
assert env[a_key] == a_value
del env[a_key]
assert env[a_key] == a_value
2019-08-06 14:39:11 -04:00
def test_lscolors_target():
lsc = LsColors.fromstring("ln=target")
assert lsc["ln"] == ("TARGET",)
assert lsc.detype() == "ln=target"
2020-01-04 13:56:02 -05:00
@pytest.mark.parametrize(
"key_in,old_in,new_in,test",
[
2020-06-09 21:47:59 -04:00
("fi", ("NO_COLOR",), ("BLUE",), "existing key, change value"),
("fi", ("NO_COLOR",), ("NO_COLOR",), "existing key, no change in value"),
2020-01-04 13:56:02 -05:00
("tw", None, ("NO_COLOR",), "create new key"),
("pi", ("BACKGROUND_BLACK", "YELLOW"), None, "delete existing key"),
],
)
def test_lscolors_events(key_in, old_in, new_in, test, xonsh_builtins):
2020-06-09 21:47:59 -04:00
lsc = LsColors.fromstring("fi=0:di=01;34:pi=40;33")
# corresponding colors: [('NO_COLOR',), ('BOLD_CYAN',), ('BOLD_CYAN',), ('BACKGROUND_BLACK', 'YELLOW')]
event_fired = False
2020-01-04 13:56:02 -05:00
@xonsh_builtins.events.on_lscolors_change
2020-01-04 13:56:02 -05:00
def handler(key, oldvalue, newvalue, **kwargs):
nonlocal old_in, new_in, key_in, event_fired
2020-01-04 13:56:02 -05:00
assert (
key == key_in and oldvalue == old_in and newvalue == new_in
), "Old and new event values match"
event_fired = True
xonsh_builtins.__xonsh__.env["LS_COLORS"] = lsc
if new_in is None:
lsc.pop(key_in, "argle")
else:
lsc[key_in] = new_in
if old_in == new_in:
assert not event_fired, "No event if value doesn't change"
else:
assert event_fired