From adcb4974ee1b3e331754b4c446be5047e40a18cf Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Fri, 15 Jun 2018 17:40:40 +0800 Subject: [PATCH] Upgrade Click and make use of shell detection This introduces an additional environment variable "PIPENV_SHELL". If set, shell detection is skipped completely. The old "SHELL" introspection is kept as a fallback if detection fails. --- pipenv/cli.py | 23 ++++++++++------------- pipenv/environments.py | 3 ++- pipenv/shells.py | 23 +++++++++++++++++++++++ 3 files changed, 35 insertions(+), 14 deletions(-) create mode 100644 pipenv/shells.py diff --git a/pipenv/cli.py b/pipenv/cli.py index 27c2a0ec..4839411e 100644 --- a/pipenv/cli.py +++ b/pipenv/cli.py @@ -14,9 +14,9 @@ from click import ( version_option, BadParameter, ) -from click_completion import init as init_completion -from click_completion import get_code from click_didyoumean import DYMCommandCollection + +import click_completion import crayons import delegator @@ -26,7 +26,7 @@ from . import environments from .utils import is_valid_url # Enable shell completion. -init_completion() +click_completion.init() CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) @@ -165,20 +165,17 @@ def cli( completion=False, ): if completion: # Handle this ASAP to make shell startup fast. - if environments.PIPENV_SHELL: + from . import shells + try: + shell = shells.detect_info()[0] + except shells.ShellDetectionFailure: echo( - get_code( - shell=environments.PIPENV_SHELL.split(os.sep)[-1], - prog_name='pipenv' - ) - ) - else: - echo( - 'Please ensure that the {0} environment variable ' - 'is set.'.format(crayons.normal('SHELL', bold=True)), + 'Fail to detect shell. Please provide the {0} environment ' + 'variable.'.format(crayons.normal('PIPENV_SHELL', bold=True)), err=True, ) sys.exit(1) + print(click_completion.get_code(shell=shell, prog_name='pipenv')) sys.exit(0) from .core import ( diff --git a/pipenv/environments.py b/pipenv/environments.py index de2f9ae8..36fada8c 100644 --- a/pipenv/environments.py +++ b/pipenv/environments.py @@ -74,7 +74,8 @@ PYENV_INSTALLED = ( bool(os.environ.get('PYENV_SHELL')) or bool(os.environ.get('PYENV_ROOT')) ) SESSION_IS_INTERACTIVE = bool(os.isatty(sys.stdout.fileno())) +PIPENV_SHELL_EXPLICIT = os.environ.get('PIPENV_SHELL') PIPENV_SHELL = os.environ.get('SHELL') or os.environ.get('PYENV_SHELL') PIPENV_CACHE_DIR = os.environ.get('PIPENV_CACHE_DIR', user_cache_dir('pipenv')) # Tells pipenv to override PyPI index urls with a mirror. -PIPENV_PYPI_MIRROR = os.environ.get('PIPENV_PYPI_MIRROR') \ No newline at end of file +PIPENV_PYPI_MIRROR = os.environ.get('PIPENV_PYPI_MIRROR') diff --git a/pipenv/shells.py b/pipenv/shells.py new file mode 100644 index 00000000..921c72ce --- /dev/null +++ b/pipenv/shells.py @@ -0,0 +1,23 @@ +import os + +from .environments import PIPENV_SHELL_EXPLICIT, PIPENV_SHELL +from .vendor import shellingham + + +class ShellDetectionFailure(shellingham.ShellDetectionFailure): + pass + + +def _build_info(value): + return (os.path.splitext(os.path.basename(value))[0], value) + + +def detect_info(): + if PIPENV_SHELL_EXPLICIT: + return _build_info(PIPENV_SHELL_EXPLICIT) + try: + return shellingham.detect_shell() + except (shellingham.ShellDetectionFailure, TypeError): + if PIPENV_SHELL: + return _build_info(PIPENV_SHELL) + raise ShellDetectionFailure