This commit is contained in:
Anthony Scopatz 2019-02-13 18:49:39 -05:00
parent 470517ff21
commit 1c6b1e1ea4
10 changed files with 151 additions and 144 deletions

View file

@ -3,40 +3,40 @@ import pytest
from xonsh.ansi_colors import ansi_color_escape_code_to_name, ansi_reverse_style
RS = ansi_reverse_style(style='default')
RS = ansi_reverse_style(style="default")
@pytest.mark.parametrize('key, value', [
('', 'NO_COLOR'),
('31', 'RED'),
])
@pytest.mark.parametrize("key, value", [("", "NO_COLOR"), ("31", "RED")])
def test_ansi_reverse_style(key, value):
assert key in RS
assert RS[key] == value
@pytest.mark.parametrize('inp, exp', [
('0', ('NO_COLOR',)),
('\0010\002', ('NO_COLOR',)),
('\033[0m', ('NO_COLOR',)),
('\001\033[0m\002', ('NO_COLOR',)),
('00;36', ('CYAN',)),
('01;31', ('BOLD_RED',)),
('04;31', ('UNDERLINE_RED',)),
('1;4;31', ('BOLD_UNDERLINE_RED',)),
('4;1;31', ('BOLD_UNDERLINE_RED',)),
('31;42', ('RED', 'BACKGROUND_GREEN')),
('42;31', ('BACKGROUND_GREEN', 'RED')),
('40', ('BACKGROUND_BLACK',)),
('38;5;89', ('PURPLE',),),
('48;5;89', ('BACKGROUND_PURPLE',),),
('38;2;170;0;0', ('RED',),),
('48;2;170;0;0', ('BACKGROUND_RED',),),
('1;38;5;124', ('BOLD_RED',),),
('4;1;38;2;170;0;0', ('BOLD_UNDERLINE_RED',),),
('1;38;5;40', ('BOLD_GREEN',),),
('48;5;16;38;5;184', ('BACKGROUND_BLACK', 'INTENSE_YELLOW')),
])
@pytest.mark.parametrize(
"inp, exp",
[
("0", ("NO_COLOR",)),
("\0010\002", ("NO_COLOR",)),
("\033[0m", ("NO_COLOR",)),
("\001\033[0m\002", ("NO_COLOR",)),
("00;36", ("CYAN",)),
("01;31", ("BOLD_RED",)),
("04;31", ("UNDERLINE_RED",)),
("1;4;31", ("BOLD_UNDERLINE_RED",)),
("4;1;31", ("BOLD_UNDERLINE_RED",)),
("31;42", ("RED", "BACKGROUND_GREEN")),
("42;31", ("BACKGROUND_GREEN", "RED")),
("40", ("BACKGROUND_BLACK",)),
("38;5;89", ("PURPLE",)),
("48;5;89", ("BACKGROUND_PURPLE",)),
("38;2;170;0;0", ("RED",)),
("48;2;170;0;0", ("BACKGROUND_RED",)),
("1;38;5;124", ("BOLD_RED",)),
("4;1;38;2;170;0;0", ("BOLD_UNDERLINE_RED",)),
("1;38;5;40", ("BOLD_GREEN",)),
("48;5;16;38;5;184", ("BACKGROUND_BLACK", "INTENSE_YELLOW")),
],
)
def test_ansi_color_escape_code_to_name(inp, exp):
obs = ansi_color_escape_code_to_name(inp, 'default', reversed_style=RS)
assert obs == exp
obs = ansi_color_escape_code_to_name(inp, "default", reversed_style=RS)
assert obs == exp

View file

@ -64,7 +64,7 @@ def test_parse_aliases():
"__XONSH_ALIAS_END__\n"
"more filth"
)
obs = parse_aliases(s, 'bash')
obs = parse_aliases(s, "bash")
assert exp == obs

View file

@ -56,7 +56,7 @@ def test_premain_D(shell):
def test_premain_custom_rc(shell, tmpdir, monkeypatch):
monkeypatch.setattr(sys.stdin, "isatty", lambda: True)
monkeypatch.setitem(os.environ, "XONSH_CACHE_SCRIPTS", 'False')
monkeypatch.setitem(os.environ, "XONSH_CACHE_SCRIPTS", "False")
f = tmpdir.join("wakkawakka")
f.write("print('hi')")
args = xonsh.main.premain(["--rc", f.strpath])
@ -78,7 +78,7 @@ def test_force_interactive_custom_rc_with_script(shell, tmpdir, monkeypatch):
"""Calling a custom RC file on a script-call with the interactive flag
should run interactively
"""
monkeypatch.setitem(os.environ, "XONSH_CACHE_SCRIPTS", 'False')
monkeypatch.setitem(os.environ, "XONSH_CACHE_SCRIPTS", "False")
f = tmpdir.join("wakkawakka")
f.write("print('hi')")
args = xonsh.main.premain(["-i", "--rc", f.strpath, "tests/sample.xsh"])
@ -120,8 +120,10 @@ def test_premain_invalid_arguments(shell, case, capsys):
xonsh.main.premain([case])
assert "unrecognized argument" in capsys.readouterr()[1]
def test_premain_timings_arg(shell):
xonsh.main.premain(['--timings'])
xonsh.main.premain(["--timings"])
def test_xonsh_failback(shell, monkeypatch, monkeypatch_stderr):
failback_checker = []

View file

@ -106,74 +106,65 @@ def test_format_prompt_with_no_env(formatter, xonsh_builtins, live_fields):
xonsh_builtins.__xonsh__.shell.prompt_formatter = formatter
env = Env()
env.pop('VIRTUAL_ENV', None) # For virtualenv
env.pop('CONDA_DEFAULT_ENV', None) # For conda/CircleCI
env.pop("VIRTUAL_ENV", None) # For virtualenv
env.pop("CONDA_DEFAULT_ENV", None) # For conda/CircleCI
xonsh_builtins.__xonsh__.env = env
assert formatter('{env_name}', fields=live_fields) == ''
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):
@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
env = Env(VIRTUAL_ENV=envname)
xonsh_builtins.__xonsh__.env = env
exp = live_fields['env_prefix'] + envname + live_fields['env_postfix']
assert formatter('{env_name}', fields=live_fields) == exp
exp = live_fields["env_prefix"] + envname + live_fields["env_postfix"]
assert formatter("{env_name}", fields=live_fields) == exp
@pytest.mark.parametrize('pre', ['(', '[[', '', ' '])
@pytest.mark.parametrize('post', [')', ']]', '', ' '])
@pytest.mark.parametrize("pre", ["(", "[[", "", " "])
@pytest.mark.parametrize("post", [")", "]]", "", " "])
def test_format_prompt_with_various_prepost(
formatter,
xonsh_builtins,
live_fields,
pre,
post,
formatter, xonsh_builtins, live_fields, pre, post
):
xonsh_builtins.__xonsh__.shell.prompt_formatter = formatter
env = Env(VIRTUAL_ENV='env')
env = Env(VIRTUAL_ENV="env")
xonsh_builtins.__xonsh__.env = env
live_fields.update({'env_prefix': pre, 'env_postfix': post})
live_fields.update({"env_prefix": pre, "env_postfix": post})
exp = pre + 'env' + post
assert formatter('{env_name}', fields=live_fields) == exp
exp = pre + "env" + post
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
env = Env(VIRTUAL_ENV='env', VIRTUAL_ENV_DISABLE_PROMPT=1)
env = Env(VIRTUAL_ENV="env", VIRTUAL_ENV_DISABLE_PROMPT=1)
xonsh_builtins.__xonsh__.env = env
exp = ''
assert formatter('{env_name}', fields=live_fields) == exp
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,
):
@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
prompt = '!venv active! '
prompt = "!venv active! "
env = Env(
VIRTUAL_ENV='env',
VIRTUAL_ENV_PROMPT=prompt,
VIRTUAL_ENV_DISABLE_PROMPT=disable,
VIRTUAL_ENV="env", VIRTUAL_ENV_PROMPT=prompt, VIRTUAL_ENV_DISABLE_PROMPT=disable
)
xonsh_builtins.__xonsh__.env = env
exp = '' if disable else prompt
assert formatter('{env_name}', fields=live_fields) == exp
exp = "" if disable else prompt
assert formatter("{env_name}", fields=live_fields) == exp
def test_promptformatter_cache(formatter):

View file

@ -375,22 +375,25 @@ def test_subproc_toks_pyeval_nested():
assert exp == obs
@pytest.mark.parametrize('phrase', [
'xandy',
'xory',
'xand',
'andy',
'xor',
'ory',
'x-and',
'x-or',
'and-y',
'or-y',
'x-and-y',
'x-or-y',
'in/and/path',
'in/or/path',
])
@pytest.mark.parametrize(
"phrase",
[
"xandy",
"xory",
"xand",
"andy",
"xor",
"ory",
"x-and",
"x-or",
"and-y",
"or-y",
"x-and-y",
"x-or-y",
"in/and/path",
"in/or/path",
],
)
def test_subproc_toks_and_or(phrase):
s = "echo " + phrase
exp = "![{0}]".format(s)

View file

@ -51,7 +51,9 @@ skip_if_on_msys = pytest.mark.skipif(
skip_if_on_windows = pytest.mark.skipif(ON_WINDOWS, reason="Unix stuff")
skip_if_on_azure_pipelines = pytest.mark.skipif(ON_AZURE_PIPELINES, reason="not suitable for azure")
skip_if_on_azure_pipelines = pytest.mark.skipif(
ON_AZURE_PIPELINES, reason="not suitable for azure"
)
skip_if_on_unix = pytest.mark.skipif(not ON_WINDOWS, reason="Windows stuff")
@ -201,9 +203,11 @@ 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"

View file

@ -117,7 +117,7 @@ def ansi_color_style(style="default"):
return cmap
def ansi_reverse_style(style='default', return_style=False):
def ansi_reverse_style(style="default", return_style=False):
"""Reverses an ANSI color style mapping so that escape codes map to
colors. Style may either be string or mapping. May also return
the style it looked up.
@ -126,22 +126,22 @@ def ansi_reverse_style(style='default', return_style=False):
reversed_style = {v: k for k, v in style.items()}
# add keys to make this more useful
updates = {
'1': 'BOLD_',
'2': 'FAINT_',
'4': 'UNDERLINE_',
'5': 'SLOWBLINK_',
'1;4': 'BOLD_UNDERLINE_',
'4;1': 'BOLD_UNDERLINE_',
'38': 'SET_FOREGROUND_',
'48': 'SET_BACKGROUND_',
'38;2': 'SET_FOREGROUND_3INTS_',
'48;2': 'SET_BACKGROUND_3INTS_',
'38;5': 'SET_FOREGROUND_SHORT_',
'48;5': 'SET_BACKGROUND_SHORT_',
"1": "BOLD_",
"2": "FAINT_",
"4": "UNDERLINE_",
"5": "SLOWBLINK_",
"1;4": "BOLD_UNDERLINE_",
"4;1": "BOLD_UNDERLINE_",
"38": "SET_FOREGROUND_",
"48": "SET_BACKGROUND_",
"38;2": "SET_FOREGROUND_3INTS_",
"48;2": "SET_BACKGROUND_3INTS_",
"38;5": "SET_FOREGROUND_SHORT_",
"48;5": "SET_BACKGROUND_SHORT_",
}
for ec, name in reversed_style.items():
no_left_zero = ec.lstrip('0')
if no_left_zero.startswith(';'):
no_left_zero = ec.lstrip("0")
if no_left_zero.startswith(";"):
updates[no_left_zero[1:]] = name
elif no_left_zero != ec:
updates[no_left_zero] = name
@ -155,40 +155,40 @@ def ansi_reverse_style(style='default', return_style=False):
@lazyobject
def ANSI_ESCAPE_CODE_RE():
return re.compile(r'\001?(\033\[)?([0-9;]+)m?\002?')
return re.compile(r"\001?(\033\[)?([0-9;]+)m?\002?")
@lazyobject
def ANSI_REVERSE_COLOR_NAME_TRANSLATIONS():
base = {
'SET_FOREGROUND_FAINT_': 'SET_FOREGROUND_3INTS_',
'SET_BACKGROUND_FAINT_': 'SET_BACKGROUND_3INTS_',
'SET_FOREGROUND_SLOWBLINK_': 'SET_FOREGROUND_SHORT_',
'SET_BACKGROUND_SLOWBLINK_': 'SET_BACKGROUND_SHORT_',
"SET_FOREGROUND_FAINT_": "SET_FOREGROUND_3INTS_",
"SET_BACKGROUND_FAINT_": "SET_BACKGROUND_3INTS_",
"SET_FOREGROUND_SLOWBLINK_": "SET_FOREGROUND_SHORT_",
"SET_BACKGROUND_SLOWBLINK_": "SET_BACKGROUND_SHORT_",
}
data = {'UNDERLINE_BOLD_': 'BOLD_UNDERLINE_'}
data = {"UNDERLINE_BOLD_": "BOLD_UNDERLINE_"}
data.update(base)
data.update({'BOLD_' + k: 'BOLD_' + v for k, v in base.items()})
data.update({'UNDERLINE_' + k: 'UNDERLINE_' + v for k, v in base.items()})
data.update({'BOLD_UNDERLINE_' + k: 'BOLD_UNDERLINE_' + v for k, v in base.items()})
data.update({'UNDERLINE_BOLD_' + k: 'BOLD_UNDERLINE_' + v for k, v in base.items()})
data.update({"BOLD_" + k: "BOLD_" + v for k, v in base.items()})
data.update({"UNDERLINE_" + k: "UNDERLINE_" + v for k, v in base.items()})
data.update({"BOLD_UNDERLINE_" + k: "BOLD_UNDERLINE_" + v for k, v in base.items()})
data.update({"UNDERLINE_BOLD_" + k: "BOLD_UNDERLINE_" + v for k, v in base.items()})
return data
@lazyobject
def ANSI_COLOR_NAME_SET_3INTS_RE():
return re.compile(r'(\w+_)?SET_(FORE|BACK)GROUND_3INTS_(\d+)_(\d+)_(\d+)')
return re.compile(r"(\w+_)?SET_(FORE|BACK)GROUND_3INTS_(\d+)_(\d+)_(\d+)")
@lazyobject
def ANSI_COLOR_NAME_SET_SHORT_RE():
return re.compile(r'(\w+_)?SET_(FORE|BACK)GROUND_SHORT_(\d+)')
return re.compile(r"(\w+_)?SET_(FORE|BACK)GROUND_SHORT_(\d+)")
def _color_name_from_ints(ints, background=False, prefix=None):
name = find_closest_color(ints, BASE_XONSH_COLORS)
if background:
name = 'BACKGROUND_' + name
name = "BACKGROUND_" + name
name = name if prefix is None else prefix + name
return name
@ -215,8 +215,8 @@ def ansi_color_escape_code_to_name(escape_code, style, reversed_style=None):
names = []
n_ints = 0
seen_set_foreback = False
for e in ec.split(';'):
no_left_zero = e.lstrip('0') if len(e) > 1 else e
for e in ec.split(";"):
no_left_zero = e.lstrip("0") if len(e) > 1 else e
if seen_set_foreback and n_ints > 0:
names.append(e)
n_ints -= 1
@ -226,49 +226,53 @@ def ansi_color_escape_code_to_name(escape_code, style, reversed_style=None):
else:
names.append(reversed_style.get(no_left_zero, no_left_zero))
# set the flags for next time
if '38' == e or '48' == e:
if "38" == e or "48" == e:
seen_set_foreback = True
elif '2' == e:
elif "2" == e:
n_ints = 3
elif '5' == e:
elif "5" == e:
n_ints = 1
# normalize names
n = ''
n = ""
norm_names = []
colors = set(reversed_style.values())
for name in names:
if name == 'NO_COLOR':
if name == "NO_COLOR":
# skip most '0' entries
continue
n = n + name if n else name
n = ANSI_REVERSE_COLOR_NAME_TRANSLATIONS.get(n, n)
if n.endswith('_'):
if n.endswith("_"):
continue
elif ANSI_COLOR_NAME_SET_SHORT_RE.match(n) is not None:
pre, fore_back, short = ANSI_COLOR_NAME_SET_SHORT_RE.match(n).groups()
n = _color_name_from_ints(short_to_ints(short),
background=(fore_back == 'BACK'),
prefix=pre)
n = _color_name_from_ints(
short_to_ints(short), background=(fore_back == "BACK"), prefix=pre
)
elif ANSI_COLOR_NAME_SET_3INTS_RE.match(n) is not None:
pre, fore_back, r, g, b = ANSI_COLOR_NAME_SET_3INTS_RE.match(n).groups()
n = _color_name_from_ints((int(r), int(g), int(b)),
background=(fore_back == 'BACK'),
prefix=pre)
elif 'GROUND_3INTS_' in n:
n = _color_name_from_ints(
(int(r), int(g), int(b)), background=(fore_back == "BACK"), prefix=pre
)
elif "GROUND_3INTS_" in n:
# have 1 or 2, but not 3 ints
n += '_'
n += "_"
continue
# error check
if n not in colors:
msg = ("Could not translate ANSI color code {escape_code!r} "
"into a known color in the palette. Specifically, the {n!r} "
"portion of {name!r} in {names!r} seems to missing.")
raise ValueError(msg.format(escape_code=escape_code, names=names, name=name, n=n))
msg = (
"Could not translate ANSI color code {escape_code!r} "
"into a known color in the palette. Specifically, the {n!r} "
"portion of {name!r} in {names!r} seems to missing."
)
raise ValueError(
msg.format(escape_code=escape_code, names=names, name=name, n=n)
)
norm_names.append(n)
n = ''
n = ""
# return
if len(norm_names) == 0:
return ('NO_COLOR',)
return ("NO_COLOR",)
else:
return tuple(norm_names)

View file

@ -609,7 +609,7 @@ class SubprocSpec:
def _cmd_event_name(self):
if callable(self.alias):
return self.alias.__name__
return self.alias.__name__
elif self.binary_loc is None:
return "<not-found>"
else:

View file

@ -365,7 +365,7 @@ class LsColors(cabc.MutableMapping):
if self._detyped is None:
self._detyped = ":".join(
[
key + "=" + ";".join([style[v] or '0' for v in val])
key + "=" + ";".join([style[v] or "0" for v in val])
for key, val in sorted(self._d.items())
]
)
@ -421,13 +421,15 @@ class LsColors(cabc.MutableMapping):
if filename is not None:
cmd.append(filename)
# get env
if hasattr(builtins, "__xonsh__") and hasattr(builtins.__xonsh__, 'env'):
if hasattr(builtins, "__xonsh__") and hasattr(builtins.__xonsh__, "env"):
denv = builtins.__xonsh__.env.detype()
else:
denv = None
# run dircolors
try:
out = subprocess.check_output(cmd, env=denv, universal_newlines=True, stderr=subprocess.DEVNULL)
out = subprocess.check_output(
cmd, env=denv, universal_newlines=True, stderr=subprocess.DEVNULL
)
except (subprocess.CalledProcessError, FileNotFoundError):
return cls(cls.default_settings)
s = out.splitlines()[0]
@ -460,7 +462,7 @@ def ensure_ls_colors_in_env(spec=None, **kwargs):
ls command is called.
"""
env = builtins.__xonsh__.env
if 'LS_COLORS' not in env._d:
if "LS_COLORS" not in env._d:
# this adds it to the env too
default_lscolors(env)
events.on_pre_spec_run_ls.discard(ensure_ls_colors_in_env)
@ -664,13 +666,13 @@ def xonsh_append_newline(env):
@default_value
def default_lscolors(env):
"""Gets a default instanse of LsColors"""
inherited_lscolors = os_environ.get('LS_COLORS', None)
inherited_lscolors = os_environ.get("LS_COLORS", None)
if inherited_lscolors is None:
lsc = LsColors.fromdircolors()
else:
lsc = LsColors.fromstring(inherited_lscolors)
# have to place this in the env, so it is applied
env['LS_COLORS'] = lsc
env["LS_COLORS"] = lsc
return lsc

View file

@ -1088,6 +1088,7 @@ def swap_values(d, updates, default=_DEFAULT_SENTINEL):
# Validators and converters
#
def detype(x):
"""This assumes that the object has a detype method, and calls that."""
return x.detype()