xonsh/tests/test_environ.py

626 lines
16 KiB
Python
Raw Normal View History

2015-05-14 18:18:46 -05:00
"""Tests the xonsh environment."""
2022-01-31 21:26:34 +05:30
import datetime
2015-05-14 18:18:46 -05:00
import os
2020-09-30 21:36:59 +03:00
import pathlib
2022-01-31 21:26:34 +05:30
import re
from random import shuffle
from tempfile import TemporaryDirectory
from threading import Thread
from time import sleep
import pytest
2018-08-30 09:18:49 -05:00
from xonsh.environ import (
Env,
2022-01-31 21:26:34 +05:30
InternalEnvironDict,
2019-08-06 14:39:11 -04:00
LsColors,
Var,
2022-01-31 21:26:34 +05:30
default_env,
default_value,
locate_binary,
make_args_env,
2018-08-30 09:18:49 -05:00
)
2022-03-24 00:46:50 +05:30
from xonsh.pytest.tools import skip_if_on_unix
2022-01-31 21:26:34 +05:30
from xonsh.tools import DefaultNotGiven, always_true
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"]])
2020-10-07 19:22:02 +03:00
def test_env_path_dirs_list(path):
env = Env(MYPATH=path, MYDIRS=path)
2018-08-30 09:18:49 -05:00
assert path == env["MYPATH"].paths
2020-10-07 19:22:02 +03:00
assert path == env["MYDIRS"].paths
2018-08-30 09:18:49 -05:00
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})
env.register("YO", validate=always_true, convert=None, detype=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
def test_thread_local_swap():
env = Env(a="orig")
iter_count = 10
num_threads = 4
success_variables = [False] * (num_threads + 1)
def loop(index, swapped_values=None):
if swapped_values:
if env["a"] != "orig":
success_variables[index] = False
return
env.set_swapped_values(swapped_values)
for _ in range(iter_count):
if env["a"] != "swapped":
success_variables[index] = False
break
with env.swap(a=index):
update test xsh usage (#4581) * todo * test: remove usage of DummyEnv and setting .env attribute on xession fixture one step closer to making too much of tweaking to xession during tests * test: fix tests vox and gitstatus-prompt * docs: update test-fixture usage * fix: import flake8 error * test: remove direct access to XSH in tests * test: remove usage of XSH in test files * todo * test: use tmp-dir to create stubs * refactor: use fixture factory to mock out XonshSession * refactor: remove direct access of XSH from functions * refactor: remove direct access of XSH from functions * fix: qa checks * refactor: rename variables to match their values * test: update failing tests because it had no PATH set previously * fix: remove builtins usage from pyghooks.py * style: * refactor: update tests to use fixtures * fix: env varialbe is setup per function some tests accidentally update the env variables and that is leaking into next tests * fix: failing vox tests * test: set commands_cache per test * test: fix failing tests * fix: failing tests on linux ptk-highlight * fix: failing tests on Windows cwd-prompt * test: copy env as to not affect original object * fix: lazily evaluate cmds-cache in pyghooks * test: fix failing tests * fix: qa errors import * test: set commands-cache per test while caching path results * test: speedup test_thread_local_swap * fix: failing tests on windows * refactor: Execer doesn't control session * refactor: XSH.unload will take care of reversing builtins attrs set * test: use env.update over monkeypatch * Revert "test: use env.update over monkeypatch" This reverts commit 010a5022247a098f1741966b8af1bf758663480e.
2022-01-08 04:03:22 +05:30
sleep(0.01)
if env["a"] == index:
success_variables[index] = True
else:
success_variables[index] = False
break
update test xsh usage (#4581) * todo * test: remove usage of DummyEnv and setting .env attribute on xession fixture one step closer to making too much of tweaking to xession during tests * test: fix tests vox and gitstatus-prompt * docs: update test-fixture usage * fix: import flake8 error * test: remove direct access to XSH in tests * test: remove usage of XSH in test files * todo * test: use tmp-dir to create stubs * refactor: use fixture factory to mock out XonshSession * refactor: remove direct access of XSH from functions * refactor: remove direct access of XSH from functions * fix: qa checks * refactor: rename variables to match their values * test: update failing tests because it had no PATH set previously * fix: remove builtins usage from pyghooks.py * style: * refactor: update tests to use fixtures * fix: env varialbe is setup per function some tests accidentally update the env variables and that is leaking into next tests * fix: failing vox tests * test: set commands_cache per test * test: fix failing tests * fix: failing tests on linux ptk-highlight * fix: failing tests on Windows cwd-prompt * test: copy env as to not affect original object * fix: lazily evaluate cmds-cache in pyghooks * test: fix failing tests * fix: qa errors import * test: set commands-cache per test while caching path results * test: speedup test_thread_local_swap * fix: failing tests on windows * refactor: Execer doesn't control session * refactor: XSH.unload will take care of reversing builtins attrs set * test: use env.update over monkeypatch * Revert "test: use env.update over monkeypatch" This reverts commit 010a5022247a098f1741966b8af1bf758663480e.
2022-01-08 04:03:22 +05:30
sleep(0.01)
with env.swap(a="swapped"):
threads = [
Thread(target=loop, args=(i, env.get_swapped_values()))
for i in range(1, num_threads + 1)
]
for t in threads:
t.start()
loop(0)
for t in threads:
t.join()
assert all(success_variables)
@skip_if_on_unix
def test_locate_binary_on_windows(xession):
2018-08-30 09:18:49 -05:00
files = ("file1.exe", "FILE2.BAT", "file3.txt")
with TemporaryDirectory() as tmpdir:
2020-10-21 03:52:31 +03:00
tmpdir = os.path.realpath(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)
xession.env.update({"PATH": [tmpdir], "PATHEXT": [".COM", ".EXE", ".BAT"]})
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
update test xsh usage (#4581) * todo * test: remove usage of DummyEnv and setting .env attribute on xession fixture one step closer to making too much of tweaking to xession during tests * test: fix tests vox and gitstatus-prompt * docs: update test-fixture usage * fix: import flake8 error * test: remove direct access to XSH in tests * test: remove usage of XSH in test files * todo * test: use tmp-dir to create stubs * refactor: use fixture factory to mock out XonshSession * refactor: remove direct access of XSH from functions * refactor: remove direct access of XSH from functions * fix: qa checks * refactor: rename variables to match their values * test: update failing tests because it had no PATH set previously * fix: remove builtins usage from pyghooks.py * style: * refactor: update tests to use fixtures * fix: env varialbe is setup per function some tests accidentally update the env variables and that is leaking into next tests * fix: failing vox tests * test: set commands_cache per test * test: fix failing tests * fix: failing tests on linux ptk-highlight * fix: failing tests on Windows cwd-prompt * test: copy env as to not affect original object * fix: lazily evaluate cmds-cache in pyghooks * test: fix failing tests * fix: qa errors import * test: set commands-cache per test while caching path results * test: speedup test_thread_local_swap * fix: failing tests on windows * refactor: Execer doesn't control session * refactor: XSH.unload will take care of reversing builtins attrs set * test: use env.update over monkeypatch * Revert "test: use env.update over monkeypatch" This reverts commit 010a5022247a098f1741966b8af1bf758663480e.
2022-01-08 04:03:22 +05:30
def test_event_on_envvar_change(xession, env):
env["TEST"] = 0
2017-01-30 14:45:35 +02:00
share = []
# register
2020-06-13 01:36:22 -04:00
@xession.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
update test xsh usage (#4581) * todo * test: remove usage of DummyEnv and setting .env attribute on xession fixture one step closer to making too much of tweaking to xession during tests * test: fix tests vox and gitstatus-prompt * docs: update test-fixture usage * fix: import flake8 error * test: remove direct access to XSH in tests * test: remove usage of XSH in test files * todo * test: use tmp-dir to create stubs * refactor: use fixture factory to mock out XonshSession * refactor: remove direct access of XSH from functions * refactor: remove direct access of XSH from functions * fix: qa checks * refactor: rename variables to match their values * test: update failing tests because it had no PATH set previously * fix: remove builtins usage from pyghooks.py * style: * refactor: update tests to use fixtures * fix: env varialbe is setup per function some tests accidentally update the env variables and that is leaking into next tests * fix: failing vox tests * test: set commands_cache per test * test: fix failing tests * fix: failing tests on linux ptk-highlight * fix: failing tests on Windows cwd-prompt * test: copy env as to not affect original object * fix: lazily evaluate cmds-cache in pyghooks * test: fix failing tests * fix: qa errors import * test: set commands-cache per test while caching path results * test: speedup test_thread_local_swap * fix: failing tests on windows * refactor: Execer doesn't control session * refactor: XSH.unload will take care of reversing builtins attrs set * test: use env.update over monkeypatch * Revert "test: use env.update over monkeypatch" This reverts commit 010a5022247a098f1741966b8af1bf758663480e.
2022-01-08 04:03:22 +05:30
def test_event_on_envvar_new(xession, env):
2017-01-30 15:41:48 +02:00
share = []
# register
2020-06-13 01:36:22 -04:00
@xession.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]
update test xsh usage (#4581) * todo * test: remove usage of DummyEnv and setting .env attribute on xession fixture one step closer to making too much of tweaking to xession during tests * test: fix tests vox and gitstatus-prompt * docs: update test-fixture usage * fix: import flake8 error * test: remove direct access to XSH in tests * test: remove usage of XSH in test files * todo * test: use tmp-dir to create stubs * refactor: use fixture factory to mock out XonshSession * refactor: remove direct access of XSH from functions * refactor: remove direct access of XSH from functions * fix: qa checks * refactor: rename variables to match their values * test: update failing tests because it had no PATH set previously * fix: remove builtins usage from pyghooks.py * style: * refactor: update tests to use fixtures * fix: env varialbe is setup per function some tests accidentally update the env variables and that is leaking into next tests * fix: failing vox tests * test: set commands_cache per test * test: fix failing tests * fix: failing tests on linux ptk-highlight * fix: failing tests on Windows cwd-prompt * test: copy env as to not affect original object * fix: lazily evaluate cmds-cache in pyghooks * test: fix failing tests * fix: qa errors import * test: set commands-cache per test while caching path results * test: speedup test_thread_local_swap * fix: failing tests on windows * refactor: Execer doesn't control session * refactor: XSH.unload will take care of reversing builtins attrs set * test: use env.update over monkeypatch * Revert "test: use env.update over monkeypatch" This reverts commit 010a5022247a098f1741966b8af1bf758663480e.
2022-01-08 04:03:22 +05:30
def test_event_on_envvar_change_from_none_value(xession, env):
env["TEST"] = None
share = []
# register
2020-06-13 01:36:22 -04:00
@xession.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"])
update test xsh usage (#4581) * todo * test: remove usage of DummyEnv and setting .env attribute on xession fixture one step closer to making too much of tweaking to xession during tests * test: fix tests vox and gitstatus-prompt * docs: update test-fixture usage * fix: import flake8 error * test: remove direct access to XSH in tests * test: remove usage of XSH in test files * todo * test: use tmp-dir to create stubs * refactor: use fixture factory to mock out XonshSession * refactor: remove direct access of XSH from functions * refactor: remove direct access of XSH from functions * fix: qa checks * refactor: rename variables to match their values * test: update failing tests because it had no PATH set previously * fix: remove builtins usage from pyghooks.py * style: * refactor: update tests to use fixtures * fix: env varialbe is setup per function some tests accidentally update the env variables and that is leaking into next tests * fix: failing vox tests * test: set commands_cache per test * test: fix failing tests * fix: failing tests on linux ptk-highlight * fix: failing tests on Windows cwd-prompt * test: copy env as to not affect original object * fix: lazily evaluate cmds-cache in pyghooks * test: fix failing tests * fix: qa errors import * test: set commands-cache per test while caching path results * test: speedup test_thread_local_swap * fix: failing tests on windows * refactor: Execer doesn't control session * refactor: XSH.unload will take care of reversing builtins attrs set * test: use env.update over monkeypatch * Revert "test: use env.update over monkeypatch" This reverts commit 010a5022247a098f1741966b8af1bf758663480e.
2022-01-08 04:03:22 +05:30
def test_event_on_envvar_change_no_fire_when_value_is_same(val, xession, env):
env["TEST"] = val
share = []
# register
2020-06-13 01:36:22 -04:00
@xession.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
update test xsh usage (#4581) * todo * test: remove usage of DummyEnv and setting .env attribute on xession fixture one step closer to making too much of tweaking to xession during tests * test: fix tests vox and gitstatus-prompt * docs: update test-fixture usage * fix: import flake8 error * test: remove direct access to XSH in tests * test: remove usage of XSH in test files * todo * test: use tmp-dir to create stubs * refactor: use fixture factory to mock out XonshSession * refactor: remove direct access of XSH from functions * refactor: remove direct access of XSH from functions * fix: qa checks * refactor: rename variables to match their values * test: update failing tests because it had no PATH set previously * fix: remove builtins usage from pyghooks.py * style: * refactor: update tests to use fixtures * fix: env varialbe is setup per function some tests accidentally update the env variables and that is leaking into next tests * fix: failing vox tests * test: set commands_cache per test * test: fix failing tests * fix: failing tests on linux ptk-highlight * fix: failing tests on Windows cwd-prompt * test: copy env as to not affect original object * fix: lazily evaluate cmds-cache in pyghooks * test: fix failing tests * fix: qa errors import * test: set commands-cache per test while caching path results * test: speedup test_thread_local_swap * fix: failing tests on windows * refactor: Execer doesn't control session * refactor: XSH.unload will take care of reversing builtins attrs set * test: use env.update over monkeypatch * Revert "test: use env.update over monkeypatch" This reverts commit 010a5022247a098f1741966b8af1bf758663480e.
2022-01-08 04:03:22 +05:30
def test_events_on_envvar_called_in_right_order(xession, env):
2017-01-31 12:51:26 +02:00
share = []
# register
2020-06-13 01:36:22 -04:00
@xession.builtins.events.on_envvar_new
2017-01-31 12:51:26 +02:00
def handler(name, value, **kwargs):
2018-08-30 09:18:49 -05:00
share[:] = ["new"]
2017-01-31 12:51:26 +02:00
@xession.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_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.default) for (k, v) in env._vars.items() if isinstance(v.default, 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
update test xsh usage (#4581) * todo * test: remove usage of DummyEnv and setting .env attribute on xession fixture one step closer to making too much of tweaking to xession during tests * test: fix tests vox and gitstatus-prompt * docs: update test-fixture usage * fix: import flake8 error * test: remove direct access to XSH in tests * test: remove usage of XSH in test files * todo * test: use tmp-dir to create stubs * refactor: use fixture factory to mock out XonshSession * refactor: remove direct access of XSH from functions * refactor: remove direct access of XSH from functions * fix: qa checks * refactor: rename variables to match their values * test: update failing tests because it had no PATH set previously * fix: remove builtins usage from pyghooks.py * style: * refactor: update tests to use fixtures * fix: env varialbe is setup per function some tests accidentally update the env variables and that is leaking into next tests * fix: failing vox tests * test: set commands_cache per test * test: fix failing tests * fix: failing tests on linux ptk-highlight * fix: failing tests on Windows cwd-prompt * test: copy env as to not affect original object * fix: lazily evaluate cmds-cache in pyghooks * test: fix failing tests * fix: qa errors import * test: set commands-cache per test while caching path results * test: speedup test_thread_local_swap * fix: failing tests on windows * refactor: Execer doesn't control session * refactor: XSH.unload will take care of reversing builtins attrs set * test: use env.update over monkeypatch * Revert "test: use env.update over monkeypatch" This reverts commit 010a5022247a098f1741966b8af1bf758663480e.
2022-01-08 04:03:22 +05:30
def test_lscolors_target(xession):
2019-08-06 14:39:11 -04:00
lsc = LsColors.fromstring("ln=target")
2020-09-23 20:50:31 +02:00
assert lsc["ln"] == ("RESET",)
2020-06-13 01:36:22 -04:00
assert lsc.is_target("ln")
2019-08-06 14:39:11 -04:00
assert lsc.detype() == "ln=target"
2020-06-13 01:36:22 -04:00
assert not (lsc.is_target("mi"))
2020-01-04 13:56:02 -05:00
@pytest.mark.parametrize(
"key_in,old_in,new_in,test",
[
2020-09-23 20:50:31 +02:00
("fi", ("RESET",), ("BLUE",), "existing key, change value"),
("fi", ("RESET",), ("RESET",), "existing key, no change in value"),
("tw", None, ("RESET",), "create new key"),
2020-01-04 13:56:02 -05:00
("pi", ("BACKGROUND_BLACK", "YELLOW"), None, "delete existing key"),
],
)
def test_lscolors_events(key_in, old_in, new_in, test, xession):
2020-06-09 21:47:59 -04:00
lsc = LsColors.fromstring("fi=0:di=01;34:pi=40;33")
2020-09-23 20:50:31 +02:00
# corresponding colors: [('RESET',), ('BOLD_CYAN',), ('BOLD_CYAN',), ('BACKGROUND_BLACK', 'YELLOW')]
event_fired = False
2020-01-04 13:56:02 -05:00
@xession.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
xession.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
def test_register_custom_var_generic():
"""Test that a registered envvar without any type is treated
permissively.
"""
env = Env()
assert "MY_SPECIAL_VAR" not in env
env.register("MY_SPECIAL_VAR")
assert "MY_SPECIAL_VAR" in env
env["MY_SPECIAL_VAR"] = 32
assert env["MY_SPECIAL_VAR"] == 32
env["MY_SPECIAL_VAR"] = True
2020-09-11 01:11:29 -04:00
assert env["MY_SPECIAL_VAR"] is True
def test_register_custom_var_int():
env = Env()
2020-08-26 10:10:59 -05:00
env.register("MY_SPECIAL_VAR", type="int")
env["MY_SPECIAL_VAR"] = "32"
assert env["MY_SPECIAL_VAR"] == 32
with pytest.raises(ValueError):
env["MY_SPECIAL_VAR"] = "wakka"
def test_register_custom_var_float():
env = Env()
2020-08-26 10:10:59 -05:00
env.register("MY_SPECIAL_VAR", type="float")
env["MY_SPECIAL_VAR"] = "27"
assert env["MY_SPECIAL_VAR"] == 27.0
with pytest.raises(ValueError):
env["MY_SPECIAL_VAR"] = "wakka"
2020-08-26 10:10:59 -05:00
@pytest.mark.parametrize(
"val,converted",
[
(True, True),
(32, True),
(0, False),
(27.0, True),
(None, False),
("lol", True),
("false", False),
("no", False),
],
)
def test_register_custom_var_bool(val, converted):
env = Env()
2020-08-26 10:10:59 -05:00
env.register("MY_SPECIAL_VAR", type="bool")
env["MY_SPECIAL_VAR"] = val
assert env["MY_SPECIAL_VAR"] == converted
2020-08-26 10:10:59 -05:00
@pytest.mark.parametrize(
"val,converted",
[
(32, "32"),
(0, "0"),
(27.0, "27.0"),
(None, ""),
2020-08-26 10:10:59 -05:00
("lol", "lol"),
("false", "false"),
("no", "no"),
],
)
def test_register_custom_var_str(val, converted):
env = Env()
2020-08-26 10:10:59 -05:00
env.register("MY_SPECIAL_VAR", type="str")
env["MY_SPECIAL_VAR"] = val
assert env["MY_SPECIAL_VAR"] == converted
2020-09-30 21:36:59 +03:00
def test_register_var_path():
env = Env()
2020-09-30 21:36:59 +03:00
env.register("MY_PATH_VAR", type="path")
path = "/tmp"
2020-09-30 21:36:59 +03:00
env["MY_PATH_VAR"] = path
assert env["MY_PATH_VAR"] == pathlib.Path(path)
# Empty string is None to avoid uncontrolled converting empty string to Path('.')
path = ""
2020-09-30 21:36:59 +03:00
env["MY_PATH_VAR"] = path
2021-09-26 21:02:24 +05:30
assert env["MY_PATH_VAR"] is None
2020-09-30 21:36:59 +03:00
with pytest.raises(TypeError):
env["MY_PATH_VAR"] = 42
def test_register_custom_var_env_path():
env = Env()
env.register("MY_SPECIAL_VAR", type="env_path")
paths = ["/home/wakka", "/home/wakka/bin"]
env["MY_SPECIAL_VAR"] = paths
2020-08-26 10:10:59 -05:00
assert hasattr(env["MY_SPECIAL_VAR"], "paths")
assert env["MY_SPECIAL_VAR"].paths == paths
with pytest.raises(TypeError):
env["MY_SPECIAL_VAR"] = 32
2020-08-16 18:46:02 -05:00
def test_deregister_custom_var():
env = Env()
2020-09-30 21:36:59 +03:00
env.register("MY_SPECIAL_VAR", type="env_path")
env.deregister("MY_SPECIAL_VAR")
assert "MY_SPECIAL_VAR" not in env
2020-09-30 21:36:59 +03:00
env.register("MY_SPECIAL_VAR", type="env_path")
paths = ["/home/wakka", "/home/wakka/bin"]
env["MY_SPECIAL_VAR"] = paths
env.deregister("MY_SPECIAL_VAR")
# deregistering a variable that has a value set doesn't
# remove it from env;
# the existing variable also maintains its type validation, conversion
assert "MY_SPECIAL_VAR" in env
with pytest.raises(TypeError):
env["MY_SPECIAL_VAR"] = 32
# removing, then re-adding the variable without registering
# gives it only default permissive validation, conversion
del env["MY_SPECIAL_VAR"]
env["MY_SPECIAL_VAR"] = 32
def test_register_callable_default():
def is_date(x):
return isinstance(x, datetime.date)
@default_value
def today(env):
return datetime.date.today()
# registration should not raise a value error just because
# default is a function which generates the proper type.
env = Env()
env.register("TODAY", default=today, validate=is_date)
def test_env_iterate():
env = Env(TEST=0)
env.register(re.compile("re"))
for key in env:
assert isinstance(key, str)
2020-08-16 18:46:02 -05:00
def test_env_iterate_rawkeys():
env = Env(TEST=0)
2020-08-16 19:13:35 -05:00
r = re.compile("re")
env.register(r)
2020-08-16 18:46:02 -05:00
saw_regex = False
for key in env.rawkeys():
if isinstance(key, str):
continue
2020-08-16 19:13:35 -05:00
elif isinstance(key, type(r)) and key.pattern == "re":
2020-08-16 18:46:02 -05:00
saw_regex = True
assert saw_regex
2020-09-08 00:12:43 -04:00
def test_env_get_defaults():
"""Verify the rather complex rules for env.get("<envvar>",default) value when envvar is not defined."""
2020-09-08 00:12:43 -04:00
env = Env(TEST1=0)
env.register("TEST_REG", default="abc")
env.register("TEST_REG_DNG", default=DefaultNotGiven)
# var is defined, registered is don't-care => value is defined value
assert env.get("TEST1", 22) == 0
# var not defined, not registered => value is immediate default
assert env.get("TEST2", 22) == 22
assert "TEST2" not in env
# var not defined, is registered, reg default is not sentinel => value is *registered* default
assert env.get("TEST_REG", 22) == "abc"
assert "TEST_REG" in env
# var not defined, is registered, reg default is sentinel => value is *immediate* default
assert env.get("TEST_REG_DNG", 22) == 22
assert "TEST_REG_DNG" not in env
@pytest.mark.parametrize(
"val,validator",
[
("string", "is_string"),
(1, "is_int"),
(0.5, "is_float"),
],
)
def test_var_with_default_initer(val, validator):
var = Var.with_default(val)
assert var.validate.__name__ == validator
def test_thread_local_dict():
d = InternalEnvironDict()
d["a"] = 1
assert d["a"] == 1
d.set_locally("a", 2)
assert d["a"] == 2
d.set_locally("a", 3)
assert d["a"] == 3
d["a"] = 4
assert d["a"] == 4
d.del_locally("a")
assert d["a"] == 1
d.set_locally("a", 5)
assert d.pop("a") == 5
assert d["a"] == 1
d.set_locally("a", 6)
assert d.popitem() == ("a", 6)
assert d["a"] == 1
assert d.pop("a", "nope") == 1
assert d.pop("a", "nope") == "nope"
assert "a" not in d
def test_thread_local_dict_multiple():
d = InternalEnvironDict()
num_threads = 5
thread_values = [None] * num_threads
def thread(i):
2022-01-31 20:30:57 +05:30
d.set_locally("a", i**2)
sleep(0.1)
thread_values[i] = d["a"]
sleep(0.1)
d.del_locally("a")
sleep(0.1)
threads = [Thread(target=thread, args=(i,)) for i in range(num_threads)]
shuffle(threads)
for t in threads:
t.start()
for t in threads:
t.join()
2022-01-31 20:30:57 +05:30
assert thread_values == [i**2 for i in range(num_threads)]