xonsh/tests/test_pyghooks.py

340 lines
11 KiB
Python
Raw Normal View History

2019-03-11 18:34:54 -04:00
"""Tests pygments hooks."""
import pytest
import os
import stat
import pathlib
2019-03-11 18:34:54 -04:00
from tempfile import TemporaryDirectory
from xonsh.platform import ON_WINDOWS
2019-03-11 18:34:54 -04:00
from xonsh.pyghooks import (
XonshStyle,
Color,
color_name_to_pygments_code,
code_by_name,
color_file,
file_color_tokens,
)
from xonsh.environ import LsColors
@pytest.fixture
def xonsh_builtins_LS_COLORS(xonsh_builtins):
"""Xonsh environment including LS_COLORS"""
e = xonsh_builtins.__xonsh__.env
lsc = LsColors(LsColors.default_settings)
xonsh_builtins.__xonsh__.env["LS_COLORS"] = lsc
xonsh_builtins.__xonsh__.shell.shell_type = "prompt_toolkit"
2020-06-13 01:36:22 -04:00
xonsh_builtins.__xonsh__.shell.shell.styler = XonshStyle() # default style
yield xonsh_builtins
2020-06-13 01:36:22 -04:00
xonsh_builtins.__xonsh__.env = e
2019-03-11 18:34:54 -04:00
DEFAULT_STYLES = {
# Reset
2020-09-23 20:50:31 +02:00
Color.RESET: "noinherit", # Text Reset
2019-03-11 18:34:54 -04:00
# Regular Colors
2019-03-12 18:36:18 -04:00
Color.BLACK: "ansiblack",
Color.BLUE: "ansiblue",
Color.CYAN: "ansicyan",
Color.GREEN: "ansigreen",
Color.PURPLE: "ansimagenta",
Color.RED: "ansired",
Color.WHITE: "ansigray",
Color.YELLOW: "ansiyellow",
Color.INTENSE_BLACK: "ansibrightblack",
Color.INTENSE_BLUE: "ansibrightblue",
Color.INTENSE_CYAN: "ansibrightcyan",
Color.INTENSE_GREEN: "ansibrightgreen",
Color.INTENSE_PURPLE: "ansibrightmagenta",
Color.INTENSE_RED: "ansibrightred",
Color.INTENSE_WHITE: "ansiwhite",
Color.INTENSE_YELLOW: "ansibrightyellow",
2019-03-11 18:34:54 -04:00
}
@pytest.mark.parametrize(
"name, exp",
[
2020-09-23 20:50:31 +02:00
("RESET", "noinherit"),
2019-03-11 18:34:54 -04:00
("RED", "ansired"),
("BACKGROUND_RED", "bg:ansired"),
("BACKGROUND_INTENSE_RED", "bg:ansibrightred"),
("BOLD_RED", "bold ansired"),
("UNDERLINE_RED", "underline ansired"),
("BOLD_UNDERLINE_RED", "bold underline ansired"),
("UNDERLINE_BOLD_RED", "underline bold ansired"),
# test unsupported modifiers
("BOLD_FAINT_RED", "bold ansired"),
("BOLD_SLOWBLINK_RED", "bold ansired"),
("BOLD_FASTBLINK_RED", "bold ansired"),
("BOLD_INVERT_RED", "bold ansired"),
("BOLD_CONCEAL_RED", "bold ansired"),
("BOLD_STRIKETHROUGH_RED", "bold ansired"),
# test hexes
("#000", "#000"),
("#000000", "#000000"),
("BACKGROUND_#000", "bg:#000"),
("BACKGROUND_#000000", "bg:#000000"),
("BG#000", "bg:#000"),
("bg#000000", "bg:#000000"),
],
)
def test_color_name_to_pygments_code(name, exp):
styles = DEFAULT_STYLES.copy()
obs = color_name_to_pygments_code(name, styles)
assert obs == exp
2019-03-12 18:36:18 -04:00
@pytest.mark.parametrize(
"name, exp",
[
2020-09-23 20:50:31 +02:00
("RESET", "noinherit"),
2019-03-12 18:36:18 -04:00
("RED", "ansired"),
("BACKGROUND_RED", "bg:ansired"),
("BACKGROUND_INTENSE_RED", "bg:ansibrightred"),
("BOLD_RED", "bold ansired"),
("UNDERLINE_RED", "underline ansired"),
("BOLD_UNDERLINE_RED", "bold underline ansired"),
("UNDERLINE_BOLD_RED", "underline bold ansired"),
# test unsupported modifiers
("BOLD_FAINT_RED", "bold ansired"),
("BOLD_SLOWBLINK_RED", "bold ansired"),
("BOLD_FASTBLINK_RED", "bold ansired"),
("BOLD_INVERT_RED", "bold ansired"),
("BOLD_CONCEAL_RED", "bold ansired"),
("BOLD_STRIKETHROUGH_RED", "bold ansired"),
# test hexes
("#000", "#000"),
("#000000", "#000000"),
("BACKGROUND_#000", "bg:#000"),
("BACKGROUND_#000000", "bg:#000000"),
("BG#000", "bg:#000"),
("bg#000000", "bg:#000000"),
],
)
def test_code_by_name(name, exp):
styles = DEFAULT_STYLES.copy()
obs = code_by_name(name, styles)
assert obs == exp
@pytest.mark.parametrize(
"in_tuple, exp_ct, exp_ansi_colors",
[
2020-09-23 20:50:31 +02:00
(("RESET",), Color.RESET, "noinherit"),
(("GREEN",), Color.GREEN, "ansigreen"),
(("BOLD_RED",), Color.BOLD_RED, "bold ansired"),
2020-01-04 13:56:02 -05:00
(
("BACKGROUND_BLACK", "BOLD_GREEN"),
Color.BACKGROUND_BLACK__BOLD_GREEN,
"bg:ansiblack bold ansigreen",
),
],
)
2020-01-04 13:56:02 -05:00
def test_color_token_by_name(
in_tuple, exp_ct, exp_ansi_colors, xonsh_builtins_LS_COLORS
):
from xonsh.pyghooks import XonshStyle, color_token_by_name
xs = XonshStyle()
styles = xs.styles
ct = color_token_by_name(in_tuple, styles)
ansi_colors = styles[ct] # if keyerror, ct was not cached
assert ct == exp_ct, "returned color token is right"
assert ansi_colors == exp_ansi_colors, "color token mapped to correct color string"
def test_XonshStyle_init_file_color_tokens(xonsh_builtins_LS_COLORS):
xs = XonshStyle()
assert xs.styles
assert type(file_color_tokens) is dict
2020-01-04 13:56:02 -05:00
assert set(file_color_tokens.keys()) == set(
xonsh_builtins_LS_COLORS.__xonsh__.env["LS_COLORS"].keys()
)
2020-06-10 22:07:50 -04:00
# parameterized tests for file colorization
# note 'ca' is checked by standalone test.
# requires privilege to create a file with capabilities
if ON_WINDOWS:
# file coloring support is very limited on Windows, only test the cases we can easily make work
# If you care about file colors, use Windows Subsystem for Linux, or another OS.
_cf = {
"fi": "regular",
"di": "simple_dir",
"ln": "sym_link",
"pi": None,
"so": None,
"do": None,
# bug ci failures: 'bd': '/dev/sda',
# bug ci failures:'cd': '/dev/tty',
"or": "orphan",
"mi": None, # never used
"su": None,
"sg": None,
"ca": None, # Separate special case test,
"tw": None,
"ow": None,
"st": None,
"ex": None, # executable is a filetype test on Windows.
"*.emf": "foo.emf",
"*.zip": "foo.zip",
"*.ogg": "foo.ogg",
"mh": "hard_link",
}
else:
# full-fledged, VT100 based infrastructure
_cf = {
"fi": "regular",
"di": "simple_dir",
"ln": "sym_link",
"pi": "pipe",
"so": None,
"do": None,
# bug ci failures: 'bd': '/dev/sda',
# bug ci failures:'cd': '/dev/tty',
"or": "orphan",
"mi": None, # never used
"su": "set_uid",
"sg": "set_gid",
"ca": None, # Separate special case test,
"tw": "sticky_ow_dir",
"ow": "other_writable_dir",
"st": "sticky_dir",
"ex": "executable",
"*.emf": "foo.emf",
"*.zip": "foo.zip",
"*.ogg": "foo.ogg",
"mh": "hard_link",
}
2020-01-04 08:32:42 -05:00
@pytest.fixture(scope="module")
def colorizable_files():
"""populate temp dir with sample files.
2020-01-04 08:32:42 -05:00
(too hard to emit indivual test cases when fixture invoked in mark.parametrize)"""
with TemporaryDirectory() as tempdir:
for k, v in _cf.items():
if v is None:
continue
if v.startswith("/"):
file_path = v
else:
file_path = tempdir + "/" + v
try:
os.lstat(file_path)
except FileNotFoundError:
if file_path.endswith("_dir"):
os.mkdir(file_path)
else:
open(file_path, "a").close()
2020-06-09 21:47:59 -04:00
if k in ("di", "fi"):
pass
elif k == "ex":
os.chmod(file_path, stat.S_IRWXU) # tmpdir on windows need u+w
elif k == "ln": # cook ln test case.
os.chmod(file_path, stat.S_IRWXU) # link to *executable* file
2020-06-13 01:36:22 -04:00
os.rename(file_path, file_path + "_target")
os.symlink(file_path + "_target", file_path)
elif k == "or":
os.rename(file_path, file_path + "_target")
os.symlink(file_path + "_target", file_path)
os.remove(file_path + "_target")
elif k == "pi": # not on Windows
os.remove(file_path)
os.mkfifo(file_path)
elif k == "su":
os.chmod(file_path, stat.S_ISUID)
elif k == "sg":
os.chmod(file_path, stat.S_ISGID)
elif k == "st":
2020-01-04 13:56:02 -05:00
os.chmod(
file_path, stat.S_ISVTX | stat.S_IRUSR | stat.S_IWUSR
) # TempDir requires o:r
elif k == "tw":
os.chmod(
2020-01-04 13:56:02 -05:00
file_path,
stat.S_ISVTX | stat.S_IWOTH | stat.S_IRUSR | stat.S_IWUSR,
)
elif k == "ow":
os.chmod(file_path, stat.S_IWOTH | stat.S_IRUSR | stat.S_IWUSR)
2020-06-09 21:47:59 -04:00
elif k == "mh":
os.rename(file_path, file_path + "_target")
os.link(file_path + "_target", file_path)
else:
pass # cauterize those elseless ifs!
2020-06-13 01:36:22 -04:00
os.symlink(file_path, file_path + "_symlink")
2020-01-04 08:32:42 -05:00
yield tempdir
pass # tempdir get cleaned up here.
2020-01-04 13:56:02 -05:00
@pytest.mark.parametrize(
"key,file_path", [(key, file_path) for key, file_path in _cf.items() if file_path],
2020-01-04 13:56:02 -05:00
)
2020-01-04 08:32:42 -05:00
def test_colorize_file(key, file_path, colorizable_files, xonsh_builtins_LS_COLORS):
"""test proper file codes with symlinks colored normally"""
2020-06-13 01:36:22 -04:00
ffp = colorizable_files + "/" + file_path
stat_result = os.lstat(ffp)
color_token, color_key = color_file(ffp, stat_result)
assert color_key == key, "File classified as expected kind"
assert color_token == file_color_tokens[key], "Color token is as expected"
@pytest.mark.parametrize(
"key,file_path", [(key, file_path) for key, file_path in _cf.items() if file_path],
2020-06-13 01:36:22 -04:00
)
def test_colorize_file_symlink(
key, file_path, colorizable_files, xonsh_builtins_LS_COLORS
):
"""test proper file codes with symlinks colored target."""
2020-06-13 01:36:22 -04:00
xonsh_builtins_LS_COLORS.__xonsh__.env["LS_COLORS"]["ln"] = "target"
ffp = colorizable_files + "/" + file_path + "_symlink"
2020-06-09 21:47:59 -04:00
stat_result = os.lstat(ffp)
2020-06-13 01:36:22 -04:00
assert stat.S_ISLNK(stat_result.st_mode)
_, color_key = color_file(ffp, stat_result)
2020-06-09 21:47:59 -04:00
try:
tar_stat_result = os.stat(ffp) # stat the target of the link
tar_ffp = str(pathlib.Path(ffp).resolve())
_, tar_color_key = color_file(tar_ffp, tar_stat_result)
if tar_color_key.startswith("*"):
tar_color_key = (
"fi" # all the *.* zoo, link is colored 'fi', not target type.
)
except FileNotFoundError: # orphan symlinks always colored 'or'
tar_color_key = "or" # Fake if for missing file
2020-06-10 22:07:50 -04:00
assert color_key == tar_color_key, "File classified as expected kind, via symlink"
2020-06-13 01:36:22 -04:00
import xonsh.lazyimps
2020-06-10 22:07:50 -04:00
def test_colorize_file_ca(xonsh_builtins_LS_COLORS, monkeypatch):
def mock_os_listxattr(*args, **kwards):
return ["security.capability"]
2020-06-10 22:07:50 -04:00
monkeypatch.setattr(xonsh.pyghooks, "os_listxattr", mock_os_listxattr)
2020-06-10 22:07:50 -04:00
with TemporaryDirectory() as tmpdir:
file_path = tmpdir + "/cap_file"
open(file_path, "a").close()
os.chmod(
file_path, stat.S_IRWXU
) # ca overrides ex, leave file deletable on Windows
2020-06-10 22:07:50 -04:00
color_token, color_key = color_file(file_path, os.lstat(file_path))
assert color_key == "ca"