diff --git a/docs/advanced.rst b/docs/advanced.rst index 4fa0b232..65af4061 100644 --- a/docs/advanced.rst +++ b/docs/advanced.rst @@ -185,10 +185,10 @@ different products which integrate with Pipenv projects: - `PyUp `_ (Security Notification) - `Emacs `_ (Editor Integration) - `Fish Shell `_ (Automatic ``$ pipenv shell``!) +- `VS Code `_ (Editor Integration) Works in progress: -- `Microsoft VSCode `_ (Editor Integration) - `Sublime Text `_ (Editor Integration) - `PyCharm `_ (Editor Integration) - Mysterious upcoming Google Cloud product (Cloud Hosting) diff --git a/pipenv/core.py b/pipenv/core.py index 4c8667e7..f9405448 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -2028,6 +2028,7 @@ def do_uninstall( def do_shell(three=None, python=False, fancy=False, shell_args=None): + from pipenv.patched.pew import pew # Ensure that virtualenv is available. ensure_project(three=three, python=python, validate=False) @@ -2097,14 +2098,13 @@ def do_shell(three=None, python=False, fancy=False, shell_args=None): # Windows! except AttributeError: - import subprocess + # import subprocess # Tell pew to use the project directory as its workon_home with temp_environ(): if PIPENV_VENV_IN_PROJECT: os.environ['WORKON_HOME'] = project.project_directory - p = subprocess.Popen([cmd] + list(args), shell=True, universal_newlines=True) - p.communicate() - sys.exit(p.returncode) + pew.workon_cmd([workon_name]) + sys.exit(0) # Activate the virtualenv if in compatibility mode. if compat: diff --git a/pipenv/patched/pew/_win_utils.py b/pipenv/patched/pew/_win_utils.py index 4d55b020..9f7b18b9 100644 --- a/pipenv/patched/pew/_win_utils.py +++ b/pipenv/patched/pew/_win_utils.py @@ -14,7 +14,7 @@ from ctypes.wintypes import DWORD, LONG ERROR_NO_MORE_FILES = 18 INVALID_HANDLE_VALUE = c_void_p(-1).value - +SHELL_NAMES = ['cmd', 'powershell', 'cmder'] class PROCESSENTRY32(Structure): _fields_ = [ @@ -92,16 +92,20 @@ def get_all_processes(): return pids -def get_grandparent_process(pid=None): - """Get grandparent process name of the supplied pid or os.getpid(). - - :param int pid: The pid to track. - :return: Name of the grandparent process. +def get_shell(pid=None, max_depth=4): + """Get the shell that the supplied pid or os.getpid() is running in. """ if not pid: pid = os.getpid() processes = get_all_processes() - ppid = processes[pid]['parent_pid'] - parent = processes[ppid] - grandparent = processes[parent['parent_pid']] - return grandparent['executable'] + + def check_parent(pid, lvl=0): + ppid = processes[pid].get('parent_pid') + if ppid and processes[ppid]['executable'].lower().rsplit('.', 1)[0] in SHELL_NAMES: + return processes[ppid]['executable'] + if lvl >= max_depth: + return + return check_parent(ppid, lvl=lvl+1) + if processes[pid]['executable'].lower().rsplit('.', 1)[0] in SHELL_NAMES: + return processes[pid]['executable'] + return check_parent(pid) diff --git a/pipenv/patched/pew/pew.py b/pipenv/patched/pew/pew.py index 470dfd3d..a6440919 100644 --- a/pipenv/patched/pew/pew.py +++ b/pipenv/patched/pew/pew.py @@ -36,7 +36,7 @@ else: InstallCommand = ListPythons = LocatePython = UninstallCommand = \ lambda : sys.exit('Command not supported on this platform') - from ._win_utils import get_grandparent_process + from ._win_utils import get_shell from pew._utils import (check_call, invoke, expandpath, own, env_bin_dir, check_path, temp_environ, NamedTemporaryFile, to_unicode) @@ -184,7 +184,7 @@ def _detect_shell(): if 'CMDER_ROOT' in os.environ: shell = 'Cmder' elif windows: - shell = get_grandparent_process(os.getpid()) + shell = get_shell(os.getpid()) else: shell = 'sh' return shell @@ -196,7 +196,7 @@ def shell(env, cwd=None): if shell_name not in ('Cmder', 'bash', 'elvish', 'powershell', 'klingon', 'cmd'): # On Windows the PATH is usually set with System Utility # so we won't worry about trying to check mistakes there - shell_check = (sys.executable + ' -c "from pew.pew import ' + shell_check = (sys.executable + ' -c "from pipenv.patched.pew import ' 'prevent_path_errors; prevent_path_errors()"') try: inve(env, shell, '-c', shell_check) diff --git a/setup.py b/setup.py index 384a0437..d7e4d2c1 100644 --- a/setup.py +++ b/setup.py @@ -22,6 +22,7 @@ if sys.argv[-1] == "publish": sys.exit() required = [ + 'setuptools>=36.2.1' 'virtualenv', 'virtualenv-clone>=0.2.5', 'pathlib;python_version<"3.4"' @@ -120,9 +121,7 @@ setup( ], }, install_requires=required, - extras_require={ - ':sys_platform=="win32"': ['psutil==5.3.1'] - }, + extras_require={}, include_package_data=True, license='MIT', classifiers=[