Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Sh as a base class, add support for ash (Almquist shell) #53

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tests/docker/debian
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ARG PYTHON_VERSION
FROM python:${PYTHON_VERSION}

RUN apt-get update \
&& apt-get --no-install-recommends -y install fish zsh
&& apt-get --no-install-recommends -y install ash fish zsh

COPY requirements.txt /
RUN pip install -r requirements.txt
Expand Down
65 changes: 65 additions & 0 deletions tests/test_ash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import pytest
import userpath

from .utils import SKIP_WINDOWS_CI, get_random_path

SHELL_NAME = 'ash'

pytestmark = [SKIP_WINDOWS_CI, pytest.mark.ash]


@pytest.mark.usefixtures('shell_test')
class TestDebian(object):
DOCKERFILE = 'debian'

def test_prepend(self, request, shell_test):
if shell_test is None:
location = get_random_path()
assert not userpath.in_current_path(location)
assert userpath.prepend(location, check=True)
assert userpath.in_new_path(location)
assert userpath.need_shell_restart(location)
else:
process = shell_test(request.node.name)
stdout, stderr = process.communicate()

assert process.returncode == 0, (stdout + stderr).decode('utf-8')

def test_prepend_multiple(self, request, shell_test):
if shell_test is None:
locations = [get_random_path(), get_random_path()]
assert not userpath.in_current_path(locations)
assert userpath.prepend(locations, check=True)
assert userpath.in_new_path(locations)
assert userpath.need_shell_restart(locations)
else:
process = shell_test(request.node.name)
stdout, stderr = process.communicate()

assert process.returncode == 0, (stdout + stderr).decode('utf-8')

def test_append(self, request, shell_test):
if shell_test is None:
location = get_random_path()
assert not userpath.in_current_path(location)
assert userpath.append(location, check=True)
assert userpath.in_new_path(location)
assert userpath.need_shell_restart(location)
else:
process = shell_test(request.node.name)
stdout, stderr = process.communicate()

assert process.returncode == 0, (stdout + stderr).decode('utf-8')

def test_append_multiple(self, request, shell_test):
if shell_test is None:
locations = [get_random_path(), get_random_path()]
assert not userpath.in_current_path(locations)
assert userpath.append(locations, check=True)
assert userpath.in_new_path(locations)
assert userpath.need_shell_restart(locations)
else:
process = shell_test(request.node.name)
stdout, stderr = process.communicate()

assert process.returncode == 0, (stdout + stderr).decode('utf-8')
46 changes: 31 additions & 15 deletions userpath/shells.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,40 @@ def __init__(self, home=None):


class Sh(Shell):
def config(self, location, front=True):
name = 'sh'

def _config_contents(self, location, front=True):
head, tail = (location, '$PATH') if front else ('$PATH', location)
new_path = '{}{}{}'.format(head, pathsep, tail)
return 'export PATH="{}"'.format(new_path)

return {path.join(self.home, '.profile'): 'PATH="{}"'.format(new_path)}
def config(self, location, front=True):
contents = self._config_contents(location, front=front)
return {path.join(self.home, '.profile'): contents}

@classmethod
def _interactive_show_path_command(cls):
return [cls.name, '-i', '-c', 'echo $PATH']

@classmethod
def _interactive_login_show_path_command(cls):
return [cls.name, '-i', '-l', '-c', 'echo $PATH']

@classmethod
def show_path_commands(cls):
# TODO: Find out what file influences non-login shells. The issue may simply be our Docker setup.
return [['sh', '-i', '-l', '-c', 'echo $PATH']]
return [cls._interactive_login_show_path_command()]


class Bash(Shell):
def config(self, location, front=True):
head, tail = (location, '$PATH') if front else ('$PATH', location)
new_path = '{}{}{}'.format(head, pathsep, tail)
contents = 'export PATH="{}"'.format(new_path)
class Ash(Sh):
name = 'ash'


class Bash(Sh):
name = 'bash'

def config(self, location, front=True):
contents = self._config_contents(location, front=front)
configs = {path.join(self.home, '.bashrc'): contents}

# https://github.com/ofek/userpath/issues/3#issuecomment-492491977
Expand All @@ -50,7 +66,7 @@ def config(self, location, front=True):

@classmethod
def show_path_commands(cls):
return [['bash', '-i', '-c', 'echo $PATH'], ['bash', '-i', '-l', '-c', 'echo $PATH']]
return [cls._interactive_show_path_command(), cls._interactive_login_show_path_command()]


class Fish(Shell):
Expand Down Expand Up @@ -88,21 +104,21 @@ def show_path_commands(cls):
return [['xonsh', '-i', '-c', command], ['xonsh', '-i', '--login', '-c', command]]


class Zsh(Shell):
def config(self, location, front=True):
head, tail = (location, '$PATH') if front else ('$PATH', location)
new_path = '{}{}{}'.format(head, pathsep, tail)
contents = 'export PATH="{}"'.format(new_path)
class Zsh(Sh):
name = 'zsh'

def config(self, location, front=True):
contents = self._config_contents(location, front=front)
zdotdir = environ.get('ZDOTDIR', self.home)
return {path.join(zdotdir, '.zshrc'): contents, path.join(zdotdir, '.zprofile'): contents}

@classmethod
def show_path_commands(cls):
return [['zsh', '-i', '-c', 'echo $PATH'], ['zsh', '-i', '-l', '-c', 'echo $PATH']]
return [cls._interactive_show_path_command(), cls._interactive_login_show_path_command()]


SHELLS = {
'ash': Ash,
'bash': Bash,
'fish': Fish,
'sh': Sh,
Expand Down