xonsh/tests/tools.py

224 lines
5.6 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
2015-02-11 02:01:35 -06:00
"""Tests the xonsh lexer."""
from __future__ import unicode_literals, print_function
2016-09-09 00:08:13 -04:00
import os
2015-09-24 19:27:19 -04:00
import sys
2016-08-19 01:45:44 -04:00
import ast
2015-02-11 02:01:35 -06:00
import builtins
2015-10-20 17:53:12 -04:00
import platform
2015-02-11 02:01:35 -06:00
import subprocess
2017-01-08 20:23:07 -05:00
import contextlib
2016-02-20 14:53:00 -05:00
from collections import defaultdict
2016-09-08 21:40:18 -04:00
from collections.abc import MutableMapping
2015-02-11 02:01:35 -06:00
2016-06-23 14:46:15 +02:00
import pytest
2016-06-22 11:33:03 -04:00
from xonsh.environ import Env
2016-02-18 00:45:01 -05:00
from xonsh.base_shell import BaseShell
2015-03-28 17:55:48 -05:00
2015-09-24 19:27:19 -04:00
VER_MAJOR_MINOR = sys.version_info[:2]
2016-02-03 01:29:06 -05:00
VER_FULL = sys.version_info[:3]
2018-08-27 18:13:44 -05:00
ON_DARWIN = platform.system() == "Darwin"
ON_WINDOWS = platform.system() == "Windows"
ON_MSYS = sys.platform == "msys"
ON_CONDA = True in [
conda in pytest.__file__.lower() for conda in ["conda", "anaconda", "miniconda"]
]
ON_TRAVIS = "TRAVIS" in os.environ and "CI" in os.environ
2018-12-06 08:49:49 -05:00
ON_AZURE_PIPELINES = os.environ.get("TF_BUILD", "") == "True"
2018-12-06 08:33:26 -05:00
print("ON_AZURE_PIPELINES", repr(ON_AZURE_PIPELINES))
2018-12-06 09:00:04 -05:00
print("os.environ['TF_BUILD']", repr(os.environ.get("TF_BUILD", "")))
2017-01-11 21:59:42 +08:00
TEST_DIR = os.path.dirname(__file__)
2015-09-24 19:27:19 -04:00
2016-06-29 19:28:39 +03:00
# pytest skip decorators
2018-08-27 18:13:44 -05:00
skip_if_on_conda = pytest.mark.skipif(
ON_CONDA, reason="Conda and virtualenv _really_ hate each other"
)
2018-08-27 18:13:44 -05:00
skip_if_on_msys = pytest.mark.skipif(
ON_MSYS, reason="MSYS and virtualenv _really_ hate each other"
)
2018-08-27 18:13:44 -05:00
skip_if_on_windows = pytest.mark.skipif(ON_WINDOWS, reason="Unix stuff")
2016-06-24 23:51:55 +03:00
2019-02-13 18:49:39 -05:00
skip_if_on_azure_pipelines = pytest.mark.skipif(
ON_AZURE_PIPELINES, reason="not suitable for azure"
)
2018-12-05 20:17:38 -05:00
2018-08-27 18:13:44 -05:00
skip_if_on_unix = pytest.mark.skipif(not ON_WINDOWS, reason="Windows stuff")
2018-08-27 18:13:44 -05:00
skip_if_on_darwin = pytest.mark.skipif(ON_DARWIN, reason="not Mac friendly")
2016-06-28 13:16:12 +03:00
2018-08-27 18:13:44 -05:00
skip_if_on_travis = pytest.mark.skipif(ON_TRAVIS, reason="not Travis CI friendly")
2017-02-12 11:50:34 -05:00
2020-08-26 23:52:47 +02:00
skip_if_pre_3_8 = pytest.mark.skipif(VER_FULL < (3, 8), reason="Python >= 3.8 feature")
2018-07-15 16:37:21 -05:00
2020-08-26 10:10:59 -05:00
2015-02-24 21:58:37 -06:00
def sp(cmd):
return subprocess.check_output(cmd, universal_newlines=True)
2016-06-26 22:09:16 +02:00
2018-08-27 18:13:44 -05:00
class DummyStyler:
styles = defaultdict(str)
2016-02-20 14:53:00 -05:00
2019-10-23 18:14:23 -04:00
highlight_color = "#ffffff"
background_color = "#000000"
2016-06-26 22:09:16 +02:00
2016-02-18 00:45:01 -05:00
class DummyBaseShell(BaseShell):
def __init__(self):
2016-02-20 14:53:00 -05:00
self.styler = DummyStyler()
2016-02-18 00:45:01 -05:00
2015-12-05 15:32:38 -05:00
class DummyShell:
2016-03-02 22:01:44 -05:00
def settitle(self):
2015-12-05 15:32:38 -05:00
pass
2016-02-18 00:45:01 -05:00
_shell = None
@property
def shell(self):
if self._shell is None:
self._shell = DummyBaseShell()
return self._shell
2016-09-09 00:58:32 -04:00
class DummyCommandsCache:
2016-09-09 00:08:13 -04:00
def locate_binary(self, name):
2018-08-27 18:13:44 -05:00
return os.path.join(os.path.dirname(__file__), "bin", name)
2016-09-08 21:40:18 -04:00
def predict_threadable(self, cmd):
2016-09-28 23:45:40 -04:00
return True
2016-09-09 00:58:32 -04:00
class DummyHistory:
2016-09-24 15:15:38 -04:00
last_cmd_rtn = 0
2018-08-27 18:13:44 -05:00
last_cmd_out = ""
2016-09-24 15:15:38 -04:00
def append(self, x):
pass
2016-09-09 00:58:32 -04:00
def flush(self, *args, **kwargs):
pass
2016-09-09 00:58:32 -04:00
2016-09-08 21:40:18 -04:00
class DummyEnv(MutableMapping):
2018-08-27 18:13:44 -05:00
DEFAULTS = {"XONSH_DEBUG": 1, "XONSH_COLOR_STYLE": "default"}
2016-09-08 21:40:18 -04:00
def __init__(self, *args, **kwargs):
self._d = self.DEFAULTS.copy()
self._d.update(dict(*args, **kwargs))
2016-09-08 21:40:18 -04:00
def detype(self):
2016-10-01 23:15:59 -04:00
return {k: str(v) for k, v in self._d.items()}
2016-09-08 21:40:18 -04:00
def __getitem__(self, k):
2019-08-28 14:30:04 -04:00
if k is ...:
return self
else:
return self._d[k]
2016-09-08 21:40:18 -04:00
def __setitem__(self, k, v):
2019-08-28 14:30:04 -04:00
assert k is not ...
2016-09-08 21:40:18 -04:00
self._d[k] = v
def __delitem__(self, k):
2019-08-28 14:30:04 -04:00
assert k is not ...
2016-09-08 21:40:18 -04:00
del self._d[k]
def __len__(self):
return len(self._d)
def __iter__(self):
yield from self._d
2017-01-08 20:23:07 -05:00
@contextlib.contextmanager
def swap(self, other=None, **kwargs):
old = {}
# single positional argument should be a dict-like object
if other is not None:
for k, v in other.items():
old[k] = self.get(k, NotImplemented)
self[k] = v
# kwargs could also have been sent in
for k, v in kwargs.items():
old[k] = self.get(k, NotImplemented)
self[k] = v
yield self
# restore the values
for k, v in old.items():
if v is NotImplemented:
del self[k]
else:
self[k] = v
2019-08-28 14:50:07 -04:00
def is_manually_set(self, key):
return False
2017-01-08 20:23:07 -05:00
2016-06-05 16:25:43 -04:00
#
# Execer tools
#
2016-10-07 10:57:31 -04:00
2016-06-29 19:28:39 +03:00
def check_exec(input, **kwargs):
2018-09-13 14:03:35 -04:00
builtins.__xonsh__.execer.exec(input, **kwargs)
return True
2016-06-05 16:25:43 -04:00
def check_eval(input):
2018-09-13 14:03:35 -04:00
builtins.__xonsh__.env = Env(
2018-08-27 18:13:44 -05:00
{
"AUTO_CD": False,
"XONSH_ENCODING": "utf-8",
"XONSH_ENCODING_ERRORS": "strict",
"PATH": [],
}
)
2016-06-21 11:43:08 -04:00
if ON_WINDOWS:
2018-09-13 14:03:35 -04:00
builtins.__xonsh__.env["PATHEXT"] = [".COM", ".EXE", ".BAT", ".CMD"]
builtins.__xonsh__.execer.eval(input)
return True
2016-06-05 16:25:43 -04:00
2016-06-26 22:09:16 +02:00
2016-06-05 16:25:43 -04:00
def check_parse(input):
2018-09-13 14:03:35 -04:00
tree = builtins.__xonsh__.execer.parse(input, ctx=None)
return tree
2016-08-19 01:45:44 -04:00
2018-08-27 18:13:44 -05:00
2016-08-19 01:45:44 -04:00
#
# Parser tools
#
2016-08-19 12:11:37 -04:00
2016-08-19 01:45:44 -04:00
def nodes_equal(x, y):
__tracebackhide__ = True
2018-08-27 18:13:44 -05:00
assert type(x) == type(y), "Ast nodes do not have the same type: '%s' != '%s' " % (
type(x),
type(y),
)
2016-08-19 01:45:44 -04:00
if isinstance(x, (ast.Expr, ast.FunctionDef, ast.ClassDef)):
2020-08-26 10:10:59 -05:00
assert x.lineno == y.lineno, (
"Ast nodes do not have the same line number : %s != %s"
% (x.lineno, y.lineno,)
2018-08-27 18:13:44 -05:00
)
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 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)):
2016-10-07 10:57:31 -04:00
assert nodes_equal(xchild, ychild), "Ast node children differs"
2016-08-19 01:45:44 -04:00
return True