# -*- coding: utf-8 -*- """Tests the xonsh main function.""" from __future__ import unicode_literals, print_function from contextlib import contextmanager import builtins import gc import os import os.path import sys import xonsh.main from xonsh.main import XonshMode from xonsh.environ import Env import pytest from tools import TEST_DIR, skip_if_on_windows def Shell(*args, **kwargs): pass @pytest.fixture def shell(xonsh_builtins, monkeypatch): """Xonsh Shell Mock""" if hasattr(builtins, "__xonsh__"): builtins.__xonsh__.unlink_builtins() del builtins.__xonsh__ for xarg in dir(builtins): if "__xonsh_" in xarg: delattr(builtins, xarg) gc.collect() Shell.shell_type_aliases = {"rl": "readline"} monkeypatch.setattr(xonsh.main, "Shell", Shell) def test_premain_no_arg(shell, monkeypatch): monkeypatch.setattr(sys.stdin, "isatty", lambda: True) xonsh.main.premain([]) assert builtins.__xonsh__.env.get("XONSH_LOGIN") def test_premain_interactive(shell): xonsh.main.premain(["-i"]) assert builtins.__xonsh__.env.get("XONSH_INTERACTIVE") def test_premain_login_command(shell): xonsh.main.premain(["-l", "-c", 'echo "hi"']) assert builtins.__xonsh__.env.get("XONSH_LOGIN") def test_premain_login(shell): xonsh.main.premain(["-l"]) assert builtins.__xonsh__.env.get("XONSH_LOGIN") def test_premain_D(shell): xonsh.main.premain(["-DTEST1=1616", "-DTEST2=LOL"]) assert builtins.__xonsh__.env.get("TEST1") == "1616" assert builtins.__xonsh__.env.get("TEST2") == "LOL" def test_premain_custom_rc(shell, tmpdir, monkeypatch): monkeypatch.setattr(sys.stdin, "isatty", lambda: True) monkeypatch.setitem(os.environ, "XONSH_CACHE_SCRIPTS", "False") f = tmpdir.join("wakkawakka") f.write("print('hi')") args = xonsh.main.premain(["--rc", f.strpath]) assert args.mode == XonshMode.interactive assert f.strpath in builtins.__xonsh__.env.get("XONSHRC") def test_no_rc_with_script(shell, tmpdir): args = xonsh.main.premain(["tests/sample.xsh"]) assert not (args.mode == XonshMode.interactive) def test_force_interactive_rc_with_script(shell, tmpdir): args = xonsh.main.premain(["-i", "tests/sample.xsh"]) assert builtins.__xonsh__.env.get("XONSH_INTERACTIVE") 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") f = tmpdir.join("wakkawakka") f.write("print('hi')") args = xonsh.main.premain(["-i", "--rc", f.strpath, "tests/sample.xsh"]) assert args.mode == XonshMode.interactive assert f.strpath in builtins.__xonsh__.env.get("XONSHRC") def test_custom_rc_with_script(shell, tmpdir): """Calling a custom RC file on a script-call without the interactive flag should not run interactively """ f = tmpdir.join("wakkawakka") f.write("print('hi')") args = xonsh.main.premain(["--rc", f.strpath, "tests/sample.xsh"]) assert not (args.mode == XonshMode.interactive) def test_premain_no_rc(shell, tmpdir): xonsh.main.premain(["--no-rc", "-i"]) assert not builtins.__xonsh__.env.get("XONSHRC") @pytest.mark.parametrize( "arg", ["", "-i", "-vERSION", "-hAALP", "TTTT", "-TT", "--TTT"] ) def test_premain_with_file_argument(arg, shell): xonsh.main.premain(["tests/sample.xsh", arg]) assert not (builtins.__xonsh__.env.get("XONSH_INTERACTIVE")) def test_premain_interactive__with_file_argument(shell): xonsh.main.premain(["-i", "tests/sample.xsh"]) assert builtins.__xonsh__.env.get("XONSH_INTERACTIVE") @pytest.mark.parametrize("case", ["----", "--hep", "-TT", "--TTTT"]) def test_premain_invalid_arguments(shell, case, capsys): with pytest.raises(SystemExit): xonsh.main.premain([case]) assert "unrecognized argument" in capsys.readouterr()[1] def test_premain_timings_arg(shell): xonsh.main.premain(["--timings"]) @skip_if_on_windows def test_xonsh_failback(shell, monkeypatch, monkeypatch_stderr): failback_checker = [] def mocked_main(*args): raise Exception("A fake failure") monkeypatch.setattr(xonsh.main, "main_xonsh", mocked_main) def mocked_execlp(f, *args): failback_checker.append(f) failback_checker.append(args[0]) monkeypatch.setattr(os, "execlp", mocked_execlp) monkeypatch.setattr(os.path, "exists", lambda x: True) monkeypatch.setattr(sys, "argv", ["xonsh", "-i"]) @contextmanager def mocked_open(*args): yield ["/usr/bin/xonsh", "/usr/bin/screen", "bash", "/bin/xshell"] monkeypatch.setattr(builtins, "open", mocked_open) xonsh.main.main() assert failback_checker == ["/bin/xshell", "/bin/xshell"] def test_xonsh_failback_single(shell, monkeypatch, monkeypatch_stderr): class FakeFailureError(Exception): pass def mocked_main(*args): raise FakeFailureError() monkeypatch.setattr(xonsh.main, "main_xonsh", mocked_main) monkeypatch.setattr(sys, "argv", ["xonsh", "-c", "echo", "foo"]) with pytest.raises(FakeFailureError): xonsh.main.main() def test_xonsh_failback_script_from_file(shell, monkeypatch, monkeypatch_stderr): checker = [] def mocked_execlp(f, *args): checker.append(f) monkeypatch.setattr(os, "execlp", mocked_execlp) script = os.path.join(TEST_DIR, "scripts", "raise.xsh") monkeypatch.setattr(sys, "argv", ["xonsh", script]) with pytest.raises(Exception): xonsh.main.main() assert len(checker) == 0 def test_xonsh_no_file_returncode(shell, monkeypatch, monkeypatch_stderr): monkeypatch.setattr(sys, "argv", ["xonsh", "foobazbarzzznotafileatall.xsh"]) with pytest.raises(SystemExit): xonsh.main.main()