mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 22:50:18 +00:00
Merge pull request #1605 from pypa/feature/vendor-pew
Vendor pew under script name `pewtwo`
This commit is contained in:
+1
-1
@@ -975,7 +975,7 @@ def do_create_virtualenv(python=None, site_packages=False):
|
||||
click.echo(crayons.normal(u'Making site-packages available…', bold=True), err=True)
|
||||
|
||||
os.environ['VIRTUAL_ENV'] = project.virtualenv_location
|
||||
delegator.run('pipenv run pew toggleglobalsitepackages')
|
||||
delegator.run('pipenv run pewtwo toggleglobalsitepackages')
|
||||
del os.environ['VIRTUAL_ENV']
|
||||
|
||||
# Say where the virtualenv is.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from . import pew
|
||||
__all__ = ['pew']
|
||||
@@ -0,0 +1,3 @@
|
||||
from pew.pew import pew
|
||||
|
||||
pew()
|
||||
@@ -0,0 +1,55 @@
|
||||
from __future__ import division, print_function
|
||||
|
||||
import os
|
||||
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 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()
|
||||
columns_number = 1
|
||||
for columns_number in range(1, len(venvs) + 1):
|
||||
rows = get_rows(venvs, columns_number)
|
||||
if max(map(row_len, rows)) > 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=' ')
|
||||
@@ -0,0 +1,89 @@
|
||||
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
|
||||
from pathlib 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)
|
||||
@@ -0,0 +1,107 @@
|
||||
# -*- 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
|
||||
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
|
||||
|
||||
|
||||
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_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.
|
||||
"""
|
||||
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']
|
||||
@@ -0,0 +1,768 @@
|
||||
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
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
from shutil import get_terminal_size
|
||||
except ImportError:
|
||||
from 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_grandparent_process
|
||||
|
||||
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')
|
||||
workon_home = 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 = 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 = 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(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)
|
||||
inve(env, *shellcmd, cwd=cwd)
|
||||
|
||||
|
||||
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']
|
||||
cmderrc_path = r'%CMDER_ROOT%\vendor\init.bat'
|
||||
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_grandparent_process(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', '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 '
|
||||
'prevent_path_errors; prevent_path_errors()"')
|
||||
try:
|
||||
inve(env, shell, '-c', shell_check)
|
||||
except CalledProcessError:
|
||||
return
|
||||
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 = (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 = 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 = 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():
|
||||
return sorted(set(env.parts[-3] for env in
|
||||
workon_home.glob(os.path.join('*', env_bin_dir, 'python*'))))
|
||||
|
||||
|
||||
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 (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 = 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)
|
||||
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 (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 (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 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 = 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 (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 (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')
|
||||
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 = 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(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(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)
|
||||
@@ -0,0 +1 @@
|
||||
complete.zsh
|
||||
@@ -0,0 +1,46 @@
|
||||
# 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
|
||||
@@ -0,0 +1,116 @@
|
||||
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'
|
||||
@@ -0,0 +1,107 @@
|
||||
#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
|
||||
@@ -0,0 +1,4 @@
|
||||
#! /usr/bin/env python
|
||||
from pew.pew import deploy_completions
|
||||
if __name__ == '__main__':
|
||||
deploy_completions()
|
||||
@@ -0,0 +1,3 @@
|
||||
source "$( dirname "${BASH_SOURCE[0]}" )"/complete.bash
|
||||
|
||||
PS1="\[\033[01;34m\]\$(basename '$VIRTUAL_ENV')\[\e[0m\]$PS1"
|
||||
@@ -0,0 +1,9 @@
|
||||
. (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
|
||||
@@ -0,0 +1,12 @@
|
||||
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
|
||||
@@ -0,0 +1,6 @@
|
||||
#! /bin/sh
|
||||
# put this inside $WORKON_HOME
|
||||
project=$1
|
||||
project_dir=$2
|
||||
pip install django
|
||||
django-admin.py startproject "$project"
|
||||
@@ -1,5 +1,4 @@
|
||||
import pew
|
||||
from pipenv.patched import pew
|
||||
|
||||
if __name__ == '__main__':
|
||||
pew.pew.pew()
|
||||
|
||||
|
||||
+1
-1
@@ -176,7 +176,7 @@ class Project(object):
|
||||
|
||||
# The user wants the virtualenv in the project.
|
||||
if not PIPENV_VENV_IN_PROJECT:
|
||||
c = delegator.run('pew dir "{0}"'.format(self.virtualenv_name))
|
||||
c = delegator.run('pewtwo dir "{0}"'.format(self.virtualenv_name))
|
||||
loc = c.out.strip()
|
||||
# Default mode.
|
||||
else:
|
||||
|
||||
@@ -23,7 +23,8 @@ if sys.argv[-1] == "publish":
|
||||
|
||||
required = [
|
||||
'virtualenv',
|
||||
'pew>=0.1.26'
|
||||
'virtualenv-clone>=0.2.5',
|
||||
'pathlib;python_version<"3.4"'
|
||||
]
|
||||
|
||||
if sys.version_info < (2, 7):
|
||||
@@ -113,7 +114,10 @@ setup(
|
||||
url='https://github.com/pypa/pipenv',
|
||||
packages=find_packages(exclude=['tests']),
|
||||
entry_points={
|
||||
'console_scripts': ['pipenv=pipenv:cli'],
|
||||
'console_scripts': [
|
||||
'pipenv=pipenv:cli',
|
||||
'pewtwo=pipenv.patched.pew.pew:pew'
|
||||
],
|
||||
},
|
||||
install_requires=required,
|
||||
extras_require={
|
||||
|
||||
@@ -692,10 +692,10 @@ requests = {version = "*"}
|
||||
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('pew ls')
|
||||
pew_list = delegator.run('pewtwo ls')
|
||||
assert '.venv' in pew_list.out
|
||||
# Check for the venv directory
|
||||
c = delegator.run('pew dir .venv')
|
||||
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
|
||||
@@ -705,7 +705,7 @@ requests = {version = "*"}
|
||||
# If we can do this we can theoretically make a subshell
|
||||
# This test doesn't work on *nix
|
||||
if os.name == 'nt':
|
||||
args = ['pew', 'in', '.venv', 'pip', 'freeze']
|
||||
args = ['pewtwo', 'in', '.venv', 'pip', 'freeze']
|
||||
process = subprocess.Popen(
|
||||
args,
|
||||
shell=True,
|
||||
|
||||
Reference in New Issue
Block a user