diff --git a/operational b/operational index 3359108ea37de36966f4a355d91b6a1686508ea5..1bdf0f1dd8e49b2236a6cc1b24ea5f5679d4338e 100644 --- a/operational +++ b/operational @@ -46,6 +46,18 @@ Time-stamp: <2019-02-27> - to upgrade project, make commits, and push to gitlab, the rest will follow. click approval to deploy to production. +** 2019-02-27 how to update virtualenv in utils/ dir +- update files + VERSION=16.4.1 + tar tf ~/d/virtualenv-$VERSION.tar.gz + cd src/leiningen/new/python/utils/ + tar xzf ~/d/virtualenv-$VERSION.tar.gz \ + virtualenv-$VERSION/virtualenv.py \ + virtualenv-$VERSION/virtualenv_support/ \ + virtualenv-$VERSION/LICENSE.txt +- update file list in ./src/leiningen/new/python.clj + TODO update the code to auto include all files in utils/virtualenv-* dir. + * current :entry: ** ** 2019-02-24 fix :url in project.clj diff --git a/project.clj b/project.clj index 67e20d717b57be593197108483708b6bc1b0bb9d..1315f5e819e3b27b38bcc69329a8208115e8a668 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject python/lein-template "1.4.2" +(defproject python/lein-template "1.5.0" :description "lein template for a python project" :url "https://blog.emacsos.com/python-project-template" :license {:name "Eclipse Public License" diff --git a/src/leiningen/new/python.clj b/src/leiningen/new/python.clj index 77a308619e2ea3de7688f252ddee4c29a54c8e38..613e5561938b29db99a199146b5ebd95d0ab494c 100644 --- a/src/leiningen/new/python.clj +++ b/src/leiningen/new/python.clj @@ -71,12 +71,12 @@ ] plain-files ["utils/__init__.py" "utils/choose_default_python.sh" - "utils/virtualenv-15.1.0/virtualenv.py" - "utils/virtualenv-15.1.0/virtualenv_support/argparse-1.4.0-py2.py3-none-any.whl" - "utils/virtualenv-15.1.0/virtualenv_support/setuptools-28.8.0-py2.py3-none-any.whl" - "utils/virtualenv-15.1.0/virtualenv_support/wheel-0.29.0-py2.py3-none-any.whl" - "utils/virtualenv-15.1.0/virtualenv_support/pip-9.0.1-py2.py3-none-any.whl" - "utils/virtualenv-15.1.0/virtualenv_support/__init__.py" + ;; virtualenv + "utils/virtualenv-16.4.1/virtualenv_support/pip-19.0.3-py2.py3-none-any.whl" + "utils/virtualenv-16.4.1/virtualenv_support/setuptools-40.8.0-py2.py3-none-any.whl" + "utils/virtualenv-16.4.1/virtualenv_support/wheel-0.33.1-py2.py3-none-any.whl" + "utils/virtualenv-16.4.1/virtualenv_support/__init__.py" + "utils/virtualenv-16.4.1/virtualenv.py" ] empty-files [] package-files ["__init__.py" diff --git a/src/leiningen/new/python/Makefile b/src/leiningen/new/python/Makefile index 654b97f8d8d99b6f3787633ecc19c33dc8a7a56e..e2f267d4c73c805624357ececaeeacd7b93801b6 100644 --- a/src/leiningen/new/python/Makefile +++ b/src/leiningen/new/python/Makefile @@ -8,7 +8,7 @@ PYTHON := env PYTHONPATH=$(PYTHONPATH) $(VENV)/bin/python PIP := $(VENV)/bin/pip DEFAULT_PYTHON := $(shell ./utils/choose_default_python.sh) -VIRTUALENV := ./utils/virtualenv-15.1.0/virtualenv.py +VIRTUALENV := $(shell ls ./utils/virtualenv-*/virtualenv.py) REQUIREMENTS := -r requirements.txt DEV_REQUIREMENTS := -r requirements-dev.txt diff --git a/src/leiningen/new/python/utils/virtualenv-15.1.0/AUTHORS.txt b/src/leiningen/new/python/utils/virtualenv-15.1.0/AUTHORS.txt deleted file mode 100644 index 272494163e7ccd48b5cbf4a12ee77cdaa52516c5..0000000000000000000000000000000000000000 --- a/src/leiningen/new/python/utils/virtualenv-15.1.0/AUTHORS.txt +++ /dev/null @@ -1,91 +0,0 @@ -Author ------- - -Ian Bicking - -Maintainers ------------ - -Brian Rosner -Carl Meyer -Jannis Leidel -Paul Moore -Paul Nasrat -Marcus Smith - -Contributors ------------- - -Alex Grönholm -Anatoly Techtonik -Antonio Cuni -Antonio Valentino -Armin Ronacher -Barry Warsaw -Benjamin Root -Bradley Ayers -Branden Rolston -Brandon Carl -Brian Kearns -Cap Petschulat -CBWhiz -Chris Adams -Chris McDonough -Christos Kontas -Christian Hudon -Christian Stefanescu -Christopher Nilsson -Cliff Xuan -Curt Micol -Damien Nozay -Dan Sully -Daniel Hahler -Daniel Holth -David Schoonover -Denis Costa -Doug Hellmann -Doug Napoleone -Douglas Creager -Eduard-Cristian Stefan -Erik M. Bray -Ethan Jucovy -Gabriel de Perthuis -Gunnlaugur Thor Briem -Graham Dennis -Greg Haskins -Jason Penney -Jason R. Coombs -Jeff Hammel -Jeremy Orem -Jason Penney -Jason R. Coombs -John Kleint -Jonathan Griffin -Jonathan Hitchcock -Jorge Vargas -Josh Bronson -Kamil Kisiel -Kyle Gibson -Konstantin Zemlyak -Kumar McMillan -Lars Francke -Marc Abramowitz -Mika Laitio -Mike Hommey -Miki Tebeka -Philip Jenvey -Philippe Ombredanne -Piotr Dobrogost -Preston Holmes -Ralf Schmitt -Raul Leal -Ronny Pfannschmidt -Satrajit Ghosh -Sergio de Carvalho -Stefano Rivera -Tarek Ziadé -Thomas Aglassinger -Vinay Sajip -Vitaly Babiy -Vladimir Rutsky -Wang Xuerui \ No newline at end of file diff --git a/src/leiningen/new/python/utils/virtualenv-15.1.0/README.rst b/src/leiningen/new/python/utils/virtualenv-15.1.0/README.rst deleted file mode 100644 index 0d5984dceff395f1d4a7c081be064dc31eb2d6d5..0000000000000000000000000000000000000000 --- a/src/leiningen/new/python/utils/virtualenv-15.1.0/README.rst +++ /dev/null @@ -1,31 +0,0 @@ -virtualenv -========== - -A tool for creating isolated 'virtual' python environments. - -.. image:: https://img.shields.io/pypi/v/virtualenv.svg - :target: https://pypi.python.org/pypi/virtualenv - -.. image:: https://img.shields.io/travis/pypa/virtualenv/develop.svg - :target: http://travis-ci.org/pypa/virtualenv - -* `Installation `_ -* `Documentation `_ -* `Changelog `_ -* `Issues `_ -* `PyPI `_ -* `Github `_ -* `User mailing list `_ -* `Dev mailing list `_ -* User IRC: #pypa on Freenode. -* Dev IRC: #pypa-dev on Freenode. - - -Code of Conduct ---------------- - -Everyone interacting in the virtualenv project's codebases, issue trackers, -chat rooms, and mailing lists is expected to follow the -`PyPA Code of Conduct`_. - -.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/ diff --git a/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv.py b/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv.py deleted file mode 100755 index 42cd1f4b01f297714e53c9b0a766dc1915151be7..0000000000000000000000000000000000000000 --- a/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv.py +++ /dev/null @@ -1,2332 +0,0 @@ -#!/usr/bin/env python -"""Create a "virtual" Python installation""" - -import os -import sys - -# If we are running in a new interpreter to create a virtualenv, -# we do NOT want paths from our existing location interfering with anything, -# So we remove this file's directory from sys.path - most likely to be -# the previous interpreter's site-packages. Solves #705, #763, #779 -if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): - for path in sys.path[:]: - if os.path.realpath(os.path.dirname(__file__)) == os.path.realpath(path): - sys.path.remove(path) - -import base64 -import codecs -import optparse -import re -import shutil -import logging -import zlib -import errno -import glob -import distutils.sysconfig -import struct -import subprocess -import pkgutil -import tempfile -import textwrap -from distutils.util import strtobool -from os.path import join - -try: - import ConfigParser -except ImportError: - import configparser as ConfigParser - -__version__ = "15.1.0" -virtualenv_version = __version__ # legacy - -if sys.version_info < (2, 6): - print('ERROR: %s' % sys.exc_info()[1]) - print('ERROR: this script requires Python 2.6 or greater.') - sys.exit(101) - -try: - basestring -except NameError: - basestring = str - -py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1]) - -is_jython = sys.platform.startswith('java') -is_pypy = hasattr(sys, 'pypy_version_info') -is_win = (sys.platform == 'win32') -is_cygwin = (sys.platform == 'cygwin') -is_darwin = (sys.platform == 'darwin') -abiflags = getattr(sys, 'abiflags', '') - -user_dir = os.path.expanduser('~') -if is_win: - default_storage_dir = os.path.join(user_dir, 'virtualenv') -else: - default_storage_dir = os.path.join(user_dir, '.virtualenv') -default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini') - -if is_pypy: - expected_exe = 'pypy' -elif is_jython: - expected_exe = 'jython' -else: - expected_exe = 'python' - -# Return a mapping of version -> Python executable -# Only provided for Windows, where the information in the registry is used -if not is_win: - def get_installed_pythons(): - return {} -else: - try: - import winreg - except ImportError: - import _winreg as winreg - - def get_installed_pythons(): - try: - python_core = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, - "Software\\Python\\PythonCore") - except WindowsError: - # No registered Python installations - return {} - i = 0 - versions = [] - while True: - try: - versions.append(winreg.EnumKey(python_core, i)) - i = i + 1 - except WindowsError: - break - exes = dict() - for ver in versions: - try: - path = winreg.QueryValue(python_core, "%s\\InstallPath" % ver) - except WindowsError: - continue - exes[ver] = join(path, "python.exe") - - winreg.CloseKey(python_core) - - # Add the major versions - # Sort the keys, then repeatedly update the major version entry - # Last executable (i.e., highest version) wins with this approach - for ver in sorted(exes): - exes[ver[0]] = exes[ver] - - return exes - -REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath', - 'fnmatch', 'locale', 'encodings', 'codecs', - 'stat', 'UserDict', 'readline', 'copy_reg', 'types', - 're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile', - 'zlib'] - -REQUIRED_FILES = ['lib-dynload', 'config'] - -majver, minver = sys.version_info[:2] -if majver == 2: - if minver >= 6: - REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc']) - if minver >= 7: - REQUIRED_MODULES.extend(['_weakrefset']) -elif majver == 3: - # Some extra modules are needed for Python 3, but different ones - # for different versions. - REQUIRED_MODULES.extend([ - '_abcoll', 'warnings', 'linecache', 'abc', 'io', '_weakrefset', - 'copyreg', 'tempfile', 'random', '__future__', 'collections', - 'keyword', 'tarfile', 'shutil', 'struct', 'copy', 'tokenize', - 'token', 'functools', 'heapq', 'bisect', 'weakref', 'reprlib' - ]) - if minver >= 2: - REQUIRED_FILES[-1] = 'config-%s' % majver - if minver >= 3: - import sysconfig - platdir = sysconfig.get_config_var('PLATDIR') - REQUIRED_FILES.append(platdir) - REQUIRED_MODULES.extend([ - 'base64', '_dummy_thread', 'hashlib', 'hmac', - 'imp', 'importlib', 'rlcompleter' - ]) - if minver >= 4: - REQUIRED_MODULES.extend([ - 'operator', - '_collections_abc', - '_bootlocale', - ]) - if minver >= 6: - REQUIRED_MODULES.extend(['enum']) - -if is_pypy: - # these are needed to correctly display the exceptions that may happen - # during the bootstrap - REQUIRED_MODULES.extend(['traceback', 'linecache']) - - if majver == 3: - # _functools is needed to import locale during stdio initialization and - # needs to be copied on PyPy because it's not built in - REQUIRED_MODULES.append('_functools') - - -class Logger(object): - - """ - Logging object for use in command-line script. Allows ranges of - levels, to avoid some redundancy of displayed information. - """ - - DEBUG = logging.DEBUG - INFO = logging.INFO - NOTIFY = (logging.INFO+logging.WARN)/2 - WARN = WARNING = logging.WARN - ERROR = logging.ERROR - FATAL = logging.FATAL - - LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] - - def __init__(self, consumers): - self.consumers = consumers - self.indent = 0 - self.in_progress = None - self.in_progress_hanging = False - - def debug(self, msg, *args, **kw): - self.log(self.DEBUG, msg, *args, **kw) - - def info(self, msg, *args, **kw): - self.log(self.INFO, msg, *args, **kw) - - def notify(self, msg, *args, **kw): - self.log(self.NOTIFY, msg, *args, **kw) - - def warn(self, msg, *args, **kw): - self.log(self.WARN, msg, *args, **kw) - - def error(self, msg, *args, **kw): - self.log(self.ERROR, msg, *args, **kw) - - def fatal(self, msg, *args, **kw): - self.log(self.FATAL, msg, *args, **kw) - - def log(self, level, msg, *args, **kw): - if args: - if kw: - raise TypeError( - "You may give positional or keyword arguments, not both") - args = args or kw - rendered = None - for consumer_level, consumer in self.consumers: - if self.level_matches(level, consumer_level): - if (self.in_progress_hanging - and consumer in (sys.stdout, sys.stderr)): - self.in_progress_hanging = False - sys.stdout.write('\n') - sys.stdout.flush() - if rendered is None: - if args: - rendered = msg % args - else: - rendered = msg - rendered = ' '*self.indent + rendered - if hasattr(consumer, 'write'): - consumer.write(rendered+'\n') - else: - consumer(rendered) - - def start_progress(self, msg): - assert not self.in_progress, ( - "Tried to start_progress(%r) while in_progress %r" - % (msg, self.in_progress)) - if self.level_matches(self.NOTIFY, self._stdout_level()): - sys.stdout.write(msg) - sys.stdout.flush() - self.in_progress_hanging = True - else: - self.in_progress_hanging = False - self.in_progress = msg - - def end_progress(self, msg='done.'): - assert self.in_progress, ( - "Tried to end_progress without start_progress") - if self.stdout_level_matches(self.NOTIFY): - if not self.in_progress_hanging: - # Some message has been printed out since start_progress - sys.stdout.write('...' + self.in_progress + msg + '\n') - sys.stdout.flush() - else: - sys.stdout.write(msg + '\n') - sys.stdout.flush() - self.in_progress = None - self.in_progress_hanging = False - - def show_progress(self): - """If we are in a progress scope, and no log messages have been - shown, write out another '.'""" - if self.in_progress_hanging: - sys.stdout.write('.') - sys.stdout.flush() - - def stdout_level_matches(self, level): - """Returns true if a message at this level will go to stdout""" - return self.level_matches(level, self._stdout_level()) - - def _stdout_level(self): - """Returns the level that stdout runs at""" - for level, consumer in self.consumers: - if consumer is sys.stdout: - return level - return self.FATAL - - def level_matches(self, level, consumer_level): - """ - >>> l = Logger([]) - >>> l.level_matches(3, 4) - False - >>> l.level_matches(3, 2) - True - >>> l.level_matches(slice(None, 3), 3) - False - >>> l.level_matches(slice(None, 3), 2) - True - >>> l.level_matches(slice(1, 3), 1) - True - >>> l.level_matches(slice(2, 3), 1) - False - """ - if isinstance(level, slice): - start, stop = level.start, level.stop - if start is not None and start > consumer_level: - return False - if stop is not None and stop <= consumer_level: - return False - return True - else: - return level >= consumer_level - - @classmethod - def level_for_integer(cls, level): - levels = cls.LEVELS - if level < 0: - return levels[0] - if level >= len(levels): - return levels[-1] - return levels[level] - -# create a silent logger just to prevent this from being undefined -# will be overridden with requested verbosity main() is called. -logger = Logger([(Logger.LEVELS[-1], sys.stdout)]) - -def mkdir(path): - if not os.path.exists(path): - logger.info('Creating %s', path) - os.makedirs(path) - else: - logger.info('Directory %s already exists', path) - -def copyfileordir(src, dest, symlink=True): - if os.path.isdir(src): - shutil.copytree(src, dest, symlink) - else: - shutil.copy2(src, dest) - -def copyfile(src, dest, symlink=True): - if not os.path.exists(src): - # Some bad symlink in the src - logger.warn('Cannot find file %s (bad symlink)', src) - return - if os.path.exists(dest): - logger.debug('File %s already exists', dest) - return - if not os.path.exists(os.path.dirname(dest)): - logger.info('Creating parent directories for %s', os.path.dirname(dest)) - os.makedirs(os.path.dirname(dest)) - if not os.path.islink(src): - srcpath = os.path.abspath(src) - else: - srcpath = os.readlink(src) - if symlink and hasattr(os, 'symlink') and not is_win: - logger.info('Symlinking %s', dest) - try: - os.symlink(srcpath, dest) - except (OSError, NotImplementedError): - logger.info('Symlinking failed, copying to %s', dest) - copyfileordir(src, dest, symlink) - else: - logger.info('Copying to %s', dest) - copyfileordir(src, dest, symlink) - -def writefile(dest, content, overwrite=True): - if not os.path.exists(dest): - logger.info('Writing %s', dest) - with open(dest, 'wb') as f: - f.write(content.encode('utf-8')) - return - else: - with open(dest, 'rb') as f: - c = f.read() - if c != content.encode("utf-8"): - if not overwrite: - logger.notify('File %s exists with different content; not overwriting', dest) - return - logger.notify('Overwriting %s with new content', dest) - with open(dest, 'wb') as f: - f.write(content.encode('utf-8')) - else: - logger.info('Content %s already in place', dest) - -def rmtree(dir): - if os.path.exists(dir): - logger.notify('Deleting tree %s', dir) - shutil.rmtree(dir) - else: - logger.info('Do not need to delete %s; already gone', dir) - -def make_exe(fn): - if hasattr(os, 'chmod'): - oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777 - newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777 - os.chmod(fn, newmode) - logger.info('Changed mode of %s to %s', fn, oct(newmode)) - -def _find_file(filename, dirs): - for dir in reversed(dirs): - files = glob.glob(os.path.join(dir, filename)) - if files and os.path.isfile(files[0]): - return True, files[0] - return False, filename - -def file_search_dirs(): - here = os.path.dirname(os.path.abspath(__file__)) - dirs = [here, join(here, 'virtualenv_support')] - if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv': - # Probably some boot script; just in case virtualenv is installed... - try: - import virtualenv - except ImportError: - pass - else: - dirs.append(os.path.join( - os.path.dirname(virtualenv.__file__), 'virtualenv_support')) - return [d for d in dirs if os.path.isdir(d)] - - -class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter): - """ - Custom help formatter for use in ConfigOptionParser that updates - the defaults before expanding them, allowing them to show up correctly - in the help listing - """ - def expand_default(self, option): - if self.parser is not None: - self.parser.update_defaults(self.parser.defaults) - return optparse.IndentedHelpFormatter.expand_default(self, option) - - -class ConfigOptionParser(optparse.OptionParser): - """ - Custom option parser which updates its defaults by checking the - configuration files and environmental variables - """ - def __init__(self, *args, **kwargs): - self.config = ConfigParser.RawConfigParser() - self.files = self.get_config_files() - self.config.read(self.files) - optparse.OptionParser.__init__(self, *args, **kwargs) - - def get_config_files(self): - config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False) - if config_file and os.path.exists(config_file): - return [config_file] - return [default_config_file] - - def update_defaults(self, defaults): - """ - Updates the given defaults with values from the config files and - the environ. Does a little special handling for certain types of - options (lists). - """ - # Then go and look for the other sources of configuration: - config = {} - # 1. config files - config.update(dict(self.get_config_section('virtualenv'))) - # 2. environmental variables - config.update(dict(self.get_environ_vars())) - # Then set the options with those values - for key, val in config.items(): - key = key.replace('_', '-') - if not key.startswith('--'): - key = '--%s' % key # only prefer long opts - option = self.get_option(key) - if option is not None: - # ignore empty values - if not val: - continue - # handle multiline configs - if option.action == 'append': - val = val.split() - else: - option.nargs = 1 - if option.action == 'store_false': - val = not strtobool(val) - elif option.action in ('store_true', 'count'): - val = strtobool(val) - try: - val = option.convert_value(key, val) - except optparse.OptionValueError: - e = sys.exc_info()[1] - print("An error occurred during configuration: %s" % e) - sys.exit(3) - defaults[option.dest] = val - return defaults - - def get_config_section(self, name): - """ - Get a section of a configuration - """ - if self.config.has_section(name): - return self.config.items(name) - return [] - - def get_environ_vars(self, prefix='VIRTUALENV_'): - """ - Returns a generator with all environmental vars with prefix VIRTUALENV - """ - for key, val in os.environ.items(): - if key.startswith(prefix): - yield (key.replace(prefix, '').lower(), val) - - def get_default_values(self): - """ - Overridding to make updating the defaults after instantiation of - the option parser possible, update_defaults() does the dirty work. - """ - if not self.process_default_values: - # Old, pre-Optik 1.5 behaviour. - return optparse.Values(self.defaults) - - defaults = self.update_defaults(self.defaults.copy()) # ours - for option in self._get_all_options(): - default = defaults.get(option.dest) - if isinstance(default, basestring): - opt_str = option.get_opt_string() - defaults[option.dest] = option.check_value(opt_str, default) - return optparse.Values(defaults) - - -def main(): - parser = ConfigOptionParser( - version=virtualenv_version, - usage="%prog [OPTIONS] DEST_DIR", - formatter=UpdatingDefaultsHelpFormatter()) - - parser.add_option( - '-v', '--verbose', - action='count', - dest='verbose', - default=0, - help="Increase verbosity.") - - parser.add_option( - '-q', '--quiet', - action='count', - dest='quiet', - default=0, - help='Decrease verbosity.') - - parser.add_option( - '-p', '--python', - dest='python', - metavar='PYTHON_EXE', - help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 ' - 'interpreter to create the new environment. The default is the interpreter that ' - 'virtualenv was installed with (%s)' % sys.executable) - - parser.add_option( - '--clear', - dest='clear', - action='store_true', - help="Clear out the non-root install and start from scratch.") - - parser.set_defaults(system_site_packages=False) - parser.add_option( - '--no-site-packages', - dest='system_site_packages', - action='store_false', - help="DEPRECATED. Retained only for backward compatibility. " - "Not having access to global site-packages is now the default behavior.") - - parser.add_option( - '--system-site-packages', - dest='system_site_packages', - action='store_true', - help="Give the virtual environment access to the global site-packages.") - - parser.add_option( - '--always-copy', - dest='symlink', - action='store_false', - default=True, - help="Always copy files rather than symlinking.") - - parser.add_option( - '--unzip-setuptools', - dest='unzip_setuptools', - action='store_true', - help="Unzip Setuptools when installing it.") - - parser.add_option( - '--relocatable', - dest='relocatable', - action='store_true', - help='Make an EXISTING virtualenv environment relocatable. ' - 'This fixes up scripts and makes all .pth files relative.') - - parser.add_option( - '--no-setuptools', - dest='no_setuptools', - action='store_true', - help='Do not install setuptools in the new virtualenv.') - - parser.add_option( - '--no-pip', - dest='no_pip', - action='store_true', - help='Do not install pip in the new virtualenv.') - - parser.add_option( - '--no-wheel', - dest='no_wheel', - action='store_true', - help='Do not install wheel in the new virtualenv.') - - default_search_dirs = file_search_dirs() - parser.add_option( - '--extra-search-dir', - dest="search_dirs", - action="append", - metavar='DIR', - default=default_search_dirs, - help="Directory to look for setuptools/pip distributions in. " - "This option can be used multiple times.") - - parser.add_option( - "--download", - dest="download", - default=True, - action="store_true", - help="Download preinstalled packages from PyPI.", - ) - - parser.add_option( - "--no-download", - '--never-download', - dest="download", - action="store_false", - help="Do not download preinstalled packages from PyPI.", - ) - - parser.add_option( - '--prompt', - dest='prompt', - help='Provides an alternative prompt prefix for this environment.') - - parser.add_option( - '--setuptools', - dest='setuptools', - action='store_true', - help="DEPRECATED. Retained only for backward compatibility. This option has no effect.") - - parser.add_option( - '--distribute', - dest='distribute', - action='store_true', - help="DEPRECATED. Retained only for backward compatibility. This option has no effect.") - - if 'extend_parser' in globals(): - extend_parser(parser) - - options, args = parser.parse_args() - - global logger - - if 'adjust_options' in globals(): - adjust_options(options, args) - - verbosity = options.verbose - options.quiet - logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)]) - - if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): - env = os.environ.copy() - interpreter = resolve_interpreter(options.python) - if interpreter == sys.executable: - logger.warn('Already using interpreter %s' % interpreter) - else: - logger.notify('Running virtualenv with interpreter %s' % interpreter) - env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true' - file = __file__ - if file.endswith('.pyc'): - file = file[:-1] - popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env) - raise SystemExit(popen.wait()) - - if not args: - print('You must provide a DEST_DIR') - parser.print_help() - sys.exit(2) - if len(args) > 1: - print('There must be only one argument: DEST_DIR (you gave %s)' % ( - ' '.join(args))) - parser.print_help() - sys.exit(2) - - home_dir = args[0] - - if os.path.exists(home_dir) and os.path.isfile(home_dir): - logger.fatal('ERROR: File already exists and is not a directory.') - logger.fatal('Please provide a different path or delete the file.') - sys.exit(3) - - if os.environ.get('WORKING_ENV'): - logger.fatal('ERROR: you cannot run virtualenv while in a workingenv') - logger.fatal('Please deactivate your workingenv, then re-run this script') - sys.exit(3) - - if 'PYTHONHOME' in os.environ: - logger.warn('PYTHONHOME is set. You *must* activate the virtualenv before using it') - del os.environ['PYTHONHOME'] - - if options.relocatable: - make_environment_relocatable(home_dir) - return - - create_environment(home_dir, - site_packages=options.system_site_packages, - clear=options.clear, - unzip_setuptools=options.unzip_setuptools, - prompt=options.prompt, - search_dirs=options.search_dirs, - download=options.download, - no_setuptools=options.no_setuptools, - no_pip=options.no_pip, - no_wheel=options.no_wheel, - symlink=options.symlink) - if 'after_install' in globals(): - after_install(options, home_dir) - -def call_subprocess(cmd, show_stdout=True, - filter_stdout=None, cwd=None, - raise_on_returncode=True, extra_env=None, - remove_from_env=None, stdin=None): - cmd_parts = [] - for part in cmd: - if len(part) > 45: - part = part[:20]+"..."+part[-20:] - if ' ' in part or '\n' in part or '"' in part or "'" in part: - part = '"%s"' % part.replace('"', '\\"') - if hasattr(part, 'decode'): - try: - part = part.decode(sys.getdefaultencoding()) - except UnicodeDecodeError: - part = part.decode(sys.getfilesystemencoding()) - cmd_parts.append(part) - cmd_desc = ' '.join(cmd_parts) - if show_stdout: - stdout = None - else: - stdout = subprocess.PIPE - logger.debug("Running command %s" % cmd_desc) - if extra_env or remove_from_env: - env = os.environ.copy() - if extra_env: - env.update(extra_env) - if remove_from_env: - for varname in remove_from_env: - env.pop(varname, None) - else: - env = None - try: - proc = subprocess.Popen( - cmd, stderr=subprocess.STDOUT, - stdin=None if stdin is None else subprocess.PIPE, - stdout=stdout, - cwd=cwd, env=env) - except Exception: - e = sys.exc_info()[1] - logger.fatal( - "Error %s while executing command %s" % (e, cmd_desc)) - raise - all_output = [] - if stdout is not None: - if stdin is not None: - proc.stdin.write(stdin) - proc.stdin.close() - - stdout = proc.stdout - encoding = sys.getdefaultencoding() - fs_encoding = sys.getfilesystemencoding() - while 1: - line = stdout.readline() - try: - line = line.decode(encoding) - except UnicodeDecodeError: - line = line.decode(fs_encoding) - if not line: - break - line = line.rstrip() - all_output.append(line) - if filter_stdout: - level = filter_stdout(line) - if isinstance(level, tuple): - level, line = level - logger.log(level, line) - if not logger.stdout_level_matches(level): - logger.show_progress() - else: - logger.info(line) - else: - proc.communicate(stdin) - proc.wait() - if proc.returncode: - if raise_on_returncode: - if all_output: - logger.notify('Complete output from command %s:' % cmd_desc) - logger.notify('\n'.join(all_output) + '\n----------------------------------------') - raise OSError( - "Command %s failed with error code %s" - % (cmd_desc, proc.returncode)) - else: - logger.warn( - "Command %s had error code %s" - % (cmd_desc, proc.returncode)) - -def filter_install_output(line): - if line.strip().startswith('running'): - return Logger.INFO - return Logger.DEBUG - -def find_wheels(projects, search_dirs): - """Find wheels from which we can import PROJECTS. - - Scan through SEARCH_DIRS for a wheel for each PROJECT in turn. Return - a list of the first wheel found for each PROJECT - """ - - wheels = [] - - # Look through SEARCH_DIRS for the first suitable wheel. Don't bother - # about version checking here, as this is simply to get something we can - # then use to install the correct version. - for project in projects: - for dirname in search_dirs: - # This relies on only having "universal" wheels available. - # The pattern could be tightened to require -py2.py3-none-any.whl. - files = glob.glob(os.path.join(dirname, project + '-*.whl')) - if files: - wheels.append(os.path.abspath(files[0])) - break - else: - # We're out of luck, so quit with a suitable error - logger.fatal('Cannot find a wheel for %s' % (project,)) - - return wheels - -def install_wheel(project_names, py_executable, search_dirs=None, - download=False): - if search_dirs is None: - search_dirs = file_search_dirs() - - wheels = find_wheels(['setuptools', 'pip'], search_dirs) - pythonpath = os.pathsep.join(wheels) - - # PIP_FIND_LINKS uses space as the path separator and thus cannot have paths - # with spaces in them. Convert any of those to local file:// URL form. - try: - from urlparse import urljoin - from urllib import pathname2url - except ImportError: - from urllib.parse import urljoin - from urllib.request import pathname2url - def space_path2url(p): - if ' ' not in p: - return p - return urljoin('file:', pathname2url(os.path.abspath(p))) - findlinks = ' '.join(space_path2url(d) for d in search_dirs) - - SCRIPT = textwrap.dedent(""" - import sys - import pkgutil - import tempfile - import os - - import pip - - cert_data = pkgutil.get_data("pip._vendor.requests", "cacert.pem") - if cert_data is not None: - cert_file = tempfile.NamedTemporaryFile(delete=False) - cert_file.write(cert_data) - cert_file.close() - else: - cert_file = None - - try: - args = ["install", "--ignore-installed"] - if cert_file is not None: - args += ["--cert", cert_file.name] - args += sys.argv[1:] - - sys.exit(pip.main(args)) - finally: - if cert_file is not None: - os.remove(cert_file.name) - """).encode("utf8") - - cmd = [py_executable, '-'] + project_names - logger.start_progress('Installing %s...' % (', '.join(project_names))) - logger.indent += 2 - - env = { - "PYTHONPATH": pythonpath, - "JYTHONPATH": pythonpath, # for Jython < 3.x - "PIP_FIND_LINKS": findlinks, - "PIP_USE_WHEEL": "1", - "PIP_ONLY_BINARY": ":all:", - "PIP_USER": "0", - } - - if not download: - env["PIP_NO_INDEX"] = "1" - - try: - call_subprocess(cmd, show_stdout=False, extra_env=env, stdin=SCRIPT) - finally: - logger.indent -= 2 - logger.end_progress() - - -def create_environment(home_dir, site_packages=False, clear=False, - unzip_setuptools=False, - prompt=None, search_dirs=None, download=False, - no_setuptools=False, no_pip=False, no_wheel=False, - symlink=True): - """ - Creates a new environment in ``home_dir``. - - If ``site_packages`` is true, then the global ``site-packages/`` - directory will be on the path. - - If ``clear`` is true (default False) then the environment will - first be cleared. - """ - home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) - - py_executable = os.path.abspath(install_python( - home_dir, lib_dir, inc_dir, bin_dir, - site_packages=site_packages, clear=clear, symlink=symlink)) - - install_distutils(home_dir) - - to_install = [] - - if not no_setuptools: - to_install.append('setuptools') - - if not no_pip: - to_install.append('pip') - - if not no_wheel: - to_install.append('wheel') - - if to_install: - install_wheel( - to_install, - py_executable, - search_dirs, - download=download, - ) - - install_activate(home_dir, bin_dir, prompt) - - install_python_config(home_dir, bin_dir, prompt) - -def is_executable_file(fpath): - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - -def path_locations(home_dir): - """Return the path locations for the environment (where libraries are, - where scripts go, etc)""" - home_dir = os.path.abspath(home_dir) - # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its - # prefix arg is broken: http://bugs.python.org/issue3386 - if is_win: - # Windows has lots of problems with executables with spaces in - # the name; this function will remove them (using the ~1 - # format): - mkdir(home_dir) - if ' ' in home_dir: - import ctypes - GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW - size = max(len(home_dir)+1, 256) - buf = ctypes.create_unicode_buffer(size) - try: - u = unicode - except NameError: - u = str - ret = GetShortPathName(u(home_dir), buf, size) - if not ret: - print('Error: the path "%s" has a space in it' % home_dir) - print('We could not determine the short pathname for it.') - print('Exiting.') - sys.exit(3) - home_dir = str(buf.value) - lib_dir = join(home_dir, 'Lib') - inc_dir = join(home_dir, 'Include') - bin_dir = join(home_dir, 'Scripts') - if is_jython: - lib_dir = join(home_dir, 'Lib') - inc_dir = join(home_dir, 'Include') - bin_dir = join(home_dir, 'bin') - elif is_pypy: - lib_dir = home_dir - inc_dir = join(home_dir, 'include') - bin_dir = join(home_dir, 'bin') - elif not is_win: - lib_dir = join(home_dir, 'lib', py_version) - inc_dir = join(home_dir, 'include', py_version + abiflags) - bin_dir = join(home_dir, 'bin') - return home_dir, lib_dir, inc_dir, bin_dir - - -def change_prefix(filename, dst_prefix): - prefixes = [sys.prefix] - - if is_darwin: - prefixes.extend(( - os.path.join("/Library/Python", sys.version[:3], "site-packages"), - os.path.join(sys.prefix, "Extras", "lib", "python"), - os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"), - # Python 2.6 no-frameworks - os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"), - # System Python 2.7 on OSX Mountain Lion - os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages"))) - - if hasattr(sys, 'real_prefix'): - prefixes.append(sys.real_prefix) - if hasattr(sys, 'base_prefix'): - prefixes.append(sys.base_prefix) - prefixes = list(map(os.path.expanduser, prefixes)) - prefixes = list(map(os.path.abspath, prefixes)) - # Check longer prefixes first so we don't split in the middle of a filename - prefixes = sorted(prefixes, key=len, reverse=True) - filename = os.path.abspath(filename) - # On Windows, make sure drive letter is uppercase - if is_win and filename[0] in 'abcdefghijklmnopqrstuvwxyz': - filename = filename[0].upper() + filename[1:] - for i, prefix in enumerate(prefixes): - if is_win and prefix[0] in 'abcdefghijklmnopqrstuvwxyz': - prefixes[i] = prefix[0].upper() + prefix[1:] - for src_prefix in prefixes: - if filename.startswith(src_prefix): - _, relpath = filename.split(src_prefix, 1) - if src_prefix != os.sep: # sys.prefix == "/" - assert relpath[0] == os.sep - relpath = relpath[1:] - return join(dst_prefix, relpath) - assert False, "Filename %s does not start with any of these prefixes: %s" % \ - (filename, prefixes) - -def copy_required_modules(dst_prefix, symlink): - import imp - - for modname in REQUIRED_MODULES: - if modname in sys.builtin_module_names: - logger.info("Ignoring built-in bootstrap module: %s" % modname) - continue - try: - f, filename, _ = imp.find_module(modname) - except ImportError: - logger.info("Cannot import bootstrap module: %s" % modname) - else: - if f is not None: - f.close() - # special-case custom readline.so on OS X, but not for pypy: - if modname == 'readline' and sys.platform == 'darwin' and not ( - is_pypy or filename.endswith(join('lib-dynload', 'readline.so'))): - dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so') - elif modname == 'readline' and sys.platform == 'win32': - # special-case for Windows, where readline is not a - # standard module, though it may have been installed in - # site-packages by a third-party package - pass - else: - dst_filename = change_prefix(filename, dst_prefix) - copyfile(filename, dst_filename, symlink) - if filename.endswith('.pyc'): - pyfile = filename[:-1] - if os.path.exists(pyfile): - copyfile(pyfile, dst_filename[:-1], symlink) - -def copy_tcltk(src, dest, symlink): - """ copy tcl/tk libraries on Windows (issue #93) """ - for libversion in '8.5', '8.6': - for libname in 'tcl', 'tk': - srcdir = join(src, 'tcl', libname + libversion) - destdir = join(dest, 'tcl', libname + libversion) - # Only copy the dirs from the above combinations that exist - if os.path.exists(srcdir) and not os.path.exists(destdir): - copyfileordir(srcdir, destdir, symlink) - - -def subst_path(prefix_path, prefix, home_dir): - prefix_path = os.path.normpath(prefix_path) - prefix = os.path.normpath(prefix) - home_dir = os.path.normpath(home_dir) - if not prefix_path.startswith(prefix): - logger.warn('Path not in prefix %r %r', prefix_path, prefix) - return - return prefix_path.replace(prefix, home_dir, 1) - - -def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, symlink=True): - """Install just the base environment, no distutils patches etc""" - if sys.executable.startswith(bin_dir): - print('Please use the *system* python to run this script') - return - - if clear: - rmtree(lib_dir) - ## FIXME: why not delete it? - ## Maybe it should delete everything with #!/path/to/venv/python in it - logger.notify('Not deleting %s', bin_dir) - - if hasattr(sys, 'real_prefix'): - logger.notify('Using real prefix %r' % sys.real_prefix) - prefix = sys.real_prefix - elif hasattr(sys, 'base_prefix'): - logger.notify('Using base prefix %r' % sys.base_prefix) - prefix = sys.base_prefix - else: - prefix = sys.prefix - mkdir(lib_dir) - fix_lib64(lib_dir, symlink) - stdlib_dirs = [os.path.dirname(os.__file__)] - if is_win: - stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs')) - elif is_darwin: - stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages')) - if hasattr(os, 'symlink'): - logger.info('Symlinking Python bootstrap modules') - else: - logger.info('Copying Python bootstrap modules') - logger.indent += 2 - try: - # copy required files... - for stdlib_dir in stdlib_dirs: - if not os.path.isdir(stdlib_dir): - continue - for fn in os.listdir(stdlib_dir): - bn = os.path.splitext(fn)[0] - if fn != 'site-packages' and bn in REQUIRED_FILES: - copyfile(join(stdlib_dir, fn), join(lib_dir, fn), symlink) - # ...and modules - copy_required_modules(home_dir, symlink) - finally: - logger.indent -= 2 - # ...copy tcl/tk - if is_win: - copy_tcltk(prefix, home_dir, symlink) - mkdir(join(lib_dir, 'site-packages')) - import site - site_filename = site.__file__ - if site_filename.endswith('.pyc') or site_filename.endswith('.pyo'): - site_filename = site_filename[:-1] - elif site_filename.endswith('$py.class'): - site_filename = site_filename.replace('$py.class', '.py') - site_filename_dst = change_prefix(site_filename, home_dir) - site_dir = os.path.dirname(site_filename_dst) - writefile(site_filename_dst, SITE_PY) - writefile(join(site_dir, 'orig-prefix.txt'), prefix) - site_packages_filename = join(site_dir, 'no-global-site-packages.txt') - if not site_packages: - writefile(site_packages_filename, '') - - if is_pypy or is_win: - stdinc_dir = join(prefix, 'include') - else: - stdinc_dir = join(prefix, 'include', py_version + abiflags) - if os.path.exists(stdinc_dir): - copyfile(stdinc_dir, inc_dir, symlink) - else: - logger.debug('No include dir %s' % stdinc_dir) - - platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1) - if platinc_dir != stdinc_dir: - platinc_dest = distutils.sysconfig.get_python_inc( - plat_specific=1, prefix=home_dir) - if platinc_dir == platinc_dest: - # Do platinc_dest manually due to a CPython bug; - # not http://bugs.python.org/issue3386 but a close cousin - platinc_dest = subst_path(platinc_dir, prefix, home_dir) - if platinc_dest: - # PyPy's stdinc_dir and prefix are relative to the original binary - # (traversing virtualenvs), whereas the platinc_dir is relative to - # the inner virtualenv and ignores the prefix argument. - # This seems more evolved than designed. - copyfile(platinc_dir, platinc_dest, symlink) - - # pypy never uses exec_prefix, just ignore it - if sys.exec_prefix != prefix and not is_pypy: - if is_win: - exec_dir = join(sys.exec_prefix, 'lib') - elif is_jython: - exec_dir = join(sys.exec_prefix, 'Lib') - else: - exec_dir = join(sys.exec_prefix, 'lib', py_version) - for fn in os.listdir(exec_dir): - copyfile(join(exec_dir, fn), join(lib_dir, fn), symlink) - - if is_jython: - # Jython has either jython-dev.jar and javalib/ dir, or just - # jython.jar - for name in 'jython-dev.jar', 'javalib', 'jython.jar': - src = join(prefix, name) - if os.path.exists(src): - copyfile(src, join(home_dir, name), symlink) - # XXX: registry should always exist after Jython 2.5rc1 - src = join(prefix, 'registry') - if os.path.exists(src): - copyfile(src, join(home_dir, 'registry'), symlink=False) - copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'), - symlink=False) - - mkdir(bin_dir) - py_executable = join(bin_dir, os.path.basename(sys.executable)) - if 'Python.framework' in prefix: - # OS X framework builds cause validation to break - # https://github.com/pypa/virtualenv/issues/322 - if os.environ.get('__PYVENV_LAUNCHER__'): - del os.environ["__PYVENV_LAUNCHER__"] - if re.search(r'/Python(?:-32|-64)*$', py_executable): - # The name of the python executable is not quite what - # we want, rename it. - py_executable = os.path.join( - os.path.dirname(py_executable), 'python') - - logger.notify('New %s executable in %s', expected_exe, py_executable) - pcbuild_dir = os.path.dirname(sys.executable) - pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth') - if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')): - logger.notify('Detected python running from build directory %s', pcbuild_dir) - logger.notify('Writing .pth file linking to build directory for *.pyd files') - writefile(pyd_pth, pcbuild_dir) - else: - pcbuild_dir = None - if os.path.exists(pyd_pth): - logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth) - os.unlink(pyd_pth) - - if sys.executable != py_executable: - ## FIXME: could I just hard link? - executable = sys.executable - shutil.copyfile(executable, py_executable) - make_exe(py_executable) - if is_win or is_cygwin: - pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe') - if os.path.exists(pythonw): - logger.info('Also created pythonw.exe') - shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe')) - python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe') - python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe') - if os.path.exists(python_d): - logger.info('Also created python_d.exe') - shutil.copyfile(python_d, python_d_dest) - elif os.path.exists(python_d_dest): - logger.info('Removed python_d.exe as it is no longer at the source') - os.unlink(python_d_dest) - # we need to copy the DLL to enforce that windows will load the correct one. - # may not exist if we are cygwin. - py_executable_dll = 'python%s%s.dll' % ( - sys.version_info[0], sys.version_info[1]) - py_executable_dll_d = 'python%s%s_d.dll' % ( - sys.version_info[0], sys.version_info[1]) - pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll) - pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d) - pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d) - if os.path.exists(pythondll): - logger.info('Also created %s' % py_executable_dll) - shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll)) - if os.path.exists(pythondll_d): - logger.info('Also created %s' % py_executable_dll_d) - shutil.copyfile(pythondll_d, pythondll_d_dest) - elif os.path.exists(pythondll_d_dest): - logger.info('Removed %s as the source does not exist' % pythondll_d_dest) - os.unlink(pythondll_d_dest) - if is_pypy: - # make a symlink python --> pypy-c - python_executable = os.path.join(os.path.dirname(py_executable), 'python') - if sys.platform in ('win32', 'cygwin'): - python_executable += '.exe' - logger.info('Also created executable %s' % python_executable) - copyfile(py_executable, python_executable, symlink) - - if is_win: - for name in ['libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', - 'libeay32.dll', 'ssleay32.dll', 'sqlite3.dll', - 'tcl85.dll', 'tk85.dll']: - src = join(prefix, name) - if os.path.exists(src): - copyfile(src, join(bin_dir, name), symlink) - - for d in sys.path: - if d.endswith('lib_pypy'): - break - else: - logger.fatal('Could not find lib_pypy in sys.path') - raise SystemExit(3) - logger.info('Copying lib_pypy') - copyfile(d, os.path.join(home_dir, 'lib_pypy'), symlink) - - if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe: - secondary_exe = os.path.join(os.path.dirname(py_executable), - expected_exe) - py_executable_ext = os.path.splitext(py_executable)[1] - if py_executable_ext.lower() == '.exe': - # python2.4 gives an extension of '.4' :P - secondary_exe += py_executable_ext - if os.path.exists(secondary_exe): - logger.warn('Not overwriting existing %s script %s (you must use %s)' - % (expected_exe, secondary_exe, py_executable)) - else: - logger.notify('Also creating executable in %s' % secondary_exe) - shutil.copyfile(sys.executable, secondary_exe) - make_exe(secondary_exe) - - if '.framework' in prefix: - if 'Python.framework' in prefix: - logger.debug('MacOSX Python framework detected') - # Make sure we use the embedded interpreter inside - # the framework, even if sys.executable points to - # the stub executable in ${sys.prefix}/bin - # See http://groups.google.com/group/python-virtualenv/ - # browse_thread/thread/17cab2f85da75951 - original_python = os.path.join( - prefix, 'Resources/Python.app/Contents/MacOS/Python') - if 'EPD' in prefix: - logger.debug('EPD framework detected') - original_python = os.path.join(prefix, 'bin/python') - shutil.copy(original_python, py_executable) - - # Copy the framework's dylib into the virtual - # environment - virtual_lib = os.path.join(home_dir, '.Python') - - if os.path.exists(virtual_lib): - os.unlink(virtual_lib) - copyfile( - os.path.join(prefix, 'Python'), - virtual_lib, - symlink) - - # And then change the install_name of the copied python executable - try: - mach_o_change(py_executable, - os.path.join(prefix, 'Python'), - '@executable_path/../.Python') - except: - e = sys.exc_info()[1] - logger.warn("Could not call mach_o_change: %s. " - "Trying to call install_name_tool instead." % e) - try: - call_subprocess( - ["install_name_tool", "-change", - os.path.join(prefix, 'Python'), - '@executable_path/../.Python', - py_executable]) - except: - logger.fatal("Could not call install_name_tool -- you must " - "have Apple's development tools installed") - raise - - if not is_win: - # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist - py_exe_version_major = 'python%s' % sys.version_info[0] - py_exe_version_major_minor = 'python%s.%s' % ( - sys.version_info[0], sys.version_info[1]) - py_exe_no_version = 'python' - required_symlinks = [ py_exe_no_version, py_exe_version_major, - py_exe_version_major_minor ] - - py_executable_base = os.path.basename(py_executable) - - if py_executable_base in required_symlinks: - # Don't try to symlink to yourself. - required_symlinks.remove(py_executable_base) - - for pth in required_symlinks: - full_pth = join(bin_dir, pth) - if os.path.exists(full_pth): - os.unlink(full_pth) - if symlink: - os.symlink(py_executable_base, full_pth) - else: - copyfile(py_executable, full_pth, symlink) - - cmd = [py_executable, '-c', 'import sys;out=sys.stdout;' - 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))'] - logger.info('Testing executable with %s %s "%s"' % tuple(cmd)) - try: - proc = subprocess.Popen(cmd, - stdout=subprocess.PIPE) - proc_stdout, proc_stderr = proc.communicate() - except OSError: - e = sys.exc_info()[1] - if e.errno == errno.EACCES: - logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e)) - sys.exit(100) - else: - raise e - - proc_stdout = proc_stdout.strip().decode("utf-8") - proc_stdout = os.path.normcase(os.path.abspath(proc_stdout)) - norm_home_dir = os.path.normcase(os.path.abspath(home_dir)) - if hasattr(norm_home_dir, 'decode'): - norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding()) - if proc_stdout != norm_home_dir: - logger.fatal( - 'ERROR: The executable %s is not functioning' % py_executable) - logger.fatal( - 'ERROR: It thinks sys.prefix is %r (should be %r)' - % (proc_stdout, norm_home_dir)) - logger.fatal( - 'ERROR: virtualenv is not compatible with this system or executable') - if is_win: - logger.fatal( - 'Note: some Windows users have reported this error when they ' - 'installed Python for "Only this user" or have multiple ' - 'versions of Python installed. Copying the appropriate ' - 'PythonXX.dll to the virtualenv Scripts/ directory may fix ' - 'this problem.') - sys.exit(100) - else: - logger.info('Got sys.prefix result: %r' % proc_stdout) - - pydistutils = os.path.expanduser('~/.pydistutils.cfg') - if os.path.exists(pydistutils): - logger.notify('Please make sure you remove any previous custom paths from ' - 'your %s file.' % pydistutils) - ## FIXME: really this should be calculated earlier - - fix_local_scheme(home_dir, symlink) - - if site_packages: - if os.path.exists(site_packages_filename): - logger.info('Deleting %s' % site_packages_filename) - os.unlink(site_packages_filename) - - return py_executable - - -def install_activate(home_dir, bin_dir, prompt=None): - if is_win or is_jython and os._name == 'nt': - files = { - 'activate.bat': ACTIVATE_BAT, - 'deactivate.bat': DEACTIVATE_BAT, - 'activate.ps1': ACTIVATE_PS, - } - - # MSYS needs paths of the form /c/path/to/file - drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/')) - home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail) - - # Run-time conditional enables (basic) Cygwin compatibility - home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" % - (home_dir, home_dir_msys)) - files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh) - - else: - files = {'activate': ACTIVATE_SH} - - # suppling activate.fish in addition to, not instead of, the - # bash script support. - files['activate.fish'] = ACTIVATE_FISH - - # same for csh/tcsh support... - files['activate.csh'] = ACTIVATE_CSH - - files['activate_this.py'] = ACTIVATE_THIS - - install_files(home_dir, bin_dir, prompt, files) - -def install_files(home_dir, bin_dir, prompt, files): - if hasattr(home_dir, 'decode'): - home_dir = home_dir.decode(sys.getfilesystemencoding()) - vname = os.path.basename(home_dir) - for name, content in files.items(): - content = content.replace('__VIRTUAL_PROMPT__', prompt or '') - content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname) - content = content.replace('__VIRTUAL_ENV__', home_dir) - content = content.replace('__VIRTUAL_NAME__', vname) - content = content.replace('__BIN_NAME__', os.path.basename(bin_dir)) - writefile(os.path.join(bin_dir, name), content) - -def install_python_config(home_dir, bin_dir, prompt=None): - if sys.platform == 'win32' or is_jython and os._name == 'nt': - files = {} - else: - files = {'python-config': PYTHON_CONFIG} - install_files(home_dir, bin_dir, prompt, files) - for name, content in files.items(): - make_exe(os.path.join(bin_dir, name)) - -def install_distutils(home_dir): - distutils_path = change_prefix(distutils.__path__[0], home_dir) - mkdir(distutils_path) - ## FIXME: maybe this prefix setting should only be put in place if - ## there's a local distutils.cfg with a prefix setting? - home_dir = os.path.abspath(home_dir) - ## FIXME: this is breaking things, removing for now: - #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir - writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT) - writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False) - -def fix_local_scheme(home_dir, symlink=True): - """ - Platforms that use the "posix_local" install scheme (like Ubuntu with - Python 2.7) need to be given an additional "local" location, sigh. - """ - try: - import sysconfig - except ImportError: - pass - else: - if sysconfig._get_default_scheme() == 'posix_local': - local_path = os.path.join(home_dir, 'local') - if not os.path.exists(local_path): - os.mkdir(local_path) - for subdir_name in os.listdir(home_dir): - if subdir_name == 'local': - continue - copyfile(os.path.abspath(os.path.join(home_dir, subdir_name)), \ - os.path.join(local_path, subdir_name), symlink) - -def fix_lib64(lib_dir, symlink=True): - """ - Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y - instead of lib/pythonX.Y. If this is such a platform we'll just create a - symlink so lib64 points to lib - """ - # PyPy's library path scheme is not affected by this. - # Return early or we will die on the following assert. - if is_pypy: - logger.debug('PyPy detected, skipping lib64 symlinking') - return - # Check we have a lib64 library path - if not [p for p in distutils.sysconfig.get_config_vars().values() - if isinstance(p, basestring) and 'lib64' in p]: - return - - logger.debug('This system uses lib64; symlinking lib64 to lib') - - assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], ( - "Unexpected python lib dir: %r" % lib_dir) - lib_parent = os.path.dirname(lib_dir) - top_level = os.path.dirname(lib_parent) - lib_dir = os.path.join(top_level, 'lib') - lib64_link = os.path.join(top_level, 'lib64') - assert os.path.basename(lib_parent) == 'lib', ( - "Unexpected parent dir: %r" % lib_parent) - if os.path.lexists(lib64_link): - return - if symlink: - os.symlink('lib', lib64_link) - else: - copyfile('lib', lib64_link) - -def resolve_interpreter(exe): - """ - If the executable given isn't an absolute path, search $PATH for the interpreter - """ - # If the "executable" is a version number, get the installed executable for - # that version - orig_exe = exe - python_versions = get_installed_pythons() - if exe in python_versions: - exe = python_versions[exe] - - if os.path.abspath(exe) != exe: - paths = os.environ.get('PATH', '').split(os.pathsep) - for path in paths: - if os.path.exists(join(path, exe)): - exe = join(path, exe) - break - if not os.path.exists(exe): - logger.fatal('The path %s (from --python=%s) does not exist' % (exe, orig_exe)) - raise SystemExit(3) - if not is_executable(exe): - logger.fatal('The path %s (from --python=%s) is not an executable file' % (exe, orig_exe)) - raise SystemExit(3) - return exe - -def is_executable(exe): - """Checks a file is executable""" - return os.path.isfile(exe) and os.access(exe, os.X_OK) - -############################################################ -## Relocating the environment: - -def make_environment_relocatable(home_dir): - """ - Makes the already-existing environment use relative paths, and takes out - the #!-based environment selection in scripts. - """ - home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) - activate_this = os.path.join(bin_dir, 'activate_this.py') - if not os.path.exists(activate_this): - logger.fatal( - 'The environment doesn\'t have a file %s -- please re-run virtualenv ' - 'on this environment to update it' % activate_this) - fixup_scripts(home_dir, bin_dir) - fixup_pth_and_egg_link(home_dir) - ## FIXME: need to fix up distutils.cfg - -OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3], - 'activate', 'activate.bat', 'activate_this.py', - 'activate.fish', 'activate.csh'] - -def fixup_scripts(home_dir, bin_dir): - if is_win: - new_shebang_args = ( - '%s /c' % os.path.normcase(os.environ.get('COMSPEC', 'cmd.exe')), - '', '.exe') - else: - new_shebang_args = ('/usr/bin/env', sys.version[:3], '') - - # This is what we expect at the top of scripts: - shebang = '#!%s' % os.path.normcase(os.path.join( - os.path.abspath(bin_dir), 'python%s' % new_shebang_args[2])) - # This is what we'll put: - new_shebang = '#!%s python%s%s' % new_shebang_args - - for filename in os.listdir(bin_dir): - filename = os.path.join(bin_dir, filename) - if not os.path.isfile(filename): - # ignore subdirs, e.g. .svn ones. - continue - lines = None - with open(filename, 'rb') as f: - try: - lines = f.read().decode('utf-8').splitlines() - except UnicodeDecodeError: - # This is probably a binary program instead - # of a script, so just ignore it. - continue - if not lines: - logger.warn('Script %s is an empty file' % filename) - continue - - old_shebang = lines[0].strip() - old_shebang = old_shebang[0:2] + os.path.normcase(old_shebang[2:]) - - if not old_shebang.startswith(shebang): - if os.path.basename(filename) in OK_ABS_SCRIPTS: - logger.debug('Cannot make script %s relative' % filename) - elif lines[0].strip() == new_shebang: - logger.info('Script %s has already been made relative' % filename) - else: - logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)' - % (filename, shebang)) - continue - logger.notify('Making script %s relative' % filename) - script = relative_script([new_shebang] + lines[1:]) - with open(filename, 'wb') as f: - f.write('\n'.join(script).encode('utf-8')) - - -def relative_script(lines): - "Return a script that'll work in a relocatable environment." - activate = "import os; activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); exec(compile(open(activate_this).read(), activate_this, 'exec'), dict(__file__=activate_this)); del os, activate_this" - # Find the last future statement in the script. If we insert the activation - # line before a future statement, Python will raise a SyntaxError. - activate_at = None - for idx, line in reversed(list(enumerate(lines))): - if line.split()[:3] == ['from', '__future__', 'import']: - activate_at = idx + 1 - break - if activate_at is None: - # Activate after the shebang. - activate_at = 1 - return lines[:activate_at] + ['', activate, ''] + lines[activate_at:] - -def fixup_pth_and_egg_link(home_dir, sys_path=None): - """Makes .pth and .egg-link files use relative paths""" - home_dir = os.path.normcase(os.path.abspath(home_dir)) - if sys_path is None: - sys_path = sys.path - for path in sys_path: - if not path: - path = '.' - if not os.path.isdir(path): - continue - path = os.path.normcase(os.path.abspath(path)) - if not path.startswith(home_dir): - logger.debug('Skipping system (non-environment) directory %s' % path) - continue - for filename in os.listdir(path): - filename = os.path.join(path, filename) - if filename.endswith('.pth'): - if not os.access(filename, os.W_OK): - logger.warn('Cannot write .pth file %s, skipping' % filename) - else: - fixup_pth_file(filename) - if filename.endswith('.egg-link'): - if not os.access(filename, os.W_OK): - logger.warn('Cannot write .egg-link file %s, skipping' % filename) - else: - fixup_egg_link(filename) - -def fixup_pth_file(filename): - lines = [] - prev_lines = [] - with open(filename) as f: - prev_lines = f.readlines() - for line in prev_lines: - line = line.strip() - if (not line or line.startswith('#') or line.startswith('import ') - or os.path.abspath(line) != line): - lines.append(line) - else: - new_value = make_relative_path(filename, line) - if line != new_value: - logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename)) - lines.append(new_value) - if lines == prev_lines: - logger.info('No changes to .pth file %s' % filename) - return - logger.notify('Making paths in .pth file %s relative' % filename) - with open(filename, 'w') as f: - f.write('\n'.join(lines) + '\n') - -def fixup_egg_link(filename): - with open(filename) as f: - link = f.readline().strip() - if os.path.abspath(link) != link: - logger.debug('Link in %s already relative' % filename) - return - new_link = make_relative_path(filename, link) - logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link)) - with open(filename, 'w') as f: - f.write(new_link) - -def make_relative_path(source, dest, dest_is_directory=True): - """ - Make a filename relative, where the filename is dest, and it is - being referred to from the filename source. - - >>> make_relative_path('/usr/share/something/a-file.pth', - ... '/usr/share/another-place/src/Directory') - '../another-place/src/Directory' - >>> make_relative_path('/usr/share/something/a-file.pth', - ... '/home/user/src/Directory') - '../../../home/user/src/Directory' - >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/') - './' - """ - source = os.path.dirname(source) - if not dest_is_directory: - dest_filename = os.path.basename(dest) - dest = os.path.dirname(dest) - dest = os.path.normpath(os.path.abspath(dest)) - source = os.path.normpath(os.path.abspath(source)) - dest_parts = dest.strip(os.path.sep).split(os.path.sep) - source_parts = source.strip(os.path.sep).split(os.path.sep) - while dest_parts and source_parts and dest_parts[0] == source_parts[0]: - dest_parts.pop(0) - source_parts.pop(0) - full_parts = ['..']*len(source_parts) + dest_parts - if not dest_is_directory: - full_parts.append(dest_filename) - if not full_parts: - # Special case for the current directory (otherwise it'd be '') - return './' - return os.path.sep.join(full_parts) - - - -############################################################ -## Bootstrap script creation: - -def create_bootstrap_script(extra_text, python_version=''): - """ - Creates a bootstrap script, which is like this script but with - extend_parser, adjust_options, and after_install hooks. - - This returns a string that (written to disk of course) can be used - as a bootstrap script with your own customizations. The script - will be the standard virtualenv.py script, with your extra text - added (your extra text should be Python code). - - If you include these functions, they will be called: - - ``extend_parser(optparse_parser)``: - You can add or remove options from the parser here. - - ``adjust_options(options, args)``: - You can change options here, or change the args (if you accept - different kinds of arguments, be sure you modify ``args`` so it is - only ``[DEST_DIR]``). - - ``after_install(options, home_dir)``: - - After everything is installed, this function is called. This - is probably the function you are most likely to use. An - example would be:: - - def after_install(options, home_dir): - subprocess.call([join(home_dir, 'bin', 'easy_install'), - 'MyPackage']) - subprocess.call([join(home_dir, 'bin', 'my-package-script'), - 'setup', home_dir]) - - This example immediately installs a package, and runs a setup - script from that package. - - If you provide something like ``python_version='2.5'`` then the - script will start with ``#!/usr/bin/env python2.5`` instead of - ``#!/usr/bin/env python``. You can use this when the script must - be run with a particular Python version. - """ - filename = __file__ - if filename.endswith('.pyc'): - filename = filename[:-1] - with codecs.open(filename, 'r', encoding='utf-8') as f: - content = f.read() - py_exe = 'python%s' % python_version - content = (('#!/usr/bin/env %s\n' % py_exe) - + '## WARNING: This file is generated\n' - + content) - return content.replace('##EXT' 'END##', extra_text) - -##EXTEND## - -def convert(s): - b = base64.b64decode(s.encode('ascii')) - return zlib.decompress(b).decode('utf-8') - -##file site.py -SITE_PY = convert(""" -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 -AVijEPwfucjncQ== -""") - -##file activate.sh -ACTIVATE_SH = convert(""" -eJytVd9v2kAMfs9fYQLq2m4MscdNVKMqEkgtVIQxbeuUHolpTgsXdHehpT/+9/mSEBJS2MOaB0ji -z77P9menDpOAK5jzEGERKw0zhFihD/dcB2CrKJYewoyLFvM0XzGNNpzOZbSAGVPBqVWHdRSDx4SI -NMhYANfgc4meDteW5ePGC45P4MkCumKhUENzDsu1H3lw1vJx1RJxGMKns6O2lWDqINGgotAHFCsu -I7FAoWHFJGezEFWGqsEvaD5C42naHb93X+A3+elYCgVaxgh8DmQAys9HL2SS0mIaWBgm7mTN/O3G -kzu6vHCng/HkW/fSve5O+hTOpnhfQAcoEry5jKVjNypoO0fgwzKSOgHm79KUK06Jfc7/RebHpD8a -9kdXvT2UcnuFWG6p0stNB0mWUUQ1q3uiGRVEMfXHR03dTuQATPjwqIIPcB9wL4CArRAY/ZHJixYL -Y9YBtcAoLQtFevOoI9QaHcEdMSAB0d08kuZhyUiSmav6CPCdVBnFOjNrLu6yMCWgKRA0TInBC5i4 -QwX3JG/mm581GKnSsSSxJTFHf9MAKr8w5T/vOv1mUurn5/zlT6fvTntjZzAaNl9rQ5JkU5KIc0GX -inagwU57T2eddqWlTrvaS6d9sImZeUMkhWysveF0m37NcGub9Dpgi0j4qGiOzATjDr06OBjOYQOo -7RBoGtNm9Denv1i0LVI7lxJDXLHSSBeWRflsyyqw7diuW3h0XdvK6lBMyaoMG1UyHdTsoYBuue75 -YOgOu1c91/2cwYpznPPeDoQpGL2xSm09NKp7BsvQ2hnT3aMs07lUnskpxewvBk73/LLnXo9HV9eT -ijB3hWBO2ygoiWg/bKuZxqCCQq0DD3vkWIVvI2KosIw+vqW1gIItEG5KJb+xb09g65ktwYKgTc51 -uGJ/EFQs0ayEWLCQM5V9N4g+1+8UbXOJzF8bqhKtIqIwicWvzNFROZJlpfD8A7Vc044R0FxkcezG -VzsV75usvTdYef+57v5n1b225qhXfwEmxHEs -""") - -##file activate.fish -ACTIVATE_FISH = convert(""" -eJyFVVFv2zYQftevuMoOnBS1gr0WGIZ08RADSRw4boBhGGhGOsUcKFIjKbUu9uN7lC2JsrXWDzZM -fnf38e6+uwlsdsJCLiRCUVkHrwiVxYy+hHqDbQKvQl3z1ImaO0xyYXdbeP9FuJ1QwMFUSnmcP4dL -2DlXfry+9v/sDqVMUl3AFVi0Vmj1PokmcKtBaecNQTjIhMHUyX0SRXmlKIpWkGEbDuYZzBZfCVcL -4youUdVQ6AyBqwwMusoocBrcDsmpKbgEQgijVYHKJbMI6DMhoEUHWmbhLdTcCP4q0TYokYNDev5c -QTxlq/tb9rJcbz7f3LOnm81d3GD8x3uav30FfwrnwCEOYRyAKot+FvXPzd3q8W71sBiJ3d2dMugu -fsxjCPsBmz+Wz3fsab16eNqw1ctivV7eBnwm8EzeuQIsSrcHqVMqwHbqq8/aarKSO+oYKhKXUn9p -SmWw0DVBdQ7bBlwaTR62bc+1tpaYb5PhUyScu48CRgvDLQbtMrMnMQ6dY5022JDRRrwJxWUfJwwP -ge0YIAVGfcUC1M8s8MxitFZjmR9W64hui7p4fBlWMZ5y81b/9cvfMbz7FWZKq4yOTeW1hbNBEWU+ -b+/ejXMu95lOx696uXb8Go4T+Kw8R2EMSqx5KLkkCkQ+ZBZFbZsHL4OYseAvY3EPO5MYTBuhDZQa -TwPza8Y+LR/Z483Dgjwd4R3f7bTXx9Znkw6T6PAL83/hRD3jNAKFjuEx9NJkq5t+fabLvdvRwbw4 -nEFTzwO6U+q34cvY7fL55tP94tg58XEA/q7LfdPsaUXFoEIMJdHF5iSW0+48CnDQ82G7n3XzAD6q -Bmo5XuOA0NQ67ir7AXJtQhtLKO7XhC0l39PGOBsHPvzBuHUSjoOnA0ldozGC9gZ5rek3+y3ALHO/ -kT7AP379lQZLSnFDLtwWihfYxw4nZd+ZR7myfkI2ZTRCuRxmF/bCzkbhcElvYamW9PbDGrvqPKC0 -+D/uLi/sFcxGjOHylYagZzzsjjhw206RQwrWIwOxS2dnk+40xOjX8bTPegz/gdWVSXuaowNuOLda -wYyNuRPSTcd/B48Ppeg= -""") - -##file activate.csh -ACTIVATE_CSH = convert(""" -eJx1U2FP2zAQ/e5f8TAV3Soo+0zXbYUiDQkKQgVp2ibjJNfFUuIg22nVf885SVFLO3+I7Lt3fr6X -d8eY58ZjYQpCWfuAhFB7yrAyIYf0Ve1SQmLsuU6DWepAw9TnEoOFq0rwdjAUx/hV1Ui1tVWAqy1M -QGYcpaFYx+yVI67LkKwx1UuTEaYGl4X2Bl+zJpAlP/6V2hTDtCq/DYXQhdEeGW040Q/Eb+t9V/e3 -U/V88zh/mtyqh8n8J47G+IKTE3gKZJdoYrK3h5MRU1tGYS83gqNc+3yEgyyP93cP820evHLvr2H8 -kaYB/peoyY7aVHzpJnE9e+6I5Z+ji4GMTNJWNuOQq6MA1N25p8pW9HWdVWlfsNpPDbdxjgpaahuw -1M7opCA/FFu1uwxC7L8KUqmto1KyQe3rx0I0Eovdf7BVe67U5c1MzSZ310pddGheZoFPWyytRkzU -aCA/I+RkBXhFXr5aWV0SxjhUI6jwdAj8kmhPzX7nTfJFkM3MImp2VdVFFq1vLHSU5szYQK4Ri+Jd -xlW2JBtOGcyYVW7SnB3v6RS91g3gKapZ0oWxbHVteYIIq3iv7QeuSrUj6KSqQ+yqsxDj1ivNQxKF -YON10Q+NH/ARS95i5Tuqq2Vxfvc23f/FO6zrtXXmJr+ZtMY9/A15ZXFWtmch2rEQ4g1ryVHH -""") - -##file activate.bat -ACTIVATE_BAT = convert(""" -eJx9Ul9LhEAQfxf8DoOclI/dYyFkaCmcq4gZQTBUrincuZFbff12T133TM+nnd35/Zvxlr7XDFhV -mUZHOVhFlOWP3g4DUriIWoVomYZpNBWUtGpaWgImO191pFkSpzlcmgaI70jVX7n2Qp8tuByg+46O -CMHbMq64T+nmlJt082D1T44muCDk2prgEHF4mdI9RaS/QwSt3zSyIAaftRccvqVTBziD1x/WlPD5 -xd729NDBb8Nr4DU9QNMKsJeH9pkhPedhQsIkDuCDCa6A+NF9IevVFAohkqizdHetg/tkWvPoftWJ -MCqnOxv7/x7Np6yv9P2Ker5dmX8yNyCkkWnbZy3N5LarczlqL8htx2EM9rQ/2H5BvIsIEi8OEG8U -+g8CsNTr -""") - -##file deactivate.bat -DEACTIVATE_BAT = convert(""" -eJyFkN0KgkAUhO8F32EQpHqFQEjQUPAPMaErqVxzId3IrV6/XST/UDx3c86c4WMO5FYysKJQFVVp -CEfqxsnJ9DI7SA25i20fFqs3HO+GYLsDZ7h8GM3xfLHrg1QNvpSX4CWpQGvokZk4uqrQAjXjyElB -a5IjCz0r+2dHcehHCe5MZNmB5R7TdqMqECMptHZh6DN/utb7Zs6Cej8OXYE5J04YOKFvD4GkHuJ0 -pilSd1jG6n87tDZ+BUwUOepI6CGSkFMYWf0ihvT33Qj1A+tCkSI= -""") - -##file activate.ps1 -ACTIVATE_PS = convert(""" -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 -rKQDxR6N/rffXv+lROXet/9Q+l9I4D1U -""") - -##file distutils-init.py -DISTUTILS_INIT = convert(""" -eJytV1uL4zYUfvevOE0ottuMW9q3gVDa3aUMXXbLMlDKMBiNrSTqOJKRlMxkf33PkXyRbGe7Dw2E -UXTu37lpxLFV2oIyifAncxmOL0xLIfcG+gv80x9VW6maw7o/CANSWWBwFtqeWMPlGY6qPjV8A0bB -C4eKSTgZ5LRgFeyErMEeOBhbN+Ipgeizhjtnhkn7DdyjuNLPoCS0l/ayQTG0djwZC08cLXozeMss -aG5EzQ0IScpnWtHSTXuxByV/QCmxE7y+eS0uxWeoheaVVfqSJHiU7Mhhi6gULbOHorshkrEnKxpT -0n3A8Y8SMpuwZx6aoix3ouFlmW8gHRSkeSJ2g7hU+kiHLDaQw3bmRDaTGfTnty7gPm0FHbIBg9U9 -oh1kZzAFLaue2R6htPCtAda2nGlDSUJ4PZBgCJBGVcwKTAMz/vJiLD+Oin5Z5QlvDPdulC6EsiyE -NFzb7McNTKJzbJqzphx92VKRFY1idenzmq3K0emRcbWBD0ryqc4NZGmKOOOX9Pz5x+/l27tP797c -f/z0d+4NruGNai8uAM0bfsYaw8itFk8ny41jsfpyO+BWlpqfhcG4yxLdi/0tQqoT4a8Vby382mt8 -p7XSo7aWGdPBc+b6utaBmCQ7rQKQoWtAuthQCiold2KfJIPTT8xwg9blPumc+YDZC/wYGdAyHpJk -vUbHbHWAp5No6pK/WhhLEWrFjUwtPEv1Agf8YmnsuXUQYkeZoHm8ogP16gt2uHoxcEMdf2C6pmbw -hUMsWGhanboh4IzzmsIpWs134jVPqD/c74bZHdY69UKKSn/+KfVhxLgUlToemayLMYQOqfEC61bh -cbhwaqoGUzIyZRFHPmau5juaWqwRn3mpWmoEA5nhzS5gog/5jbcFQqOZvmBasZtwYlG93k5GEiyw -buHhMWLjDarEGpMGB2LFs5nIJkhp/nUmZneFaRth++lieJtHepIvKgx6PJqIlD9X2j6pG1i9x3pZ -5bHuCPFiirGHeO7McvoXkz786GaKVzC9DSpnOxJdc4xm6NSVq7lNEnKdVlnpu9BNYoKX2Iq3wvgh -gGEUM66kK6j4NiyoneuPLSwaCWDxczgaolEWpiMyDVDb7dNuLAbriL8ig8mmeju31oNvQdpnvEPC -1vAXbWacGRVrGt/uXN/gU0CDDwgooKRrHfTBb1/s9lYZ8ZqOBU0yLvpuP6+K9hLFsvIjeNhBi0KL -MlOuWRn3FRwx5oHXjl0YImUx0+gLzjGchrgzca026ETmYJzPD+IpuKzNi8AFn048Thd63OdD86M6 -84zE8yQm0VqXdbbgvub2pKVnS76icBGdeTHHXTKspUmr4NYo/furFLKiMdQzFjHJNcdAnMhltBJK -0/IKX3DVFqvPJ2dLE7bDBkH0l/PJ29074+F0CsGYOxsb7U3myTUncYfXqnLLfa6sJybX4g+hmcjO -kMRBfA1JellfRRKJcyRpxdS4rIl6FdmQCWjo/o9Qz7yKffoP4JHjOvABcRn4CZIT2RH4jnxmfpVG -qgLaAvQBNfuO6X0/Ux02nb4FKx3vgP+XnkX0QW9pLy/NsXgdN24dD3LxO2Nwil7Zlc1dqtP3d7/h -kzp1/+7hGBuY4pk0XD/0Ao/oTe/XGrfyM773aB7iUhgkpy+dwAMalxMP0DrBcsVw/6p25+/hobP9 -GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ= -""") - -##file distutils.cfg -DISTUTILS_CFG = convert(""" -eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH -xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg -9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q= -""") - -##file activate_this.py -ACTIVATE_THIS = convert(""" -eJyNU01v2zAMvetXEB4K21jnDOstQA4dMGCHbeihlyEIDMWmE62yJEiKE//7kXKdpEWLzYBt8evx -kRSzLPs6wiEoswM8YdMpjUXcq1Dz6RZa1cSiTkJdr86GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe -5a3p0cRKiEe2NtLAFikftnDco0ko/SFEVgEZ8aRCZDIPY9xbA8pE9M4jfW/B2CjiHq9zbJVZuOQq -siwTIvpxKYCembPAU4Muwi/Z4zfvrZ/MXipKeB8C+qisSZYiWfjJfs+0/MFMdWn1hJcO5U7G/SLa -xVx8zU6VG/PXLXvfsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCJN9dzKaoexyB/uH79TnjwvxcW0ntSb -yZ8jq1Z5Q1UXsyy3gf9nbjTEj7NzQMfCJa/YSmrQ+2D/BqfiOi6sclrGzvoeVivIj8rcfcmnIQRF -7XCyeZI7DFe5/lhlCs5PRf5QW66VXT/NrlQ46oD/D6InkOmi3IQcbhKxAX2g4a+Xd5s3UtCtG2py -m8eg6WYWqR6SL5OjKMGfSrYt/6kxxQtOpeAgj1LXBNmpE2ElmCSIy5H0zFd8gJ924HWijWhb2hRC -6wNEm1QdDZtuSZcEprIUBo/XRNcbQe1OUbQ/r3hPTaPJJDNtFLu8KHV5XoNr3Eo6h6YtOKw8e8yw -VF5PnJ+ts3a9/Mz38RpG/AUSzYUW -""") - -##file python-config -PYTHON_CONFIG = convert(""" -eJyNVV1P2zAUfc+v8ODBiSABxlulTipbO6p1LWqBgVhlhcZpPYUkctzSivHfd6+dpGloGH2Ja/ue -e+65Hz78xNhtf3x90xmw7vCWsRPGLvpDNuz87MKfdKMWSWxZ4ilNpCLZJiuWc66SVFUOZkkcirll -rfxIBAzOMtImDzSVPBRrekwoX/OZu/0r4lm0DHiG60g86u8sjPw5rCyy86NRkB8QuuBRSqfAKESn -3orLTCQxE3GYkC9tYp8fk89OSwNsmXgizrhUtnumeSgeo5GbLUMk49Rv+2nK48Cm/qMwfp333J2/ -dVcAGE0CIQHBsgIeEr4Wij0LtWDLzJ9ze5YEvH2WI6CHTAVcSu9ZCsXtgxu81CIvp6/k4eXsdfo7 -PvDCRD75yi41QitfzlcPp1OI7i/1/iQitqnr0iMgQ+A6wa+IKwwdxyk9IiXNAzgquTFU8NIxAVjM -osm1Zz526e+shQ4hKRVci69nPC3Kw4NQEmkQ65E7OodxorSvxjvpBjQHDmWFIQ1mlmzlS5vedseT -/mgIEsMJ7Lxz2bLAF9M5xeLEhdbHxpWOw0GdkJApMVBRF1y+a0z3c9WZPAXGFcFrJgCIB+024uad -0CrzmEoRa3Ub4swNIHPGf7QDV+2uj2OiFWsChgCwjKqN6rp5izpbH6Wc1O1TclQTP/XVwi6anTr1 -1sbubjZLI1+VptPSdCfwnFBrB1jvebrTA9uUhU2/9gad7xPqeFkaQcnnLbCViZK8d7R1kxzFrIJV -8EaLYmKYpvGVkig+3C5HCXbM1jGCGekiM2pRCVPyRyXYdPf6kcbWEQ36F5V4Gq9N7icNNw+JHwRE -LTgxRXACpvnQv/PuT0xCCAywY/K4hE6Now2qDwaSE5FB+1agsoUveYDepS83qFcF1NufvULD3fTl -g6Hgf7WBt6lzMeiyyWVn3P1WVbwaczHmTzE9A5SyItTVgFYyvs/L/fXlaNgbw8v3azT+0eikVlWD -/vBHbzQumP23uBCjsYdrL9OWARwxs/nuLOzeXbPJTa/Xv6sUmQir5pC1YRLz3eA+CD8Z0XpcW8v9 -MZWF36ryyXXf3yBIz6nzqz8Muyz0m5Qj7OexfYo/Ph3LqvkHUg7AuA== -""") - -MH_MAGIC = 0xfeedface -MH_CIGAM = 0xcefaedfe -MH_MAGIC_64 = 0xfeedfacf -MH_CIGAM_64 = 0xcffaedfe -FAT_MAGIC = 0xcafebabe -BIG_ENDIAN = '>' -LITTLE_ENDIAN = '<' -LC_LOAD_DYLIB = 0xc -maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint') - - -class fileview(object): - """ - A proxy for file-like objects that exposes a given view of a file. - Modified from macholib. - """ - - def __init__(self, fileobj, start=0, size=maxint): - if isinstance(fileobj, fileview): - self._fileobj = fileobj._fileobj - else: - self._fileobj = fileobj - self._start = start - self._end = start + size - self._pos = 0 - - def __repr__(self): - return '' % ( - self._start, self._end, self._fileobj) - - def tell(self): - return self._pos - - def _checkwindow(self, seekto, op): - if not (self._start <= seekto <= self._end): - raise IOError("%s to offset %d is outside window [%d, %d]" % ( - op, seekto, self._start, self._end)) - - def seek(self, offset, whence=0): - seekto = offset - if whence == os.SEEK_SET: - seekto += self._start - elif whence == os.SEEK_CUR: - seekto += self._start + self._pos - elif whence == os.SEEK_END: - seekto += self._end - else: - raise IOError("Invalid whence argument to seek: %r" % (whence,)) - self._checkwindow(seekto, 'seek') - self._fileobj.seek(seekto) - self._pos = seekto - self._start - - def write(self, bytes): - here = self._start + self._pos - self._checkwindow(here, 'write') - self._checkwindow(here + len(bytes), 'write') - self._fileobj.seek(here, os.SEEK_SET) - self._fileobj.write(bytes) - self._pos += len(bytes) - - def read(self, size=maxint): - assert size >= 0 - here = self._start + self._pos - self._checkwindow(here, 'read') - size = min(size, self._end - here) - self._fileobj.seek(here, os.SEEK_SET) - bytes = self._fileobj.read(size) - self._pos += len(bytes) - return bytes - - -def read_data(file, endian, num=1): - """ - Read a given number of 32-bits unsigned integers from the given file - with the given endianness. - """ - res = struct.unpack(endian + 'L' * num, file.read(num * 4)) - if len(res) == 1: - return res[0] - return res - - -def mach_o_change(path, what, value): - """ - Replace a given name (what) in any LC_LOAD_DYLIB command found in - the given binary with a new name (value), provided it's shorter. - """ - - def do_macho(file, bits, endian): - # Read Mach-O header (the magic number is assumed read by the caller) - cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6) - # 64-bits header has one more field. - if bits == 64: - read_data(file, endian) - # The header is followed by ncmds commands - for n in range(ncmds): - where = file.tell() - # Read command header - cmd, cmdsize = read_data(file, endian, 2) - if cmd == LC_LOAD_DYLIB: - # The first data field in LC_LOAD_DYLIB commands is the - # offset of the name, starting from the beginning of the - # command. - name_offset = read_data(file, endian) - file.seek(where + name_offset, os.SEEK_SET) - # Read the NUL terminated string - load = file.read(cmdsize - name_offset).decode() - load = load[:load.index('\0')] - # If the string is what is being replaced, overwrite it. - if load == what: - file.seek(where + name_offset, os.SEEK_SET) - file.write(value.encode() + '\0'.encode()) - # Seek to the next command - file.seek(where + cmdsize, os.SEEK_SET) - - def do_file(file, offset=0, size=maxint): - file = fileview(file, offset, size) - # Read magic number - magic = read_data(file, BIG_ENDIAN) - if magic == FAT_MAGIC: - # Fat binaries contain nfat_arch Mach-O binaries - nfat_arch = read_data(file, BIG_ENDIAN) - for n in range(nfat_arch): - # Read arch header - cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5) - do_file(file, offset, size) - elif magic == MH_MAGIC: - do_macho(file, 32, BIG_ENDIAN) - elif magic == MH_CIGAM: - do_macho(file, 32, LITTLE_ENDIAN) - elif magic == MH_MAGIC_64: - do_macho(file, 64, BIG_ENDIAN) - elif magic == MH_CIGAM_64: - do_macho(file, 64, LITTLE_ENDIAN) - - assert(len(what) >= len(value)) - - with open(path, 'r+b') as f: - do_file(f) - - -if __name__ == '__main__': - main() - -# TODO: -# Copy python.exe.manifest -# Monkeypatch distutils.sysconfig diff --git a/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/argparse-1.4.0-py2.py3-none-any.whl b/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/argparse-1.4.0-py2.py3-none-any.whl deleted file mode 100644 index dfef51d4483025c5a535e553266234d372480439..0000000000000000000000000000000000000000 Binary files a/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/argparse-1.4.0-py2.py3-none-any.whl and /dev/null differ diff --git a/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/pip-9.0.1-py2.py3-none-any.whl b/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/pip-9.0.1-py2.py3-none-any.whl deleted file mode 100644 index 4b8ecc69db7e37fc6dd7b6dd8f690508f42866a1..0000000000000000000000000000000000000000 Binary files a/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/pip-9.0.1-py2.py3-none-any.whl and /dev/null differ diff --git a/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/setuptools-28.8.0-py2.py3-none-any.whl b/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/setuptools-28.8.0-py2.py3-none-any.whl deleted file mode 100644 index 502e3cb418c154872ad6e677ef8b63557b38ec35..0000000000000000000000000000000000000000 Binary files a/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/setuptools-28.8.0-py2.py3-none-any.whl and /dev/null differ diff --git a/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/wheel-0.29.0-py2.py3-none-any.whl b/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/wheel-0.29.0-py2.py3-none-any.whl deleted file mode 100644 index 506d5e520f918acc9c1a36014cca1f4b953c594c..0000000000000000000000000000000000000000 Binary files a/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/wheel-0.29.0-py2.py3-none-any.whl and /dev/null differ diff --git a/src/leiningen/new/python/utils/virtualenv-15.1.0/LICENSE.txt b/src/leiningen/new/python/utils/virtualenv-16.4.1/LICENSE.txt similarity index 100% rename from src/leiningen/new/python/utils/virtualenv-15.1.0/LICENSE.txt rename to src/leiningen/new/python/utils/virtualenv-16.4.1/LICENSE.txt diff --git a/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv.py b/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv.py new file mode 100755 index 0000000000000000000000000000000000000000..fd7974de812848425d79847966ced39177ab7269 --- /dev/null +++ b/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv.py @@ -0,0 +1,2584 @@ +#!/usr/bin/env python +"""Create a "virtual" Python installation""" + +# fmt: off +import os # isort:skip +import sys # isort:skip + +# If we are running in a new interpreter to create a virtualenv, +# we do NOT want paths from our existing location interfering with anything, +# So we remove this file's directory from sys.path - most likely to be +# the previous interpreter's site-packages. Solves #705, #763, #779 +if os.environ.get("VIRTUALENV_INTERPRETER_RUNNING"): + for path in sys.path[:]: + if os.path.realpath(os.path.dirname(__file__)) == os.path.realpath(path): + sys.path.remove(path) +# fmt: on + +import ast +import base64 +import codecs +import contextlib +import distutils.spawn +import distutils.sysconfig +import errno +import glob +import logging +import optparse +import os +import re +import shutil +import struct +import subprocess +import sys +import tempfile +import textwrap +import zipfile +import zlib +from distutils.util import strtobool +from os.path import join + +try: + import ConfigParser +except ImportError: + # noinspection PyPep8Naming + import configparser as ConfigParser + +__version__ = "16.4.1" +virtualenv_version = __version__ # legacy +DEBUG = os.environ.get("_VIRTUALENV_DEBUG", None) == "1" +if sys.version_info < (2, 7): + print("ERROR: {}".format(sys.exc_info()[1])) + print("ERROR: this script requires Python 2.7 or greater.") + sys.exit(101) + +HERE = os.path.dirname(os.path.abspath(__file__)) +IS_ZIPAPP = os.path.isfile(HERE) + +try: + # noinspection PyUnresolvedReferences,PyUnboundLocalVariable + basestring +except NameError: + basestring = str + +PY_VERSION = "python{}.{}".format(sys.version_info[0], sys.version_info[1]) + +IS_JYTHON = sys.platform.startswith("java") +IS_PYPY = hasattr(sys, "pypy_version_info") +IS_WIN = sys.platform == "win32" +IS_CYGWIN = sys.platform == "cygwin" +IS_DARWIN = sys.platform == "darwin" +ABI_FLAGS = getattr(sys, "abiflags", "") + +USER_DIR = os.path.expanduser("~") +if IS_WIN: + DEFAULT_STORAGE_DIR = os.path.join(USER_DIR, "virtualenv") +else: + DEFAULT_STORAGE_DIR = os.path.join(USER_DIR, ".virtualenv") +DEFAULT_CONFIG_FILE = os.path.join(DEFAULT_STORAGE_DIR, "virtualenv.ini") + +if IS_PYPY: + EXPECTED_EXE = "pypy" +elif IS_JYTHON: + EXPECTED_EXE = "jython" +else: + EXPECTED_EXE = "python" + +# Return a mapping of version -> Python executable +# Only provided for Windows, where the information in the registry is used +if not IS_WIN: + + def get_installed_pythons(): + return {} + + +else: + try: + import winreg + except ImportError: + # noinspection PyUnresolvedReferences + import _winreg as winreg + + def get_installed_pythons(): + exes = dict() + # If both system and current user installations are found for a + # particular Python version, the current user one is used + for key in (winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER): + try: + python_core = winreg.CreateKey(key, "Software\\Python\\PythonCore") + except WindowsError: + # No registered Python installations + continue + i = 0 + while True: + try: + version = winreg.EnumKey(python_core, i) + i += 1 + try: + at_path = winreg.QueryValue(python_core, "{}\\InstallPath".format(version)) + except WindowsError: + continue + exes[version] = join(at_path, "python.exe") + except WindowsError: + break + winreg.CloseKey(python_core) + + # For versions that track separate 32-bit (`X.Y-32`) & 64-bit (`X-Y`) + # installation registrations, add a `X.Y-64` version tag and make the + # extensionless `X.Y` version tag represent the 64-bit installation if + # available or 32-bit if it is not + updated = {} + for ver in exes: + if ver < "3.5": + continue + if ver.endswith("-32"): + base_ver = ver[:-3] + if base_ver not in exes: + updated[base_ver] = exes[ver] + else: + updated[ver + "-64"] = exes[ver] + exes.update(updated) + + # Add the major versions + # Sort the keys, then repeatedly update the major version entry + # Last executable (i.e., highest version) wins with this approach, + # 64-bit over 32-bit if both are found + for ver in sorted(exes): + exes[ver[0]] = exes[ver] + + return exes + + +REQUIRED_MODULES = [ + "os", + "posix", + "posixpath", + "nt", + "ntpath", + "genericpath", + "fnmatch", + "locale", + "encodings", + "codecs", + "stat", + "UserDict", + "readline", + "copy_reg", + "types", + "re", + "sre", + "sre_parse", + "sre_constants", + "sre_compile", + "zlib", +] + +REQUIRED_FILES = ["lib-dynload", "config"] + +MAJOR, MINOR = sys.version_info[:2] +if MAJOR == 2: + if MINOR >= 6: + REQUIRED_MODULES.extend(["warnings", "linecache", "_abcoll", "abc"]) + if MINOR >= 7: + REQUIRED_MODULES.extend(["_weakrefset"]) +elif MAJOR == 3: + # Some extra modules are needed for Python 3, but different ones + # for different versions. + REQUIRED_MODULES.extend( + [ + "_abcoll", + "warnings", + "linecache", + "abc", + "io", + "_weakrefset", + "copyreg", + "tempfile", + "random", + "__future__", + "collections", + "keyword", + "tarfile", + "shutil", + "struct", + "copy", + "tokenize", + "token", + "functools", + "heapq", + "bisect", + "weakref", + "reprlib", + ] + ) + if MINOR >= 2: + REQUIRED_FILES[-1] = "config-{}".format(MAJOR) + if MINOR >= 3: + import sysconfig + + platform_dir = sysconfig.get_config_var("PLATDIR") + REQUIRED_FILES.append(platform_dir) + REQUIRED_MODULES.extend(["base64", "_dummy_thread", "hashlib", "hmac", "imp", "importlib", "rlcompleter"]) + if MINOR >= 4: + REQUIRED_MODULES.extend(["operator", "_collections_abc", "_bootlocale"]) + if MINOR >= 6: + REQUIRED_MODULES.extend(["enum"]) + +if IS_PYPY: + # these are needed to correctly display the exceptions that may happen + # during the bootstrap + REQUIRED_MODULES.extend(["traceback", "linecache"]) + + if MAJOR == 3: + # _functools is needed to import locale during stdio initialization and + # needs to be copied on PyPy because it's not built in + REQUIRED_MODULES.append("_functools") + + +class Logger(object): + + """ + Logging object for use in command-line script. Allows ranges of + levels, to avoid some redundancy of displayed information. + """ + + DEBUG = logging.DEBUG + INFO = logging.INFO + NOTIFY = (logging.INFO + logging.WARN) / 2 + WARN = WARNING = logging.WARN + ERROR = logging.ERROR + FATAL = logging.FATAL + + LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] + + def __init__(self, consumers): + self.consumers = consumers + self.indent = 0 + self.in_progress = None + self.in_progress_hanging = False + + def debug(self, msg, *args, **kw): + self.log(self.DEBUG, msg, *args, **kw) + + def info(self, msg, *args, **kw): + self.log(self.INFO, msg, *args, **kw) + + def notify(self, msg, *args, **kw): + self.log(self.NOTIFY, msg, *args, **kw) + + def warn(self, msg, *args, **kw): + self.log(self.WARN, msg, *args, **kw) + + def error(self, msg, *args, **kw): + self.log(self.ERROR, msg, *args, **kw) + + def fatal(self, msg, *args, **kw): + self.log(self.FATAL, msg, *args, **kw) + + def log(self, level, msg, *args, **kw): + if args: + if kw: + raise TypeError("You may give positional or keyword arguments, not both") + args = args or kw + rendered = None + for consumer_level, consumer in self.consumers: + if self.level_matches(level, consumer_level): + if self.in_progress_hanging and consumer in (sys.stdout, sys.stderr): + self.in_progress_hanging = False + print("") + sys.stdout.flush() + if rendered is None: + if args: + rendered = msg % args + else: + rendered = msg + rendered = " " * self.indent + rendered + if hasattr(consumer, "write"): + consumer.write(rendered + "\n") + else: + consumer(rendered) + + def start_progress(self, msg): + assert not self.in_progress, "Tried to start_progress({!r}) while in_progress {!r}".format( + msg, self.in_progress + ) + if self.level_matches(self.NOTIFY, self._stdout_level()): + print(msg) + sys.stdout.flush() + self.in_progress_hanging = True + else: + self.in_progress_hanging = False + self.in_progress = msg + + def end_progress(self, msg="done."): + assert self.in_progress, "Tried to end_progress without start_progress" + if self.stdout_level_matches(self.NOTIFY): + if not self.in_progress_hanging: + # Some message has been printed out since start_progress + print("...{}{}".format(self.in_progress, msg)) + sys.stdout.flush() + else: + print(msg) + sys.stdout.flush() + self.in_progress = None + self.in_progress_hanging = False + + def show_progress(self): + """If we are in a progress scope, and no log messages have been + shown, write out another '.'""" + if self.in_progress_hanging: + print(".") + sys.stdout.flush() + + def stdout_level_matches(self, level): + """Returns true if a message at this level will go to stdout""" + return self.level_matches(level, self._stdout_level()) + + def _stdout_level(self): + """Returns the level that stdout runs at""" + for level, consumer in self.consumers: + if consumer is sys.stdout: + return level + return self.FATAL + + @staticmethod + def level_matches(level, consumer_level): + """ + >>> l = Logger([]) + >>> l.level_matches(3, 4) + False + >>> l.level_matches(3, 2) + True + >>> l.level_matches(slice(None, 3), 3) + False + >>> l.level_matches(slice(None, 3), 2) + True + >>> l.level_matches(slice(1, 3), 1) + True + >>> l.level_matches(slice(2, 3), 1) + False + """ + if isinstance(level, slice): + start, stop = level.start, level.stop + if start is not None and start > consumer_level: + return False + if stop is not None and stop <= consumer_level: + return False + return True + else: + return level >= consumer_level + + @classmethod + def level_for_integer(cls, level): + levels = cls.LEVELS + if level < 0: + return levels[0] + if level >= len(levels): + return levels[-1] + return levels[level] + + +# create a silent logger just to prevent this from being undefined +# will be overridden with requested verbosity main() is called. +logger = Logger([(Logger.LEVELS[-1], sys.stdout)]) + + +def mkdir(at_path): + if not os.path.exists(at_path): + logger.info("Creating %s", at_path) + os.makedirs(at_path) + else: + logger.info("Directory %s already exists", at_path) + + +def copy_file_or_folder(src, dest, symlink=True): + if os.path.isdir(src): + shutil.copytree(src, dest, symlink) + else: + shutil.copy2(src, dest) + + +def symlink_file_or_folder(src, dest): + if os.path.exists(dest): + return + if os.path.isdir(src): + if not os.path.exists(dest): + os.makedirs(dest) + for fn in os.listdir(src): + symlink_file_or_folder(os.path.join(src, fn), os.path.join(dest, fn)) + else: + if not os.path.exists(os.path.dirname(dest)): + os.makedirs(os.path.dirname(dest)) + if not os.path.islink(src): + srcpath = os.path.abspath(src) + else: + srcpath = os.readlink(src) + if not srcpath[0] == "/": + # relative symlink, needs to be prefixed with absolute source path + srcpath = os.path.join(os.path.dirname(src), srcpath) + srcpath = os.path.abspath(srcpath) + logger.info("Symlinking %s :: %s -> %s", src, srcpath, dest) + os.symlink(srcpath, dest) + + +def copyfile(src, dest, symlink=True): + if symlink and hasattr(os, "symlink") and not IS_WIN: + return symlink_file_or_folder(src, dest) + if not os.path.exists(src): + # Some bad symlink in the src + logger.warn("Cannot find file %s (bad symlink)", src) + return + if os.path.exists(dest): + logger.debug("File %s already exists", dest) + return + if not os.path.exists(os.path.dirname(dest)): + logger.info("Creating parent directories for %s", os.path.dirname(dest)) + os.makedirs(os.path.dirname(dest)) + logger.info("Copying to %s", dest) + copy_file_or_folder(src, dest, symlink) + + +def writefile(dest, content, overwrite=True): + if not os.path.exists(dest): + logger.info("Writing %s", dest) + with open(dest, "wb") as f: + f.write(content.encode("utf-8")) + return + else: + with open(dest, "rb") as f: + c = f.read() + if c != content.encode("utf-8"): + if not overwrite: + logger.notify("File %s exists with different content; not overwriting", dest) + return + logger.notify("Overwriting %s with new content", dest) + with open(dest, "wb") as f: + f.write(content.encode("utf-8")) + else: + logger.info("Content %s already in place", dest) + + +def rm_tree(folder): + if os.path.exists(folder): + logger.notify("Deleting tree %s", folder) + shutil.rmtree(folder) + else: + logger.info("Do not need to delete %s; already gone", folder) + + +def make_exe(fn): + if hasattr(os, "chmod"): + old_mode = os.stat(fn).st_mode & 0xFFF # 0o7777 + new_mode = (old_mode | 0x16D) & 0xFFF # 0o555, 0o7777 + os.chmod(fn, new_mode) + logger.info("Changed mode of %s to %s", fn, oct(new_mode)) + + +def _find_file(filename, folders): + for folder in reversed(folders): + files = glob.glob(os.path.join(folder, filename)) + if files and os.path.isfile(files[0]): + return True, files[0] + return False, filename + + +@contextlib.contextmanager +def virtualenv_support_dirs(): + """Context manager yielding either [virtualenv_support_dir] or []""" + + # normal filesystem installation + if os.path.isdir(join(HERE, "virtualenv_support")): + yield [join(HERE, "virtualenv_support")] + elif IS_ZIPAPP: + tmpdir = tempfile.mkdtemp() + try: + with zipfile.ZipFile(HERE) as zipf: + for member in zipf.namelist(): + if os.path.dirname(member) == "virtualenv_support": + zipf.extract(member, tmpdir) + yield [join(tmpdir, "virtualenv_support")] + finally: + shutil.rmtree(tmpdir) + # probably a bootstrap script + elif os.path.splitext(os.path.dirname(__file__))[0] != "virtualenv": + try: + # noinspection PyUnresolvedReferences + import virtualenv + except ImportError: + yield [] + else: + yield [join(os.path.dirname(virtualenv.__file__), "virtualenv_support")] + # we tried! + else: + yield [] + + +class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter): + """ + Custom help formatter for use in ConfigOptionParser that updates + the defaults before expanding them, allowing them to show up correctly + in the help listing + """ + + def expand_default(self, option): + if self.parser is not None: + self.parser.update_defaults(self.parser.defaults) + return optparse.IndentedHelpFormatter.expand_default(self, option) + + +class ConfigOptionParser(optparse.OptionParser): + """ + Custom option parser which updates its defaults by checking the + configuration files and environmental variables + """ + + def __init__(self, *args, **kwargs): + self.config = ConfigParser.RawConfigParser() + self.files = self.get_config_files() + self.config.read(self.files) + optparse.OptionParser.__init__(self, *args, **kwargs) + + @staticmethod + def get_config_files(): + config_file = os.environ.get("VIRTUALENV_CONFIG_FILE", False) + if config_file and os.path.exists(config_file): + return [config_file] + return [DEFAULT_CONFIG_FILE] + + def update_defaults(self, defaults): + """ + Updates the given defaults with values from the config files and + the environ. Does a little special handling for certain types of + options (lists). + """ + # Then go and look for the other sources of configuration: + config = {} + # 1. config files + config.update(dict(self.get_config_section("virtualenv"))) + # 2. environmental variables + config.update(dict(self.get_environ_vars())) + # Then set the options with those values + for key, val in config.items(): + key = key.replace("_", "-") + if not key.startswith("--"): + key = "--{}".format(key) # only prefer long opts + option = self.get_option(key) + if option is not None: + # ignore empty values + if not val: + continue + # handle multiline configs + if option.action == "append": + val = val.split() + else: + option.nargs = 1 + if option.action == "store_false": + val = not strtobool(val) + elif option.action in ("store_true", "count"): + val = strtobool(val) + try: + val = option.convert_value(key, val) + except optparse.OptionValueError: + e = sys.exc_info()[1] + print("An error occurred during configuration: {!r}".format(e)) + sys.exit(3) + defaults[option.dest] = val + return defaults + + def get_config_section(self, name): + """ + Get a section of a configuration + """ + if self.config.has_section(name): + return self.config.items(name) + return [] + + def get_environ_vars(self, prefix="VIRTUALENV_"): + """ + Returns a generator with all environmental vars with prefix VIRTUALENV + """ + for key, val in os.environ.items(): + if key.startswith(prefix): + yield (key.replace(prefix, "").lower(), val) + + def get_default_values(self): + """ + Overriding to make updating the defaults after instantiation of + the option parser possible, update_defaults() does the dirty work. + """ + if not self.process_default_values: + # Old, pre-Optik 1.5 behaviour. + return optparse.Values(self.defaults) + + defaults = self.update_defaults(self.defaults.copy()) # ours + for option in self._get_all_options(): + default = defaults.get(option.dest) + if isinstance(default, basestring): + opt_str = option.get_opt_string() + defaults[option.dest] = option.check_value(opt_str, default) + return optparse.Values(defaults) + + +def main(): + parser = ConfigOptionParser( + version=virtualenv_version, usage="%prog [OPTIONS] DEST_DIR", formatter=UpdatingDefaultsHelpFormatter() + ) + + parser.add_option( + "-v", "--verbose", action="count", dest="verbose", default=5 if DEBUG else 0, help="Increase verbosity." + ) + + parser.add_option("-q", "--quiet", action="count", dest="quiet", default=0, help="Decrease verbosity.") + + parser.add_option( + "-p", + "--python", + dest="python", + metavar="PYTHON_EXE", + help="The Python interpreter to use, e.g., --python=python3.5 will use the python3.5 " + "interpreter to create the new environment. The default is the interpreter that " + "virtualenv was installed with ({})".format(sys.executable), + ) + + parser.add_option( + "--clear", dest="clear", action="store_true", help="Clear out the non-root install and start from scratch." + ) + + parser.set_defaults(system_site_packages=False) + parser.add_option( + "--no-site-packages", + dest="system_site_packages", + action="store_false", + help="DEPRECATED. Retained only for backward compatibility. " + "Not having access to global site-packages is now the default behavior.", + ) + + parser.add_option( + "--system-site-packages", + dest="system_site_packages", + action="store_true", + help="Give the virtual environment access to the global site-packages.", + ) + + parser.add_option( + "--always-copy", + dest="symlink", + action="store_false", + default=True, + help="Always copy files rather than symlinking.", + ) + + parser.add_option( + "--relocatable", + dest="relocatable", + action="store_true", + help="Make an EXISTING virtualenv environment relocatable. " + "This fixes up scripts and makes all .pth files relative.", + ) + + parser.add_option( + "--no-setuptools", + dest="no_setuptools", + action="store_true", + help="Do not install setuptools in the new virtualenv.", + ) + + parser.add_option("--no-pip", dest="no_pip", action="store_true", help="Do not install pip in the new virtualenv.") + + parser.add_option( + "--no-wheel", dest="no_wheel", action="store_true", help="Do not install wheel in the new virtualenv." + ) + + parser.add_option( + "--extra-search-dir", + dest="search_dirs", + action="append", + metavar="DIR", + default=[], + help="Directory to look for setuptools/pip distributions in. " "This option can be used multiple times.", + ) + + parser.add_option( + "--download", + dest="download", + default=True, + action="store_true", + help="Download pre-installed packages from PyPI.", + ) + + parser.add_option( + "--no-download", + "--never-download", + dest="download", + action="store_false", + help="Do not download pre-installed packages from PyPI.", + ) + + parser.add_option("--prompt", dest="prompt", help="Provides an alternative prompt prefix for this environment.") + + parser.add_option( + "--setuptools", + dest="setuptools", + action="store_true", + help="DEPRECATED. Retained only for backward compatibility. This option has no effect.", + ) + + parser.add_option( + "--distribute", + dest="distribute", + action="store_true", + help="DEPRECATED. Retained only for backward compatibility. This option has no effect.", + ) + + parser.add_option( + "--unzip-setuptools", + action="store_true", + help="DEPRECATED. Retained only for backward compatibility. This option has no effect.", + ) + + if "extend_parser" in globals(): + # noinspection PyUnresolvedReferences + extend_parser(parser) # noqa: F821 + + options, args = parser.parse_args() + + global logger + + if "adjust_options" in globals(): + # noinspection PyUnresolvedReferences + adjust_options(options, args) # noqa: F821 + + verbosity = options.verbose - options.quiet + logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)]) + + if options.python and not os.environ.get("VIRTUALENV_INTERPRETER_RUNNING"): + env = os.environ.copy() + interpreter = resolve_interpreter(options.python) + if interpreter == sys.executable: + logger.warn("Already using interpreter {}".format(interpreter)) + else: + logger.notify("Running virtualenv with interpreter {}".format(interpreter)) + env["VIRTUALENV_INTERPRETER_RUNNING"] = "true" + file = __file__ + if file.endswith(".pyc"): + file = file[:-1] + elif IS_ZIPAPP: + file = HERE + sub_process_call = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env) + raise SystemExit(sub_process_call.wait()) + + if not args: + print("You must provide a DEST_DIR") + parser.print_help() + sys.exit(2) + if len(args) > 1: + print("There must be only one argument: DEST_DIR (you gave {})".format(" ".join(args))) + parser.print_help() + sys.exit(2) + + home_dir = args[0] + + if os.path.exists(home_dir) and os.path.isfile(home_dir): + logger.fatal("ERROR: File already exists and is not a directory.") + logger.fatal("Please provide a different path or delete the file.") + sys.exit(3) + + if os.environ.get("WORKING_ENV"): + logger.fatal("ERROR: you cannot run virtualenv while in a working env") + logger.fatal("Please deactivate your working env, then re-run this script") + sys.exit(3) + + if "PYTHONHOME" in os.environ: + logger.warn("PYTHONHOME is set. You *must* activate the virtualenv before using it") + del os.environ["PYTHONHOME"] + + if options.relocatable: + make_environment_relocatable(home_dir) + return + + with virtualenv_support_dirs() as search_dirs: + create_environment( + home_dir, + site_packages=options.system_site_packages, + clear=options.clear, + prompt=options.prompt, + search_dirs=search_dirs + options.search_dirs, + download=options.download, + no_setuptools=options.no_setuptools, + no_pip=options.no_pip, + no_wheel=options.no_wheel, + symlink=options.symlink, + ) + if "after_install" in globals(): + # noinspection PyUnresolvedReferences + after_install(options, home_dir) # noqa: F821 + + +def call_subprocess( + cmd, + show_stdout=True, + filter_stdout=None, + cwd=None, + raise_on_return_code=True, + extra_env=None, + remove_from_env=None, + stdin=None, +): + cmd_parts = [] + for part in cmd: + if len(part) > 45: + part = part[:20] + "..." + part[-20:] + if " " in part or "\n" in part or '"' in part or "'" in part: + part = '"{}"'.format(part.replace('"', '\\"')) + if hasattr(part, "decode"): + try: + part = part.decode(sys.getdefaultencoding()) + except UnicodeDecodeError: + part = part.decode(sys.getfilesystemencoding()) + cmd_parts.append(part) + cmd_desc = " ".join(cmd_parts) + if show_stdout: + stdout = None + else: + stdout = subprocess.PIPE + logger.debug("Running command {}".format(cmd_desc)) + if extra_env or remove_from_env: + env = os.environ.copy() + if extra_env: + env.update(extra_env) + if remove_from_env: + for var_name in remove_from_env: + env.pop(var_name, None) + else: + env = None + try: + proc = subprocess.Popen( + cmd, + stderr=subprocess.STDOUT, + stdin=None if stdin is None else subprocess.PIPE, + stdout=stdout, + cwd=cwd, + env=env, + ) + except Exception: + e = sys.exc_info()[1] + logger.fatal("Error {} while executing command {}".format(e, cmd_desc)) + raise + all_output = [] + if stdout is not None: + if stdin is not None: + with proc.stdin: + proc.stdin.write(stdin) + + encoding = sys.getdefaultencoding() + fs_encoding = sys.getfilesystemencoding() + with proc.stdout as stdout: + while 1: + line = stdout.readline() + try: + line = line.decode(encoding) + except UnicodeDecodeError: + line = line.decode(fs_encoding) + if not line: + break + line = line.rstrip() + all_output.append(line) + if filter_stdout: + level = filter_stdout(line) + if isinstance(level, tuple): + level, line = level + logger.log(level, line) + if not logger.stdout_level_matches(level): + logger.show_progress() + else: + logger.info(line) + else: + proc.communicate(stdin) + proc.wait() + if proc.returncode: + if raise_on_return_code: + if all_output: + logger.notify("Complete output from command {}:".format(cmd_desc)) + logger.notify("\n".join(all_output) + "\n----------------------------------------") + raise OSError("Command {} failed with error code {}".format(cmd_desc, proc.returncode)) + else: + logger.warn("Command {} had error code {}".format(cmd_desc, proc.returncode)) + return all_output + + +def filter_install_output(line): + if line.strip().startswith("running"): + return Logger.INFO + return Logger.DEBUG + + +def find_wheels(projects, search_dirs): + """Find wheels from which we can import PROJECTS. + + Scan through SEARCH_DIRS for a wheel for each PROJECT in turn. Return + a list of the first wheel found for each PROJECT + """ + + wheels = [] + + # Look through SEARCH_DIRS for the first suitable wheel. Don't bother + # about version checking here, as this is simply to get something we can + # then use to install the correct version. + for project in projects: + for dirname in search_dirs: + # This relies on only having "universal" wheels available. + # The pattern could be tightened to require -py2.py3-none-any.whl. + files = glob.glob(os.path.join(dirname, project + "-*.whl")) + if files: + wheels.append(os.path.abspath(files[0])) + break + else: + # We're out of luck, so quit with a suitable error + logger.fatal("Cannot find a wheel for {}".format(project)) + + return wheels + + +def install_wheel(project_names, py_executable, search_dirs=None, download=False): + if search_dirs is None: + search_dirs_context = virtualenv_support_dirs + else: + + @contextlib.contextmanager + def search_dirs_context(): + yield search_dirs + + with search_dirs_context() as search_dirs: + _install_wheel_with_search_dir(download, project_names, py_executable, search_dirs) + + +def _install_wheel_with_search_dir(download, project_names, py_executable, search_dirs): + wheels = find_wheels(["setuptools", "pip"], search_dirs) + python_path = os.pathsep.join(wheels) + + # PIP_FIND_LINKS uses space as the path separator and thus cannot have paths + # with spaces in them. Convert any of those to local file:// URL form. + try: + from urlparse import urljoin + from urllib import pathname2url + except ImportError: + from urllib.parse import urljoin + from urllib.request import pathname2url + + def space_path2url(p): + if " " not in p: + return p + return urljoin("file:", pathname2url(os.path.abspath(p))) + + find_links = " ".join(space_path2url(d) for d in search_dirs) + + extra_args = ["--ignore-installed"] + if DEBUG: + extra_args.append("-v") + if IS_JYTHON: + extra_args.append("--no-cache") + + config = _pip_config(py_executable, python_path) + defined_cert = bool(config.get("install.cert") or config.get(":env:.cert") or config.get("global.cert")) + + script = textwrap.dedent( + """ + import sys + import pkgutil + import tempfile + import os + + defined_cert = {defined_cert} + + try: + from pip._internal import main as _main + cert_data = pkgutil.get_data("pip._vendor.certifi", "cacert.pem") + except ImportError: + from pip import main as _main + cert_data = pkgutil.get_data("pip._vendor.requests", "cacert.pem") + except IOError: + cert_data = None + + if not defined_cert and cert_data is not None: + cert_file = tempfile.NamedTemporaryFile(delete=False) + cert_file.write(cert_data) + cert_file.close() + else: + cert_file = None + + try: + args = ["install"] + [{extra_args}] + if cert_file is not None: + args += ["--cert", cert_file.name] + args += sys.argv[1:] + + sys.exit(_main(args)) + finally: + if cert_file is not None: + os.remove(cert_file.name) + """.format( + defined_cert=defined_cert, extra_args=", ".join(repr(i) for i in extra_args) + ) + ).encode("utf8") + + cmd = [py_executable, "-"] + project_names + logger.start_progress("Installing {}...".format(", ".join(project_names))) + logger.indent += 2 + + env = { + "PYTHONPATH": python_path, + "JYTHONPATH": python_path, # for Jython < 3.x + "PIP_FIND_LINKS": find_links, + "PIP_USE_WHEEL": "1", + "PIP_ONLY_BINARY": ":all:", + "PIP_USER": "0", + "PIP_NO_INPUT": "1", + } + + if not download: + env["PIP_NO_INDEX"] = "1" + + try: + call_subprocess(cmd, show_stdout=False, extra_env=env, stdin=script) + finally: + logger.indent -= 2 + logger.end_progress() + + +def _pip_config(py_executable, python_path): + cmd = [py_executable, "-m", "pip", "config", "list"] + config = {} + for line in call_subprocess( + cmd, + show_stdout=False, + extra_env={"PYTHONPATH": python_path, "JYTHONPATH": python_path}, + remove_from_env=["PIP_VERBOSE", "PIP_QUIET"], + raise_on_return_code=False, + ): + key, _, value = line.partition("=") + if value: + config[key] = ast.literal_eval(value) + return config + + +def create_environment( + home_dir, + site_packages=False, + clear=False, + prompt=None, + search_dirs=None, + download=False, + no_setuptools=False, + no_pip=False, + no_wheel=False, + symlink=True, +): + """ + Creates a new environment in ``home_dir``. + + If ``site_packages`` is true, then the global ``site-packages/`` + directory will be on the path. + + If ``clear`` is true (default False) then the environment will + first be cleared. + """ + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) + + py_executable = os.path.abspath( + install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages=site_packages, clear=clear, symlink=symlink) + ) + + install_distutils(home_dir) + + to_install = [] + + if not no_setuptools: + to_install.append("setuptools") + + if not no_pip: + to_install.append("pip") + + if not no_wheel: + to_install.append("wheel") + + if to_install: + install_wheel(to_install, py_executable, search_dirs, download=download) + + install_activate(home_dir, bin_dir, prompt) + + install_python_config(home_dir, bin_dir, prompt) + + +def is_executable_file(fpath): + return os.path.isfile(fpath) and is_executable(fpath) + + +def path_locations(home_dir, dry_run=False): + """Return the path locations for the environment (where libraries are, + where scripts go, etc)""" + home_dir = os.path.abspath(home_dir) + lib_dir, inc_dir, bin_dir = None, None, None + # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its + # prefix arg is broken: http://bugs.python.org/issue3386 + if IS_WIN: + # Windows has lots of problems with executables with spaces in + # the name; this function will remove them (using the ~1 + # format): + if not dry_run: + mkdir(home_dir) + if " " in home_dir: + import ctypes + + get_short_path_name = ctypes.windll.kernel32.GetShortPathNameW + size = max(len(home_dir) + 1, 256) + buf = ctypes.create_unicode_buffer(size) + try: + # noinspection PyUnresolvedReferences + u = unicode + except NameError: + u = str + ret = get_short_path_name(u(home_dir), buf, size) + if not ret: + print('Error: the path "{}" has a space in it'.format(home_dir)) + print("We could not determine the short pathname for it.") + print("Exiting.") + sys.exit(3) + home_dir = str(buf.value) + lib_dir = join(home_dir, "Lib") + inc_dir = join(home_dir, "Include") + bin_dir = join(home_dir, "Scripts") + if IS_JYTHON: + lib_dir = join(home_dir, "Lib") + inc_dir = join(home_dir, "Include") + bin_dir = join(home_dir, "bin") + elif IS_PYPY: + lib_dir = home_dir + inc_dir = join(home_dir, "include") + bin_dir = join(home_dir, "bin") + elif not IS_WIN: + lib_dir = join(home_dir, "lib", PY_VERSION) + inc_dir = join(home_dir, "include", PY_VERSION + ABI_FLAGS) + bin_dir = join(home_dir, "bin") + return home_dir, lib_dir, inc_dir, bin_dir + + +def change_prefix(filename, dst_prefix): + prefixes = [sys.prefix] + + if IS_DARWIN: + prefixes.extend( + ( + os.path.join("/Library/Python", sys.version[:3], "site-packages"), + os.path.join(sys.prefix, "Extras", "lib", "python"), + os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"), + # Python 2.6 no-frameworks + os.path.join("~", ".local", "lib", "python", sys.version[:3], "site-packages"), + # System Python 2.7 on OSX Mountain Lion + os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages"), + ) + ) + + if hasattr(sys, "real_prefix"): + prefixes.append(sys.real_prefix) + if hasattr(sys, "base_prefix"): + prefixes.append(sys.base_prefix) + prefixes = list(map(os.path.expanduser, prefixes)) + prefixes = list(map(os.path.abspath, prefixes)) + # Check longer prefixes first so we don't split in the middle of a filename + prefixes = sorted(prefixes, key=len, reverse=True) + filename = os.path.abspath(filename) + # On Windows, make sure drive letter is uppercase + if IS_WIN and filename[0] in "abcdefghijklmnopqrstuvwxyz": + filename = filename[0].upper() + filename[1:] + for i, prefix in enumerate(prefixes): + if IS_WIN and prefix[0] in "abcdefghijklmnopqrstuvwxyz": + prefixes[i] = prefix[0].upper() + prefix[1:] + for src_prefix in prefixes: + if filename.startswith(src_prefix): + _, relative_path = filename.split(src_prefix, 1) + if src_prefix != os.sep: # sys.prefix == "/" + assert relative_path[0] == os.sep + relative_path = relative_path[1:] + return join(dst_prefix, relative_path) + assert False, "Filename {} does not start with any of these prefixes: {}".format(filename, prefixes) + + +def find_module_filename(modname): + + if sys.version_info < (3, 4): + # noinspection PyDeprecation + import imp + + try: + file_handler, filepath, _ = imp.find_module(modname) + except ImportError: + return None + else: + if file_handler is not None: + file_handler.close() + return filepath + else: + import importlib.util + + if sys.version_info < (3, 5): + + def find_spec(modname): + # noinspection PyDeprecation + loader = importlib.find_loader(modname) + if loader is None: + return None + else: + return importlib.util.spec_from_loader(modname, loader) + + else: + find_spec = importlib.util.find_spec + + spec = find_spec(modname) + if spec is None: + return None + if not os.path.exists(spec.origin): + # https://bitbucket.org/pypy/pypy/issues/2944/origin-for-several-builtin-modules + # on pypy3, some builtin modules have a bogus build-time file path, ignore them + return None + filepath = spec.origin + # https://www.python.org/dev/peps/pep-3147/#file guarantee to be non-cached + if os.path.basename(filepath) == "__init__.py": + filepath = os.path.dirname(filepath) + return filepath + + +def copy_required_modules(dst_prefix, symlink): + for modname in REQUIRED_MODULES: + if modname in sys.builtin_module_names: + logger.info("Ignoring built-in bootstrap module: %s" % modname) + continue + filename = find_module_filename(modname) + if filename is None: + logger.info("Cannot import bootstrap module: %s" % modname) + else: + # special-case custom readline.so on OS X, but not for pypy: + if ( + modname == "readline" + and sys.platform == "darwin" + and not (IS_PYPY or filename.endswith(join("lib-dynload", "readline.so"))) + ): + dst_filename = join(dst_prefix, "lib", "python{}".format(sys.version[:3]), "readline.so") + elif modname == "readline" and sys.platform == "win32": + # special-case for Windows, where readline is not a standard module, though it may have been installed + # in site-packages by a third-party package + dst_filename = None + else: + dst_filename = change_prefix(filename, dst_prefix) + if dst_filename is not None: + copyfile(filename, dst_filename, symlink) + if filename.endswith(".pyc"): + py_file = filename[:-1] + if os.path.exists(py_file): + copyfile(py_file, dst_filename[:-1], symlink) + + +def copy_required_files(src_dir, lib_dir, symlink): + if not os.path.isdir(src_dir): + return + for fn in os.listdir(src_dir): + bn = os.path.splitext(fn)[0] + if fn != "site-packages" and bn in REQUIRED_FILES: + copyfile(join(src_dir, fn), join(lib_dir, fn), symlink) + + +def copy_license(prefix, dst_prefix, lib_dir, symlink): + """Copy the license file so `license()` builtin works""" + for license_path in ( + # posix cpython + os.path.join(prefix, os.path.relpath(lib_dir, dst_prefix), "LICENSE.txt"), + # windows cpython + os.path.join(prefix, "LICENSE.txt"), + # pypy + os.path.join(prefix, "LICENSE"), + ): + if os.path.exists(license_path): + dest = subst_path(license_path, prefix, dst_prefix) + copyfile(license_path, dest, symlink) + return + logger.warn("No LICENSE.txt / LICENSE found in source") + + +def copy_include_dir(include_src, include_dest, symlink): + """Copy headers from *include_src* to *include_dest* symlinking if required""" + if not os.path.isdir(include_src): + return + # PyPy headers are located in ``pypy-dir/include`` and following code + # avoids making ``venv-dir/include`` symlink to it + if IS_PYPY: + for fn in os.listdir(include_src): + copyfile(join(include_src, fn), join(include_dest, fn), symlink) + else: + copyfile(include_src, include_dest, symlink) + + +def copy_tcltk(src, dest, symlink): + """ copy tcl/tk libraries on Windows (issue #93) """ + for lib_version in "8.5", "8.6": + for libname in "tcl", "tk": + src_dir = join(src, "tcl", libname + lib_version) + dest_dir = join(dest, "tcl", libname + lib_version) + # Only copy the dirs from the above combinations that exist + if os.path.exists(src_dir) and not os.path.exists(dest_dir): + copy_file_or_folder(src_dir, dest_dir, symlink) + + +def subst_path(prefix_path, prefix, home_dir): + prefix_path = os.path.normpath(prefix_path) + prefix = os.path.normpath(prefix) + home_dir = os.path.normpath(home_dir) + if not prefix_path.startswith(prefix): + logger.warn("Path not in prefix %r %r", prefix_path, prefix) + return + return prefix_path.replace(prefix, home_dir, 1) + + +def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, symlink=True): + """Install just the base environment, no distutils patches etc""" + if sys.executable.startswith(bin_dir): + print("Please use the *system* python to run this script") + return + + if clear: + rm_tree(lib_dir) + # FIXME: why not delete it? + # Maybe it should delete everything with #!/path/to/venv/python in it + logger.notify("Not deleting %s", bin_dir) + + if hasattr(sys, "real_prefix"): + logger.notify("Using real prefix %r", sys.real_prefix) + prefix = sys.real_prefix + elif hasattr(sys, "base_prefix"): + logger.notify("Using base prefix %r", sys.base_prefix) + prefix = sys.base_prefix + else: + prefix = sys.prefix + prefix = os.path.abspath(prefix) + mkdir(lib_dir) + fix_lib64(lib_dir, symlink) + stdlib_dirs = [os.path.dirname(os.__file__)] + if IS_WIN: + stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), "DLLs")) + elif IS_DARWIN: + stdlib_dirs.append(join(stdlib_dirs[0], "site-packages")) + if hasattr(os, "symlink"): + logger.info("Symlinking Python bootstrap modules") + else: + logger.info("Copying Python bootstrap modules") + logger.indent += 2 + try: + # copy required files... + for stdlib_dir in stdlib_dirs: + copy_required_files(stdlib_dir, lib_dir, symlink) + # ...and modules + copy_required_modules(home_dir, symlink) + copy_license(prefix, home_dir, lib_dir, symlink) + finally: + logger.indent -= 2 + # ...copy tcl/tk + if IS_WIN: + copy_tcltk(prefix, home_dir, symlink) + mkdir(join(lib_dir, "site-packages")) + import site + + site_filename = site.__file__ + if site_filename.endswith(".pyc") or site_filename.endswith(".pyo"): + site_filename = site_filename[:-1] + elif site_filename.endswith("$py.class"): + site_filename = site_filename.replace("$py.class", ".py") + site_filename_dst = change_prefix(site_filename, home_dir) + site_dir = os.path.dirname(site_filename_dst) + writefile(site_filename_dst, SITE_PY) + writefile(join(site_dir, "orig-prefix.txt"), prefix) + site_packages_filename = join(site_dir, "no-global-site-packages.txt") + if not site_packages: + writefile(site_packages_filename, "") + + if IS_PYPY or IS_WIN: + standard_lib_include_dir = join(prefix, "include") + else: + standard_lib_include_dir = join(prefix, "include", PY_VERSION + ABI_FLAGS) + if os.path.exists(standard_lib_include_dir): + copy_include_dir(standard_lib_include_dir, inc_dir, symlink) + else: + logger.debug("No include dir %s", standard_lib_include_dir) + + platform_include_dir = distutils.sysconfig.get_python_inc(plat_specific=1) + if platform_include_dir != standard_lib_include_dir: + platform_include_dest = distutils.sysconfig.get_python_inc(plat_specific=1, prefix=home_dir) + if platform_include_dir == platform_include_dest: + # Do platinc_dest manually due to a CPython bug; + # not http://bugs.python.org/issue3386 but a close cousin + platform_include_dest = subst_path(platform_include_dir, prefix, home_dir) + if platform_include_dest: + # PyPy's stdinc_dir and prefix are relative to the original binary + # (traversing virtualenvs), whereas the platinc_dir is relative to + # the inner virtualenv and ignores the prefix argument. + # This seems more evolved than designed. + copy_include_dir(platform_include_dir, platform_include_dest, symlink) + + # pypy never uses exec_prefix, just ignore it + if os.path.realpath(sys.exec_prefix) != os.path.realpath(prefix) and not IS_PYPY: + if IS_WIN: + exec_dir = join(sys.exec_prefix, "lib") + elif IS_JYTHON: + exec_dir = join(sys.exec_prefix, "Lib") + else: + exec_dir = join(sys.exec_prefix, "lib", PY_VERSION) + copy_required_files(exec_dir, lib_dir, symlink) + + if IS_JYTHON: + # Jython has either jython-dev.jar and javalib/ dir, or just + # jython.jar + for name in "jython-dev.jar", "javalib", "jython.jar": + src = join(prefix, name) + if os.path.exists(src): + copyfile(src, join(home_dir, name), symlink) + # XXX: registry should always exist after Jython 2.5rc1 + src = join(prefix, "registry") + if os.path.exists(src): + copyfile(src, join(home_dir, "registry"), symlink=False) + copyfile(join(prefix, "cachedir"), join(home_dir, "cachedir"), symlink=False) + + mkdir(bin_dir) + py_executable = join(bin_dir, os.path.basename(sys.executable)) + if "Python.framework" in prefix: + # OS X framework builds cause validation to break + # https://github.com/pypa/virtualenv/issues/322 + if os.environ.get("__PYVENV_LAUNCHER__"): + del os.environ["__PYVENV_LAUNCHER__"] + if re.search(r"/Python(?:-32|-64)*$", py_executable): + # The name of the python executable is not quite what + # we want, rename it. + py_executable = os.path.join(os.path.dirname(py_executable), "python") + + logger.notify("New %s executable in %s", EXPECTED_EXE, py_executable) + pc_build_dir = os.path.dirname(sys.executable) + pyd_pth = os.path.join(lib_dir, "site-packages", "virtualenv_builddir_pyd.pth") + if IS_WIN and os.path.exists(os.path.join(pc_build_dir, "build.bat")): + logger.notify("Detected python running from build directory %s", pc_build_dir) + logger.notify("Writing .pth file linking to build directory for *.pyd files") + writefile(pyd_pth, pc_build_dir) + else: + if os.path.exists(pyd_pth): + logger.info("Deleting %s (not Windows env or not build directory python)", pyd_pth) + os.unlink(pyd_pth) + + if sys.executable != py_executable: + # FIXME: could I just hard link? + executable = sys.executable + shutil.copyfile(executable, py_executable) + make_exe(py_executable) + if IS_WIN or IS_CYGWIN: + python_w = os.path.join(os.path.dirname(sys.executable), "pythonw.exe") + if os.path.exists(python_w): + logger.info("Also created pythonw.exe") + shutil.copyfile(python_w, os.path.join(os.path.dirname(py_executable), "pythonw.exe")) + python_d = os.path.join(os.path.dirname(sys.executable), "python_d.exe") + python_d_dest = os.path.join(os.path.dirname(py_executable), "python_d.exe") + if os.path.exists(python_d): + logger.info("Also created python_d.exe") + shutil.copyfile(python_d, python_d_dest) + elif os.path.exists(python_d_dest): + logger.info("Removed python_d.exe as it is no longer at the source") + os.unlink(python_d_dest) + + # we need to copy the DLL to enforce that windows will load the correct one. + # may not exist if we are cygwin. + if IS_PYPY: + py_executable_dll_s = [("libpypy-c.dll", "libpypy_d-c.dll")] + else: + py_executable_dll_s = [ + ("python{}.dll".format(sys.version_info[0]), "python{}_d.dll".format(sys.version_info[0])), + ( + "python{}{}.dll".format(sys.version_info[0], sys.version_info[1]), + "python{}{}_d.dll".format(sys.version_info[0], sys.version_info[1]), + ), + ] + + for py_executable_dll, py_executable_dll_d in py_executable_dll_s: + python_dll = os.path.join(os.path.dirname(sys.executable), py_executable_dll) + python_dll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d) + python_dll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d) + if os.path.exists(python_dll): + logger.info("Also created %s", py_executable_dll) + shutil.copyfile(python_dll, os.path.join(os.path.dirname(py_executable), py_executable_dll)) + if os.path.exists(python_dll_d): + logger.info("Also created %s", py_executable_dll_d) + shutil.copyfile(python_dll_d, python_dll_d_dest) + elif os.path.exists(python_dll_d_dest): + logger.info("Removed %s as the source does not exist", python_dll_d_dest) + os.unlink(python_dll_d_dest) + if IS_PYPY: + # make a symlink python --> pypy-c + python_executable = os.path.join(os.path.dirname(py_executable), "python") + if sys.platform in ("win32", "cygwin"): + python_executable += ".exe" + logger.info("Also created executable %s", python_executable) + copyfile(py_executable, python_executable, symlink) + + if IS_WIN: + for name in ["libexpat.dll", "libeay32.dll", "ssleay32.dll", "sqlite3.dll", "tcl85.dll", "tk85.dll"]: + src = join(prefix, name) + if os.path.exists(src): + copyfile(src, join(bin_dir, name), symlink) + + for d in sys.path: + if d.endswith("lib_pypy"): + break + else: + logger.fatal("Could not find lib_pypy in sys.path") + raise SystemExit(3) + logger.info("Copying lib_pypy") + copyfile(d, os.path.join(home_dir, "lib_pypy"), symlink) + + if os.path.splitext(os.path.basename(py_executable))[0] != EXPECTED_EXE: + secondary_exe = os.path.join(os.path.dirname(py_executable), EXPECTED_EXE) + py_executable_ext = os.path.splitext(py_executable)[1] + if py_executable_ext.lower() == ".exe": + # python2.4 gives an extension of '.4' :P + secondary_exe += py_executable_ext + if os.path.exists(secondary_exe): + logger.warn( + "Not overwriting existing {} script {} (you must use {})".format( + EXPECTED_EXE, secondary_exe, py_executable + ) + ) + else: + logger.notify("Also creating executable in %s", secondary_exe) + shutil.copyfile(sys.executable, secondary_exe) + make_exe(secondary_exe) + + if ".framework" in prefix: + original_python = None + if "Python.framework" in prefix: + logger.debug("MacOSX Python framework detected") + # Make sure we use the embedded interpreter inside + # the framework, even if sys.executable points to + # the stub executable in ${sys.prefix}/bin + # See http://groups.google.com/group/python-virtualenv/ + # browse_thread/thread/17cab2f85da75951 + original_python = os.path.join(prefix, "Resources/Python.app/Contents/MacOS/Python") + if "EPD" in prefix: + logger.debug("EPD framework detected") + original_python = os.path.join(prefix, "bin/python") + shutil.copy(original_python, py_executable) + + # Copy the framework's dylib into the virtual + # environment + virtual_lib = os.path.join(home_dir, ".Python") + + if os.path.exists(virtual_lib): + os.unlink(virtual_lib) + copyfile(os.path.join(prefix, "Python"), virtual_lib, symlink) + + # And then change the install_name of the copied python executable + # noinspection PyBroadException + try: + mach_o_change(py_executable, os.path.join(prefix, "Python"), "@executable_path/../.Python") + except Exception: + e = sys.exc_info()[1] + logger.warn("Could not call mach_o_change: %s. " "Trying to call install_name_tool instead.", e) + try: + call_subprocess( + [ + "install_name_tool", + "-change", + os.path.join(prefix, "Python"), + "@executable_path/../.Python", + py_executable, + ] + ) + except Exception: + logger.fatal("Could not call install_name_tool -- you must " "have Apple's development tools installed") + raise + + if not IS_WIN: + # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist + py_exe_version_major = "python{}".format(sys.version_info[0]) + py_exe_version_major_minor = "python{}.{}".format(sys.version_info[0], sys.version_info[1]) + py_exe_no_version = "python" + required_symlinks = [py_exe_no_version, py_exe_version_major, py_exe_version_major_minor] + + py_executable_base = os.path.basename(py_executable) + + if py_executable_base in required_symlinks: + # Don't try to symlink to yourself. + required_symlinks.remove(py_executable_base) + + for pth in required_symlinks: + full_pth = join(bin_dir, pth) + if os.path.exists(full_pth): + os.unlink(full_pth) + if symlink: + os.symlink(py_executable_base, full_pth) + else: + copyfile(py_executable, full_pth, symlink) + + cmd = [ + py_executable, + "-c", + "import sys;out=sys.stdout;" 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))', + ] + logger.info('Testing executable with %s %s "%s"', *cmd) + try: + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) + proc_stdout, proc_stderr = proc.communicate() + except OSError: + e = sys.exc_info()[1] + if e.errno == errno.EACCES: + logger.fatal("ERROR: The executable {} could not be run: {}".format(py_executable, e)) + sys.exit(100) + else: + raise e + + proc_stdout = proc_stdout.strip().decode("utf-8") + # normalize paths using realpath to ensure that a virtualenv correctly identifies itself even + # when addressed over a symlink + proc_stdout = os.path.normcase(os.path.realpath(proc_stdout)) + norm_home_dir = os.path.normcase(os.path.realpath(home_dir)) + if hasattr(norm_home_dir, "decode"): + norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding()) + if proc_stdout != norm_home_dir: + logger.fatal("ERROR: The executable %s is not functioning", py_executable) + logger.fatal("ERROR: It thinks sys.prefix is {!r} (should be {!r})".format(proc_stdout, norm_home_dir)) + logger.fatal("ERROR: virtualenv is not compatible with this system or executable") + if IS_WIN: + logger.fatal( + "Note: some Windows users have reported this error when they " + 'installed Python for "Only this user" or have multiple ' + "versions of Python installed. Copying the appropriate " + "PythonXX.dll to the virtualenv Scripts/ directory may fix " + "this problem." + ) + sys.exit(100) + else: + logger.info("Got sys.prefix result: %r", proc_stdout) + + pydistutils = os.path.expanduser("~/.pydistutils.cfg") + if os.path.exists(pydistutils): + logger.notify("Please make sure you remove any previous custom paths from " "your %s file.", pydistutils) + # FIXME: really this should be calculated earlier + + fix_local_scheme(home_dir, symlink) + + if site_packages: + if os.path.exists(site_packages_filename): + logger.info("Deleting %s", site_packages_filename) + os.unlink(site_packages_filename) + + return py_executable + + +def install_activate(home_dir, bin_dir, prompt=None): + if IS_WIN or IS_JYTHON and getattr(os, "_name", None) == "nt": + files = {"activate.bat": ACTIVATE_BAT, "deactivate.bat": DEACTIVATE_BAT, "activate.ps1": ACTIVATE_PS} + + # MSYS needs paths of the form /c/path/to/file + drive, tail = os.path.splitdrive(home_dir.replace(os.sep, "/")) + home_dir_msys = (drive and "/{}{}" or "{}{}").format(drive[:1], tail) + + # Run-time conditional enables (basic) Cygwin compatibility + home_dir_sh = """$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '{}'; else echo '{}'; fi;)""".format( + home_dir, home_dir_msys + ) + files["activate"] = ACTIVATE_SH.replace("__VIRTUAL_ENV__", home_dir_sh) + + else: + files = { + "activate": ACTIVATE_SH, + "activate.fish": ACTIVATE_FISH, + "activate.csh": ACTIVATE_CSH, + "activate.ps1": ACTIVATE_PS, + } + files["activate_this.py"] = ACTIVATE_THIS + + if sys.version_info >= (3, 4): + # Add xonsh support + files["activate.xsh"] = ACTIVATE_XSH + + install_files(home_dir, bin_dir, prompt, files) + + +def install_files(home_dir, bin_dir, prompt, files): + if hasattr(home_dir, "decode"): + home_dir = home_dir.decode(sys.getfilesystemencoding()) + virtualenv_name = os.path.basename(home_dir) + for name, content in files.items(): + content = content.replace("__VIRTUAL_PROMPT__", prompt or "") + content = content.replace("__VIRTUAL_WINPROMPT__", prompt or "({})".format(virtualenv_name)) + content = content.replace("__VIRTUAL_ENV__", home_dir) + content = content.replace("__VIRTUAL_NAME__", virtualenv_name) + content = content.replace("__BIN_NAME__", os.path.basename(bin_dir)) + content = content.replace("__PATH_SEP__", os.pathsep) + writefile(os.path.join(bin_dir, name), content) + + +def install_python_config(home_dir, bin_dir, prompt=None): + if sys.platform == "win32" or IS_JYTHON and getattr(os, "_name", None) == "nt": + files = {} + else: + files = {"python-config": PYTHON_CONFIG} + install_files(home_dir, bin_dir, prompt, files) + for name, _ in files.items(): + make_exe(os.path.join(bin_dir, name)) + + +def install_distutils(home_dir): + distutils_path = change_prefix(distutils.__path__[0], home_dir) + mkdir(distutils_path) + # FIXME: maybe this prefix setting should only be put in place if + # there's a local distutils.cfg with a prefix setting? + # FIXME: this is breaking things, removing for now: + # distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" home_dir + writefile(os.path.join(distutils_path, "__init__.py"), DISTUTILS_INIT) + writefile(os.path.join(distutils_path, "distutils.cfg"), DISTUTILS_CFG, overwrite=False) + + +def fix_local_scheme(home_dir, symlink=True): + """ + Platforms that use the "posix_local" install scheme (like Ubuntu with + Python 2.7) need to be given an additional "local" location, sigh. + """ + try: + import sysconfig + except ImportError: + pass + else: + # noinspection PyProtectedMember + if sysconfig._get_default_scheme() == "posix_local": + local_path = os.path.join(home_dir, "local") + if not os.path.exists(local_path): + os.mkdir(local_path) + for subdir_name in os.listdir(home_dir): + if subdir_name == "local": + continue + copyfile( + os.path.abspath(os.path.join(home_dir, subdir_name)), + os.path.join(local_path, subdir_name), + symlink, + ) + + +def fix_lib64(lib_dir, symlink=True): + """ + Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y + instead of lib/pythonX.Y. If this is such a platform we'll just create a + symlink so lib64 points to lib + """ + # PyPy's library path scheme is not affected by this. + # Return early or we will die on the following assert. + if IS_PYPY: + logger.debug("PyPy detected, skipping lib64 symlinking") + return + # Check we have a lib64 library path + if not [p for p in distutils.sysconfig.get_config_vars().values() if isinstance(p, basestring) and "lib64" in p]: + return + + logger.debug("This system uses lib64; symlinking lib64 to lib") + + assert os.path.basename(lib_dir) == "python{}".format(sys.version[:3]), "Unexpected python lib dir: {!r}".format( + lib_dir + ) + lib_parent = os.path.dirname(lib_dir) + top_level = os.path.dirname(lib_parent) + lib_dir = os.path.join(top_level, "lib") + lib64_link = os.path.join(top_level, "lib64") + assert os.path.basename(lib_parent) == "lib", "Unexpected parent dir: {!r}".format(lib_parent) + if os.path.lexists(lib64_link): + return + if symlink: + os.symlink("lib", lib64_link) + else: + copyfile(lib_dir, lib64_link, symlink=False) + + +def resolve_interpreter(exe): + """ + If the executable given isn't an absolute path, search $PATH for the interpreter + """ + # If the "executable" is a version number, get the installed executable for + # that version + orig_exe = exe + python_versions = get_installed_pythons() + if exe in python_versions: + exe = python_versions[exe] + + if os.path.abspath(exe) != exe: + exe = distutils.spawn.find_executable(exe) or exe + if not os.path.exists(exe): + logger.fatal("The path {} (from --python={}) does not exist".format(exe, orig_exe)) + raise SystemExit(3) + if not is_executable(exe): + logger.fatal("The path {} (from --python={}) is not an executable file".format(exe, orig_exe)) + raise SystemExit(3) + return exe + + +def is_executable(exe): + """Checks a file is executable""" + return os.path.isfile(exe) and os.access(exe, os.X_OK) + + +# Relocating the environment: +def make_environment_relocatable(home_dir): + """ + Makes the already-existing environment use relative paths, and takes out + the #!-based environment selection in scripts. + """ + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) + activate_this = os.path.join(bin_dir, "activate_this.py") + if not os.path.exists(activate_this): + logger.fatal( + "The environment doesn't have a file %s -- please re-run virtualenv " "on this environment to update it", + activate_this, + ) + fixup_scripts(home_dir, bin_dir) + fixup_pth_and_egg_link(home_dir) + # FIXME: need to fix up distutils.cfg + + +OK_ABS_SCRIPTS = [ + "python", + "python{}".format(sys.version[:3]), + "activate", + "activate.bat", + "activate_this.py", + "activate.fish", + "activate.csh", + "activate.xsh", +] + + +def fixup_scripts(_, bin_dir): + if IS_WIN: + new_shebang_args = ("{} /c".format(os.path.normcase(os.environ.get("COMSPEC", "cmd.exe"))), "", ".exe") + else: + new_shebang_args = ("/usr/bin/env", sys.version[:3], "") + + # This is what we expect at the top of scripts: + shebang = "#!{}".format( + os.path.normcase(os.path.join(os.path.abspath(bin_dir), "python{}".format(new_shebang_args[2]))) + ) + # This is what we'll put: + new_shebang = "#!{} python{}{}".format(*new_shebang_args) + + for filename in os.listdir(bin_dir): + filename = os.path.join(bin_dir, filename) + if not os.path.isfile(filename): + # ignore child directories, e.g. .svn ones. + continue + with open(filename, "rb") as f: + try: + lines = f.read().decode("utf-8").splitlines() + except UnicodeDecodeError: + # This is probably a binary program instead + # of a script, so just ignore it. + continue + if not lines: + logger.warn("Script %s is an empty file", filename) + continue + + old_shebang = lines[0].strip() + old_shebang = old_shebang[0:2] + os.path.normcase(old_shebang[2:]) + + if not old_shebang.startswith(shebang): + if os.path.basename(filename) in OK_ABS_SCRIPTS: + logger.debug("Cannot make script %s relative", filename) + elif lines[0].strip() == new_shebang: + logger.info("Script %s has already been made relative", filename) + else: + logger.warn( + "Script %s cannot be made relative (it's not a normal script that starts with %s)", + filename, + shebang, + ) + continue + logger.notify("Making script %s relative", filename) + script = relative_script([new_shebang] + lines[1:]) + with open(filename, "wb") as f: + f.write("\n".join(script).encode("utf-8")) + + +def relative_script(lines): + """Return a script that'll work in a relocatable environment.""" + activate = ( + "import os; " + "activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); " + "exec(compile(open(activate_this).read(), activate_this, 'exec'), { '__file__': activate_this}); " + "del os, activate_this" + ) + # Find the last future statement in the script. If we insert the activation + # line before a future statement, Python will raise a SyntaxError. + activate_at = None + for idx, line in reversed(list(enumerate(lines))): + if line.split()[:3] == ["from", "__future__", "import"]: + activate_at = idx + 1 + break + if activate_at is None: + # Activate after the shebang. + activate_at = 1 + return lines[:activate_at] + ["", activate, ""] + lines[activate_at:] + + +def fixup_pth_and_egg_link(home_dir, sys_path=None): + """Makes .pth and .egg-link files use relative paths""" + home_dir = os.path.normcase(os.path.abspath(home_dir)) + if sys_path is None: + sys_path = sys.path + for a_path in sys_path: + if not a_path: + a_path = "." + if not os.path.isdir(a_path): + continue + a_path = os.path.normcase(os.path.abspath(a_path)) + if not a_path.startswith(home_dir): + logger.debug("Skipping system (non-environment) directory %s", a_path) + continue + for filename in os.listdir(a_path): + filename = os.path.join(a_path, filename) + if filename.endswith(".pth"): + if not os.access(filename, os.W_OK): + logger.warn("Cannot write .pth file %s, skipping", filename) + else: + fixup_pth_file(filename) + if filename.endswith(".egg-link"): + if not os.access(filename, os.W_OK): + logger.warn("Cannot write .egg-link file %s, skipping", filename) + else: + fixup_egg_link(filename) + + +def fixup_pth_file(filename): + lines = [] + with open(filename) as f: + prev_lines = f.readlines() + for line in prev_lines: + line = line.strip() + if not line or line.startswith("#") or line.startswith("import ") or os.path.abspath(line) != line: + lines.append(line) + else: + new_value = make_relative_path(filename, line) + if line != new_value: + logger.debug("Rewriting path {} as {} (in {})".format(line, new_value, filename)) + lines.append(new_value) + if lines == prev_lines: + logger.info("No changes to .pth file %s", filename) + return + logger.notify("Making paths in .pth file %s relative", filename) + with open(filename, "w") as f: + f.write("\n".join(lines) + "\n") + + +def fixup_egg_link(filename): + with open(filename) as f: + link = f.readline().strip() + if os.path.abspath(link) != link: + logger.debug("Link in %s already relative", filename) + return + new_link = make_relative_path(filename, link) + logger.notify("Rewriting link {} in {} as {}".format(link, filename, new_link)) + with open(filename, "w") as f: + f.write(new_link) + + +def make_relative_path(source, dest, dest_is_directory=True): + """ + Make a filename relative, where the filename is dest, and it is + being referred to from the filename source. + + >>> make_relative_path('/usr/share/something/a-file.pth', + ... '/usr/share/another-place/src/Directory') + '../another-place/src/Directory' + >>> make_relative_path('/usr/share/something/a-file.pth', + ... '/home/user/src/Directory') + '../../../home/user/src/Directory' + >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/') + './' + """ + source = os.path.dirname(source) + if not dest_is_directory: + dest_filename = os.path.basename(dest) + dest = os.path.dirname(dest) + else: + dest_filename = None + dest = os.path.normpath(os.path.abspath(dest)) + source = os.path.normpath(os.path.abspath(source)) + dest_parts = dest.strip(os.path.sep).split(os.path.sep) + source_parts = source.strip(os.path.sep).split(os.path.sep) + while dest_parts and source_parts and dest_parts[0] == source_parts[0]: + dest_parts.pop(0) + source_parts.pop(0) + full_parts = [".."] * len(source_parts) + dest_parts + if not dest_is_directory and dest_filename is not None: + full_parts.append(dest_filename) + if not full_parts: + # Special case for the current directory (otherwise it'd be '') + return "./" + return os.path.sep.join(full_parts) + + +FILE_PATH = __file__ if os.path.isabs(__file__) else os.path.join(os.getcwd(), __file__) + + +# Bootstrap script creation: +def create_bootstrap_script(extra_text, python_version=""): + """ + Creates a bootstrap script, which is like this script but with + extend_parser, adjust_options, and after_install hooks. + + This returns a string that (written to disk of course) can be used + as a bootstrap script with your own customizations. The script + will be the standard virtualenv.py script, with your extra text + added (your extra text should be Python code). + + If you include these functions, they will be called: + + ``extend_parser(optparse_parser)``: + You can add or remove options from the parser here. + + ``adjust_options(options, args)``: + You can change options here, or change the args (if you accept + different kinds of arguments, be sure you modify ``args`` so it is + only ``[DEST_DIR]``). + + ``after_install(options, home_dir)``: + + After everything is installed, this function is called. This + is probably the function you are most likely to use. An + example would be:: + + def after_install(options, home_dir): + subprocess.call([join(home_dir, 'bin', 'easy_install'), + 'MyPackage']) + subprocess.call([join(home_dir, 'bin', 'my-package-script'), + 'setup', home_dir]) + + This example immediately installs a package, and runs a setup + script from that package. + + If you provide something like ``python_version='2.5'`` then the + script will start with ``#!/usr/bin/env python2.5`` instead of + ``#!/usr/bin/env python``. You can use this when the script must + be run with a particular Python version. + """ + filename = FILE_PATH + if filename.endswith(".pyc"): + filename = filename[:-1] + with codecs.open(filename, "r", encoding="utf-8") as f: + content = f.read() + py_exe = "python{}".format(python_version) + content = "#!/usr/bin/env {}\n# WARNING: This file is generated\n{}".format(py_exe, content) + # we build the string as two, to avoid replacing here, but yes further done + return content.replace("# EXTEND - " "bootstrap here", extra_text) + + +# EXTEND - bootstrap here + + +def convert(s): + b = base64.b64decode(s.encode("ascii")) + return zlib.decompress(b).decode("utf-8") + + +# file site.py +SITE_PY = convert( + """ +eJy1Pf1z2zaWv+uvQOnJiEplOnHaXNepc+MkTus7N/HG6WxuXZ+OkiCJNUWqBGlZ2+n+7fc+ABAg +Kdm+7Wk6qUQCDw8P7xsPcBAEJ6uVzKZimU+rVAol42KyEKu4XCgxywtRLpJiur+Ki3IDTyc38Vwq +UeZCbVSEraJe7+m/+Ok9FZ8XiTIowLe4KvNlXCaTOE03Ilmu8qKUUzGtiiSbiyRLyiROk39AizyL +xNN/HYPeWSZg5mkiC3ErCwVwlchn4mJTLvJMhNUK5/w8+jZ+MRgKNSmSVQkNCo0zUGQRl71Myimg +CS0rBaRMSrmvVnKSzJKJbbjOq3QqVmk8keJ//oenRk37/Z7Kl3K9kIUUGSADMCXAWiEe8DUpxCSf +ykiIN3IS4wD8vCZWj6ENcc0UkjHLRZpnc5hTJidSqbjYiHBclQSIUBbTHHBKAIMySdPeOi9u1ACW +lNZjDY9EzOzhT4bZA+aJ47c5B3D8mPV+zpK7IcMG7kFw5YLZppCz5E7ECBZ+yjs5GelnYTIT02Q2 +Axpk5QCb9BgBJdJkfLCi5fher9DrA8LKcmUMY0hEmRvzS+oR9c5KEacK2LZaIY0UYf5OjpM4A2pk +tzAcQASS9rrGmSaqtOPQ7EQOAApcxxKkZKlEuIyTDJj1p3hCaP8tyab5Wg2IArBaSvxaqdKdf9hB +AGjtEGDYw8Uyq1llaXIj080AEPgM2BdSVWmJAjFNCjkp8yKRigAAahsh7wDpoYgLqUnInGnkdkj0 +J5okGS4sChgKPL5EksySeVWQhIlZApwLXPH+4yfx7vTN2ckHzWMGGMvsfAk4AxRaaAcnGEAcVKo4 +SHMQ6Kh3jv8T8XSKQjbH8QGvusHBvSvdC2Huq6jZx1lwILteXD0MzLEEZUJj9ajf79BlqBZAnz/u +We9e72QbVWji/G29yEEms3gpxSJm/kLO6H2v4byOVuXiFXCDQjglkErh4iCCCcIDkrg0C/NMihWw +WJpkctADCo2prb+KwAof8myf1rrBCQCh6GXw0nk2oBEzCRNtw3qF+sI03tDMdJOeXedlXpDiAP7P +JqSL0ji7IRwVMRR/G8t5kmWIEPJCr7/Xp4HVTQKcOI3EObUivWAaiT5rL26JIlEBLyHTAU/Ku3i5 +SuWQxRd16241QoPJUpi1TpnjoGVJ6pVWrZ5qJ+8dRl8aXEdolotCAvBq7AndLM+HYgw6m7BZxUsW +r3KdE+f0OuSJOiFPUEvoi9+BoidKVUtpXyKvgGYhhurN8jTN10Cyo15PiD1sZIyyz5zwFt7BvwAX +/01lOVn0es5IFrAGhchvA4VAwCTITHO1RsLjNs3KTSWTZKwp8mIqCxrqYcQ+YMQf2Bjn2vuQl9qo +8XRxlfNlUqJKGmuTmbDFy/ol68dXPG+YBlhuRTQzTWs6LXF66WoRj6VxScZyhpKgF+mVXXYYs9cx +JtniUizZysA7IItM2IJ0KxZUOrNSkhMAMFj44ixZVSk1UshgIoaBliuCv4zRpOfaWQL2ZrPcQ4XE +5nsC9gdw+weI0XqRAH0mAAE0DGopWL5xUhboINT6qOcbfdOfxwdOPZtp28RDzuIk1VY+znpn9PC0 +KEh8J3KFvYaaGApmmJXo2s0zoCOKeRAEPe3AiFyZb8BIvV5ZbI6AF4QZaDQaVwlavtEIbb3+oXo8 +jHBG9rrZdhYeqAjT6QOQyekyK/IlvraTuwRtAmNhj96euCA1I9lD9ljxFdLP1ekr0xSNt8PPAhVR +7+LT6fuzL6eX4lhc1Tpt2FRo1zDmaRYDX5NJAK5qDFsrM2iJmi9B5Sfeg30nrgCDRr1JfmVcVsC8 +gPrnoqLXMI2J97J3+uHkzfnp6OfL00+jy7PPp4AgGBrZ26Mpo32swGNUEUgHsOVURdrA9lo96MGb +k0v7oDdK1OjlN8Bv8CScyxK4uAhhxkMRLOM7BRwaDKnpAHFsNQATHgwG4rU4FE+fiheHBG+1WW0A +HFhepzE+HGmjPkqyWR4MqPGv7NUfs57SLtzV0TfX4vhYBL/Gt3HQAzeqbspM8RNJ1OfNSkLXEv4X +5mrQ6/WmcgbidyNRSMOn5BsPuAesCjTNta3+NU8y854Z0x2DdEhIPQCJ0WiSxkph49EoEETzImJP +GkUshBarjdtmoMfETyFhETPsMsR/OnCJx9QPx2Nc3C6mEcjmchIrya14otBxNEINNRqFekQQXRIP +cK9Y6fSFaYIaqkjAiyU2Q401VnmKP3EAlHmSNgykUCfieuhAKbqN00qq0JkVkCts0Au1aqKI98Af +CcHs1os0IPYxHAGvgGRpDmqyQGrVYPGzB/4MqCMTpGEgx7EVkwlx+w+OJGhYcCn7qM6VakBh7Scu +Ti/Ei2eH++iuQEw5tfTwmqMFTrJK2oczWCDD7owv9zLi4FJihnoUnx7thrmM7Fq0V39mVrWQy/xW +TgFd5E5nYcUnegOhN0xkEsPCgeImg88q0jiGMQaaPH0QBXQOgHxLgmKW3Kz2Hkf7MlOgaDhyJlrr +sJ5t3arIbxP0JsYb/RKMIShDNInGc+k5K+fxFdo8kH9wczMk1Vr2Qd0VFXukhDeCRHswrRVnRODO +URNf09ebLF9nIw51j1GphgPLrShMml+xQb0Ge+I9WBlAMofIrSYaQwGfXqA87QPyMH2YLlCWggcA +BJZcUTzmwDKxHE2Rw0IcFmEMXgkS2EKiQ3BrhqBYyhDDgURvI/vAaAaEBJOz2suqA81lKF+mGQzs +kMRnu/OIY0wfQIOKEZjFUEPjRoZ+V0egesW5q4icfj00uV++fGG+UQvKoCBmY5w1+gszsobRagOW +MwFFYHwuzscQH6zBfQUwldK8KfYvRb5ifwsW9EJLNxh6iN/KcnV0cLBeryOdP8iL+YGaHXz73cuX +3z1jPTidEgPBfBxx0cm06IDeoc8afW8MzGuzdA2GTDKfHQlWKMnvImcT8fuhSqa5ONofWJ2JbFzb +YfzX+CqgQkZm0B7TGagb1Cj9/sf+70fRiz+CCJvEZej2CAfsfmi7aS2Vb1qhR5mDwQf3ZJJXaJFr +hlDiaxgOIvGpHFfzwGLg2UHzAyaM4hpaVth/fo0Y+Axi2Mva2xFqC2IPtOvOCnxi9onJC9KaAqmM +1qkVJm+6tZmh8fThcm99Skd4zBQThUyCkuE3ebAg2sZtCcKPdmHR5jkurPl4FsFYeWPMp1PtQYYo +QIQMrsbQFT+Hu9G1Balas44GTePqSNDU4A2OmdwaHFnLPoLsCwoEKKznpdUtgFCNHKHJBJhlgBbu +OC271+QFxw1CJjgWz+mJBF/4qPXuGa9tlaaUumlwqUcVBuytNFrsHDgzNABANIqAG5pw5GNjUXgN +OmDlnOxBBpu1mAnfeP7fXtOHaS32rt5M4i4QuEYhJ50eBJ1QPuYRCgXStAr9nttY3NK2PdhOy0M8 +ZVaJRFptEa6m9ugUqp0GapZkqIKdRYomaQ4esVWLxEf1e99poHgHH3caNS2Bmg41PZxWx+T3eQLY +1+0wUTavMKXgZlwQpWWiyMohnRbwD/gXlMmgtBMQk6BZMA+VMn9mf4LM2fnqL1v4w1IaOcJtus0f +adkMDQfdICSgzriAAGRAvLYckvfIiiAF5nKWxpNreC23CjbBiBSImGM8SMEA1vTSC2vwSYS7HCSc +CPmuVHIlvoYYFsxRg7UfprX/XAY1iYbQaUF+gs5QHLvZCydzcdzIZPi87OcwaENklQPzjsHrcbP5 +LocbfrWJFXDYfZ1tkQJlTLmWYOCiem0o42aMvzp2WtTUMoMYXvIG8vZtzEiDnl1vDRpW3IDxFr05 +ln7s5iSwbxjk6lAu7wI0LYma5CqgwLaZnXA/mi3atLHYnidjBOgtQDC49iDJVCcoMI/yfxnkfuje +ZDHvMY2LdZIFpLs0/Y79pWnhYUnpGbiDSwqpDmCimNY8eF+AhND+5gHIE+kCiM1lX2nXvw23OcfO +BvjxJh/YERlu4HnTV0cvrtuEGT4MtKXr6V1ZxArXL+VlZDHZBui6PTfSy0iEONvorUy91Y0hRZEr +CDnFx8svAinGWd51vLmXRN3o+kiCUruXIA2MiVUANqpEZJKDYDc3duL5Z+HWTeOd0B1V9rj+u9AC +2PvTTYYZrS6g160n0OHlN6OOlKSL7stvHkmOLnFsOGd24IHnuhUyTsnQO+8pn5fds4K242rAepZC +Mr3+bUK0eUWjafPQ3S3wY6BieluCMX82rMnYnjp+fI9nKzxtT3YAa0WU5rNHiwIBeD7+FaJYpRNg +t3GSUo4fiLG/j0rQROCcWugWXg/STvl2SNAVIqmrZ8gdHPIP2tPRXtOJyQd3RKrms4pVG5U9vaFf +70d5m/TuXuR25dBpxn0LfvAAjeCN3DVZbdlMr2e8sXDYobYegd2fgNd25vwTcHj2IBQeNRBD04pz +0LAJXVNxrYAB9gDVvMVF2eGgtIfmnbGZcTNY6JR4itL5VKxpd5wSfbhXAVCm7IB0wEE+1Husb6ui +4J1SEvKVLPZx828osDDIeBpUb9QGc/BBloiJbTahxKlTRpJ3MW6gU6F2JkHtwXbzziI3iROZ3SYF +9AWVEgY/fvzptMM+6GGw08P1pLeG2JVdWJwWruLDXS0fH7N9a9J6etQ2Xq1snokIu6dwT1Tv7bjx +nijFWpOFnNyMJG304jJjXye1+RZfIyp2/9cv11HxjGqOYCqTtEIasBuFxWKzKptQsruUYJJ1ZSdW +etD2LSdxZmk8FyF1nmL+QK8mpRhu40I7Gasix1pCUSXTg3kyFfK3Kk4xQJOzGeCCWxH6VcTDUxpB +vOMdaK4xU3JSFUm5ARrEKtc7ObRZ7TQcb3iioYck5+yZgrh9fSQucdr4ngk3NeQyYZ6fuMZJYgSF +HZyt5Yiew/ssH+GoIyQvMBQh1d5Zpce95gi5zozD/PUIzTeSXrnbRbTmLlFRy3ikdGPGnMw1QgkH +GLPyb/rpc6LLXFuwnG/Hcr4by3kTy3knlnMfy/luLF2ZwIWt8w9GFLpyEM3kdGd5hJs+4HFO48mC +22GtHtbkAUSxMiGQESouWfWSFLxbQ0BI7zn7h/SwLndIuAiwyDmTqUEi++NehA63TLGx05mKJ3Rn +norxeLaVfPh9D6KISnvG1J0FbhqXceQJxjzNxyC3Ft1hDWAomtUfnPfKbkdjztE1Vf3Ff33+8eMH +bI6g7HY1dcNFRLWNUwmfxsVctcWpDhhWwI/U0i+aoG4a4F5nlqTPWZL+UPQ5S9LXw+zxP+9oyx45 +R6xpxzkXK7ChVIVjm7m1Kv1+47kuatHPmc15zwDcgqx0XIItVDq5uHh38vmE0zfBPwNXZAxxfflw +8TEtbIO2B+Q2tyTHPrWJrO2fOyeP2A5LmF4tT6/x4HBbYOjj+P86TyAoIBHpNNzjpvn4LIDV/a1C +KTfEZV/BvnMY3/EQHLnryt82B/A3jNBDHgH62oMJzVTqWKahcq1x20EPB+jjIo6m9+zTwQ7d4TU5 +9LDNtvtM7TS1kuWb0x/OPpyfvbk4+fyj4zWh9/Px8uBQnP70RdD+OKp8diNi3BMusRQDVLF7lENM +c/ivwnB6WpWc+IJe787PdZp6icX8WN2JWjqC51zHYaFxZoIza/ahLsBAjFLtkzunJqhcgU5VoIu+ +5Ip9lesKUDqMMUb/rtLevj4NY07N0IZeBAwPjV1SMAiusYFXVKdbmkCk4P0PfZKkAylt1eyOeEqZ +l9Y2qZP8N6llLz9FneFJ3VlrxqvAxTW4jtQqTUBXvgqsAOhuWBhQ841+aHf2GK8upeN0h5F1Q571 +ViywXOJVwHPT/Qc1o/1WAYY1g72DeWeStsWpxBSre0QfG/V5+1vewVe79HoNFCwY7nKUuIiG6RKY +fQzxnFgk4HMDTy7AXKFrDRAaK+FnRI8c6yNz3JUO3i6n+38NNEH81r/80tG8LNL9v4sVBA6CayiC +DmK6jd9BrBDJSJx+fD8IGDmqRxR/rbAAGkw4ZZUcYafCDd45HIVKpjO9r+6rA3yhDSu97jX6F3JV +6P7d7mSAIvD7HyHZ2d//MAS01S52gCHOZ9CEjxXeFj88KeVuwprPnrhcyDTVZb1n785PwefConOU +I956OIUxOVDHbURdgsQnuRqgcJMRXhfIzAW6frTHPI28Zp35QBQ86u1tS9vVopxbu1crwVbEiXLR +DnHamjCmbDpCjoYlMasb4G8tpbYN0tltQ3RH0WHOGF0UVMjnswawND2NOZiAKANr2k12k3fSkqw0 +hVtpMgF1CpoX9OoQZAWpiwe3iAHzjPOLeaHMeQ94uNoUyXxRYnoZOkdUa47Nfzr5cn72gcqvD1/U +7moHjw7JhR7yHvox1khhogC+uHVPyFejkcu6jVcIA5UQ/K/5ijfnj3mAVj9OaXn5bf2KD9wcOzEU +zwD0VLVqCgk6zk63LumphYFxtREkftwSqBozHwxlwbC+X+92u/Nrs6Jt2bAo5HqYl49Ijs9WtiJH +d3YqcpofPcXZCrcUpmF3I3jbJVvmM4auN60322p/3E9LCvHoH2DUbu2PYYpjWk31dBxe28YsFA5q +S/uLGxQ47SYZSjLQMHQ7D1we69bEujkzoFdN2gImvtfoGkHs1ueAovYzPEwssVsBgulItfpPVMgF +BFIfcajAk3qiSH8E4okIQ0dwhwPxVBx6s3Tswf2z1MoLbOSPoAl1MSLVt+cFsCJ8+Y0dSH5FiKEi +PRJ1OIjTy3JbJ4Of9QK9y+f+LDuFgPJ/KHdFnM1lyLCGBubXPrm3pC9J3XrEvkquu0yLOAMn9W4L +j7cloztnb1BrsEKr3Y3cNPWRTx5s0FkUv5NgPvgiXoPyX1VlyCu5ZZOv89DQdqj3Q8TqK2iq9z/D +AD3o37rK83zAndTQsNDT+23LlhOvjfVorYVsHOno2xfalZ0UEKKVqo9IOsewjFNq/YDa5B7XRj+w +T3Wm3v7uOA7jZFMsUB7cB8nPkFx8QIPPwiVU91sfH9DvpvJWpmAdwJqGWN39q63uHkQ2Y9FZ9PJQ +JC42F5tuFOhNjcCRqTLHcai+vDNlsmtcb2VrJPzHQfCLjjzi7Iaiy7d/OxuKtx8+wb9v5EcwlXiI +ayj+DmiJt3kBYSQfQ6Tz4ViwXnJ8mFcKT3oRNEri81F6dMsuPPLihoGupPdL6K0iFFg0iL443t8A +KNY4Mw3okG7tEZgacfhtDrM0/E7jE3ZRJ9AvnVECU+Wv2mX+KzU70D0OnC5XwfnZ29MPl6dReYf8 +a34G104bNw72t6wkaX98VOC20VDYJ5MKn2gojqv8o0xXHZ6yjjbNiQGMNkUfQpGVjTD5toDYxhNx +gSkDsdpM80mELYH3+ZhSuQbXeeAElvfads+wIqxwoHecav8dHwN9RICnr7CJngI1pPHjMZ6O4cdR +sMXWDgVlfeF/T2/WUzdprI850IR6TdTqaYZ+/1rbLZiyGqLlIULt2BLeHnhLk1gtxxP3VNTHTOj7 +HUCR0S6AnMVVWgqZQeREAT0dtAdt7h5kYjHhlWaTRad7KCWTruONcqo4YiUCHJV2XyVuV1BKD+Lt +n+Ib1vl4wkpUfLAToBOiFCTlTldVTRYsxhz3aEXb2tdeJ9kLt0BBE5kH5Th4ompqw0TRO2SU5rLU +BOAH4eDqeb2TTlnfiVecN1npGjz49vTp00D8+/2ODWMQpXl+Ax4XQOx0SM7p9RajrOdkF6mjLs68 +ioAVJwt5BQ+uKSltn1cZZR93dKWFkPb/BgavSc2GpkPD5nJmruANWG7B+zjajvycJXR9C+aPJKpa +fQsO5paMJBEvghLox2qSJH3OQsA6bPIKTx5hLlEzirwDXk8QzBDf4sYRB9ILdB+p8s+yjUUH5kKA +Ay7L4eHovCadugFERxcbjefoLEvKulz+mburqI80l/ZaFs1QIl6jTJiJNKjhHGPzmLReTfi9izm9 +kCSfXD1vlIg58+TX9yEPTA1Cls9mBlV4aJZpkstiYswprlkySUoHjGmHcLgzXUdDSfao14FSAMqc +bMDUCrN9+5VdGRfTj7TDum9G0oUppb3ih7M/cdYozoqienzKM1lCWs41X6i2/gOlr7Ur4A0mvtJc +jxXT3lUE7sGtKtNXDHBpQ33vAMCha22scrQc6SkK5y4lC5/5dsu9APihIJyRu02KsorTkT7JPkIX +bmT3nDWi9sDPzsNs1ksZohVM5vu6QBldh0F9sg0LGU0B+rGY6SxE5B6i8c+brHJ0AA/ZRwJPAkkz +HZkjoCZNdGUZ1h6q0xVoDlsgqK/NMY0tnrc5JdCqr3cx1xl/XTq1xX32C+LoLL54LcIXQ4i1G8fV +Vhu8nQaQfTLF6LzZDabiBP5mjs2D/uL1sQifD8W3O6BHWwY4OnRHaEasDQhbgby4fjQZ02RMZMPj +Cvc3NXVxQ43S4LpJ7TZVviei/KVBFD77pMs7nz9u7GAJCmCWyOn+E4WE0LjUOnY7m9KwePJXl86R +4eNDr6LPZXZ9Pi87hqhiXSs0R7UZb9eOYk7TajXEBw5RZ7ANtKelTUVIo6zNXoCFJW8avwaxAMCo +aw8Mv+FuKbzXtHB9rK1bo7pG2oLtCPn12TTe6aob1vJ2rzP3KEG+lwFwF7SWd1dAHsHpO/fbHV7+ +8/mHa663bWO2EL2nIt7zJjoL3ztWdXfxuSePtuK8XnPz6U6nedzS1fVfkhoHSi0/4Hyaq/TIbTzC +cle+QyO3Za9LvKyO9pXRvKXSdYI4GOZbidArofifiqdgNcAvqma4DXxLd++dKCrywis2vjl8PjTn +GRmQnsCL6MXX+oo66mbObPs+81AHYfBS9zuM/s0BlpR+b/uqFZ/QtI4bV9X4g3HKaxCNLB1qI3N/ +aXy9ZrHAO91qYrKrbK8veA+eyxh8FnM5Yw7eF0SWURe6rtqoRXibfnu8FPvaEAfdJSzbNOAu7fdo +Vta9us0AxvLIuYuY36BbVq2ObMLLGAbccAzd6kPiiZvOozVsFNBkljfBrulz/11z1y16duamlKA1 +d/9km0sD3Xe7KeyiAecZNCEeVBNfK21rEbx5eTRy9fpQl7O0y7TdVjjPLXah1c+Ux2BSnbhRI2uY +cxlP3O9YMrXP97t2lDU559JchmhMt6Xrm5z+EDPPJSf43J5npjqiqeY8HbTQzV0jLuYcyflcjWK8 +Nm5EsS5VUbVCGBM8vadLv2SsNibkwbtSAIRhI10i6paBA0eAkuPra7kKybkNQ9DQVN3qlMuqZMq6 +XMdXAC7iNCX1N4lyrncNUon5ZlUVqwKC0kBfcsrlMV01uDVQk0JbxurGoG56DPWdl6QRqSbLnGbk +5GijtgaIwNa3pdNHI/sOuOZZfbY7GVpukFm1lEVc1nea+DvwCUQ+9Qh00BVX18mP1eLYYBMXscQy +h4MUpqrs968huvND2x2HuQdWzz2cn6iHzrs+5py4Y0YsHyd39jIz9z6dKd2a67p2tlnNd/YSF1gI +c00XqUedtuK3+uIgvr6SE+joHDocBLLvniPzC6atJmPf1KLhPHN1QvuKGDynTHa183q3Jg+073dr +xKF2fF9lWFZpOYdbGlsqao+6U+fUow2cVA5Wat6TyvEL2B+ZyvHgPyaVwydBihRveUjxzjAHOZ23 +M8lFzLnQwRL/Dk7cSGzVJAEnjzea6edY00X5ulgLodN+kec3oxHzz9nMeLI8jjZIukLf3G0+pEbY +j3NySmeCP8dj3MxlXaWEnhBiiFu8qDwMKuKfB3obawS6lc4aQAfzle8URSjkMenRc1CKRTKd4j1p +rPO97BnypbcGGnl2I2jbBy+7o+L/y88nnz7/fOEM5G0oGSxHhg5he0MHVOZdUtYmtn2nErczIDrf +1Wve9K87mYYXkwqfHM//E4xgys382+bxNBLyyYDrfZfxxtxEJrO8mi+40ATm4kDzF814WNgK73ie +gddSmlq1jCbHZSqWkIwjz3k0pdy2sUrmMZkmeEV3BQa+o+l11TfRYt0AjYmuKe4b016R27JJIn6D ++5dKjqDnaJyAXgjwX/HfZ0D3kSF8sEsJbQUE/umRcEBs5wILAr9wpR7Sysnr6wX/eNkZSZ1k5g3v +M/OxSHJ4l3gdAt3aqzjy5fvtVSn46nXRLLfY44M6XFBdoM+d5SKico9iwiwSwjgRktg80JJGmQld +tliDw+vjP16KL2C89coMTAfcqqFb2s35ULyCN+PRJ3TIY91Ebh2zz8bX7Goo+i5ePyRk5dnBNbh/ +MprwMVSjWEZgLedop9GWPWvS9wzr06ziWeNt/HjrJqg4o3MBo4aqihowsER+XuEhWbrGz/zxAkwn +3ObJlGvzUULNMHhrLCiQBhjaN3WvjqT61LWRM9LHiCDeYxdPN9YGyGkDULkoSLqb2g4V9hAry5pE +0MUd42qu3OKCRKlKfvvdN9/uLdX8+V++e/nipdfRTGfLZXnO+ajgn5ipCxp0bBQ6dm6k+vJjlpRE +SP/o3FntlKY26+AHFf66QF9RA2ye+9uKm4efB2IHgg6S4Xto9SEv36NXT/gOxYUs6EasPKMHW2qq +9hrH+fgvY6CupKiNrB3/RrTQhdgGRpeVdC49LPlfnnd2bFORzWFkLGfokcOJDTs8DyxkaxpccI28 +rRlrmtly2mIuyra5CwZ2nGqXjBd3xCUPtvrEnJvR/jVeylnIfftHW/Q16BYcdQZ/al7ES6WVGqcY ++OSLfw0wOmLkFVeryCZ7GHIdiuPdjYhiX5l7QCMX+6af0bH/j+ferWbUhROAhKEJIzNqXNzlgrR9 +fZj/SFb6pr1Hg7Rd7Q3ToAj0sujwtvOY5j3bmCaJ07FH18kH7Hm6lz7X0dAIm20UcZt/f7AZxT0i +ucpVchfYv9fAGQPnsBxGY+2rQKkrX+qsnAyTd/2qO6fmHqYfWNLjH84/vjk5J4qNLk7e/ufJD3QC +AGW7kal58CZvlu/zmux75wTdDV9dtt01eI1tx7XrfNRcQ2i9b9W7dkDovlagaxmbQbz7eluH1uns +didAfPe0G1C3pSs6Ibeykfq6NLdUu3E2sKef8kEu88spgjWPTKWYO1ZjMxqHfOEckGpHnixBdRWZ +AV7X/+jQtlUbsW3VneHaUTi92zP3dm8p3BjYU4G0fBgPInPaqh9zJtpWlnBqr/mXt8hPwxslzH13 +IMET6Vy9TLcuM6jS/xNfRZVhfBrrP6Y1tH8ug9pxhZOyfwcGSxUnOhxqXenQnp+bLJnKdAsVQLGy +UjV3CjMqRsnqekBbQftEiat9un5lH1XVtf2Fq6Yzw39LsE62tFdzKq6lZ6MHjWdV6ta+2j6tDpQw +pYqqfOacdwZ9eQCUrqVbgXRgrpGt4Xgj+k9UX6cz8SQXUVLfq+sgj+6Mg72h1jOxv+1yEfdyDSGe +b284bdzfoXsccg91Tw9VmRscHJuIJ4q23RoiXhNkLsoTdCOnl7bDGlC91wVfb6+eH9nqGOR4fO3o +ITr4EDgpsSvHo955AbTTHb/+/lXxx9CeOMR9m0FzlOugcfRw+/ZA6yj1li0EU57LkALvffdusenh +/VWcoNfE1XLgEc1MhL//MbCzc06O6ynYJ4P2tGsttg0Un4V3QdHh+Taoll4UTwrcamw+d843bfiM +YvjMnm6kS/XdoqnAkRNy23we4R4mj1rPtNmdLpB5UHdG0fTnBk2e1MsP4s7OCLcaeIme7WaiOfWa +J7b4FHwXT3f/5w/o3z6DY7sf7koP2VYvOu+PYM8YD25hcXuTS83zCCwPqNKQFPgTEVrZxxvKakK6 +DFVPDhmDAiVyzTGUonQ9edEj7VRYQ9H7X+4V6Ls= +""" +) + +# file activate.sh +ACTIVATE_SH = convert( + """ +eJytVV1v2kAQfPevWAxKk7QU0cdWRCUKEkgJRJhStU3lHPYSn2rO6O5MQj7+e/dsY2wc6EPDA2Dv +3N3szuxeHSYBVzDnIcIiVhpmCLFCH+65DsBWUSw9hBkXLeZpvmIabTidy2gBM6aCU6sO6ygGjwkR +aZCxAK7B5xI9Ha4ty8fNKjg+gScL6BMLhRqac1iu/ciDs5aPq5aIwxA+nR21rQRTB4kGFYU+oFhx +GYkFCg0rJjmbhagyVA1+QfMRGk/T7vi9+wK/aZ2OpVCgZYzA50ABoPx89EImKS2mgYVhspyi2Xq7 +8eSOLi/c6WA8+da9dK+7kz5tZ9N+X0AHKBK8+ZhIx25U0HaOwIdlJHUCzN+lKVcWJfE5/xeZH5P+ +aNgfXfX2UMrjFWJ5pEovDx0kWUYR1azuiWdUEMWkj4+a1E7sAEz48KiCD3AfcC+AgK0QGP1QyIsW +CxPWAUlgnJZtRX7zSBGSRkdwRwzIQPRvHknzsGRkyWyp+gjwnVwZxToLay7usm1KQFMgaJgSgxcw +cYcK7snezDdfazBWpWPJYktijv5GACq/MOU/7zr9ZlLq5+f85U+n7057Y2cwGjZfkyFJsinJxLmh +S0U7ILDT3qOs065I6rSrWjrtgyJm4Q2RFLKJ9obTbfo1w61t0uuALSLho6I+Mh2MO/Tq4GA4hw2g +tkOgaUKb1t+c/mLRtEjjXEoMccVKLV0YFuWzLavAtmO7buHRdW0rq0MxJavSbFTJtFGzhwK65brn +g6E77F71XPdzBiv2cc572xCmYPTGKsl6qFX3NJahtdOmu0dZRrnUnskpxewvBk73/LLnXo9HV9eT +ijF3jdAxJB2j8FZ0+2Fb0HQbqinUOvCwx5FVeGlTDBWWFxzf0nBAwRYIN6XC39i3J1BanE3DgrNN +8nW4Yn8QVCzRzIZYsJAzlV0glATX7xSNdYnMXxvCEq0iotCSxevm6GhnJ+p2c21YVvqY31jLNQ0d +Ac1FhrMbX+3UzW8yB99gBv7n/Puf2ffa3CPN/gKu/HeT +""" +) + +# file activate.fish +ACTIVATE_FISH = convert( + """ +eJytVm1v2zYQ/q5fcZUdyClqGVuHfQgwDGnjIQYSO3DcAMM6yLREWxxo0iMpty7243ekLImy5RQY +lg+RJT73fvfwerDImYY14xS2hTawolBomuE/Jjaw1LJQKYUVEyOSGrYnhsZrpvMlvP3CTM4EEFCF +EBZsv8MAcmN2N6ORfdM55TxO5RauQVOtmRRv46AHdxKENFYQmIGMKZoafoiDYF0ItCIFJCuic7Y+ +JDtichhmEH6UYk+V0WjQGXIHRoKWW2od2YAVgZQIQHVyI9g3GgaAf5oaJ3JU1idqs68PrFB10ID+ ++OFPh1hL5QzhR2UAo/UxP8bx8Ijr0Bb2m5ebfq2kdImKrHymuQQPGNgDLwvW2qUsuHDPs+CS05GF +0pSNHf4BoyC6iSD6LKITkxmt6mztReOvWKA9U6YgnIo9bGVGgYgMtZtCCWva5BSrqbaEY1gIlWJL +hYkjZ7WHQJsYyTP/FPZEMbLiVDsUW4Oh2HxDgWlLZg93yctkvvh0+5A83S7uwzrFPddcGrtrg81X +rGxruUYbuk7zfzKtC6pHP73/GQg3VGFLW12Qo/Mc81TrrGwPygT9Nnm+T17G8+fJbFomKoxDCD+L +8BqbAobcwPtatir7cPO11D5oV+w8lutalnJNLys6l2wEj71Ty1DoBrvCfie9vy/uZ9P72eM4DM78 +qM9OvakPXvejDXvFG5fzp/ns8WmRzDD388nd2C/6M2rHhqbbnTkAlyl22tINYlK1rUv30nYj4Vx+ +cT2p6FbuESrXsHTgnZKoYVlRWyWr0fNl3A6Fw7n6wPNorIim3lxE+sRGOSLaSEWdM1KxDROEN3Z8 +8+DJdgFSSHCAEg/1PQl6JtFZq67Mt6t1RFdFHU9f2lUMHaXgaITw5heIhBQZflaFJREatYrI18Pq +7E23z7tDJtPuo4aXLoTrXxgXIP5s1lG6SHvwSdhImVKU0z3xGSoOPE5sxxcE1bB4+YEwSbzXJAmt +/v+PuP4jYVWennEFklbrsu2XPFXz02VBh3QJbHFX2PfCHyXJh8k0md4+jjETR5E638t+wxJL21P4 +MQ7KJwz/hhMO6XbF46kuPPW1tC+7pt92B5Pjh+G2/HZcEhy65qtv7ciSu8nz7YeH8XF+wuN991Hu +Dm7k0wKbCRupTQy1bYKUcTqjRxpqTb4/9Gcz3YJ3cgIOHtnTlkN9bYgp9Du33XgyGlHErmN6x8kB +N7MzUrTmS+FKiU+KT6WTEhcUxXBNQK17fGa/epjJ2m5+7+Avu2vuFN1hip1z/nIgyJY2tv37opms +I2klzT3hyqiYMGuIrvSVjjrhMMBYklRyjL3cWl65kht1gyt9DVGHMAxweKj1uN0doae24tIyBfOO +a6FOZy1jZzukdvvqN1kPccDLjbwGdtJ8m72rgeki+xOnXcf/CzFcuJM= +""" +) + +# file activate.csh +ACTIVATE_CSH = convert( + """ +eJx9k9tq20AQhu/3Kf7IJm5N4vRarts6caCBxAnBCZSmLCtpXC1IK2e1svFNn72zklzkA9WFkOb0 +z34708Mi1SWWOiPkVekQEaqSEmy0SxGURWVjQqTNlYqdXitHo7hMAwyXtsjBn8OR6OFHUSFWxhQO +tjLQDom2FLts6703ljgvQbTFTK11QphpXGeq1Pic1IYk+vY7VzobxUX+ZSRESQ6GNpk2NBm8iYEQ +KtOqREK7LjBwxN32v8rH+5l8vXtevEzv5dN08R1nE3zC+Tm4CJk1alvQP4oL3wMfVRkvduQdw1Kq +ynSMkzrPjw9Pi64SVsxj5SaHQnXgf6Rq/7hx+W53jtv5aysdvJ2Fw8BrBaYwCZts5SFQW/OITMe6 +2iZFzPR6eKm1tbWU0VoZh7WyWkUZlSPRyd1XqC/ioCsEUnZ+pQya6zoiyChazGL/JjrZ4fuVlNd3 +czmfPtxKGf7L4Ecv8aGj1ZBiuZpE8BEuJSPAj1fn8tKonDDBqRxBWUkng/e6cV6aTKKXHtlNUWWJ +3wdtoDyZS20c2ZoV+SLaFiYn4y44mGM2qY5TXoOSLtBvxgG8WhUTXfIgJ1CG14qw8XXNwHFWrCxB +RUXl/HHaGeK47Ubx5ngCPHmt9eDEJ8aIiTex/hh1cseAyR8Mg367VWwYdiuG+4RaSebzs7+jFb7/ +Qqd+g6mF1Uz2LnK3rfX08dulhcFl3vwL0SyW+At+C2qe +""" +) + +# file activate.xsh +ACTIVATE_XSH = convert( + """ +eJyFU11rwjAUfc+vuIt9sMz1Bwg+OCYoaB2bkw2RkNlbLdSkJLFsjP33JdV+aN2Wh5L7eW7PuaGU +vkqhd8A3Jsm5QdAblWQGYqkgT5Q58BRFTiklsZJ7+HDJgZEy1ZDsM6kMbNEwjRlwDex0JyTCGFiE +ZdcuV1vt9wnYk8RAs89IbigkAniacI36GHInwrR0rk55a1IWel9BEHwHFqZL2Xz6wJaTp8XLcMoe +h4sx7QGlft3Jc04YgNfKPAO7Ev4f7m0xnofj+WzUBq1Cbegq9NcAdVJFVxkbhcuCtONc55x5jaS6 +UkgRoTbq4IRACkKagnUrR13egWdMYygTb65rUavpBCEdOAiNtptSmGLOhYGcq4S/p6hJU/rV5RBr +n1xtavlq1BHS/CMbU5SxhocxalNa2jnSCw29prXqr4+OgEdR96zxbbW1Xd8aFuR+ErJwOBtZhB7Y +rRdmsFAH7IHCLOUbLCyfkIsFub4TJU2NtbB11lNEf5O+mPt8WwqNm8tx+UhsjbubnRRugLu9+5YP +6AcvDiI9 +""" +) + +# file activate.bat +ACTIVATE_BAT = convert( + """ +eJx9Ul9LhEAQfxf8DoOclI/dYyFkaCmcq4gZQTBUrincuZFbff12T133TM+nnd35/Zvxlr7XDFhV +mUZHOVhFlOWP3g4DUriIWoVomYZpNBWUtGpaWgImO191pFkSpzlcmgaI70jVX7n2Qp8tuByg+46O +CMHbMq64T+nmlJt082D1T44muCDk2prgEHF4mdI9RaS/QwSt3zSyIAaftRccvqVTBziD1x/WlPD5 +xd729NDBb8Nr4DU9QNMKsJeH9pkhPedhQsIkDuCDCa6A+NF9IevVFAohkqizdHetg/tkWvPoftWJ +MCqnOxv7/x7Np6yv9P2Ker5dmX8yNyCkkWnbZy3N5LarczlqL8htx2EM9rQ/2H5BvIsIEi8OEG8U ++g8CsNTr +""" +) + +# file deactivate.bat +DEACTIVATE_BAT = convert( + """ +eJyFkN0KgkAUhO8X9h0GQapXCIQEDQX/EBO6kso1F9KN3Or1201Si6JzN+fMGT5mxQ61gKgqSijp +mETup9nGDgo3yi29S90QjmhnEteOYb6AFNjdBC9xvoj9iTUd7lzWkDVrwFuYiZ15JiW8QiskSlbx +lpUo4sApXtlJGodJhqNQWW7k+Ou831ACNZrC6BeW+eXPNEbfl7OiXr6H/oHZZl4ceXHoToG0nuIM +pk+k4fAba/wd0Pr4P2CqyLeOlJ4iKfkJo6v/iaH9YzfPMEoeMG2RUA== +""" +) + +# file activate.ps1 +ACTIVATE_PS = convert( + """ +eJyNVMtu2zAQvOsrNrLQ2miloFcXPdiwgRhwHCN2c2kLgqZWMQGKFEhKqVHky3LoJ/UXSlqWX3LS +8ibtzHJ2d5Z/Xn53YLnmBjIuEPLSWFghpMqCUaVmmEKmVQ5ztVh/ho0qgVEpXVSXEriFlGtkVmwS +GCmwLk8fEkiuKbO8ohaTwnwKgsgwzQvbX95MFmQ+WN7AF4jyDZeVYtRyJZN8w1SeU5kmBbXrPWE4 +WIzJaHLv8KYQ3MY+Cl2NRokK668w2qe9TpKwB/GcapQ2CLJSMp8dHoVaUdFPsZHV/WaeuGXrHxDN +lByhsbr0IewFvwJwh2fQte53fUVFNacrgX1yNx2Rh8n98utgur2xt0XXHH8ilFW/qfB12h6vMVeu +kAYJYQsaQmyYKnBXxJb5HFwQ2VTbJ0qkpOLallSQwg2vsC2Ze3Ad92rf4p/r5Rbzw4XfX2Mc6dw2 +pqlrPHtoKfIpHOZ00ucsiAXS7KKaFhK1VprWBjDO29K5lClpuSzxXN1Vywan6jqwQJFBukNcvd2P +g8/exhWbVLGdlOe2XetwLaLY2LWLxDls/0JE9aPxpA6U0qAFrjUKrKi0e7ea4CAEYqlkeijQ7eRx +s9z4m1ULWj13waNPx9zpa1nVIxv/B8ebEJ7nvCZkOJmR2eB2TNzxMLIYzwkJ4cNRjno0Z1wncjEY +Tsdkfn93O182G3vevdc8eRhqGO56f7oRF4gn63GUqzWxS9d0YJCmQKHQmPGfYP0zicBK7R8pqCkf +YVW6t1TJ9/5FNYzq1D2uyT7Hk3bOidfKPc5hN+r+e0Wg14NwO3R8ElwejPjuPxbdu/EvkRDrCw== +""" +) + +# file distutils-init.py +DISTUTILS_INIT = convert( + """ +eJytV21v5DQQ/p5fMaRCJLANcAcSqlghuBdUcRzo6BdUnSI3cXZNs3bO9m679+uZsbOJnWR7fKBS +u65nPC/PvK7YdUpbUCYR/mSOw/GBaSnkxiTJBaiuUjUHYUAqCwwOQts9a7k8wE7V+5avwCh44FAx +CXuDnBasgkbIGuyWg7F1K+5Q0LWTzaT9DG7wgdL3oCR0x+64QkaUv9sbC3ccdXjBeMssaG5EzQ0I +SeJQDkq77I52q+TXyCcawevLx+JYfIRaaF5ZpY8nP7ztSYIEyXYc1uhu0TG7LfobIhm7t6I1Jd0H +HP8oIbMJe+YFFmXZiJaXZb6CdBCQ5olohudS6R0dslhBDuuZEdnszSA/v0oAf07xKOiQpTcIaxCG +QQN0rLpnG0TQwucGWNdxpg1FA1H1+IEhHFpVMSsQfWb85dFYvhsF/YS+8NZwr710lpdlIaTh2mbf +rGDqFFxgdnxgV/D6h2ffukcIBUotDlwbVFQK2Sj4EbLnK/iud8px+TjhRzLcac7acvRpTdSiVawu +fVpkaTk6PzKmK3irJJ/atoIsRRL9kpw/f/u1fHn97tWLmz/e/Z3nTunoaWwSfmCuFTtWbYXkmFUD +z9NJMzUgLdF9YRHA7pjmgxByiWvv31RV8Zfa64q/xix449jOOz0JxejH2QB8HwQg8NgeO26SiDIL +heMpfndxuMFz5p0oKI1H1TGgi6CSwFiX6XgVgUEsBd2WjVa70msKFa56CPOnbZ5I9EnkZZL0jP5M +o1LwR9Tb51ssMfdmX8AL1R1d9Wje8gP2NSw7q8Xd3iKMxGL1cUShLDU/CBeKEo2KZRYh1efkY8U7 +Cz+fJL7SWulRWseM6WvzFOBFqQMxScjhoFX0EaGLFSVKpWQjNuSXMEi4MvcCa3Jw4Y4ZbtAWuUl6 +095iBAKrRga0Aw80OjAhqy3c7UVbl/zRwlgZUCtu5BcW7qV6gC3+YpPacOvwxFCZoJc7OVuaFQ84 +U9SDgUuaMVuma2rGvoMRC3Y8rfb92HG6ee1qoNO8EY8YuL4mupbZBnst9eIUhT5/lnonYoyKSu12 +TNbF6EGP2niBDVThcbjwyVG1GJ+RK4tYguqreUODkrXiIy9VRy3ZZIa3zbRC0W68LRAZzfQRQ4xt +HScmNbyY01XSjHUNt+8jNt6iSMw3aXAgVzybPVkFAc3/m4rZHRZvK+xpuhne5ZOKnz0YB0zUUClm +LrV9ILGjvsEUSfO48COQi2VYkyfCvBjc4Z++GXgB09sgQ9YQ5MJFoIVOfVaaqyQha2lHKn3huYFP +KBJb8VIYX/doeTHjSnBr8YkT34eZ07hCWMOimh6LPrMQar8cYTF0yojHdIw37nPavenXpxRHWABc +s0kXJujs0eKbKdcs4qdgR4yh1Y5dGCJlMdNoC5Y5NgvcbXD9adGIzAEzLy/iKbiszYPA/Wtm8UIJ +OEGYljt14Bk9z5OYROuXrLMF8zW3ey09W+JX0E+EHPFZSIMwvcYWHucYNtXSb8u4AtCAHRiLmNRn +1UCevMyoabqBiRt3tcYS9fFZUw/q4UEc/eW8N/X3Tn1YyyEec3NjpSeVWMXJOTNx5tWqcsNwLu5E +TM5hEMJTTuGZyMPGdQ5N+r7zBJpInqNJjbjGkUbUs+iGTEAt63+Ee2ZVbNMnwacF6yz4AXEZ/Ama +5RTNk7yefGB+5ESiAtoi/AE9+5LpjemBdfj0Ehf09Lzht5qzCwT9oL00zZZaWjzEWjfEwoU9mMiD +UbThVzZ34U7fXP+C315S91UcO9rAFLen4fr29OA9WnOyC1c8Zu5xNaLeyNo2WNvPmkCtc2ICqidc +zmg+LaPu/BXc9srfx9pJbJiSw5NZkgXxWMiyBWpyNjdmeRbmzb+31cHS +""" +) + +# file distutils.cfg +DISTUTILS_CFG = convert( + """ +eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH +xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg +9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q= +""" +) + +# file activate_this.py +ACTIVATE_THIS = convert( + """ +eJylVE1v2zAMvetXENqhNpZ5wHoL0EMOBdqh64Kt3RAEhaE4TMzOlgxJ+ULR/z7Sdpr041BsOUSS +9fj0SD5Jaz0qIq1NRFiTjytToV3DwnkoVt6jjUA2om888v9QqduAgFssEtegTWJJIV9QhWnm0cyT +dAAPJ3n7Jc9PhvC0/5hmSt3wCgpjYYawCjiHTYkWdm4F9SpE+QS8iVsKkewSxrtYOnt8/gCsi0z6 +TOuM7OemhWZKa62obpyP4MJ+Fiji03wXlIp+N1TAv71ShdsCmwjXpsZz753vtr0hljQKAX0kZ9ud +RE+O9f5TKVKdKvUBOCcOnEsCEB2MRzcX0NKAwIBHsoHm2CYsoDl5LKLzu1TxMuclnHGeWWNimfHK +svxkvzazIGOyl5Cmire4YOSdnWo5Td8d4gM22b0jm0x76jv4CIeAbIkx6YIGoHWahaaimByCmV7N +DFfktaKesM257xtI4zhBT8sygpm59YsMn2n9dfnj5nZ0lZ9f/2olyzlCZubzYzNAH1Cza0Pb9U+N +Kf6YJUp5BVg6blvT26ozRI1FaSyFWl3+zMeT8YT5SxNMjD5hs3Cyza7Z5Wv0gS2Qk1047h5jv05u +Lr5fM5pRWVOZyHemzkI0PoYNceH1vVkbxtICnuCdr0Ra3ksLRwVr6y/J8alXNJNKH2cRmAyrjk6U +vp/sNUvALpqpfl++zALOzkBvyJ5+0S2oO5JxXcx/piDhBwHvJas6sq55D486E6EmSo+yvjnT4eld ++saBii/aWlLEDi7cqRJUxg6SkW2XPBPB2wzke1zlHLyg7b5C7UIdpkdu/CYmFpcxKb9tTFeHvfEW +bEt+khbtQs4f8N0GrneByuKGWSp+9I7V9bPpUAw/pfZFJgkSODeE2qdQSDg5uatvYvb76i9zKfxE +""" +) + +# file python-config +PYTHON_CONFIG = convert( + """ +eJyNVV1P2zAUfc+v8ODBiSABxlulTipbO6p1LWqBgVhlhcZpPYUkctzSivHfd6+dpGloGH2Ja/ue +e+65Hz78xNhtf3x90xmw7vCWsRPGLvpDNuz87MKfdKMWSWxZ4ilNpCLZJiuWc66SVFUOZkkcirll +rfxIBAzOMtImDzSVPBRrekwoX/OZu/0r4lm0DHiG60g86u8sjPw5rCyy86NRkB8QuuBRSqfAKESn +3orLTCQxE3GYkC9tYp8fk89OSwNsmXgizrhUtnumeSgeo5GbLUMk49Rv+2nK48Cm/qMwfp333J2/ +dVcAGE0CIQHBsgIeEr4Wij0LtWDLzJ9ze5YEvH2WI6CHTAVcSu9ZCsXtgxu81CIvp6/k4eXsdfo7 +PvDCRD75yi41QitfzlcPp1OI7i/1/iQitqnr0iMgQ+A6wa+IKwwdxyk9IiXNAzgquTFU8NIxAVjM +osm1Zz526e+shQ4hKRVci69nPC3Kw4NQEmkQ65E7OodxorSvxjvpBjQHDmWFIQ1mlmzlS5vedseT +/mgIEsMJ7Lxz2bLAF9M5xeLEhdbHxpWOw0GdkJApMVBRF1y+a0z3c9WZPAXGFcFrJgCIB+024uad +0CrzmEoRa3Ub4swNIHPGf7QDV+2uj2OiFWsChgCwjKqN6rp5izpbH6Wc1O1TclQTP/XVwi6anTr1 +1sbubjZLI1+VptPSdCfwnFBrB1jvebrTA9uUhU2/9gad7xPqeFkaQcnnLbCViZK8d7R1kxzFrIJV +8EaLYmKYpvGVkig+3C5HCXbM1jGCGekiM2pRCVPyRyXYdPf6kcbWEQ36F5V4Gq9N7icNNw+JHwRE +LTgxRXACpvnQv/PuT0xCCAywY/K4hE6Now2qDwaSE5FB+1agsoUveYDepS83qFcF1NufvULD3fTl +g6Hgf7WBt6lzMeiyyWVn3P1WVbwaczHmTzE9A5SyItTVgFYyvs/L/fXlaNgbw8v3azT+0eikVlWD +/vBHbzQumP23uBCjsYdrL9OWARwxs/nuLOzeXbPJTa/Xv6sUmQir5pC1YRLz3eA+CD8Z0XpcW8v9 +MZWF36ryyXXf3yBIz6nzqz8Muyz0m5Qj7OexfYo/Ph3LqvkHUg7AuA== +""" +) + +MH_MAGIC = 0xFEEDFACE +MH_CIGAM = 0xCEFAEDFE +MH_MAGIC_64 = 0xFEEDFACF +MH_CIGAM_64 = 0xCFFAEDFE +FAT_MAGIC = 0xCAFEBABE +BIG_ENDIAN = ">" +LITTLE_ENDIAN = "<" +LC_LOAD_DYLIB = 0xC +maxint = MAJOR == 3 and getattr(sys, "maxsize") or getattr(sys, "maxint") + + +class FileView(object): + """ + A proxy for file-like objects that exposes a given view of a file. + Modified from macholib. + """ + + def __init__(self, file_obj, start=0, size=maxint): + if isinstance(file_obj, FileView): + self._file_obj = file_obj._file_obj + else: + self._file_obj = file_obj + self._start = start + self._end = start + size + self._pos = 0 + + def __repr__(self): + return "".format(self._start, self._end, self._file_obj) + + def tell(self): + return self._pos + + def _checkwindow(self, seek_to, op): + if not (self._start <= seek_to <= self._end): + raise IOError( + "{} to offset {:d} is outside window [{:d}, {:d}]".format(op, seek_to, self._start, self._end) + ) + + def seek(self, offset, whence=0): + seek_to = offset + if whence == os.SEEK_SET: + seek_to += self._start + elif whence == os.SEEK_CUR: + seek_to += self._start + self._pos + elif whence == os.SEEK_END: + seek_to += self._end + else: + raise IOError("Invalid whence argument to seek: {!r}".format(whence)) + self._checkwindow(seek_to, "seek") + self._file_obj.seek(seek_to) + self._pos = seek_to - self._start + + def write(self, content): + here = self._start + self._pos + self._checkwindow(here, "write") + self._checkwindow(here + len(content), "write") + self._file_obj.seek(here, os.SEEK_SET) + self._file_obj.write(content) + self._pos += len(content) + + def read(self, size=maxint): + assert size >= 0 + here = self._start + self._pos + self._checkwindow(here, "read") + size = min(size, self._end - here) + self._file_obj.seek(here, os.SEEK_SET) + read_bytes = self._file_obj.read(size) + self._pos += len(read_bytes) + return read_bytes + + +def read_data(file, endian, num=1): + """ + Read a given number of 32-bits unsigned integers from the given file + with the given endianness. + """ + res = struct.unpack(endian + "L" * num, file.read(num * 4)) + if len(res) == 1: + return res[0] + return res + + +def mach_o_change(at_path, what, value): + """ + Replace a given name (what) in any LC_LOAD_DYLIB command found in + the given binary with a new name (value), provided it's shorter. + """ + + def do_macho(file, bits, endian): + # Read Mach-O header (the magic number is assumed read by the caller) + cpu_type, cpu_sub_type, file_type, n_commands, size_of_commands, flags = read_data(file, endian, 6) + # 64-bits header has one more field. + if bits == 64: + read_data(file, endian) + # The header is followed by n commands + for _ in range(n_commands): + where = file.tell() + # Read command header + cmd, cmd_size = read_data(file, endian, 2) + if cmd == LC_LOAD_DYLIB: + # The first data field in LC_LOAD_DYLIB commands is the + # offset of the name, starting from the beginning of the + # command. + name_offset = read_data(file, endian) + file.seek(where + name_offset, os.SEEK_SET) + # Read the NUL terminated string + load = file.read(cmd_size - name_offset).decode() + load = load[: load.index("\0")] + # If the string is what is being replaced, overwrite it. + if load == what: + file.seek(where + name_offset, os.SEEK_SET) + file.write(value.encode() + "\0".encode()) + # Seek to the next command + file.seek(where + cmd_size, os.SEEK_SET) + + def do_file(file, offset=0, size=maxint): + file = FileView(file, offset, size) + # Read magic number + magic = read_data(file, BIG_ENDIAN) + if magic == FAT_MAGIC: + # Fat binaries contain nfat_arch Mach-O binaries + n_fat_arch = read_data(file, BIG_ENDIAN) + for _ in range(n_fat_arch): + # Read arch header + cpu_type, cpu_sub_type, offset, size, align = read_data(file, BIG_ENDIAN, 5) + do_file(file, offset, size) + elif magic == MH_MAGIC: + do_macho(file, 32, BIG_ENDIAN) + elif magic == MH_CIGAM: + do_macho(file, 32, LITTLE_ENDIAN) + elif magic == MH_MAGIC_64: + do_macho(file, 64, BIG_ENDIAN) + elif magic == MH_CIGAM_64: + do_macho(file, 64, LITTLE_ENDIAN) + + assert len(what) >= len(value) + + with open(at_path, "r+b") as f: + do_file(f) + + +if __name__ == "__main__": + main() diff --git a/src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/__init__.py b/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv_support/__init__.py similarity index 100% rename from src/leiningen/new/python/utils/virtualenv-15.1.0/virtualenv_support/__init__.py rename to src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv_support/__init__.py diff --git a/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv_support/pip-19.0.3-py2.py3-none-any.whl b/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv_support/pip-19.0.3-py2.py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..24f247caa0ab432c8c93e9ada0963c2a21d2bffe Binary files /dev/null and b/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv_support/pip-19.0.3-py2.py3-none-any.whl differ diff --git a/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv_support/setuptools-40.8.0-py2.py3-none-any.whl b/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv_support/setuptools-40.8.0-py2.py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..fdc66e9330e073a68f76b0518910ead9016cc3f7 Binary files /dev/null and b/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv_support/setuptools-40.8.0-py2.py3-none-any.whl differ diff --git a/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv_support/wheel-0.33.1-py2.py3-none-any.whl b/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv_support/wheel-0.33.1-py2.py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..676d746b58db034da993ae00b61807e0f661e004 Binary files /dev/null and b/src/leiningen/new/python/utils/virtualenv-16.4.1/virtualenv_support/wheel-0.33.1-py2.py3-none-any.whl differ