Un-vendor Pew

This commit is contained in:
Tzu-ping Chung
2018-07-05 16:29:49 +08:00
parent 9e55b351ce
commit a5a9583c2d
35 changed files with 15 additions and 2040 deletions
+4 -3
View File
@@ -382,7 +382,7 @@ will detect it.
- ``PIPENV_SHELL_FANCY`` — Always use fancy mode when invoking ``pipenv shell``.
- ``PIPENV_VENV_IN_PROJECT`` — If set, use ``.venv`` in your project directory
instead of the global virtualenv manager ``pew``.
instead of a global location.
- ``PIPENV_COLORBLIND`` — Disable terminal colors, for some reason.
@@ -424,8 +424,9 @@ For example::
☤ Custom Virtual Environment Location
-------------------------------------
Pipenv's underlying ``pew`` dependency will automatically honor the ``WORKON_HOME`` environment
variable, if you have it set — so you can tell pipenv to store your virtual environments wherever you want, e.g.::
Pipenv automatically honors the ``WORKON_HOME`` environment variable, if you
have it set — so you can tell pipenv to store your virtual environments
wherever you want, e.g.::
export WORKON_HOME=~/.venvs
-1
View File
@@ -10,7 +10,6 @@ imagesize==0.7.1
Jinja2==2.9.6
MarkupSafe==1.0
pbr==3.1.1
pew==0.1.26
pip-tools==1.9.0
-e .
Pygments==2.2.0
+1 -1
View File
@@ -454,7 +454,7 @@ def ensure_python(three=None, python=None):
if (not PIPENV_DONT_USE_PYENV) and (SESSION_IS_INTERACTIVE or PIPENV_YES):
version_map = {
# TODO: Keep this up to date!
# These versions appear incompatible with pew:
# These versions appear incompatible with virtualenv:
# '2.5': '2.5.6',
"2.6": "2.6.9",
"2.7": "2.7.15",
+1 -1
View File
@@ -11,7 +11,7 @@ os.environ.pop("__PYVENV_LAUNCHER__", None)
PIPENV_SHELL_FANCY = bool(os.environ.get("PIPENV_SHELL_FANCY"))
# Support for both Python 2 and Python 3 at the same time.
PIPENV_PYTHON = os.environ.get("PIPENV_PYTHON")
# Create the virtualenv in the project, instead of with pew.
# Create the virtualenv in the project, instead of in WORKON_HOME.
PIPENV_VENV_IN_PROJECT = bool(os.environ.get("PIPENV_VENV_IN_PROJECT"))
# Overwrite all index funcitonality.
PIPENV_TEST_INDEX = os.environ.get("PIPENV_TEST_INDEX")
-1
View File
@@ -1,7 +1,6 @@
safety
git+https://github.com/jumpscale7/python-consistent-toml.git#egg=contoml
crayons==0.1.2
git+https://github.com/berdario/pew.git@1.1.5#egg=pew
pipfile==0.0.2
git+https://github.com/jazzband/pip-tools.git@9cb41d828fcb0967a32cc140c1dcaca94e5f4daa#egg=piptools
prettytoml==0.3
-17
View File
@@ -1,17 +0,0 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-4
View File
@@ -1,4 +0,0 @@
from __future__ import absolute_import
from . import pew
__all__ = ['pew']
-4
View File
@@ -1,4 +0,0 @@
from . import pew
if __name__ == '__main__':
pew.pew.pew()
-58
View File
@@ -1,58 +0,0 @@
from __future__ import division, print_function
import os
from functools import partial
from math import ceil
try:
from itertools import zip_longest
except ImportError:
from itertools import izip_longest as zip_longest
try:
from shutil import get_terminal_size
except ImportError:
from pipenv.vendor.backports.shutil_get_terminal_size import get_terminal_size
SEP = ' '
L = len(SEP)
def get_rows(venvs, columns_number):
lines_number = int(ceil(len(venvs) / columns_number))
for i in range(lines_number):
yield venvs[i::lines_number]
def row_len(names):
return sum(map(len, names)) + L * len(names) - L
def get_best_columns_number(venvs):
max_width, _ = get_terminal_size()
longest = partial(max, key=len)
columns_number = 1
for columns_number in range(1, len(venvs) + 1):
rows = get_rows(venvs, columns_number)
longest_row = list(map(longest, zip_longest(*rows, fillvalue='')))
if row_len(longest_row) > max_width:
return (columns_number - 1) or 1
else:
return columns_number
def align_column(column):
m = max(map(len, column))
return [name.ljust(m) for name in column]
def columnize(venvs):
columns_n = get_best_columns_number(venvs)
columns = map(align_column, zip_longest(*get_rows(venvs, columns_n), fillvalue=''))
return map(SEP.join, zip(*columns))
def print_virtualenvs(*venvs):
venvs = sorted(venvs)
if os.isatty(1):
print(*columnize(venvs), sep='\n')
else:
print(*venvs, sep=' ')
-92
View File
@@ -1,92 +0,0 @@
import os
import sys
import locale
from codecs import getwriter
from contextlib import contextmanager
from subprocess import check_call, Popen, PIPE
from collections import namedtuple
from functools import partial, wraps
try:
from pathlib import Path
except ImportError:
from pipenv.vendor.pathlib2 import Path
from tempfile import NamedTemporaryFile as _ntf
try:
from shutil import which
except ImportError:
from shutilwhich import which
py2 = sys.version_info[0] == 2
windows = sys.platform == 'win32'
if py2 or windows:
locale.setlocale(locale.LC_CTYPE, '')
encoding = locale.getlocale()[1] or 'ascii'
if py2:
@wraps(_ntf)
def NamedTemporaryFile(mode):
return getwriter(encoding)(_ntf(mode))
def to_unicode(x):
return x.decode(encoding)
else:
NamedTemporaryFile = _ntf
to_unicode = str
def check_path():
parent = os.path.dirname
return parent(parent(which('python'))) == os.environ['VIRTUAL_ENV']
def resolve_path(f):
def call(cmd, **kwargs):
ex = cmd[0]
ex = which(ex) or ex
return f([ex] + list(cmd[1:]), **kwargs) # list-conversion is required in case `cmd` is a tuple
return call
if windows:
check_call = resolve_path(check_call)
Popen = resolve_path(Popen)
Result = namedtuple('Result', 'returncode out err')
# TODO: it's better to fail early, and thus I'd need to check the exit code, but it'll
# need a refactoring of a couple of tests
def invoke(*args, **kwargs):
inp = kwargs.pop('inp', '').encode(encoding)
popen = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE, **kwargs)
out, err = [o.strip().decode(encoding) for o in popen.communicate(inp)]
return Result(popen.returncode, out, err)
invoke_pew = partial(invoke, 'pew')
env_bin_dir = 'bin' if sys.platform != 'win32' else 'Scripts'
def expandpath(path):
return Path(os.path.expanduser(os.path.expandvars(path)))
def own(path):
if sys.platform == 'win32':
# Even if run by an administrator, the permissions will be set
# correctly on Windows, no need to check
return True
while not path.exists():
path = path.parent
return path.stat().st_uid == os.getuid()
@contextmanager
def temp_environ():
environ = dict(os.environ)
try:
yield
finally:
os.environ.clear()
os.environ.update(environ)
-121
View File
@@ -1,121 +0,0 @@
# -*- coding=utf-8 -*-
# psutil is painfully slow in win32. So to avoid adding big
# dependencies like pywin32 a ctypes based solution is preferred
# Code based on the winappdbg project http://winappdbg.sourceforge.net/
# (BSD License) - adapted from Celery
# https://github.com/celery/celery/blob/2.5-archived/celery/concurrency/processes/_win.py
import os
import six
from ctypes import (
byref, sizeof, windll, Structure, WinError, POINTER,
c_size_t, c_char, c_void_p
)
from ctypes.wintypes import DWORD, LONG
ERROR_NO_MORE_FILES = 18
INVALID_HANDLE_VALUE = c_void_p(-1).value
SHELL_NAMES = ['cmd', 'powershell', 'pwsh', 'cmder']
class PROCESSENTRY32(Structure):
_fields_ = [
('dwSize', DWORD),
('cntUsage', DWORD),
('th32ProcessID', DWORD),
('th32DefaultHeapID', c_size_t),
('th32ModuleID', DWORD),
('cntThreads', DWORD),
('th32ParentProcessID', DWORD),
('pcPriClassBase', LONG),
('dwFlags', DWORD),
('szExeFile', c_char * 260),
]
LPPROCESSENTRY32 = POINTER(PROCESSENTRY32)
def CreateToolhelp32Snapshot(dwFlags=2, th32ProcessID=0):
hSnapshot = windll.kernel32.CreateToolhelp32Snapshot(
dwFlags,
th32ProcessID
)
if hSnapshot == INVALID_HANDLE_VALUE:
raise WinError()
return hSnapshot
def Process32First(hSnapshot):
pe = PROCESSENTRY32()
pe.dwSize = sizeof(PROCESSENTRY32)
success = windll.kernel32.Process32First(hSnapshot, byref(pe))
if not success:
if windll.kernel32.GetLastError() == ERROR_NO_MORE_FILES:
return
raise WinError()
return pe
def Process32Next(hSnapshot, pe=None):
if pe is None:
pe = PROCESSENTRY32()
pe.dwSize = sizeof(PROCESSENTRY32)
success = windll.kernel32.Process32Next(hSnapshot, byref(pe))
if not success:
if windll.kernel32.GetLastError() == ERROR_NO_MORE_FILES:
return
raise WinError()
return pe
def get_all_processes():
"""Return a dictionary of properties about all processes.
>>> get_all_processes()
{
1509: {
'parent_pid': 1201,
'executable': 'C:\\Program\\\\ Files\\Python36\\python.exe'
}
}
"""
h_process = CreateToolhelp32Snapshot()
pids = {}
pe = Process32First(h_process)
while pe:
pids[pe.th32ProcessID] = {
'executable': str(pe.szExeFile.decode('utf-8'))
}
if pe.th32ParentProcessID:
pids[pe.th32ProcessID]['parent_pid'] = pe.th32ParentProcessID
pe = Process32Next(h_process, pe)
return pids
def _get_executable(process_dict):
if hasattr(process_dict, 'keys'):
executable = process_dict.get('executable')
if isinstance(executable, six.string_types):
return executable.lower().rsplit('.', 1)[0]
return ''
def get_shell(pid=None, max_depth=6):
"""Get the shell that the supplied pid or os.getpid() is running in.
"""
if not pid:
pid = os.getpid()
processes = get_all_processes()
def check_parent(pid, lvl=0):
ppid = processes[pid].get('parent_pid')
if ppid and _get_executable(processes.get(ppid)) in SHELL_NAMES:
return processes[ppid]['executable']
if lvl >= max_depth:
return
return check_parent(ppid, lvl=lvl+1)
if _get_executable(processes.get(pid)) in SHELL_NAMES:
return processes[pid]['executable']
return check_parent(pid)
-786
View File
@@ -1,786 +0,0 @@
from __future__ import print_function, absolute_import, unicode_literals
import os
import sys
import argparse
import shutil
import random
import textwrap
from functools import partial
from subprocess import CalledProcessError
try:
from pathlib import Path
except ImportError:
from pipenv.vendor.pathlib2 import Path
try:
from shutil import get_terminal_size
except ImportError:
from pipenv.vendor.backports.shutil_get_terminal_size import get_terminal_size
windows = sys.platform == 'win32'
from clonevirtualenv import clone_virtualenv
if not windows:
try:
# Try importing these packages if avaiable
from pythonz.commands.install import InstallCommand
from pythonz.commands.uninstall import UninstallCommand
from pythonz.installer.pythoninstaller import PythonInstaller, AlreadyInstalledError
from pythonz.commands.list import ListCommand as ListPythons
from pythonz.define import PATH_PYTHONS
from pythonz.commands.locate import LocateCommand as LocatePython
except:
# create mock commands
InstallCommand = ListPythons = LocatePython = UninstallCommand = \
lambda : sys.exit('You need to install the pythonz extra. pip install pew[pythonz]')
else:
# Pythonz does not support windows
InstallCommand = ListPythons = LocatePython = UninstallCommand = \
lambda : sys.exit('Command not supported on this platform')
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)
from pew._print_utils import print_virtualenvs
if sys.version_info[0] == 2:
input = raw_input
err = partial(print, file=sys.stderr)
if windows:
default_home = '~/.virtualenvs'
else:
default_home = os.path.join(
os.environ.get('XDG_DATA_HOME', '~/.local/share'), 'virtualenvs')
def get_workon_home():
return expandpath(os.environ.get('WORKON_HOME', default_home))
def makedirs_and_symlink_if_needed(workon_home):
if not workon_home.exists() and own(workon_home):
workon_home.mkdir(parents=True)
link = expandpath('~/.virtualenvs')
if os.name == 'posix' and 'WORKON_HOME' not in os.environ and \
'XDG_DATA_HOME' not in os.environ and not link.exists():
link.symlink_to(str(workon_home))
return True
else:
return False
pew_site = Path(__file__).parent
def supported_shell():
shell = Path(os.environ.get('SHELL', '')).stem
if shell in ('bash', 'zsh', 'fish'):
return shell
def shell_config_cmd(argv):
"Prints the path for the current $SHELL helper file"
shell = supported_shell()
if shell:
print(pew_site / 'shell_config' / ('init.' + shell))
else:
err('Completions and prompts are unavailable for %s' %
repr(os.environ.get('SHELL', '')))
def deploy_completions():
completions = {'complete.bash': Path('/etc/bash_completion.d/pew'),
'complete.zsh': Path('/usr/local/share/zsh/site-functions/_pew'),
'complete.fish': Path('/etc/fish/completions/pew.fish')}
for comp, dest in completions.items():
if not dest.parent.exists():
dest.parent.mkdir(parents=True)
shutil.copy(str(pew_site / 'shell_config' / comp), str(dest))
def get_project_dir(env):
project_file = get_workon_home() / env / '.project'
if project_file.exists():
with project_file.open() as f:
project_dir = f.readline().strip()
if os.path.exists(project_dir):
return project_dir
else:
err('Corrupted or outdated:', project_file, '\nDirectory',
project_dir, "doesn't exist.")
def unsetenv(key):
if key in os.environ:
del os.environ[key]
def compute_path(env):
envdir = get_workon_home() / env
return os.pathsep.join([
str(envdir / env_bin_dir),
os.environ['PATH'],
])
def inve(env, command, *args, **kwargs):
"""Run a command in the given virtual environment.
Pass additional keyword arguments to ``subprocess.check_call()``."""
# we don't strictly need to restore the environment, since pew runs in
# its own process, but it feels like the right thing to do
with temp_environ():
os.environ['VIRTUAL_ENV'] = str(get_workon_home() / env)
os.environ['PATH'] = compute_path(env)
unsetenv('PYTHONHOME')
unsetenv('__PYVENV_LAUNCHER__')
try:
return check_call([command] + list(args), shell=windows, **kwargs)
# need to have shell=True on windows, otherwise the PYTHONPATH
# won't inherit the PATH
except OSError as e:
if e.errno == 2:
err('Unable to find', command)
else:
raise
def fork_shell(env, shellcmd, cwd):
or_ctrld = '' if windows else "or 'Ctrl+D' "
err("Launching subshell in virtual environment. Type 'exit' ", or_ctrld,
"to return.", sep='')
if 'VIRTUAL_ENV' in os.environ:
err("Be aware that this environment will be nested on top "
"of '%s'" % Path(os.environ['VIRTUAL_ENV']).name)
try:
inve(env, *shellcmd, cwd=cwd)
except CalledProcessError:
# These shells report errors when the last command executed in the
# subshell in an error. This causes the subprocess to fail, which is
# not what we want. Stay silent for them, there's nothing we can do.
shell_name, _ = os.path.splitext(os.path.basename(shellcmd[0]))
suppress_error = shell_name.lower() in ('cmd', 'powershell', 'pwsh')
if not suppress_error:
raise
def fork_bash(env, cwd):
# bash is a special little snowflake, and prevent_path_errors cannot work there
# https://github.com/berdario/pew/issues/58#issuecomment-102182346
bashrcpath = expandpath('~/.bashrc')
if bashrcpath.exists():
with NamedTemporaryFile('w+') as rcfile:
with bashrcpath.open() as bashrc:
rcfile.write(bashrc.read())
rcfile.write('\nexport PATH="' + to_unicode(compute_path(env)) + '"')
rcfile.flush()
fork_shell(env, ['bash', '--rcfile', rcfile.name], cwd)
else:
fork_shell(env, ['bash'], cwd)
def fork_cmder(env, cwd):
shell_cmd = ['cmd']
escaped_cmder_root = os.environ['CMDER_ROOT'].replace(' ', '^ ')
cmderrc_path = r'{0}\vendor\init.bat'.format(escaped_cmder_root)
if expandpath(cmderrc_path).exists():
shell_cmd += ['/k', cmderrc_path]
if cwd:
os.environ['CMDER_START'] = cwd
fork_shell(env, shell_cmd, cwd)
def _detect_shell():
shell = os.environ.get('SHELL', None)
if not shell:
if 'CMDER_ROOT' in os.environ:
shell = 'Cmder'
elif windows:
shell = get_shell(os.getpid())
else:
shell = 'sh'
return shell
def shell(env, cwd=None):
env = str(env)
shell = _detect_shell()
shell_name = Path(shell).stem
if shell_name not in ('Cmder', 'bash', 'elvish', 'powershell', 'pwsh', '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 pipenv.patched.pew.pew import '
'prevent_path_errors; prevent_path_errors()"')
try:
inve(env, shell, '-c', shell_check)
except CalledProcessError:
return
if shell_name in ('Cmder', 'cmd'):
os.environ['PROMPT'] = '({0}) {1}'.format(env, os.environ['PROMPT'])
if shell_name == 'bash':
fork_bash(env, cwd)
elif shell_name == 'Cmder':
fork_cmder(env, cwd)
else:
fork_shell(env, [shell], cwd)
def mkvirtualenv(envname, python=None, packages=[], project=None,
requirements=None, rest=[]):
if python:
rest = ["--python=%s" % python] + rest
path = (get_workon_home() / envname).absolute()
try:
check_call([sys.executable, "-m", "virtualenv", str(path)] + rest)
except (CalledProcessError, KeyboardInterrupt):
rmvirtualenvs([envname])
raise
else:
if project:
setvirtualenvproject(envname, project.absolute())
if requirements:
inve(envname, 'pip', 'install', '-r', str(expandpath(requirements)))
if packages:
inve(envname, 'pip', 'install', *packages)
def mkvirtualenv_argparser():
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--python')
parser.add_argument('-i', action='append', dest='packages', help='Install \
a package after the environment is created. This option may be repeated.')
parser.add_argument('-r', dest='requirements', help='Provide a pip \
requirements file to install a base set of packages into the new environment.')
parser.add_argument('-d', '--dont-activate', action='store_false',
default=True, dest='activate', help="After \
creation, continue with the existing shell (don't \
activate the new environment).")
return parser
def new_cmd(argv):
"""Create a new environment, in $WORKON_HOME."""
parser = mkvirtualenv_argparser()
parser.add_argument('-a', dest='project', help='Provide a full path to a \
project directory to associate with the new environment.')
parser.add_argument('envname')
args, rest = parser.parse_known_args(argv)
project = expandpath(args.project) if args.project else None
mkvirtualenv(args.envname, args.python, args.packages, project,
args.requirements, rest)
if args.activate:
shell(args.envname)
def rmvirtualenvs(envs):
error_happened = False
for env in envs:
env = get_workon_home() / env
if os.environ.get('VIRTUAL_ENV') == str(env):
err("ERROR: You cannot remove the active environment (%s)." % env)
error_happened = True
break
try:
shutil.rmtree(str(env))
except OSError as e:
err("Error while trying to remove the {0} env: \n{1}".format
(env, e.strerror))
error_happened = True
return error_happened
def rm_cmd(argv):
"""Remove one or more environment, from $WORKON_HOME."""
if len(argv) < 1:
sys.exit("Please specify an environment")
return rmvirtualenvs(argv)
def packages(site_packages):
nodes = site_packages.iterdir()
return set([x.stem.split('-')[0] for x in nodes]) - set(['__pycache__'])
def showvirtualenv(env):
columns, _ = get_terminal_size()
pkgs = sorted(packages(sitepackages_dir(env)))
env_python = get_workon_home() / env / env_bin_dir / 'python'
l = len(env) + 2
version = invoke(str(env_python), '-V')
version = ' - '.join((version.out + version.err).splitlines())
print(env, ': ', version, sep='')
print(textwrap.fill(' '.join(pkgs),
width=columns-l,
initial_indent=(l * ' '),
subsequent_indent=(l * ' ')), '\n')
def show_cmd(argv):
try:
showvirtualenv(argv[0])
except IndexError:
if 'VIRTUAL_ENV' in os.environ:
showvirtualenv(Path(os.environ['VIRTUAL_ENV']).name)
else:
sys.exit('pew show [env]')
def lsenvs():
items = get_workon_home().glob(os.path.join('*', env_bin_dir, 'python*'))
return sorted(set(env.parts[-3] for env in items))
def lsvirtualenv(verbose):
envs = lsenvs()
if not verbose:
print_virtualenvs(*envs)
else:
for env in envs:
showvirtualenv(env)
def ls_cmd(argv):
"""List available environments."""
parser = argparse.ArgumentParser()
p_group = parser.add_mutually_exclusive_group()
p_group.add_argument('-b', '--brief', action='store_false')
p_group.add_argument('-l', '--long', action='store_true')
args = parser.parse_args(argv)
lsvirtualenv(args.long)
def parse_envname(argv, no_arg_callback):
if len(argv) < 1:
no_arg_callback()
env = argv[0]
if env.startswith('/'):
sys.exit("ERROR: Invalid environment name '{0}'.".format(env))
if not (get_workon_home() / env).exists():
sys.exit("ERROR: Environment '{0}' does not exist. Create it with \
'pew new {0}'.".format(env))
else:
return env
def workon_cmd(argv):
"""List or change working virtual environments."""
def list_and_exit():
lsvirtualenv(False)
sys.exit(0)
env = parse_envname(argv, list_and_exit)
# Check if the virtualenv has an associated project directory and in
# this case, use it as the current working directory.
project_dir = get_project_dir(env) or os.getcwd()
shell(env, cwd=project_dir)
def sitepackages_dir(env=os.environ.get('VIRTUAL_ENV')):
if not env:
sys.exit('ERROR: no virtualenv active')
else:
env_python = get_workon_home() / env / env_bin_dir / 'python'
return Path(invoke(str(env_python), '-c', 'import distutils; \
print(distutils.sysconfig.get_python_lib())').out)
def add_cmd(argv):
"""Add the specified directories to the Python path for the currently active virtualenv.
This will be done by placing the directory names in a path file named
"virtualenv_path_extensions.pth" inside the virtualenv's site-packages
directory; if this file does not exists, it will be created first.
"""
parser = argparse.ArgumentParser()
parser.add_argument('-d', dest='remove', action='store_true')
parser.add_argument('dirs', nargs='+')
args = parser.parse_args(argv)
extra_paths = sitepackages_dir() / '_virtualenv_path_extensions.pth'
new_paths = [os.path.abspath(d) + "\n" for d in args.dirs]
if not extra_paths.exists():
with extra_paths.open('w') as extra:
extra.write('''import sys; sys.__plen = len(sys.path)
import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)
''')
def rewrite(f):
with extra_paths.open('r+') as extra:
to_write = f(extra.readlines())
extra.seek(0)
extra.truncate()
extra.writelines(to_write)
if args.remove:
rewrite(lambda ls: [line for line in ls if line not in new_paths])
else:
rewrite(lambda lines: lines[0:1] + new_paths + lines[1:])
def sitepackages_dir_cmd(argv):
print(sitepackages_dir())
def lssitepackages_cmd(argv):
"""Show the content of the site-packages directory of the current virtualenv."""
site = sitepackages_dir()
print(*sorted(site.iterdir()), sep=os.linesep)
extra_paths = site / '_virtualenv_path_extensions.pth'
if extra_paths.exists():
print('from _virtualenv_path_extensions.pth:')
with extra_paths.open() as extra:
print(''.join(extra.readlines()))
def toggleglobalsitepackages_cmd(argv):
"""Toggle the current virtualenv between having and not having access to the global site-packages."""
quiet = argv == ['-q']
site = sitepackages_dir()
ngsp_file = site.parent / 'no-global-site-packages.txt'
if ngsp_file.exists():
ngsp_file.unlink()
if not quiet:
print('Enabled global site-packages')
else:
with ngsp_file.open('w'):
if not quiet:
print('Disabled global site-packages')
def cp_cmd(argv):
"""Duplicate the named virtualenv to make a new one."""
parser = argparse.ArgumentParser()
parser.add_argument('source')
parser.add_argument('target', nargs='?')
parser.add_argument('-d', '--dont-activate', action='store_false',
default=True, dest='activate', help="After \
creation, continue with the existing shell (don't \
activate the new environment).")
args = parser.parse_args(argv)
target_name = copy_virtualenv_project(args.source, args.target)
if args.activate:
shell(target_name)
def copy_virtualenv_project(source, target):
source = expandpath(source)
workon_home = get_workon_home()
if not source.exists():
source = workon_home / source
if not source.exists():
sys.exit('Please provide a valid virtualenv to copy')
target_name = target or source.name
target = workon_home / target_name
if target.exists():
sys.exit('%s virtualenv already exists in %s.' % (
target_name, workon_home
))
print('Copying {0} in {1}'.format(source, target_name))
clone_virtualenv(str(source), str(target))
return target_name
def rename_cmd(argv):
"""Rename a virtualenv"""
parser = argparse.ArgumentParser()
parser.add_argument('source')
parser.add_argument('target')
pargs = parser.parse_args(argv)
copy_virtualenv_project(pargs.source, pargs.target)
return rmvirtualenvs([pargs.source])
def setvirtualenvproject(env, project):
print('Setting project for {0} to {1}'.format(env, project))
with (get_workon_home() / env / '.project').open('wb') as prj:
prj.write(str(project).encode())
def setproject_cmd(argv):
"""Given a virtualenv directory and a project directory, set the
virtualenv up to be associated with the project."""
args = dict(enumerate(argv))
project = os.path.abspath(args.get(1, '.'))
env = args.get(0, os.environ.get('VIRTUAL_ENV'))
if not env:
sys.exit('pew setproject [virtualenv] [project_path]')
if not (get_workon_home() / env).exists():
sys.exit("Environment '%s' doesn't exist." % env)
if not os.path.isdir(project):
sys.exit('pew setproject: %s does not exist' % project)
setvirtualenvproject(env, project)
def mkproject_cmd(argv):
"""Create a new project directory and its associated virtualenv."""
if '-l' in argv or '--list' in argv:
templates = [t.name[9:] for t in get_workon_home().glob("template_*")]
print("Available project templates:", *templates, sep='\n')
return
parser = mkvirtualenv_argparser()
parser.add_argument('envname')
parser.add_argument(
'-t', action='append', default=[], dest='templates', help='Multiple \
templates may be selected. They are applied in the order specified on the \
command line.')
parser.add_argument(
'-l', '--list', action='store_true', help='List available templates.')
args, rest = parser.parse_known_args(argv)
projects_home = Path(os.environ.get('PROJECT_HOME', '.'))
if not projects_home.exists():
sys.exit('ERROR: Projects directory %s does not exist. \
Create it or set PROJECT_HOME to an existing directory.' % projects_home)
project = (projects_home / args.envname).absolute()
if project.exists():
sys.exit('Project %s already exists.' % args.envname)
mkvirtualenv(args.envname, args.python, args.packages, project.absolute(),
args.requirements, rest)
project.mkdir()
for template_name in args.templates:
template = get_workon_home() / ("template_" + template_name)
inve(args.envname, str(template), args.envname, str(project))
if args.activate:
shell(args.envname, cwd=str(project))
def mktmpenv_cmd(argv):
"""Create a temporary virtualenv."""
parser = mkvirtualenv_argparser()
env = '.'
while (get_workon_home() / env).exists():
env = hex(random.getrandbits(64))[2:-1]
args, rest = parser.parse_known_args(argv)
mkvirtualenv(env, args.python, args.packages, requirements=args.requirements,
rest=rest)
print('This is a temporary environment. It will be deleted when you exit')
try:
if args.activate:
# only used for testing on windows
shell(env)
finally:
return rmvirtualenvs([env])
def wipeenv_cmd(argv):
"""Remove all installed packages from the current (or supplied) env."""
env = argv[0] if argv else os.environ.get('VIRTUAL_ENV')
if not env:
sys.exit('ERROR: no virtualenv active')
elif not (get_workon_home() / env).exists():
sys.exit("ERROR: Environment '{0}' does not exist.".format(env))
else:
env_pip = str(get_workon_home() / env / env_bin_dir / 'pip')
all_pkgs = set(invoke(env_pip, 'freeze').out.splitlines())
pkgs = set(p for p in all_pkgs if len(p.split("==")) == 2)
ignored = sorted(all_pkgs - pkgs)
pkgs = set(p.split("==")[0] for p in pkgs)
to_remove = sorted(pkgs - set(['distribute', 'wsgiref']))
if to_remove:
print("Ignoring:\n %s" % "\n ".join(ignored))
print("Uninstalling packages:\n %s" % "\n ".join(to_remove))
inve(env, 'pip', 'uninstall', '-y', *to_remove)
else:
print("Nothing to remove")
def inall_cmd(argv):
"""Run a command in each virtualenv."""
envs = lsenvs()
errors = False
for env in envs:
print("\n%s:" % env)
try:
inve(env, *argv)
except CalledProcessError as e:
errors = True
err(e)
sys.exit(errors)
def in_cmd(argv):
"""Run a command in the given virtualenv."""
if len(argv) == 1:
return workon_cmd(argv)
parse_envname(argv, lambda : sys.exit('You must provide a valid virtualenv to target'))
inve(*argv)
def restore_cmd(argv):
"""Try to restore a broken virtualenv by reinstalling the same python version on top of it"""
if len(argv) < 1:
sys.exit('You must provide a valid virtualenv to target')
env = argv[0]
path = get_workon_home() / env
path = workon_home / env
py = path / env_bin_dir / ('python.exe' if windows else 'python')
exact_py = py.resolve().name
check_call([sys.executable, "-m", "virtualenv", str(path.absolute()), "--python=%s" % exact_py])
def dir_cmd(argv):
"""Print the path for the virtualenv directory"""
env = parse_envname(argv, lambda : sys.exit('You must provide a valid virtualenv to target'))
print(get_workon_home() / env)
def install_cmd(argv):
'''Use Pythonz to download and build the specified Python version'''
installer = InstallCommand()
options, versions = installer.parser.parse_args(argv)
if len(versions) != 1:
installer.parser.print_help()
sys.exit(1)
else:
try:
actual_installer = PythonInstaller.get_installer(versions[0], options)
actual_installer.install()
except AlreadyInstalledError as e:
print(e)
def uninstall_cmd(argv):
'''Use Pythonz to uninstall the specified Python version'''
UninstallCommand().run(argv)
def list_pythons_cmd(argv):
'''List the pythons installed by Pythonz (or all the installable ones)'''
try:
Path(PATH_PYTHONS).mkdir(parents=True)
except OSError:
pass
ListPythons().run(argv)
def locate_python_cmd(argv):
'''Locate the path for the python version installed by Pythonz'''
LocatePython().run(argv)
def version_cmd(argv):
"""Prints current pew version"""
import pkg_resources
try:
__version__ = pkg_resources.get_distribution('pew').version
except pkg_resources.DistributionNotFound:
__version__ = 'unknown'
print('Setuptools has some issues here, failed to get our own package.', file=sys.stderr)
print(__version__)
def prevent_path_errors():
if 'VIRTUAL_ENV' in os.environ and not check_path():
sys.exit('''ERROR: The virtualenv hasn't been activated correctly.
Either the env is corrupted (try running `pew restore env`),
Or an upgrade of your Python version broke your env,
Or check the contents of your $PATH. You might be adding new directories to it
from inside your shell's configuration file.
In this case, for further details please see: https://github.com/berdario/pew#the-environment-doesnt-seem-to-be-activated''')
def first_run_setup():
shell = supported_shell()
if shell:
if shell == 'fish':
source_cmd = 'source (pew shell_config)'
else:
source_cmd = 'source $(pew shell_config)'
rcpath = expandpath({'bash': '~/.bashrc'
, 'zsh': '~/.zshrc'
, 'fish': '~/.config/fish/config.fish'}[shell])
if rcpath.exists():
update_config_file(rcpath, source_cmd)
else:
print("It seems that you're running pew for the first time\n"
"If you want source shell competions and update your prompt, "
"Add the following line to your shell config file:\n %s" % source_cmd)
print('\nWill now continue with the command:', *sys.argv[1:])
input('[enter]')
def update_config_file(rcpath, source_cmd):
with rcpath.open('r+') as rcfile:
if source_cmd not in (line.strip() for line in rcfile.readlines()):
choice = 'X'
while choice not in ('y', '', 'n'):
choice = input("It seems that you're running pew for the first time\n"
"do you want to modify %s to source completions and"
" update your prompt? [y/N]\n> " % rcpath).lower()
if choice == 'y':
rcfile.write('\n# added by Pew\n%s\n' % source_cmd)
print('Done')
else:
print('\nOk, if you want to do it manually, just add\n %s\nat'
' the end of %s' % (source_cmd, rcpath))
def print_commands(cmds):
longest = max(map(len, cmds)) + 3
columns, _ = get_terminal_size()
print('Available commands:\n')
for cmd, fun in sorted(cmds.items()):
if fun.__doc__:
print(textwrap.fill(
fun.__doc__.splitlines()[0],
columns or 1000,
initial_indent=(' {0}: '.format(cmd)).ljust(longest),
subsequent_indent=longest * ' '))
else:
print(' ' + cmd)
def pew():
first_run = makedirs_and_symlink_if_needed(get_workon_home())
if first_run and sys.stdin.isatty():
first_run_setup()
cmds = dict((cmd[:-4], fun)
for cmd, fun in globals().items() if cmd.endswith('_cmd'))
if sys.argv[1:]:
if sys.argv[1] in cmds:
command = cmds[sys.argv[1]]
try:
return command(sys.argv[2:])
except CalledProcessError as e:
return e.returncode
except KeyboardInterrupt:
pass
else:
err("ERROR: command", sys.argv[1], "does not exist.")
print_commands(cmds)
sys.exit(1)
else:
print_commands(cmds)
-107
View File
@@ -1,107 +0,0 @@
#compdef pew
_pew_list_venvs () {
local expl
local -a venvs
venvs=(${(f)"$(_call_program venvs pew ls | tr " " "\n" 2>/dev/null)"})
_wanted venvs expl 'virtual envs' compadd -a venvs
}
local curcontext="$curcontext" state line
typeset -A opt_args
_arguments -C \
':subcommand:->subcommand' \
'*::option:->option'
case $state in
(subcommand)
local -a subcommands
subcommands=(
'add:Add directories to python path of active virtualenv'
'cp:Duplicate the named virtualenv to make a new one'
'inall:Run a command in each virtualenv:command'
'install:Use Pythonz to download and build the specified Python version'
'list_pythons:List the pythons installed by Pythonz (or all the installable ones)'
'locate_python:Locate the path for the python version installed by Pythonz'
'ls:List all existing virtual environments'
'lssitepackages:List currently active site-packages'
'mkproject:Create environment with an associated project directory'
'mktmpenv:Create a temporary virtualenv'
'new:Create a new environment'
'rename:Rename a virtualenv'
'restore:Try to restore a broken virtualenv by reinstalling the same python version on top of it'
'rm:Remove one or more environments'
'setproject:Bind an existing virtualenv to an existing project directory'
'show:Display currently active virtualenv'
'sitepackages_dir:Location of the currently active site-packages'
'toggleglobalsitepackages:Toggle access to global site-packages for current virtualenv'
'wipeenv:Remove all installed packages from current env'
'workon:Activates an existing virtual environment'
)
_describe -t commands 'pew subcommands' subcommands
;;
(option)
local -a new_env_options
new_env_options=(
'-h[Show help]'
'-p[Python executable]:python:_command_names'
'*-i[Install a package after the environment is created]:package name'
'-a[Project directory to associate]:project directory:_path_files -/'
'-r[Pip requirements file]:requirements file:_files'
)
case "$line[1]" in
(mktmpenv)
_arguments \
$new_env_options
;;
(new)
_arguments \
$new_env_options \
'1:new env name'
;;
(mkproject)
_arguments \
$new_env_options \
'*-t[Apply templates]' \
'-l[List available templates]' \
'1:new env name'
;;
(ls)
_arguments \
'(-l --long)--long[Verbose ls]' \
'(-b --brief)--brief[One line ls]'
;;
(inall)
_arguments \
'*:command'
;;
(show|workon|rm|wipeenv|restore)
_arguments \
'1:virtual env:_pew_list_venvs'
;;
(cp)
_arguments \
'1:virtual env:_pew_list_venvs' \
'2:new env name'
;;
(add)
_arguments \
'-h[Show help]' \
'-d[Removes previously added directories]' \
'*: :_directories -/'
;;
(setproject)
_arguments \
'1:virtual env:_pew_list_venvs' \
'*:project directory:_directories -/'
;;
esac
esac
@@ -1,46 +0,0 @@
# Homebrew on Macs have version 1.3 of bash-completion which doesn't include
# _init_completion. This is a very minimal version of that function.
__my_init_completion()
{
COMPREPLY=()
_get_comp_words_by_ref cur prev words cword
}
_pew()
{
local cur prev words cword args commands
if declare -F _init_completions >/dev/null 2>&1; then
_init_completion || return
else
__my_init_completion || return
fi
args="--help --python -i -a -r"
commands="ls add mkproject rm lssitepackages cp workon new mktmpenv setproject show wipeenv sitepackages_dir inall toggleglobalsitepackages rename restore install list_pythons locate_python"
case $prev in
ls|show|rm|workon|cp|setproject|rename|wipeenv)
COMPREPLY=( $(compgen -W "$(pew ls)" -- ${cur}) )
return 0
;;
inall)
_command_offset 2
return 0
;;
mktmpenv|new)
COMPREPLY=( $(compgen -W "${args}" -- ${cur}) )
return 0
;;
mkproject)
COMPREPLY=( $(compgen -W "${args} -t --list" -- ${cur}) )
return 0
;;
add)
COMPREPLY=( $(compgen -W "--help -d" -- ${cur}) )
return 0
;;
esac
COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
} &&
complete -o default -F _pew pew
@@ -1,116 +0,0 @@
set pew pew
function __pew_needs_command
set cmd (commandline -opc)
if [ (count $cmd) -eq 1 -a $cmd[1] = "$pew" ]
return 0
end
return 1
end
function __pew_list_envs
eval "$pew ls" | tr " " "\n"
end
function __pew_using_command
set cmd (commandline -opc)
if test (count $cmd) -gt 1
if test $argv[1] = $cmd[2]
return 0
end
end
return 1
end
#### new
complete -f -c $pew -n '__pew_needs_command' -a new -d 'Create a new environment'
complete -f -c $pew -n '__pew_using_command new' -s h -d 'Show help'
complete -f -c $pew -n '__pew_using_command new' -s p -l python -d 'Python executable'
complete -f -c $pew -n '__pew_using_command new' -s i -d 'Install a package after the environment is created'
complete -f -c $pew -n '__pew_using_command new' -s a -a '(__fish_complete_directories (commandline -ct))' -d 'Project directory to associate'
complete -f -c $pew -n '__pew_using_command new' -s r -d 'Pip requirements file'
#### workon
complete -f -c $pew -n '__pew_needs_command' -a workon -d 'Activates an existing virtual environment'
complete -f -c $pew -n '__pew_using_command workon' -a '(__pew_list_envs)' -d 'Virtual env'
#### mktmpenv
complete -f -c $pew -n '__pew_needs_command' -a mktmpenv -d 'Create a temporary virtualenv'
complete -f -c $pew -n '__pew_using_command mktmpenv' -s h -d 'Show help'
complete -f -c $pew -n '__pew_using_command mktmpenv' -s p -l python -d 'Python executable'
complete -f -c $pew -n '__pew_using_command mktmpenv' -s i -d 'Install a package after the environment is created'
complete -f -c $pew -n '__pew_using_command mktmpenv' -s a -d 'Project directory to associate'
complete -f -c $pew -n '__pew_using_command mktmpenv' -s r -d 'Pip requirements file'
#### ls
complete -f -c $pew -n '__pew_needs_command' -a ls -d 'List all existing virtual environments'
complete -f -c $pew -n '__pew_using_command ls' -s l -l long -d 'Verbose ls'
complete -f -c $pew -n '__pew_using_command ls' -s b -l brief -d 'One line ls'
#### show
complete -f -c $pew -n '__pew_needs_command' -a show -d 'Show'
complete -f -c $pew -n '__pew_using_command show' -a '(__pew_list_envs)' -d 'Virtual env'
#### rm
complete -f -c $pew -n '__pew_needs_command' -a rm -d 'Remove one or more environments'
complete -f -c $pew -n '__pew_using_command rm' -a '(__pew_list_envs)' -d 'Virtual env'
#### cp
complete -f -c $pew -n '__pew_needs_command' -a cp -d 'Duplicate an existing virtualenv environment'
#### sitepackages_dir
complete -f -c $pew -n '__pew_needs_command' -a sitepackages_dir -d 'Location of the currently active site-packages'
#### lssitepackages
complete -f -c $pew -n '__pew_needs_command' -a lssitepackages -d 'List currently active site-packages'
#### add
complete -f -c $pew -n '__pew_needs_command' -a add -d 'Adds the specified directories'
complete -f -c $pew -n '__pew_using_command add' -s h -d 'Show help'
complete -f -c $pew -n '__pew_using_command add' -s d -d 'Removes previously added directiories'
#### toggleglobalsitepackages
complete -f -c $pew -n '__pew_needs_command' -a toggleglobalsitepackages -d 'Active virtualenv can access global site-packages'
#### mkproject
complete -f -c $pew -n '__pew_needs_command' -a mkproject -d 'Create a new environment with a project directory'
complete -f -c $pew -n '__pew_using_command mkproject' -s h -d 'Show help'
complete -f -c $pew -n '__pew_using_command mkproject' -s p -l python -d 'Python executable'
complete -f -c $pew -n '__pew_using_command mkproject' -s i -d 'Install a package after the environment is created'
complete -f -c $pew -n '__pew_using_command mkproject' -s a -d 'Project directory to associate'
complete -f -c $pew -n '__pew_using_command mkproject' -s r -d 'Pip requirements file'
complete -f -c $pew -n '__pew_using_command mkproject' -s t -d 'Apply templates'
complete -f -c $pew -n '__pew_using_command mkproject' -s l -l list -d 'List available templates'
#### setproject
complete -f -c $pew -n '__pew_needs_command' -a setproject -d 'Bind an existing virtualenv to an existing project'
#### version
complete -f -c $pew -n '__pew_needs_command' -a version -d 'Prints current version'
#### wipeenv
complete -f -c $pew -n '__pew_needs_command' -a wipeenv -d 'Remove all installed packages from a virtualenv'
complete -f -c $pew -n '__pew_using_command workon' -a '(__pew_list_envs)' -d 'Virtual env'
#### restore
complete -f -c $pew -n '__pew_needs_command' -a restore -d 'Try to restore a broken virtualenv'
complete -f -c $pew -n '__pew_using_command workon' -a '(__pew_list_envs)' -d 'Virtual env'
#### rename
complete -f -c $pew -n '__pew_needs_command' -a rename -d 'Rename a virtualenv'
#### install
complete -f -c $pew -n '__pew_needs_command' -a install -d 'Use Pythonz to download and build a Python vm'
#### list_pythons
complete -f -c $pew -n '__pew_needs_command' -a list_pythons -d 'List the pythons installed by Pythonz'
#### locate_python
complete -f -c $pew -n '__pew_needs_command' -a locate_python -d 'Locate the path for the python version installed by Pythonz'
@@ -1,107 +0,0 @@
#compdef pew
_pew_list_venvs () {
local expl
local -a venvs
venvs=(${(f)"$(_call_program venvs pew ls | tr " " "\n" 2>/dev/null)"})
_wanted venvs expl 'virtual envs' compadd -a venvs
}
local curcontext="$curcontext" state line
typeset -A opt_args
_arguments -C \
':subcommand:->subcommand' \
'*::option:->option'
case $state in
(subcommand)
local -a subcommands
subcommands=(
'add:Add directories to python path of active virtualenv'
'cp:Duplicate the named virtualenv to make a new one'
'inall:Run a command in each virtualenv:command'
'install:Use Pythonz to download and build the specified Python version'
'list_pythons:List the pythons installed by Pythonz (or all the installable ones)'
'locate_python:Locate the path for the python version installed by Pythonz'
'ls:List all existing virtual environments'
'lssitepackages:List currently active site-packages'
'mkproject:Create environment with an associated project directory'
'mktmpenv:Create a temporary virtualenv'
'new:Create a new environment'
'rename:Rename a virtualenv'
'restore:Try to restore a broken virtualenv by reinstalling the same python version on top of it'
'rm:Remove one or more environments'
'setproject:Bind an existing virtualenv to an existing project directory'
'show:Display currently active virtualenv'
'sitepackages_dir:Location of the currently active site-packages'
'toggleglobalsitepackages:Toggle access to global site-packages for current virtualenv'
'wipeenv:Remove all installed packages from current env'
'workon:Activates an existing virtual environment'
)
_describe -t commands 'pew subcommands' subcommands
;;
(option)
local -a new_env_options
new_env_options=(
'-h[Show help]'
'-p[Python executable]:python:_command_names'
'*-i[Install a package after the environment is created]:package name'
'-a[Project directory to associate]:project directory:_path_files -/'
'-r[Pip requirements file]:requirements file:_files'
)
case "$line[1]" in
(mktmpenv)
_arguments \
$new_env_options
;;
(new)
_arguments \
$new_env_options \
'1:new env name'
;;
(mkproject)
_arguments \
$new_env_options \
'*-t[Apply templates]' \
'-l[List available templates]' \
'1:new env name'
;;
(ls)
_arguments \
'(-l --long)--long[Verbose ls]' \
'(-b --brief)--brief[One line ls]'
;;
(inall)
_arguments \
'*:command'
;;
(show|workon|rm|wipeenv|restore)
_arguments \
'1:virtual env:_pew_list_venvs'
;;
(cp)
_arguments \
'1:virtual env:_pew_list_venvs' \
'2:new env name'
;;
(add)
_arguments \
'-h[Show help]' \
'-d[Removes previously added directories]' \
'*: :_directories -/'
;;
(setproject)
_arguments \
'1:virtual env:_pew_list_venvs' \
'*:project directory:_directories -/'
;;
esac
esac
@@ -1,4 +0,0 @@
#! /usr/bin/env python
from pew.pew import deploy_completions
if __name__ == '__main__':
deploy_completions()
@@ -1,3 +0,0 @@
source "$( dirname "${BASH_SOURCE[0]}" )"/complete.bash
[[ -z "${VIRTUAL_ENV}" ]] || PS1="\[\033[01;34m\]\$(basename '$VIRTUAL_ENV')\[\e[0m\] $PS1"
@@ -1,9 +0,0 @@
. (dirname (status --current-filename))/complete.fish
function pew_prompt
if [ -n "$VIRTUAL_ENV" ]
echo -n (set_color --bold -b blue white) (basename "$VIRTUAL_ENV") (set_color normal)" "
end
end
# Remember to use (pew_prompt) inside fish_prompt if you want your prompt to display the active environment
-12
View File
@@ -1,12 +0,0 @@
fpath=( ${0:a:h} "${fpath[@]}" )
compinit
function virtualenv_prompt_info() {
if [ -n "$VIRTUAL_ENV" ]; then
local name=$(basename $VIRTUAL_ENV)
echo "($name) "
fi
}
PS1="$(virtualenv_prompt_info)$PS1"
# be sure to disable promptinit if the prompt is not updated
-6
View File
@@ -1,6 +0,0 @@
#! /bin/sh
# put this inside $WORKON_HOME
project=$1
project_dir=$2
pip install django
django-admin.py startproject "$project"
+1 -1
View File
@@ -341,7 +341,7 @@ def fs_str(string):
_fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
# Borrowed from pew to avoid importing pew which imports psutil
# Borrowed from Pew.
# See https://github.com/berdario/pew/blob/master/pew/_utils.py#L82
@contextmanager
def temp_environ():
View File
-13
View File
@@ -1,13 +0,0 @@
import os
import sys
PIPENV_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PIPENV_VENDOR = os.sep.join([PIPENV_ROOT, 'vendor'])
PIPENV_PATCHED = os.sep.join([PIPENV_ROOT, 'patched'])
import pew
if __name__ == '__main__':
sys.path.insert(0, PIPENV_VENDOR)
sys.path.insert(0, PIPENV_PATCHED)
pew.pew.pew()
+3 -4
View File
@@ -326,7 +326,6 @@ Then, simply run:
.sp
.nf
.ft C
$ pipsi install pew
$ pipsi install pipenv
.ft P
.fi
@@ -345,7 +344,7 @@ $ pipsi upgrade pipenv
.UNINDENT
.UNINDENT
.sp
This will install both \fBpipenv\fP and \fBpew\fP (one of our dependencies) in an isolated virtualenv, so it doesn\(aqt interfere with the rest of your Python installation!
This will install \fBpipenv\fP in an isolated virtualenv, so it doesn\(aqt interfere with the rest of your Python installation!
.SS Pragmatic Installation of Pipenv
.sp
If you have a working installation of pip, and maintain certain "toolchain" type Python modules as global utilities in your user environment, pip \fI\%user installs\fP allow for installation into your home directory. Note that due to interaction between dependencies, you should limit tools installed in this way to basic building blocks for a Python workflow like virtualenv, pipenv, tox, and similar software.
@@ -1172,7 +1171,7 @@ will detect it.
\fBPIPENV_SHELL_FANCY\fP — Always use fancy mode when invoking \fBpipenv shell\fP\&.
.IP \(bu 2
\fBPIPENV_VENV_IN_PROJECT\fP — If set, use \fB\&.venv\fP in your project directory
instead of the global virtualenv manager \fBpew\fP\&.
instead of the global location.
.IP \(bu 2
\fBPIPENV_COLORBLIND\fP — Disable terminal colors, for some reason.
.IP \(bu 2
@@ -1205,7 +1204,7 @@ $ PIP_INSTALL_OPTION="\-\- \-DCMAKE_BUILD_TYPE=Release" pipenv install \-e .
.UNINDENT
.SS Custom Virtual Environment Location
.sp
Pipenv\(aqs underlying \fBpew\fP dependency will automatically honor the \fBWORKON_HOME\fP environment
Pipenv will automatically honor the \fBWORKON_HOME\fP environment
variable, if you have it set —\ so you can tell pipenv to store your virtual environments wherever you want, e.g.:
.INDENT 0.0
.INDENT 3.5
+1 -1
View File
@@ -920,7 +920,7 @@ def find_requirements(max_depth=3):
raise RuntimeError("No requirements.txt found!")
# Borrowed from pew to avoid importing pew which imports psutil
# Borrowed from Pew.
# See https://github.com/berdario/pew/blob/master/pew/_utils.py#L82
@contextmanager
def temp_environ():
-1
View File
@@ -111,7 +111,6 @@ setup(
entry_points={
"console_scripts": [
"pipenv=pipenv:cli",
"pewtwo=pipenv.patched.pew.pew:pew",
"pipenv-resolver=pipenv.resolver:main",
]
},
+2 -4
View File
@@ -8,7 +8,6 @@ from pipenv.utils import mkdir_p
# from tempfile import TemporaryDirectory
import tarfile
import zipfile
import os
import re
import shutil
import sys
@@ -41,7 +40,6 @@ HARDCODED_LICENSE_URLS = {
'semver': 'https://raw.githubusercontent.com/k-bx/python-semver/master/LICENSE.txt',
'crayons': 'https://raw.githubusercontent.com/kennethreitz/crayons/master/LICENSE',
'pip-tools': 'https://raw.githubusercontent.com/jazzband/pip-tools/master/LICENSE',
'pew': 'https://raw.githubusercontent.com/berdario/pew/master/LICENSE',
'pytoml': 'https://github.com/avakar/pytoml/raw/master/LICENSE',
'webencodings': 'https://github.com/SimonSapin/python-webencodings/raw/'
'master/LICENSE',
@@ -141,7 +139,7 @@ def rewrite_imports(package_dir, vendored_libs, vendor_dir):
def rewrite_file_imports(item, vendored_libs, vendor_dir):
"""Rewrite 'import xxx' and 'from xxx import' for vendored_libs"""
log('Reading file: %s' % item)
try:
try:
text = item.read_text(encoding='utf-8')
except UnicodeDecodeError:
text = item.read_text(encoding='cp1252')
@@ -489,7 +487,7 @@ def extract_license_member(vendor_dir, tar, member, name):
def generate_patch(ctx, package_path, patch_description, base='HEAD'):
pkg = Path(package_path)
if len(pkg.parts) != 2 or pkg.parts[0] not in ('vendor', 'patched'):
raise ValueError('example usage: generate-patch patched/pew some-description')
raise ValueError('example usage: generate-patch patched/piptools some-description')
if patch_description:
patch_fn = '{0}-{1}.patch'.format(pkg.parts[1], patch_description)
else:
@@ -1,14 +0,0 @@
diff --git a/pipenv/patched/pew/pew.py b/pipenv/patched/pew/pew.py
index 2d3889a0..91f313c1 100644
--- a/pipenv/patched/pew/pew.py
+++ b/pipenv/patched/pew/pew.py
@@ -184,7 +184,8 @@ def fork_bash(env, cwd):
def fork_cmder(env, cwd):
shell_cmd = ['cmd']
- cmderrc_path = r'%CMDER_ROOT%\vendor\init.bat'
+ escaped_cmder_root = os.environ['CMDER_ROOT'].replace(' ', '^ ')
+ cmderrc_path = r'{0}\vendor\init.bat'.format(escaped_cmder_root)
if expandpath(cmderrc_path).exists():
shell_cmd += ['/k', cmderrc_path]
if cwd:
@@ -1,13 +0,0 @@
diff --git a/pipenv/patched/pew/pew.py b/pipenv/patched/pew/pew.py
index 2d3889a0..07dbdf4f 100644
--- a/pipenv/patched/pew/pew.py
+++ b/pipenv/patched/pew/pew.py
@@ -215,6 +215,8 @@ def shell(env, cwd=None):
inve(env, shell, '-c', shell_check)
except CalledProcessError:
return
+ if shell_name in ('Cmder', 'cmd'):
+ os.environ['PROMPT'] = '({0}) {1}'.format(env, os.environ['PROMPT'])
if shell_name == 'bash':
fork_bash(env, cwd)
elif shell_name == 'Cmder':
-287
View File
@@ -1,287 +0,0 @@
diff --git a/pipenv/patched/pew/_print_utils.py b/pipenv/patched/pew/_print_utils.py
index 91a1d2b..05584e0 100644
--- a/pipenv/patched/pew/_print_utils.py
+++ b/pipenv/patched/pew/_print_utils.py
@@ -9,7 +9,7 @@ except ImportError:
try:
from shutil import get_terminal_size
except ImportError:
- from backports.shutil_get_terminal_size import get_terminal_size
+ from pipenv.vendor.backports.shutil_get_terminal_size import get_terminal_size
SEP = ' '
L = len(SEP)
diff --git a/pipenv/patched/pew/_utils.py b/pipenv/patched/pew/_utils.py
index d1d8e0a..c45c37e 100644
--- a/pipenv/patched/pew/_utils.py
+++ b/pipenv/patched/pew/_utils.py
@@ -6,7 +6,10 @@ from contextlib import contextmanager
from subprocess import check_call, Popen, PIPE
from collections import namedtuple
from functools import partial, wraps
-from pathlib import Path
+try:
+ from pathlib import Path
+except ImportError:
+ from pipenv.vendor.pathlib2 import Path
from tempfile import NamedTemporaryFile as _ntf
try:
from shutil import which
diff --git a/pipenv/patched/pew/pew.py b/pipenv/patched/pew/pew.py
index bcaabad..b8fc3e7 100644
--- a/pipenv/patched/pew/pew.py
+++ b/pipenv/patched/pew/pew.py
@@ -8,12 +8,15 @@ import random
import textwrap
from functools import partial
from subprocess import CalledProcessError
-from pathlib import Path
+try:
+ from pathlib import Path
+except ImportError:
+ from pipenv.vendor.pathlib2 import Path
try:
from shutil import get_terminal_size
except ImportError:
- from backports.shutil_get_terminal_size import get_terminal_size
+ from pipenv.vendor.backports.shutil_get_terminal_size import get_terminal_size
windows = sys.platform == 'win32'
@@ -36,7 +39,7 @@ else:
InstallCommand = ListPythons = LocatePython = UninstallCommand = \
lambda : sys.exit('Command not supported on this platform')
- import psutil
+ 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)
@@ -52,8 +55,9 @@ if windows:
else:
default_home = os.path.join(
os.environ.get('XDG_DATA_HOME', '~/.local/share'), 'virtualenvs')
-workon_home = expandpath(
- os.environ.get('WORKON_HOME', default_home))
+
+def get_workon_home():
+ return expandpath(os.environ.get('WORKON_HOME', default_home))
def makedirs_and_symlink_if_needed(workon_home):
@@ -96,7 +100,7 @@ def deploy_completions():
def get_project_dir(env):
- project_file = workon_home / env / '.project'
+ project_file = get_workon_home() / env / '.project'
if project_file.exists():
with project_file.open() as f:
project_dir = f.readline().strip()
@@ -113,7 +117,7 @@ def unsetenv(key):
def compute_path(env):
- envdir = workon_home / env
+ envdir = get_workon_home() / env
return os.pathsep.join([
str(envdir / env_bin_dir),
os.environ['PATH'],
@@ -127,7 +131,7 @@ def inve(env, command, *args, **kwargs):
# we don't strictly need to restore the environment, since pew runs in
# its own process, but it feels like the right thing to do
with temp_environ():
- os.environ['VIRTUAL_ENV'] = str(workon_home / env)
+ os.environ['VIRTUAL_ENV'] = str(get_workon_home() / env)
os.environ['PATH'] = compute_path(env)
unsetenv('PYTHONHOME')
@@ -151,7 +155,16 @@ def fork_shell(env, shellcmd, cwd):
if 'VIRTUAL_ENV' in os.environ:
err("Be aware that this environment will be nested on top "
"of '%s'" % Path(os.environ['VIRTUAL_ENV']).name)
- inve(env, *shellcmd, cwd=cwd)
+ try:
+ inve(env, *shellcmd, cwd=cwd)
+ except CalledProcessError:
+ # These shells report errors when the last command executed in the
+ # subshell in an error. This causes the subprocess to fail, which is
+ # not what we want. Stay silent for them, there's nothing we can do.
+ shell_name, _ = os.path.splitext(os.path.basename(shellcmd[0]))
+ suppress_error = shell_name.lower() in ('cmd', 'powershell', 'pwsh')
+ if not suppress_error:
+ raise
def fork_bash(env, cwd):
@@ -184,7 +197,7 @@ def _detect_shell():
if 'CMDER_ROOT' in os.environ:
shell = 'Cmder'
elif windows:
- shell = psutil.Process(os.getpid()).parent().parent().name()
+ shell = get_shell(os.getpid())
else:
shell = 'sh'
return shell
@@ -193,10 +206,10 @@ def shell(env, cwd=None):
env = str(env)
shell = _detect_shell()
shell_name = Path(shell).stem
- if shell_name not in ('Cmder', 'bash', 'elvish', 'powershell', 'klingon', 'cmd'):
+ if shell_name not in ('Cmder', 'bash', 'elvish', 'powershell', 'pwsh', '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.pew import '
'prevent_path_errors; prevent_path_errors()"')
try:
inve(env, shell, '-c', shell_check)
@@ -216,7 +229,7 @@ def mkvirtualenv(envname, python=None, packages=[], project=None,
if python:
rest = ["--python=%s" % python] + rest
- path = (workon_home / envname).absolute()
+ path = (get_workon_home() / envname).absolute()
try:
check_call([sys.executable, "-m", "virtualenv", str(path)] + rest)
@@ -265,7 +278,7 @@ project directory to associate with the new environment.')
def rmvirtualenvs(envs):
error_happened = False
for env in envs:
- env = workon_home / env
+ env = get_workon_home() / env
if os.environ.get('VIRTUAL_ENV') == str(env):
err("ERROR: You cannot remove the active environment (%s)." % env)
error_happened = True
@@ -295,7 +308,7 @@ def packages(site_packages):
def showvirtualenv(env):
columns, _ = get_terminal_size()
pkgs = sorted(packages(sitepackages_dir(env)))
- env_python = workon_home / env / env_bin_dir / 'python'
+ env_python = get_workon_home() / env / env_bin_dir / 'python'
l = len(env) + 2
version = invoke(str(env_python), '-V')
version = ' - '.join((version.out + version.err).splitlines())
@@ -317,8 +330,8 @@ def show_cmd(argv):
def lsenvs():
- return sorted(set(env.parts[-3] for env in
- workon_home.glob(os.path.join('*', env_bin_dir, 'python*'))))
+ items = get_workon_home().glob(os.path.join('*', env_bin_dir, 'python*'))
+ return sorted(set(env.parts[-3] for env in items))
def lsvirtualenv(verbose):
@@ -347,7 +360,7 @@ def parse_envname(argv, no_arg_callback):
env = argv[0]
if env.startswith('/'):
sys.exit("ERROR: Invalid environment name '{0}'.".format(env))
- if not (workon_home / env).exists():
+ if not (get_workon_home() / env).exists():
sys.exit("ERROR: Environment '{0}' does not exist. Create it with \
'pew new {0}'.".format(env))
else:
@@ -372,7 +385,7 @@ def sitepackages_dir(env=os.environ.get('VIRTUAL_ENV')):
if not env:
sys.exit('ERROR: no virtualenv active')
else:
- env_python = workon_home / env / env_bin_dir / 'python'
+ env_python = get_workon_home() / env / env_bin_dir / 'python'
return Path(invoke(str(env_python), '-c', 'import distutils; \
print(distutils.sysconfig.get_python_lib())').out)
@@ -459,6 +472,7 @@ def cp_cmd(argv):
def copy_virtualenv_project(source, target):
source = expandpath(source)
+ workon_home = get_workon_home()
if not source.exists():
source = workon_home / source
if not source.exists():
@@ -490,7 +504,7 @@ def rename_cmd(argv):
def setvirtualenvproject(env, project):
print('Setting project for {0} to {1}'.format(env, project))
- with (workon_home / env / '.project').open('wb') as prj:
+ with (get_workon_home() / env / '.project').open('wb') as prj:
prj.write(str(project).encode())
@@ -502,7 +516,7 @@ def setproject_cmd(argv):
env = args.get(0, os.environ.get('VIRTUAL_ENV'))
if not env:
sys.exit('pew setproject [virtualenv] [project_path]')
- if not (workon_home / env).exists():
+ if not (get_workon_home() / env).exists():
sys.exit("Environment '%s' doesn't exist." % env)
if not os.path.isdir(project):
sys.exit('pew setproject: %s does not exist' % project)
@@ -512,7 +526,7 @@ def setproject_cmd(argv):
def mkproject_cmd(argv):
"""Create a new project directory and its associated virtualenv."""
if '-l' in argv or '--list' in argv:
- templates = [t.name[9:] for t in workon_home.glob("template_*")]
+ templates = [t.name[9:] for t in get_workon_home().glob("template_*")]
print("Available project templates:", *templates, sep='\n')
return
@@ -542,7 +556,7 @@ Create it or set PROJECT_HOME to an existing directory.' % projects_home)
project.mkdir()
for template_name in args.templates:
- template = workon_home / ("template_" + template_name)
+ template = get_workon_home() / ("template_" + template_name)
inve(args.envname, str(template), args.envname, str(project))
if args.activate:
shell(args.envname, cwd=str(project))
@@ -552,7 +566,7 @@ def mktmpenv_cmd(argv):
"""Create a temporary virtualenv."""
parser = mkvirtualenv_argparser()
env = '.'
- while (workon_home / env).exists():
+ while (get_workon_home() / env).exists():
env = hex(random.getrandbits(64))[2:-1]
args, rest = parser.parse_known_args(argv)
@@ -574,10 +588,10 @@ def wipeenv_cmd(argv):
if not env:
sys.exit('ERROR: no virtualenv active')
- elif not (workon_home / env).exists():
+ elif not (get_workon_home() / env).exists():
sys.exit("ERROR: Environment '{0}' does not exist.".format(env))
else:
- env_pip = str(workon_home / env / env_bin_dir / 'pip')
+ env_pip = str(get_workon_home() / env / env_bin_dir / 'pip')
all_pkgs = set(invoke(env_pip, 'freeze').out.splitlines())
pkgs = set(p for p in all_pkgs if len(p.split("==")) == 2)
ignored = sorted(all_pkgs - pkgs)
@@ -623,6 +637,7 @@ def restore_cmd(argv):
sys.exit('You must provide a valid virtualenv to target')
env = argv[0]
+ path = get_workon_home() / env
path = workon_home / env
py = path / env_bin_dir / ('python.exe' if windows else 'python')
exact_py = py.resolve().name
@@ -633,7 +648,7 @@ def restore_cmd(argv):
def dir_cmd(argv):
"""Print the path for the virtualenv directory"""
env = parse_envname(argv, lambda : sys.exit('You must provide a valid virtualenv to target'))
- print(workon_home / env)
+ print(get_workon_home() / env)
def install_cmd(argv):
@@ -745,7 +760,7 @@ def print_commands(cmds):
def pew():
- first_run = makedirs_and_symlink_if_needed(workon_home)
+ first_run = makedirs_and_symlink_if_needed(get_workon_home())
if first_run and sys.stdin.isatty():
first_run_setup()
@@ -1,151 +0,0 @@
diff --git a/pipenv/patched/pew/__main__.py b/pipenv/patched/pew/__main__.py
index e35cf68..2267b8d 100644
--- a/pipenv/patched/pew/__main__.py
+++ b/pipenv/patched/pew/__main__.py
@@ -1,3 +1,4 @@
-from pew.pew import pew
+from . import pew
-pew()
+if __name__ == '__main__':
+ pew.pew.pew()
diff --git a/pipenv/patched/pew/_win_utils.py b/pipenv/patched/pew/_win_utils.py
new file mode 100644
index 0000000..8ab7a0b
--- /dev/null
+++ b/pipenv/patched/pew/_win_utils.py
@@ -0,0 +1,121 @@
+# -*- coding=utf-8 -*-
+# psutil is painfully slow in win32. So to avoid adding big
+# dependencies like pywin32 a ctypes based solution is preferred
+
+# Code based on the winappdbg project http://winappdbg.sourceforge.net/
+# (BSD License) - adapted from Celery
+# https://github.com/celery/celery/blob/2.5-archived/celery/concurrency/processes/_win.py
+import os
+import six
+from ctypes import (
+ byref, sizeof, windll, Structure, WinError, POINTER,
+ c_size_t, c_char, c_void_p
+)
+from ctypes.wintypes import DWORD, LONG
+
+ERROR_NO_MORE_FILES = 18
+INVALID_HANDLE_VALUE = c_void_p(-1).value
+SHELL_NAMES = ['cmd', 'powershell', 'pwsh', 'cmder']
+
+
+class PROCESSENTRY32(Structure):
+ _fields_ = [
+ ('dwSize', DWORD),
+ ('cntUsage', DWORD),
+ ('th32ProcessID', DWORD),
+ ('th32DefaultHeapID', c_size_t),
+ ('th32ModuleID', DWORD),
+ ('cntThreads', DWORD),
+ ('th32ParentProcessID', DWORD),
+ ('pcPriClassBase', LONG),
+ ('dwFlags', DWORD),
+ ('szExeFile', c_char * 260),
+ ]
+
+
+LPPROCESSENTRY32 = POINTER(PROCESSENTRY32)
+
+
+def CreateToolhelp32Snapshot(dwFlags=2, th32ProcessID=0):
+ hSnapshot = windll.kernel32.CreateToolhelp32Snapshot(
+ dwFlags,
+ th32ProcessID
+ )
+ if hSnapshot == INVALID_HANDLE_VALUE:
+ raise WinError()
+ return hSnapshot
+
+
+def Process32First(hSnapshot):
+ pe = PROCESSENTRY32()
+ pe.dwSize = sizeof(PROCESSENTRY32)
+ success = windll.kernel32.Process32First(hSnapshot, byref(pe))
+ if not success:
+ if windll.kernel32.GetLastError() == ERROR_NO_MORE_FILES:
+ return
+ raise WinError()
+ return pe
+
+
+def Process32Next(hSnapshot, pe=None):
+ if pe is None:
+ pe = PROCESSENTRY32()
+ pe.dwSize = sizeof(PROCESSENTRY32)
+ success = windll.kernel32.Process32Next(hSnapshot, byref(pe))
+ if not success:
+ if windll.kernel32.GetLastError() == ERROR_NO_MORE_FILES:
+ return
+ raise WinError()
+ return pe
+
+
+def get_all_processes():
+ """Return a dictionary of properties about all processes.
+
+ >>> get_all_processes()
+ {
+ 1509: {
+ 'parent_pid': 1201,
+ 'executable': 'C:\\Program\\\\ Files\\Python36\\python.exe'
+ }
+ }
+ """
+ h_process = CreateToolhelp32Snapshot()
+ pids = {}
+ pe = Process32First(h_process)
+ while pe:
+ pids[pe.th32ProcessID] = {
+ 'executable': str(pe.szExeFile.decode('utf-8'))
+ }
+ if pe.th32ParentProcessID:
+ pids[pe.th32ProcessID]['parent_pid'] = pe.th32ParentProcessID
+ pe = Process32Next(h_process, pe)
+
+ return pids
+
+
+def _get_executable(process_dict):
+ if hasattr(process_dict, 'keys'):
+ executable = process_dict.get('executable')
+ if isinstance(executable, six.string_types):
+ return executable.lower().rsplit('.', 1)[0]
+ return ''
+
+
+def get_shell(pid=None, max_depth=6):
+ """Get the shell that the supplied pid or os.getpid() is running in.
+ """
+ if not pid:
+ pid = os.getpid()
+ processes = get_all_processes()
+
+ def check_parent(pid, lvl=0):
+ ppid = processes[pid].get('parent_pid')
+ if ppid and _get_executable(processes.get(ppid)) in SHELL_NAMES:
+ return processes[ppid]['executable']
+ if lvl >= max_depth:
+ return
+ return check_parent(ppid, lvl=lvl+1)
+ if _get_executable(processes.get(pid)) in SHELL_NAMES:
+ return processes[pid]['executable']
+ return check_parent(pid)
diff --git a/pipenv/patched/pew/template_django b/pipenv/patched/pew/template_django
new file mode 100644
index 0000000..4fec88e
--- /dev/null
+++ b/pipenv/patched/pew/template_django
@@ -0,0 +1,6 @@
+#! /bin/sh
+# put this inside $WORKON_HOME
+project=$1
+project_dir=$2
+pip install django
+django-admin.py startproject "$project"
\ No newline at end of file
-45
View File
@@ -39,48 +39,3 @@ def test_reuse_previous_venv(PipenvInstance, pypi):
c = p.pipenv('install requests')
assert c.return_code == 0
assert normalize_drive(p.path) in p.pipenv('--venv').out
@pytest.mark.dotvenv
@pytest.mark.install
@pytest.mark.complex
@pytest.mark.shell
@pytest.mark.windows
@pytest.mark.pew
@pytest.mark.skip('Not mocking this.')
def test_shell_nested_venv_in_project(PipenvInstance, pypi):
import subprocess
with temp_environ():
os.environ['PIPENV_VENV_IN_PROJECT'] = '1'
os.environ['PIPENV_IGNORE_VIRTUALENVS'] = '1'
with PipenvInstance(chdir=True, pypi=pypi) as p:
# Signal to pew to look in the project directory for the environment
os.environ['WORKON_HOME'] = p.path
c = p.pipenv('install requests')
assert c.return_code == 0
assert 'requests' in p.pipfile['packages']
assert 'requests' in p.lockfile['default']
# Check that .venv now shows in pew's managed list
pew_list = delegator.run('pewtwo ls')
assert '.venv' in pew_list.out
# Check for the venv directory
c = delegator.run('pewtwo dir .venv')
# Compare pew's virtualenv path to what we expect
venv_path = get_windows_path(Project().project_directory, '.venv')
# os.path.normpath will normalize slashes
assert venv_path == normalize_drive(os.path.normpath(c.out.strip()))
# Have pew run 'pip freeze' in the virtualenv
# This is functionally the same as spawning a subshell
# If we can do this we can theoretically make a subshell
# This test doesn't work on *nix
if os.name == 'nt':
process = subprocess.Popen(
'pewtwo in .venv pip freeze',
shell=True,
universal_newlines=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
out, _ = process.communicate()
assert any(req.startswith('requests') for req in out.splitlines()) is True
+1 -4
View File
@@ -350,10 +350,7 @@ def test_editable_no_args(PipenvInstance):
@pytest.mark.install
@pytest.mark.virtualenv
def test_install_venv_project_directory(PipenvInstance, pypi):
"""Test pew's project functionality during virtualenv creation.
Since .venv virtualenvs are not created with pew, we need to swap to a
workon_home based virtualenv for this test.
"""Test the project functionality during virtualenv creation.
"""
with PipenvInstance(pypi=pypi, chdir=True) as p:
with temp_environ(), TemporaryDirectory(
+1 -3
View File
@@ -84,7 +84,7 @@ def test_update_locks(PipenvInstance, pypi):
@pytest.mark.project
@pytest.mark.proper_names
def test_proper_names_unamanged_virtualenv(PipenvInstance, pypi):
with PipenvInstance(chdir=True, pypi=pypi) as p:
with PipenvInstance(chdir=True, pypi=pypi):
c = delegator.run('python -m virtualenv .venv')
assert c.return_code == 0
project = Project()
@@ -100,8 +100,6 @@ def test_directory_with_leading_dash(PipenvInstance):
with mock.patch('pipenv._compat.mkdtemp', side_effect=mocked_mkdtemp):
with temp_environ(), PipenvInstance(chdir=True) as p:
# This environment variable is set in the context manager and will
# cause pipenv to use virtualenv, not pew.
del os.environ['PIPENV_VENV_IN_PROJECT']
p.pipenv('--python python')
venv_path = p.pipenv('--venv').out.strip()