From 1e24bbb2ede0275eea400b7aa4b061f83b4eac0d Mon Sep 17 00:00:00 2001 From: Anthony Scopatz Date: Sat, 10 Oct 2015 19:52:53 -0400 Subject: [PATCH] added tests for foreign shells --- docs/api/foreign_shells.rst | 10 +++++++ docs/api/index.rst | 1 + tests/bashrc.sh | 5 ++++ tests/test_foreign_shells.py | 56 ++++++++++++++++++++++++++++++++++++ xonsh/foreign_shells.py | 15 +++++++--- 5 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 docs/api/foreign_shells.rst create mode 100644 tests/bashrc.sh create mode 100644 tests/test_foreign_shells.py diff --git a/docs/api/foreign_shells.rst b/docs/api/foreign_shells.rst new file mode 100644 index 000000000..d11488410 --- /dev/null +++ b/docs/api/foreign_shells.rst @@ -0,0 +1,10 @@ +.. _xonsh_foreign_shells: + +****************************************************** +Foreign Shell Tools (``xonsh.foreign_shells``) +****************************************************** + +.. automodule:: xonsh.foreign_shells + :members: + :undoc-members: + :inherited-members: diff --git a/docs/api/index.rst b/docs/api/index.rst index 367dbff38..61d6485d9 100644 --- a/docs/api/index.rst +++ b/docs/api/index.rst @@ -51,5 +51,6 @@ For those of you who want the gritty details. lazyjson teepty openpy + foriegn_shells main pyghooks diff --git a/tests/bashrc.sh b/tests/bashrc.sh new file mode 100644 index 000000000..a150d22da --- /dev/null +++ b/tests/bashrc.sh @@ -0,0 +1,5 @@ +export EMERALD="SWORD" +alias ll='ls -a -lF' +alias la='ls -A' +export MIGHTY=WARRIOR +alias l='ls -CF' diff --git a/tests/test_foreign_shells.py b/tests/test_foreign_shells.py new file mode 100644 index 000000000..adc9d4657 --- /dev/null +++ b/tests/test_foreign_shells.py @@ -0,0 +1,56 @@ +"""Tests foreign shells.""" +from __future__ import unicode_literals, print_function +import os +import subprocess + +import nose +from nose.plugins.skip import SkipTest +from nose.tools import assert_equal, assert_true, assert_false + +from xonsh.foreign_shells import foreign_shell_data, parse_env, parse_aliases + +def test_parse_env(): + exp = {'X': 'YES', 'Y': 'NO'} + s = ('some garbage\n' + '__XONSH_ENV_BEG__\n' + 'Y=NO\n' + 'X=YES\n' + '__XONSH_ENV_END__\n' + 'more filth') + obs = parse_env(s) + assert_equal(exp, obs) + + +def test_parse_aliases(): + exp = {'x': ['yes', '-1'], 'y': ['echo', 'no']} + s = ('some garbage\n' + '__XONSH_ALIAS_BEG__\n' + "alias x='yes -1'\n" + "alias y='echo no'\n" + '__XONSH_ALIAS_END__\n' + 'more filth') + obs = parse_aliases(s) + assert_equal(exp, obs) + + +def test_foreign_bash_data(): + expenv = {"EMERALD": "SWORD", 'MIGHTY': 'WARRIOR'} + expaliases = { + 'l': ['ls', '-CF'], + 'la': ['ls', '-A'], + 'll': ['ls', '-a', '-lF'], + } + rcfile = os.path.join(os.path.dirname(__file__), 'bashrc.sh') + try: + obsenv, obsaliases = foreign_shell_data('bash', currenv=(), + extra_args=('--rcfile', rcfile), + safe=False) + except (subprocess.CalledProcessError, FileNotFoundError): + raise SkipTest + for key, expval in expenv.items(): + yield assert_equal, expval, obsenv.get(key, False) + yield assert_equal, expaliases, obsaliases + + +if __name__ == '__main__': + nose.runmodule() diff --git a/xonsh/foreign_shells.py b/xonsh/foreign_shells.py index 5ea41d94a..07826576a 100644 --- a/xonsh/foreign_shells.py +++ b/xonsh/foreign_shells.py @@ -25,7 +25,8 @@ __XONSH_ALIAS_END__ @lru_cache() def foreign_shell_data(shell, interactive=True, login=False, envcmd='env', - aliascmd='alias', extra_args=(), currenv=None): + aliascmd='alias', extra_args=(), currenv=None, + safe=True): """Extracts data from a foreign (non-xonsh) shells. Currently this gets the environment and aliases, but may be extended in the future. @@ -41,10 +42,12 @@ def foreign_shell_data(shell, interactive=True, login=False, envcmd='env', The command to generate environment output with. aliascmd : str, optional The command to generate alais output with. - extra_args : list of str, optional + extra_args : tuple of str, optional Addtional command line options to pass into the shell. - currenv : dict or None, optional + currenv : tuple of items or None, optional Manual override for the current environment. + safe : bool, optional + Flag for whether or not to safely handle exceptions and other errors. Returns ------- @@ -54,19 +57,23 @@ def foreign_shell_data(shell, interactive=True, login=False, envcmd='env', Dictionary of shell's alaiases. """ cmd = [shell] + cmd.extend(extra_args) # needs to come here for GNU long options if interactive: cmd.append('-i') if login: cmd.append('-l') - cmd.extend(extra_args) cmd.append('-c') cmd.append(COMMAND.format(envcmd=envcmd, aliascmd=aliascmd)) if currenv is None and hasattr(builtins, '__xonsh_env__'): currenv = builtins.__xonsh_env__.detype() + elif currenv is not None: + currenv = dict(currenv) try: s = subprocess.check_output(cmd,stderr=subprocess.PIPE, env=currenv, universal_newlines=True) except (subprocess.CalledProcessError, FileNotFoundError): + if not safe: + raise s = FAILED_COMMAND_STDOUT env = parse_env(s) aliases = parse_aliases(s)