From 7f8aeefae80b0c28715a744a7564a28bc93703c4 Mon Sep 17 00:00:00 2001 From: Daniel Shimon Date: Fri, 28 May 2021 15:42:37 +0300 Subject: [PATCH] tests: Run tests with the amalgamated xonsh (#4290) * tests: Run tests with the amalgamated xonsh * tests: Test xonsh loads correctly interactively * tests: Ensure tests run from amalgamated xonsh * environ: Separate $XONSH_DEBUG and $XONSH_NO_AMALGAMATE * tests: Keep XONSH_NO_AMALGAMATE in a comment for ease of debugging * tests: Fix monkeypatch for amalgamated code --- news/run-tests-amalgamated.rst | 23 +++++++++++++++++++ requirements/tests.txt | 3 +++ run-tests.xsh | 6 ++++- setup.py | 2 +- tests/completers/test_xompletions.py | 6 ++--- tests/test_integrations.py | 33 +++++++++++++++++++++++++--- xonsh/__init__.py | 2 +- xonsh/ast.py | 4 ++-- xonsh/completers/__init__.py | 2 +- xonsh/environ.py | 11 ++++++---- xonsh/execer.py | 6 ++--- xonsh/foreign_shells.py | 2 +- xonsh/history/__init__.py | 2 +- xonsh/procs/__init__.py | 2 +- xonsh/prompt/__init__.py | 2 +- xonsh/shell.py | 2 +- 16 files changed, 83 insertions(+), 25 deletions(-) create mode 100644 news/run-tests-amalgamated.rst diff --git a/news/run-tests-amalgamated.rst b/news/run-tests-amalgamated.rst new file mode 100644 index 000000000..dd80fa976 --- /dev/null +++ b/news/run-tests-amalgamated.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* Separated between ``XONSH_DEBUG`` and ``XONSH_NO_AMALGAMATE``. Setting ``XONSH_DEBUG=1`` now acts like ``XONSH_DEBUG=2`` before (basic information like input transformation, command replacement) and ``XONSH_DEBUG=2`` like ``XONSH_DEBUG=1`` before (more debugging information presented, like PLY parsing messages). + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/requirements/tests.txt b/requirements/tests.txt index 9d593ed2c..d0b94c316 100644 --- a/requirements/tests.txt +++ b/requirements/tests.txt @@ -11,3 +11,6 @@ coverage>=5.3.1 black==21.5b0 pre-commit mypy==0.812 + +# ensure tests run with the amalgamated (==production) xonsh +amalgamate diff --git a/run-tests.xsh b/run-tests.xsh index 1a2da3531..a98d4235b 100755 --- a/run-tests.xsh +++ b/run-tests.xsh @@ -4,8 +4,8 @@ import subprocess from typing import List -$XONSH_DEBUG = 1 $RAISE_SUBPROC_ERROR = True +# $XONSH_NO_AMALGAMATE = 1 # $XONSH_TRACE_SUBPROC = True @@ -26,6 +26,10 @@ def test(ns: argparse.Namespace): args = ns.pytest_args + if not $(xonsh -c "import xonsh.main; print(xonsh.main.__file__, end='')").endswith("__amalgam__.py"): + echo "Tests need to run from the amalgamated xonsh! install with `pip install .` (without `-e`)" + exit(1) + if ns.report_coverage: ![pytest @(_replace_args(args, 0)) --cov --cov-report=xml --cov-report=term] else: diff --git a/setup.py b/setup.py index ae66ee5db..87f4dbee0 100755 --- a/setup.py +++ b/setup.py @@ -49,7 +49,7 @@ def amalgamate_source(): amalgamate.main( [ "amalgamate", - "--debug=XONSH_DEBUG", + "--debug=XONSH_NO_AMALGAMATE", "xonsh", "xonsh.completers", "xonsh.history", diff --git a/tests/completers/test_xompletions.py b/tests/completers/test_xompletions.py index 3d012d321..cdd882edb 100644 --- a/tests/completers/test_xompletions.py +++ b/tests/completers/test_xompletions.py @@ -3,7 +3,7 @@ from xonsh.parsers.completion_context import ( CommandContext, CompletionContext, ) -from xonsh.completers.xompletions import complete_xonfig, complete_xontrib +from xonsh.completers.xompletions import complete_xonfig, complete_xontrib, xt def test_xonfig(): @@ -15,9 +15,7 @@ def test_xonfig(): def test_xonfig_colors(monkeypatch): - monkeypatch.setattr( - "xonsh.tools.color_style_names", lambda: ["blue", "brown", "other"] - ) + monkeypatch.setattr(xt, "color_style_names", lambda: ["blue", "brown", "other"]) assert ( complete_xonfig( CompletionContext( diff --git a/tests/test_integrations.py b/tests/test_integrations.py index 65df0f36a..7d9193d54 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -8,6 +8,7 @@ import subprocess as sp import pytest +import xonsh from xonsh.lib.os import indir from tools import ( @@ -39,7 +40,12 @@ skip_if_no_sleep = pytest.mark.skipif( def run_xonsh( - cmd, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.STDOUT, single_command=False + cmd, + stdin=sp.PIPE, + stdout=sp.PIPE, + stderr=sp.STDOUT, + single_command=False, + interactive=False, ): env = dict(os.environ) env["PATH"] = PATH @@ -48,11 +54,13 @@ def run_xonsh( env["RAISE_SUBPROC_ERROR"] = "0" env["PROMPT"] = "" xonsh = shutil.which("xonsh", path=PATH) + args = [xonsh, "--no-rc"] + if interactive: + args.append("-i") if single_command: - args = [xonsh, "--no-rc", "-c", cmd] + args += ["-c", cmd] input = None else: - args = [xonsh, "--no-rc"] input = cmd proc = sp.Popen( @@ -753,3 +761,22 @@ def test_single_command_return_code(cmd, exp_rtn): @skip_if_on_darwin def test_argv0(): check_run_xonsh("checkargv0.xsh", None, "OK\n") + + +@pytest.mark.parametrize("interactive", [True, False]) +def test_loading_correctly(monkeypatch, interactive): + # Ensure everything loads correctly in interactive mode (e.g. #4289) + monkeypatch.setenv("SHELL_TYPE", "prompt_toolkit") + monkeypatch.setenv("XONSH_LOGIN", "1") + monkeypatch.setenv("XONSH_INTERACTIVE", "1") + out, err, ret = run_xonsh( + "import xonsh; echo -n AAA @(xonsh.__file__) BBB", + interactive=interactive, + single_command=True, + ) + assert not err + assert ret == 0 + our_xonsh = ( + xonsh.__file__ + ) # make sure xonsh didn't fail and fallback to the system shell + assert f"AAA {our_xonsh} BBB" in out # ignore tty warnings/prompt text diff --git a/xonsh/__init__.py b/xonsh/__init__.py index cc834b12e..6a5c73816 100644 --- a/xonsh/__init__.py +++ b/xonsh/__init__.py @@ -6,7 +6,7 @@ __version__ = "0.9.27" # amalgamate exclude jupyter_shell proc built_ins import os as _os -if _os.getenv("XONSH_DEBUG", ""): +if _os.getenv("XONSH_NO_AMALGAMATE", ""): pass else: import sys as _sys diff --git a/xonsh/ast.py b/xonsh/ast.py index 9b0e97e85..91925d8ff 100644 --- a/xonsh/ast.py +++ b/xonsh/ast.py @@ -437,7 +437,7 @@ class CtxAwareTransformer(NodeTransformer): spline, mode=self.mode, filename=self.filename, - debug_level=(self.debug_level > 2), + debug_level=(self.debug_level >= 2), ) newnode = newnode.body if not isinstance(newnode, AST): @@ -445,7 +445,7 @@ class CtxAwareTransformer(NodeTransformer): newnode = newnode[0] increment_lineno(newnode, n=node.lineno - 1) newnode.col_offset = node.col_offset - if self.debug_level > 1: + if self.debug_level >= 1: msg = "{0}:{1}:{2}{3} - {4}\n" "{0}:{1}:{2}{3} + {5}" mstr = "" if maxcol is None else ":" + str(maxcol) msg = msg.format(self.filename, node.lineno, mincol, mstr, line, spline) diff --git a/xonsh/completers/__init__.py b/xonsh/completers/__init__.py index 17eded8a6..6f07d8604 100644 --- a/xonsh/completers/__init__.py +++ b/xonsh/completers/__init__.py @@ -1,7 +1,7 @@ # amalgamate exclude import os as _os -if _os.getenv("XONSH_DEBUG", ""): +if _os.getenv("XONSH_NO_AMALGAMATE", ""): pass else: import sys as _sys diff --git a/xonsh/environ.py b/xonsh/environ.py index 811722627..0d00481b5 100644 --- a/xonsh/environ.py +++ b/xonsh/environ.py @@ -998,13 +998,16 @@ class GeneralSetting(Xettings): bool_or_int_to_str, 0, "Sets the xonsh debugging level. This may be an integer or a boolean. " - "Setting this variable prior to stating xonsh to ``1`` or ``True`` " - "will suppress amalgamated imports. Setting it to ``2`` will get some " - "basic information like input transformation, command replacement. " - "With ``3`` or a higher number will make more debugging information " + "Setting it to ``1`` will get some basic information like input transformation, command replacement. " + "With ``2`` or a higher number will make more debugging information " "presented, like PLY parsing messages.", is_configurable=False, ) + XONSH_NO_AMALGAMATE = Var.with_default( + False, + "Setting this variable prior to starting xonsh to a truthy value will suppress amalgamated imports.", + is_configurable=False, + ) XONSH_DATA_DIR = Var.with_default( xonsh_data_dir, "This is the location where xonsh data files are stored, such as " "history.", diff --git a/xonsh/execer.py b/xonsh/execer.py index 674a2bf3e..f6e54bb32 100644 --- a/xonsh/execer.py +++ b/xonsh/execer.py @@ -75,7 +75,7 @@ class Execer(object): filename = self.filename if not transform: return self.parser.parse( - input, filename=filename, mode=mode, debug_level=(self.debug_level > 2) + input, filename=filename, mode=mode, debug_level=(self.debug_level >= 2) ) # Parsing actually happens in a couple of phases. The first is a @@ -196,7 +196,7 @@ class Execer(object): self, line, sbpline, last_error_line, last_error_col, maxcol=None ): """print some debugging info if asked for.""" - if self.debug_level > 1: + if self.debug_level >= 1: msg = "{0}:{1}:{2}{3} - {4}\n" "{0}:{1}:{2}{3} + {5}" mstr = "" if maxcol is None else ":" + str(maxcol) msg = msg.format( @@ -220,7 +220,7 @@ class Execer(object): input, filename=filename, mode=mode, - debug_level=(self.debug_level > 2), + debug_level=(self.debug_level >= 2), ) parsed = True except IndentationError as e: diff --git a/xonsh/foreign_shells.py b/xonsh/foreign_shells.py index 481217663..13fbd2eed 100644 --- a/xonsh/foreign_shells.py +++ b/xonsh/foreign_shells.py @@ -707,7 +707,7 @@ def load_foreign_aliases(shells): shaliases = {} if shaliases is None else shaliases for alias in set(shaliases) & set(xonsh_aliases): del shaliases[alias] - if XSH.env.get("XONSH_DEBUG") > 1: + if XSH.env.get("XONSH_DEBUG") >= 1: print( "aliases: ignoring alias {!r} of shell {!r} " "which tries to override xonsh alias." diff --git a/xonsh/history/__init__.py b/xonsh/history/__init__.py index 7be641573..e2d94cd5a 100644 --- a/xonsh/history/__init__.py +++ b/xonsh/history/__init__.py @@ -1,7 +1,7 @@ # amalgamate exclude import os as _os -if _os.getenv("XONSH_DEBUG", ""): +if _os.getenv("XONSH_NO_AMALGAMATE", ""): pass else: import sys as _sys diff --git a/xonsh/procs/__init__.py b/xonsh/procs/__init__.py index 50eb7b2b4..20e9debd0 100644 --- a/xonsh/procs/__init__.py +++ b/xonsh/procs/__init__.py @@ -1,7 +1,7 @@ # amalgamate exclude import os as _os -if _os.getenv("XONSH_DEBUG", ""): +if _os.getenv("XONSH_NO_AMALGAMATE", ""): pass else: import sys as _sys diff --git a/xonsh/prompt/__init__.py b/xonsh/prompt/__init__.py index 6511e8b20..51809ccba 100644 --- a/xonsh/prompt/__init__.py +++ b/xonsh/prompt/__init__.py @@ -1,7 +1,7 @@ # amalgamate exclude import os as _os -if _os.getenv("XONSH_DEBUG", ""): +if _os.getenv("XONSH_NO_AMALGAMATE", ""): pass else: import sys as _sys diff --git a/xonsh/shell.py b/xonsh/shell.py index 05bcc0cb7..d7d72158d 100644 --- a/xonsh/shell.py +++ b/xonsh/shell.py @@ -106,7 +106,7 @@ def transform_command(src, show_diff=True): "converge." ) debug_level = XSH.env.get("XONSH_DEBUG") - if show_diff and debug_level > 1 and src != raw: + if show_diff and debug_level >= 1 and src != raw: sys.stderr.writelines( difflib.unified_diff( raw.splitlines(keepends=True),