python/virtualenv/virtualenv.py

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/python/virtualenv/virtualenv.py	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2342 @@
     1.4 +#!/usr/bin/env python
     1.5 +"""Create a "virtual" Python installation
     1.6 +"""
     1.7 +
     1.8 +__version__ = "1.11.4"
     1.9 +virtualenv_version = __version__  # legacy
    1.10 +
    1.11 +import base64
    1.12 +import sys
    1.13 +import os
    1.14 +import codecs
    1.15 +import optparse
    1.16 +import re
    1.17 +import shutil
    1.18 +import logging
    1.19 +import tempfile
    1.20 +import zlib
    1.21 +import errno
    1.22 +import glob
    1.23 +import distutils.sysconfig
    1.24 +from distutils.util import strtobool
    1.25 +import struct
    1.26 +import subprocess
    1.27 +import tarfile
    1.28 +
    1.29 +if sys.version_info < (2, 6):
    1.30 +    print('ERROR: %s' % sys.exc_info()[1])
    1.31 +    print('ERROR: this script requires Python 2.6 or greater.')
    1.32 +    sys.exit(101)
    1.33 +
    1.34 +try:
    1.35 +    set
    1.36 +except NameError:
    1.37 +    from sets import Set as set
    1.38 +try:
    1.39 +    basestring
    1.40 +except NameError:
    1.41 +    basestring = str
    1.42 +
    1.43 +try:
    1.44 +    import ConfigParser
    1.45 +except ImportError:
    1.46 +    import configparser as ConfigParser
    1.47 +
    1.48 +join = os.path.join
    1.49 +py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
    1.50 +
    1.51 +is_jython = sys.platform.startswith('java')
    1.52 +is_pypy = hasattr(sys, 'pypy_version_info')
    1.53 +is_win = (sys.platform == 'win32')
    1.54 +is_cygwin = (sys.platform == 'cygwin')
    1.55 +is_darwin = (sys.platform == 'darwin')
    1.56 +abiflags = getattr(sys, 'abiflags', '')
    1.57 +
    1.58 +user_dir = os.path.expanduser('~')
    1.59 +if is_win:
    1.60 +    default_storage_dir = os.path.join(user_dir, 'virtualenv')
    1.61 +else:
    1.62 +    default_storage_dir = os.path.join(user_dir, '.virtualenv')
    1.63 +default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini')
    1.64 +
    1.65 +if is_pypy:
    1.66 +    expected_exe = 'pypy'
    1.67 +elif is_jython:
    1.68 +    expected_exe = 'jython'
    1.69 +else:
    1.70 +    expected_exe = 'python'
    1.71 +
    1.72 +# Return a mapping of version -> Python executable
    1.73 +# Only provided for Windows, where the information in the registry is used
    1.74 +if not is_win:
    1.75 +    def get_installed_pythons():
    1.76 +        return {}
    1.77 +else:
    1.78 +    try:
    1.79 +        import winreg
    1.80 +    except ImportError:
    1.81 +        import _winreg as winreg
    1.82 +
    1.83 +    def get_installed_pythons():
    1.84 +        python_core = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE,
    1.85 +                "Software\\Python\\PythonCore")
    1.86 +        i = 0
    1.87 +        versions = []
    1.88 +        while True:
    1.89 +            try:
    1.90 +                versions.append(winreg.EnumKey(python_core, i))
    1.91 +                i = i + 1
    1.92 +            except WindowsError:
    1.93 +                break
    1.94 +        exes = dict()
    1.95 +        for ver in versions:
    1.96 +            path = winreg.QueryValue(python_core, "%s\\InstallPath" % ver)
    1.97 +            exes[ver] = join(path, "python.exe")
    1.98 +
    1.99 +        winreg.CloseKey(python_core)
   1.100 +
   1.101 +        # Add the major versions
   1.102 +        # Sort the keys, then repeatedly update the major version entry
   1.103 +        # Last executable (i.e., highest version) wins with this approach
   1.104 +        for ver in sorted(exes):
   1.105 +            exes[ver[0]] = exes[ver]
   1.106 +
   1.107 +        return exes
   1.108 +
   1.109 +REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
   1.110 +                    'fnmatch', 'locale', 'encodings', 'codecs',
   1.111 +                    'stat', 'UserDict', 'readline', 'copy_reg', 'types',
   1.112 +                    're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
   1.113 +                    'zlib']
   1.114 +
   1.115 +REQUIRED_FILES = ['lib-dynload', 'config']
   1.116 +
   1.117 +majver, minver = sys.version_info[:2]
   1.118 +if majver == 2:
   1.119 +    if minver >= 6:
   1.120 +        REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc'])
   1.121 +    if minver >= 7:
   1.122 +        REQUIRED_MODULES.extend(['_weakrefset'])
   1.123 +    if minver <= 3:
   1.124 +        REQUIRED_MODULES.extend(['sets', '__future__'])
   1.125 +elif majver == 3:
   1.126 +    # Some extra modules are needed for Python 3, but different ones
   1.127 +    # for different versions.
   1.128 +    REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
   1.129 +                             '_weakrefset', 'copyreg', 'tempfile', 'random',
   1.130 +                             '__future__', 'collections', 'keyword', 'tarfile',
   1.131 +                             'shutil', 'struct', 'copy', 'tokenize', 'token',
   1.132 +                             'functools', 'heapq', 'bisect', 'weakref',
   1.133 +                             'reprlib'])
   1.134 +    if minver >= 2:
   1.135 +        REQUIRED_FILES[-1] = 'config-%s' % majver
   1.136 +    if minver >= 3:
   1.137 +        import sysconfig
   1.138 +        platdir = sysconfig.get_config_var('PLATDIR')
   1.139 +        REQUIRED_FILES.append(platdir)
   1.140 +        # The whole list of 3.3 modules is reproduced below - the current
   1.141 +        # uncommented ones are required for 3.3 as of now, but more may be
   1.142 +        # added as 3.3 development continues.
   1.143 +        REQUIRED_MODULES.extend([
   1.144 +            #"aifc",
   1.145 +            #"antigravity",
   1.146 +            #"argparse",
   1.147 +            #"ast",
   1.148 +            #"asynchat",
   1.149 +            #"asyncore",
   1.150 +            "base64",
   1.151 +            #"bdb",
   1.152 +            #"binhex",
   1.153 +            #"bisect",
   1.154 +            #"calendar",
   1.155 +            #"cgi",
   1.156 +            #"cgitb",
   1.157 +            #"chunk",
   1.158 +            #"cmd",
   1.159 +            #"codeop",
   1.160 +            #"code",
   1.161 +            #"colorsys",
   1.162 +            #"_compat_pickle",
   1.163 +            #"compileall",
   1.164 +            #"concurrent",
   1.165 +            #"configparser",
   1.166 +            #"contextlib",
   1.167 +            #"cProfile",
   1.168 +            #"crypt",
   1.169 +            #"csv",
   1.170 +            #"ctypes",
   1.171 +            #"curses",
   1.172 +            #"datetime",
   1.173 +            #"dbm",
   1.174 +            #"decimal",
   1.175 +            #"difflib",
   1.176 +            #"dis",
   1.177 +            #"doctest",
   1.178 +            #"dummy_threading",
   1.179 +            "_dummy_thread",
   1.180 +            #"email",
   1.181 +            #"filecmp",
   1.182 +            #"fileinput",
   1.183 +            #"formatter",
   1.184 +            #"fractions",
   1.185 +            #"ftplib",
   1.186 +            #"functools",
   1.187 +            #"getopt",
   1.188 +            #"getpass",
   1.189 +            #"gettext",
   1.190 +            #"glob",
   1.191 +            #"gzip",
   1.192 +            "hashlib",
   1.193 +            #"heapq",
   1.194 +            "hmac",
   1.195 +            #"html",
   1.196 +            #"http",
   1.197 +            #"idlelib",
   1.198 +            #"imaplib",
   1.199 +            #"imghdr",
   1.200 +            "imp",
   1.201 +            "importlib",
   1.202 +            #"inspect",
   1.203 +            #"json",
   1.204 +            #"lib2to3",
   1.205 +            #"logging",
   1.206 +            #"macpath",
   1.207 +            #"macurl2path",
   1.208 +            #"mailbox",
   1.209 +            #"mailcap",
   1.210 +            #"_markupbase",
   1.211 +            #"mimetypes",
   1.212 +            #"modulefinder",
   1.213 +            #"multiprocessing",
   1.214 +            #"netrc",
   1.215 +            #"nntplib",
   1.216 +            #"nturl2path",
   1.217 +            #"numbers",
   1.218 +            #"opcode",
   1.219 +            #"optparse",
   1.220 +            #"os2emxpath",
   1.221 +            #"pdb",
   1.222 +            #"pickle",
   1.223 +            #"pickletools",
   1.224 +            #"pipes",
   1.225 +            #"pkgutil",
   1.226 +            #"platform",
   1.227 +            #"plat-linux2",
   1.228 +            #"plistlib",
   1.229 +            #"poplib",
   1.230 +            #"pprint",
   1.231 +            #"profile",
   1.232 +            #"pstats",
   1.233 +            #"pty",
   1.234 +            #"pyclbr",
   1.235 +            #"py_compile",
   1.236 +            #"pydoc_data",
   1.237 +            #"pydoc",
   1.238 +            #"_pyio",
   1.239 +            #"queue",
   1.240 +            #"quopri",
   1.241 +            #"reprlib",
   1.242 +            "rlcompleter",
   1.243 +            #"runpy",
   1.244 +            #"sched",
   1.245 +            #"shelve",
   1.246 +            #"shlex",
   1.247 +            #"smtpd",
   1.248 +            #"smtplib",
   1.249 +            #"sndhdr",
   1.250 +            #"socket",
   1.251 +            #"socketserver",
   1.252 +            #"sqlite3",
   1.253 +            #"ssl",
   1.254 +            #"stringprep",
   1.255 +            #"string",
   1.256 +            #"_strptime",
   1.257 +            #"subprocess",
   1.258 +            #"sunau",
   1.259 +            #"symbol",
   1.260 +            #"symtable",
   1.261 +            #"sysconfig",
   1.262 +            #"tabnanny",
   1.263 +            #"telnetlib",
   1.264 +            #"test",
   1.265 +            #"textwrap",
   1.266 +            #"this",
   1.267 +            #"_threading_local",
   1.268 +            #"threading",
   1.269 +            #"timeit",
   1.270 +            #"tkinter",
   1.271 +            #"tokenize",
   1.272 +            #"token",
   1.273 +            #"traceback",
   1.274 +            #"trace",
   1.275 +            #"tty",
   1.276 +            #"turtledemo",
   1.277 +            #"turtle",
   1.278 +            #"unittest",
   1.279 +            #"urllib",
   1.280 +            #"uuid",
   1.281 +            #"uu",
   1.282 +            #"wave",
   1.283 +            #"weakref",
   1.284 +            #"webbrowser",
   1.285 +            #"wsgiref",
   1.286 +            #"xdrlib",
   1.287 +            #"xml",
   1.288 +            #"xmlrpc",
   1.289 +            #"zipfile",
   1.290 +        ])
   1.291 +    if minver >= 4:
   1.292 +        REQUIRED_MODULES.extend([
   1.293 +            'operator',
   1.294 +            '_collections_abc',
   1.295 +            '_bootlocale',
   1.296 +        ])
   1.297 +
   1.298 +if is_pypy:
   1.299 +    # these are needed to correctly display the exceptions that may happen
   1.300 +    # during the bootstrap
   1.301 +    REQUIRED_MODULES.extend(['traceback', 'linecache'])
   1.302 +
   1.303 +class Logger(object):
   1.304 +
   1.305 +    """
   1.306 +    Logging object for use in command-line script.  Allows ranges of
   1.307 +    levels, to avoid some redundancy of displayed information.
   1.308 +    """
   1.309 +
   1.310 +    DEBUG = logging.DEBUG
   1.311 +    INFO = logging.INFO
   1.312 +    NOTIFY = (logging.INFO+logging.WARN)/2
   1.313 +    WARN = WARNING = logging.WARN
   1.314 +    ERROR = logging.ERROR
   1.315 +    FATAL = logging.FATAL
   1.316 +
   1.317 +    LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
   1.318 +
   1.319 +    def __init__(self, consumers):
   1.320 +        self.consumers = consumers
   1.321 +        self.indent = 0
   1.322 +        self.in_progress = None
   1.323 +        self.in_progress_hanging = False
   1.324 +
   1.325 +    def debug(self, msg, *args, **kw):
   1.326 +        self.log(self.DEBUG, msg, *args, **kw)
   1.327 +    def info(self, msg, *args, **kw):
   1.328 +        self.log(self.INFO, msg, *args, **kw)
   1.329 +    def notify(self, msg, *args, **kw):
   1.330 +        self.log(self.NOTIFY, msg, *args, **kw)
   1.331 +    def warn(self, msg, *args, **kw):
   1.332 +        self.log(self.WARN, msg, *args, **kw)
   1.333 +    def error(self, msg, *args, **kw):
   1.334 +        self.log(self.ERROR, msg, *args, **kw)
   1.335 +    def fatal(self, msg, *args, **kw):
   1.336 +        self.log(self.FATAL, msg, *args, **kw)
   1.337 +    def log(self, level, msg, *args, **kw):
   1.338 +        if args:
   1.339 +            if kw:
   1.340 +                raise TypeError(
   1.341 +                    "You may give positional or keyword arguments, not both")
   1.342 +        args = args or kw
   1.343 +        rendered = None
   1.344 +        for consumer_level, consumer in self.consumers:
   1.345 +            if self.level_matches(level, consumer_level):
   1.346 +                if (self.in_progress_hanging
   1.347 +                    and consumer in (sys.stdout, sys.stderr)):
   1.348 +                    self.in_progress_hanging = False
   1.349 +                    sys.stdout.write('\n')
   1.350 +                    sys.stdout.flush()
   1.351 +                if rendered is None:
   1.352 +                    if args:
   1.353 +                        rendered = msg % args
   1.354 +                    else:
   1.355 +                        rendered = msg
   1.356 +                    rendered = ' '*self.indent + rendered
   1.357 +                if hasattr(consumer, 'write'):
   1.358 +                    consumer.write(rendered+'\n')
   1.359 +                else:
   1.360 +                    consumer(rendered)
   1.361 +
   1.362 +    def start_progress(self, msg):
   1.363 +        assert not self.in_progress, (
   1.364 +            "Tried to start_progress(%r) while in_progress %r"
   1.365 +            % (msg, self.in_progress))
   1.366 +        if self.level_matches(self.NOTIFY, self._stdout_level()):
   1.367 +            sys.stdout.write(msg)
   1.368 +            sys.stdout.flush()
   1.369 +            self.in_progress_hanging = True
   1.370 +        else:
   1.371 +            self.in_progress_hanging = False
   1.372 +        self.in_progress = msg
   1.373 +
   1.374 +    def end_progress(self, msg='done.'):
   1.375 +        assert self.in_progress, (
   1.376 +            "Tried to end_progress without start_progress")
   1.377 +        if self.stdout_level_matches(self.NOTIFY):
   1.378 +            if not self.in_progress_hanging:
   1.379 +                # Some message has been printed out since start_progress
   1.380 +                sys.stdout.write('...' + self.in_progress + msg + '\n')
   1.381 +                sys.stdout.flush()
   1.382 +            else:
   1.383 +                sys.stdout.write(msg + '\n')
   1.384 +                sys.stdout.flush()
   1.385 +        self.in_progress = None
   1.386 +        self.in_progress_hanging = False
   1.387 +
   1.388 +    def show_progress(self):
   1.389 +        """If we are in a progress scope, and no log messages have been
   1.390 +        shown, write out another '.'"""
   1.391 +        if self.in_progress_hanging:
   1.392 +            sys.stdout.write('.')
   1.393 +            sys.stdout.flush()
   1.394 +
   1.395 +    def stdout_level_matches(self, level):
   1.396 +        """Returns true if a message at this level will go to stdout"""
   1.397 +        return self.level_matches(level, self._stdout_level())
   1.398 +
   1.399 +    def _stdout_level(self):
   1.400 +        """Returns the level that stdout runs at"""
   1.401 +        for level, consumer in self.consumers:
   1.402 +            if consumer is sys.stdout:
   1.403 +                return level
   1.404 +        return self.FATAL
   1.405 +
   1.406 +    def level_matches(self, level, consumer_level):
   1.407 +        """
   1.408 +        >>> l = Logger([])
   1.409 +        >>> l.level_matches(3, 4)
   1.410 +        False
   1.411 +        >>> l.level_matches(3, 2)
   1.412 +        True
   1.413 +        >>> l.level_matches(slice(None, 3), 3)
   1.414 +        False
   1.415 +        >>> l.level_matches(slice(None, 3), 2)
   1.416 +        True
   1.417 +        >>> l.level_matches(slice(1, 3), 1)
   1.418 +        True
   1.419 +        >>> l.level_matches(slice(2, 3), 1)
   1.420 +        False
   1.421 +        """
   1.422 +        if isinstance(level, slice):
   1.423 +            start, stop = level.start, level.stop
   1.424 +            if start is not None and start > consumer_level:
   1.425 +                return False
   1.426 +            if stop is not None and stop <= consumer_level:
   1.427 +                return False
   1.428 +            return True
   1.429 +        else:
   1.430 +            return level >= consumer_level
   1.431 +
   1.432 +    #@classmethod
   1.433 +    def level_for_integer(cls, level):
   1.434 +        levels = cls.LEVELS
   1.435 +        if level < 0:
   1.436 +            return levels[0]
   1.437 +        if level >= len(levels):
   1.438 +            return levels[-1]
   1.439 +        return levels[level]
   1.440 +
   1.441 +    level_for_integer = classmethod(level_for_integer)
   1.442 +
   1.443 +# create a silent logger just to prevent this from being undefined
   1.444 +# will be overridden with requested verbosity main() is called.
   1.445 +logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
   1.446 +
   1.447 +def mkdir(path):
   1.448 +    if not os.path.exists(path):
   1.449 +        logger.info('Creating %s', path)
   1.450 +        os.makedirs(path)
   1.451 +    else:
   1.452 +        logger.info('Directory %s already exists', path)
   1.453 +
   1.454 +def copyfileordir(src, dest, symlink=True):
   1.455 +    if os.path.isdir(src):
   1.456 +        shutil.copytree(src, dest, symlink)
   1.457 +    else:
   1.458 +        shutil.copy2(src, dest)
   1.459 +
   1.460 +def copyfile(src, dest, symlink=True):
   1.461 +    if not os.path.exists(src):
   1.462 +        # Some bad symlink in the src
   1.463 +        logger.warn('Cannot find file %s (bad symlink)', src)
   1.464 +        return
   1.465 +    if os.path.exists(dest):
   1.466 +        logger.debug('File %s already exists', dest)
   1.467 +        return
   1.468 +    if not os.path.exists(os.path.dirname(dest)):
   1.469 +        logger.info('Creating parent directories for %s', os.path.dirname(dest))
   1.470 +        os.makedirs(os.path.dirname(dest))
   1.471 +    if not os.path.islink(src):
   1.472 +        srcpath = os.path.abspath(src)
   1.473 +    else:
   1.474 +        srcpath = os.readlink(src)
   1.475 +    if symlink and hasattr(os, 'symlink') and not is_win:
   1.476 +        logger.info('Symlinking %s', dest)
   1.477 +        try:
   1.478 +            os.symlink(srcpath, dest)
   1.479 +        except (OSError, NotImplementedError):
   1.480 +            logger.info('Symlinking failed, copying to %s', dest)
   1.481 +            copyfileordir(src, dest, symlink)
   1.482 +    else:
   1.483 +        logger.info('Copying to %s', dest)
   1.484 +        copyfileordir(src, dest, symlink)
   1.485 +
   1.486 +def writefile(dest, content, overwrite=True):
   1.487 +    if not os.path.exists(dest):
   1.488 +        logger.info('Writing %s', dest)
   1.489 +        f = open(dest, 'wb')
   1.490 +        f.write(content.encode('utf-8'))
   1.491 +        f.close()
   1.492 +        return
   1.493 +    else:
   1.494 +        f = open(dest, 'rb')
   1.495 +        c = f.read()
   1.496 +        f.close()
   1.497 +        if c != content.encode("utf-8"):
   1.498 +            if not overwrite:
   1.499 +                logger.notify('File %s exists with different content; not overwriting', dest)
   1.500 +                return
   1.501 +            logger.notify('Overwriting %s with new content', dest)
   1.502 +            f = open(dest, 'wb')
   1.503 +            f.write(content.encode('utf-8'))
   1.504 +            f.close()
   1.505 +        else:
   1.506 +            logger.info('Content %s already in place', dest)
   1.507 +
   1.508 +def rmtree(dir):
   1.509 +    if os.path.exists(dir):
   1.510 +        logger.notify('Deleting tree %s', dir)
   1.511 +        shutil.rmtree(dir)
   1.512 +    else:
   1.513 +        logger.info('Do not need to delete %s; already gone', dir)
   1.514 +
   1.515 +def make_exe(fn):
   1.516 +    if hasattr(os, 'chmod'):
   1.517 +        oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777
   1.518 +        newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777
   1.519 +        os.chmod(fn, newmode)
   1.520 +        logger.info('Changed mode of %s to %s', fn, oct(newmode))
   1.521 +
   1.522 +def _find_file(filename, dirs):
   1.523 +    for dir in reversed(dirs):
   1.524 +        files = glob.glob(os.path.join(dir, filename))
   1.525 +        if files and os.path.isfile(files[0]):
   1.526 +            return True, files[0]
   1.527 +    return False, filename
   1.528 +
   1.529 +def file_search_dirs():
   1.530 +    here = os.path.dirname(os.path.abspath(__file__))
   1.531 +    dirs = ['.', here,
   1.532 +            join(here, 'virtualenv_support')]
   1.533 +    if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
   1.534 +        # Probably some boot script; just in case virtualenv is installed...
   1.535 +        try:
   1.536 +            import virtualenv
   1.537 +        except ImportError:
   1.538 +            pass
   1.539 +        else:
   1.540 +            dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
   1.541 +    return [d for d in dirs if os.path.isdir(d)]
   1.542 +
   1.543 +
   1.544 +class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
   1.545 +    """
   1.546 +    Custom help formatter for use in ConfigOptionParser that updates
   1.547 +    the defaults before expanding them, allowing them to show up correctly
   1.548 +    in the help listing
   1.549 +    """
   1.550 +    def expand_default(self, option):
   1.551 +        if self.parser is not None:
   1.552 +            self.parser.update_defaults(self.parser.defaults)
   1.553 +        return optparse.IndentedHelpFormatter.expand_default(self, option)
   1.554 +
   1.555 +
   1.556 +class ConfigOptionParser(optparse.OptionParser):
   1.557 +    """
   1.558 +    Custom option parser which updates its defaults by checking the
   1.559 +    configuration files and environmental variables
   1.560 +    """
   1.561 +    def __init__(self, *args, **kwargs):
   1.562 +        self.config = ConfigParser.RawConfigParser()
   1.563 +        self.files = self.get_config_files()
   1.564 +        self.config.read(self.files)
   1.565 +        optparse.OptionParser.__init__(self, *args, **kwargs)
   1.566 +
   1.567 +    def get_config_files(self):
   1.568 +        config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False)
   1.569 +        if config_file and os.path.exists(config_file):
   1.570 +            return [config_file]
   1.571 +        return [default_config_file]
   1.572 +
   1.573 +    def update_defaults(self, defaults):
   1.574 +        """
   1.575 +        Updates the given defaults with values from the config files and
   1.576 +        the environ. Does a little special handling for certain types of
   1.577 +        options (lists).
   1.578 +        """
   1.579 +        # Then go and look for the other sources of configuration:
   1.580 +        config = {}
   1.581 +        # 1. config files
   1.582 +        config.update(dict(self.get_config_section('virtualenv')))
   1.583 +        # 2. environmental variables
   1.584 +        config.update(dict(self.get_environ_vars()))
   1.585 +        # Then set the options with those values
   1.586 +        for key, val in config.items():
   1.587 +            key = key.replace('_', '-')
   1.588 +            if not key.startswith('--'):
   1.589 +                key = '--%s' % key  # only prefer long opts
   1.590 +            option = self.get_option(key)
   1.591 +            if option is not None:
   1.592 +                # ignore empty values
   1.593 +                if not val:
   1.594 +                    continue
   1.595 +                # handle multiline configs
   1.596 +                if option.action == 'append':
   1.597 +                    val = val.split()
   1.598 +                else:
   1.599 +                    option.nargs = 1
   1.600 +                if option.action == 'store_false':
   1.601 +                    val = not strtobool(val)
   1.602 +                elif option.action in ('store_true', 'count'):
   1.603 +                    val = strtobool(val)
   1.604 +                try:
   1.605 +                    val = option.convert_value(key, val)
   1.606 +                except optparse.OptionValueError:
   1.607 +                    e = sys.exc_info()[1]
   1.608 +                    print("An error occured during configuration: %s" % e)
   1.609 +                    sys.exit(3)
   1.610 +                defaults[option.dest] = val
   1.611 +        return defaults
   1.612 +
   1.613 +    def get_config_section(self, name):
   1.614 +        """
   1.615 +        Get a section of a configuration
   1.616 +        """
   1.617 +        if self.config.has_section(name):
   1.618 +            return self.config.items(name)
   1.619 +        return []
   1.620 +
   1.621 +    def get_environ_vars(self, prefix='VIRTUALENV_'):
   1.622 +        """
   1.623 +        Returns a generator with all environmental vars with prefix VIRTUALENV
   1.624 +        """
   1.625 +        for key, val in os.environ.items():
   1.626 +            if key.startswith(prefix):
   1.627 +                yield (key.replace(prefix, '').lower(), val)
   1.628 +
   1.629 +    def get_default_values(self):
   1.630 +        """
   1.631 +        Overridding to make updating the defaults after instantiation of
   1.632 +        the option parser possible, update_defaults() does the dirty work.
   1.633 +        """
   1.634 +        if not self.process_default_values:
   1.635 +            # Old, pre-Optik 1.5 behaviour.
   1.636 +            return optparse.Values(self.defaults)
   1.637 +
   1.638 +        defaults = self.update_defaults(self.defaults.copy())  # ours
   1.639 +        for option in self._get_all_options():
   1.640 +            default = defaults.get(option.dest)
   1.641 +            if isinstance(default, basestring):
   1.642 +                opt_str = option.get_opt_string()
   1.643 +                defaults[option.dest] = option.check_value(opt_str, default)
   1.644 +        return optparse.Values(defaults)
   1.645 +
   1.646 +
   1.647 +def main():
   1.648 +    parser = ConfigOptionParser(
   1.649 +        version=virtualenv_version,
   1.650 +        usage="%prog [OPTIONS] DEST_DIR",
   1.651 +        formatter=UpdatingDefaultsHelpFormatter())
   1.652 +
   1.653 +    parser.add_option(
   1.654 +        '-v', '--verbose',
   1.655 +        action='count',
   1.656 +        dest='verbose',
   1.657 +        default=0,
   1.658 +        help="Increase verbosity.")
   1.659 +
   1.660 +    parser.add_option(
   1.661 +        '-q', '--quiet',
   1.662 +        action='count',
   1.663 +        dest='quiet',
   1.664 +        default=0,
   1.665 +        help='Decrease verbosity.')
   1.666 +
   1.667 +    parser.add_option(
   1.668 +        '-p', '--python',
   1.669 +        dest='python',
   1.670 +        metavar='PYTHON_EXE',
   1.671 +        help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
   1.672 +        'interpreter to create the new environment.  The default is the interpreter that '
   1.673 +        'virtualenv was installed with (%s)' % sys.executable)
   1.674 +
   1.675 +    parser.add_option(
   1.676 +        '--clear',
   1.677 +        dest='clear',
   1.678 +        action='store_true',
   1.679 +        help="Clear out the non-root install and start from scratch.")
   1.680 +
   1.681 +    parser.set_defaults(system_site_packages=False)
   1.682 +    parser.add_option(
   1.683 +        '--no-site-packages',
   1.684 +        dest='system_site_packages',
   1.685 +        action='store_false',
   1.686 +        help="DEPRECATED. Retained only for backward compatibility. "
   1.687 +             "Not having access to global site-packages is now the default behavior.")
   1.688 +
   1.689 +    parser.add_option(
   1.690 +        '--system-site-packages',
   1.691 +        dest='system_site_packages',
   1.692 +        action='store_true',
   1.693 +        help="Give the virtual environment access to the global site-packages.")
   1.694 +
   1.695 +    parser.add_option(
   1.696 +        '--always-copy',
   1.697 +        dest='symlink',
   1.698 +        action='store_false',
   1.699 +        default=True,
   1.700 +        help="Always copy files rather than symlinking.")
   1.701 +
   1.702 +    parser.add_option(
   1.703 +        '--unzip-setuptools',
   1.704 +        dest='unzip_setuptools',
   1.705 +        action='store_true',
   1.706 +        help="Unzip Setuptools when installing it.")
   1.707 +
   1.708 +    parser.add_option(
   1.709 +        '--relocatable',
   1.710 +        dest='relocatable',
   1.711 +        action='store_true',
   1.712 +        help='Make an EXISTING virtualenv environment relocatable. '
   1.713 +             'This fixes up scripts and makes all .pth files relative.')
   1.714 +
   1.715 +    parser.add_option(
   1.716 +        '--no-setuptools',
   1.717 +        dest='no_setuptools',
   1.718 +        action='store_true',
   1.719 +        help='Do not install setuptools (or pip) in the new virtualenv.')
   1.720 +
   1.721 +    parser.add_option(
   1.722 +        '--no-pip',
   1.723 +        dest='no_pip',
   1.724 +        action='store_true',
   1.725 +        help='Do not install pip in the new virtualenv.')
   1.726 +
   1.727 +    default_search_dirs = file_search_dirs()
   1.728 +    parser.add_option(
   1.729 +        '--extra-search-dir',
   1.730 +        dest="search_dirs",
   1.731 +        action="append",
   1.732 +        metavar='DIR',
   1.733 +        default=default_search_dirs,
   1.734 +        help="Directory to look for setuptools/pip distributions in. "
   1.735 +              "This option can be used multiple times.")
   1.736 +
   1.737 +    parser.add_option(
   1.738 +        '--never-download',
   1.739 +        dest="never_download",
   1.740 +        action="store_true",
   1.741 +        default=True,
   1.742 +        help="DEPRECATED. Retained only for backward compatibility. This option has no effect. "
   1.743 +              "Virtualenv never downloads pip or setuptools.")
   1.744 +
   1.745 +    parser.add_option(
   1.746 +        '--prompt',
   1.747 +        dest='prompt',
   1.748 +        help='Provides an alternative prompt prefix for this environment.')
   1.749 +
   1.750 +    parser.add_option(
   1.751 +        '--setuptools',
   1.752 +        dest='setuptools',
   1.753 +        action='store_true',
   1.754 +        help="DEPRECATED. Retained only for backward compatibility. This option has no effect.")
   1.755 +
   1.756 +    parser.add_option(
   1.757 +        '--distribute',
   1.758 +        dest='distribute',
   1.759 +        action='store_true',
   1.760 +        help="DEPRECATED. Retained only for backward compatibility. This option has no effect.")
   1.761 +
   1.762 +    if 'extend_parser' in globals():
   1.763 +        extend_parser(parser)
   1.764 +
   1.765 +    options, args = parser.parse_args()
   1.766 +
   1.767 +    global logger
   1.768 +
   1.769 +    if 'adjust_options' in globals():
   1.770 +        adjust_options(options, args)
   1.771 +
   1.772 +    verbosity = options.verbose - options.quiet
   1.773 +    logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)])
   1.774 +
   1.775 +    if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
   1.776 +        env = os.environ.copy()
   1.777 +        interpreter = resolve_interpreter(options.python)
   1.778 +        if interpreter == sys.executable:
   1.779 +            logger.warn('Already using interpreter %s' % interpreter)
   1.780 +        else:
   1.781 +            logger.notify('Running virtualenv with interpreter %s' % interpreter)
   1.782 +            env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
   1.783 +            file = __file__
   1.784 +            if file.endswith('.pyc'):
   1.785 +                file = file[:-1]
   1.786 +            popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
   1.787 +            raise SystemExit(popen.wait())
   1.788 +
   1.789 +    if not args:
   1.790 +        print('You must provide a DEST_DIR')
   1.791 +        parser.print_help()
   1.792 +        sys.exit(2)
   1.793 +    if len(args) > 1:
   1.794 +        print('There must be only one argument: DEST_DIR (you gave %s)' % (
   1.795 +            ' '.join(args)))
   1.796 +        parser.print_help()
   1.797 +        sys.exit(2)
   1.798 +
   1.799 +    home_dir = args[0]
   1.800 +
   1.801 +    if os.environ.get('WORKING_ENV'):
   1.802 +        logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
   1.803 +        logger.fatal('Please deactivate your workingenv, then re-run this script')
   1.804 +        sys.exit(3)
   1.805 +
   1.806 +    if 'PYTHONHOME' in os.environ:
   1.807 +        logger.warn('PYTHONHOME is set.  You *must* activate the virtualenv before using it')
   1.808 +        del os.environ['PYTHONHOME']
   1.809 +
   1.810 +    if options.relocatable:
   1.811 +        make_environment_relocatable(home_dir)
   1.812 +        return
   1.813 +
   1.814 +    if not options.never_download:
   1.815 +        logger.warn('The --never-download option is for backward compatibility only.')
   1.816 +        logger.warn('Setting it to false is no longer supported, and will be ignored.')
   1.817 +
   1.818 +    create_environment(home_dir,
   1.819 +                       site_packages=options.system_site_packages,
   1.820 +                       clear=options.clear,
   1.821 +                       unzip_setuptools=options.unzip_setuptools,
   1.822 +                       prompt=options.prompt,
   1.823 +                       search_dirs=options.search_dirs,
   1.824 +                       never_download=True,
   1.825 +                       no_setuptools=options.no_setuptools,
   1.826 +                       no_pip=options.no_pip,
   1.827 +                       symlink=options.symlink)
   1.828 +    if 'after_install' in globals():
   1.829 +        after_install(options, home_dir)
   1.830 +
   1.831 +def call_subprocess(cmd, show_stdout=True,
   1.832 +                    filter_stdout=None, cwd=None,
   1.833 +                    raise_on_returncode=True, extra_env=None,
   1.834 +                    remove_from_env=None):
   1.835 +    cmd_parts = []
   1.836 +    for part in cmd:
   1.837 +        if len(part) > 45:
   1.838 +            part = part[:20]+"..."+part[-20:]
   1.839 +        if ' ' in part or '\n' in part or '"' in part or "'" in part:
   1.840 +            part = '"%s"' % part.replace('"', '\\"')
   1.841 +        if hasattr(part, 'decode'):
   1.842 +            try:
   1.843 +                part = part.decode(sys.getdefaultencoding())
   1.844 +            except UnicodeDecodeError:
   1.845 +                part = part.decode(sys.getfilesystemencoding())
   1.846 +        cmd_parts.append(part)
   1.847 +    cmd_desc = ' '.join(cmd_parts)
   1.848 +    if show_stdout:
   1.849 +        stdout = None
   1.850 +    else:
   1.851 +        stdout = subprocess.PIPE
   1.852 +    logger.debug("Running command %s" % cmd_desc)
   1.853 +    if extra_env or remove_from_env:
   1.854 +        env = os.environ.copy()
   1.855 +        if extra_env:
   1.856 +            env.update(extra_env)
   1.857 +        if remove_from_env:
   1.858 +            for varname in remove_from_env:
   1.859 +                env.pop(varname, None)
   1.860 +    else:
   1.861 +        env = None
   1.862 +    try:
   1.863 +        proc = subprocess.Popen(
   1.864 +            cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
   1.865 +            cwd=cwd, env=env)
   1.866 +    except Exception:
   1.867 +        e = sys.exc_info()[1]
   1.868 +        logger.fatal(
   1.869 +            "Error %s while executing command %s" % (e, cmd_desc))
   1.870 +        raise
   1.871 +    all_output = []
   1.872 +    if stdout is not None:
   1.873 +        stdout = proc.stdout
   1.874 +        encoding = sys.getdefaultencoding()
   1.875 +        fs_encoding = sys.getfilesystemencoding()
   1.876 +        while 1:
   1.877 +            line = stdout.readline()
   1.878 +            try:
   1.879 +                line = line.decode(encoding)
   1.880 +            except UnicodeDecodeError:
   1.881 +                line = line.decode(fs_encoding)
   1.882 +            if not line:
   1.883 +                break
   1.884 +            line = line.rstrip()
   1.885 +            all_output.append(line)
   1.886 +            if filter_stdout:
   1.887 +                level = filter_stdout(line)
   1.888 +                if isinstance(level, tuple):
   1.889 +                    level, line = level
   1.890 +                logger.log(level, line)
   1.891 +                if not logger.stdout_level_matches(level):
   1.892 +                    logger.show_progress()
   1.893 +            else:
   1.894 +                logger.info(line)
   1.895 +    else:
   1.896 +        proc.communicate()
   1.897 +    proc.wait()
   1.898 +    if proc.returncode:
   1.899 +        if raise_on_returncode:
   1.900 +            if all_output:
   1.901 +                logger.notify('Complete output from command %s:' % cmd_desc)
   1.902 +                logger.notify('\n'.join(all_output) + '\n----------------------------------------')
   1.903 +            raise OSError(
   1.904 +                "Command %s failed with error code %s"
   1.905 +                % (cmd_desc, proc.returncode))
   1.906 +        else:
   1.907 +            logger.warn(
   1.908 +                "Command %s had error code %s"
   1.909 +                % (cmd_desc, proc.returncode))
   1.910 +
   1.911 +def filter_install_output(line):
   1.912 +    if line.strip().startswith('running'):
   1.913 +        return Logger.INFO
   1.914 +    return Logger.DEBUG
   1.915 +
   1.916 +def find_wheels(projects, search_dirs):
   1.917 +    """Find wheels from which we can import PROJECTS.
   1.918 +
   1.919 +    Scan through SEARCH_DIRS for a wheel for each PROJECT in turn. Return
   1.920 +    a list of the first wheel found for each PROJECT
   1.921 +    """
   1.922 +
   1.923 +    wheels = []
   1.924 +
   1.925 +    # Look through SEARCH_DIRS for the first suitable wheel. Don't bother
   1.926 +    # about version checking here, as this is simply to get something we can
   1.927 +    # then use to install the correct version.
   1.928 +    for project in projects:
   1.929 +        for dirname in search_dirs:
   1.930 +            # This relies on only having "universal" wheels available.
   1.931 +            # The pattern could be tightened to require -py2.py3-none-any.whl.
   1.932 +            files = glob.glob(os.path.join(dirname, project + '-*.whl'))
   1.933 +            if files:
   1.934 +                wheels.append(os.path.abspath(files[0]))
   1.935 +                break
   1.936 +        else:
   1.937 +            # We're out of luck, so quit with a suitable error
   1.938 +            logger.fatal('Cannot find a wheel for %s' % (project,))
   1.939 +
   1.940 +    return wheels
   1.941 +
   1.942 +def install_wheel(project_names, py_executable, search_dirs=None):
   1.943 +    if search_dirs is None:
   1.944 +        search_dirs = file_search_dirs()
   1.945 +
   1.946 +    wheels = find_wheels(['setuptools', 'pip'], search_dirs)
   1.947 +    pythonpath = os.pathsep.join(wheels)
   1.948 +    findlinks = ' '.join(search_dirs)
   1.949 +
   1.950 +    cmd = [
   1.951 +        py_executable, '-c',
   1.952 +        'import sys, pip; sys.exit(pip.main(["install", "--ignore-installed"] + sys.argv[1:]))',
   1.953 +    ] + project_names
   1.954 +    logger.start_progress('Installing %s...' % (', '.join(project_names)))
   1.955 +    logger.indent += 2
   1.956 +    try:
   1.957 +        call_subprocess(cmd, show_stdout=False,
   1.958 +            extra_env = {
   1.959 +                'PYTHONPATH': pythonpath,
   1.960 +                'PIP_FIND_LINKS': findlinks,
   1.961 +                'PIP_USE_WHEEL': '1',
   1.962 +                'PIP_PRE': '1',
   1.963 +                'PIP_NO_INDEX': '1'
   1.964 +            }
   1.965 +        )
   1.966 +    finally:
   1.967 +        logger.indent -= 2
   1.968 +        logger.end_progress()
   1.969 +
   1.970 +def create_environment(home_dir, site_packages=False, clear=False,
   1.971 +                       unzip_setuptools=False,
   1.972 +                       prompt=None, search_dirs=None, never_download=False,
   1.973 +                       no_setuptools=False, no_pip=False, symlink=True):
   1.974 +    """
   1.975 +    Creates a new environment in ``home_dir``.
   1.976 +
   1.977 +    If ``site_packages`` is true, then the global ``site-packages/``
   1.978 +    directory will be on the path.
   1.979 +
   1.980 +    If ``clear`` is true (default False) then the environment will
   1.981 +    first be cleared.
   1.982 +    """
   1.983 +    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
   1.984 +
   1.985 +    py_executable = os.path.abspath(install_python(
   1.986 +        home_dir, lib_dir, inc_dir, bin_dir,
   1.987 +        site_packages=site_packages, clear=clear, symlink=symlink))
   1.988 +
   1.989 +    install_distutils(home_dir)
   1.990 +
   1.991 +    if not no_setuptools:
   1.992 +        to_install = ['setuptools']
   1.993 +        if not no_pip:
   1.994 +            to_install.append('pip')
   1.995 +        install_wheel(to_install, py_executable, search_dirs)
   1.996 +
   1.997 +    install_activate(home_dir, bin_dir, prompt)
   1.998 +
   1.999 +def is_executable_file(fpath):
  1.1000 +    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
  1.1001 +
  1.1002 +def path_locations(home_dir):
  1.1003 +    """Return the path locations for the environment (where libraries are,
  1.1004 +    where scripts go, etc)"""
  1.1005 +    # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
  1.1006 +    # prefix arg is broken: http://bugs.python.org/issue3386
  1.1007 +    if is_win:
  1.1008 +        # Windows has lots of problems with executables with spaces in
  1.1009 +        # the name; this function will remove them (using the ~1
  1.1010 +        # format):
  1.1011 +        mkdir(home_dir)
  1.1012 +        if ' ' in home_dir:
  1.1013 +            import ctypes
  1.1014 +            GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW
  1.1015 +            size = max(len(home_dir)+1, 256)
  1.1016 +            buf = ctypes.create_unicode_buffer(size)
  1.1017 +            try:
  1.1018 +                u = unicode
  1.1019 +            except NameError:
  1.1020 +                u = str
  1.1021 +            ret = GetShortPathName(u(home_dir), buf, size)
  1.1022 +            if not ret:
  1.1023 +                print('Error: the path "%s" has a space in it' % home_dir)
  1.1024 +                print('We could not determine the short pathname for it.')
  1.1025 +                print('Exiting.')
  1.1026 +                sys.exit(3)
  1.1027 +            home_dir = str(buf.value)
  1.1028 +        lib_dir = join(home_dir, 'Lib')
  1.1029 +        inc_dir = join(home_dir, 'Include')
  1.1030 +        bin_dir = join(home_dir, 'Scripts')
  1.1031 +    if is_jython:
  1.1032 +        lib_dir = join(home_dir, 'Lib')
  1.1033 +        inc_dir = join(home_dir, 'Include')
  1.1034 +        bin_dir = join(home_dir, 'bin')
  1.1035 +    elif is_pypy:
  1.1036 +        lib_dir = home_dir
  1.1037 +        inc_dir = join(home_dir, 'include')
  1.1038 +        bin_dir = join(home_dir, 'bin')
  1.1039 +    elif not is_win:
  1.1040 +        lib_dir = join(home_dir, 'lib', py_version)
  1.1041 +        multiarch_exec = '/usr/bin/multiarch-platform'
  1.1042 +        if is_executable_file(multiarch_exec):
  1.1043 +            # In Mageia (2) and Mandriva distros the include dir must be like:
  1.1044 +            # virtualenv/include/multiarch-x86_64-linux/python2.7
  1.1045 +            # instead of being virtualenv/include/python2.7
  1.1046 +            p = subprocess.Popen(multiarch_exec, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  1.1047 +            stdout, stderr = p.communicate()
  1.1048 +            # stdout.strip is needed to remove newline character
  1.1049 +            inc_dir = join(home_dir, 'include', stdout.strip(), py_version + abiflags)
  1.1050 +        else:
  1.1051 +            inc_dir = join(home_dir, 'include', py_version + abiflags)
  1.1052 +        bin_dir = join(home_dir, 'bin')
  1.1053 +    return home_dir, lib_dir, inc_dir, bin_dir
  1.1054 +
  1.1055 +
  1.1056 +def change_prefix(filename, dst_prefix):
  1.1057 +    prefixes = [sys.prefix]
  1.1058 +
  1.1059 +    if is_darwin:
  1.1060 +        prefixes.extend((
  1.1061 +            os.path.join("/Library/Python", sys.version[:3], "site-packages"),
  1.1062 +            os.path.join(sys.prefix, "Extras", "lib", "python"),
  1.1063 +            os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"),
  1.1064 +            # Python 2.6 no-frameworks
  1.1065 +            os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"),
  1.1066 +            # System Python 2.7 on OSX Mountain Lion
  1.1067 +            os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages")))
  1.1068 +
  1.1069 +    if hasattr(sys, 'real_prefix'):
  1.1070 +        prefixes.append(sys.real_prefix)
  1.1071 +    if hasattr(sys, 'base_prefix'):
  1.1072 +        prefixes.append(sys.base_prefix)
  1.1073 +    prefixes = list(map(os.path.expanduser, prefixes))
  1.1074 +    prefixes = list(map(os.path.abspath, prefixes))
  1.1075 +    # Check longer prefixes first so we don't split in the middle of a filename
  1.1076 +    prefixes = sorted(prefixes, key=len, reverse=True)
  1.1077 +    filename = os.path.abspath(filename)
  1.1078 +    for src_prefix in prefixes:
  1.1079 +        if filename.startswith(src_prefix):
  1.1080 +            _, relpath = filename.split(src_prefix, 1)
  1.1081 +            if src_prefix != os.sep: # sys.prefix == "/"
  1.1082 +                assert relpath[0] == os.sep
  1.1083 +                relpath = relpath[1:]
  1.1084 +            return join(dst_prefix, relpath)
  1.1085 +    assert False, "Filename %s does not start with any of these prefixes: %s" % \
  1.1086 +        (filename, prefixes)
  1.1087 +
  1.1088 +def copy_required_modules(dst_prefix, symlink):
  1.1089 +    import imp
  1.1090 +    # If we are running under -p, we need to remove the current
  1.1091 +    # directory from sys.path temporarily here, so that we
  1.1092 +    # definitely get the modules from the site directory of
  1.1093 +    # the interpreter we are running under, not the one
  1.1094 +    # virtualenv.py is installed under (which might lead to py2/py3
  1.1095 +    # incompatibility issues)
  1.1096 +    _prev_sys_path = sys.path
  1.1097 +    if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
  1.1098 +        sys.path = sys.path[1:]
  1.1099 +    try:
  1.1100 +        for modname in REQUIRED_MODULES:
  1.1101 +            if modname in sys.builtin_module_names:
  1.1102 +                logger.info("Ignoring built-in bootstrap module: %s" % modname)
  1.1103 +                continue
  1.1104 +            try:
  1.1105 +                f, filename, _ = imp.find_module(modname)
  1.1106 +            except ImportError:
  1.1107 +                logger.info("Cannot import bootstrap module: %s" % modname)
  1.1108 +            else:
  1.1109 +                if f is not None:
  1.1110 +                    f.close()
  1.1111 +                # special-case custom readline.so on OS X, but not for pypy:
  1.1112 +                if modname == 'readline' and sys.platform == 'darwin' and not (
  1.1113 +                        is_pypy or filename.endswith(join('lib-dynload', 'readline.so'))):
  1.1114 +                    dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so')
  1.1115 +                elif modname == 'readline' and sys.platform == 'win32':
  1.1116 +                    # special-case for Windows, where readline is not a
  1.1117 +                    # standard module, though it may have been installed in
  1.1118 +                    # site-packages by a third-party package
  1.1119 +                    pass
  1.1120 +                else:
  1.1121 +                    dst_filename = change_prefix(filename, dst_prefix)
  1.1122 +                copyfile(filename, dst_filename, symlink)
  1.1123 +                if filename.endswith('.pyc'):
  1.1124 +                    pyfile = filename[:-1]
  1.1125 +                    if os.path.exists(pyfile):
  1.1126 +                        copyfile(pyfile, dst_filename[:-1], symlink)
  1.1127 +    finally:
  1.1128 +        sys.path = _prev_sys_path
  1.1129 +
  1.1130 +
  1.1131 +def subst_path(prefix_path, prefix, home_dir):
  1.1132 +    prefix_path = os.path.normpath(prefix_path)
  1.1133 +    prefix = os.path.normpath(prefix)
  1.1134 +    home_dir = os.path.normpath(home_dir)
  1.1135 +    if not prefix_path.startswith(prefix):
  1.1136 +        logger.warn('Path not in prefix %r %r', prefix_path, prefix)
  1.1137 +        return
  1.1138 +    return prefix_path.replace(prefix, home_dir, 1)
  1.1139 +
  1.1140 +
  1.1141 +def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, symlink=True):
  1.1142 +    """Install just the base environment, no distutils patches etc"""
  1.1143 +    if sys.executable.startswith(bin_dir):
  1.1144 +        print('Please use the *system* python to run this script')
  1.1145 +        return
  1.1146 +
  1.1147 +    if clear:
  1.1148 +        rmtree(lib_dir)
  1.1149 +        ## FIXME: why not delete it?
  1.1150 +        ## Maybe it should delete everything with #!/path/to/venv/python in it
  1.1151 +        logger.notify('Not deleting %s', bin_dir)
  1.1152 +
  1.1153 +    if hasattr(sys, 'real_prefix'):
  1.1154 +        logger.notify('Using real prefix %r' % sys.real_prefix)
  1.1155 +        prefix = sys.real_prefix
  1.1156 +    elif hasattr(sys, 'base_prefix'):
  1.1157 +        logger.notify('Using base prefix %r' % sys.base_prefix)
  1.1158 +        prefix = sys.base_prefix
  1.1159 +    else:
  1.1160 +        prefix = sys.prefix
  1.1161 +    mkdir(lib_dir)
  1.1162 +    fix_lib64(lib_dir, symlink)
  1.1163 +    stdlib_dirs = [os.path.dirname(os.__file__)]
  1.1164 +    if is_win:
  1.1165 +        stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
  1.1166 +    elif is_darwin:
  1.1167 +        stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
  1.1168 +    if hasattr(os, 'symlink'):
  1.1169 +        logger.info('Symlinking Python bootstrap modules')
  1.1170 +    else:
  1.1171 +        logger.info('Copying Python bootstrap modules')
  1.1172 +    logger.indent += 2
  1.1173 +    try:
  1.1174 +        # copy required files...
  1.1175 +        for stdlib_dir in stdlib_dirs:
  1.1176 +            if not os.path.isdir(stdlib_dir):
  1.1177 +                continue
  1.1178 +            for fn in os.listdir(stdlib_dir):
  1.1179 +                bn = os.path.splitext(fn)[0]
  1.1180 +                if fn != 'site-packages' and bn in REQUIRED_FILES:
  1.1181 +                    copyfile(join(stdlib_dir, fn), join(lib_dir, fn), symlink)
  1.1182 +        # ...and modules
  1.1183 +        copy_required_modules(home_dir, symlink)
  1.1184 +    finally:
  1.1185 +        logger.indent -= 2
  1.1186 +    mkdir(join(lib_dir, 'site-packages'))
  1.1187 +    import site
  1.1188 +    site_filename = site.__file__
  1.1189 +    if site_filename.endswith('.pyc'):
  1.1190 +        site_filename = site_filename[:-1]
  1.1191 +    elif site_filename.endswith('$py.class'):
  1.1192 +        site_filename = site_filename.replace('$py.class', '.py')
  1.1193 +    site_filename_dst = change_prefix(site_filename, home_dir)
  1.1194 +    site_dir = os.path.dirname(site_filename_dst)
  1.1195 +    writefile(site_filename_dst, SITE_PY)
  1.1196 +    writefile(join(site_dir, 'orig-prefix.txt'), prefix)
  1.1197 +    site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
  1.1198 +    if not site_packages:
  1.1199 +        writefile(site_packages_filename, '')
  1.1200 +
  1.1201 +    if is_pypy or is_win:
  1.1202 +        stdinc_dir = join(prefix, 'include')
  1.1203 +    else:
  1.1204 +        stdinc_dir = join(prefix, 'include', py_version + abiflags)
  1.1205 +    if os.path.exists(stdinc_dir):
  1.1206 +        copyfile(stdinc_dir, inc_dir, symlink)
  1.1207 +    else:
  1.1208 +        logger.debug('No include dir %s' % stdinc_dir)
  1.1209 +
  1.1210 +    platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1)
  1.1211 +    if platinc_dir != stdinc_dir:
  1.1212 +        platinc_dest = distutils.sysconfig.get_python_inc(
  1.1213 +            plat_specific=1, prefix=home_dir)
  1.1214 +        if platinc_dir == platinc_dest:
  1.1215 +            # Do platinc_dest manually due to a CPython bug;
  1.1216 +            # not http://bugs.python.org/issue3386 but a close cousin
  1.1217 +            platinc_dest = subst_path(platinc_dir, prefix, home_dir)
  1.1218 +        if platinc_dest:
  1.1219 +            # PyPy's stdinc_dir and prefix are relative to the original binary
  1.1220 +            # (traversing virtualenvs), whereas the platinc_dir is relative to
  1.1221 +            # the inner virtualenv and ignores the prefix argument.
  1.1222 +            # This seems more evolved than designed.
  1.1223 +            copyfile(platinc_dir, platinc_dest, symlink)
  1.1224 +
  1.1225 +    # pypy never uses exec_prefix, just ignore it
  1.1226 +    if sys.exec_prefix != prefix and not is_pypy:
  1.1227 +        if is_win:
  1.1228 +            exec_dir = join(sys.exec_prefix, 'lib')
  1.1229 +        elif is_jython:
  1.1230 +            exec_dir = join(sys.exec_prefix, 'Lib')
  1.1231 +        else:
  1.1232 +            exec_dir = join(sys.exec_prefix, 'lib', py_version)
  1.1233 +        for fn in os.listdir(exec_dir):
  1.1234 +            copyfile(join(exec_dir, fn), join(lib_dir, fn), symlink)
  1.1235 +
  1.1236 +    if is_jython:
  1.1237 +        # Jython has either jython-dev.jar and javalib/ dir, or just
  1.1238 +        # jython.jar
  1.1239 +        for name in 'jython-dev.jar', 'javalib', 'jython.jar':
  1.1240 +            src = join(prefix, name)
  1.1241 +            if os.path.exists(src):
  1.1242 +                copyfile(src, join(home_dir, name), symlink)
  1.1243 +        # XXX: registry should always exist after Jython 2.5rc1
  1.1244 +        src = join(prefix, 'registry')
  1.1245 +        if os.path.exists(src):
  1.1246 +            copyfile(src, join(home_dir, 'registry'), symlink=False)
  1.1247 +        copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
  1.1248 +                 symlink=False)
  1.1249 +
  1.1250 +    mkdir(bin_dir)
  1.1251 +    py_executable = join(bin_dir, os.path.basename(sys.executable))
  1.1252 +    if 'Python.framework' in prefix:
  1.1253 +        # OS X framework builds cause validation to break
  1.1254 +        # https://github.com/pypa/virtualenv/issues/322
  1.1255 +        if os.environ.get('__PYVENV_LAUNCHER__'):
  1.1256 +            del os.environ["__PYVENV_LAUNCHER__"]
  1.1257 +        if re.search(r'/Python(?:-32|-64)*$', py_executable):
  1.1258 +            # The name of the python executable is not quite what
  1.1259 +            # we want, rename it.
  1.1260 +            py_executable = os.path.join(
  1.1261 +                    os.path.dirname(py_executable), 'python')
  1.1262 +
  1.1263 +    logger.notify('New %s executable in %s', expected_exe, py_executable)
  1.1264 +    pcbuild_dir = os.path.dirname(sys.executable)
  1.1265 +    pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth')
  1.1266 +    if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')):
  1.1267 +        logger.notify('Detected python running from build directory %s', pcbuild_dir)
  1.1268 +        logger.notify('Writing .pth file linking to build directory for *.pyd files')
  1.1269 +        writefile(pyd_pth, pcbuild_dir)
  1.1270 +    else:
  1.1271 +        pcbuild_dir = None
  1.1272 +        if os.path.exists(pyd_pth):
  1.1273 +            logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth)
  1.1274 +            os.unlink(pyd_pth)
  1.1275 +
  1.1276 +    if sys.executable != py_executable:
  1.1277 +        ## FIXME: could I just hard link?
  1.1278 +        executable = sys.executable
  1.1279 +        shutil.copyfile(executable, py_executable)
  1.1280 +        make_exe(py_executable)
  1.1281 +        if is_win or is_cygwin:
  1.1282 +            pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
  1.1283 +            if os.path.exists(pythonw):
  1.1284 +                logger.info('Also created pythonw.exe')
  1.1285 +                shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
  1.1286 +            python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe')
  1.1287 +            python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe')
  1.1288 +            if os.path.exists(python_d):
  1.1289 +                logger.info('Also created python_d.exe')
  1.1290 +                shutil.copyfile(python_d, python_d_dest)
  1.1291 +            elif os.path.exists(python_d_dest):
  1.1292 +                logger.info('Removed python_d.exe as it is no longer at the source')
  1.1293 +                os.unlink(python_d_dest)
  1.1294 +            # we need to copy the DLL to enforce that windows will load the correct one.
  1.1295 +            # may not exist if we are cygwin.
  1.1296 +            py_executable_dll = 'python%s%s.dll' % (
  1.1297 +                sys.version_info[0], sys.version_info[1])
  1.1298 +            py_executable_dll_d = 'python%s%s_d.dll' % (
  1.1299 +                sys.version_info[0], sys.version_info[1])
  1.1300 +            pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll)
  1.1301 +            pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d)
  1.1302 +            pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d)
  1.1303 +            if os.path.exists(pythondll):
  1.1304 +                logger.info('Also created %s' % py_executable_dll)
  1.1305 +                shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll))
  1.1306 +            if os.path.exists(pythondll_d):
  1.1307 +                logger.info('Also created %s' % py_executable_dll_d)
  1.1308 +                shutil.copyfile(pythondll_d, pythondll_d_dest)
  1.1309 +            elif os.path.exists(pythondll_d_dest):
  1.1310 +                logger.info('Removed %s as the source does not exist' % pythondll_d_dest)
  1.1311 +                os.unlink(pythondll_d_dest)
  1.1312 +        if is_pypy:
  1.1313 +            # make a symlink python --> pypy-c
  1.1314 +            python_executable = os.path.join(os.path.dirname(py_executable), 'python')
  1.1315 +            if sys.platform in ('win32', 'cygwin'):
  1.1316 +                python_executable += '.exe'
  1.1317 +            logger.info('Also created executable %s' % python_executable)
  1.1318 +            copyfile(py_executable, python_executable, symlink)
  1.1319 +
  1.1320 +            if is_win:
  1.1321 +                for name in 'libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', 'libeay32.dll', 'ssleay32.dll', 'sqlite.dll':
  1.1322 +                    src = join(prefix, name)
  1.1323 +                    if os.path.exists(src):
  1.1324 +                        copyfile(src, join(bin_dir, name), symlink)
  1.1325 +
  1.1326 +    if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
  1.1327 +        secondary_exe = os.path.join(os.path.dirname(py_executable),
  1.1328 +                                     expected_exe)
  1.1329 +        py_executable_ext = os.path.splitext(py_executable)[1]
  1.1330 +        if py_executable_ext.lower() == '.exe':
  1.1331 +            # python2.4 gives an extension of '.4' :P
  1.1332 +            secondary_exe += py_executable_ext
  1.1333 +        if os.path.exists(secondary_exe):
  1.1334 +            logger.warn('Not overwriting existing %s script %s (you must use %s)'
  1.1335 +                        % (expected_exe, secondary_exe, py_executable))
  1.1336 +        else:
  1.1337 +            logger.notify('Also creating executable in %s' % secondary_exe)
  1.1338 +            shutil.copyfile(sys.executable, secondary_exe)
  1.1339 +            make_exe(secondary_exe)
  1.1340 +
  1.1341 +    if '.framework' in prefix:
  1.1342 +        if 'Python.framework' in prefix:
  1.1343 +            logger.debug('MacOSX Python framework detected')
  1.1344 +            # Make sure we use the the embedded interpreter inside
  1.1345 +            # the framework, even if sys.executable points to
  1.1346 +            # the stub executable in ${sys.prefix}/bin
  1.1347 +            # See http://groups.google.com/group/python-virtualenv/
  1.1348 +            #                              browse_thread/thread/17cab2f85da75951
  1.1349 +            original_python = os.path.join(
  1.1350 +                prefix, 'Resources/Python.app/Contents/MacOS/Python')
  1.1351 +        if 'EPD' in prefix:
  1.1352 +            logger.debug('EPD framework detected')
  1.1353 +            original_python = os.path.join(prefix, 'bin/python')
  1.1354 +        shutil.copy(original_python, py_executable)
  1.1355 +
  1.1356 +        # Copy the framework's dylib into the virtual
  1.1357 +        # environment
  1.1358 +        virtual_lib = os.path.join(home_dir, '.Python')
  1.1359 +
  1.1360 +        if os.path.exists(virtual_lib):
  1.1361 +            os.unlink(virtual_lib)
  1.1362 +        copyfile(
  1.1363 +            os.path.join(prefix, 'Python'),
  1.1364 +            virtual_lib,
  1.1365 +            symlink)
  1.1366 +
  1.1367 +        # And then change the install_name of the copied python executable
  1.1368 +        try:
  1.1369 +            mach_o_change(py_executable,
  1.1370 +                          os.path.join(prefix, 'Python'),
  1.1371 +                          '@executable_path/../.Python')
  1.1372 +        except:
  1.1373 +            e = sys.exc_info()[1]
  1.1374 +            logger.warn("Could not call mach_o_change: %s. "
  1.1375 +                        "Trying to call install_name_tool instead." % e)
  1.1376 +            try:
  1.1377 +                call_subprocess(
  1.1378 +                    ["install_name_tool", "-change",
  1.1379 +                     os.path.join(prefix, 'Python'),
  1.1380 +                     '@executable_path/../.Python',
  1.1381 +                     py_executable])
  1.1382 +            except:
  1.1383 +                logger.fatal("Could not call install_name_tool -- you must "
  1.1384 +                             "have Apple's development tools installed")
  1.1385 +                raise
  1.1386 +
  1.1387 +    if not is_win:
  1.1388 +        # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist
  1.1389 +        py_exe_version_major = 'python%s' % sys.version_info[0]
  1.1390 +        py_exe_version_major_minor = 'python%s.%s' % (
  1.1391 +            sys.version_info[0], sys.version_info[1])
  1.1392 +        py_exe_no_version = 'python'
  1.1393 +        required_symlinks = [ py_exe_no_version, py_exe_version_major,
  1.1394 +                         py_exe_version_major_minor ]
  1.1395 +
  1.1396 +        py_executable_base = os.path.basename(py_executable)
  1.1397 +
  1.1398 +        if py_executable_base in required_symlinks:
  1.1399 +            # Don't try to symlink to yourself.
  1.1400 +            required_symlinks.remove(py_executable_base)
  1.1401 +
  1.1402 +        for pth in required_symlinks:
  1.1403 +            full_pth = join(bin_dir, pth)
  1.1404 +            if os.path.exists(full_pth):
  1.1405 +                os.unlink(full_pth)
  1.1406 +            if symlink:
  1.1407 +                os.symlink(py_executable_base, full_pth)
  1.1408 +            else:
  1.1409 +                copyfile(py_executable, full_pth, symlink)
  1.1410 +
  1.1411 +    if is_win and ' ' in py_executable:
  1.1412 +        # There's a bug with subprocess on Windows when using a first
  1.1413 +        # argument that has a space in it.  Instead we have to quote
  1.1414 +        # the value:
  1.1415 +        py_executable = '"%s"' % py_executable
  1.1416 +    # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks
  1.1417 +    cmd = [py_executable, '-c', 'import sys;out=sys.stdout;'
  1.1418 +        'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))']
  1.1419 +    logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
  1.1420 +    try:
  1.1421 +        proc = subprocess.Popen(cmd,
  1.1422 +                            stdout=subprocess.PIPE)
  1.1423 +        proc_stdout, proc_stderr = proc.communicate()
  1.1424 +    except OSError:
  1.1425 +        e = sys.exc_info()[1]
  1.1426 +        if e.errno == errno.EACCES:
  1.1427 +            logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e))
  1.1428 +            sys.exit(100)
  1.1429 +        else:
  1.1430 +            raise e
  1.1431 +
  1.1432 +    proc_stdout = proc_stdout.strip().decode("utf-8")
  1.1433 +    proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
  1.1434 +    norm_home_dir = os.path.normcase(os.path.abspath(home_dir))
  1.1435 +    if hasattr(norm_home_dir, 'decode'):
  1.1436 +        norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding())
  1.1437 +    if proc_stdout != norm_home_dir:
  1.1438 +        logger.fatal(
  1.1439 +            'ERROR: The executable %s is not functioning' % py_executable)
  1.1440 +        logger.fatal(
  1.1441 +            'ERROR: It thinks sys.prefix is %r (should be %r)'
  1.1442 +            % (proc_stdout, norm_home_dir))
  1.1443 +        logger.fatal(
  1.1444 +            'ERROR: virtualenv is not compatible with this system or executable')
  1.1445 +        if is_win:
  1.1446 +            logger.fatal(
  1.1447 +                'Note: some Windows users have reported this error when they '
  1.1448 +                'installed Python for "Only this user" or have multiple '
  1.1449 +                'versions of Python installed. Copying the appropriate '
  1.1450 +                'PythonXX.dll to the virtualenv Scripts/ directory may fix '
  1.1451 +                'this problem.')
  1.1452 +        sys.exit(100)
  1.1453 +    else:
  1.1454 +        logger.info('Got sys.prefix result: %r' % proc_stdout)
  1.1455 +
  1.1456 +    pydistutils = os.path.expanduser('~/.pydistutils.cfg')
  1.1457 +    if os.path.exists(pydistutils):
  1.1458 +        logger.notify('Please make sure you remove any previous custom paths from '
  1.1459 +                      'your %s file.' % pydistutils)
  1.1460 +    ## FIXME: really this should be calculated earlier
  1.1461 +
  1.1462 +    fix_local_scheme(home_dir, symlink)
  1.1463 +
  1.1464 +    if site_packages:
  1.1465 +        if os.path.exists(site_packages_filename):
  1.1466 +            logger.info('Deleting %s' % site_packages_filename)
  1.1467 +            os.unlink(site_packages_filename)
  1.1468 +
  1.1469 +    return py_executable
  1.1470 +
  1.1471 +
  1.1472 +def install_activate(home_dir, bin_dir, prompt=None):
  1.1473 +    home_dir = os.path.abspath(home_dir)
  1.1474 +    if is_win or is_jython and os._name == 'nt':
  1.1475 +        files = {
  1.1476 +            'activate.bat': ACTIVATE_BAT,
  1.1477 +            'deactivate.bat': DEACTIVATE_BAT,
  1.1478 +            'activate.ps1': ACTIVATE_PS,
  1.1479 +        }
  1.1480 +
  1.1481 +        # MSYS needs paths of the form /c/path/to/file
  1.1482 +        drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/'))
  1.1483 +        home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail)
  1.1484 +
  1.1485 +        # Run-time conditional enables (basic) Cygwin compatibility
  1.1486 +        home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" %
  1.1487 +                       (home_dir, home_dir_msys))
  1.1488 +        files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh)
  1.1489 +
  1.1490 +    else:
  1.1491 +        files = {'activate': ACTIVATE_SH}
  1.1492 +
  1.1493 +        # suppling activate.fish in addition to, not instead of, the
  1.1494 +        # bash script support.
  1.1495 +        files['activate.fish'] = ACTIVATE_FISH
  1.1496 +
  1.1497 +        # same for csh/tcsh support...
  1.1498 +        files['activate.csh'] = ACTIVATE_CSH
  1.1499 +
  1.1500 +    files['activate_this.py'] = ACTIVATE_THIS
  1.1501 +    if hasattr(home_dir, 'decode'):
  1.1502 +        home_dir = home_dir.decode(sys.getfilesystemencoding())
  1.1503 +    vname = os.path.basename(home_dir)
  1.1504 +    for name, content in files.items():
  1.1505 +        content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
  1.1506 +        content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname)
  1.1507 +        content = content.replace('__VIRTUAL_ENV__', home_dir)
  1.1508 +        content = content.replace('__VIRTUAL_NAME__', vname)
  1.1509 +        content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
  1.1510 +        writefile(os.path.join(bin_dir, name), content)
  1.1511 +
  1.1512 +def install_distutils(home_dir):
  1.1513 +    distutils_path = change_prefix(distutils.__path__[0], home_dir)
  1.1514 +    mkdir(distutils_path)
  1.1515 +    ## FIXME: maybe this prefix setting should only be put in place if
  1.1516 +    ## there's a local distutils.cfg with a prefix setting?
  1.1517 +    home_dir = os.path.abspath(home_dir)
  1.1518 +    ## FIXME: this is breaking things, removing for now:
  1.1519 +    #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
  1.1520 +    writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
  1.1521 +    writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
  1.1522 +
  1.1523 +def fix_local_scheme(home_dir, symlink=True):
  1.1524 +    """
  1.1525 +    Platforms that use the "posix_local" install scheme (like Ubuntu with
  1.1526 +    Python 2.7) need to be given an additional "local" location, sigh.
  1.1527 +    """
  1.1528 +    try:
  1.1529 +        import sysconfig
  1.1530 +    except ImportError:
  1.1531 +        pass
  1.1532 +    else:
  1.1533 +        if sysconfig._get_default_scheme() == 'posix_local':
  1.1534 +            local_path = os.path.join(home_dir, 'local')
  1.1535 +            if not os.path.exists(local_path):
  1.1536 +                os.mkdir(local_path)
  1.1537 +                for subdir_name in os.listdir(home_dir):
  1.1538 +                    if subdir_name == 'local':
  1.1539 +                        continue
  1.1540 +                    copyfile(os.path.abspath(os.path.join(home_dir, subdir_name)), \
  1.1541 +                                                            os.path.join(local_path, subdir_name), symlink)
  1.1542 +
  1.1543 +def fix_lib64(lib_dir, symlink=True):
  1.1544 +    """
  1.1545 +    Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
  1.1546 +    instead of lib/pythonX.Y.  If this is such a platform we'll just create a
  1.1547 +    symlink so lib64 points to lib
  1.1548 +    """
  1.1549 +    if [p for p in distutils.sysconfig.get_config_vars().values()
  1.1550 +        if isinstance(p, basestring) and 'lib64' in p]:
  1.1551 +        # PyPy's library path scheme is not affected by this.
  1.1552 +        # Return early or we will die on the following assert.
  1.1553 +        if is_pypy:
  1.1554 +            logger.debug('PyPy detected, skipping lib64 symlinking')
  1.1555 +            return
  1.1556 +
  1.1557 +        logger.debug('This system uses lib64; symlinking lib64 to lib')
  1.1558 +
  1.1559 +        assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
  1.1560 +            "Unexpected python lib dir: %r" % lib_dir)
  1.1561 +        lib_parent = os.path.dirname(lib_dir)
  1.1562 +        top_level = os.path.dirname(lib_parent)
  1.1563 +        lib_dir = os.path.join(top_level, 'lib')
  1.1564 +        lib64_link = os.path.join(top_level, 'lib64')
  1.1565 +        assert os.path.basename(lib_parent) == 'lib', (
  1.1566 +            "Unexpected parent dir: %r" % lib_parent)
  1.1567 +        if os.path.lexists(lib64_link):
  1.1568 +            return
  1.1569 +        cp_or_ln = (os.symlink if symlink else copyfile)
  1.1570 +        cp_or_ln('lib', lib64_link)
  1.1571 +
  1.1572 +def resolve_interpreter(exe):
  1.1573 +    """
  1.1574 +    If the executable given isn't an absolute path, search $PATH for the interpreter
  1.1575 +    """
  1.1576 +    # If the "executable" is a version number, get the installed executable for
  1.1577 +    # that version
  1.1578 +    python_versions = get_installed_pythons()
  1.1579 +    if exe in python_versions:
  1.1580 +        exe = python_versions[exe]
  1.1581 +
  1.1582 +    if os.path.abspath(exe) != exe:
  1.1583 +        paths = os.environ.get('PATH', '').split(os.pathsep)
  1.1584 +        for path in paths:
  1.1585 +            if os.path.exists(os.path.join(path, exe)):
  1.1586 +                exe = os.path.join(path, exe)
  1.1587 +                break
  1.1588 +    if not os.path.exists(exe):
  1.1589 +        logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
  1.1590 +        raise SystemExit(3)
  1.1591 +    if not is_executable(exe):
  1.1592 +        logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
  1.1593 +        raise SystemExit(3)
  1.1594 +    return exe
  1.1595 +
  1.1596 +def is_executable(exe):
  1.1597 +    """Checks a file is executable"""
  1.1598 +    return os.access(exe, os.X_OK)
  1.1599 +
  1.1600 +############################################################
  1.1601 +## Relocating the environment:
  1.1602 +
  1.1603 +def make_environment_relocatable(home_dir):
  1.1604 +    """
  1.1605 +    Makes the already-existing environment use relative paths, and takes out
  1.1606 +    the #!-based environment selection in scripts.
  1.1607 +    """
  1.1608 +    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
  1.1609 +    activate_this = os.path.join(bin_dir, 'activate_this.py')
  1.1610 +    if not os.path.exists(activate_this):
  1.1611 +        logger.fatal(
  1.1612 +            'The environment doesn\'t have a file %s -- please re-run virtualenv '
  1.1613 +            'on this environment to update it' % activate_this)
  1.1614 +    fixup_scripts(home_dir, bin_dir)
  1.1615 +    fixup_pth_and_egg_link(home_dir)
  1.1616 +    ## FIXME: need to fix up distutils.cfg
  1.1617 +
  1.1618 +OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
  1.1619 +                  'activate', 'activate.bat', 'activate_this.py',
  1.1620 +                  'activate.fish', 'activate.csh']
  1.1621 +
  1.1622 +def fixup_scripts(home_dir, bin_dir):
  1.1623 +    if is_win:
  1.1624 +        new_shebang_args = (
  1.1625 +            '%s /c' % os.path.normcase(os.environ.get('COMSPEC', 'cmd.exe')),
  1.1626 +            '', '.exe')
  1.1627 +    else:
  1.1628 +        new_shebang_args = ('/usr/bin/env', sys.version[:3], '')
  1.1629 +
  1.1630 +    # This is what we expect at the top of scripts:
  1.1631 +    shebang = '#!%s' % os.path.normcase(os.path.join(
  1.1632 +        os.path.abspath(bin_dir), 'python%s' % new_shebang_args[2]))
  1.1633 +    # This is what we'll put:
  1.1634 +    new_shebang = '#!%s python%s%s' % new_shebang_args
  1.1635 +
  1.1636 +    for filename in os.listdir(bin_dir):
  1.1637 +        filename = os.path.join(bin_dir, filename)
  1.1638 +        if not os.path.isfile(filename):
  1.1639 +            # ignore subdirs, e.g. .svn ones.
  1.1640 +            continue
  1.1641 +        f = open(filename, 'rb')
  1.1642 +        try:
  1.1643 +            try:
  1.1644 +                lines = f.read().decode('utf-8').splitlines()
  1.1645 +            except UnicodeDecodeError:
  1.1646 +                # This is probably a binary program instead
  1.1647 +                # of a script, so just ignore it.
  1.1648 +                continue
  1.1649 +        finally:
  1.1650 +            f.close()
  1.1651 +        if not lines:
  1.1652 +            logger.warn('Script %s is an empty file' % filename)
  1.1653 +            continue
  1.1654 +
  1.1655 +        old_shebang = lines[0].strip()
  1.1656 +        old_shebang = old_shebang[0:2] + os.path.normcase(old_shebang[2:])
  1.1657 +
  1.1658 +        if not old_shebang.startswith(shebang):
  1.1659 +            if os.path.basename(filename) in OK_ABS_SCRIPTS:
  1.1660 +                logger.debug('Cannot make script %s relative' % filename)
  1.1661 +            elif lines[0].strip() == new_shebang:
  1.1662 +                logger.info('Script %s has already been made relative' % filename)
  1.1663 +            else:
  1.1664 +                logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
  1.1665 +                            % (filename, shebang))
  1.1666 +            continue
  1.1667 +        logger.notify('Making script %s relative' % filename)
  1.1668 +        script = relative_script([new_shebang] + lines[1:])
  1.1669 +        f = open(filename, 'wb')
  1.1670 +        f.write('\n'.join(script).encode('utf-8'))
  1.1671 +        f.close()
  1.1672 +
  1.1673 +def relative_script(lines):
  1.1674 +    "Return a script that'll work in a relocatable environment."
  1.1675 +    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"
  1.1676 +    # Find the last future statement in the script. If we insert the activation
  1.1677 +    # line before a future statement, Python will raise a SyntaxError.
  1.1678 +    activate_at = None
  1.1679 +    for idx, line in reversed(list(enumerate(lines))):
  1.1680 +        if line.split()[:3] == ['from', '__future__', 'import']:
  1.1681 +            activate_at = idx + 1
  1.1682 +            break
  1.1683 +    if activate_at is None:
  1.1684 +        # Activate after the shebang.
  1.1685 +        activate_at = 1
  1.1686 +    return lines[:activate_at] + ['', activate, ''] + lines[activate_at:]
  1.1687 +
  1.1688 +def fixup_pth_and_egg_link(home_dir, sys_path=None):
  1.1689 +    """Makes .pth and .egg-link files use relative paths"""
  1.1690 +    home_dir = os.path.normcase(os.path.abspath(home_dir))
  1.1691 +    if sys_path is None:
  1.1692 +        sys_path = sys.path
  1.1693 +    for path in sys_path:
  1.1694 +        if not path:
  1.1695 +            path = '.'
  1.1696 +        if not os.path.isdir(path):
  1.1697 +            continue
  1.1698 +        path = os.path.normcase(os.path.abspath(path))
  1.1699 +        if not path.startswith(home_dir):
  1.1700 +            logger.debug('Skipping system (non-environment) directory %s' % path)
  1.1701 +            continue
  1.1702 +        for filename in os.listdir(path):
  1.1703 +            filename = os.path.join(path, filename)
  1.1704 +            if filename.endswith('.pth'):
  1.1705 +                if not os.access(filename, os.W_OK):
  1.1706 +                    logger.warn('Cannot write .pth file %s, skipping' % filename)
  1.1707 +                else:
  1.1708 +                    fixup_pth_file(filename)
  1.1709 +            if filename.endswith('.egg-link'):
  1.1710 +                if not os.access(filename, os.W_OK):
  1.1711 +                    logger.warn('Cannot write .egg-link file %s, skipping' % filename)
  1.1712 +                else:
  1.1713 +                    fixup_egg_link(filename)
  1.1714 +
  1.1715 +def fixup_pth_file(filename):
  1.1716 +    lines = []
  1.1717 +    prev_lines = []
  1.1718 +    f = open(filename)
  1.1719 +    prev_lines = f.readlines()
  1.1720 +    f.close()
  1.1721 +    for line in prev_lines:
  1.1722 +        line = line.strip()
  1.1723 +        if (not line or line.startswith('#') or line.startswith('import ')
  1.1724 +            or os.path.abspath(line) != line):
  1.1725 +            lines.append(line)
  1.1726 +        else:
  1.1727 +            new_value = make_relative_path(filename, line)
  1.1728 +            if line != new_value:
  1.1729 +                logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
  1.1730 +            lines.append(new_value)
  1.1731 +    if lines == prev_lines:
  1.1732 +        logger.info('No changes to .pth file %s' % filename)
  1.1733 +        return
  1.1734 +    logger.notify('Making paths in .pth file %s relative' % filename)
  1.1735 +    f = open(filename, 'w')
  1.1736 +    f.write('\n'.join(lines) + '\n')
  1.1737 +    f.close()
  1.1738 +
  1.1739 +def fixup_egg_link(filename):
  1.1740 +    f = open(filename)
  1.1741 +    link = f.readline().strip()
  1.1742 +    f.close()
  1.1743 +    if os.path.abspath(link) != link:
  1.1744 +        logger.debug('Link in %s already relative' % filename)
  1.1745 +        return
  1.1746 +    new_link = make_relative_path(filename, link)
  1.1747 +    logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
  1.1748 +    f = open(filename, 'w')
  1.1749 +    f.write(new_link)
  1.1750 +    f.close()
  1.1751 +
  1.1752 +def make_relative_path(source, dest, dest_is_directory=True):
  1.1753 +    """
  1.1754 +    Make a filename relative, where the filename is dest, and it is
  1.1755 +    being referred to from the filename source.
  1.1756 +
  1.1757 +        >>> make_relative_path('/usr/share/something/a-file.pth',
  1.1758 +        ...                    '/usr/share/another-place/src/Directory')
  1.1759 +        '../another-place/src/Directory'
  1.1760 +        >>> make_relative_path('/usr/share/something/a-file.pth',
  1.1761 +        ...                    '/home/user/src/Directory')
  1.1762 +        '../../../home/user/src/Directory'
  1.1763 +        >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
  1.1764 +        './'
  1.1765 +    """
  1.1766 +    source = os.path.dirname(source)
  1.1767 +    if not dest_is_directory:
  1.1768 +        dest_filename = os.path.basename(dest)
  1.1769 +        dest = os.path.dirname(dest)
  1.1770 +    dest = os.path.normpath(os.path.abspath(dest))
  1.1771 +    source = os.path.normpath(os.path.abspath(source))
  1.1772 +    dest_parts = dest.strip(os.path.sep).split(os.path.sep)
  1.1773 +    source_parts = source.strip(os.path.sep).split(os.path.sep)
  1.1774 +    while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
  1.1775 +        dest_parts.pop(0)
  1.1776 +        source_parts.pop(0)
  1.1777 +    full_parts = ['..']*len(source_parts) + dest_parts
  1.1778 +    if not dest_is_directory:
  1.1779 +        full_parts.append(dest_filename)
  1.1780 +    if not full_parts:
  1.1781 +        # Special case for the current directory (otherwise it'd be '')
  1.1782 +        return './'
  1.1783 +    return os.path.sep.join(full_parts)
  1.1784 +
  1.1785 +
  1.1786 +
  1.1787 +############################################################
  1.1788 +## Bootstrap script creation:
  1.1789 +
  1.1790 +def create_bootstrap_script(extra_text, python_version=''):
  1.1791 +    """
  1.1792 +    Creates a bootstrap script, which is like this script but with
  1.1793 +    extend_parser, adjust_options, and after_install hooks.
  1.1794 +
  1.1795 +    This returns a string that (written to disk of course) can be used
  1.1796 +    as a bootstrap script with your own customizations.  The script
  1.1797 +    will be the standard virtualenv.py script, with your extra text
  1.1798 +    added (your extra text should be Python code).
  1.1799 +
  1.1800 +    If you include these functions, they will be called:
  1.1801 +
  1.1802 +    ``extend_parser(optparse_parser)``:
  1.1803 +        You can add or remove options from the parser here.
  1.1804 +
  1.1805 +    ``adjust_options(options, args)``:
  1.1806 +        You can change options here, or change the args (if you accept
  1.1807 +        different kinds of arguments, be sure you modify ``args`` so it is
  1.1808 +        only ``[DEST_DIR]``).
  1.1809 +
  1.1810 +    ``after_install(options, home_dir)``:
  1.1811 +
  1.1812 +        After everything is installed, this function is called.  This
  1.1813 +        is probably the function you are most likely to use.  An
  1.1814 +        example would be::
  1.1815 +
  1.1816 +            def after_install(options, home_dir):
  1.1817 +                subprocess.call([join(home_dir, 'bin', 'easy_install'),
  1.1818 +                                 'MyPackage'])
  1.1819 +                subprocess.call([join(home_dir, 'bin', 'my-package-script'),
  1.1820 +                                 'setup', home_dir])
  1.1821 +
  1.1822 +        This example immediately installs a package, and runs a setup
  1.1823 +        script from that package.
  1.1824 +
  1.1825 +    If you provide something like ``python_version='2.5'`` then the
  1.1826 +    script will start with ``#!/usr/bin/env python2.5`` instead of
  1.1827 +    ``#!/usr/bin/env python``.  You can use this when the script must
  1.1828 +    be run with a particular Python version.
  1.1829 +    """
  1.1830 +    filename = __file__
  1.1831 +    if filename.endswith('.pyc'):
  1.1832 +        filename = filename[:-1]
  1.1833 +    f = codecs.open(filename, 'r', encoding='utf-8')
  1.1834 +    content = f.read()
  1.1835 +    f.close()
  1.1836 +    py_exe = 'python%s' % python_version
  1.1837 +    content = (('#!/usr/bin/env %s\n' % py_exe)
  1.1838 +               + '## WARNING: This file is generated\n'
  1.1839 +               + content)
  1.1840 +    return content.replace('##EXT' 'END##', extra_text)
  1.1841 +
  1.1842 +##EXTEND##
  1.1843 +
  1.1844 +def convert(s):
  1.1845 +    b = base64.b64decode(s.encode('ascii'))
  1.1846 +    return zlib.decompress(b).decode('utf-8')
  1.1847 +
  1.1848 +##file site.py
  1.1849 +SITE_PY = convert("""
  1.1850 +eJzFPf1z2zaWv/OvwMqToZTIdOJ0e3tOnRsncVrvuYm3SWdz63q0lARZrCmSJUjL2pu7v/3eBwAC
  1.1851 +JCXbm+6cphNLJPDw8PC+8PAeOhgMTopCZnOxyud1KoWScTlbiiKulkos8lJUy6Sc7xdxWW3g6ewm
  1.1852 +vpZKVLlQGxVhqygInn7lJ3gqPi8TZVCAb3Fd5au4SmZxmm5EsiryspJzMa/LJLsWSZZUSZwm/4AW
  1.1853 +eRaJp1+PQXCWCZh5mshS3MpSAVwl8oW42FTLPBPDusA5v4j+GL8cjYWalUlRQYNS4wwUWcZVkEk5
  1.1854 +BzShZa2AlEkl91UhZ8kimdmG67xO56JI45kUf/87T42ahmGg8pVcL2UpRQbIAEwJsArEA74mpZjl
  1.1855 +cxkJ8UbOYhyAnzfEChjaGNdMIRmzXKR5dg1zyuRMKhWXGzGc1hUBIpTFPAecEsCgStI0WOfljRrB
  1.1856 +ktJ6rOGRiJk9/Mkwe8A8cfwu5wCOH7Pg5yy5GzNs4B4EVy2ZbUq5SO5EjGDhp7yTs4l+NkwWYp4s
  1.1857 +FkCDrBphk4ARUCJNpgcFLcd3eoVeHxBWlitjGEMiytyYX1KPKDirRJwqYNu6QBopwvydnCZxBtTI
  1.1858 +bmE4gAgkDfrGmSeqsuPQ7EQOAEpcxwqkZKXEcBUnGTDrj/GM0P5rks3ztRoRBWC1lPi1VpU7/2EP
  1.1859 +AaC1Q4BxgItlVrPO0uRGppsRIPAZsC+lqtMKBWKelHJW5WUiFQEA1DZC3gHSYxGXUpOQOdPI7Zjo
  1.1860 +TzRJMlxYFDAUeHyJJFkk13VJEiYWCXAucMX7jz+Jd6dvzk4+aB4zwFhmr1eAM0ChhXZwggHEQa3K
  1.1861 +gzQHgY6Cc/wj4vkchewaxwe8mgYH9650MIS5F1G7j7PgQHa9uHoYmGMFyoTGCqjff0OXsVoCff7n
  1.1862 +nvUOgpNtVKGJ87f1MgeZzOKVFMuY+Qs5I/hOw3kdFdXyFXCDQjgVkErh4iCCCcIDkrg0G+aZFAWw
  1.1863 +WJpkchQAhabU1l9FYIUPebZPa93iBIBQBhm8dJ6NaMRMwkS7sF6hvjCNNzQz3SSw67zKS1IcwP/Z
  1.1864 +jHRRGmc3hKMihuJvU3mdZBkihLwQhHshDaxuEuDEeSTOqRXpBdNIhKy9uCWKRA28hEwHPCnv4lWR
  1.1865 +yjGLL+rW3WqEBpOVMGudMsdBy4rUK61aM9Ve3juMvrS4jtCslqUE4PXUE7pFno/FFHQ2YVPEKxav
  1.1866 +ap0T5wQ98kSdkCeoJfTF70DRE6XqlbQvkVdAsxBDBYs8TfM1kOwoCITYw0bGKPvMCW/hHfwLcPHf
  1.1867 +VFazZRA4I1nAGhQivw0UAgGTIDPN1RoJj9s0K7eVTJKxpsjLuSxpqIcR+4ARf2BjnGvwIa+0UePp
  1.1868 +4irnq6RClTTVJjNhi5eFFevHVzxvmAZYbkU0M00bOq1wemmxjKfSuCRTuUBJ0Iv0yi47jBn0jEm2
  1.1869 +uBIrtjLwDsgiE7Yg/YoFlc6ikuQEAAwWvjhLijqlRgoZTMQw0Kog+KsYTXqunSVgbzbLASokNt8z
  1.1870 +sD+A2z9AjNbLBOgzAwigYVBLwfJNk6pEB6HRR4Fv9E1/Hh849WyhbRMPuYiTVFv5OAvO6OFpWZL4
  1.1871 +zmSBvcaaGApmmFXo2l1nQEcU88FgEATGHdoo8zVXQVVujoAVhBlnMpnWCRq+yQRNvf6hAh5FOAN7
  1.1872 +3Ww7Cw80hOn0AajkdFmU+Qpf27l9AmUCY2GPYE9ckJaR7CB7nPgKyeeq9MI0RdvtsLNAPRRc/HT6
  1.1873 +/uzL6SdxLC4blTZu67MrGPM0i4GtySIAU7WGbXQZtETFl6DuE+/BvBNTgD2j3iS+Mq5q4F1A/XNZ
  1.1874 +02uYxsx7GZx+OHlzfjr5+dPpT5NPZ59PAUGwMzLYoymjeazBYVQRCAdw5VxF2r4GnR704M3JJ/sg
  1.1875 +mCRq8u03wG7wZHgtK2DicggzHotwFd8pYNBwTE1HiGOnAVjwcDQSr8Xh06cvDwlasSk2AAzMrtMU
  1.1876 +H060RZ8k2SIPR9T4V3bpj1lJaf/t8uibK3F8LMJf49s4DMCHapoyS/xI4vR5U0joWsGfYa5GQTCX
  1.1877 +CxC9G4kCOnxKfvGIO8CSQMtc2+lf8yQz75kr3SFIfwypB+AwmczSWClsPJmEQATq0POBDhE71yh1
  1.1878 +Q+hYbNyuI40KfkoJC5thlzH+04NiPKV+iAaj6HYxjUBcV7NYSW5F04d+kwnqrMlkqAcEYSaJAYeL
  1.1879 +1VAoTBPUWWUCfi1xHuqwqcpT/InwUQuQAOLWCrUkLpLeOkW3cVpLNXQmBUQcDltkREWbKOJHcFGG
  1.1880 +YImbpRuN2tQ0PAPNgHxpDlq0bFEOP3vg74C6Mps43Ojx3otphpj+mXcahAO4nCGqe6VaUFg7iovT
  1.1881 +C/Hy+eE+ujOw55xb6njN0UInWS3twwWslpEHRph7GXlx6bJAPYtPj3bDXEV2ZbqssNBLXMpVfivn
  1.1882 +gC0ysLPK4id6AztzmMcshlUEvU7+AKtQ4zfGuA/l2YO0oO8A1FsRFLP+Zun3OBggMwWKiDfWRGq9
  1.1883 +62dTWJT5bYLOxnSjX4KtBGWJFtM4NoGzcB6ToUkEDQFecIaUWssQ1GFZs8NKeCNItBfzRrFGBO4c
  1.1884 +NfUVfb3J8nU24Z3wMSrd4ciyLgqWZl5s0CzBnngPVgiQzGFj1xCNoYDLL1C29gF5mD5MFyhLewsA
  1.1885 +BIZe0XbNgWW2ejRF3jXisAhj9EqQ8JYS/YVbMwRttQwxHEj0NrIPjJZASDA5q+CsatBMhrJmmsHA
  1.1886 +Dkl8rjuPeAvqA2hRMQKzOdTQuJGh3+URKGdx7iolpx9a5C9fvjDbqCXFVxCxKU4aXYgFGcuo2IBh
  1.1887 +TUAnGI+MozXEBmtwbgFMrTRriv1PIi/YG4P1vNCyDX4A7O6qqjg6OFiv15GOLuTl9YFaHPzxT99+
  1.1888 ++6fnrBPnc+IfmI4jLTrUFh3QO/Roo++MBXptVq7Fj0nmcyPBGkryysgVRfy+r5N5Lo72R1Z/Ihc3
  1.1889 +Zhr/Na4MKJCJGZSpDLQdNBg9UftPopdqIJ6QdbZthyP2S7RJtVbMt7rQo8rBEwC/ZZbXaKobTlDi
  1.1890 +GVg32KHP5bS+Du3gno00P2CqKKdDywP7L64QA58zDF8ZUzxBLUFsgRbfIf1PzDYxeUdaQyB50UR1
  1.1891 +ds+bfi1miDt/uLxbX9MRGjPDRCF3oET4TR4sgLZxV3Lwo11btHuOa2s+niEwlj4wzKsdyyEKDuGC
  1.1892 +azF2pc7havR4QZrWrJpBwbiqERQ0OIlTprYGRzYyRJDo3ZjNPi+sbgF0akUOTXzArAK0cMfpWLs2
  1.1893 +KzieEPLAsXhBTyS4yEedd895aes0pYBOi0c9qjBgb6HRTufAl0MDYCwG5c8Dbmm2KR9bi8Jr0AMs
  1.1894 +5xgQMtiiw0z4xvUBB3uDHnbqWP1tvZnGfSBwkYYci3oQdEL5mEcoFUhTMfR7bmNxS9zuYDstDjGV
  1.1895 +WSYSabVFuNrKo1eodhqmRZKh7nUWKZqlOXjFVisSIzXvfWeB9kH4uM+YaQnUZGjI4TQ6Jm/PE8BQ
  1.1896 +t8Pw2XWNgQY3DoMYrRJF1g3JtIR/wK2g+AYFo4CWBM2CeaiU+RP7HWTOzld/2cIeltDIEG7TbW5I
  1.1897 +x2JoOOb9nkAy6mgMSEEGJOwKI7mOrA5S4DBngTzhhtdyq3QTjEiBnDkWhNQM4E4vvQ0OPonwBIQk
  1.1898 +FCHfVUoW4pkYwPK1RfVhuvt35VIThBg6DchV0NGLYzey4UQ1jltRDp+h/fgGnZUUOXDwFFweN9Dv
  1.1899 +srlhWht0AWfdV9wWKdDIFIcZjFxUrwxh3GDyH46dFg2xzCCGobyBvCMdM9IosMutQcOCGzDemrfH
  1.1900 +0o/diAX2HYa5OpSrO9j/hWWiZrkKKWbSjl24H80VXdpYbM+T6QD+eAswGF15kGSq4xcYZfknBgk9
  1.1901 +6GEfdG+yGBaZx+U6yUJSYJp+x/7SdPCwpPSM3MEn2k4dwEQx4nnwvgQBoaPPAxAn1ASwK5eh0m5/
  1.1902 +F+zOKQ4sXO4+8Nzmy6OXV13ijrdFeOynf6lO76oyVrhaKS8aCwWuVteAo9KFycXZRh9e6sNt3CaU
  1.1903 +uYJdpPj46YtAQnBcdx1vHjf1huERm3vn5H0M6qDX7iVXa3bELoAIakVklIPw8Rz5cGQfO7kdE3sE
  1.1904 +kEcxzI5FMZA0n/wzcHYtFIyxP99kGEdrqwz8wOtvv5n0REZdJL/9ZnDPKC1i9In9sOUJ2pE5qWDX
  1.1905 +bEsZp+RqOH0oqJg1rGPbFCPW57T90zx21eNzarRs7Lu/BX4MFAypS/ARno8bsnWnih/fndoKT9up
  1.1906 +HcA6u1Xz2aNFgL19Pv0VdshKB9Vu4ySlcwWY/P4+Klezued4Rb/28CDtVDAOCfr2X+ryOXBDyNGE
  1.1907 +UXc62hk7MQHnnl2w+RSx6qKyp3MImiMwLy/APf7sQtUWzDDucz5eOOxRTd6M+5yJr1Gr+PldNJAF
  1.1908 +5tFg0Ef2rez4/zHL5/+aST5wKubk+ne0ho8E9HvNhI0HQ9PGw4fVv+yu3TXAHmCetridO9zC7tB8
  1.1909 +Vrkwzh2rJCWeou56KtaUrkCxVTwpAihz9vt64OAy6kPvt3VZ8tE1qcBClvt4HDsWmKllPL9eE7Mn
  1.1910 +Dj7ICjGxzWYUq3byevI+NRLq6LOdSdjsG/rlbJmbmJXMbpMS+oLCHYY/fPzxNOw3IRjHhU4PtyIP
  1.1911 +9xsQ7iOYNtTECR/Thyn0mC7/vFS1ty4+QU1GgIkIa7L12gc/EGziCP1rcE9EyDuw5WN23KHPlnJ2
  1.1912 +M5GUOoBsil2doPhbfI2Y2IwCP/9LxQtKYoOZzNIaacWON2YfLupsRucjlQT/SqcKY+oQJQRw+G+R
  1.1913 +xtdiSJ3nGHrS3EjRqdu41N5nUeaYnCrqZH5wncyF/K2OU9zWy8UCcMHDK/0q4uEpAiXecU4DJy0q
  1.1914 +OavLpNoACWKV67M/Sn9wGk43PNGhhyQf8zABMSHiSHzCaeN7JtzckMsEB/wTD5wk7ruxg5OsENFz
  1.1915 +eJ/lExx1Qjm+Y0aqey5Pj4P2CDkAGABQmP9gpCN3/htJr9wDRlpzl6ioJT1SupGGnJwxhDIcYaSD
  1.1916 +f9NPnxFd3tqC5fV2LK93Y3ndxvK6F8trH8vr3Vi6IoELa4NWRhL6AlftY43efBs35sTDnMazJbfD
  1.1917 +3E/M8QSIojAbbCNTnALtRbb4fI+AkNp2DpzpYZM/k3BSaZlzCFyDRO7HQyy9mTfJ605nysbRnXkq
  1.1918 +xp3dlkPk9z2IIkoVm1J3lrd5XMWRJxfXaT4FsbXojhsAY9FOJ+JYaXY7mXJ0t2WpBhf/9fmHjx+w
  1.1919 +OYIamPQG6oaLiIYFpzJ8GpfXqitNzeavAHakln4iDnXTAPceGFnjUfb4n3eU4YGMI9aUoZCLAjwA
  1.1920 +yuqyzdzcpzBsPddJUvo5MzkfNh2LQVYNmkltIdLJxcW7k88nAwr5Df534AqMoa0vHS4+poVt0PXf
  1.1921 +3OaW4tgHhFrHthrj587Jo3XDEffbWAO248O3Hhw+xGD3hgn8Wf5LKQVLAoSKdPD3MYR68B7oq7YJ
  1.1922 +HfoYRuwk/7kna+ys2HeO7DkuiiP6fccO7QH8w07cY0yAANqFGpqdQbOZail9a153UNQB+kBf76u3
  1.1923 +YO2tV3sn41PUTqLHAXQoa5ttd/+8cxo2ekpWb06/P/twfvbm4uTzD44LiK7cx08Hh+L0xy+C8kPQ
  1.1924 +gLFPFGNqRIWZSGBY3EInMc/hvxojP/O64iAx9Hp3fq5PalZY6oK5z2hzInjOaUwWGgfNOAptH+r8
  1.1925 +I8Qo1Rskp6aI0nWo5gj3SyuuZ1G5zo+mUqUpOqu13nrpWjFTU0bn2hFIHzR2ScEgOMUMXlEWe2V2
  1.1926 +hSWfAOo6qx6ktI22iSEpBQU76QLO+Zc5XfECpdQZnjSdtaK/DF1cw6tIFWkCO7lXoZUl3Q3TYxrG
  1.1927 +0Q/tATfj1acBne4wsm7Is96KBVqtVyHPTfcfNYz2Ww0YNgz2DuadSUoPoQxsTG4TITbik5xQ3sFX
  1.1928 +u/R6DRQsGB70VbiIhukSmH0Mm2uxTGADATy5BOuL+wSA0FoJ/0DgyIkOyByzM8K3q/n+X0JNEL/1
  1.1929 +L7/0NK/KdP9vooBdkOBUorCHmG7jd7DxiWQkTj++H4WMHKXmir/UWB4ADgkFQB1pp/wlPkGfDJVM
  1.1930 +Fzq/xNcH+EL7CfS61b2URam797vGIUrAEzUkr+GJMvQLMd3Lwh7jVEYt0Fj5YDHDCkI3DcF89sSn
  1.1931 +pUxTne9+9u78FHxHLMZACeJzt1MYjuMleISuk++4wrEFCg/Y4XWJbFyiC0tJFvPIa9YbtEaRo95e
  1.1932 +XoZdJwoMd3t1osBlnCgX7SFOm2GZcoIIWRnWwiwrs3arDVLYbUMUR5lhlphclJTA6vME8DI9jXlL
  1.1933 +BHslLPUwEXg+RU6yymQspskM9CioXFCoYxASJC7WMxLn5RnHwPNSmTIoeFhsyuR6WeHpBnSOqAQD
  1.1934 +m/948uX87AOVJRy+bLzuHuYc005gzEkkx5giiNEO+OKm/SFXTSZ9PKtfIQzUPvCn/YqzU455gE4/
  1.1935 +Dizin/YrrkM7dnaCPANQUHXRFg/cADjd+uSmkQXG1e6D8eOmADaY+WAoFollLzrRw51flxNty5Yp
  1.1936 +obiPefmIA5xFYVPSdGc3Ja390XNcFHjONR/2N4K3fbJlPlPoetN5sy35zf10pBBLYgGjbmt/DJMd
  1.1937 +1mmqp+Mw2zZuoW2ttrG/ZE6s1Gk3y1CUgYhDt/PIZbJ+JaybMwd6adQdYOI7ja6RxF5VPvglG2gP
  1.1938 +w8PEEruzTzEdqYyFjABGMqSu/anBh0KLAAqEsn+HjuSOR08PvTk61uD+OWrdBbbxB1CEOheXajzy
  1.1939 +EjgRvvzGjiO/IrRQjx6J0PFUMpnlNk8MP+slepUv/Dn2ygAFMVHsyji7lkOGNTYwn/nE3hKCJW3r
  1.1940 +kfoyueozLOIMnNO7LRzelYv+gxODWosROu1u5KatjnzyYIPeUpCdBPPBl/EadH9RV0NeyS3n0L21
  1.1941 +dNuh3g8Rsw+hqT59H4YYjvkt3LI+DeBeamhY6OH9tuUUltfGOLLWPraqmkL7QnuwsxK2ZpWiYxmn
  1.1942 +ONH4otYLaAzucWPyB/apThSyv3vqxJyYkAXKg7sgvbkNdINWOGHA5UpcOZpQOnxTTaPfzeWtTMFo
  1.1943 +gJEdYrXDr7baYRTZcEpvHthXY3exudj040ZvGsyOTDkGIkCFGL2Bnl0INTjgCv+idyJxdkPO8du/
  1.1944 +no3F2w8/wb9v5EewoFjzOBZ/g9HF27yEbSUX7dJtCljAUfF+Ma8VFkYSNDqh4Isn0Fu78MiLpyG6
  1.1945 +ssQvKbEKUmAybbni204ARZ4gFbI37oGpl4DfpqCr5YQaB7FvLQb6JdJge40L1oUc6JbRslqlaCac
  1.1946 +4EiziJeD87O3px8+nUbVHTK2+Tlwgid+HhZORx8Nl3gMNhb2yazGJ1eOv/yDTIsed1nvNU29DO41
  1.1947 +RQjbkcLuL/kmjdjuKeISAwai2MzzWYQtgdO5RK9ag/88craV99p3z7girOFIH541Tjw+BmqIX9r6
  1.1948 +ZwANqY+eE/UkhOIp1orx42jQb4HHgiLa8OfpzXruBsR10Q9NsI1pM+uh392qwCXTWcOznER4Hdtl
  1.1949 +MHWgaRKr1XTm1gd+zIS+CAWUGx1vyEVcp5WQGWylaG9PN1KAgndL+lhCmFXYilGdG0Vn0nW8UU7u
  1.1950 +UazEAEcdUFE9nsNQoBC23j/GN2wGsNZQ1FwCDdAJUdo25U5XVc+WLMG8EyLq9eQbrJPspZvGoynM
  1.1951 +g/LGeNb4rzBP9BYZo2tZ6fnzg+Ho8kWT4EDB6JlX0DsrwNi5bLIHGrN4+vTpQPzH/U4PoxKleX4D
  1.1952 +3hjA7nVWzun1FoOtJ2dXq+vQmzcR8ONsKS/hwRUFze3zOqOI5I6utCDS/jUwQlyb0DKjad8yxxyr
  1.1953 +K/l8mVvwOZU2GD9nCV13hBElicpW3xqF0SYjTcSSoBjCWM2SJOToBKzHJq+xFg+ji5pf5B1wfIJg
  1.1954 +xvgWD8Z4h71Ex5LyZi33WHSOxYAADyiljEejYmaqRgM8JxcbjebkLEuqpozkuXtmqq8AqOwtRpqv
  1.1955 +RLxGyTDzaBHDKev0WLVxrPOdLOptVPLZpRtnbM2SX9+HO7A2SFq+WBhM4aFZpFkuy5kxp7hiySyp
  1.1956 +HDCmHcLhznR5E1mfKOhBaQDqnazC3Eq0ffsHuy4uph/p+HjfjKSzhip7IRbHhOKslVcYRc34FH2y
  1.1957 +hLR8a76MYJQPFM3WnoA3lviDjqViDYF3b4dbzlhn+j4OTttoLukAOHQHlFWQlh09HeFcPGbhM9Nu
  1.1958 +uUUDP7QzJ9xuk7Kq43Sir32YoJ82sefpGk9bBrezwNN6K+Db5+D47uuMfXAcTHIN0hMzbk1FxrFY
  1.1959 +6MhE5FaW+UVYRY5e3iH7SuBTIGXmE1MPbWJHl5ZdbaGpTtV0VDyCemaKl7Y45KZqplNw4mI+pvQm
  1.1960 +U+6wxXn2M0fp6grxWgxfjsVha+czKzZ4kxMg+2Qe+q4YdYOpOMEAM8f2vRji9bEYvhiLP+6AHm0Z
  1.1961 +4OjQHaG9j21B2Ark5dWjyZgmUyJb2JfCfn9fncMImp5xHF21yd8l03dEpX9vUYkrBHWi8ot2onJr
  1.1962 +7K371s7HRzJcgeJYJHK+/0QhCTXSjW7ezuCEHxbQ79kcLV073lTUUOHcFDYj60YPOhrRuM12EFOU
  1.1963 +rtUX1++irmHDae8cMGkyrVRFe8scpjFq9FpEBQCTvqM0/IZ3u8B7TQrXP9t6xKqLACzYngiCrvTk
  1.1964 +A7OmYSOo9zqCj9IA9zCKCPEwtVEUrmQ9QkRCugeHmOhZ6xDb4fjfnXm4xGDbUWgHy2+/2YWnK5i9
  1.1965 +RR09C7q70sITWVte0Sy3+fQH5jxG6ev6VQLjQGlEB5xVc1UluZlHmL3Md9DkNot5hZdB0sk0msRU
  1.1966 +um4Tb6X51i/0Yyh2QMlksBbgSdULPEi+pbstTxQlveEVNd8cvhibymAGpCfwMnr5TF8BSd3M5Qe+
  1.1967 +jz3Wezd4qfsdRv/mAEsqv7d91dnN0LSOW3dB+YOFFD0bRRNLh8Yw3V8H0qxZLPDOxIaY7FvbC0De
  1.1968 +g7czBT/HXH6ag8MGG9KoD11XYzTSu021bRHg+03GNsl5UNdGkSLSu4Rtm/LcpTgfLQq6V78FwRAC
  1.1969 +cv4y5jfoCtbFkQ2xGZuCJ59DN5sTP9VNb90Z2xM0ttVNuGv63H/X3HWLwM7cJDN05u7Xl7o00H23
  1.1970 +W9E+GnB4QxPiQSUSjcbvNyauHRjrHJr+CL3+IPndTjjTLWblPjAmYwfj/cSeGntj9lfxzP2OCWH7
  1.1971 +fCGzW07c62y0pt2xGW2Of4inwMkv+NzeMEAZTXPNgbxfohv2JpwjO5HX12oS4+2OE9pkUz5XZ/dk
  1.1972 +tm3v6XI+GauN2W3hpUUAwnCTzrx1k+uBMUBX8i3TnA7l3E4jaGhKGnaykFUyZ5Ogt3YALuKIKfU3
  1.1973 +gXhOIx6kEgPdqi6LEnbDA30XMefp9KU2N0BNAG8VqxuDuukx1lfTkmKl5DBTgsxx2laSDxCBjXjH
  1.1974 +NEwm9h3wyvPmmoVkbJlBZvVKlnHVXDHkZwQksOlqRqCic1xcJzzXSGWLS1zEEssbDlIYILPfn8HG
  1.1975 +0ttU77hXYWS13cPZiXrokO9jrmxwjJHh4uTOXi/oXms1p6utXe/QNmu4zl6pBMtg7sojHaljZfxW
  1.1976 +39/Fd8xyJB/9S4d/QN7dyks/C92qM/ZuLRrOM1chdC9swhsDyDj33cPY4YDujYutDbAd39cXllE6
  1.1977 +HuaWxpaK2ifvVTjNaKMmgoQJo/dEkPyigEdGkDz4D4wg6VszwdBofLQe6C0TuCfUxOrBvYKyYQTo
  1.1978 +MwEi4QF26wJDYyqHbtJ9kavkbmAvlGZd6VTyGfOAHNm9m4xA8FWTys1Q9q6C2xVB8qWLHn9//vHN
  1.1979 +yTnRYnJx8vY/T76npCw8LmnZqgeH2LJ8n6m976V/u+E2nUjTN3iDbc8NsVzDpCF03ndyEHog9Ner
  1.1980 +9S1oW5G5r7d16NT9dDsB4run3YK6TWX3Qu74ZbrGxE2faeVpB/opJ9WaX05mgnlkTupYHJqTOPO+
  1.1981 +OTzRMtqJLW9bOCe9tatOtL+qbwHdEvce2SRrWgE8M0H+skcmpmLGBubZQWn/bz4oMxyrDc0NOiCF
  1.1982 +M+nc5EiXODKoyv//iZSg7GLc27GjOLZ3c1M7Ph5S9tJ5PPudycgQxCv3G3Tn5wr7XKZbqBAErPD0
  1.1983 +PYWMiNF/+kDVph88UeJynwqL91HZXNlfuGbauf1rgkkGlb3vS3GCEh+zQuNFnbqJA7ZPpwM5fXQa
  1.1984 +lS+cShbQfAdA50Y8FbA3+kusEKcbEcLGUbtkmBxLdNSX9TnIo910sDe0ei72t5WdumWXQrzY3nDe
  1.1985 +quzUPQ65h7qnh6pNcZ9jgTFLc1s9qXhNkPk4U9AFX57zgWfoetsPX28vXxzZwwXkd3ztKBLKJhs4
  1.1986 +hv3Sycbceamk052YpRxTuh7u1ZyQsG5x5UBln2Db3qZTkrJl/2PyHBjSwHvfHzIzPbyr9wdtTC3r
  1.1987 +HcGUxPCJGtG0nCIejbt9MupOt1FbXSBckPQAIB0VCLAQTEc3OgmiG87yHj7Xu8FpTdfxuidMoSMV
  1.1988 +lCzmcwT3ML5fg1+7OxUSP6g7o2j6c4M2B+olB+Fm34FbjbxQyHaT0J56wwdbXACuye7v/+IB/btp
  1.1989 +jLb74S6/2rZ62VsHyL4sZr5iZlCLROZxBEYG9OaQtDWWSxhBx2toGjq6DNXMDfkCHT/KpsXLtmmD
  1.1990 +Qc7sRHsA1igE/wfVIOdx
  1.1991 +""")
  1.1992 +
  1.1993 +##file activate.sh
  1.1994 +ACTIVATE_SH = convert("""
  1.1995 +eJytVVFvokAQfudXTLEPtTlLeo9tvMSmJpq02hSvl7u2wRUG2QR2DSxSe7n/frOACEVNLlceRHa+
  1.1996 +nfl25pvZDswCnoDPQ4QoTRQsENIEPci4CsBMZBq7CAsuLOYqvmYKTTj3YxnBgiXBudGBjUzBZUJI
  1.1997 +BXEqgCvweIyuCjeG4eF2F5x14bcB9KQiQQWrjSddI1/oQIx6SYYeoFjzWIoIhYI1izlbhJjkKO7D
  1.1998 +M/QEmKfO9O7WeRo/zr4P7pyHwWxkwitcgwpQ5Ej96OX+PmiFwLeVjFUOrNYKaq1Nud3nR2n8nI2m
  1.1999 +k9H0friPTGVsUdptaxGrTEfpNVFEskxpXtUkkCkl1UNF9cgLBkx48J4EXyALuBtAwNYIjF5kcmUU
  1.2000 +abMKmMq1ULoiRbgsDEkTSsKSGFCJ6Z8vY/2xYiSacmtyAfCDdCNTVZoVF8vSTQOoEwSnOrngBkws
  1.2001 +MYGMBMg8/bMBLSYKS7pYEXP0PqT+ZmBT0Xuy+Pplj5yn4aM9nk72JD8/Wi+Gr98sD9eWSMOwkapD
  1.2002 +BbUv91XSvmyVkICt2tmXR4tWmrcUCsjWOpw87YidEC8i0gdTSOFhouJUNxR+4NYBG0MftoCTD9F7
  1.2003 +2rTtxG3oPwY1b2HncYwhrlmj6Wq924xtGDWqfdNxap+OYxplEurnMVo9RWks+rH8qKEtx7kZT5zJ
  1.2004 +4H7oOFclrN6uFe+d+nW2aIUsSgs/42EIPuOhXq+jEo3S6tX6w2ilNkDnIpHCWdEQhFgwj9pkk7FN
  1.2005 +l/y5eQvRSIQ5+TrL05lewxWpt/Lbhes5cJF3mLET1MGhcKCF+40tNWnUulxrpojwDo2sObdje3Bz
  1.2006 +N3QeHqf3D7OjEXMVV8LN3ZlvuzoWHqiUcNKHtwNd0IbvPGKYYM31nPKCgkUILw3KL+Y8l7aO1ArS
  1.2007 +Ad37nIU0fCj5NE5gQCuC5sOSu+UdI2NeXg/lFkQIlFpdWVaWZRfvqGiirC9o6liJ9FXGYrSY9mI1
  1.2008 +D/Ncozgn13vJvsznr7DnkJWXsyMH7e42ljdJ+aqNDF1bFnKWFLdj31xtaJYK6EXFgqmV/ymD/ROG
  1.2009 ++n8O9H8f5vsGOWXsL1+1k3g=
  1.2010 +""")
  1.2011 +
  1.2012 +##file activate.fish
  1.2013 +ACTIVATE_FISH = convert("""
  1.2014 +eJydVW2P2jgQ/s6vmAZQoVpA9/WkqqJaTou0u6x2uZVOVWWZZEKsS+yc7UDpr+84bziQbauLxEvs
  1.2015 +eXnsZ56ZIWwTYSAWKUJWGAs7hMJgBEdhEwiMKnSIsBNywUMrDtziPBYmCeBDrFUG7v8HmCTW5n8u
  1.2016 +Fu7NJJim81Bl08EQTqqAkEupLOhCgrAQCY2hTU+DQVxIiqgkRNiEBphFEKy+kd1BaFvwFOUBuIxA
  1.2017 +oy20BKtAKp3xFMo0QNtCK5mhtMEA6BmSpUELKo38TThwLfguRVNaiRgs0llnEoIR29zfstf18/bv
  1.2018 +5T17Wm7vAiiN3ONCzfbfwC3DtWXXDqHfAGX0q6z/bO82j3ebh1VwnbrduwTQbvwcRtesAfMGor/W
  1.2019 +L3fs6Xnz8LRlm9fV8/P61sM0LDNwCZjl9gSpCokJRzpryGQ5t8kNGFUt51QjOZGu0Mj35FlYlXEr
  1.2020 +yC09EVOp4lEXfF84Lz1qbhBsgl59vDedXI3rTV03xipduSgt9kLytI3XmBp3aV6MPoMQGNUU62T6
  1.2021 +uQdeefTy1Hfj10zVHg2pq8fXDoHBiOv94csfXwN49xECqWREy7pwukKfvxdMY2j23vXDPuuxxeE+
  1.2022 +JOdCOhxCE3N44B1ZeSLuZh8Mmkr2wEPAmPfKWHA2uxIRjEopdbQYjDz3BWOf14/scfmwoki1eQvX
  1.2023 +ExBdF60Mqh+Y/QcX4uiH4Amwzx79KOVFtbL63sXJbtcvy8/3q5rupmO5CnE91wBviQAhjUUegYpL
  1.2024 +vVEbpLt2/W+PklRgq5Ku6mp+rpMhhCo/lXthQTxJ2ysO4Ka0ad97S7VT/n6YXus6fzk3fLnBZW5C
  1.2025 +KDC6gSO62QDqgFqLCCtPmjegjnLeAdArtSE8VYGbAJ/aLb+vnQutFhk768E9uRbSxhCMzdgEveYw
  1.2026 +IZ5ZqFKl6+kz7UR4U+buqQZXu9SIujrAfD7f0FXpozB4Q0gwp31H9mVTZGGC4b871/wm7lvyDLu1
  1.2027 +FUyvTj/yvD66k3UPTs08x1AQQaGziOl0S1qRkPG9COtBTSTWM9NzQ4R64B+Px/l3tDzCgxv5C6Ni
  1.2028 +e+QaF9xFWrxx0V/G5uvYQOdiZzvYpQUVQSIsTr1TTghI33GnPbTA7/GCqcE3oE3GZurq4HeQXQD6
  1.2029 +32XS1ITj/qLjN72ob0hc5C9bzw8MhfmL
  1.2030 +""")
  1.2031 +
  1.2032 +##file activate.csh
  1.2033 +ACTIVATE_CSH = convert("""
  1.2034 +eJx9VG1P2zAQ/u5fcYQKNgTNPtN1WxlIQ4KCUEGaxuQ6yYVYSuzKdhqVX7+zk3bpy5YPUXL3PPfc
  1.2035 +ne98DLNCWshliVDV1kGCUFvMoJGugMjq2qQIiVSxSJ1cCofD1BYRnOVGV0CfZ0N2DD91DalQSjsw
  1.2036 +tQLpIJMGU1euvPe7QeJlkKzgWixlhnAt4aoUVsLnLBiy5NtbJWQ5THX1ZciYKKWwkOFaE04dUm6D
  1.2037 +r/zh7pq/3D7Nnid3/HEy+wFHY/gEJydg0aFaQrBFgz1c5DG1IhTs+UZgsBC2GMFBlaeH+8dZXwcW
  1.2038 +VPvCjXdlAvCfQsE7al0+07XjZvrSCUevR5dnkVeKlFYZmUztG4BdzL2u9KyLVabTU0bdfg7a0hgs
  1.2039 +cSmUg6UwUiQl2iHrcbcVGNvPCiLOe7+cRwG13z9qRGgx2z6DHjfm/Op2yqeT+xvOLzs0PTKHDz2V
  1.2040 +tkckFHoQfQRXoGJAj9el0FyJCmEMhzgMS4sB7KPOE2ExoLcSieYwDvR+cP8cg11gKkVJc2wRcm1g
  1.2041 +QhYFlXiTaTfO2ki0fQoiFM4tLuO4aZrhOzqR4dIPcWx17hphMBY+Srwh7RTyN83XOWkcSPh1Pg/k
  1.2042 +TXX/jbJTbMtUmcxZ+/bbqOsy82suFQg/BhdSOTRhMNBHlUarCpU7JzBhmkKmRejKOQzayQe6MWoa
  1.2043 +n1wqWmuh6LZAaHxcdeqIlVLhIBJdO9/kbl0It2oEXQj+eGjJOuvOIR/YGRqvFhttUB2XTvLXYN2H
  1.2044 +37CBdbW2W7j2r2+VsCn0doVWcFG1/4y1VwBjfwAyoZhD
  1.2045 +""")
  1.2046 +
  1.2047 +##file activate.bat
  1.2048 +ACTIVATE_BAT = convert("""
  1.2049 +eJx9UdEKgjAUfW6wfxjiIH+hEDKUFHSKLCMI7kNOEkIf9P9pTJ3OLJ/03HPPPed4Es9XS9qqwqgT
  1.2050 +PbGKKOdXL4aAFS7A4gvAwgijuiKlqOpGlATS2NeMLE+TjJM9RkQ+SmqAXLrBo1LLIeLdiWlD6jZt
  1.2051 +r7VNubWkndkXaxg5GO3UaOOKS6drO3luDDiO5my3iA0YAKGzPRV1ack8cOdhysI0CYzIPzjSiH5X
  1.2052 +0QcvC8Lfaj0emsVKYF2rhL5L3fCkVjV76kShi59NHwDniAHzkgDgqBcwOgTMx+gDQQqXCw==
  1.2053 +""")
  1.2054 +
  1.2055 +##file deactivate.bat
  1.2056 +DEACTIVATE_BAT = convert("""
  1.2057 +eJxzSE3OyFfIT0vj4ipOLVEI8wwKCXX0iXf1C7Pl4spMU0hJTcvMS01RiPf3cYmHyQYE+fsGhCho
  1.2058 +cCkAAUibEkTEVhWLMlUlLk6QGixStlyaeCyJDPHw9/Pw93VFsQguim4ZXAJoIUw5DhX47XUM8UCx
  1.2059 +EchHtwsohN1bILUgw61c/Vy4AJYPYm4=
  1.2060 +""")
  1.2061 +
  1.2062 +##file activate.ps1
  1.2063 +ACTIVATE_PS = convert("""
  1.2064 +eJylWdmS40Z2fVeE/oHT6rCloNUEAXDThB6wAyQAEjsB29GBjdgXYiWgmC/zgz/Jv+AEWNVd3S2N
  1.2065 +xuOKYEUxM+/Jmzfvcm7W//zXf/+wUMOoXtyi1F9kbd0sHH/hFc2iLtrK9b3FrSqyxaVQwr8uhqJd
  1.2066 +uHaeg9mqzRdR8/13Pyy8qPLdJh0+LMhi0QCoXxYfFh9WtttEnd34H8p6/f1300KauwrULws39e18
  1.2067 +0ZaLNm9rgN/ZVf3h++/e124Vlc0vKsspHy+Yyi5+XbzPhijvCtduoiL/kA1ukWV27n0o7Sb8LIFj
  1.2068 +CvWR5GQgUJdp1Pw8TS9+rPy6SDv/+e3d+0+4qw8f3v20+PliV37efEYBAB9FTKC+RHn/Cfxn3rdv
  1.2069 +00Fube5O+iyCtHDs9BfPfz3q4sfFv9d91Ljhfy7ei0VO+nVTtdOkv/jpt0l2AX6iG1jXgKnnDuD4
  1.2070 +ke2k/i8fzzz5UedkVcP4pwF+Wvz2FJl+3vt598urXf5Y6LNA5WcFOP7r0sW7b9a+W/xcu0Xpv5zk
  1.2071 +Kfq3P9Dz9di/fCxS72MXVU1rpx9L4Bxl85Wmn5a+zP76Zuh3pL9ROWr87PN+//GHIl+oOtvn9XSU
  1.2072 +qH+p0gQBFnx1uV+JLH5O5zv+PXW+WepXVVHZT0+oQezkIATcIm+ivPV/z5J/+cYj3ir4w0Lx09vC
  1.2073 +e5n/y5/Y5LPPfdrqb88ga/PabxZRVfmp39l588m/6u+/e+OpP+dF7n1WZpJ9//Z4v372fDDz9eHB
  1.2074 +7Juvs/BLMHzrxL9+9twXpJfhd1/DrpQ5Euu/vlss3wp9HXC/54C/Ld69m6zwdx3tC0d8daSv0V8B
  1.2075 +n4b9YYF53sJelJV/ix6LZspw/sJtqyl5LJ5r/23htA1Imfm/gt9R7dqVB1LjhydAX4Gb+zksQF59
  1.2076 +9+P7H//U+376afFuvh2/T6P85Xr/5c8C6OXyFY4BGuN+EE0+GeR201b+wkkLN5mmBY5TfMw8ngqL
  1.2077 +CztXxCSXKMCYrRIElWkEJlEPYsSOeKBVZCAQTKBhApMwRFQzmCThE0YQu2CdEhgjbgmk9GluHpfR
  1.2078 +/hhwJCZhGI5jt5FsAkOrObVyE6g2y1snyhMGFlDY1x+BoHpCMulTj5JYWNAYJmnKpvLxXgmQ8az1
  1.2079 +4fUGxxcitMbbhDFcsiAItg04E+OSBIHTUYD1HI4FHH4kMREPknuYRMyhh3AARWMkfhCketqD1CWJ
  1.2080 +mTCo/nhUScoQcInB1hpFhIKoIXLo5jLpwFCgsnLCx1QlEMlz/iFEGqzH3vWYcpRcThgWnEKm0QcS
  1.2081 +rA8ek2a2IYYeowUanOZOlrbWSJUC4c7y2EMI3uJPMnMF/SSXdk6E495VLhzkWHps0rOhKwqk+xBI
  1.2082 +DhJirhdUCTamMfXz2Hy303hM4DFJ8QL21BcPBULR+gcdYxoeiDqOFSqpi5B5PUISfGg46gFZBPo4
  1.2083 +jdh8lueaWuVSMTURfbAUnLINr/QYuuYoMQV6l1aWxuZVTjlaLC14UzqZ+ziTGDzJzhiYoPLrt3uI
  1.2084 +tXkVR47kAo09lo5BD76CH51cTt1snVpMOttLhY93yxChCQPI4OBecS7++h4p4Bdn4H97bJongtPk
  1.2085 +s9gQnXku1vzsjjmX4/o4YUDkXkjHwDg5FXozU0fW4y5kyeYW0uJWlh536BKr0kMGjtzTkng6Ep62
  1.2086 +uTWnQtiIqKnEsx7e1hLtzlXs7Upw9TwEnp0t9yzCGgUJIZConx9OHJArLkRYW0dW42G9OeR5Nzwk
  1.2087 +yk1mX7du5RGHT7dka7N3AznmSif7y6tuKe2N1Al/1TUPRqH6E2GLVc27h9IptMLkCKQYRqPQJgzV
  1.2088 +2m6WLsSipS3v3b1/WmXEYY1meLEVIU/arOGVkyie7ZsH05ZKpjFW4cpY0YkjySpSExNG2TS8nnJx
  1.2089 +nrQmWh2WY3cP1eISP9wbaVK35ZXc60yC3VN/j9n7UFoK6zvjSTE2+Pvz6Mx322rnftfP8Y0XKIdv
  1.2090 +Qd7AfK0nexBTMqRiErvCMa3Hegpfjdh58glW2oNMsKeAX8x6YJLZs9K8/ozjJkWL+JmECMvhQ54x
  1.2091 +9rsTHwcoGrDi6Y4I+H7yY4/rJVPAbYymUH7C2D3uiUS3KQ1nrCAUkE1dJMneDQIJMQQx5SONxoEO
  1.2092 +OEn1/Ig1eBBUeEDRuOT2WGGGE4bNypBLFh2PeIg3bEbg44PHiqNDbGIQm50LW6MJU62JHCGBrmc9
  1.2093 +2F7WBJrrj1ssnTAK4sxwRgh5LLblhwNAclv3Gd+jC/etCfyfR8TMhcWQz8TBIbG8IIyAQ81w2n/C
  1.2094 +mHWAwRzxd3WoBY7BZnsqGOWrOCKwGkMMNfO0Kci/joZgEocLjNnzgcmdehPHJY0FudXgsr+v44TB
  1.2095 +I3jnMGnsK5veAhgi9iXGifkHMOC09Rh9cAw9sQ0asl6wKMk8mpzFYaaDSgG4F0wisQDDBRpjCINg
  1.2096 +FIxhlhQ31xdSkkk6odXZFpTYOQpOOgw9ugM2cDQ+2MYa7JsEirGBrOuxsQy5nPMRdYjsTJ/j1iNw
  1.2097 +FeSt1jY2+dd5yx1/pzZMOQXUIDcXeAzR7QlDRM8AMkUldXOmGmvYXPABjxqkYKO7VAY6JRU7kpXr
  1.2098 ++Epu2BU3qFFXClFi27784LrDZsJwbNlDw0JzhZ6M0SMXE4iBHehCpHVkrQhpTFn2dsvsZYkiPEEB
  1.2099 +GSEAwdiur9LS1U6P2U9JhGp4hnFpJo4FfkdJHcwV6Q5dV1Q9uNeeu7rV8PAjwdFg9RLtroifOr0k
  1.2100 +uOiRTo/obNPhQIf42Fr4mtThWoSjitEdAmFW66UCe8WFjPk1YVNpL9srFbond7jrLg8tqAasIMpy
  1.2101 +zkH0SY/6zVAwJrEc14zt14YRXdY+fcJ4qOd2XKB0/Kghw1ovd11t2o+zjt+txndo1ZDZ2T+uMVHT
  1.2102 +VSXhedBAHoJIID9xm6wPQI3cXY+HR7vxtrJuCKh6kbXaW5KkVeJsdsjqsYsOwYSh0w5sMbu7LF8J
  1.2103 +5T7U6LJdiTx+ca7RKlulGgS5Z1JSU2Llt32cHFipkaurtBrvNX5UtvNZjkufZ/r1/XyLl6yOpytL
  1.2104 +Km8Fn+y4wkhlqZP5db0rooqy7xdL4wxzFVTX+6HaxuQJK5E5B1neSSovZ9ALB8091dDbbjVxhWNY
  1.2105 +Ve5hn1VnI9OF0wpvaRm7SZuC1IRczwC7GnkhPt3muHV1YxUJfo+uh1sYnJy+vI0ZwuPV2uqWJYUH
  1.2106 +bmBsi1zmFSxHrqwA+WIzLrHkwW4r+bad7xbOzJCnKIa3S3YvrzEBK1Dc0emzJW+SqysQfdEDorQG
  1.2107 +9ZJlbQzEHQV8naPaF440YXzJk/7vHGK2xwuP+Gc5xITxyiP+WQ4x18oXHjFzCBy9kir1EFTAm0Zq
  1.2108 +LYwS8MpiGhtfxiBRDXpxDWxk9g9Q2fzPPAhS6VFDAc/aiNGatUkPtZIStZFQ1qD0IlJa/5ZPAi5J
  1.2109 +ySp1ETDomZMnvgiysZSBfMikrSDte/K5lqV6iwC5q7YN9I1dBZXUytDJNqU74MJsUyNNLAPopWK3
  1.2110 +tzmLkCiDyl7WQnj9sm7Kd5kzgpoccdNeMw/6zPVB3pUwMgi4C7hj4AMFAf4G27oXH8NNT9zll/sK
  1.2111 +S6wVlQwazjxWKWy20ZzXb9ne8ngGalPBWSUSj9xkc1drsXkZ8oOyvYT3e0rnYsGwx85xZB9wKeKg
  1.2112 +cJKZnamYwiaMymZvzk6wtDUkxmdUg0mPad0YHtvzpjEfp2iMxvORhnx0kCVLf5Qa43WJsVoyfEyI
  1.2113 +pzmf8ruM6xBr7dnBgzyxpqXuUPYaKahOaz1LrxNkS/Q3Ae5AC+xl6NbxAqXXlzghZBZHmOrM6Y6Y
  1.2114 +ctAkltwlF7SKEsShjVh7QHuxMU0a08/eiu3x3M+07OijMcKFFltByXrpk8w+JNnZpnp3CfgjV1Ax
  1.2115 +gUYCnWwYow42I5wHCcTzLXK0hMZN2DrPM/zCSqe9jRSlJnr70BPE4+zrwbk/xVIDHy2FAQyHoomT
  1.2116 +Tt5jiM68nBQut35Y0qLclLiQrutxt/c0OlSqXAC8VrxW97lGoRWzhOnifE2zbF05W4xuyhg7JTUL
  1.2117 +aqJ7SWDywhjlal0b+NLTpERBgnPW0+Nw99X2Ws72gOL27iER9jgzj7Uu09JaZ3n+hmCjjvZpjNst
  1.2118 +vOWWTbuLrg+/1ltX8WpPauEDEvcunIgTxuMEHweWKCx2KQ9DU/UKdO/3za4Szm2iHYL+ss9AAttm
  1.2119 +gZHq2pkUXFbV+FiJCKrpBms18zH75vax5jSo7FNunrVWY3Chvd8KKnHdaTt/6ealwaA1x17yTlft
  1.2120 +8VBle3nAE+7R0MScC3MJofNCCkA9PGKBgGMYEwfB2QO5j8zUqa8F/EkWKCzGQJ5EZ05HTly1B01E
  1.2121 +z813G5BY++RZ2sxbQS8ZveGPJNabp5kXAeoign6Tlt5+L8i5ZquY9+S+KEUHkmYMRFBxRrHnbl2X
  1.2122 +rVemKnG+oB1yd9+zT+4c43jQ0wWmQRR6mTCkY1q3VG05Y120ZzKOMBe6Vy7I5Vz4ygPB3yY4G0FP
  1.2123 +8RxiMx985YJPXsgRU58EuHj75gygTzejP+W/zKGe78UQN3yOJ1aMQV9hFH+GAfLRsza84WlPLAI/
  1.2124 +9G/5JdcHftEfH+Y3/fHUG7/o8bv98dzzy3e8S+XCvgqB+VUf7sH0yDHpONdbRE8tAg9NWOzcTJ7q
  1.2125 +TuAxe/AJ07c1Rs9okJvl1/0G60qvbdDzz5zO0FuPFQIHNp9y9Bd1CufYVx7dB26mAxwa8GMNrN/U
  1.2126 +oGbNZ3EQ7inLzHy5tRg9AXJrN8cB59cCUBeCiVO7zKM0jU0MamhnRThkg/NMmBOGb6StNeD9tDfA
  1.2127 +7czsAWopDdnGoXUHtA+s/k0vNPkBcxEI13jVd/axp85va3LpwGggXXWw12Gwr/JGAH0b8CPboiZd
  1.2128 +QO1l0mk/UHukud4C+w5uRoNzpCmoW6GbgbMyaQNkga2pQINB18lOXOCJzSWPFOhZcwzdgrsQnne7
  1.2129 +nvjBi+7cP2BbtBeDOW5uOLGf3z94FasKIguOqJl+8ss/6Kumns4cuWbqq5592TN/RNIbn5Qo6qbi
  1.2130 +O4F0P9txxPAwagqPlftztO8cWBzdN/jz3b7GD6JHYP/Zp4ToAMaA74M+EGSft3hEGMuf8EwjnTk/
  1.2131 +nz/P7SLipB/ogQ6xNX0fDqNncMCfHqGLCMM0ZzFa+6lPJYQ5p81vW4HkCvidYf6kb+P/oB965g8K
  1.2132 +C6uR0rdjX1DNKc5pOSTquI8uQ6KXxYaKBn+30/09tK4kMpJPgUIQkbENEPbuezNPPje2Um83SgyX
  1.2133 +GTCJb6MnGVIpgncdQg1qz2bvPfxYD9fewCXDomx9S+HQJuX6W3VAL+v5WZMudRQZk9ZdOk6GIUtC
  1.2134 +PqEb/uwSIrtR7/edzqgEdtpEwq7p2J5OQV+RLrmtTvFwFpf03M/VrRyTZ73qVod7v7Jh2Dwe5J25
  1.2135 +JqFOU2qEu1sP+CRotklediycKfLjeIZzjJQsvKmiGSNQhxuJpKa+hoWUizaE1PuIRGzJqropwgVB
  1.2136 +oo1hr870MZLgnXF5ZIpr6mF0L8aSy2gVnTAuoB4WEd4d5NPVC9TMotYXERKlTcwQ2KiB/C48AEfH
  1.2137 +Qbyq4CN8xTFnTvf/ebOc3isnjD95s0QF0nx9s+y+zMmz782xL0SgEmRpA3x1w1Ff9/74xcxKEPdS
  1.2138 +IEFTz6GgU0+BK/UZ5Gwbl4gZwycxEw+Kqa5QmMkh4OzgzEVPnDAiAOGBFaBW4wkDmj1G4RyElKgj
  1.2139 +NlLCq8zsp085MNh/+R4t1Q8yxoSv8PUpTt7izZwf2BTHZZ3pIZpUIpuLkL1nNL6sYcHqcKm237wp
  1.2140 +T2+RCjgXweXd2Zp7ZM8W6dG5bZsqo0nrJBTx8EC0+CQQdzEGnabTnkzofu1pYkWl4E7XSniECdxy
  1.2141 +vLYavPMcL9LW5SToJFNnos+uqweOHriUZ1ntIYZUonc7ltEQ6oTRtwOHNwez2sVREskHN+bqG3ua
  1.2142 +eaEbJ8XpyO8CeD9QJc8nbLP2C2R3A437ISUNyt5Yd0TbDNcl11/DSsOzdbi/VhCC0KE6v1vqVNkq
  1.2143 +45ZnG6fiV2NwzInxCNth3BwL0+8814jE6+1W1EeWtpWbSZJOJNYXmWRXa7vLnAljE692eHjZ4y5u
  1.2144 +y1u63De0IzKca7As48Z3XshVF+3XiLNz0JIMh/JOpbiNLlMi672uO0wYzOCZjRxcxj3D+gVenGIE
  1.2145 +MvFUGGXuRps2RzMcgWIRolHXpGUP6sMsQt1hspUBnVKUn/WQj2u6j3SXd9Xz0QtEzoM7qTu5y7gR
  1.2146 +q9gNNsrlEMLdikBt9bFvBnfbUIh6voTw7eDsyTmPKUvF0bHqWLbHe3VRHyRZnNeSGKsB73q66Vsk
  1.2147 +taxWYmwz1tYVFG/vOQhlM0gUkyvIab3nv2caJ1udU1F3pDMty7stubTE4OJqm0i0ECfrJIkLtraC
  1.2148 +HwRWKzlqpfhEIqYH09eT9WrOhQyt8YEoyBlnXtAT37WHIQ03TIuEHbnRxZDdLun0iok9PUC79prU
  1.2149 +m5beZzfQUelEXnhzb/pIROKx3F7qCttYIFGh5dXNzFzID7u8vKykA8Uejf7XXz//S4nKvW//ofS/
  1.2150 +QastYw==
  1.2151 +""")
  1.2152 +
  1.2153 +##file distutils-init.py
  1.2154 +DISTUTILS_INIT = convert("""
  1.2155 +eJytV1uL4zYUfvevOE0ottuMW9q3gVDa3aUMXXbLMlDKMBiNrSTqOJKRlMxkf33PkXyRbGe7Dw2E
  1.2156 +UXTu37lpxLFV2oIyifAncxmOL0xLIfcG+gv80x9VW6maw7o/CANSWWBwFtqeWMPlGY6qPjV8A0bB
  1.2157 +C4eKSTgZ5LRgFeyErMEeOBhbN+Ipgeizhjtnhkn7DdyjuNLPoCS0l/ayQTG0djwZC08cLXozeMss
  1.2158 +aG5EzQ0IScpnWtHSTXuxByV/QCmxE7y+eS0uxWeoheaVVfqSJHiU7Mhhi6gULbOHorshkrEnKxpT
  1.2159 +0n3A8Y8SMpuwZx6aoix3ouFlmW8gHRSkeSJ2g7hU+kiHLDaQw3bmRDaTGfTnty7gPm0FHbIBg9U9
  1.2160 +oh1kZzAFLaue2R6htPCtAda2nGlDSUJ4PZBgCJBGVcwKTAMz/vJiLD+Oin5Z5QlvDPdulC6EsiyE
  1.2161 +NFzb7McNTKJzbJqzphx92VKRFY1idenzmq3K0emRcbWBD0ryqc4NZGmKOOOX9Pz5x+/l27tP797c
  1.2162 +f/z0d+4NruGNai8uAM0bfsYaw8itFk8ny41jsfpyO+BWlpqfhcG4yxLdi/0tQqoT4a8Vby382mt8
  1.2163 +p7XSo7aWGdPBc+b6utaBmCQ7rQKQoWtAuthQCiold2KfJIPTT8xwg9blPumc+YDZC/wYGdAyHpJk
  1.2164 +vUbHbHWAp5No6pK/WhhLEWrFjUwtPEv1Agf8YmnsuXUQYkeZoHm8ogP16gt2uHoxcEMdf2C6pmbw
  1.2165 +hUMsWGhanboh4IzzmsIpWs134jVPqD/c74bZHdY69UKKSn/+KfVhxLgUlToemayLMYQOqfEC61bh
  1.2166 +cbhwaqoGUzIyZRFHPmau5juaWqwRn3mpWmoEA5nhzS5gog/5jbcFQqOZvmBasZtwYlG93k5GEiyw
  1.2167 +buHhMWLjDarEGpMGB2LFs5nIJkhp/nUmZneFaRth++lieJtHepIvKgx6PJqIlD9X2j6pG1i9x3pZ
  1.2168 +5bHuCPFiirGHeO7McvoXkz786GaKVzC9DSpnOxJdc4xm6NSVq7lNEnKdVlnpu9BNYoKX2Iq3wvgh
  1.2169 +gGEUM66kK6j4NiyoneuPLSwaCWDxczgaolEWpiMyDVDb7dNuLAbriL8ig8mmeju31oNvQdpnvEPC
  1.2170 +1vAXbWacGRVrGt/uXN/gU0CDDwgooKRrHfTBb1/s9lYZ8ZqOBU0yLvpuP6+K9hLFsvIjeNhBi0KL
  1.2171 +MlOuWRn3FRwx5oHXjl0YImUx0+gLzjGchrgzca026ETmYJzPD+IpuKzNi8AFn048Thd63OdD86M6
  1.2172 +84zE8yQm0VqXdbbgvub2pKVnS76icBGdeTHHXTKspUmr4NYo/furFLKiMdQzFjHJNcdAnMhltBJK
  1.2173 +0/IKX3DVFqvPJ2dLE7bDBkH0l/PJ29074+F0CsGYOxsb7U3myTUncYfXqnLLfa6sJybX4g+hmcjO
  1.2174 +kMRBfA1JellfRRKJcyRpxdS4rIl6FdmQCWjo/o9Qz7yKffoP4JHjOvABcRn4CZIT2RH4jnxmfpVG
  1.2175 +qgLaAvQBNfuO6X0/Ux02nb4FKx3vgP+XnkX0QW9pLy/NsXgdN24dD3LxO2Nwil7Zlc1dqtP3d7/h
  1.2176 +kzp1/+7hGBuY4pk0XD/0Ao/oTe/XGrfyM773aB7iUhgkpy+dwAMalxMP0DrBcsVw/6p25+/hobP9
  1.2177 +GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ=
  1.2178 +""")
  1.2179 +
  1.2180 +##file distutils.cfg
  1.2181 +DISTUTILS_CFG = convert("""
  1.2182 +eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
  1.2183 +xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
  1.2184 +9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
  1.2185 +""")
  1.2186 +
  1.2187 +##file activate_this.py
  1.2188 +ACTIVATE_THIS = convert("""
  1.2189 +eJyNU01v2zAMvetXEB4K21jmDOstQA4dMGCHbeihlyEIDMWmG62yJEiKE//7kXKdpN2KzYBt8euR
  1.2190 +fKSyLPs8wiEo8wh4wqZTGou4V6Hm0wJa1cSiTkJdr8+GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe
  1.2191 +5a3p0cRKiAe2NtLADikftnDco0ko/SFEVgEZ8aRC5GLux7i3BpSJ6J1H+i7A2CjiHq9z7JRZuuQq
  1.2192 +siwTIvpxJYCeuWaBpwZdhB+yxy/eWz+ZvVSU8C4E9FFZkyxFsvCT/ZzL8gcz9aXVE14Yyp2M+2W0
  1.2193 +y7n5mp0qN+avKXvbsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCZN9UzlJr+/e/iab8WfqsmPI6pWeUPd
  1.2194 +FrMsd4H/55poeO9n54COhUs+sZNEzNtg/wanpjpuqHJaxs76HtZryI/K3H7KJ/KDIhqcbJ7kI4ar
  1.2195 +XL+sMgXnX0D+Te2Iy5xdP8yueSlQB/x/ED2BTAtyE3K4SYUN6AMNfbO63f4lBW3bUJPbTL+mjSxS
  1.2196 +PyRfJkZRgj+VbFv+EzHFi5pKwUEepa4JslMnwkowSRCXI+m5XvEOvtuBrxHdhLalG0JofYBok6qj
  1.2197 +YdN2dEngUlbC4PG60M1WEN0piu7Nq7on0mgyyUw3iV1etLo6r/81biWdQ9MWHFaePWZYaq+nmp+t
  1.2198 +s3az+sj7eA0jfgPfeoN1
  1.2199 +""")
  1.2200 +
  1.2201 +MH_MAGIC = 0xfeedface
  1.2202 +MH_CIGAM = 0xcefaedfe
  1.2203 +MH_MAGIC_64 = 0xfeedfacf
  1.2204 +MH_CIGAM_64 = 0xcffaedfe
  1.2205 +FAT_MAGIC = 0xcafebabe
  1.2206 +BIG_ENDIAN = '>'
  1.2207 +LITTLE_ENDIAN = '<'
  1.2208 +LC_LOAD_DYLIB = 0xc
  1.2209 +maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint')
  1.2210 +
  1.2211 +
  1.2212 +class fileview(object):
  1.2213 +    """
  1.2214 +    A proxy for file-like objects that exposes a given view of a file.
  1.2215 +    Modified from macholib.
  1.2216 +    """
  1.2217 +
  1.2218 +    def __init__(self, fileobj, start=0, size=maxint):
  1.2219 +        if isinstance(fileobj, fileview):
  1.2220 +            self._fileobj = fileobj._fileobj
  1.2221 +        else:
  1.2222 +            self._fileobj = fileobj
  1.2223 +        self._start = start
  1.2224 +        self._end = start + size
  1.2225 +        self._pos = 0
  1.2226 +
  1.2227 +    def __repr__(self):
  1.2228 +        return '<fileview [%d, %d] %r>' % (
  1.2229 +            self._start, self._end, self._fileobj)
  1.2230 +
  1.2231 +    def tell(self):
  1.2232 +        return self._pos
  1.2233 +
  1.2234 +    def _checkwindow(self, seekto, op):
  1.2235 +        if not (self._start <= seekto <= self._end):
  1.2236 +            raise IOError("%s to offset %d is outside window [%d, %d]" % (
  1.2237 +                op, seekto, self._start, self._end))
  1.2238 +
  1.2239 +    def seek(self, offset, whence=0):
  1.2240 +        seekto = offset
  1.2241 +        if whence == os.SEEK_SET:
  1.2242 +            seekto += self._start
  1.2243 +        elif whence == os.SEEK_CUR:
  1.2244 +            seekto += self._start + self._pos
  1.2245 +        elif whence == os.SEEK_END:
  1.2246 +            seekto += self._end
  1.2247 +        else:
  1.2248 +            raise IOError("Invalid whence argument to seek: %r" % (whence,))
  1.2249 +        self._checkwindow(seekto, 'seek')
  1.2250 +        self._fileobj.seek(seekto)
  1.2251 +        self._pos = seekto - self._start
  1.2252 +
  1.2253 +    def write(self, bytes):
  1.2254 +        here = self._start + self._pos
  1.2255 +        self._checkwindow(here, 'write')
  1.2256 +        self._checkwindow(here + len(bytes), 'write')
  1.2257 +        self._fileobj.seek(here, os.SEEK_SET)
  1.2258 +        self._fileobj.write(bytes)
  1.2259 +        self._pos += len(bytes)
  1.2260 +
  1.2261 +    def read(self, size=maxint):
  1.2262 +        assert size >= 0
  1.2263 +        here = self._start + self._pos
  1.2264 +        self._checkwindow(here, 'read')
  1.2265 +        size = min(size, self._end - here)
  1.2266 +        self._fileobj.seek(here, os.SEEK_SET)
  1.2267 +        bytes = self._fileobj.read(size)
  1.2268 +        self._pos += len(bytes)
  1.2269 +        return bytes
  1.2270 +
  1.2271 +
  1.2272 +def read_data(file, endian, num=1):
  1.2273 +    """
  1.2274 +    Read a given number of 32-bits unsigned integers from the given file
  1.2275 +    with the given endianness.
  1.2276 +    """
  1.2277 +    res = struct.unpack(endian + 'L' * num, file.read(num * 4))
  1.2278 +    if len(res) == 1:
  1.2279 +        return res[0]
  1.2280 +    return res
  1.2281 +
  1.2282 +
  1.2283 +def mach_o_change(path, what, value):
  1.2284 +    """
  1.2285 +    Replace a given name (what) in any LC_LOAD_DYLIB command found in
  1.2286 +    the given binary with a new name (value), provided it's shorter.
  1.2287 +    """
  1.2288 +
  1.2289 +    def do_macho(file, bits, endian):
  1.2290 +        # Read Mach-O header (the magic number is assumed read by the caller)
  1.2291 +        cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6)
  1.2292 +        # 64-bits header has one more field.
  1.2293 +        if bits == 64:
  1.2294 +            read_data(file, endian)
  1.2295 +        # The header is followed by ncmds commands
  1.2296 +        for n in range(ncmds):
  1.2297 +            where = file.tell()
  1.2298 +            # Read command header
  1.2299 +            cmd, cmdsize = read_data(file, endian, 2)
  1.2300 +            if cmd == LC_LOAD_DYLIB:
  1.2301 +                # The first data field in LC_LOAD_DYLIB commands is the
  1.2302 +                # offset of the name, starting from the beginning of the
  1.2303 +                # command.
  1.2304 +                name_offset = read_data(file, endian)
  1.2305 +                file.seek(where + name_offset, os.SEEK_SET)
  1.2306 +                # Read the NUL terminated string
  1.2307 +                load = file.read(cmdsize - name_offset).decode()
  1.2308 +                load = load[:load.index('\0')]
  1.2309 +                # If the string is what is being replaced, overwrite it.
  1.2310 +                if load == what:
  1.2311 +                    file.seek(where + name_offset, os.SEEK_SET)
  1.2312 +                    file.write(value.encode() + '\0'.encode())
  1.2313 +            # Seek to the next command
  1.2314 +            file.seek(where + cmdsize, os.SEEK_SET)
  1.2315 +
  1.2316 +    def do_file(file, offset=0, size=maxint):
  1.2317 +        file = fileview(file, offset, size)
  1.2318 +        # Read magic number
  1.2319 +        magic = read_data(file, BIG_ENDIAN)
  1.2320 +        if magic == FAT_MAGIC:
  1.2321 +            # Fat binaries contain nfat_arch Mach-O binaries
  1.2322 +            nfat_arch = read_data(file, BIG_ENDIAN)
  1.2323 +            for n in range(nfat_arch):
  1.2324 +                # Read arch header
  1.2325 +                cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5)
  1.2326 +                do_file(file, offset, size)
  1.2327 +        elif magic == MH_MAGIC:
  1.2328 +            do_macho(file, 32, BIG_ENDIAN)
  1.2329 +        elif magic == MH_CIGAM:
  1.2330 +            do_macho(file, 32, LITTLE_ENDIAN)
  1.2331 +        elif magic == MH_MAGIC_64:
  1.2332 +            do_macho(file, 64, BIG_ENDIAN)
  1.2333 +        elif magic == MH_CIGAM_64:
  1.2334 +            do_macho(file, 64, LITTLE_ENDIAN)
  1.2335 +
  1.2336 +    assert(len(what) >= len(value))
  1.2337 +    do_file(open(path, 'r+b'))
  1.2338 +
  1.2339 +
  1.2340 +if __name__ == '__main__':
  1.2341 +    main()
  1.2342 +
  1.2343 +## TODO:
  1.2344 +## Copy python.exe.manifest
  1.2345 +## Monkeypatch distutils.sysconfig

mercurial