virtualenv/web/virtualenv.py
changeset 39 4b3c183a1fe4
equal deleted inserted replaced
38:c4261299912d 39:4b3c183a1fe4
       
     1 #!/usr/bin/env python
       
     2 """Create a "virtual" Python installation
       
     3 """
       
     4 
       
     5 # If you change the version here, change it in setup.py
       
     6 # and docs/conf.py as well.
       
     7 __version__ = "1.8.4"  # following best practices
       
     8 virtualenv_version = __version__  # legacy, again
       
     9 
       
    10 import base64
       
    11 import sys
       
    12 import os
       
    13 import codecs
       
    14 import optparse
       
    15 import re
       
    16 import shutil
       
    17 import logging
       
    18 import tempfile
       
    19 import zlib
       
    20 import errno
       
    21 import glob
       
    22 import distutils.sysconfig
       
    23 from distutils.util import strtobool
       
    24 import struct
       
    25 import subprocess
       
    26 
       
    27 if sys.version_info < (2, 5):
       
    28     print('ERROR: %s' % sys.exc_info()[1])
       
    29     print('ERROR: this script requires Python 2.5 or greater.')
       
    30     sys.exit(101)
       
    31 
       
    32 try:
       
    33     set
       
    34 except NameError:
       
    35     from sets import Set as set
       
    36 try:
       
    37     basestring
       
    38 except NameError:
       
    39     basestring = str
       
    40 
       
    41 try:
       
    42     import ConfigParser
       
    43 except ImportError:
       
    44     import configparser as ConfigParser
       
    45 
       
    46 join = os.path.join
       
    47 py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
       
    48 
       
    49 is_jython = sys.platform.startswith('java')
       
    50 is_pypy = hasattr(sys, 'pypy_version_info')
       
    51 is_win = (sys.platform == 'win32')
       
    52 is_cygwin = (sys.platform == 'cygwin')
       
    53 is_darwin = (sys.platform == 'darwin')
       
    54 abiflags = getattr(sys, 'abiflags', '')
       
    55 
       
    56 user_dir = os.path.expanduser('~')
       
    57 if is_win:
       
    58     default_storage_dir = os.path.join(user_dir, 'virtualenv')
       
    59 else:
       
    60     default_storage_dir = os.path.join(user_dir, '.virtualenv')
       
    61 default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini')
       
    62 
       
    63 if is_pypy:
       
    64     expected_exe = 'pypy'
       
    65 elif is_jython:
       
    66     expected_exe = 'jython'
       
    67 else:
       
    68     expected_exe = 'python'
       
    69 
       
    70 
       
    71 REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
       
    72                     'fnmatch', 'locale', 'encodings', 'codecs',
       
    73                     'stat', 'UserDict', 'readline', 'copy_reg', 'types',
       
    74                     're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
       
    75                     'zlib']
       
    76 
       
    77 REQUIRED_FILES = ['lib-dynload', 'config']
       
    78 
       
    79 majver, minver = sys.version_info[:2]
       
    80 if majver == 2:
       
    81     if minver >= 6:
       
    82         REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc'])
       
    83     if minver >= 7:
       
    84         REQUIRED_MODULES.extend(['_weakrefset'])
       
    85     if minver <= 3:
       
    86         REQUIRED_MODULES.extend(['sets', '__future__'])
       
    87 elif majver == 3:
       
    88     # Some extra modules are needed for Python 3, but different ones
       
    89     # for different versions.
       
    90     REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
       
    91                              '_weakrefset', 'copyreg', 'tempfile', 'random',
       
    92                              '__future__', 'collections', 'keyword', 'tarfile',
       
    93                              'shutil', 'struct', 'copy', 'tokenize', 'token',
       
    94                              'functools', 'heapq', 'bisect', 'weakref',
       
    95                              'reprlib'])
       
    96     if minver >= 2:
       
    97         REQUIRED_FILES[-1] = 'config-%s' % majver
       
    98     if minver == 3:
       
    99         import sysconfig
       
   100         platdir = sysconfig.get_config_var('PLATDIR')
       
   101         REQUIRED_FILES.append(platdir)
       
   102         # The whole list of 3.3 modules is reproduced below - the current
       
   103         # uncommented ones are required for 3.3 as of now, but more may be
       
   104         # added as 3.3 development continues.
       
   105         REQUIRED_MODULES.extend([
       
   106             #"aifc",
       
   107             #"antigravity",
       
   108             #"argparse",
       
   109             #"ast",
       
   110             #"asynchat",
       
   111             #"asyncore",
       
   112             "base64",
       
   113             #"bdb",
       
   114             #"binhex",
       
   115             #"bisect",
       
   116             #"calendar",
       
   117             #"cgi",
       
   118             #"cgitb",
       
   119             #"chunk",
       
   120             #"cmd",
       
   121             #"codeop",
       
   122             #"code",
       
   123             #"colorsys",
       
   124             #"_compat_pickle",
       
   125             #"compileall",
       
   126             #"concurrent",
       
   127             #"configparser",
       
   128             #"contextlib",
       
   129             #"cProfile",
       
   130             #"crypt",
       
   131             #"csv",
       
   132             #"ctypes",
       
   133             #"curses",
       
   134             #"datetime",
       
   135             #"dbm",
       
   136             #"decimal",
       
   137             #"difflib",
       
   138             #"dis",
       
   139             #"doctest",
       
   140             #"dummy_threading",
       
   141             "_dummy_thread",
       
   142             #"email",
       
   143             #"filecmp",
       
   144             #"fileinput",
       
   145             #"formatter",
       
   146             #"fractions",
       
   147             #"ftplib",
       
   148             #"functools",
       
   149             #"getopt",
       
   150             #"getpass",
       
   151             #"gettext",
       
   152             #"glob",
       
   153             #"gzip",
       
   154             "hashlib",
       
   155             #"heapq",
       
   156             "hmac",
       
   157             #"html",
       
   158             #"http",
       
   159             #"idlelib",
       
   160             #"imaplib",
       
   161             #"imghdr",
       
   162             "imp",
       
   163             "importlib",
       
   164             #"inspect",
       
   165             #"json",
       
   166             #"lib2to3",
       
   167             #"logging",
       
   168             #"macpath",
       
   169             #"macurl2path",
       
   170             #"mailbox",
       
   171             #"mailcap",
       
   172             #"_markupbase",
       
   173             #"mimetypes",
       
   174             #"modulefinder",
       
   175             #"multiprocessing",
       
   176             #"netrc",
       
   177             #"nntplib",
       
   178             #"nturl2path",
       
   179             #"numbers",
       
   180             #"opcode",
       
   181             #"optparse",
       
   182             #"os2emxpath",
       
   183             #"pdb",
       
   184             #"pickle",
       
   185             #"pickletools",
       
   186             #"pipes",
       
   187             #"pkgutil",
       
   188             #"platform",
       
   189             #"plat-linux2",
       
   190             #"plistlib",
       
   191             #"poplib",
       
   192             #"pprint",
       
   193             #"profile",
       
   194             #"pstats",
       
   195             #"pty",
       
   196             #"pyclbr",
       
   197             #"py_compile",
       
   198             #"pydoc_data",
       
   199             #"pydoc",
       
   200             #"_pyio",
       
   201             #"queue",
       
   202             #"quopri",
       
   203             #"reprlib",
       
   204             "rlcompleter",
       
   205             #"runpy",
       
   206             #"sched",
       
   207             #"shelve",
       
   208             #"shlex",
       
   209             #"smtpd",
       
   210             #"smtplib",
       
   211             #"sndhdr",
       
   212             #"socket",
       
   213             #"socketserver",
       
   214             #"sqlite3",
       
   215             #"ssl",
       
   216             #"stringprep",
       
   217             #"string",
       
   218             #"_strptime",
       
   219             #"subprocess",
       
   220             #"sunau",
       
   221             #"symbol",
       
   222             #"symtable",
       
   223             #"sysconfig",
       
   224             #"tabnanny",
       
   225             #"telnetlib",
       
   226             #"test",
       
   227             #"textwrap",
       
   228             #"this",
       
   229             #"_threading_local",
       
   230             #"threading",
       
   231             #"timeit",
       
   232             #"tkinter",
       
   233             #"tokenize",
       
   234             #"token",
       
   235             #"traceback",
       
   236             #"trace",
       
   237             #"tty",
       
   238             #"turtledemo",
       
   239             #"turtle",
       
   240             #"unittest",
       
   241             #"urllib",
       
   242             #"uuid",
       
   243             #"uu",
       
   244             #"wave",
       
   245             #"weakref",
       
   246             #"webbrowser",
       
   247             #"wsgiref",
       
   248             #"xdrlib",
       
   249             #"xml",
       
   250             #"xmlrpc",
       
   251             #"zipfile",
       
   252         ])
       
   253 
       
   254 if is_pypy:
       
   255     # these are needed to correctly display the exceptions that may happen
       
   256     # during the bootstrap
       
   257     REQUIRED_MODULES.extend(['traceback', 'linecache'])
       
   258 
       
   259 class Logger(object):
       
   260 
       
   261     """
       
   262     Logging object for use in command-line script.  Allows ranges of
       
   263     levels, to avoid some redundancy of displayed information.
       
   264     """
       
   265 
       
   266     DEBUG = logging.DEBUG
       
   267     INFO = logging.INFO
       
   268     NOTIFY = (logging.INFO+logging.WARN)/2
       
   269     WARN = WARNING = logging.WARN
       
   270     ERROR = logging.ERROR
       
   271     FATAL = logging.FATAL
       
   272 
       
   273     LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
       
   274 
       
   275     def __init__(self, consumers):
       
   276         self.consumers = consumers
       
   277         self.indent = 0
       
   278         self.in_progress = None
       
   279         self.in_progress_hanging = False
       
   280 
       
   281     def debug(self, msg, *args, **kw):
       
   282         self.log(self.DEBUG, msg, *args, **kw)
       
   283     def info(self, msg, *args, **kw):
       
   284         self.log(self.INFO, msg, *args, **kw)
       
   285     def notify(self, msg, *args, **kw):
       
   286         self.log(self.NOTIFY, msg, *args, **kw)
       
   287     def warn(self, msg, *args, **kw):
       
   288         self.log(self.WARN, msg, *args, **kw)
       
   289     def error(self, msg, *args, **kw):
       
   290         self.log(self.ERROR, msg, *args, **kw)
       
   291     def fatal(self, msg, *args, **kw):
       
   292         self.log(self.FATAL, msg, *args, **kw)
       
   293     def log(self, level, msg, *args, **kw):
       
   294         if args:
       
   295             if kw:
       
   296                 raise TypeError(
       
   297                     "You may give positional or keyword arguments, not both")
       
   298         args = args or kw
       
   299         rendered = None
       
   300         for consumer_level, consumer in self.consumers:
       
   301             if self.level_matches(level, consumer_level):
       
   302                 if (self.in_progress_hanging
       
   303                     and consumer in (sys.stdout, sys.stderr)):
       
   304                     self.in_progress_hanging = False
       
   305                     sys.stdout.write('\n')
       
   306                     sys.stdout.flush()
       
   307                 if rendered is None:
       
   308                     if args:
       
   309                         rendered = msg % args
       
   310                     else:
       
   311                         rendered = msg
       
   312                     rendered = ' '*self.indent + rendered
       
   313                 if hasattr(consumer, 'write'):
       
   314                     consumer.write(rendered+'\n')
       
   315                 else:
       
   316                     consumer(rendered)
       
   317 
       
   318     def start_progress(self, msg):
       
   319         assert not self.in_progress, (
       
   320             "Tried to start_progress(%r) while in_progress %r"
       
   321             % (msg, self.in_progress))
       
   322         if self.level_matches(self.NOTIFY, self._stdout_level()):
       
   323             sys.stdout.write(msg)
       
   324             sys.stdout.flush()
       
   325             self.in_progress_hanging = True
       
   326         else:
       
   327             self.in_progress_hanging = False
       
   328         self.in_progress = msg
       
   329 
       
   330     def end_progress(self, msg='done.'):
       
   331         assert self.in_progress, (
       
   332             "Tried to end_progress without start_progress")
       
   333         if self.stdout_level_matches(self.NOTIFY):
       
   334             if not self.in_progress_hanging:
       
   335                 # Some message has been printed out since start_progress
       
   336                 sys.stdout.write('...' + self.in_progress + msg + '\n')
       
   337                 sys.stdout.flush()
       
   338             else:
       
   339                 sys.stdout.write(msg + '\n')
       
   340                 sys.stdout.flush()
       
   341         self.in_progress = None
       
   342         self.in_progress_hanging = False
       
   343 
       
   344     def show_progress(self):
       
   345         """If we are in a progress scope, and no log messages have been
       
   346         shown, write out another '.'"""
       
   347         if self.in_progress_hanging:
       
   348             sys.stdout.write('.')
       
   349             sys.stdout.flush()
       
   350 
       
   351     def stdout_level_matches(self, level):
       
   352         """Returns true if a message at this level will go to stdout"""
       
   353         return self.level_matches(level, self._stdout_level())
       
   354 
       
   355     def _stdout_level(self):
       
   356         """Returns the level that stdout runs at"""
       
   357         for level, consumer in self.consumers:
       
   358             if consumer is sys.stdout:
       
   359                 return level
       
   360         return self.FATAL
       
   361 
       
   362     def level_matches(self, level, consumer_level):
       
   363         """
       
   364         >>> l = Logger([])
       
   365         >>> l.level_matches(3, 4)
       
   366         False
       
   367         >>> l.level_matches(3, 2)
       
   368         True
       
   369         >>> l.level_matches(slice(None, 3), 3)
       
   370         False
       
   371         >>> l.level_matches(slice(None, 3), 2)
       
   372         True
       
   373         >>> l.level_matches(slice(1, 3), 1)
       
   374         True
       
   375         >>> l.level_matches(slice(2, 3), 1)
       
   376         False
       
   377         """
       
   378         if isinstance(level, slice):
       
   379             start, stop = level.start, level.stop
       
   380             if start is not None and start > consumer_level:
       
   381                 return False
       
   382             if stop is not None and stop <= consumer_level:
       
   383                 return False
       
   384             return True
       
   385         else:
       
   386             return level >= consumer_level
       
   387 
       
   388     #@classmethod
       
   389     def level_for_integer(cls, level):
       
   390         levels = cls.LEVELS
       
   391         if level < 0:
       
   392             return levels[0]
       
   393         if level >= len(levels):
       
   394             return levels[-1]
       
   395         return levels[level]
       
   396 
       
   397     level_for_integer = classmethod(level_for_integer)
       
   398 
       
   399 # create a silent logger just to prevent this from being undefined
       
   400 # will be overridden with requested verbosity main() is called.
       
   401 logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
       
   402 
       
   403 def mkdir(path):
       
   404     if not os.path.exists(path):
       
   405         logger.info('Creating %s', path)
       
   406         os.makedirs(path)
       
   407     else:
       
   408         logger.info('Directory %s already exists', path)
       
   409 
       
   410 def copyfileordir(src, dest):
       
   411     if os.path.isdir(src):
       
   412         shutil.copytree(src, dest, True)
       
   413     else:
       
   414         shutil.copy2(src, dest)
       
   415 
       
   416 def copyfile(src, dest, symlink=True):
       
   417     if not os.path.exists(src):
       
   418         # Some bad symlink in the src
       
   419         logger.warn('Cannot find file %s (bad symlink)', src)
       
   420         return
       
   421     if os.path.exists(dest):
       
   422         logger.debug('File %s already exists', dest)
       
   423         return
       
   424     if not os.path.exists(os.path.dirname(dest)):
       
   425         logger.info('Creating parent directories for %s' % os.path.dirname(dest))
       
   426         os.makedirs(os.path.dirname(dest))
       
   427     if not os.path.islink(src):
       
   428         srcpath = os.path.abspath(src)
       
   429     else:
       
   430         srcpath = os.readlink(src)
       
   431     if symlink and hasattr(os, 'symlink') and not is_win:
       
   432         logger.info('Symlinking %s', dest)
       
   433         try:
       
   434             os.symlink(srcpath, dest)
       
   435         except (OSError, NotImplementedError):
       
   436             logger.info('Symlinking failed, copying to %s', dest)
       
   437             copyfileordir(src, dest)
       
   438     else:
       
   439         logger.info('Copying to %s', dest)
       
   440         copyfileordir(src, dest)
       
   441 
       
   442 def writefile(dest, content, overwrite=True):
       
   443     if not os.path.exists(dest):
       
   444         logger.info('Writing %s', dest)
       
   445         f = open(dest, 'wb')
       
   446         f.write(content.encode('utf-8'))
       
   447         f.close()
       
   448         return
       
   449     else:
       
   450         f = open(dest, 'rb')
       
   451         c = f.read()
       
   452         f.close()
       
   453         if c != content.encode("utf-8"):
       
   454             if not overwrite:
       
   455                 logger.notify('File %s exists with different content; not overwriting', dest)
       
   456                 return
       
   457             logger.notify('Overwriting %s with new content', dest)
       
   458             f = open(dest, 'wb')
       
   459             f.write(content.encode('utf-8'))
       
   460             f.close()
       
   461         else:
       
   462             logger.info('Content %s already in place', dest)
       
   463 
       
   464 def rmtree(dir):
       
   465     if os.path.exists(dir):
       
   466         logger.notify('Deleting tree %s', dir)
       
   467         shutil.rmtree(dir)
       
   468     else:
       
   469         logger.info('Do not need to delete %s; already gone', dir)
       
   470 
       
   471 def make_exe(fn):
       
   472     if hasattr(os, 'chmod'):
       
   473         oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777
       
   474         newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777
       
   475         os.chmod(fn, newmode)
       
   476         logger.info('Changed mode of %s to %s', fn, oct(newmode))
       
   477 
       
   478 def _find_file(filename, dirs):
       
   479     for dir in reversed(dirs):
       
   480         files = glob.glob(os.path.join(dir, filename))
       
   481         if files and os.path.isfile(files[0]):
       
   482             return True, files[0]
       
   483     return False, filename
       
   484 
       
   485 def _install_req(py_executable, unzip=False, distribute=False,
       
   486                  search_dirs=None, never_download=False):
       
   487 
       
   488     if search_dirs is None:
       
   489         search_dirs = file_search_dirs()
       
   490 
       
   491     if not distribute:
       
   492         egg_path = 'setuptools-*-py%s.egg' % sys.version[:3]
       
   493         found, egg_path = _find_file(egg_path, search_dirs)
       
   494         project_name = 'setuptools'
       
   495         bootstrap_script = EZ_SETUP_PY
       
   496         tgz_path = None
       
   497     else:
       
   498         # Look for a distribute egg (these are not distributed by default,
       
   499         # but can be made available by the user)
       
   500         egg_path = 'distribute-*-py%s.egg' % sys.version[:3]
       
   501         found, egg_path = _find_file(egg_path, search_dirs)
       
   502         project_name = 'distribute'
       
   503         if found:
       
   504             tgz_path = None
       
   505             bootstrap_script = DISTRIBUTE_FROM_EGG_PY
       
   506         else:
       
   507             # Fall back to sdist
       
   508             # NB: egg_path is not None iff tgz_path is None
       
   509             # iff bootstrap_script is a generic setup script accepting
       
   510             # the standard arguments.
       
   511             egg_path = None
       
   512             tgz_path = 'distribute-*.tar.gz'
       
   513             found, tgz_path = _find_file(tgz_path, search_dirs)
       
   514             bootstrap_script = DISTRIBUTE_SETUP_PY
       
   515 
       
   516     if is_jython and os._name == 'nt':
       
   517         # Jython's .bat sys.executable can't handle a command line
       
   518         # argument with newlines
       
   519         fd, ez_setup = tempfile.mkstemp('.py')
       
   520         os.write(fd, bootstrap_script)
       
   521         os.close(fd)
       
   522         cmd = [py_executable, ez_setup]
       
   523     else:
       
   524         cmd = [py_executable, '-c', bootstrap_script]
       
   525     if unzip and egg_path:
       
   526         cmd.append('--always-unzip')
       
   527     env = {}
       
   528     remove_from_env = ['__PYVENV_LAUNCHER__']
       
   529     if logger.stdout_level_matches(logger.DEBUG) and egg_path:
       
   530         cmd.append('-v')
       
   531 
       
   532     old_chdir = os.getcwd()
       
   533     if egg_path is not None and os.path.exists(egg_path):
       
   534         logger.info('Using existing %s egg: %s' % (project_name, egg_path))
       
   535         cmd.append(egg_path)
       
   536         if os.environ.get('PYTHONPATH'):
       
   537             env['PYTHONPATH'] = egg_path + os.path.pathsep + os.environ['PYTHONPATH']
       
   538         else:
       
   539             env['PYTHONPATH'] = egg_path
       
   540     elif tgz_path is not None and os.path.exists(tgz_path):
       
   541         # Found a tgz source dist, let's chdir
       
   542         logger.info('Using existing %s egg: %s' % (project_name, tgz_path))
       
   543         os.chdir(os.path.dirname(tgz_path))
       
   544         # in this case, we want to be sure that PYTHONPATH is unset (not
       
   545         # just empty, really unset), else CPython tries to import the
       
   546         # site.py that it's in virtualenv_support
       
   547         remove_from_env.append('PYTHONPATH')
       
   548     elif never_download:
       
   549         logger.fatal("Can't find any local distributions of %s to install "
       
   550                      "and --never-download is set.  Either re-run virtualenv "
       
   551                      "without the --never-download option, or place a %s "
       
   552                      "distribution (%s) in one of these "
       
   553                      "locations: %r" % (project_name, project_name,
       
   554                                         egg_path or tgz_path,
       
   555                                         search_dirs))
       
   556         sys.exit(1)
       
   557     elif egg_path:
       
   558         logger.info('No %s egg found; downloading' % project_name)
       
   559         cmd.extend(['--always-copy', '-U', project_name])
       
   560     else:
       
   561         logger.info('No %s tgz found; downloading' % project_name)
       
   562     logger.start_progress('Installing %s...' % project_name)
       
   563     logger.indent += 2
       
   564     cwd = None
       
   565     if project_name == 'distribute':
       
   566         env['DONT_PATCH_SETUPTOOLS'] = 'true'
       
   567 
       
   568     def _filter_ez_setup(line):
       
   569         return filter_ez_setup(line, project_name)
       
   570 
       
   571     if not os.access(os.getcwd(), os.W_OK):
       
   572         cwd = tempfile.mkdtemp()
       
   573         if tgz_path is not None and os.path.exists(tgz_path):
       
   574             # the current working dir is hostile, let's copy the
       
   575             # tarball to a temp dir
       
   576             target = os.path.join(cwd, os.path.split(tgz_path)[-1])
       
   577             shutil.copy(tgz_path, target)
       
   578     try:
       
   579         call_subprocess(cmd, show_stdout=False,
       
   580                         filter_stdout=_filter_ez_setup,
       
   581                         extra_env=env,
       
   582                         remove_from_env=remove_from_env,
       
   583                         cwd=cwd)
       
   584     finally:
       
   585         logger.indent -= 2
       
   586         logger.end_progress()
       
   587         if cwd is not None:
       
   588             shutil.rmtree(cwd)
       
   589         if os.getcwd() != old_chdir:
       
   590             os.chdir(old_chdir)
       
   591         if is_jython and os._name == 'nt':
       
   592             os.remove(ez_setup)
       
   593 
       
   594 def file_search_dirs():
       
   595     here = os.path.dirname(os.path.abspath(__file__))
       
   596     dirs = ['.', here,
       
   597             join(here, 'virtualenv_support')]
       
   598     if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
       
   599         # Probably some boot script; just in case virtualenv is installed...
       
   600         try:
       
   601             import virtualenv
       
   602         except ImportError:
       
   603             pass
       
   604         else:
       
   605             dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
       
   606     return [d for d in dirs if os.path.isdir(d)]
       
   607 
       
   608 def install_setuptools(py_executable, unzip=False,
       
   609                        search_dirs=None, never_download=False):
       
   610     _install_req(py_executable, unzip,
       
   611                  search_dirs=search_dirs, never_download=never_download)
       
   612 
       
   613 def install_distribute(py_executable, unzip=False,
       
   614                        search_dirs=None, never_download=False):
       
   615     _install_req(py_executable, unzip, distribute=True,
       
   616                  search_dirs=search_dirs, never_download=never_download)
       
   617 
       
   618 _pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I)
       
   619 def install_pip(py_executable, search_dirs=None, never_download=False):
       
   620     if search_dirs is None:
       
   621         search_dirs = file_search_dirs()
       
   622 
       
   623     filenames = []
       
   624     for dir in search_dirs:
       
   625         filenames.extend([join(dir, fn) for fn in os.listdir(dir)
       
   626                           if _pip_re.search(fn)])
       
   627     filenames = [(os.path.basename(filename).lower(), i, filename) for i, filename in enumerate(filenames)]
       
   628     filenames.sort()
       
   629     filenames = [filename for basename, i, filename in filenames]
       
   630     if not filenames:
       
   631         filename = 'pip'
       
   632     else:
       
   633         filename = filenames[-1]
       
   634     easy_install_script = 'easy_install'
       
   635     if is_win:
       
   636         easy_install_script = 'easy_install-script.py'
       
   637     # There's two subtle issues here when invoking easy_install.
       
   638     # 1. On unix-like systems the easy_install script can *only* be executed
       
   639     #    directly if its full filesystem path is no longer than 78 characters.
       
   640     # 2. A work around to [1] is to use the `python path/to/easy_install foo`
       
   641     #    pattern, but that breaks if the path contains non-ASCII characters, as
       
   642     #    you can't put the file encoding declaration before the shebang line.
       
   643     # The solution is to use Python's -x flag to skip the first line of the
       
   644     # script (and any ASCII decoding errors that may have occurred in that line)
       
   645     cmd = [py_executable, '-x', join(os.path.dirname(py_executable), easy_install_script), filename]
       
   646     # jython and pypy don't yet support -x
       
   647     if is_jython or is_pypy:
       
   648         cmd.remove('-x')
       
   649     if filename == 'pip':
       
   650         if never_download:
       
   651             logger.fatal("Can't find any local distributions of pip to install "
       
   652                          "and --never-download is set.  Either re-run virtualenv "
       
   653                          "without the --never-download option, or place a pip "
       
   654                          "source distribution (zip/tar.gz/tar.bz2) in one of these "
       
   655                          "locations: %r" % search_dirs)
       
   656             sys.exit(1)
       
   657         logger.info('Installing pip from network...')
       
   658     else:
       
   659         logger.info('Installing existing %s distribution: %s' % (
       
   660                 os.path.basename(filename), filename))
       
   661     logger.start_progress('Installing pip...')
       
   662     logger.indent += 2
       
   663     def _filter_setup(line):
       
   664         return filter_ez_setup(line, 'pip')
       
   665     try:
       
   666         call_subprocess(cmd, show_stdout=False,
       
   667                         filter_stdout=_filter_setup)
       
   668     finally:
       
   669         logger.indent -= 2
       
   670         logger.end_progress()
       
   671 
       
   672 def filter_ez_setup(line, project_name='setuptools'):
       
   673     if not line.strip():
       
   674         return Logger.DEBUG
       
   675     if project_name == 'distribute':
       
   676         for prefix in ('Extracting', 'Now working', 'Installing', 'Before',
       
   677                        'Scanning', 'Setuptools', 'Egg', 'Already',
       
   678                        'running', 'writing', 'reading', 'installing',
       
   679                        'creating', 'copying', 'byte-compiling', 'removing',
       
   680                        'Processing'):
       
   681             if line.startswith(prefix):
       
   682                 return Logger.DEBUG
       
   683         return Logger.DEBUG
       
   684     for prefix in ['Reading ', 'Best match', 'Processing setuptools',
       
   685                    'Copying setuptools', 'Adding setuptools',
       
   686                    'Installing ', 'Installed ']:
       
   687         if line.startswith(prefix):
       
   688             return Logger.DEBUG
       
   689     return Logger.INFO
       
   690 
       
   691 
       
   692 class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
       
   693     """
       
   694     Custom help formatter for use in ConfigOptionParser that updates
       
   695     the defaults before expanding them, allowing them to show up correctly
       
   696     in the help listing
       
   697     """
       
   698     def expand_default(self, option):
       
   699         if self.parser is not None:
       
   700             self.parser.update_defaults(self.parser.defaults)
       
   701         return optparse.IndentedHelpFormatter.expand_default(self, option)
       
   702 
       
   703 
       
   704 class ConfigOptionParser(optparse.OptionParser):
       
   705     """
       
   706     Custom option parser which updates its defaults by by checking the
       
   707     configuration files and environmental variables
       
   708     """
       
   709     def __init__(self, *args, **kwargs):
       
   710         self.config = ConfigParser.RawConfigParser()
       
   711         self.files = self.get_config_files()
       
   712         self.config.read(self.files)
       
   713         optparse.OptionParser.__init__(self, *args, **kwargs)
       
   714 
       
   715     def get_config_files(self):
       
   716         config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False)
       
   717         if config_file and os.path.exists(config_file):
       
   718             return [config_file]
       
   719         return [default_config_file]
       
   720 
       
   721     def update_defaults(self, defaults):
       
   722         """
       
   723         Updates the given defaults with values from the config files and
       
   724         the environ. Does a little special handling for certain types of
       
   725         options (lists).
       
   726         """
       
   727         # Then go and look for the other sources of configuration:
       
   728         config = {}
       
   729         # 1. config files
       
   730         config.update(dict(self.get_config_section('virtualenv')))
       
   731         # 2. environmental variables
       
   732         config.update(dict(self.get_environ_vars()))
       
   733         # Then set the options with those values
       
   734         for key, val in config.items():
       
   735             key = key.replace('_', '-')
       
   736             if not key.startswith('--'):
       
   737                 key = '--%s' % key  # only prefer long opts
       
   738             option = self.get_option(key)
       
   739             if option is not None:
       
   740                 # ignore empty values
       
   741                 if not val:
       
   742                     continue
       
   743                 # handle multiline configs
       
   744                 if option.action == 'append':
       
   745                     val = val.split()
       
   746                 else:
       
   747                     option.nargs = 1
       
   748                 if option.action == 'store_false':
       
   749                     val = not strtobool(val)
       
   750                 elif option.action in ('store_true', 'count'):
       
   751                     val = strtobool(val)
       
   752                 try:
       
   753                     val = option.convert_value(key, val)
       
   754                 except optparse.OptionValueError:
       
   755                     e = sys.exc_info()[1]
       
   756                     print("An error occured during configuration: %s" % e)
       
   757                     sys.exit(3)
       
   758                 defaults[option.dest] = val
       
   759         return defaults
       
   760 
       
   761     def get_config_section(self, name):
       
   762         """
       
   763         Get a section of a configuration
       
   764         """
       
   765         if self.config.has_section(name):
       
   766             return self.config.items(name)
       
   767         return []
       
   768 
       
   769     def get_environ_vars(self, prefix='VIRTUALENV_'):
       
   770         """
       
   771         Returns a generator with all environmental vars with prefix VIRTUALENV
       
   772         """
       
   773         for key, val in os.environ.items():
       
   774             if key.startswith(prefix):
       
   775                 yield (key.replace(prefix, '').lower(), val)
       
   776 
       
   777     def get_default_values(self):
       
   778         """
       
   779         Overridding to make updating the defaults after instantiation of
       
   780         the option parser possible, update_defaults() does the dirty work.
       
   781         """
       
   782         if not self.process_default_values:
       
   783             # Old, pre-Optik 1.5 behaviour.
       
   784             return optparse.Values(self.defaults)
       
   785 
       
   786         defaults = self.update_defaults(self.defaults.copy())  # ours
       
   787         for option in self._get_all_options():
       
   788             default = defaults.get(option.dest)
       
   789             if isinstance(default, basestring):
       
   790                 opt_str = option.get_opt_string()
       
   791                 defaults[option.dest] = option.check_value(opt_str, default)
       
   792         return optparse.Values(defaults)
       
   793 
       
   794 
       
   795 def main():
       
   796     parser = ConfigOptionParser(
       
   797         version=virtualenv_version,
       
   798         usage="%prog [OPTIONS] DEST_DIR",
       
   799         formatter=UpdatingDefaultsHelpFormatter())
       
   800 
       
   801     parser.add_option(
       
   802         '-v', '--verbose',
       
   803         action='count',
       
   804         dest='verbose',
       
   805         default=0,
       
   806         help="Increase verbosity")
       
   807 
       
   808     parser.add_option(
       
   809         '-q', '--quiet',
       
   810         action='count',
       
   811         dest='quiet',
       
   812         default=0,
       
   813         help='Decrease verbosity')
       
   814 
       
   815     parser.add_option(
       
   816         '-p', '--python',
       
   817         dest='python',
       
   818         metavar='PYTHON_EXE',
       
   819         help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
       
   820         'interpreter to create the new environment.  The default is the interpreter that '
       
   821         'virtualenv was installed with (%s)' % sys.executable)
       
   822 
       
   823     parser.add_option(
       
   824         '--clear',
       
   825         dest='clear',
       
   826         action='store_true',
       
   827         help="Clear out the non-root install and start from scratch")
       
   828 
       
   829     parser.set_defaults(system_site_packages=False)
       
   830     parser.add_option(
       
   831         '--no-site-packages',
       
   832         dest='system_site_packages',
       
   833         action='store_false',
       
   834         help="Don't give access to the global site-packages dir to the "
       
   835              "virtual environment (default)")
       
   836 
       
   837     parser.add_option(
       
   838         '--system-site-packages',
       
   839         dest='system_site_packages',
       
   840         action='store_true',
       
   841         help="Give access to the global site-packages dir to the "
       
   842              "virtual environment")
       
   843 
       
   844     parser.add_option(
       
   845         '--unzip-setuptools',
       
   846         dest='unzip_setuptools',
       
   847         action='store_true',
       
   848         help="Unzip Setuptools or Distribute when installing it")
       
   849 
       
   850     parser.add_option(
       
   851         '--relocatable',
       
   852         dest='relocatable',
       
   853         action='store_true',
       
   854         help='Make an EXISTING virtualenv environment relocatable.  '
       
   855         'This fixes up scripts and makes all .pth files relative')
       
   856 
       
   857     parser.add_option(
       
   858         '--distribute', '--use-distribute',  # the second option is for legacy reasons here. Hi Kenneth!
       
   859         dest='use_distribute',
       
   860         action='store_true',
       
   861         help='Use Distribute instead of Setuptools. Set environ variable '
       
   862         'VIRTUALENV_DISTRIBUTE to make it the default ')
       
   863 
       
   864     parser.add_option(
       
   865         '--setuptools',
       
   866         dest='use_distribute',
       
   867         action='store_false',
       
   868         help='Use Setuptools instead of Distribute.  Set environ variable '
       
   869         'VIRTUALENV_SETUPTOOLS to make it the default ')
       
   870 
       
   871     # Set this to True to use distribute by default, even in Python 2.
       
   872     parser.set_defaults(use_distribute=False)
       
   873 
       
   874     default_search_dirs = file_search_dirs()
       
   875     parser.add_option(
       
   876         '--extra-search-dir',
       
   877         dest="search_dirs",
       
   878         action="append",
       
   879         default=default_search_dirs,
       
   880         help="Directory to look for setuptools/distribute/pip distributions in. "
       
   881         "You can add any number of additional --extra-search-dir paths.")
       
   882 
       
   883     parser.add_option(
       
   884         '--never-download',
       
   885         dest="never_download",
       
   886         action="store_true",
       
   887         help="Never download anything from the network.  Instead, virtualenv will fail "
       
   888         "if local distributions of setuptools/distribute/pip are not present.")
       
   889 
       
   890     parser.add_option(
       
   891         '--prompt',
       
   892         dest='prompt',
       
   893         help='Provides an alternative prompt prefix for this environment')
       
   894 
       
   895     if 'extend_parser' in globals():
       
   896         extend_parser(parser)
       
   897 
       
   898     options, args = parser.parse_args()
       
   899 
       
   900     global logger
       
   901 
       
   902     if 'adjust_options' in globals():
       
   903         adjust_options(options, args)
       
   904 
       
   905     verbosity = options.verbose - options.quiet
       
   906     logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)])
       
   907 
       
   908     if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
       
   909         env = os.environ.copy()
       
   910         interpreter = resolve_interpreter(options.python)
       
   911         if interpreter == sys.executable:
       
   912             logger.warn('Already using interpreter %s' % interpreter)
       
   913         else:
       
   914             logger.notify('Running virtualenv with interpreter %s' % interpreter)
       
   915             env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
       
   916             file = __file__
       
   917             if file.endswith('.pyc'):
       
   918                 file = file[:-1]
       
   919             popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
       
   920             raise SystemExit(popen.wait())
       
   921 
       
   922     # Force --distribute on Python 3, since setuptools is not available.
       
   923     if majver > 2:
       
   924         options.use_distribute = True
       
   925 
       
   926     if os.environ.get('PYTHONDONTWRITEBYTECODE') and not options.use_distribute:
       
   927         print(
       
   928             "The PYTHONDONTWRITEBYTECODE environment variable is "
       
   929             "not compatible with setuptools. Either use --distribute "
       
   930             "or unset PYTHONDONTWRITEBYTECODE.")
       
   931         sys.exit(2)
       
   932     if not args:
       
   933         print('You must provide a DEST_DIR')
       
   934         parser.print_help()
       
   935         sys.exit(2)
       
   936     if len(args) > 1:
       
   937         print('There must be only one argument: DEST_DIR (you gave %s)' % (
       
   938             ' '.join(args)))
       
   939         parser.print_help()
       
   940         sys.exit(2)
       
   941 
       
   942     home_dir = args[0]
       
   943 
       
   944     if os.environ.get('WORKING_ENV'):
       
   945         logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
       
   946         logger.fatal('Please deactivate your workingenv, then re-run this script')
       
   947         sys.exit(3)
       
   948 
       
   949     if 'PYTHONHOME' in os.environ:
       
   950         logger.warn('PYTHONHOME is set.  You *must* activate the virtualenv before using it')
       
   951         del os.environ['PYTHONHOME']
       
   952 
       
   953     if options.relocatable:
       
   954         make_environment_relocatable(home_dir)
       
   955         return
       
   956 
       
   957     create_environment(home_dir,
       
   958                        site_packages=options.system_site_packages,
       
   959                        clear=options.clear,
       
   960                        unzip_setuptools=options.unzip_setuptools,
       
   961                        use_distribute=options.use_distribute,
       
   962                        prompt=options.prompt,
       
   963                        search_dirs=options.search_dirs,
       
   964                        never_download=options.never_download)
       
   965     if 'after_install' in globals():
       
   966         after_install(options, home_dir)
       
   967 
       
   968 def call_subprocess(cmd, show_stdout=True,
       
   969                     filter_stdout=None, cwd=None,
       
   970                     raise_on_returncode=True, extra_env=None,
       
   971                     remove_from_env=None):
       
   972     cmd_parts = []
       
   973     for part in cmd:
       
   974         if len(part) > 45:
       
   975             part = part[:20]+"..."+part[-20:]
       
   976         if ' ' in part or '\n' in part or '"' in part or "'" in part:
       
   977             part = '"%s"' % part.replace('"', '\\"')
       
   978         if hasattr(part, 'decode'):
       
   979             try:
       
   980                 part = part.decode(sys.getdefaultencoding())
       
   981             except UnicodeDecodeError:
       
   982                 part = part.decode(sys.getfilesystemencoding())
       
   983         cmd_parts.append(part)
       
   984     cmd_desc = ' '.join(cmd_parts)
       
   985     if show_stdout:
       
   986         stdout = None
       
   987     else:
       
   988         stdout = subprocess.PIPE
       
   989     logger.debug("Running command %s" % cmd_desc)
       
   990     if extra_env or remove_from_env:
       
   991         env = os.environ.copy()
       
   992         if extra_env:
       
   993             env.update(extra_env)
       
   994         if remove_from_env:
       
   995             for varname in remove_from_env:
       
   996                 env.pop(varname, None)
       
   997     else:
       
   998         env = None
       
   999     try:
       
  1000         proc = subprocess.Popen(
       
  1001             cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
       
  1002             cwd=cwd, env=env)
       
  1003     except Exception:
       
  1004         e = sys.exc_info()[1]
       
  1005         logger.fatal(
       
  1006             "Error %s while executing command %s" % (e, cmd_desc))
       
  1007         raise
       
  1008     all_output = []
       
  1009     if stdout is not None:
       
  1010         stdout = proc.stdout
       
  1011         encoding = sys.getdefaultencoding()
       
  1012         fs_encoding = sys.getfilesystemencoding()
       
  1013         while 1:
       
  1014             line = stdout.readline()
       
  1015             try:
       
  1016                 line = line.decode(encoding)
       
  1017             except UnicodeDecodeError:
       
  1018                 line = line.decode(fs_encoding)
       
  1019             if not line:
       
  1020                 break
       
  1021             line = line.rstrip()
       
  1022             all_output.append(line)
       
  1023             if filter_stdout:
       
  1024                 level = filter_stdout(line)
       
  1025                 if isinstance(level, tuple):
       
  1026                     level, line = level
       
  1027                 logger.log(level, line)
       
  1028                 if not logger.stdout_level_matches(level):
       
  1029                     logger.show_progress()
       
  1030             else:
       
  1031                 logger.info(line)
       
  1032     else:
       
  1033         proc.communicate()
       
  1034     proc.wait()
       
  1035     if proc.returncode:
       
  1036         if raise_on_returncode:
       
  1037             if all_output:
       
  1038                 logger.notify('Complete output from command %s:' % cmd_desc)
       
  1039                 logger.notify('\n'.join(all_output) + '\n----------------------------------------')
       
  1040             raise OSError(
       
  1041                 "Command %s failed with error code %s"
       
  1042                 % (cmd_desc, proc.returncode))
       
  1043         else:
       
  1044             logger.warn(
       
  1045                 "Command %s had error code %s"
       
  1046                 % (cmd_desc, proc.returncode))
       
  1047 
       
  1048 
       
  1049 def create_environment(home_dir, site_packages=False, clear=False,
       
  1050                        unzip_setuptools=False, use_distribute=False,
       
  1051                        prompt=None, search_dirs=None, never_download=False):
       
  1052     """
       
  1053     Creates a new environment in ``home_dir``.
       
  1054 
       
  1055     If ``site_packages`` is true, then the global ``site-packages/``
       
  1056     directory will be on the path.
       
  1057 
       
  1058     If ``clear`` is true (default False) then the environment will
       
  1059     first be cleared.
       
  1060     """
       
  1061     home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
       
  1062 
       
  1063     py_executable = os.path.abspath(install_python(
       
  1064         home_dir, lib_dir, inc_dir, bin_dir,
       
  1065         site_packages=site_packages, clear=clear))
       
  1066 
       
  1067     install_distutils(home_dir)
       
  1068 
       
  1069     if use_distribute:
       
  1070         install_distribute(py_executable, unzip=unzip_setuptools,
       
  1071                            search_dirs=search_dirs, never_download=never_download)
       
  1072     else:
       
  1073         install_setuptools(py_executable, unzip=unzip_setuptools,
       
  1074                            search_dirs=search_dirs, never_download=never_download)
       
  1075 
       
  1076     install_pip(py_executable, search_dirs=search_dirs, never_download=never_download)
       
  1077 
       
  1078     install_activate(home_dir, bin_dir, prompt)
       
  1079 
       
  1080 def is_executable_file(fpath):
       
  1081     return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
       
  1082 
       
  1083 def path_locations(home_dir):
       
  1084     """Return the path locations for the environment (where libraries are,
       
  1085     where scripts go, etc)"""
       
  1086     # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
       
  1087     # prefix arg is broken: http://bugs.python.org/issue3386
       
  1088     if is_win:
       
  1089         # Windows has lots of problems with executables with spaces in
       
  1090         # the name; this function will remove them (using the ~1
       
  1091         # format):
       
  1092         mkdir(home_dir)
       
  1093         if ' ' in home_dir:
       
  1094             import ctypes
       
  1095             GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW
       
  1096             size = max(len(home_dir)+1, 256)
       
  1097             buf = ctypes.create_unicode_buffer(size)
       
  1098             try:
       
  1099                 u = unicode
       
  1100             except NameError:
       
  1101                 u = str
       
  1102             ret = GetShortPathName(u(home_dir), buf, size)
       
  1103             if not ret:
       
  1104                 print('Error: the path "%s" has a space in it' % home_dir)
       
  1105                 print('We could not determine the short pathname for it.')
       
  1106                 print('Exiting.')
       
  1107                 sys.exit(3)
       
  1108             home_dir = str(buf.value)
       
  1109         lib_dir = join(home_dir, 'Lib')
       
  1110         inc_dir = join(home_dir, 'Include')
       
  1111         bin_dir = join(home_dir, 'Scripts')
       
  1112     if is_jython:
       
  1113         lib_dir = join(home_dir, 'Lib')
       
  1114         inc_dir = join(home_dir, 'Include')
       
  1115         bin_dir = join(home_dir, 'bin')
       
  1116     elif is_pypy:
       
  1117         lib_dir = home_dir
       
  1118         inc_dir = join(home_dir, 'include')
       
  1119         bin_dir = join(home_dir, 'bin')
       
  1120     elif not is_win:
       
  1121         lib_dir = join(home_dir, 'lib', py_version)
       
  1122         multiarch_exec = '/usr/bin/multiarch-platform'
       
  1123         if is_executable_file(multiarch_exec):
       
  1124             # In Mageia (2) and Mandriva distros the include dir must be like:
       
  1125             # virtualenv/include/multiarch-x86_64-linux/python2.7
       
  1126             # instead of being virtualenv/include/python2.7
       
  1127             p = subprocess.Popen(multiarch_exec, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
       
  1128             stdout, stderr = p.communicate()
       
  1129             # stdout.strip is needed to remove newline character
       
  1130             inc_dir = join(home_dir, 'include', stdout.strip(), py_version + abiflags)
       
  1131         else:
       
  1132             inc_dir = join(home_dir, 'include', py_version + abiflags)
       
  1133         bin_dir = join(home_dir, 'bin')
       
  1134     return home_dir, lib_dir, inc_dir, bin_dir
       
  1135 
       
  1136 
       
  1137 def change_prefix(filename, dst_prefix):
       
  1138     prefixes = [sys.prefix]
       
  1139 
       
  1140     if is_darwin:
       
  1141         prefixes.extend((
       
  1142             os.path.join("/Library/Python", sys.version[:3], "site-packages"),
       
  1143             os.path.join(sys.prefix, "Extras", "lib", "python"),
       
  1144             os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"),
       
  1145             # Python 2.6 no-frameworks
       
  1146             os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"),
       
  1147             # System Python 2.7 on OSX Mountain Lion
       
  1148             os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages")))
       
  1149 
       
  1150     if hasattr(sys, 'real_prefix'):
       
  1151         prefixes.append(sys.real_prefix)
       
  1152     if hasattr(sys, 'base_prefix'):
       
  1153         prefixes.append(sys.base_prefix)
       
  1154     prefixes = list(map(os.path.expanduser, prefixes))
       
  1155     prefixes = list(map(os.path.abspath, prefixes))
       
  1156     # Check longer prefixes first so we don't split in the middle of a filename
       
  1157     prefixes = sorted(prefixes, key=len, reverse=True)
       
  1158     filename = os.path.abspath(filename)
       
  1159     for src_prefix in prefixes:
       
  1160         if filename.startswith(src_prefix):
       
  1161             _, relpath = filename.split(src_prefix, 1)
       
  1162             if src_prefix != os.sep: # sys.prefix == "/"
       
  1163                 assert relpath[0] == os.sep
       
  1164                 relpath = relpath[1:]
       
  1165             return join(dst_prefix, relpath)
       
  1166     assert False, "Filename %s does not start with any of these prefixes: %s" % \
       
  1167         (filename, prefixes)
       
  1168 
       
  1169 def copy_required_modules(dst_prefix):
       
  1170     import imp
       
  1171     # If we are running under -p, we need to remove the current
       
  1172     # directory from sys.path temporarily here, so that we
       
  1173     # definitely get the modules from the site directory of
       
  1174     # the interpreter we are running under, not the one
       
  1175     # virtualenv.py is installed under (which might lead to py2/py3
       
  1176     # incompatibility issues)
       
  1177     _prev_sys_path = sys.path
       
  1178     if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
       
  1179         sys.path = sys.path[1:]
       
  1180     try:
       
  1181         for modname in REQUIRED_MODULES:
       
  1182             if modname in sys.builtin_module_names:
       
  1183                 logger.info("Ignoring built-in bootstrap module: %s" % modname)
       
  1184                 continue
       
  1185             try:
       
  1186                 f, filename, _ = imp.find_module(modname)
       
  1187             except ImportError:
       
  1188                 logger.info("Cannot import bootstrap module: %s" % modname)
       
  1189             else:
       
  1190                 if f is not None:
       
  1191                     f.close()
       
  1192                 # special-case custom readline.so on OS X:
       
  1193                 if modname == 'readline' and sys.platform == 'darwin' and not filename.endswith(join('lib-dynload', 'readline.so')):
       
  1194                     dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so')
       
  1195                 else:
       
  1196                     dst_filename = change_prefix(filename, dst_prefix)
       
  1197                 copyfile(filename, dst_filename)
       
  1198                 if filename.endswith('.pyc'):
       
  1199                     pyfile = filename[:-1]
       
  1200                     if os.path.exists(pyfile):
       
  1201                         copyfile(pyfile, dst_filename[:-1])
       
  1202     finally:
       
  1203         sys.path = _prev_sys_path
       
  1204 
       
  1205 
       
  1206 def subst_path(prefix_path, prefix, home_dir):
       
  1207     prefix_path = os.path.normpath(prefix_path)
       
  1208     prefix = os.path.normpath(prefix)
       
  1209     home_dir = os.path.normpath(home_dir)
       
  1210     if not prefix_path.startswith(prefix):
       
  1211         logger.warn('Path not in prefix %r %r', prefix_path, prefix)
       
  1212         return
       
  1213     return prefix_path.replace(prefix, home_dir, 1)
       
  1214 
       
  1215 
       
  1216 def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
       
  1217     """Install just the base environment, no distutils patches etc"""
       
  1218     if sys.executable.startswith(bin_dir):
       
  1219         print('Please use the *system* python to run this script')
       
  1220         return
       
  1221 
       
  1222     if clear:
       
  1223         rmtree(lib_dir)
       
  1224         ## FIXME: why not delete it?
       
  1225         ## Maybe it should delete everything with #!/path/to/venv/python in it
       
  1226         logger.notify('Not deleting %s', bin_dir)
       
  1227 
       
  1228     if hasattr(sys, 'real_prefix'):
       
  1229         logger.notify('Using real prefix %r' % sys.real_prefix)
       
  1230         prefix = sys.real_prefix
       
  1231     elif hasattr(sys, 'base_prefix'):
       
  1232         logger.notify('Using base prefix %r' % sys.base_prefix)
       
  1233         prefix = sys.base_prefix
       
  1234     else:
       
  1235         prefix = sys.prefix
       
  1236     mkdir(lib_dir)
       
  1237     fix_lib64(lib_dir)
       
  1238     stdlib_dirs = [os.path.dirname(os.__file__)]
       
  1239     if is_win:
       
  1240         stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
       
  1241     elif is_darwin:
       
  1242         stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
       
  1243     if hasattr(os, 'symlink'):
       
  1244         logger.info('Symlinking Python bootstrap modules')
       
  1245     else:
       
  1246         logger.info('Copying Python bootstrap modules')
       
  1247     logger.indent += 2
       
  1248     try:
       
  1249         # copy required files...
       
  1250         for stdlib_dir in stdlib_dirs:
       
  1251             if not os.path.isdir(stdlib_dir):
       
  1252                 continue
       
  1253             for fn in os.listdir(stdlib_dir):
       
  1254                 bn = os.path.splitext(fn)[0]
       
  1255                 if fn != 'site-packages' and bn in REQUIRED_FILES:
       
  1256                     copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
       
  1257         # ...and modules
       
  1258         copy_required_modules(home_dir)
       
  1259     finally:
       
  1260         logger.indent -= 2
       
  1261     mkdir(join(lib_dir, 'site-packages'))
       
  1262     import site
       
  1263     site_filename = site.__file__
       
  1264     if site_filename.endswith('.pyc'):
       
  1265         site_filename = site_filename[:-1]
       
  1266     elif site_filename.endswith('$py.class'):
       
  1267         site_filename = site_filename.replace('$py.class', '.py')
       
  1268     site_filename_dst = change_prefix(site_filename, home_dir)
       
  1269     site_dir = os.path.dirname(site_filename_dst)
       
  1270     writefile(site_filename_dst, SITE_PY)
       
  1271     writefile(join(site_dir, 'orig-prefix.txt'), prefix)
       
  1272     site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
       
  1273     if not site_packages:
       
  1274         writefile(site_packages_filename, '')
       
  1275 
       
  1276     if is_pypy or is_win:
       
  1277         stdinc_dir = join(prefix, 'include')
       
  1278     else:
       
  1279         stdinc_dir = join(prefix, 'include', py_version + abiflags)
       
  1280     if os.path.exists(stdinc_dir):
       
  1281         copyfile(stdinc_dir, inc_dir)
       
  1282     else:
       
  1283         logger.debug('No include dir %s' % stdinc_dir)
       
  1284 
       
  1285     platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1)
       
  1286     if platinc_dir != stdinc_dir:
       
  1287         platinc_dest = distutils.sysconfig.get_python_inc(
       
  1288             plat_specific=1, prefix=home_dir)
       
  1289         if platinc_dir == platinc_dest:
       
  1290             # Do platinc_dest manually due to a CPython bug;
       
  1291             # not http://bugs.python.org/issue3386 but a close cousin
       
  1292             platinc_dest = subst_path(platinc_dir, prefix, home_dir)
       
  1293         if platinc_dest:
       
  1294             # PyPy's stdinc_dir and prefix are relative to the original binary
       
  1295             # (traversing virtualenvs), whereas the platinc_dir is relative to
       
  1296             # the inner virtualenv and ignores the prefix argument.
       
  1297             # This seems more evolved than designed.
       
  1298             copyfile(platinc_dir, platinc_dest)
       
  1299 
       
  1300     # pypy never uses exec_prefix, just ignore it
       
  1301     if sys.exec_prefix != prefix and not is_pypy:
       
  1302         if is_win:
       
  1303             exec_dir = join(sys.exec_prefix, 'lib')
       
  1304         elif is_jython:
       
  1305             exec_dir = join(sys.exec_prefix, 'Lib')
       
  1306         else:
       
  1307             exec_dir = join(sys.exec_prefix, 'lib', py_version)
       
  1308         for fn in os.listdir(exec_dir):
       
  1309             copyfile(join(exec_dir, fn), join(lib_dir, fn))
       
  1310 
       
  1311     if is_jython:
       
  1312         # Jython has either jython-dev.jar and javalib/ dir, or just
       
  1313         # jython.jar
       
  1314         for name in 'jython-dev.jar', 'javalib', 'jython.jar':
       
  1315             src = join(prefix, name)
       
  1316             if os.path.exists(src):
       
  1317                 copyfile(src, join(home_dir, name))
       
  1318         # XXX: registry should always exist after Jython 2.5rc1
       
  1319         src = join(prefix, 'registry')
       
  1320         if os.path.exists(src):
       
  1321             copyfile(src, join(home_dir, 'registry'), symlink=False)
       
  1322         copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
       
  1323                  symlink=False)
       
  1324 
       
  1325     mkdir(bin_dir)
       
  1326     py_executable = join(bin_dir, os.path.basename(sys.executable))
       
  1327     if 'Python.framework' in prefix:
       
  1328         # OS X framework builds cause validation to break
       
  1329         # https://github.com/pypa/virtualenv/issues/322
       
  1330         if os.environ.get('__PYVENV_LAUNCHER__'):
       
  1331           os.unsetenv('__PYVENV_LAUNCHER__')
       
  1332         if re.search(r'/Python(?:-32|-64)*$', py_executable):
       
  1333             # The name of the python executable is not quite what
       
  1334             # we want, rename it.
       
  1335             py_executable = os.path.join(
       
  1336                     os.path.dirname(py_executable), 'python')
       
  1337 
       
  1338     logger.notify('New %s executable in %s', expected_exe, py_executable)
       
  1339     pcbuild_dir = os.path.dirname(sys.executable)
       
  1340     pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth')
       
  1341     if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')):
       
  1342         logger.notify('Detected python running from build directory %s', pcbuild_dir)
       
  1343         logger.notify('Writing .pth file linking to build directory for *.pyd files')
       
  1344         writefile(pyd_pth, pcbuild_dir)
       
  1345     else:
       
  1346         pcbuild_dir = None
       
  1347         if os.path.exists(pyd_pth):
       
  1348             logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth)
       
  1349             os.unlink(pyd_pth)
       
  1350 
       
  1351     if sys.executable != py_executable:
       
  1352         ## FIXME: could I just hard link?
       
  1353         executable = sys.executable
       
  1354         if is_cygwin and os.path.exists(executable + '.exe'):
       
  1355             # Cygwin misreports sys.executable sometimes
       
  1356             executable += '.exe'
       
  1357             py_executable += '.exe'
       
  1358             logger.info('Executable actually exists in %s' % executable)
       
  1359         shutil.copyfile(executable, py_executable)
       
  1360         make_exe(py_executable)
       
  1361         if is_win or is_cygwin:
       
  1362             pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
       
  1363             if os.path.exists(pythonw):
       
  1364                 logger.info('Also created pythonw.exe')
       
  1365                 shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
       
  1366             python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe')
       
  1367             python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe')
       
  1368             if os.path.exists(python_d):
       
  1369                 logger.info('Also created python_d.exe')
       
  1370                 shutil.copyfile(python_d, python_d_dest)
       
  1371             elif os.path.exists(python_d_dest):
       
  1372                 logger.info('Removed python_d.exe as it is no longer at the source')
       
  1373                 os.unlink(python_d_dest)
       
  1374             # we need to copy the DLL to enforce that windows will load the correct one.
       
  1375             # may not exist if we are cygwin.
       
  1376             py_executable_dll = 'python%s%s.dll' % (
       
  1377                 sys.version_info[0], sys.version_info[1])
       
  1378             py_executable_dll_d = 'python%s%s_d.dll' % (
       
  1379                 sys.version_info[0], sys.version_info[1])
       
  1380             pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll)
       
  1381             pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d)
       
  1382             pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d)
       
  1383             if os.path.exists(pythondll):
       
  1384                 logger.info('Also created %s' % py_executable_dll)
       
  1385                 shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll))
       
  1386             if os.path.exists(pythondll_d):
       
  1387                 logger.info('Also created %s' % py_executable_dll_d)
       
  1388                 shutil.copyfile(pythondll_d, pythondll_d_dest)
       
  1389             elif os.path.exists(pythondll_d_dest):
       
  1390                 logger.info('Removed %s as the source does not exist' % pythondll_d_dest)
       
  1391                 os.unlink(pythondll_d_dest)
       
  1392         if is_pypy:
       
  1393             # make a symlink python --> pypy-c
       
  1394             python_executable = os.path.join(os.path.dirname(py_executable), 'python')
       
  1395             if sys.platform in ('win32', 'cygwin'):
       
  1396                 python_executable += '.exe'
       
  1397             logger.info('Also created executable %s' % python_executable)
       
  1398             copyfile(py_executable, python_executable)
       
  1399 
       
  1400             if is_win:
       
  1401                 for name in 'libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', 'libeay32.dll', 'ssleay32.dll', 'sqlite.dll':
       
  1402                     src = join(prefix, name)
       
  1403                     if os.path.exists(src):
       
  1404                         copyfile(src, join(bin_dir, name))
       
  1405 
       
  1406     if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
       
  1407         secondary_exe = os.path.join(os.path.dirname(py_executable),
       
  1408                                      expected_exe)
       
  1409         py_executable_ext = os.path.splitext(py_executable)[1]
       
  1410         if py_executable_ext == '.exe':
       
  1411             # python2.4 gives an extension of '.4' :P
       
  1412             secondary_exe += py_executable_ext
       
  1413         if os.path.exists(secondary_exe):
       
  1414             logger.warn('Not overwriting existing %s script %s (you must use %s)'
       
  1415                         % (expected_exe, secondary_exe, py_executable))
       
  1416         else:
       
  1417             logger.notify('Also creating executable in %s' % secondary_exe)
       
  1418             shutil.copyfile(sys.executable, secondary_exe)
       
  1419             make_exe(secondary_exe)
       
  1420 
       
  1421     if '.framework' in prefix:
       
  1422         if 'Python.framework' in prefix:
       
  1423             logger.debug('MacOSX Python framework detected')
       
  1424             # Make sure we use the the embedded interpreter inside
       
  1425             # the framework, even if sys.executable points to
       
  1426             # the stub executable in ${sys.prefix}/bin
       
  1427             # See http://groups.google.com/group/python-virtualenv/
       
  1428             #                              browse_thread/thread/17cab2f85da75951
       
  1429             original_python = os.path.join(
       
  1430                 prefix, 'Resources/Python.app/Contents/MacOS/Python')
       
  1431         if 'EPD' in prefix:
       
  1432             logger.debug('EPD framework detected')
       
  1433             original_python = os.path.join(prefix, 'bin/python')
       
  1434         shutil.copy(original_python, py_executable)
       
  1435 
       
  1436         # Copy the framework's dylib into the virtual
       
  1437         # environment
       
  1438         virtual_lib = os.path.join(home_dir, '.Python')
       
  1439 
       
  1440         if os.path.exists(virtual_lib):
       
  1441             os.unlink(virtual_lib)
       
  1442         copyfile(
       
  1443             os.path.join(prefix, 'Python'),
       
  1444             virtual_lib)
       
  1445 
       
  1446         # And then change the install_name of the copied python executable
       
  1447         try:
       
  1448             mach_o_change(py_executable,
       
  1449                           os.path.join(prefix, 'Python'),
       
  1450                           '@executable_path/../.Python')
       
  1451         except:
       
  1452             e = sys.exc_info()[1]
       
  1453             logger.warn("Could not call mach_o_change: %s. "
       
  1454                         "Trying to call install_name_tool instead." % e)
       
  1455             try:
       
  1456                 call_subprocess(
       
  1457                     ["install_name_tool", "-change",
       
  1458                      os.path.join(prefix, 'Python'),
       
  1459                      '@executable_path/../.Python',
       
  1460                      py_executable])
       
  1461             except:
       
  1462                 logger.fatal("Could not call install_name_tool -- you must "
       
  1463                              "have Apple's development tools installed")
       
  1464                 raise
       
  1465 
       
  1466     if not is_win:
       
  1467         # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist
       
  1468         py_exe_version_major = 'python%s' % sys.version_info[0]
       
  1469         py_exe_version_major_minor = 'python%s.%s' % (
       
  1470             sys.version_info[0], sys.version_info[1])
       
  1471         py_exe_no_version = 'python'
       
  1472         required_symlinks = [ py_exe_no_version, py_exe_version_major,
       
  1473                          py_exe_version_major_minor ]
       
  1474 
       
  1475         py_executable_base = os.path.basename(py_executable)
       
  1476 
       
  1477         if py_executable_base in required_symlinks:
       
  1478             # Don't try to symlink to yourself.
       
  1479             required_symlinks.remove(py_executable_base)
       
  1480 
       
  1481         for pth in required_symlinks:
       
  1482             full_pth = join(bin_dir, pth)
       
  1483             if os.path.exists(full_pth):
       
  1484                 os.unlink(full_pth)
       
  1485             os.symlink(py_executable_base, full_pth)
       
  1486 
       
  1487     if is_win and ' ' in py_executable:
       
  1488         # There's a bug with subprocess on Windows when using a first
       
  1489         # argument that has a space in it.  Instead we have to quote
       
  1490         # the value:
       
  1491         py_executable = '"%s"' % py_executable
       
  1492     # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks
       
  1493     cmd = [py_executable, '-c', 'import sys;out=sys.stdout;'
       
  1494         'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))']
       
  1495     logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
       
  1496     try:
       
  1497         proc = subprocess.Popen(cmd,
       
  1498                             stdout=subprocess.PIPE)
       
  1499         proc_stdout, proc_stderr = proc.communicate()
       
  1500     except OSError:
       
  1501         e = sys.exc_info()[1]
       
  1502         if e.errno == errno.EACCES:
       
  1503             logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e))
       
  1504             sys.exit(100)
       
  1505         else:
       
  1506             raise e
       
  1507 
       
  1508     proc_stdout = proc_stdout.strip().decode("utf-8")
       
  1509     proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
       
  1510     norm_home_dir = os.path.normcase(os.path.abspath(home_dir))
       
  1511     if hasattr(norm_home_dir, 'decode'):
       
  1512         norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding())
       
  1513     if proc_stdout != norm_home_dir:
       
  1514         logger.fatal(
       
  1515             'ERROR: The executable %s is not functioning' % py_executable)
       
  1516         logger.fatal(
       
  1517             'ERROR: It thinks sys.prefix is %r (should be %r)'
       
  1518             % (proc_stdout, norm_home_dir))
       
  1519         logger.fatal(
       
  1520             'ERROR: virtualenv is not compatible with this system or executable')
       
  1521         if is_win:
       
  1522             logger.fatal(
       
  1523                 'Note: some Windows users have reported this error when they '
       
  1524                 'installed Python for "Only this user" or have multiple '
       
  1525                 'versions of Python installed. Copying the appropriate '
       
  1526                 'PythonXX.dll to the virtualenv Scripts/ directory may fix '
       
  1527                 'this problem.')
       
  1528         sys.exit(100)
       
  1529     else:
       
  1530         logger.info('Got sys.prefix result: %r' % proc_stdout)
       
  1531 
       
  1532     pydistutils = os.path.expanduser('~/.pydistutils.cfg')
       
  1533     if os.path.exists(pydistutils):
       
  1534         logger.notify('Please make sure you remove any previous custom paths from '
       
  1535                       'your %s file.' % pydistutils)
       
  1536     ## FIXME: really this should be calculated earlier
       
  1537 
       
  1538     fix_local_scheme(home_dir)
       
  1539 
       
  1540     if site_packages:
       
  1541         if os.path.exists(site_packages_filename):
       
  1542             logger.info('Deleting %s' % site_packages_filename)
       
  1543             os.unlink(site_packages_filename)
       
  1544 
       
  1545     return py_executable
       
  1546 
       
  1547 
       
  1548 def install_activate(home_dir, bin_dir, prompt=None):
       
  1549     home_dir = os.path.abspath(home_dir)
       
  1550     if is_win or is_jython and os._name == 'nt':
       
  1551         files = {
       
  1552             'activate.bat': ACTIVATE_BAT,
       
  1553             'deactivate.bat': DEACTIVATE_BAT,
       
  1554             'activate.ps1': ACTIVATE_PS,
       
  1555         }
       
  1556 
       
  1557         # MSYS needs paths of the form /c/path/to/file
       
  1558         drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/'))
       
  1559         home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail)
       
  1560 
       
  1561         # Run-time conditional enables (basic) Cygwin compatibility
       
  1562         home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" %
       
  1563                        (home_dir, home_dir_msys))
       
  1564         files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh)
       
  1565 
       
  1566     else:
       
  1567         files = {'activate': ACTIVATE_SH}
       
  1568 
       
  1569         # suppling activate.fish in addition to, not instead of, the
       
  1570         # bash script support.
       
  1571         files['activate.fish'] = ACTIVATE_FISH
       
  1572 
       
  1573         # same for csh/tcsh support...
       
  1574         files['activate.csh'] = ACTIVATE_CSH
       
  1575 
       
  1576     files['activate_this.py'] = ACTIVATE_THIS
       
  1577     if hasattr(home_dir, 'decode'):
       
  1578         home_dir = home_dir.decode(sys.getfilesystemencoding())
       
  1579     vname = os.path.basename(home_dir)
       
  1580     for name, content in files.items():
       
  1581         content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
       
  1582         content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname)
       
  1583         content = content.replace('__VIRTUAL_ENV__', home_dir)
       
  1584         content = content.replace('__VIRTUAL_NAME__', vname)
       
  1585         content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
       
  1586         writefile(os.path.join(bin_dir, name), content)
       
  1587 
       
  1588 def install_distutils(home_dir):
       
  1589     distutils_path = change_prefix(distutils.__path__[0], home_dir)
       
  1590     mkdir(distutils_path)
       
  1591     ## FIXME: maybe this prefix setting should only be put in place if
       
  1592     ## there's a local distutils.cfg with a prefix setting?
       
  1593     home_dir = os.path.abspath(home_dir)
       
  1594     ## FIXME: this is breaking things, removing for now:
       
  1595     #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
       
  1596     writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
       
  1597     writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
       
  1598 
       
  1599 def fix_local_scheme(home_dir):
       
  1600     """
       
  1601     Platforms that use the "posix_local" install scheme (like Ubuntu with
       
  1602     Python 2.7) need to be given an additional "local" location, sigh.
       
  1603     """
       
  1604     try:
       
  1605         import sysconfig
       
  1606     except ImportError:
       
  1607         pass
       
  1608     else:
       
  1609         if sysconfig._get_default_scheme() == 'posix_local':
       
  1610             local_path = os.path.join(home_dir, 'local')
       
  1611             if not os.path.exists(local_path):
       
  1612                 os.mkdir(local_path)
       
  1613                 for subdir_name in os.listdir(home_dir):
       
  1614                     if subdir_name == 'local':
       
  1615                         continue
       
  1616                     os.symlink(os.path.abspath(os.path.join(home_dir, subdir_name)), \
       
  1617                                                             os.path.join(local_path, subdir_name))
       
  1618 
       
  1619 def fix_lib64(lib_dir):
       
  1620     """
       
  1621     Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
       
  1622     instead of lib/pythonX.Y.  If this is such a platform we'll just create a
       
  1623     symlink so lib64 points to lib
       
  1624     """
       
  1625     if [p for p in distutils.sysconfig.get_config_vars().values()
       
  1626         if isinstance(p, basestring) and 'lib64' in p]:
       
  1627         logger.debug('This system uses lib64; symlinking lib64 to lib')
       
  1628         assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
       
  1629             "Unexpected python lib dir: %r" % lib_dir)
       
  1630         lib_parent = os.path.dirname(lib_dir)
       
  1631         top_level = os.path.dirname(lib_parent)
       
  1632         lib_dir = os.path.join(top_level, 'lib')
       
  1633         lib64_link = os.path.join(top_level, 'lib64')
       
  1634         assert os.path.basename(lib_parent) == 'lib', (
       
  1635             "Unexpected parent dir: %r" % lib_parent)
       
  1636         if os.path.lexists(lib64_link):
       
  1637             return
       
  1638         os.symlink('lib', lib64_link)
       
  1639 
       
  1640 def resolve_interpreter(exe):
       
  1641     """
       
  1642     If the executable given isn't an absolute path, search $PATH for the interpreter
       
  1643     """
       
  1644     if os.path.abspath(exe) != exe:
       
  1645         paths = os.environ.get('PATH', '').split(os.pathsep)
       
  1646         for path in paths:
       
  1647             if os.path.exists(os.path.join(path, exe)):
       
  1648                 exe = os.path.join(path, exe)
       
  1649                 break
       
  1650     if not os.path.exists(exe):
       
  1651         logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
       
  1652         raise SystemExit(3)
       
  1653     if not is_executable(exe):
       
  1654         logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
       
  1655         raise SystemExit(3)
       
  1656     return exe
       
  1657 
       
  1658 def is_executable(exe):
       
  1659     """Checks a file is executable"""
       
  1660     return os.access(exe, os.X_OK)
       
  1661 
       
  1662 ############################################################
       
  1663 ## Relocating the environment:
       
  1664 
       
  1665 def make_environment_relocatable(home_dir):
       
  1666     """
       
  1667     Makes the already-existing environment use relative paths, and takes out
       
  1668     the #!-based environment selection in scripts.
       
  1669     """
       
  1670     home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
       
  1671     activate_this = os.path.join(bin_dir, 'activate_this.py')
       
  1672     if not os.path.exists(activate_this):
       
  1673         logger.fatal(
       
  1674             'The environment doesn\'t have a file %s -- please re-run virtualenv '
       
  1675             'on this environment to update it' % activate_this)
       
  1676     fixup_scripts(home_dir)
       
  1677     fixup_pth_and_egg_link(home_dir)
       
  1678     ## FIXME: need to fix up distutils.cfg
       
  1679 
       
  1680 OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
       
  1681                   'activate', 'activate.bat', 'activate_this.py']
       
  1682 
       
  1683 def fixup_scripts(home_dir):
       
  1684     # This is what we expect at the top of scripts:
       
  1685     shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
       
  1686     # This is what we'll put:
       
  1687     new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
       
  1688     if is_win:
       
  1689         bin_suffix = 'Scripts'
       
  1690     else:
       
  1691         bin_suffix = 'bin'
       
  1692     bin_dir = os.path.join(home_dir, bin_suffix)
       
  1693     home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
       
  1694     for filename in os.listdir(bin_dir):
       
  1695         filename = os.path.join(bin_dir, filename)
       
  1696         if not os.path.isfile(filename):
       
  1697             # ignore subdirs, e.g. .svn ones.
       
  1698             continue
       
  1699         f = open(filename, 'rb')
       
  1700         try:
       
  1701             try:
       
  1702                 lines = f.read().decode('utf-8').splitlines()
       
  1703             except UnicodeDecodeError:
       
  1704                 # This is probably a binary program instead
       
  1705                 # of a script, so just ignore it.
       
  1706                 continue
       
  1707         finally:
       
  1708             f.close()
       
  1709         if not lines:
       
  1710             logger.warn('Script %s is an empty file' % filename)
       
  1711             continue
       
  1712         if not lines[0].strip().startswith(shebang):
       
  1713             if os.path.basename(filename) in OK_ABS_SCRIPTS:
       
  1714                 logger.debug('Cannot make script %s relative' % filename)
       
  1715             elif lines[0].strip() == new_shebang:
       
  1716                 logger.info('Script %s has already been made relative' % filename)
       
  1717             else:
       
  1718                 logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
       
  1719                             % (filename, shebang))
       
  1720             continue
       
  1721         logger.notify('Making script %s relative' % filename)
       
  1722         script = relative_script([new_shebang] + lines[1:])
       
  1723         f = open(filename, 'wb')
       
  1724         f.write('\n'.join(script).encode('utf-8'))
       
  1725         f.close()
       
  1726 
       
  1727 def relative_script(lines):
       
  1728     "Return a script that'll work in a relocatable environment."
       
  1729     activate = "import os; activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this"
       
  1730     # Find the last future statement in the script. If we insert the activation
       
  1731     # line before a future statement, Python will raise a SyntaxError.
       
  1732     activate_at = None
       
  1733     for idx, line in reversed(list(enumerate(lines))):
       
  1734         if line.split()[:3] == ['from', '__future__', 'import']:
       
  1735             activate_at = idx + 1
       
  1736             break
       
  1737     if activate_at is None:
       
  1738         # Activate after the shebang.
       
  1739         activate_at = 1
       
  1740     return lines[:activate_at] + ['', activate, ''] + lines[activate_at:]
       
  1741 
       
  1742 def fixup_pth_and_egg_link(home_dir, sys_path=None):
       
  1743     """Makes .pth and .egg-link files use relative paths"""
       
  1744     home_dir = os.path.normcase(os.path.abspath(home_dir))
       
  1745     if sys_path is None:
       
  1746         sys_path = sys.path
       
  1747     for path in sys_path:
       
  1748         if not path:
       
  1749             path = '.'
       
  1750         if not os.path.isdir(path):
       
  1751             continue
       
  1752         path = os.path.normcase(os.path.abspath(path))
       
  1753         if not path.startswith(home_dir):
       
  1754             logger.debug('Skipping system (non-environment) directory %s' % path)
       
  1755             continue
       
  1756         for filename in os.listdir(path):
       
  1757             filename = os.path.join(path, filename)
       
  1758             if filename.endswith('.pth'):
       
  1759                 if not os.access(filename, os.W_OK):
       
  1760                     logger.warn('Cannot write .pth file %s, skipping' % filename)
       
  1761                 else:
       
  1762                     fixup_pth_file(filename)
       
  1763             if filename.endswith('.egg-link'):
       
  1764                 if not os.access(filename, os.W_OK):
       
  1765                     logger.warn('Cannot write .egg-link file %s, skipping' % filename)
       
  1766                 else:
       
  1767                     fixup_egg_link(filename)
       
  1768 
       
  1769 def fixup_pth_file(filename):
       
  1770     lines = []
       
  1771     prev_lines = []
       
  1772     f = open(filename)
       
  1773     prev_lines = f.readlines()
       
  1774     f.close()
       
  1775     for line in prev_lines:
       
  1776         line = line.strip()
       
  1777         if (not line or line.startswith('#') or line.startswith('import ')
       
  1778             or os.path.abspath(line) != line):
       
  1779             lines.append(line)
       
  1780         else:
       
  1781             new_value = make_relative_path(filename, line)
       
  1782             if line != new_value:
       
  1783                 logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
       
  1784             lines.append(new_value)
       
  1785     if lines == prev_lines:
       
  1786         logger.info('No changes to .pth file %s' % filename)
       
  1787         return
       
  1788     logger.notify('Making paths in .pth file %s relative' % filename)
       
  1789     f = open(filename, 'w')
       
  1790     f.write('\n'.join(lines) + '\n')
       
  1791     f.close()
       
  1792 
       
  1793 def fixup_egg_link(filename):
       
  1794     f = open(filename)
       
  1795     link = f.readline().strip()
       
  1796     f.close()
       
  1797     if os.path.abspath(link) != link:
       
  1798         logger.debug('Link in %s already relative' % filename)
       
  1799         return
       
  1800     new_link = make_relative_path(filename, link)
       
  1801     logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
       
  1802     f = open(filename, 'w')
       
  1803     f.write(new_link)
       
  1804     f.close()
       
  1805 
       
  1806 def make_relative_path(source, dest, dest_is_directory=True):
       
  1807     """
       
  1808     Make a filename relative, where the filename is dest, and it is
       
  1809     being referred to from the filename source.
       
  1810 
       
  1811         >>> make_relative_path('/usr/share/something/a-file.pth',
       
  1812         ...                    '/usr/share/another-place/src/Directory')
       
  1813         '../another-place/src/Directory'
       
  1814         >>> make_relative_path('/usr/share/something/a-file.pth',
       
  1815         ...                    '/home/user/src/Directory')
       
  1816         '../../../home/user/src/Directory'
       
  1817         >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
       
  1818         './'
       
  1819     """
       
  1820     source = os.path.dirname(source)
       
  1821     if not dest_is_directory:
       
  1822         dest_filename = os.path.basename(dest)
       
  1823         dest = os.path.dirname(dest)
       
  1824     dest = os.path.normpath(os.path.abspath(dest))
       
  1825     source = os.path.normpath(os.path.abspath(source))
       
  1826     dest_parts = dest.strip(os.path.sep).split(os.path.sep)
       
  1827     source_parts = source.strip(os.path.sep).split(os.path.sep)
       
  1828     while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
       
  1829         dest_parts.pop(0)
       
  1830         source_parts.pop(0)
       
  1831     full_parts = ['..']*len(source_parts) + dest_parts
       
  1832     if not dest_is_directory:
       
  1833         full_parts.append(dest_filename)
       
  1834     if not full_parts:
       
  1835         # Special case for the current directory (otherwise it'd be '')
       
  1836         return './'
       
  1837     return os.path.sep.join(full_parts)
       
  1838 
       
  1839 
       
  1840 
       
  1841 ############################################################
       
  1842 ## Bootstrap script creation:
       
  1843 
       
  1844 def create_bootstrap_script(extra_text, python_version=''):
       
  1845     """
       
  1846     Creates a bootstrap script, which is like this script but with
       
  1847     extend_parser, adjust_options, and after_install hooks.
       
  1848 
       
  1849     This returns a string that (written to disk of course) can be used
       
  1850     as a bootstrap script with your own customizations.  The script
       
  1851     will be the standard virtualenv.py script, with your extra text
       
  1852     added (your extra text should be Python code).
       
  1853 
       
  1854     If you include these functions, they will be called:
       
  1855 
       
  1856     ``extend_parser(optparse_parser)``:
       
  1857         You can add or remove options from the parser here.
       
  1858 
       
  1859     ``adjust_options(options, args)``:
       
  1860         You can change options here, or change the args (if you accept
       
  1861         different kinds of arguments, be sure you modify ``args`` so it is
       
  1862         only ``[DEST_DIR]``).
       
  1863 
       
  1864     ``after_install(options, home_dir)``:
       
  1865 
       
  1866         After everything is installed, this function is called.  This
       
  1867         is probably the function you are most likely to use.  An
       
  1868         example would be::
       
  1869 
       
  1870             def after_install(options, home_dir):
       
  1871                 subprocess.call([join(home_dir, 'bin', 'easy_install'),
       
  1872                                  'MyPackage'])
       
  1873                 subprocess.call([join(home_dir, 'bin', 'my-package-script'),
       
  1874                                  'setup', home_dir])
       
  1875 
       
  1876         This example immediately installs a package, and runs a setup
       
  1877         script from that package.
       
  1878 
       
  1879     If you provide something like ``python_version='2.5'`` then the
       
  1880     script will start with ``#!/usr/bin/env python2.5`` instead of
       
  1881     ``#!/usr/bin/env python``.  You can use this when the script must
       
  1882     be run with a particular Python version.
       
  1883     """
       
  1884     filename = __file__
       
  1885     if filename.endswith('.pyc'):
       
  1886         filename = filename[:-1]
       
  1887     f = codecs.open(filename, 'r', encoding='utf-8')
       
  1888     content = f.read()
       
  1889     f.close()
       
  1890     py_exe = 'python%s' % python_version
       
  1891     content = (('#!/usr/bin/env %s\n' % py_exe)
       
  1892                + '## WARNING: This file is generated\n'
       
  1893                + content)
       
  1894     return content.replace('##EXT' 'END##', extra_text)
       
  1895 
       
  1896 ##EXTEND##
       
  1897 
       
  1898 def convert(s):
       
  1899     b = base64.b64decode(s.encode('ascii'))
       
  1900     return zlib.decompress(b).decode('utf-8')
       
  1901 
       
  1902 ##file site.py
       
  1903 SITE_PY = convert("""
       
  1904 eJzFPf1z2zaWv/OvwMqToeTKdOJ0OztO3RsncVrvuYm3SWdz63q0lARZrCmSJUjL6s3d337vAwAB
       
  1905 kpLtTXdO04klEnh4eHhfeHgPHQwGp0Uhs7lY5fM6lULJuJwtRRFXSyUWeSmqZVLOD4q4rDbwdHYb
       
  1906 30glqlyojYqwVRQE+1/4CfbFp2WiDArwLa6rfBVXySxO041IVkVeVnIu5nWZZDciyZIqidPkd2iR
       
  1907 Z5HY/3IMgvNMwMzTRJbiTpYK4CqRL8TlplrmmRjWBc75RfTn+OVoLNSsTIoKGpQaZ6DIMq6CTMo5
       
  1908 oAktawWkTCp5oAo5SxbJzDZc53U6F0Uaz6T45z95atQ0DAOVr+R6KUspMkAGYEqAVSAe8DUpxSyf
       
  1909 y0iI13IW4wD8vCFWwNDGuGYKyZjlIs2zG5hTJmdSqbjciOG0rggQoSzmOeCUAAZVkqbBOi9v1QiW
       
  1910 lNZjDY9EzOzhT4bZA+aJ43c5B3D8kAU/Z8n9mGED9yC4aslsU8pFci9iBAs/5b2cTfSzYbIQ82Sx
       
  1911 ABpk1QibBIyAEmkyPSxoOb7VK/TdIWFluTKGMSSizI35JfWIgvNKxKkCtq0LpJEizN/KaRJnQI3s
       
  1912 DoYDiEDSoG+ceaIqOw7NTuQAoMR1rEBKVkoMV3GSAbP+GM8I7b8n2TxfqxFRAFZLiV9rVbnzH/YQ
       
  1913 AFo7BBgHuFhmNessTW5luhkBAp8A+1KqOq1QIOZJKWdVXiZSEQBAbSPkPSA9FnEpNQmZM43cjon+
       
  1914 RJMkw4VFAUOBx5dIkkVyU5ckYWKRAOcCV7z78JN4e/b6/PS95jEDjGX2ZgU4AxRaaAcnGEAc1qo8
       
  1915 THMQ6Ci4wD8ins9RyG5wfMCraXD44EoHQ5h7EbX7OAsOZNeLq4eBOVagTGisgPr9N3QZqyXQ538e
       
  1916 WO8gON1GFZo4f1svc5DJLF5JsYyZv5Azgm81nO+iolq+Am5QCKcCUilcHEQwQXhAEpdmwzyTogAW
       
  1917 S5NMjgKg0JTa+qsIrPA+zw5orVucABDKIIOXzrMRjZhJmGgX1ivUF6bxhmammwR2nVd5SYoD+D+b
       
  1918 kS5K4+yWcFTEUPxtKm+SLEOEkBeCcC+kgdVtApw4j8QFtSK9YBqJkLUXt0SRqIGXkOmAJ+V9vCpS
       
  1919 OWbxRd26W43QYLISZq1T5jhoWZF6pVVrptrLe0fR5xbXEZrVspQAvJ56QrfI87GYgs4mbIp4xeJV
       
  1920 rXPinKBHnqgT8gS1hL74HSh6qlS9kvYl8gpoFmKoYJGnab4Gkh0HgRB72MgYZZ854S28g38BLv6b
       
  1921 ymq2DAJnJAtYg0Lkt4FCIGASZKa5WiPhcZtm5baSSTLWFHk5lyUN9ThiHzLij2yMcw3e55U2ajxd
       
  1922 XOV8lVSokqbaZCZs8bKwYv34iucN0wDLrYhmpmlDpxVOLy2W8VQal2QqFygJepFe2WWHMYOeMckW
       
  1923 V2LFVgbeAVlkwhakX7Gg0llUkpwAgMHCF2dJUafUSCGDiRgGWhUEfxWjSc+1swTszWY5QIXE5nsG
       
  1924 9gdw+x3EaL1MgD4zgAAaBrUULN80qUp0EBp9FPhG3/Tn8YFTzxfaNvGQizhJtZWPs+CcHp6VJYnv
       
  1925 TBbYa6yJoWCGWYWu3U0GdEQxHwwGQWDcoY0yX3MVVOXmGFhBmHEmk2mdoOGbTNDU6x8q4FGEM7DX
       
  1926 zbaz8EBDmE7vgUpOl0WZr/C1ndtHUCYwFvYI9sQlaRnJDrLHia+QfK5KL0xTtN0OOwvUQ8HlT2fv
       
  1927 zj+ffRQn4qpRaeO2PruGMc+yGNiaLAIwVWvYRpdBS1R8Ceo+8Q7MOzEF2DPqTeIr46oG3gXUP5U1
       
  1928 vYZpzLyXwdn709cXZ5OfP579NPl4/ukMEAQ7I4M9mjKaxxocRhWBcABXzlWk7WvQ6UEPXp9+tA+C
       
  1929 SaImxabYwAMwlMDC5RDmOxYhPpxoGzxJskUejqjxr+yEn7Ba0R7X1fHX1+LkRIS/xndxGIDX0zTl
       
  1930 RfyRBODTppDQtYI/w1yNgmAuFyAstxJFarhPnuyIOwARoWWuLeuveZKZ98xH7hAk8UPqAThMJrM0
       
  1931 VgobTyYhkJY69HygQ8TuMMrJEDoWG7frSKOCn1LCUmTYZYz/9KAYT6kfosEoul1MIxCw1SxWklvR
       
  1932 9KHfZIJaZjIZ6gFB/IjHwUVixREK0wS1TJmAJ0q8glpnqvIUfyJ8lFsSGdwMoV7DRdKbneguTmup
       
  1933 hs6kgIjDYYuMqBoTRRwETsUQbGezdKNRm5qGZ6AZkC/NQe+VLcrhZw88FFAwZtuFWzPeLTHNENO/
       
  1934 8t6AcAAnMUQFrVQLCuszcXl2KV4+PzpABwR2iXNLHa852tQkq6V9uIDVupGVgzD3CsckDCOXLgvU
       
  1935 jPj0eDfMVWRXpssKC73EpVzld3IO2CIDO6ssfqI3sJeGecxiWEXQxGTBWekZTy/GnSPPHqQFrT1Q
       
  1936 b0VQzPqbpd/j7bvMFKgO3goTqfU+nY1XUeZ3CboH041+CdYN1BvaOOOKBM7CeUyGRgw0BPitGVJq
       
  1937 LUNQYGXNLibhjSBRw88bVRgRuAvUrdf09TbL19mE964nqCaHI8u6KFiaebFBswR74h3YDUAyh61Y
       
  1938 QzSGAk66QNk6AORh+jBdoCztBgAQmGZFGywHltmc0RR5n4fDIozRK0HCW0q08HdmCNocGWI4kOht
       
  1939 ZB8YLYGQYHJWwVnVoJkMZc00g4EdkvhcdxHxptEH0KJiBIZuqKFxI0O/q2NQzuLCVUpOP7Shnz9/
       
  1940 ZrZRS4qIIGJTnDQa/QWZt6jYgClMQCcYH4rjK8QGa3BHAUytNGuKg48iL9h/gvW81LINlhv2Y1VV
       
  1941 HB8ertfrSMcD8vLmUC0O//yXb775y3PWifM58Q9Mx5EWHRyLDukd+qDRt8YCfWdWrsWPSeZzI8Ea
       
  1942 SvKjyHlE/L6vk3kujg9GVn8iFzeGFf81zgcokIkZlKkMtB00GD1TB8+il2ognomh23Y4Yk9Cm1Rr
       
  1943 xXyrCz2qHGw3eBqzvM6q0FGkSnwF1g321HM5rW9CO7hnI80PmCrK6dDywMGLa8TA5wzDV8YUT1BL
       
  1944 EFugxXdI/xOzTUz+jNYQSF40UZ397qZfixnizh8v79Y7dITGzDBRyB0oEX6TRwugbdyVHPxoZxTt
       
  1945 nuOMmo9nCIylDwzzaldwiIJDuOBajF2pc7gafVSQpjWrZlAwrmoEBQ1u3ZSprcGRjQwRJHo3ZnvO
       
  1946 C6tbAJ1asT6zozerAC3ccTrWrs0KjieEPHAiXtATCU7tcefdc17aOk0pBNPiUY8qDNhbaLTTOfDl
       
  1947 0AAYi0H584Bbmo3Fh9ai8Br0AMs5aoMMtugwE75xfcDB3qCHnTpWf1tvpnEfCFykIUePHgWdUD7h
       
  1948 EUoF0lQM/Z7bWNwStzvYTotDTGWWiURabRGutvLoFaqdhmmRZKh7nUWKZmkOXrHVisRIzXvfWaCd
       
  1949 Cz7uM2ZaAjUZGnI4jU7I2/MEMNTtMOB1U2NowI2cIEarRJF1QzIt4R9wKygiQeEjoCVBs2AeK2X+
       
  1950 xP4AmbPz1V+2sIclNDKE23SbG9KxGBqOeb8nkIw6fgJSkAEJu8JIriOrgxQ4zFkgT7jhtdwq3QQj
       
  1951 UiBnjgUhNQO400tvg4NPIjyzIAlFyPeVkoX4Sgxg+dqi+jjd/YdyqQkbDJ0G5CroeMOJG4tw4hAn
       
  1952 rbiEz9B+RIJON4ocOHgKLo8bmnfZ3DCtDZOAs+4rbosUaGSKnAxGLqrXhjBu+PdPJ06LhlhmEMNQ
       
  1953 3kDeIYwZaRTY5dagYcENGG/N22Ppx27EAvsOw1wdydU97P/CMlGzXIW4we3ELtyP5ooubSy2F8l0
       
  1954 AH+8BRiMrj1IMtXxC4yy/AuDhB70sA+6N1kMi8zjcp1kISkwTb8Tf2k6eFhSekbu8CNtpw5hohij
       
  1955 PHxXgoDQYeUhiBNqAtiVy1Bpt78LducUBxYudx94bvPV8cvrLnHH2yI89tO/VGf3VRkrXK2UF42F
       
  1956 Alera8BR6cLk4myjjxv1cTRuE8pcwS5SfPj4WSAhOBK7jjdPm3rD8IjNg3PyPgZ10GsPkqs1O2IX
       
  1957 QAS1IjLKYfh0jnw8sk+d3I6JPQHIkxhmx6IYSJpP/hU4uxYKxjiYbzKMo7VVBn7g9TdfT3oioy6S
       
  1958 33w9eGCUFjH6xH7Y8gTtyJQGIHqnbbqUMk7J13A6UVQxa3jHtilGrNBp/6eZ7LrH6dR4UTwzvlfJ
       
  1959 71J8J472918e9bfFj4GH8XAJ7sLzcUPB7qzx43tWW+Fpk7UDWGfjaj57NAXY5ufTX2GzrHR87S5O
       
  1960 UjoUADIcHKCeNft8Dl30KxIP0k5d45Cgbyumrp4DY4QcWBh1p6P9slMTe+7ZEJtPEasuKns6AaA5
       
  1961 v/IO9d2zyy5UveyGh5/zScNRj5byZtznV3yJhsXPH6KMLDCPBoM+sm9lx/+PWT7/90zykVMxx85/
       
  1962 oGF8IqA/aiZsRxiatiM+rP5ld02wAfYIS7XFA93hIXaH5oPGhfHzWCUpsY+6a1+sKdeAwqx4aARQ
       
  1963 5uwC9sDBZdQn1m/qsuRzZ1KBhSwP8Cx1LDDNyjiBlL3VBXP4XlaIiW02o7C1k5ST96mRUAei7UzC
       
  1964 ZgvRL2fL3ISvZHaXlNAXFO4w/OHDj2dhvwnBkC50erwVebwLgXCfwLShJk74lD5Moad0+delqr2L
       
  1965 8QlqjvNNcFiTrdc++DFhE1LoX4MHgkPe2S2fkeNmfbaUs9uJpHN/ZFPs6sTH3+BrxMSmA/jJWype
       
  1966 UAYazGSW1kgr9sExdXBRZzM6KqkkuFo6zxfzfug0nyOBizS+EUPqPMcolOZGClTdxaV2RIsyx8xS
       
  1967 USfzw5tkLuRvdZziDl8uFoALnmPpVxEPT8Eo8ZYTEjjjUMlZXSbVBkgQq1wfA1LugtNwuuGJDj0k
       
  1968 +cSHCYjZDMfiI04b3zPh5oZcJk7gH37gJHELjh3MOS1yFz2H91k+wVEnlKA7ZqS6R/T0OGiPkAOA
       
  1969 AQCF+Q9GOojnv5H0yj1rpDV3iYpa0iOlG3TIyRlDKMMRBj34N/30GdHlrS1Y3mzH8mY3ljdtLG96
       
  1970 sbzxsbzZjaUrEriwNn5lJKEvhtU+4ehNlnHDTzzMWTxbcjtM3MQETYAoCrPXNjLF+ctekIuP+ggI
       
  1971 qW3n7JkeNskvCWeEljlHwzVI5H48z9L7epN57nSmVBrdmadi3NltCUB+38MoojyvKXVneZvHVRx5
       
  1972 cnGT5lMQW4vuuAEwFu1cIA6bZneTKQd6W5ZqcPlfn3748B6bI6iByXSgbriIaFhwKsP9uLxRXWlq
       
  1973 9oEFsCO19HNyqJsGuPfIIBuPssf/vKVkD2QcsaZkhVwU4AFQSpZt5iYuhWHruc5w0s+Zyfnc6UQM
       
  1974 smrQTGoLkU4vL9+efjodUPRv8L8DV2AMbX3pcPExLWyDrv/mNrcUxz4g1DrM1Rg/d04erRuOeNjG
       
  1975 GrAdH7714OgxBrs3YuDP8t9KKVgSIFSk48BPIdSj90BftE3o0McwYidzzz1kY2fFvnNkz3FRHNHv
       
  1976 O4FoD+Cfe+IeYwIE0C7U0OwMms1US+lb87qDog7QR/p6X7wFa2+92jsZn6J2Ej0OoENZ22y7++cd
       
  1977 2bDRU7J6ffb9+fuL89eXp59+cFxAdOU+fDw8Emc/fhaUKoIGjH2iGLMkKkxKAsPiVimJeQ7/1Rj5
       
  1978 mdcVx4uh19uLC31os8I6FUxcRpsTwXPOaLLQOHzGAWn7UKciIUap3iA5BUGUuUMFQ7hfWnExisp1
       
  1979 cjPVGU3RWa311ksXepmCMDrijkD6oLFLCgbB2WbwilLQK7MrLPkwUBdJ9SClbbTNEUkpPNjJHHCO
       
  1980 wsxBixczpc7wpOmsFf1V6OIaXkeqSBPYyb0KrSzpbpgp0zCOfmjPuhmvPg3odIeRdUOe9VYs0Gq9
       
  1981 Cnluuv+oYbTfasCwYbC3MO9MUqYIpU9jnpsIsREf6oTyHr7apddroGDB8MyvwkU0TJfA7GPYXItl
       
  1982 AhsI4MklWF/cJwCE1kr4ZwPHTnRA5pioEb5ZzQ/+FmqC+K1/+aWneVWmB/8QBeyCBGcVhT3EdBu/
       
  1983 hY1PJCNx9uHdKGTkKEtX/K3G3H5wSCgA6kg7pTLxYfpkqGS60Kkmvj7AF9pPoNet7qUsSt293zUO
       
  1984 UQKeqSF5Dc+UoV+ImV8W9hinMmqBxrIFixmW/7kZCeazJz4uZZrqZPXztxdn4DtiJQVKEB/BncFw
       
  1985 HC/B03Sdh8fliS1QeNYOr0tk4xJdWMq3mEdes96gNYoc9fZSNOw6UWC426sTBS7jRLloD3HaDMvU
       
  1986 AkTIyrAWZlmZtVttkMJuG6I4ygyzxOSypFxWnyeAl+lpzFsi2CthnYaJwPOBcpJVJnkxTWagR0Hl
       
  1987 gkIdg5AgcbEYkTgvzzgGnpfK1DDBw2JTJjfLCs85oHNE9RPY/MfTzxfn76mm4Ohl43X3MOeYdgJj
       
  1988 zic5wWxBjHbAFzcDELlqMunjWf0KYaD2gT/tV5yocsIDdPpxYBH/tF9xEdmJsxPkGYCCqou2eOAG
       
  1989 wOnWJzeNLDCudh+MHzcbsMHMB0OxSKxZ0Tkf7vy6nGhbtkwJxX3Myycc4CwKm52mO7vZae2PnuOi
       
  1990 wBOv+bC/Ebztky3zmULX286bbXlw7qcjhVjPChh1W/tjmESxTlM9HYfZtnELbWu1jf0lc2KlTrtZ
       
  1991 hqIMRBy6nUcuk/UrYd2cOdDLqO4AE99qdI0k9qrywS/ZQHsYHiaW2J19iulIFS1kBDCSIXXhTg0+
       
  1992 FFoEUCCUCDx0JHc82j/y5uhYg4fnqHUX2MYfQBHqtFwq98hL4ET48hs7jvyK0EI9eixCx1PJZJbb
       
  1993 lDH8rJfoVb7w59grAxTERLEr4+xGDhnW2MD8yif2lhAsaVuP1FfJdZ9hEefgnN5v4fCuXPQfnBjU
       
  1994 WozQaXcrN2115JMHG/RWhewkmA++jNeg+4u6GvJKbjmH7i2E2w71YYiYiAhN9Tn8MMRwzG/hlvVp
       
  1995 APdSQ8NCD++3LaewvDbGkbX2sVXgFNoX2oOdlbA1qxQdyziVhcYXtV5AY3BPGpM/sE91zpD93VMy
       
  1996 5sSELFAe3AXpzW2gG7TCCQOuXOKyz4Qy45vCGv1uLu9kCkYDjOwQCx9+tYUPo8iGU3pTwr4Yu8vN
       
  1997 5aYfN3rTYHZsKjPQM1MFrF+UyeoQ0emN+OzCrEEGl/oXvSWJs1vykt/8/Xws3rz/Cf59LT+AKcXK
       
  1998 xbH4B6Ah3uQl7C+59JbuRMCijoo3jnmtsLyRoNFRBV8fgW7bpUdnPBbR1SZ+mYnVlAITbMsV31kC
       
  1999 KPIEqRy98RNMDQX8NkVeLW/UeIp9izLQL5EG2+tesFbkULeMltUqRXvhREma1bwaXJy/OXv/8Syq
       
  2000 7pHDzc+BE0Xxc7NwOvqMuMTzsLGwT2Y1Prl2HOcfZFr0+M1602lqaHDTKULYlxR2o8n3YcR2cxGX
       
  2001 GDkQxWaezyJsCSzPZXvVGhzpkbO/fNDQe1YWYQ1H+hSt8ebxMVBD/NJWRANoSH30nKgnIRRPsX6M
       
  2002 H0eDflM8FhTahj/7t+u5GxnXhUA0wTamzayHfnerC5dMZw3PchLhdWKXwdSGpkmsVtOZWzP4IRP6
       
  2003 OhPQcnTOIRdxnVZCZiC5tMmneyVA07tlfiwhzCpszqj2jcI06TreKCcJKVZigKMOqDQeD2QoYgh7
       
  2004 8B/jW7YHWH8oai5kBuiEKO2fcqerqmdLlmDeEhH1ehIP1kn20s3n0RTmQXmHPGscWZgnuo2M0Y2s
       
  2005 9Pz5wXB09aLJdKCo9Mwr8p0VYPVcNtkD1Vns7+8PxH887P0wKlGa57fglgHsXq/lgl5vsdx6cna1
       
  2006 up69eRMBP86W8goeXFP03D6vMwpN7uhKCyLtXwMjxLUJLTOa9i27zEG7kg+auQUfWGnL8XOW0KVF
       
  2007 GFqSqGz13U8YdjLSRCwJiiGM1SxJQg5TwHps8hrr8zDMqPlF3gPHJwhmjG/xhIy32kv0MCmX1nKP
       
  2008 RedEDAjwgHLLeDQqcKYKNcBzcrnRaE7Os6RqSkueu4enupC/sncRab4S8Rolw8yjRQyn1NNj1cbD
       
  2009 zneyqLdjyWdXbsCxNUt+/RDuwNogafliYTCFh2aRZrksZ8ac4ools6RywJh2CIc70xVMZH2ioAel
       
  2010 Aah3sgpzK9H27Z/suriYfqBz5AMzkk4fquy1VhwcirNWgmEUNeNTGMoS0vKt+TKCUd5TWFt7At5Y
       
  2011 4k86qIp1Bd7tG26JY53pWzU4f6O5agPg0E1OVkFadvR0hHN9mIXPTLvlLgz80BadcLtLyqqO04m+
       
  2012 vGGCDtvEHqxrPG1p3M6iT+utgJOfgwd8oLP4wXEwWTZIT0zCNVUaJ2KhQxSRW23mF2YVOXp5R+wr
       
  2013 gU+BlJlPTI20CSJdWXa1xac6Z9NR8QjqK1PQtMUzN5U0nSIUF/Mx5TmZEogtXrTBpX2nhfjuRAxf
       
  2014 jMWfWxuhWbHBW5kA5Wfz6Nk89H0y6np1fNTYme7GswVhK5CX10+ebppMaXphX/r5w3110iFuAFcg
       
  2015 O4tEzg+eKcSOcf5SqBpKM6/tnEIzxur0PZv1pAuzm3IVqkqbgle/bhSKo1qM/2kHMRXfWg9wcSwK
       
  2016 LVsgW9BvEk9ayX/20jVMDNTo+SuLnsuk73AKv+HFKfBeE9R1dLYeWuoMewu2Z0+uyyj5CKpp2HD8
       
  2017 gx7Vk0SpnSPeaYXHk43Euaz/BB4O6ZIZYpqvWsfC/07m4aT9bYeLHSy/+XoXnq6C6a2Y6FnQx1Yx
       
  2018 8KK3SxeahTef/qCXxzJ9Xf940dkqGE9d/kdkBTwsZY+XsF3S9WQq6V79tMING6ZLL2N+g4a3Lo5t
       
  2019 QMMoHjxwGrpJdPipbnsrf1jpoAaubsNd0+f+u+auWwR25uYMuTN3v8LPpYHuu51f+mjAm0lNiEdl
       
  2020 pjdqoV/juMpirFMX+gOj+oPkdzvhTLfonofAmEQJDLMSm2rsjW1YxTP3O+bhHPAltm5BZ69Fak27
       
  2021 o1jaHP8Yc8I5B/jc1nhTIslccyB7p3Qr2YRTEyfy5kZNYrwRb0JbGkqj6fiqxkl+RxeayVhtjG+L
       
  2022 18YACMNNOuHRzWkGxoBtE9/My1kozv0ggoamXE0n+VMlc45TaUcawEUcn6L+Jv7J2ZuDVGJYUdVl
       
  2023 UcLeY6Dvb+X0iL6M0gaoCZesYnVrUDc9xvo6TxyCc3JMEShHxXg/41EHCME63rmcitOhJxP7Dvjl
       
  2024 eVPsnowtQ8isXskyrpqLXvzD2ATsSzMClf7iAjsBkUYyW5ziIpZY/nCQwpCE/f6VduW9rcyOCveR
       
  2025 1XqPZyvqoQNtTymed2yP4ebk3l705l4wNKdrgV1XwjZruM9ebgNLYW4tI12pIxT8Vt+kxPdzcvwU
       
  2026 nRGHj0Du3cI3PwnYqjV2hSwazjNXMXSvzsHabbLFfTfidbige/ddaztjx/f1hmWWjhOypbGlonbg
       
  2027 ehVPM9qo2bdjvt4D+3Y/J/uJ+3YP/iP37fr+QjA4Gh+tD3qztB/Y4LOacC8DbBgB+kyASHh+2LpK
       
  2028 zpjMoZvzDJvr5H5gL+NlnekUUhkzgRzZvSWKQPClf8pNEPUu5dq1b/elix5/f/Hh9ekF0WJyefrm
       
  2029 P0+/p5wYDFK3bNajAxtZfsDUPvCyb90gh85j6Bu8wbbndk0uIdEQOu87R8A9EPrLhfoWtK3I3Nfb
       
  2030 OnTKLrqdAPHd025B3aayeyF3/DOd4u9mL7TSZAP9lHMazS/nYNg8MucjLA7N+Yd534SstYx2Inrb
       
  2031 Fs7JLuyqE+236vsYt0QbRzbHlVYAI9XIXzZQbQoWbDiUHZX2/yKBEnOx2MvcZQJSOJPOnXp0nR6D
       
  2032 qvz/F0MJyi7G0zZ2GMf2XmNqx0F5ZS/sxhO3mYwMQbxqq0F3fq6wz2W6hQpBwApP3xjHiBj9p4+x
       
  2033 7KHvMyWuDqiu8wCVzbX9hWumndy/J3i0W9mblxTnh/DhFjRe1Kl7XGv7dDqQ80dnAPnCKSQAzXcI
       
  2034 dG7EUwF7o8/ECnG6ESFsJPWxJOYmEh31tWkO8mg3HewNrZ6Lg21Vf27VmxAvtjectwrrdI8j7qEe
       
  2035 6KFqU1vlWGBMkttWzie+I8h8iCToqiXP+cCTS33DL3y9u3pxbEO6yO/42lEklMwzcAz7lZMMt/N6
       
  2036 P6c7MUs5pmwp3LM5xaC6xbUDlX2CbXucTkXAln2QOV1mSAPvfX9UxfTwri0ftDG1rHcMUxLDZ2pE
       
  2037 03JqKDTu9smoO91GbXWBcD3II4B0VCDAQjAd3ejk5204yXb4XO8KpzVdjOrG9UNHKihXx+cI7mF8
       
  2038 vwa/dneq43xUd0bR9OcGbQ7USw7Czb4Dtxp5IZHtJqE99YYPtrgAXBLb3//FI/p3s8hs96NdfrVt
       
  2039 9bK3DIt9WUw8xHyMFonM4wiMDOjNIWlrzFY3go63gDR0dBmqmRvyBTp+lMyI1x7TBoOc2Yn2AKxR
       
  2040 CP4PNIke9w==
       
  2041 """)
       
  2042 
       
  2043 ##file ez_setup.py
       
  2044 EZ_SETUP_PY = convert("""
       
  2045 eJzNWmmP20YS/a5fwSgYSIJlDu9DhrzIJg5gIMgGuYCFPavpc8SYIhWS8li7yH/f181DJDWcJIt8
       
  2046 WAbOzJDN6qpXVa+qWvr8s+O52ufZbD6f/z3Pq7IqyNEoRXU6VnmelkaSlRVJU1IlWDR7K41zfjIe
       
  2047 SVYZVW6cSjFcq54WxpGwD+RBLMr6oXk8r41fTmWFBSw9cWFU+6ScySQV6pVqDyHkIAyeFIJVeXE2
       
  2048 HpNqbyTV2iAZNwjn+gW1oVpb5Ucjl/VOrfzNZjYzcMkiPxji3zt930gOx7yolJa7i5Z63fDWcnVl
       
  2049 WSF+PUEdgxjlUbBEJsz4KIoSIKi9L6+u1e9YxfPHLM0Jnx2SosiLtZEXGh2SGSStRJGRSnSLLpau
       
  2050 9aYMq3hulLlBz0Z5Oh7Tc5I9zJSx5Hgs8mORqNfzo3KCxuH+fmzB/b05m/2oYNK4Mr2xkiiM4oTf
       
  2051 S2UKK5KjNq/xqtby+FAQ3vejqYJh1oBXnsvZV2++/uKnb37c/fzm+x/e/uNbY2vMLTNgtj3vHv30
       
  2052 /TcKV/VoX1XHze3t8XxMzDq4zLx4uG2Cory9KW/xX7fb7dy4UbuYDb7vNu7dbHbg/o6TikDgf7TH
       
  2053 Fpc3XmJzar88nh3TNcXDw2JjLKLIcRiRsWU7vsUjL6JxHNBQOj4LRMDIYv2MFK+VQsOYRMSzXOH5
       
  2054 liMpjXwhXGnHnh26PqMTUpyhLn7gh6Ef84gEPJLM86zQIjG3Qid0eBw/L6XTxYMBJOJ2EHOHiiCw
       
  2055 JXEdEgjfEZ6MnCmL3KEulLo2syQL3TgmgeuHcRz6jPBY+sQK7OhZKZ0ubkQihrs8EIw7juOF0g5j
       
  2056 GXISBLEkbEKKN9QlcCzPJ44nuCdsQVkYSmG5MSGeCGQo/GelXHBh1CF25EOPiBMmJXW4DX0sl7rU
       
  2057 Zt7TUtgoXqgrHer7bswD+DWUoUd4GNsOBJHYiiYsYuN4gT1ccCAZhNzhjpTC9iwrdgNPOsSb8DSz
       
  2058 raEyDHA4hPrcJZbjB54fwD/MdiPLIqEVW8+L6bTxQ44X4aOYRlYYOsyPie+SyHNd4nM+iUwtxm/F
       
  2059 cOEFhEXAMg5ZFPt+6AhfRD7CUdCIhc+LCTptIoFMIkJaAQBymAg824M0B0YC8Alvg1SG2DiUCIIc
       
  2060 tl2O95FGTiRCSnzqE2jExfNiLp7igRvLmFoQ5jHP8eLQcj0umCOYxZxJT9lDbAKPxZ50qQxJiCh0
       
  2061 BYtcYVEH7g69mDrPi+mwoZLEjm1ZlMNNHDkBSYJzF44PPCsKJsSMeEZaVuBRGRDi0JBbUAvIeghs
       
  2062 K7JD5kw5asQzgR3YsSMEc33phQJeswPGA2I7kOqEU1JGPCPtCAQF8uUSoUIcP2YxpEibhzSM5ARb
       
  2063 sRHPCEvw0Asih8VxRCUNgXRkIXot+Dy0p5ztDp1EqJB2IDmHYb7v217k2SwEf/E4igN/SsqIrahF
       
  2064 Y9u1CSPUdSyAAZ4LpecxH0QR2vJZKZ1FCBKJPQPuSSpdZBSVsRcwC1CB9cRUwHhDiyLF1iB+12Gc
       
  2065 xix0KJMe6MsJpBMROcVW/tAiIWLJIwvqICERsdIV4HQ/BGHwyA6mPO0PLSISXMUlqoodWrYQADdE
       
  2066 cfIpQ8EjwRTL+CMfRdyVAQjBY4yQKLQ9BA53Q8oYd7nPJ6QEQ4uQMBGqfGTbASpRFHmhAxGomL4X
       
  2067 I7WniDMYVTfmB0T6IQW+6B6QDYEFQzzPRYL5ZIobgqFF1JERCX0HxR60S10UaQuu5sKXaCV8d0JK
       
  2068 OKI7Cz6SMeHMJYHtC9+2faQhWooIFDgZL+GoEpBIxr6HKsDB5ZakQcikLR24AY+cqQwIhxZ5qLEE
       
  2069 fCvRMiABPdezbVtyEbk2/oVTukSjbshSvZATA5GYo36oEASBR66lGivreSmdRYwSNwI3oOfwIpdZ
       
  2070 KmYRbQCbobJMloFoaJEdOnYIkoOjY85s3/Jji/gRdQXyPPanPB0PLYLuzLPQzNgKYerFgfCYpMKK
       
  2071 YCuzpjwdj5gBQYbGDrXVjSIegJ2IEFYA8mKB6031d42UziIp4FpX+MQOqe0wuIn5nk1D1F5UfjFV
       
  2072 SeJhPWIEaWNLxZrEERzEZMcuKltI/dhBjwMpv816EwHGm3JWFedNPXDtSblPE9rOW+jdZ+ITExg1
       
  2073 3uo7b9RI1KzFw/66GRfS2H0kaYJuX+xwawmddhnmwbWhBoDVRhuQSKO9r2bGdjyoH6qLJ5gtKowL
       
  2074 SoR+0dyLT/VdzHftMshpVn627aS8a0XfXeSpC3MXpsHXr9V0UlZcFJjrloMV6porkxoLmvnwBlMY
       
  2075 wRjGPzOM5Xd5WSY07Y1/GOnw9+Fvq/mVsJvOzMGj1eAvpY/4lFRLp75fwLlFpuGqAR0Nh3pRM15t
       
  2076 R8PculNrR0kptr2Bbo1JcYdRdZuXJjsV+K0Opu4FLlJy3tr+rHESxsYvTlV+AA4M0+UZo2jGbzuz
       
  2077 eycFaq4/kA/wJYbnj4CKKIAAnjLtSKp9Pc7fN0rfG+U+P6VcTbOkxrovrZ3Ms9OBisKo9qQyMAh3
       
  2078 grUsNQFnCl1DYurtlDplXL8ijPsBEPeGGmmXj/uE7dvdBbRWRxO1PGNxu1iZULJG6V5tqeT0jjH2
       
  2079 ohgckDwmmLnpJRIEXyMi6wDXKmc58EgLQfj5oj72eCt76mnY9XbN2YQWUzVaamlUaFUaQPSJBcsz
       
  2080 XtbYtGocCQJFgQpEVFolVQLXZQ+984za4439eSb0eUJ9NsJrvQBqnioMnzwfUVo2hw2iEabPcor8
       
  2081 hJ1ErUqdZ8Q4iLIkD6I+4Lgk3f29jpeCJKUwfjiXlTi8+aTwympHZAapcK8+2SBUUYsyXoWgMqY+
       
  2082 9TDbCNU/H0m5q1kI9m+NxfHDw64QZX4qmCgXimHU9oecn1JRqlOSHoGOH9c5gazjiIMGtuXqwiQq
       
  2083 5LaXpOnlZYPYKAXbtFuPEu3CAW2SmEBWFNXSWqtNeiTXEHW306v+6Q5tj/l2jWN2mpi3SkbtIBD7
       
  2084 WNYAIP3wCYbvXmoJqQ9I8+h6h4Foswmu5fyi8evt/EUD1epVI7uvwlDAz/XKL/NMpgmrAM2mz/59
       
  2085 z/9Ztp//uL9E/0S8L19vb8pVl8ttDuujzPfZkPDnjGSLSqVUlyLgDHV8p3OkOa5T2XLKMoSyaXyX
       
  2086 CkRIu/xKnsohlcogIAFbWg1lUpQA4lSqdFhAwrl1vfHyp57yC3Mk7332Plt+eSoKSAOd1wJuilHd
       
  2087 WqFqXWJZmKR4KN9Zd8/XrCd991WCwEzoSdXRb/Pq6xzs3AsUUpazJtvS4ZvrfkK+G6XznXrlc4Ci
       
  2088 CT//MKiZ/RCti+dTmfpXV1CVz8i4Qen86ok6qTOTXHjeSHNWdxmaEWsbkqo+9NVdw/9p3axZVx3r
       
  2089 t3Xz98qmuqd2va6ZNZXfX8rgRKnL6wLX1jdVJ1h1IunFiKZuDGtD+6lBgfJBHUTWHvGY1kHbtqBb
       
  2090 o8dPL29KtNM3peqm5/1cGJ1q14EPuf1yoDAzXgy7vpJ8FNB+iy675vlf8iRbtlWhXVqLKwumxOnW
       
  2091 91sU6LZbVuzTvo68K6tyWYtdbVQyfPExT1QAHQVRJbBVp+ySbUDR6tKhyCFIoVG2KKX5w2CV6q+V
       
  2092 X4bvqgsrzUdSZEuF88u/7qo/9Gi4siHn8qkov9EhoT4MWYqPIlN/wJwjlJ3tRXpUrdzbOtp67UQX
       
  2093 Kug3VPyrj2uWCooZWH5tgKpm6tYB6ZwJAIlXkIeqmQXpikdFsQQTalnqt/u0rknZnDVbgo2btuWy
       
  2094 I1TmbTSbs9kSjCg2CmEt5kDYXnVQPBd1rdnDvVCiesyLD82ma+NYF4ycVqT5qE0xhWaJG5CpYhEg
       
  2095 wHQjrhdA8iUTm8wpRFOA+gaYq7/SiwiK9VXI9Ej3qkfSUbZW2XT1GpoEHaxVoobFphdKhTi+qn8s
       
  2096 R+3UMDpbGtalrpzrLUalTKdcww8mfuZHkS2vln1ufI8+/vaxSCqQD3wMfHUHDQ7/sFaf9j0q76kO
       
  2097 gBUqDUGNLC+Kkw6OVIyEab/3w0M11pXQ61tObK/mk7OpuRoGmGrGWK6GGtcsoq2puWI9f6RzwIkH
       
  2098 prajnqy7lzDfqTlvM6YAbLDRu7A0L8VydUURZbXRQvvPm2rWkhYUTNUvLW3N/sil6vcBkb5ED/Jx
       
  2099 PVWxLzX37XOfg+oa+wbdUrOqLRBP9cejz5efa47reaDj6iuJlzXPzwx6+Lauu6zhZDAYDLTPVGr0
       
  2100 xgGWHw4w1By0he0JDWlmrPZqfKQhTlELNM6rF+oA5W6lw/RRLAod1sJQZfx3Q0VZqnAe1Sql9nUN
       
  2101 waJThqHuw7IzS6TlsMHvmbbbNWjtdsYWU55lWqa9+NNd/z9B8Jpc1ahLyzwVyNWJabft41FM6l79
       
  2102 qkcvxCH/qPlWe6L+GoMealE5KlBv+ju8O2q+J7vsJql+HTYrvWGq3+1cz3d/YEbDz2ea+dEgtpmO
       
  2103 9v85JJ9Ls07w70q5iuan8q5Nt7vhGK7BtlYIfFilqj8cx3SkqCdPR6ja5S8CoFNfa37BZbCldqAO
       
  2104 8/kPV23RfN0yyhwk+KALUaFOdBGEaJIuAT1/Qt5i+T3aqXn7hRvzeB4OlPP6qzTX3zYxV4vmpPLY
       
  2105 1ad2hCkv9PyTfmqoFKGnJK1e1ke/EPmgJsWzYuR+FBfN/KN6rfaouBN7AUT33JfuWv2pViwvXbUW
       
  2106 0tZCXTQXBV1cnnUnx+rdu+bUWbZF9cmTZ9kVu3oErEv0u7n646bY4N8aXIHxoek064as3chE8T2U
       
  2107 y9Vd97JZwuKudB7VUDGf15NCXaT7wMADGCGrdmLQXxHatnfNB1HVSavuL/uT9E53DLtdE/UdJI2M
       
  2108 taFhedW0RC0Ar8bGHkiFaXALPc1SkILtl/P3Wf8rPu+z5bt//Xb3YvXbXLcnq/4Yo9/ucdETjI1C
       
  2109 rr9klRpCscBn8+skbRmxVhX/f7fRgk3dei/t1R3GMA3kC/20fojRFY82d0+bv3hsYkI27VGneg+A
       
  2110 GcxocdxuF7udStjdbtF9sJEqiVBT5/BrR5fD9u939h3eefkSYNWp0itfvdzpljubu6fqouaIi0y1
       
  2111 qL7+C1AkCcw=
       
  2112 """)
       
  2113 
       
  2114 ##file distribute_from_egg.py
       
  2115 DISTRIBUTE_FROM_EGG_PY = convert("""
       
  2116 eJw9j8tqAzEMRfcG/4MgmxQyptkGusonZBmGoGTUGYFfWPKE6dfXTkM3gqt7rh47OKP3NMF3SQFW
       
  2117 LlrRU1zhybpAxoKBlIqcrNnBdRjQP3GTocYfzmNrrCPQPN9iwzpxSQfQhWBi0cL3qtRtYIG/4Mv0
       
  2118 KApY5hooqrOGQ05FQTaxptF9Fnx16Rq0XofjaE1XGXVxHIWK7j8P8EY/rHndLqQ1a0pe3COFgHFy
       
  2119 hLLdWkDbi/DeEpCjNb3u/zccT2Ob8gtnwVyI
       
  2120 """)
       
  2121 
       
  2122 ##file distribute_setup.py
       
  2123 DISTRIBUTE_SETUP_PY = convert("""
       
  2124 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
       
  2211 """)
       
  2212 
       
  2213 ##file activate.sh
       
  2214 ACTIVATE_SH = convert("""
       
  2215 eJytVVFvokAQfudXTLEPtTlLeo9tvMSmJpq02hSvl7u2wRUG2QR2DSxSe7n/frOACEVNLlceRHa+
       
  2216 nfl25pvZDswCnoDPQ4QoTRQsENIEPci4CsBMZBq7CAsuLOYqvmYKTTj3YxnBgiXBudGBjUzBZUJI
       
  2217 BXEqgCvweIyuCjeG4eF2F5x14bcB9KQiQQWrjSddI1/oQIx6SYYeoFjzWIoIhYI1izlbhJjkKO7D
       
  2218 M/QEmKfO9O7WeRo/zr4P7pyHwWxkwitcgwpQ5Ej96OX+PmiFwLeVjFUOrNYKaq1Nud3nR2n8nI2m
       
  2219 k9H0friPTGVsUdptaxGrTEfpNVFEskxpXtUkkCkl1UNF9cgLBkx48J4EXyALuBtAwNYIjF5kcmUU
       
  2220 abMKmMq1ULoiRbgsDEkTSsKSGFCJ6Z8vY/2xYiSacmtyAfCDdCNTVZoVF8vSTQOoEwSnOrngBkws
       
  2221 MYGMBMg8/bMBLSYKS7pYEXP0PqT+ZmBT0Xuy+Pplj5yn4aM9nk72JD8/Wi+Gr98sD9eWSMOwkapD
       
  2222 BbUv91XSvmyVkICt2tmXR4tWmrcUCsjWOpw87YidEC8i0gdTSOFhouJUNxR+4NYBG0MftoCTD9F7
       
  2223 2rTtxG3oPwY1b2HncYwhrlmj6Wq924xtGDWqfdNxap+OYxplEurnMVo9RWks+rH8qKEtx7kZT5zJ
       
  2224 4H7oOFclrN6uFe+d+nW2aIUsSgs/42EIPuOhXq+jEo3S6tX6w2ilNkDnIpHCWdEQhFgwj9pkk7FN
       
  2225 l/y5eQvRSIQ5+TrL05lewxWpt/Lbhes5cJF3mLET1MGhcKCF+40tNWnUulxrpojwDo2sObdje3Bz
       
  2226 N3QeHqf3D7OjEXMVV8LN3ZlvuzoWHqiUcNKHtwNd0IbvPGKYYM31nPKCgkUILw3KL+Y8l7aO1ArS
       
  2227 Ad37nIU0fCj5NE5gQCuC5sOSu+UdI2NeXg/lFkQIlFpdWVaWZRfvqGiirC9o6liJ9FXGYrSY9mI1
       
  2228 D/Ncozgn13vJvsznr7DnkJWXsyMH7e42ljdJ+aqNDF1bFnKWFLdj31xtaJYK6EXFgqmV/ymD/ROG
       
  2229 +n8O9H8f5vsGOWXsL1+1k3g=
       
  2230 """)
       
  2231 
       
  2232 ##file activate.fish
       
  2233 ACTIVATE_FISH = convert("""
       
  2234 eJyVVWFv2jAQ/c6vuBoqQVWC9nVSNVGVCaS2VC2rNLWVZZILWAs2s52wVvvxsyEJDrjbmgpK7PP5
       
  2235 3bt3d22YLbmGlGcIq1wbmCPkGhPYcLMEEsGciwGLDS+YwSjlekngLFVyBe73GXSXxqw/DwbuTS8x
       
  2236 yyKpFr1WG15lDjETQhpQuQBuIOEKY5O9tlppLqxHKSDByjVAPwEy+mXtCq5MzjIUBTCRgEKTKwFG
       
  2237 gpBqxTLYXgN2myspVigMaYF92tZSowGZJf4mFExxNs9Qb614CgZtmH0BpEOn11f0cXI/+za8pnfD
       
  2238 2ZjA1sg9zlV/8QvcMhxbNu0QwgYokn/d+n02nt6Opzcjcnx1vXcIoN74O4ymWQXmHURfJw9jenc/
       
  2239 vbmb0enj6P5+cuVhqlKm3S0u2XRtRbA2QQAhV7VhBF0rsgUX9Ur1rBUXJgVSy8O751k8mzY5OrKH
       
  2240 RW3eaQhYGTr8hrXO59ALhxQ83mCsDLAid3T72CCSdJhaFE+fXgicXAARUiR2WeVO37gH3oYHzFKo
       
  2241 9k7CaPZ1UeNwH1tWuXA4uFKYYcEa8vaKqXl7q1UpygMPhFLvlVKyNzsSM3S2km7UBOl4xweUXk5u
       
  2242 6e3wZmQ9leY1XE/Ili670tr9g/5POBBpGIJXCCF79L1siarl/dbESa8mD8PL61GpzqpzuMS7tqeB
       
  2243 1YkALrRBloBMbR9yLcVx7frQAgUqR7NZIuzkEu110gbNit1enNs82Rx5utq7Z3prU78HFRgulqNC
       
  2244 OTwbqJa9vkJFclQgZSjbKeBgSsUtCtt9D8OwAbIVJuewQdfvQRaoFE9wd1TmCuRG7OgJ1bVXGHc7
       
  2245 z5WDL/WW36v2oi37CyVBak61+yPBA9C1qqGxzKQqZ0oPuocU9hpud0PIp8sDHkXR1HKkNlzjuUWA
       
  2246 a0enFUyzOWZA4yXGP+ZMI3Tdt2OuqU/SO4q64526cPE0A7ZyW2PMbWZiZ5HamIZ2RcCKLXhcDl2b
       
  2247 vXL+eccQoRzem80mekPDEiyiWK4GWqZmwxQOmPM0eIfgp1P9cqrBsewR2p/DPMtt+pfcYM+Ls2uh
       
  2248 hALufTAdmGl8B1H3VPd2af8fQAc4PgqjlIBL9cGQqNpXaAwe3LrtVn8AkZTUxg==
       
  2249 """)
       
  2250 
       
  2251 ##file activate.csh
       
  2252 ACTIVATE_CSH = convert("""
       
  2253 eJx9VG1P2zAQ/u5fcYQKNgTNPtN1WxlIQ4KCUEGaxuQ6yYVYSuzKdhqVX7+zk3bpy5YPUXL3PPfc
       
  2254 ne98DLNCWshliVDV1kGCUFvMoJGugMjq2qQIiVSxSJ1cCofD1BYRnOVGV0CfZ0N2DD91DalQSjsw
       
  2255 tQLpIJMGU1euvPe7QeJlkKzgWixlhnAt4aoUVsLnLBiy5NtbJWQ5THX1ZciYKKWwkOFaE04dUm6D
       
  2256 r/zh7pq/3D7Nnid3/HEy+wFHY/gEJydg0aFaQrBFgz1c5DG1IhTs+UZgsBC2GMFBlaeH+8dZXwcW
       
  2257 VPvCjXdlAvCfQsE7al0+07XjZvrSCUevR5dnkVeKlFYZmUztG4BdzL2u9KyLVabTU0bdfg7a0hgs
       
  2258 cSmUg6UwUiQl2iHrcbcVGNvPCiLOe7+cRwG13z9qRGgx2z6DHjfm/Op2yqeT+xvOLzs0PTKHDz2V
       
  2259 tkckFHoQfQRXoGJAj9el0FyJCmEMhzgMS4sB7KPOE2ExoLcSieYwDvR+cP8cg11gKkVJc2wRcm1g
       
  2260 QhYFlXiTaTfO2ki0fQoiFM4tLuO4aZrhOzqR4dIPcWx17hphMBY+Srwh7RTyN83XOWkcSPh1Pg/k
       
  2261 TXX/jbJTbMtUmcxZ+/bbqOsy82suFQg/BhdSOTRhMNBHlUarCpU7JzBhmkKmRejKOQzayQe6MWoa
       
  2262 n1wqWmuh6LZAaHxcdeqIlVLhIBJdO9/kbl0It2oEXQj+eGjJOuvOIR/YGRqvFhttUB2XTvLXYN2H
       
  2263 37CBdbW2W7j2r2+VsCn0doVWcFG1/4y1VwBjfwAyoZhD
       
  2264 """)
       
  2265 
       
  2266 ##file activate.bat
       
  2267 ACTIVATE_BAT = convert("""
       
  2268 eJx9UdEKgjAUfW6wfxjiIH+hEDKUFHSKLCMI7kNOEkIf9P9pTJ3OLJ/03HPPPed4Es9XS9qqwqgT
       
  2269 PbGKKOdXL4aAFS7A4gvAwgijuiKlqOpGlATS2NeMLE+TjJM9RkQ+SmqAXLrBo1LLIeLdiWlD6jZt
       
  2270 r7VNubWkndkXaxg5GO3UaOOKS6drO3luDDiO5my3iA0YAKGzPRV1ack8cOdhysI0CYzIPzjSiH5X
       
  2271 0QcvC8Lfaj0emsVKYF2rhL5L3fCkVjV76kShi59NHwDniAHzkgDgqBcwOgTMx+gDQQqXCw==
       
  2272 """)
       
  2273 
       
  2274 ##file deactivate.bat
       
  2275 DEACTIVATE_BAT = convert("""
       
  2276 eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgUliIit
       
  2277 KhZlqkpcnCA1WKRsuTTxWBIZ4uHv5+Hv64piEVwU3TK4BNBCmHIcKvDb6xjigWIjkI9uF1AIu7dA
       
  2278 akGGW7n6uXABALCXXUI=
       
  2279 """)
       
  2280 
       
  2281 ##file activate.ps1
       
  2282 ACTIVATE_PS = convert("""
       
  2283 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
       
  2369 QastYw==
       
  2370 """)
       
  2371 
       
  2372 ##file distutils-init.py
       
  2373 DISTUTILS_INIT = convert("""
       
  2374 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
       
  2396 GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ=
       
  2397 """)
       
  2398 
       
  2399 ##file distutils.cfg
       
  2400 DISTUTILS_CFG = convert("""
       
  2401 eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
       
  2402 xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
       
  2403 9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
       
  2404 """)
       
  2405 
       
  2406 ##file activate_this.py
       
  2407 ACTIVATE_THIS = convert("""
       
  2408 eJyNU01v2zAMvetXEB4K21jmDOstQA4dMGCHbeihlyEIDMWmG62yJEiKE//7kXKdpN2KzYBt8euR
       
  2409 fKSyLPs8wiEo8wh4wqZTGou4V6Hm0wJa1cSiTkJdr8+GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe
       
  2410 5a3p0cRKiAe2NtLADikftnDco0ko/SFEVgEZ8aRC5GLux7i3BpSJ6J1H+i7A2CjiHq9z7JRZuuQq
       
  2411 siwTIvpxJYCeuWaBpwZdhB+yxy/eWz+ZvVSU8C4E9FFZkyxFsvCT/ZzL8gcz9aXVE14Yyp2M+2W0
       
  2412 y7n5mp0qN+avKXvbsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCZN9UzlJr+/e/iab8WfqsmPI6pWeUPd
       
  2413 FrMsd4H/55poeO9n54COhUs+sZNEzNtg/wanpjpuqHJaxs76HtZryI/K3H7KJ/KDIhqcbJ7kI4ar
       
  2414 XL+sMgXnX0D+Te2Iy5xdP8yueSlQB/x/ED2BTAtyE3K4SYUN6AMNfbO63f4lBW3bUJPbTL+mjSxS
       
  2415 PyRfJkZRgj+VbFv+EzHFi5pKwUEepa4JslMnwkowSRCXI+m5XvEOvtuBrxHdhLalG0JofYBok6qj
       
  2416 YdN2dEngUlbC4PG60M1WEN0piu7Nq7on0mgyyUw3iV1etLo6r/81biWdQ9MWHFaePWZYaq+nmp+t
       
  2417 s3az+sj7eA0jfgPfeoN1
       
  2418 """)
       
  2419 
       
  2420 MH_MAGIC = 0xfeedface
       
  2421 MH_CIGAM = 0xcefaedfe
       
  2422 MH_MAGIC_64 = 0xfeedfacf
       
  2423 MH_CIGAM_64 = 0xcffaedfe
       
  2424 FAT_MAGIC = 0xcafebabe
       
  2425 BIG_ENDIAN = '>'
       
  2426 LITTLE_ENDIAN = '<'
       
  2427 LC_LOAD_DYLIB = 0xc
       
  2428 maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint')
       
  2429 
       
  2430 
       
  2431 class fileview(object):
       
  2432     """
       
  2433     A proxy for file-like objects that exposes a given view of a file.
       
  2434     Modified from macholib.
       
  2435     """
       
  2436 
       
  2437     def __init__(self, fileobj, start=0, size=maxint):
       
  2438         if isinstance(fileobj, fileview):
       
  2439             self._fileobj = fileobj._fileobj
       
  2440         else:
       
  2441             self._fileobj = fileobj
       
  2442         self._start = start
       
  2443         self._end = start + size
       
  2444         self._pos = 0
       
  2445 
       
  2446     def __repr__(self):
       
  2447         return '<fileview [%d, %d] %r>' % (
       
  2448             self._start, self._end, self._fileobj)
       
  2449 
       
  2450     def tell(self):
       
  2451         return self._pos
       
  2452 
       
  2453     def _checkwindow(self, seekto, op):
       
  2454         if not (self._start <= seekto <= self._end):
       
  2455             raise IOError("%s to offset %d is outside window [%d, %d]" % (
       
  2456                 op, seekto, self._start, self._end))
       
  2457 
       
  2458     def seek(self, offset, whence=0):
       
  2459         seekto = offset
       
  2460         if whence == os.SEEK_SET:
       
  2461             seekto += self._start
       
  2462         elif whence == os.SEEK_CUR:
       
  2463             seekto += self._start + self._pos
       
  2464         elif whence == os.SEEK_END:
       
  2465             seekto += self._end
       
  2466         else:
       
  2467             raise IOError("Invalid whence argument to seek: %r" % (whence,))
       
  2468         self._checkwindow(seekto, 'seek')
       
  2469         self._fileobj.seek(seekto)
       
  2470         self._pos = seekto - self._start
       
  2471 
       
  2472     def write(self, bytes):
       
  2473         here = self._start + self._pos
       
  2474         self._checkwindow(here, 'write')
       
  2475         self._checkwindow(here + len(bytes), 'write')
       
  2476         self._fileobj.seek(here, os.SEEK_SET)
       
  2477         self._fileobj.write(bytes)
       
  2478         self._pos += len(bytes)
       
  2479 
       
  2480     def read(self, size=maxint):
       
  2481         assert size >= 0
       
  2482         here = self._start + self._pos
       
  2483         self._checkwindow(here, 'read')
       
  2484         size = min(size, self._end - here)
       
  2485         self._fileobj.seek(here, os.SEEK_SET)
       
  2486         bytes = self._fileobj.read(size)
       
  2487         self._pos += len(bytes)
       
  2488         return bytes
       
  2489 
       
  2490 
       
  2491 def read_data(file, endian, num=1):
       
  2492     """
       
  2493     Read a given number of 32-bits unsigned integers from the given file
       
  2494     with the given endianness.
       
  2495     """
       
  2496     res = struct.unpack(endian + 'L' * num, file.read(num * 4))
       
  2497     if len(res) == 1:
       
  2498         return res[0]
       
  2499     return res
       
  2500 
       
  2501 
       
  2502 def mach_o_change(path, what, value):
       
  2503     """
       
  2504     Replace a given name (what) in any LC_LOAD_DYLIB command found in
       
  2505     the given binary with a new name (value), provided it's shorter.
       
  2506     """
       
  2507 
       
  2508     def do_macho(file, bits, endian):
       
  2509         # Read Mach-O header (the magic number is assumed read by the caller)
       
  2510         cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6)
       
  2511         # 64-bits header has one more field.
       
  2512         if bits == 64:
       
  2513             read_data(file, endian)
       
  2514         # The header is followed by ncmds commands
       
  2515         for n in range(ncmds):
       
  2516             where = file.tell()
       
  2517             # Read command header
       
  2518             cmd, cmdsize = read_data(file, endian, 2)
       
  2519             if cmd == LC_LOAD_DYLIB:
       
  2520                 # The first data field in LC_LOAD_DYLIB commands is the
       
  2521                 # offset of the name, starting from the beginning of the
       
  2522                 # command.
       
  2523                 name_offset = read_data(file, endian)
       
  2524                 file.seek(where + name_offset, os.SEEK_SET)
       
  2525                 # Read the NUL terminated string
       
  2526                 load = file.read(cmdsize - name_offset).decode()
       
  2527                 load = load[:load.index('\0')]
       
  2528                 # If the string is what is being replaced, overwrite it.
       
  2529                 if load == what:
       
  2530                     file.seek(where + name_offset, os.SEEK_SET)
       
  2531                     file.write(value.encode() + '\0'.encode())
       
  2532             # Seek to the next command
       
  2533             file.seek(where + cmdsize, os.SEEK_SET)
       
  2534 
       
  2535     def do_file(file, offset=0, size=maxint):
       
  2536         file = fileview(file, offset, size)
       
  2537         # Read magic number
       
  2538         magic = read_data(file, BIG_ENDIAN)
       
  2539         if magic == FAT_MAGIC:
       
  2540             # Fat binaries contain nfat_arch Mach-O binaries
       
  2541             nfat_arch = read_data(file, BIG_ENDIAN)
       
  2542             for n in range(nfat_arch):
       
  2543                 # Read arch header
       
  2544                 cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5)
       
  2545                 do_file(file, offset, size)
       
  2546         elif magic == MH_MAGIC:
       
  2547             do_macho(file, 32, BIG_ENDIAN)
       
  2548         elif magic == MH_CIGAM:
       
  2549             do_macho(file, 32, LITTLE_ENDIAN)
       
  2550         elif magic == MH_MAGIC_64:
       
  2551             do_macho(file, 64, BIG_ENDIAN)
       
  2552         elif magic == MH_CIGAM_64:
       
  2553             do_macho(file, 64, LITTLE_ENDIAN)
       
  2554 
       
  2555     assert(len(what) >= len(value))
       
  2556     do_file(open(path, 'r+b'))
       
  2557 
       
  2558 
       
  2559 if __name__ == '__main__':
       
  2560     main()
       
  2561 
       
  2562 ## TODO:
       
  2563 ## Copy python.exe.manifest
       
  2564 ## Monkeypatch distutils.sysconfig