virtualenv/web/virtualenv.py
changeset 10 fb466c64d84c
equal deleted inserted replaced
9:2e1053dff5f2 10:fb466c64d84c
       
     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.9.1"  # 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         '--no-setuptools',
       
   866         dest='no_setuptools',
       
   867         action='store_true',
       
   868         help='Do not install distribute/setuptools (or pip) '
       
   869         'in the new virtualenv.')
       
   870 
       
   871     parser.add_option(
       
   872         '--no-pip',
       
   873         dest='no_pip',
       
   874         action='store_true',
       
   875         help='Do not install pip in the new virtualenv.')
       
   876 
       
   877     parser.add_option(
       
   878         '--setuptools',
       
   879         dest='use_distribute',
       
   880         action='store_false',
       
   881         help='Use Setuptools instead of Distribute.  Set environ variable '
       
   882         'VIRTUALENV_SETUPTOOLS to make it the default ')
       
   883 
       
   884     # Set this to True to use distribute by default, even in Python 2.
       
   885     parser.set_defaults(use_distribute=False)
       
   886 
       
   887     default_search_dirs = file_search_dirs()
       
   888     parser.add_option(
       
   889         '--extra-search-dir',
       
   890         dest="search_dirs",
       
   891         action="append",
       
   892         default=default_search_dirs,
       
   893         help="Directory to look for setuptools/distribute/pip distributions in. "
       
   894         "You can add any number of additional --extra-search-dir paths.")
       
   895 
       
   896     parser.add_option(
       
   897         '--never-download',
       
   898         dest="never_download",
       
   899         action="store_true",
       
   900         help="Never download anything from the network.  Instead, virtualenv will fail "
       
   901         "if local distributions of setuptools/distribute/pip are not present.")
       
   902 
       
   903     parser.add_option(
       
   904         '--prompt',
       
   905         dest='prompt',
       
   906         help='Provides an alternative prompt prefix for this environment')
       
   907 
       
   908     if 'extend_parser' in globals():
       
   909         extend_parser(parser)
       
   910 
       
   911     options, args = parser.parse_args()
       
   912 
       
   913     global logger
       
   914 
       
   915     if 'adjust_options' in globals():
       
   916         adjust_options(options, args)
       
   917 
       
   918     verbosity = options.verbose - options.quiet
       
   919     logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)])
       
   920 
       
   921     if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
       
   922         env = os.environ.copy()
       
   923         interpreter = resolve_interpreter(options.python)
       
   924         if interpreter == sys.executable:
       
   925             logger.warn('Already using interpreter %s' % interpreter)
       
   926         else:
       
   927             logger.notify('Running virtualenv with interpreter %s' % interpreter)
       
   928             env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
       
   929             file = __file__
       
   930             if file.endswith('.pyc'):
       
   931                 file = file[:-1]
       
   932             popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
       
   933             raise SystemExit(popen.wait())
       
   934 
       
   935     # Force --distribute on Python 3, since setuptools is not available.
       
   936     if majver > 2:
       
   937         options.use_distribute = True
       
   938 
       
   939     if os.environ.get('PYTHONDONTWRITEBYTECODE') and not options.use_distribute:
       
   940         print(
       
   941             "The PYTHONDONTWRITEBYTECODE environment variable is "
       
   942             "not compatible with setuptools. Either use --distribute "
       
   943             "or unset PYTHONDONTWRITEBYTECODE.")
       
   944         sys.exit(2)
       
   945     if not args:
       
   946         print('You must provide a DEST_DIR')
       
   947         parser.print_help()
       
   948         sys.exit(2)
       
   949     if len(args) > 1:
       
   950         print('There must be only one argument: DEST_DIR (you gave %s)' % (
       
   951             ' '.join(args)))
       
   952         parser.print_help()
       
   953         sys.exit(2)
       
   954 
       
   955     home_dir = args[0]
       
   956 
       
   957     if os.environ.get('WORKING_ENV'):
       
   958         logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
       
   959         logger.fatal('Please deactivate your workingenv, then re-run this script')
       
   960         sys.exit(3)
       
   961 
       
   962     if 'PYTHONHOME' in os.environ:
       
   963         logger.warn('PYTHONHOME is set.  You *must* activate the virtualenv before using it')
       
   964         del os.environ['PYTHONHOME']
       
   965 
       
   966     if options.relocatable:
       
   967         make_environment_relocatable(home_dir)
       
   968         return
       
   969 
       
   970     create_environment(home_dir,
       
   971                        site_packages=options.system_site_packages,
       
   972                        clear=options.clear,
       
   973                        unzip_setuptools=options.unzip_setuptools,
       
   974                        use_distribute=options.use_distribute,
       
   975                        prompt=options.prompt,
       
   976                        search_dirs=options.search_dirs,
       
   977                        never_download=options.never_download,
       
   978                        no_setuptools=options.no_setuptools,
       
   979                        no_pip=options.no_pip)
       
   980     if 'after_install' in globals():
       
   981         after_install(options, home_dir)
       
   982 
       
   983 def call_subprocess(cmd, show_stdout=True,
       
   984                     filter_stdout=None, cwd=None,
       
   985                     raise_on_returncode=True, extra_env=None,
       
   986                     remove_from_env=None):
       
   987     cmd_parts = []
       
   988     for part in cmd:
       
   989         if len(part) > 45:
       
   990             part = part[:20]+"..."+part[-20:]
       
   991         if ' ' in part or '\n' in part or '"' in part or "'" in part:
       
   992             part = '"%s"' % part.replace('"', '\\"')
       
   993         if hasattr(part, 'decode'):
       
   994             try:
       
   995                 part = part.decode(sys.getdefaultencoding())
       
   996             except UnicodeDecodeError:
       
   997                 part = part.decode(sys.getfilesystemencoding())
       
   998         cmd_parts.append(part)
       
   999     cmd_desc = ' '.join(cmd_parts)
       
  1000     if show_stdout:
       
  1001         stdout = None
       
  1002     else:
       
  1003         stdout = subprocess.PIPE
       
  1004     logger.debug("Running command %s" % cmd_desc)
       
  1005     if extra_env or remove_from_env:
       
  1006         env = os.environ.copy()
       
  1007         if extra_env:
       
  1008             env.update(extra_env)
       
  1009         if remove_from_env:
       
  1010             for varname in remove_from_env:
       
  1011                 env.pop(varname, None)
       
  1012     else:
       
  1013         env = None
       
  1014     try:
       
  1015         proc = subprocess.Popen(
       
  1016             cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
       
  1017             cwd=cwd, env=env)
       
  1018     except Exception:
       
  1019         e = sys.exc_info()[1]
       
  1020         logger.fatal(
       
  1021             "Error %s while executing command %s" % (e, cmd_desc))
       
  1022         raise
       
  1023     all_output = []
       
  1024     if stdout is not None:
       
  1025         stdout = proc.stdout
       
  1026         encoding = sys.getdefaultencoding()
       
  1027         fs_encoding = sys.getfilesystemencoding()
       
  1028         while 1:
       
  1029             line = stdout.readline()
       
  1030             try:
       
  1031                 line = line.decode(encoding)
       
  1032             except UnicodeDecodeError:
       
  1033                 line = line.decode(fs_encoding)
       
  1034             if not line:
       
  1035                 break
       
  1036             line = line.rstrip()
       
  1037             all_output.append(line)
       
  1038             if filter_stdout:
       
  1039                 level = filter_stdout(line)
       
  1040                 if isinstance(level, tuple):
       
  1041                     level, line = level
       
  1042                 logger.log(level, line)
       
  1043                 if not logger.stdout_level_matches(level):
       
  1044                     logger.show_progress()
       
  1045             else:
       
  1046                 logger.info(line)
       
  1047     else:
       
  1048         proc.communicate()
       
  1049     proc.wait()
       
  1050     if proc.returncode:
       
  1051         if raise_on_returncode:
       
  1052             if all_output:
       
  1053                 logger.notify('Complete output from command %s:' % cmd_desc)
       
  1054                 logger.notify('\n'.join(all_output) + '\n----------------------------------------')
       
  1055             raise OSError(
       
  1056                 "Command %s failed with error code %s"
       
  1057                 % (cmd_desc, proc.returncode))
       
  1058         else:
       
  1059             logger.warn(
       
  1060                 "Command %s had error code %s"
       
  1061                 % (cmd_desc, proc.returncode))
       
  1062 
       
  1063 
       
  1064 def create_environment(home_dir, site_packages=False, clear=False,
       
  1065                        unzip_setuptools=False, use_distribute=False,
       
  1066                        prompt=None, search_dirs=None, never_download=False,
       
  1067                        no_setuptools=False, no_pip=False):
       
  1068     """
       
  1069     Creates a new environment in ``home_dir``.
       
  1070 
       
  1071     If ``site_packages`` is true, then the global ``site-packages/``
       
  1072     directory will be on the path.
       
  1073 
       
  1074     If ``clear`` is true (default False) then the environment will
       
  1075     first be cleared.
       
  1076     """
       
  1077     home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
       
  1078 
       
  1079     py_executable = os.path.abspath(install_python(
       
  1080         home_dir, lib_dir, inc_dir, bin_dir,
       
  1081         site_packages=site_packages, clear=clear))
       
  1082 
       
  1083     install_distutils(home_dir)
       
  1084 
       
  1085     if not no_setuptools:
       
  1086         if use_distribute:
       
  1087             install_distribute(py_executable, unzip=unzip_setuptools,
       
  1088                                search_dirs=search_dirs, never_download=never_download)
       
  1089         else:
       
  1090             install_setuptools(py_executable, unzip=unzip_setuptools,
       
  1091                                search_dirs=search_dirs, never_download=never_download)
       
  1092 
       
  1093         if not no_pip:
       
  1094             install_pip(py_executable, search_dirs=search_dirs, never_download=never_download)
       
  1095 
       
  1096     install_activate(home_dir, bin_dir, prompt)
       
  1097 
       
  1098 def is_executable_file(fpath):
       
  1099     return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
       
  1100 
       
  1101 def path_locations(home_dir):
       
  1102     """Return the path locations for the environment (where libraries are,
       
  1103     where scripts go, etc)"""
       
  1104     # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
       
  1105     # prefix arg is broken: http://bugs.python.org/issue3386
       
  1106     if is_win:
       
  1107         # Windows has lots of problems with executables with spaces in
       
  1108         # the name; this function will remove them (using the ~1
       
  1109         # format):
       
  1110         mkdir(home_dir)
       
  1111         if ' ' in home_dir:
       
  1112             import ctypes
       
  1113             GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW
       
  1114             size = max(len(home_dir)+1, 256)
       
  1115             buf = ctypes.create_unicode_buffer(size)
       
  1116             try:
       
  1117                 u = unicode
       
  1118             except NameError:
       
  1119                 u = str
       
  1120             ret = GetShortPathName(u(home_dir), buf, size)
       
  1121             if not ret:
       
  1122                 print('Error: the path "%s" has a space in it' % home_dir)
       
  1123                 print('We could not determine the short pathname for it.')
       
  1124                 print('Exiting.')
       
  1125                 sys.exit(3)
       
  1126             home_dir = str(buf.value)
       
  1127         lib_dir = join(home_dir, 'Lib')
       
  1128         inc_dir = join(home_dir, 'Include')
       
  1129         bin_dir = join(home_dir, 'Scripts')
       
  1130     if is_jython:
       
  1131         lib_dir = join(home_dir, 'Lib')
       
  1132         inc_dir = join(home_dir, 'Include')
       
  1133         bin_dir = join(home_dir, 'bin')
       
  1134     elif is_pypy:
       
  1135         lib_dir = home_dir
       
  1136         inc_dir = join(home_dir, 'include')
       
  1137         bin_dir = join(home_dir, 'bin')
       
  1138     elif not is_win:
       
  1139         lib_dir = join(home_dir, 'lib', py_version)
       
  1140         multiarch_exec = '/usr/bin/multiarch-platform'
       
  1141         if is_executable_file(multiarch_exec):
       
  1142             # In Mageia (2) and Mandriva distros the include dir must be like:
       
  1143             # virtualenv/include/multiarch-x86_64-linux/python2.7
       
  1144             # instead of being virtualenv/include/python2.7
       
  1145             p = subprocess.Popen(multiarch_exec, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
       
  1146             stdout, stderr = p.communicate()
       
  1147             # stdout.strip is needed to remove newline character
       
  1148             inc_dir = join(home_dir, 'include', stdout.strip(), py_version + abiflags)
       
  1149         else:
       
  1150             inc_dir = join(home_dir, 'include', py_version + abiflags)
       
  1151         bin_dir = join(home_dir, 'bin')
       
  1152     return home_dir, lib_dir, inc_dir, bin_dir
       
  1153 
       
  1154 
       
  1155 def change_prefix(filename, dst_prefix):
       
  1156     prefixes = [sys.prefix]
       
  1157 
       
  1158     if is_darwin:
       
  1159         prefixes.extend((
       
  1160             os.path.join("/Library/Python", sys.version[:3], "site-packages"),
       
  1161             os.path.join(sys.prefix, "Extras", "lib", "python"),
       
  1162             os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"),
       
  1163             # Python 2.6 no-frameworks
       
  1164             os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"),
       
  1165             # System Python 2.7 on OSX Mountain Lion
       
  1166             os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages")))
       
  1167 
       
  1168     if hasattr(sys, 'real_prefix'):
       
  1169         prefixes.append(sys.real_prefix)
       
  1170     if hasattr(sys, 'base_prefix'):
       
  1171         prefixes.append(sys.base_prefix)
       
  1172     prefixes = list(map(os.path.expanduser, prefixes))
       
  1173     prefixes = list(map(os.path.abspath, prefixes))
       
  1174     # Check longer prefixes first so we don't split in the middle of a filename
       
  1175     prefixes = sorted(prefixes, key=len, reverse=True)
       
  1176     filename = os.path.abspath(filename)
       
  1177     for src_prefix in prefixes:
       
  1178         if filename.startswith(src_prefix):
       
  1179             _, relpath = filename.split(src_prefix, 1)
       
  1180             if src_prefix != os.sep: # sys.prefix == "/"
       
  1181                 assert relpath[0] == os.sep
       
  1182                 relpath = relpath[1:]
       
  1183             return join(dst_prefix, relpath)
       
  1184     assert False, "Filename %s does not start with any of these prefixes: %s" % \
       
  1185         (filename, prefixes)
       
  1186 
       
  1187 def copy_required_modules(dst_prefix):
       
  1188     import imp
       
  1189     # If we are running under -p, we need to remove the current
       
  1190     # directory from sys.path temporarily here, so that we
       
  1191     # definitely get the modules from the site directory of
       
  1192     # the interpreter we are running under, not the one
       
  1193     # virtualenv.py is installed under (which might lead to py2/py3
       
  1194     # incompatibility issues)
       
  1195     _prev_sys_path = sys.path
       
  1196     if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
       
  1197         sys.path = sys.path[1:]
       
  1198     try:
       
  1199         for modname in REQUIRED_MODULES:
       
  1200             if modname in sys.builtin_module_names:
       
  1201                 logger.info("Ignoring built-in bootstrap module: %s" % modname)
       
  1202                 continue
       
  1203             try:
       
  1204                 f, filename, _ = imp.find_module(modname)
       
  1205             except ImportError:
       
  1206                 logger.info("Cannot import bootstrap module: %s" % modname)
       
  1207             else:
       
  1208                 if f is not None:
       
  1209                     f.close()
       
  1210                 # special-case custom readline.so on OS X, but not for pypy:
       
  1211                 if modname == 'readline' and sys.platform == 'darwin' and not (
       
  1212                         is_pypy or filename.endswith(join('lib-dynload', 'readline.so'))):
       
  1213                     dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so')
       
  1214                 else:
       
  1215                     dst_filename = change_prefix(filename, dst_prefix)
       
  1216                 copyfile(filename, dst_filename)
       
  1217                 if filename.endswith('.pyc'):
       
  1218                     pyfile = filename[:-1]
       
  1219                     if os.path.exists(pyfile):
       
  1220                         copyfile(pyfile, dst_filename[:-1])
       
  1221     finally:
       
  1222         sys.path = _prev_sys_path
       
  1223 
       
  1224 
       
  1225 def subst_path(prefix_path, prefix, home_dir):
       
  1226     prefix_path = os.path.normpath(prefix_path)
       
  1227     prefix = os.path.normpath(prefix)
       
  1228     home_dir = os.path.normpath(home_dir)
       
  1229     if not prefix_path.startswith(prefix):
       
  1230         logger.warn('Path not in prefix %r %r', prefix_path, prefix)
       
  1231         return
       
  1232     return prefix_path.replace(prefix, home_dir, 1)
       
  1233 
       
  1234 
       
  1235 def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
       
  1236     """Install just the base environment, no distutils patches etc"""
       
  1237     if sys.executable.startswith(bin_dir):
       
  1238         print('Please use the *system* python to run this script')
       
  1239         return
       
  1240 
       
  1241     if clear:
       
  1242         rmtree(lib_dir)
       
  1243         ## FIXME: why not delete it?
       
  1244         ## Maybe it should delete everything with #!/path/to/venv/python in it
       
  1245         logger.notify('Not deleting %s', bin_dir)
       
  1246 
       
  1247     if hasattr(sys, 'real_prefix'):
       
  1248         logger.notify('Using real prefix %r' % sys.real_prefix)
       
  1249         prefix = sys.real_prefix
       
  1250     elif hasattr(sys, 'base_prefix'):
       
  1251         logger.notify('Using base prefix %r' % sys.base_prefix)
       
  1252         prefix = sys.base_prefix
       
  1253     else:
       
  1254         prefix = sys.prefix
       
  1255     mkdir(lib_dir)
       
  1256     fix_lib64(lib_dir)
       
  1257     stdlib_dirs = [os.path.dirname(os.__file__)]
       
  1258     if is_win:
       
  1259         stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
       
  1260     elif is_darwin:
       
  1261         stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
       
  1262     if hasattr(os, 'symlink'):
       
  1263         logger.info('Symlinking Python bootstrap modules')
       
  1264     else:
       
  1265         logger.info('Copying Python bootstrap modules')
       
  1266     logger.indent += 2
       
  1267     try:
       
  1268         # copy required files...
       
  1269         for stdlib_dir in stdlib_dirs:
       
  1270             if not os.path.isdir(stdlib_dir):
       
  1271                 continue
       
  1272             for fn in os.listdir(stdlib_dir):
       
  1273                 bn = os.path.splitext(fn)[0]
       
  1274                 if fn != 'site-packages' and bn in REQUIRED_FILES:
       
  1275                     copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
       
  1276         # ...and modules
       
  1277         copy_required_modules(home_dir)
       
  1278     finally:
       
  1279         logger.indent -= 2
       
  1280     mkdir(join(lib_dir, 'site-packages'))
       
  1281     import site
       
  1282     site_filename = site.__file__
       
  1283     if site_filename.endswith('.pyc'):
       
  1284         site_filename = site_filename[:-1]
       
  1285     elif site_filename.endswith('$py.class'):
       
  1286         site_filename = site_filename.replace('$py.class', '.py')
       
  1287     site_filename_dst = change_prefix(site_filename, home_dir)
       
  1288     site_dir = os.path.dirname(site_filename_dst)
       
  1289     writefile(site_filename_dst, SITE_PY)
       
  1290     writefile(join(site_dir, 'orig-prefix.txt'), prefix)
       
  1291     site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
       
  1292     if not site_packages:
       
  1293         writefile(site_packages_filename, '')
       
  1294 
       
  1295     if is_pypy or is_win:
       
  1296         stdinc_dir = join(prefix, 'include')
       
  1297     else:
       
  1298         stdinc_dir = join(prefix, 'include', py_version + abiflags)
       
  1299     if os.path.exists(stdinc_dir):
       
  1300         copyfile(stdinc_dir, inc_dir)
       
  1301     else:
       
  1302         logger.debug('No include dir %s' % stdinc_dir)
       
  1303 
       
  1304     platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1)
       
  1305     if platinc_dir != stdinc_dir:
       
  1306         platinc_dest = distutils.sysconfig.get_python_inc(
       
  1307             plat_specific=1, prefix=home_dir)
       
  1308         if platinc_dir == platinc_dest:
       
  1309             # Do platinc_dest manually due to a CPython bug;
       
  1310             # not http://bugs.python.org/issue3386 but a close cousin
       
  1311             platinc_dest = subst_path(platinc_dir, prefix, home_dir)
       
  1312         if platinc_dest:
       
  1313             # PyPy's stdinc_dir and prefix are relative to the original binary
       
  1314             # (traversing virtualenvs), whereas the platinc_dir is relative to
       
  1315             # the inner virtualenv and ignores the prefix argument.
       
  1316             # This seems more evolved than designed.
       
  1317             copyfile(platinc_dir, platinc_dest)
       
  1318 
       
  1319     # pypy never uses exec_prefix, just ignore it
       
  1320     if sys.exec_prefix != prefix and not is_pypy:
       
  1321         if is_win:
       
  1322             exec_dir = join(sys.exec_prefix, 'lib')
       
  1323         elif is_jython:
       
  1324             exec_dir = join(sys.exec_prefix, 'Lib')
       
  1325         else:
       
  1326             exec_dir = join(sys.exec_prefix, 'lib', py_version)
       
  1327         for fn in os.listdir(exec_dir):
       
  1328             copyfile(join(exec_dir, fn), join(lib_dir, fn))
       
  1329 
       
  1330     if is_jython:
       
  1331         # Jython has either jython-dev.jar and javalib/ dir, or just
       
  1332         # jython.jar
       
  1333         for name in 'jython-dev.jar', 'javalib', 'jython.jar':
       
  1334             src = join(prefix, name)
       
  1335             if os.path.exists(src):
       
  1336                 copyfile(src, join(home_dir, name))
       
  1337         # XXX: registry should always exist after Jython 2.5rc1
       
  1338         src = join(prefix, 'registry')
       
  1339         if os.path.exists(src):
       
  1340             copyfile(src, join(home_dir, 'registry'), symlink=False)
       
  1341         copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
       
  1342                  symlink=False)
       
  1343 
       
  1344     mkdir(bin_dir)
       
  1345     py_executable = join(bin_dir, os.path.basename(sys.executable))
       
  1346     if 'Python.framework' in prefix:
       
  1347         # OS X framework builds cause validation to break
       
  1348         # https://github.com/pypa/virtualenv/issues/322
       
  1349         if os.environ.get('__PYVENV_LAUNCHER__'):
       
  1350           os.unsetenv('__PYVENV_LAUNCHER__')
       
  1351         if re.search(r'/Python(?:-32|-64)*$', py_executable):
       
  1352             # The name of the python executable is not quite what
       
  1353             # we want, rename it.
       
  1354             py_executable = os.path.join(
       
  1355                     os.path.dirname(py_executable), 'python')
       
  1356 
       
  1357     logger.notify('New %s executable in %s', expected_exe, py_executable)
       
  1358     pcbuild_dir = os.path.dirname(sys.executable)
       
  1359     pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth')
       
  1360     if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')):
       
  1361         logger.notify('Detected python running from build directory %s', pcbuild_dir)
       
  1362         logger.notify('Writing .pth file linking to build directory for *.pyd files')
       
  1363         writefile(pyd_pth, pcbuild_dir)
       
  1364     else:
       
  1365         pcbuild_dir = None
       
  1366         if os.path.exists(pyd_pth):
       
  1367             logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth)
       
  1368             os.unlink(pyd_pth)
       
  1369 
       
  1370     if sys.executable != py_executable:
       
  1371         ## FIXME: could I just hard link?
       
  1372         executable = sys.executable
       
  1373         shutil.copyfile(executable, py_executable)
       
  1374         make_exe(py_executable)
       
  1375         if is_win or is_cygwin:
       
  1376             pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
       
  1377             if os.path.exists(pythonw):
       
  1378                 logger.info('Also created pythonw.exe')
       
  1379                 shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
       
  1380             python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe')
       
  1381             python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe')
       
  1382             if os.path.exists(python_d):
       
  1383                 logger.info('Also created python_d.exe')
       
  1384                 shutil.copyfile(python_d, python_d_dest)
       
  1385             elif os.path.exists(python_d_dest):
       
  1386                 logger.info('Removed python_d.exe as it is no longer at the source')
       
  1387                 os.unlink(python_d_dest)
       
  1388             # we need to copy the DLL to enforce that windows will load the correct one.
       
  1389             # may not exist if we are cygwin.
       
  1390             py_executable_dll = 'python%s%s.dll' % (
       
  1391                 sys.version_info[0], sys.version_info[1])
       
  1392             py_executable_dll_d = 'python%s%s_d.dll' % (
       
  1393                 sys.version_info[0], sys.version_info[1])
       
  1394             pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll)
       
  1395             pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d)
       
  1396             pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d)
       
  1397             if os.path.exists(pythondll):
       
  1398                 logger.info('Also created %s' % py_executable_dll)
       
  1399                 shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll))
       
  1400             if os.path.exists(pythondll_d):
       
  1401                 logger.info('Also created %s' % py_executable_dll_d)
       
  1402                 shutil.copyfile(pythondll_d, pythondll_d_dest)
       
  1403             elif os.path.exists(pythondll_d_dest):
       
  1404                 logger.info('Removed %s as the source does not exist' % pythondll_d_dest)
       
  1405                 os.unlink(pythondll_d_dest)
       
  1406         if is_pypy:
       
  1407             # make a symlink python --> pypy-c
       
  1408             python_executable = os.path.join(os.path.dirname(py_executable), 'python')
       
  1409             if sys.platform in ('win32', 'cygwin'):
       
  1410                 python_executable += '.exe'
       
  1411             logger.info('Also created executable %s' % python_executable)
       
  1412             copyfile(py_executable, python_executable)
       
  1413 
       
  1414             if is_win:
       
  1415                 for name in 'libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', 'libeay32.dll', 'ssleay32.dll', 'sqlite.dll':
       
  1416                     src = join(prefix, name)
       
  1417                     if os.path.exists(src):
       
  1418                         copyfile(src, join(bin_dir, name))
       
  1419 
       
  1420     if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
       
  1421         secondary_exe = os.path.join(os.path.dirname(py_executable),
       
  1422                                      expected_exe)
       
  1423         py_executable_ext = os.path.splitext(py_executable)[1]
       
  1424         if py_executable_ext == '.exe':
       
  1425             # python2.4 gives an extension of '.4' :P
       
  1426             secondary_exe += py_executable_ext
       
  1427         if os.path.exists(secondary_exe):
       
  1428             logger.warn('Not overwriting existing %s script %s (you must use %s)'
       
  1429                         % (expected_exe, secondary_exe, py_executable))
       
  1430         else:
       
  1431             logger.notify('Also creating executable in %s' % secondary_exe)
       
  1432             shutil.copyfile(sys.executable, secondary_exe)
       
  1433             make_exe(secondary_exe)
       
  1434 
       
  1435     if '.framework' in prefix:
       
  1436         if 'Python.framework' in prefix:
       
  1437             logger.debug('MacOSX Python framework detected')
       
  1438             # Make sure we use the the embedded interpreter inside
       
  1439             # the framework, even if sys.executable points to
       
  1440             # the stub executable in ${sys.prefix}/bin
       
  1441             # See http://groups.google.com/group/python-virtualenv/
       
  1442             #                              browse_thread/thread/17cab2f85da75951
       
  1443             original_python = os.path.join(
       
  1444                 prefix, 'Resources/Python.app/Contents/MacOS/Python')
       
  1445         if 'EPD' in prefix:
       
  1446             logger.debug('EPD framework detected')
       
  1447             original_python = os.path.join(prefix, 'bin/python')
       
  1448         shutil.copy(original_python, py_executable)
       
  1449 
       
  1450         # Copy the framework's dylib into the virtual
       
  1451         # environment
       
  1452         virtual_lib = os.path.join(home_dir, '.Python')
       
  1453 
       
  1454         if os.path.exists(virtual_lib):
       
  1455             os.unlink(virtual_lib)
       
  1456         copyfile(
       
  1457             os.path.join(prefix, 'Python'),
       
  1458             virtual_lib)
       
  1459 
       
  1460         # And then change the install_name of the copied python executable
       
  1461         try:
       
  1462             mach_o_change(py_executable,
       
  1463                           os.path.join(prefix, 'Python'),
       
  1464                           '@executable_path/../.Python')
       
  1465         except:
       
  1466             e = sys.exc_info()[1]
       
  1467             logger.warn("Could not call mach_o_change: %s. "
       
  1468                         "Trying to call install_name_tool instead." % e)
       
  1469             try:
       
  1470                 call_subprocess(
       
  1471                     ["install_name_tool", "-change",
       
  1472                      os.path.join(prefix, 'Python'),
       
  1473                      '@executable_path/../.Python',
       
  1474                      py_executable])
       
  1475             except:
       
  1476                 logger.fatal("Could not call install_name_tool -- you must "
       
  1477                              "have Apple's development tools installed")
       
  1478                 raise
       
  1479 
       
  1480     if not is_win:
       
  1481         # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist
       
  1482         py_exe_version_major = 'python%s' % sys.version_info[0]
       
  1483         py_exe_version_major_minor = 'python%s.%s' % (
       
  1484             sys.version_info[0], sys.version_info[1])
       
  1485         py_exe_no_version = 'python'
       
  1486         required_symlinks = [ py_exe_no_version, py_exe_version_major,
       
  1487                          py_exe_version_major_minor ]
       
  1488 
       
  1489         py_executable_base = os.path.basename(py_executable)
       
  1490 
       
  1491         if py_executable_base in required_symlinks:
       
  1492             # Don't try to symlink to yourself.
       
  1493             required_symlinks.remove(py_executable_base)
       
  1494 
       
  1495         for pth in required_symlinks:
       
  1496             full_pth = join(bin_dir, pth)
       
  1497             if os.path.exists(full_pth):
       
  1498                 os.unlink(full_pth)
       
  1499             os.symlink(py_executable_base, full_pth)
       
  1500 
       
  1501     if is_win and ' ' in py_executable:
       
  1502         # There's a bug with subprocess on Windows when using a first
       
  1503         # argument that has a space in it.  Instead we have to quote
       
  1504         # the value:
       
  1505         py_executable = '"%s"' % py_executable
       
  1506     # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks
       
  1507     cmd = [py_executable, '-c', 'import sys;out=sys.stdout;'
       
  1508         'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))']
       
  1509     logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
       
  1510     try:
       
  1511         proc = subprocess.Popen(cmd,
       
  1512                             stdout=subprocess.PIPE)
       
  1513         proc_stdout, proc_stderr = proc.communicate()
       
  1514     except OSError:
       
  1515         e = sys.exc_info()[1]
       
  1516         if e.errno == errno.EACCES:
       
  1517             logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e))
       
  1518             sys.exit(100)
       
  1519         else:
       
  1520             raise e
       
  1521 
       
  1522     proc_stdout = proc_stdout.strip().decode("utf-8")
       
  1523     proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
       
  1524     norm_home_dir = os.path.normcase(os.path.abspath(home_dir))
       
  1525     if hasattr(norm_home_dir, 'decode'):
       
  1526         norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding())
       
  1527     if proc_stdout != norm_home_dir:
       
  1528         logger.fatal(
       
  1529             'ERROR: The executable %s is not functioning' % py_executable)
       
  1530         logger.fatal(
       
  1531             'ERROR: It thinks sys.prefix is %r (should be %r)'
       
  1532             % (proc_stdout, norm_home_dir))
       
  1533         logger.fatal(
       
  1534             'ERROR: virtualenv is not compatible with this system or executable')
       
  1535         if is_win:
       
  1536             logger.fatal(
       
  1537                 'Note: some Windows users have reported this error when they '
       
  1538                 'installed Python for "Only this user" or have multiple '
       
  1539                 'versions of Python installed. Copying the appropriate '
       
  1540                 'PythonXX.dll to the virtualenv Scripts/ directory may fix '
       
  1541                 'this problem.')
       
  1542         sys.exit(100)
       
  1543     else:
       
  1544         logger.info('Got sys.prefix result: %r' % proc_stdout)
       
  1545 
       
  1546     pydistutils = os.path.expanduser('~/.pydistutils.cfg')
       
  1547     if os.path.exists(pydistutils):
       
  1548         logger.notify('Please make sure you remove any previous custom paths from '
       
  1549                       'your %s file.' % pydistutils)
       
  1550     ## FIXME: really this should be calculated earlier
       
  1551 
       
  1552     fix_local_scheme(home_dir)
       
  1553 
       
  1554     if site_packages:
       
  1555         if os.path.exists(site_packages_filename):
       
  1556             logger.info('Deleting %s' % site_packages_filename)
       
  1557             os.unlink(site_packages_filename)
       
  1558 
       
  1559     return py_executable
       
  1560 
       
  1561 
       
  1562 def install_activate(home_dir, bin_dir, prompt=None):
       
  1563     home_dir = os.path.abspath(home_dir)
       
  1564     if is_win or is_jython and os._name == 'nt':
       
  1565         files = {
       
  1566             'activate.bat': ACTIVATE_BAT,
       
  1567             'deactivate.bat': DEACTIVATE_BAT,
       
  1568             'activate.ps1': ACTIVATE_PS,
       
  1569         }
       
  1570 
       
  1571         # MSYS needs paths of the form /c/path/to/file
       
  1572         drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/'))
       
  1573         home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail)
       
  1574 
       
  1575         # Run-time conditional enables (basic) Cygwin compatibility
       
  1576         home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" %
       
  1577                        (home_dir, home_dir_msys))
       
  1578         files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh)
       
  1579 
       
  1580     else:
       
  1581         files = {'activate': ACTIVATE_SH}
       
  1582 
       
  1583         # suppling activate.fish in addition to, not instead of, the
       
  1584         # bash script support.
       
  1585         files['activate.fish'] = ACTIVATE_FISH
       
  1586 
       
  1587         # same for csh/tcsh support...
       
  1588         files['activate.csh'] = ACTIVATE_CSH
       
  1589 
       
  1590     files['activate_this.py'] = ACTIVATE_THIS
       
  1591     if hasattr(home_dir, 'decode'):
       
  1592         home_dir = home_dir.decode(sys.getfilesystemencoding())
       
  1593     vname = os.path.basename(home_dir)
       
  1594     for name, content in files.items():
       
  1595         content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
       
  1596         content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname)
       
  1597         content = content.replace('__VIRTUAL_ENV__', home_dir)
       
  1598         content = content.replace('__VIRTUAL_NAME__', vname)
       
  1599         content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
       
  1600         writefile(os.path.join(bin_dir, name), content)
       
  1601 
       
  1602 def install_distutils(home_dir):
       
  1603     distutils_path = change_prefix(distutils.__path__[0], home_dir)
       
  1604     mkdir(distutils_path)
       
  1605     ## FIXME: maybe this prefix setting should only be put in place if
       
  1606     ## there's a local distutils.cfg with a prefix setting?
       
  1607     home_dir = os.path.abspath(home_dir)
       
  1608     ## FIXME: this is breaking things, removing for now:
       
  1609     #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
       
  1610     writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
       
  1611     writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
       
  1612 
       
  1613 def fix_local_scheme(home_dir):
       
  1614     """
       
  1615     Platforms that use the "posix_local" install scheme (like Ubuntu with
       
  1616     Python 2.7) need to be given an additional "local" location, sigh.
       
  1617     """
       
  1618     try:
       
  1619         import sysconfig
       
  1620     except ImportError:
       
  1621         pass
       
  1622     else:
       
  1623         if sysconfig._get_default_scheme() == 'posix_local':
       
  1624             local_path = os.path.join(home_dir, 'local')
       
  1625             if not os.path.exists(local_path):
       
  1626                 os.mkdir(local_path)
       
  1627                 for subdir_name in os.listdir(home_dir):
       
  1628                     if subdir_name == 'local':
       
  1629                         continue
       
  1630                     os.symlink(os.path.abspath(os.path.join(home_dir, subdir_name)), \
       
  1631                                                             os.path.join(local_path, subdir_name))
       
  1632 
       
  1633 def fix_lib64(lib_dir):
       
  1634     """
       
  1635     Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
       
  1636     instead of lib/pythonX.Y.  If this is such a platform we'll just create a
       
  1637     symlink so lib64 points to lib
       
  1638     """
       
  1639     if [p for p in distutils.sysconfig.get_config_vars().values()
       
  1640         if isinstance(p, basestring) and 'lib64' in p]:
       
  1641         logger.debug('This system uses lib64; symlinking lib64 to lib')
       
  1642         assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
       
  1643             "Unexpected python lib dir: %r" % lib_dir)
       
  1644         lib_parent = os.path.dirname(lib_dir)
       
  1645         top_level = os.path.dirname(lib_parent)
       
  1646         lib_dir = os.path.join(top_level, 'lib')
       
  1647         lib64_link = os.path.join(top_level, 'lib64')
       
  1648         assert os.path.basename(lib_parent) == 'lib', (
       
  1649             "Unexpected parent dir: %r" % lib_parent)
       
  1650         if os.path.lexists(lib64_link):
       
  1651             return
       
  1652         os.symlink('lib', lib64_link)
       
  1653 
       
  1654 def resolve_interpreter(exe):
       
  1655     """
       
  1656     If the executable given isn't an absolute path, search $PATH for the interpreter
       
  1657     """
       
  1658     if os.path.abspath(exe) != exe:
       
  1659         paths = os.environ.get('PATH', '').split(os.pathsep)
       
  1660         for path in paths:
       
  1661             if os.path.exists(os.path.join(path, exe)):
       
  1662                 exe = os.path.join(path, exe)
       
  1663                 break
       
  1664     if not os.path.exists(exe):
       
  1665         logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
       
  1666         raise SystemExit(3)
       
  1667     if not is_executable(exe):
       
  1668         logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
       
  1669         raise SystemExit(3)
       
  1670     return exe
       
  1671 
       
  1672 def is_executable(exe):
       
  1673     """Checks a file is executable"""
       
  1674     return os.access(exe, os.X_OK)
       
  1675 
       
  1676 ############################################################
       
  1677 ## Relocating the environment:
       
  1678 
       
  1679 def make_environment_relocatable(home_dir):
       
  1680     """
       
  1681     Makes the already-existing environment use relative paths, and takes out
       
  1682     the #!-based environment selection in scripts.
       
  1683     """
       
  1684     home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
       
  1685     activate_this = os.path.join(bin_dir, 'activate_this.py')
       
  1686     if not os.path.exists(activate_this):
       
  1687         logger.fatal(
       
  1688             'The environment doesn\'t have a file %s -- please re-run virtualenv '
       
  1689             'on this environment to update it' % activate_this)
       
  1690     fixup_scripts(home_dir)
       
  1691     fixup_pth_and_egg_link(home_dir)
       
  1692     ## FIXME: need to fix up distutils.cfg
       
  1693 
       
  1694 OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
       
  1695                   'activate', 'activate.bat', 'activate_this.py']
       
  1696 
       
  1697 def fixup_scripts(home_dir):
       
  1698     # This is what we expect at the top of scripts:
       
  1699     shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
       
  1700     # This is what we'll put:
       
  1701     new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
       
  1702     if is_win:
       
  1703         bin_suffix = 'Scripts'
       
  1704     else:
       
  1705         bin_suffix = 'bin'
       
  1706     bin_dir = os.path.join(home_dir, bin_suffix)
       
  1707     home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
       
  1708     for filename in os.listdir(bin_dir):
       
  1709         filename = os.path.join(bin_dir, filename)
       
  1710         if not os.path.isfile(filename):
       
  1711             # ignore subdirs, e.g. .svn ones.
       
  1712             continue
       
  1713         f = open(filename, 'rb')
       
  1714         try:
       
  1715             try:
       
  1716                 lines = f.read().decode('utf-8').splitlines()
       
  1717             except UnicodeDecodeError:
       
  1718                 # This is probably a binary program instead
       
  1719                 # of a script, so just ignore it.
       
  1720                 continue
       
  1721         finally:
       
  1722             f.close()
       
  1723         if not lines:
       
  1724             logger.warn('Script %s is an empty file' % filename)
       
  1725             continue
       
  1726         if not lines[0].strip().startswith(shebang):
       
  1727             if os.path.basename(filename) in OK_ABS_SCRIPTS:
       
  1728                 logger.debug('Cannot make script %s relative' % filename)
       
  1729             elif lines[0].strip() == new_shebang:
       
  1730                 logger.info('Script %s has already been made relative' % filename)
       
  1731             else:
       
  1732                 logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
       
  1733                             % (filename, shebang))
       
  1734             continue
       
  1735         logger.notify('Making script %s relative' % filename)
       
  1736         script = relative_script([new_shebang] + lines[1:])
       
  1737         f = open(filename, 'wb')
       
  1738         f.write('\n'.join(script).encode('utf-8'))
       
  1739         f.close()
       
  1740 
       
  1741 def relative_script(lines):
       
  1742     "Return a script that'll work in a relocatable environment."
       
  1743     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"
       
  1744     # Find the last future statement in the script. If we insert the activation
       
  1745     # line before a future statement, Python will raise a SyntaxError.
       
  1746     activate_at = None
       
  1747     for idx, line in reversed(list(enumerate(lines))):
       
  1748         if line.split()[:3] == ['from', '__future__', 'import']:
       
  1749             activate_at = idx + 1
       
  1750             break
       
  1751     if activate_at is None:
       
  1752         # Activate after the shebang.
       
  1753         activate_at = 1
       
  1754     return lines[:activate_at] + ['', activate, ''] + lines[activate_at:]
       
  1755 
       
  1756 def fixup_pth_and_egg_link(home_dir, sys_path=None):
       
  1757     """Makes .pth and .egg-link files use relative paths"""
       
  1758     home_dir = os.path.normcase(os.path.abspath(home_dir))
       
  1759     if sys_path is None:
       
  1760         sys_path = sys.path
       
  1761     for path in sys_path:
       
  1762         if not path:
       
  1763             path = '.'
       
  1764         if not os.path.isdir(path):
       
  1765             continue
       
  1766         path = os.path.normcase(os.path.abspath(path))
       
  1767         if not path.startswith(home_dir):
       
  1768             logger.debug('Skipping system (non-environment) directory %s' % path)
       
  1769             continue
       
  1770         for filename in os.listdir(path):
       
  1771             filename = os.path.join(path, filename)
       
  1772             if filename.endswith('.pth'):
       
  1773                 if not os.access(filename, os.W_OK):
       
  1774                     logger.warn('Cannot write .pth file %s, skipping' % filename)
       
  1775                 else:
       
  1776                     fixup_pth_file(filename)
       
  1777             if filename.endswith('.egg-link'):
       
  1778                 if not os.access(filename, os.W_OK):
       
  1779                     logger.warn('Cannot write .egg-link file %s, skipping' % filename)
       
  1780                 else:
       
  1781                     fixup_egg_link(filename)
       
  1782 
       
  1783 def fixup_pth_file(filename):
       
  1784     lines = []
       
  1785     prev_lines = []
       
  1786     f = open(filename)
       
  1787     prev_lines = f.readlines()
       
  1788     f.close()
       
  1789     for line in prev_lines:
       
  1790         line = line.strip()
       
  1791         if (not line or line.startswith('#') or line.startswith('import ')
       
  1792             or os.path.abspath(line) != line):
       
  1793             lines.append(line)
       
  1794         else:
       
  1795             new_value = make_relative_path(filename, line)
       
  1796             if line != new_value:
       
  1797                 logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
       
  1798             lines.append(new_value)
       
  1799     if lines == prev_lines:
       
  1800         logger.info('No changes to .pth file %s' % filename)
       
  1801         return
       
  1802     logger.notify('Making paths in .pth file %s relative' % filename)
       
  1803     f = open(filename, 'w')
       
  1804     f.write('\n'.join(lines) + '\n')
       
  1805     f.close()
       
  1806 
       
  1807 def fixup_egg_link(filename):
       
  1808     f = open(filename)
       
  1809     link = f.readline().strip()
       
  1810     f.close()
       
  1811     if os.path.abspath(link) != link:
       
  1812         logger.debug('Link in %s already relative' % filename)
       
  1813         return
       
  1814     new_link = make_relative_path(filename, link)
       
  1815     logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
       
  1816     f = open(filename, 'w')
       
  1817     f.write(new_link)
       
  1818     f.close()
       
  1819 
       
  1820 def make_relative_path(source, dest, dest_is_directory=True):
       
  1821     """
       
  1822     Make a filename relative, where the filename is dest, and it is
       
  1823     being referred to from the filename source.
       
  1824 
       
  1825         >>> make_relative_path('/usr/share/something/a-file.pth',
       
  1826         ...                    '/usr/share/another-place/src/Directory')
       
  1827         '../another-place/src/Directory'
       
  1828         >>> make_relative_path('/usr/share/something/a-file.pth',
       
  1829         ...                    '/home/user/src/Directory')
       
  1830         '../../../home/user/src/Directory'
       
  1831         >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
       
  1832         './'
       
  1833     """
       
  1834     source = os.path.dirname(source)
       
  1835     if not dest_is_directory:
       
  1836         dest_filename = os.path.basename(dest)
       
  1837         dest = os.path.dirname(dest)
       
  1838     dest = os.path.normpath(os.path.abspath(dest))
       
  1839     source = os.path.normpath(os.path.abspath(source))
       
  1840     dest_parts = dest.strip(os.path.sep).split(os.path.sep)
       
  1841     source_parts = source.strip(os.path.sep).split(os.path.sep)
       
  1842     while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
       
  1843         dest_parts.pop(0)
       
  1844         source_parts.pop(0)
       
  1845     full_parts = ['..']*len(source_parts) + dest_parts
       
  1846     if not dest_is_directory:
       
  1847         full_parts.append(dest_filename)
       
  1848     if not full_parts:
       
  1849         # Special case for the current directory (otherwise it'd be '')
       
  1850         return './'
       
  1851     return os.path.sep.join(full_parts)
       
  1852 
       
  1853 
       
  1854 
       
  1855 ############################################################
       
  1856 ## Bootstrap script creation:
       
  1857 
       
  1858 def create_bootstrap_script(extra_text, python_version=''):
       
  1859     """
       
  1860     Creates a bootstrap script, which is like this script but with
       
  1861     extend_parser, adjust_options, and after_install hooks.
       
  1862 
       
  1863     This returns a string that (written to disk of course) can be used
       
  1864     as a bootstrap script with your own customizations.  The script
       
  1865     will be the standard virtualenv.py script, with your extra text
       
  1866     added (your extra text should be Python code).
       
  1867 
       
  1868     If you include these functions, they will be called:
       
  1869 
       
  1870     ``extend_parser(optparse_parser)``:
       
  1871         You can add or remove options from the parser here.
       
  1872 
       
  1873     ``adjust_options(options, args)``:
       
  1874         You can change options here, or change the args (if you accept
       
  1875         different kinds of arguments, be sure you modify ``args`` so it is
       
  1876         only ``[DEST_DIR]``).
       
  1877 
       
  1878     ``after_install(options, home_dir)``:
       
  1879 
       
  1880         After everything is installed, this function is called.  This
       
  1881         is probably the function you are most likely to use.  An
       
  1882         example would be::
       
  1883 
       
  1884             def after_install(options, home_dir):
       
  1885                 subprocess.call([join(home_dir, 'bin', 'easy_install'),
       
  1886                                  'MyPackage'])
       
  1887                 subprocess.call([join(home_dir, 'bin', 'my-package-script'),
       
  1888                                  'setup', home_dir])
       
  1889 
       
  1890         This example immediately installs a package, and runs a setup
       
  1891         script from that package.
       
  1892 
       
  1893     If you provide something like ``python_version='2.5'`` then the
       
  1894     script will start with ``#!/usr/bin/env python2.5`` instead of
       
  1895     ``#!/usr/bin/env python``.  You can use this when the script must
       
  1896     be run with a particular Python version.
       
  1897     """
       
  1898     filename = __file__
       
  1899     if filename.endswith('.pyc'):
       
  1900         filename = filename[:-1]
       
  1901     f = codecs.open(filename, 'r', encoding='utf-8')
       
  1902     content = f.read()
       
  1903     f.close()
       
  1904     py_exe = 'python%s' % python_version
       
  1905     content = (('#!/usr/bin/env %s\n' % py_exe)
       
  1906                + '## WARNING: This file is generated\n'
       
  1907                + content)
       
  1908     return content.replace('##EXT' 'END##', extra_text)
       
  1909 
       
  1910 ##EXTEND##
       
  1911 
       
  1912 def convert(s):
       
  1913     b = base64.b64decode(s.encode('ascii'))
       
  1914     return zlib.decompress(b).decode('utf-8')
       
  1915 
       
  1916 ##file site.py
       
  1917 SITE_PY = convert("""
       
  1918 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
       
  2057 UM3ckC/Q8aP8VLy+mjYY5MxOtAdgjULwf2RtvCc=
       
  2058 """)
       
  2059 
       
  2060 ##file ez_setup.py
       
  2061 EZ_SETUP_PY = convert("""
       
  2062 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
       
  2128 qL7+C1AkCcw=
       
  2129 """)
       
  2130 
       
  2131 ##file distribute_from_egg.py
       
  2132 DISTRIBUTE_FROM_EGG_PY = convert("""
       
  2133 eJw9j8tqAzEMRfcG/4MgmxQyptkGusonZBmGoGTUGYFfWPKE6dfXTkM3gqt7rh47OKP3NMF3SQFW
       
  2134 LlrRU1zhybpAxoKBlIqcrNnBdRjQP3GTocYfzmNrrCPQPN9iwzpxSQfQhWBi0cL3qtRtYIG/4Mv0
       
  2135 KApY5hooqrOGQ05FQTaxptF9Fnx16Rq0XofjaE1XGXVxHIWK7j8P8EY/rHndLqQ1a0pe3COFgHFy
       
  2136 hLLdWkDbi/DeEpCjNb3u/zccT2Ob8gtnwVyI
       
  2137 """)
       
  2138 
       
  2139 ##file distribute_setup.py
       
  2140 DISTRIBUTE_SETUP_PY = convert("""
       
  2141 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
       
  2228 """)
       
  2229 
       
  2230 ##file activate.sh
       
  2231 ACTIVATE_SH = convert("""
       
  2232 eJytVVFvokAQfudXTLEPtTlLeo9tvMSmJpq02hSvl7u2wRUG2QR2DSxSe7n/frOACEVNLlceRHa+
       
  2233 nfl25pvZDswCnoDPQ4QoTRQsENIEPci4CsBMZBq7CAsuLOYqvmYKTTj3YxnBgiXBudGBjUzBZUJI
       
  2234 BXEqgCvweIyuCjeG4eF2F5x14bcB9KQiQQWrjSddI1/oQIx6SYYeoFjzWIoIhYI1izlbhJjkKO7D
       
  2235 M/QEmKfO9O7WeRo/zr4P7pyHwWxkwitcgwpQ5Ej96OX+PmiFwLeVjFUOrNYKaq1Nud3nR2n8nI2m
       
  2236 k9H0friPTGVsUdptaxGrTEfpNVFEskxpXtUkkCkl1UNF9cgLBkx48J4EXyALuBtAwNYIjF5kcmUU
       
  2237 abMKmMq1ULoiRbgsDEkTSsKSGFCJ6Z8vY/2xYiSacmtyAfCDdCNTVZoVF8vSTQOoEwSnOrngBkws
       
  2238 MYGMBMg8/bMBLSYKS7pYEXP0PqT+ZmBT0Xuy+Pplj5yn4aM9nk72JD8/Wi+Gr98sD9eWSMOwkapD
       
  2239 BbUv91XSvmyVkICt2tmXR4tWmrcUCsjWOpw87YidEC8i0gdTSOFhouJUNxR+4NYBG0MftoCTD9F7
       
  2240 2rTtxG3oPwY1b2HncYwhrlmj6Wq924xtGDWqfdNxap+OYxplEurnMVo9RWks+rH8qKEtx7kZT5zJ
       
  2241 4H7oOFclrN6uFe+d+nW2aIUsSgs/42EIPuOhXq+jEo3S6tX6w2ilNkDnIpHCWdEQhFgwj9pkk7FN
       
  2242 l/y5eQvRSIQ5+TrL05lewxWpt/Lbhes5cJF3mLET1MGhcKCF+40tNWnUulxrpojwDo2sObdje3Bz
       
  2243 N3QeHqf3D7OjEXMVV8LN3ZlvuzoWHqiUcNKHtwNd0IbvPGKYYM31nPKCgkUILw3KL+Y8l7aO1ArS
       
  2244 Ad37nIU0fCj5NE5gQCuC5sOSu+UdI2NeXg/lFkQIlFpdWVaWZRfvqGiirC9o6liJ9FXGYrSY9mI1
       
  2245 D/Ncozgn13vJvsznr7DnkJWXsyMH7e42ljdJ+aqNDF1bFnKWFLdj31xtaJYK6EXFgqmV/ymD/ROG
       
  2246 +n8O9H8f5vsGOWXsL1+1k3g=
       
  2247 """)
       
  2248 
       
  2249 ##file activate.fish
       
  2250 ACTIVATE_FISH = convert("""
       
  2251 eJyVVWFv2jAQ/c6vuBoqQVWC9nVSNVGVCaS2VC2rNLWVZZILWAs2s52wVvvxsyEJDrjbmgpK7PP5
       
  2252 3bt3d22YLbmGlGcIq1wbmCPkGhPYcLMEEsGciwGLDS+YwSjlekngLFVyBe73GXSXxqw/DwbuTS8x
       
  2253 yyKpFr1WG15lDjETQhpQuQBuIOEKY5O9tlppLqxHKSDByjVAPwEy+mXtCq5MzjIUBTCRgEKTKwFG
       
  2254 gpBqxTLYXgN2myspVigMaYF92tZSowGZJf4mFExxNs9Qb614CgZtmH0BpEOn11f0cXI/+za8pnfD
       
  2255 2ZjA1sg9zlV/8QvcMhxbNu0QwgYokn/d+n02nt6Opzcjcnx1vXcIoN74O4ymWQXmHURfJw9jenc/
       
  2256 vbmb0enj6P5+cuVhqlKm3S0u2XRtRbA2QQAhV7VhBF0rsgUX9Ur1rBUXJgVSy8O751k8mzY5OrKH
       
  2257 RW3eaQhYGTr8hrXO59ALhxQ83mCsDLAid3T72CCSdJhaFE+fXgicXAARUiR2WeVO37gH3oYHzFKo
       
  2258 9k7CaPZ1UeNwH1tWuXA4uFKYYcEa8vaKqXl7q1UpygMPhFLvlVKyNzsSM3S2km7UBOl4xweUXk5u
       
  2259 6e3wZmQ9leY1XE/Ili670tr9g/5POBBpGIJXCCF79L1siarl/dbESa8mD8PL61GpzqpzuMS7tqeB
       
  2260 1YkALrRBloBMbR9yLcVx7frQAgUqR7NZIuzkEu110gbNit1enNs82Rx5utq7Z3prU78HFRgulqNC
       
  2261 OTwbqJa9vkJFclQgZSjbKeBgSsUtCtt9D8OwAbIVJuewQdfvQRaoFE9wd1TmCuRG7OgJ1bVXGHc7
       
  2262 z5WDL/WW36v2oi37CyVBak61+yPBA9C1qqGxzKQqZ0oPuocU9hpud0PIp8sDHkXR1HKkNlzjuUWA
       
  2263 a0enFUyzOWZA4yXGP+ZMI3Tdt2OuqU/SO4q64526cPE0A7ZyW2PMbWZiZ5HamIZ2RcCKLXhcDl2b
       
  2264 vXL+eccQoRzem80mekPDEiyiWK4GWqZmwxQOmPM0eIfgp1P9cqrBsewR2p/DPMtt+pfcYM+Ls2uh
       
  2265 hALufTAdmGl8B1H3VPd2af8fQAc4PgqjlIBL9cGQqNpXaAwe3LrtVn8AkZTUxg==
       
  2266 """)
       
  2267 
       
  2268 ##file activate.csh
       
  2269 ACTIVATE_CSH = convert("""
       
  2270 eJx9VG1P2zAQ/u5fcYQKNgTNPtN1WxlIQ4KCUEGaxuQ6yYVYSuzKdhqVX7+zk3bpy5YPUXL3PPfc
       
  2271 ne98DLNCWshliVDV1kGCUFvMoJGugMjq2qQIiVSxSJ1cCofD1BYRnOVGV0CfZ0N2DD91DalQSjsw
       
  2272 tQLpIJMGU1euvPe7QeJlkKzgWixlhnAt4aoUVsLnLBiy5NtbJWQ5THX1ZciYKKWwkOFaE04dUm6D
       
  2273 r/zh7pq/3D7Nnid3/HEy+wFHY/gEJydg0aFaQrBFgz1c5DG1IhTs+UZgsBC2GMFBlaeH+8dZXwcW
       
  2274 VPvCjXdlAvCfQsE7al0+07XjZvrSCUevR5dnkVeKlFYZmUztG4BdzL2u9KyLVabTU0bdfg7a0hgs
       
  2275 cSmUg6UwUiQl2iHrcbcVGNvPCiLOe7+cRwG13z9qRGgx2z6DHjfm/Op2yqeT+xvOLzs0PTKHDz2V
       
  2276 tkckFHoQfQRXoGJAj9el0FyJCmEMhzgMS4sB7KPOE2ExoLcSieYwDvR+cP8cg11gKkVJc2wRcm1g
       
  2277 QhYFlXiTaTfO2ki0fQoiFM4tLuO4aZrhOzqR4dIPcWx17hphMBY+Srwh7RTyN83XOWkcSPh1Pg/k
       
  2278 TXX/jbJTbMtUmcxZ+/bbqOsy82suFQg/BhdSOTRhMNBHlUarCpU7JzBhmkKmRejKOQzayQe6MWoa
       
  2279 n1wqWmuh6LZAaHxcdeqIlVLhIBJdO9/kbl0It2oEXQj+eGjJOuvOIR/YGRqvFhttUB2XTvLXYN2H
       
  2280 37CBdbW2W7j2r2+VsCn0doVWcFG1/4y1VwBjfwAyoZhD
       
  2281 """)
       
  2282 
       
  2283 ##file activate.bat
       
  2284 ACTIVATE_BAT = convert("""
       
  2285 eJx9UdEKgjAUfW6wfxjiIH+hEDKUFHSKLCMI7kNOEkIf9P9pTJ3OLJ/03HPPPed4Es9XS9qqwqgT
       
  2286 PbGKKOdXL4aAFS7A4gvAwgijuiKlqOpGlATS2NeMLE+TjJM9RkQ+SmqAXLrBo1LLIeLdiWlD6jZt
       
  2287 r7VNubWkndkXaxg5GO3UaOOKS6drO3luDDiO5my3iA0YAKGzPRV1ack8cOdhysI0CYzIPzjSiH5X
       
  2288 0QcvC8Lfaj0emsVKYF2rhL5L3fCkVjV76kShi59NHwDniAHzkgDgqBcwOgTMx+gDQQqXCw==
       
  2289 """)
       
  2290 
       
  2291 ##file deactivate.bat
       
  2292 DEACTIVATE_BAT = convert("""
       
  2293 eJxzSE3OyFfIT0vj4ipOLVEI8wwKCXX0iXf1C7Pl4spMU0hJTcvMS01RiPf3cYmHyQYE+fsGhCho
       
  2294 cCkAAUibEkTEVhWLMlUlLk6QGixStlyaeCyJDPHw9/Pw93VFsQguim4ZXAJoIUw5DhX47XUM8UCx
       
  2295 EchHtwsohN1bILUgw61c/Vy4AJYPYm4=
       
  2296 """)
       
  2297 
       
  2298 ##file activate.ps1
       
  2299 ACTIVATE_PS = convert("""
       
  2300 eJylWdmS40Z2fVeE/oHT6rCloNUEAXDThB6wAyQAEjsB29GBjdgXYiWgmC/zgz/Jv+AEWNVd3S2N
       
  2301 xuOKYEUxM+/Jmzfvcm7W//zXf/+wUMOoXtyi1F9kbd0sHH/hFc2iLtrK9b3FrSqyxaVQwr8uhqJd
       
  2302 uHaeg9mqzRdR8/13Pyy8qPLdJh0+LMhi0QCoXxYfFh9WtttEnd34H8p6/f1300KauwrULws39e18
       
  2303 0ZaLNm9rgN/ZVf3h++/e124Vlc0vKsspHy+Yyi5+XbzPhijvCtduoiL/kA1ukWV27n0o7Sb8LIFj
       
  2304 CvWR5GQgUJdp1Pw8TS9+rPy6SDv/+e3d+0+4qw8f3v20+PliV37efEYBAB9FTKC+RHn/Cfxn3rdv
       
  2305 00Fube5O+iyCtHDs9BfPfz3q4sfFv9d91Ljhfy7ei0VO+nVTtdOkv/jpt0l2AX6iG1jXgKnnDuD4
       
  2306 ke2k/i8fzzz5UedkVcP4pwF+Wvz2FJl+3vt598urXf5Y6LNA5WcFOP7r0sW7b9a+W/xcu0Xpv5zk
       
  2307 Kfq3P9Dz9di/fCxS72MXVU1rpx9L4Bxl85Wmn5a+zP76Zuh3pL9ROWr87PN+//GHIl+oOtvn9XSU
       
  2308 qH+p0gQBFnx1uV+JLH5O5zv+PXW+WepXVVHZT0+oQezkIATcIm+ivPV/z5J/+cYj3ir4w0Lx09vC
       
  2309 e5n/y5/Y5LPPfdrqb88ga/PabxZRVfmp39l588m/6u+/e+OpP+dF7n1WZpJ9//Z4v372fDDz9eHB
       
  2310 7Juvs/BLMHzrxL9+9twXpJfhd1/DrpQ5Euu/vlss3wp9HXC/54C/Ld69m6zwdx3tC0d8daSv0V8B
       
  2311 n4b9YYF53sJelJV/ix6LZspw/sJtqyl5LJ5r/23htA1Imfm/gt9R7dqVB1LjhydAX4Gb+zksQF59
       
  2312 9+P7H//U+376afFuvh2/T6P85Xr/5c8C6OXyFY4BGuN+EE0+GeR201b+wkkLN5mmBY5TfMw8ngqL
       
  2313 CztXxCSXKMCYrRIElWkEJlEPYsSOeKBVZCAQTKBhApMwRFQzmCThE0YQu2CdEhgjbgmk9GluHpfR
       
  2314 /hhwJCZhGI5jt5FsAkOrObVyE6g2y1snyhMGFlDY1x+BoHpCMulTj5JYWNAYJmnKpvLxXgmQ8az1
       
  2315 4fUGxxcitMbbhDFcsiAItg04E+OSBIHTUYD1HI4FHH4kMREPknuYRMyhh3AARWMkfhCketqD1CWJ
       
  2316 mTCo/nhUScoQcInB1hpFhIKoIXLo5jLpwFCgsnLCx1QlEMlz/iFEGqzH3vWYcpRcThgWnEKm0QcS
       
  2317 rA8ek2a2IYYeowUanOZOlrbWSJUC4c7y2EMI3uJPMnMF/SSXdk6E495VLhzkWHps0rOhKwqk+xBI
       
  2318 DhJirhdUCTamMfXz2Hy303hM4DFJ8QL21BcPBULR+gcdYxoeiDqOFSqpi5B5PUISfGg46gFZBPo4
       
  2319 jdh8lueaWuVSMTURfbAUnLINr/QYuuYoMQV6l1aWxuZVTjlaLC14UzqZ+ziTGDzJzhiYoPLrt3uI
       
  2320 tXkVR47kAo09lo5BD76CH51cTt1snVpMOttLhY93yxChCQPI4OBecS7++h4p4Bdn4H97bJongtPk
       
  2321 s9gQnXku1vzsjjmX4/o4YUDkXkjHwDg5FXozU0fW4y5kyeYW0uJWlh536BKr0kMGjtzTkng6Ep62
       
  2322 uTWnQtiIqKnEsx7e1hLtzlXs7Upw9TwEnp0t9yzCGgUJIZConx9OHJArLkRYW0dW42G9OeR5Nzwk
       
  2323 yk1mX7du5RGHT7dka7N3AznmSif7y6tuKe2N1Al/1TUPRqH6E2GLVc27h9IptMLkCKQYRqPQJgzV
       
  2324 2m6WLsSipS3v3b1/WmXEYY1meLEVIU/arOGVkyie7ZsH05ZKpjFW4cpY0YkjySpSExNG2TS8nnJx
       
  2325 nrQmWh2WY3cP1eISP9wbaVK35ZXc60yC3VN/j9n7UFoK6zvjSTE2+Pvz6Mx322rnftfP8Y0XKIdv
       
  2326 Qd7AfK0nexBTMqRiErvCMa3Hegpfjdh58glW2oNMsKeAX8x6YJLZs9K8/ozjJkWL+JmECMvhQ54x
       
  2327 9rsTHwcoGrDi6Y4I+H7yY4/rJVPAbYymUH7C2D3uiUS3KQ1nrCAUkE1dJMneDQIJMQQx5SONxoEO
       
  2328 OEn1/Ig1eBBUeEDRuOT2WGGGE4bNypBLFh2PeIg3bEbg44PHiqNDbGIQm50LW6MJU62JHCGBrmc9
       
  2329 2F7WBJrrj1ssnTAK4sxwRgh5LLblhwNAclv3Gd+jC/etCfyfR8TMhcWQz8TBIbG8IIyAQ81w2n/C
       
  2330 mHWAwRzxd3WoBY7BZnsqGOWrOCKwGkMMNfO0Kci/joZgEocLjNnzgcmdehPHJY0FudXgsr+v44TB
       
  2331 I3jnMGnsK5veAhgi9iXGifkHMOC09Rh9cAw9sQ0asl6wKMk8mpzFYaaDSgG4F0wisQDDBRpjCINg
       
  2332 FIxhlhQ31xdSkkk6odXZFpTYOQpOOgw9ugM2cDQ+2MYa7JsEirGBrOuxsQy5nPMRdYjsTJ/j1iNw
       
  2333 FeSt1jY2+dd5yx1/pzZMOQXUIDcXeAzR7QlDRM8AMkUldXOmGmvYXPABjxqkYKO7VAY6JRU7kpXr
       
  2334 +Epu2BU3qFFXClFi27784LrDZsJwbNlDw0JzhZ6M0SMXE4iBHehCpHVkrQhpTFn2dsvsZYkiPEEB
       
  2335 GSEAwdiur9LS1U6P2U9JhGp4hnFpJo4FfkdJHcwV6Q5dV1Q9uNeeu7rV8PAjwdFg9RLtroifOr0k
       
  2336 uOiRTo/obNPhQIf42Fr4mtThWoSjitEdAmFW66UCe8WFjPk1YVNpL9srFbond7jrLg8tqAasIMpy
       
  2337 zkH0SY/6zVAwJrEc14zt14YRXdY+fcJ4qOd2XKB0/Kghw1ovd11t2o+zjt+txndo1ZDZ2T+uMVHT
       
  2338 VSXhedBAHoJIID9xm6wPQI3cXY+HR7vxtrJuCKh6kbXaW5KkVeJsdsjqsYsOwYSh0w5sMbu7LF8J
       
  2339 5T7U6LJdiTx+ca7RKlulGgS5Z1JSU2Llt32cHFipkaurtBrvNX5UtvNZjkufZ/r1/XyLl6yOpytL
       
  2340 Km8Fn+y4wkhlqZP5db0rooqy7xdL4wxzFVTX+6HaxuQJK5E5B1neSSovZ9ALB8091dDbbjVxhWNY
       
  2341 Ve5hn1VnI9OF0wpvaRm7SZuC1IRczwC7GnkhPt3muHV1YxUJfo+uh1sYnJy+vI0ZwuPV2uqWJYUH
       
  2342 bmBsi1zmFSxHrqwA+WIzLrHkwW4r+bad7xbOzJCnKIa3S3YvrzEBK1Dc0emzJW+SqysQfdEDorQG
       
  2343 9ZJlbQzEHQV8naPaF440YXzJk/7vHGK2xwuP+Gc5xITxyiP+WQ4x18oXHjFzCBy9kir1EFTAm0Zq
       
  2344 LYwS8MpiGhtfxiBRDXpxDWxk9g9Q2fzPPAhS6VFDAc/aiNGatUkPtZIStZFQ1qD0IlJa/5ZPAi5J
       
  2345 ySp1ETDomZMnvgiysZSBfMikrSDte/K5lqV6iwC5q7YN9I1dBZXUytDJNqU74MJsUyNNLAPopWK3
       
  2346 tzmLkCiDyl7WQnj9sm7Kd5kzgpoccdNeMw/6zPVB3pUwMgi4C7hj4AMFAf4G27oXH8NNT9zll/sK
       
  2347 S6wVlQwazjxWKWy20ZzXb9ne8ngGalPBWSUSj9xkc1drsXkZ8oOyvYT3e0rnYsGwx85xZB9wKeKg
       
  2348 cJKZnamYwiaMymZvzk6wtDUkxmdUg0mPad0YHtvzpjEfp2iMxvORhnx0kCVLf5Qa43WJsVoyfEyI
       
  2349 pzmf8ruM6xBr7dnBgzyxpqXuUPYaKahOaz1LrxNkS/Q3Ae5AC+xl6NbxAqXXlzghZBZHmOrM6Y6Y
       
  2350 ctAkltwlF7SKEsShjVh7QHuxMU0a08/eiu3x3M+07OijMcKFFltByXrpk8w+JNnZpnp3CfgjV1Ax
       
  2351 gUYCnWwYow42I5wHCcTzLXK0hMZN2DrPM/zCSqe9jRSlJnr70BPE4+zrwbk/xVIDHy2FAQyHoomT
       
  2352 Tt5jiM68nBQut35Y0qLclLiQrutxt/c0OlSqXAC8VrxW97lGoRWzhOnifE2zbF05W4xuyhg7JTUL
       
  2353 aqJ7SWDywhjlal0b+NLTpERBgnPW0+Nw99X2Ws72gOL27iER9jgzj7Uu09JaZ3n+hmCjjvZpjNst
       
  2354 vOWWTbuLrg+/1ltX8WpPauEDEvcunIgTxuMEHweWKCx2KQ9DU/UKdO/3za4Szm2iHYL+ss9AAttm
       
  2355 gZHq2pkUXFbV+FiJCKrpBms18zH75vax5jSo7FNunrVWY3Chvd8KKnHdaTt/6ealwaA1x17yTlft
       
  2356 8VBle3nAE+7R0MScC3MJofNCCkA9PGKBgGMYEwfB2QO5j8zUqa8F/EkWKCzGQJ5EZ05HTly1B01E
       
  2357 z813G5BY++RZ2sxbQS8ZveGPJNabp5kXAeoign6Tlt5+L8i5ZquY9+S+KEUHkmYMRFBxRrHnbl2X
       
  2358 rVemKnG+oB1yd9+zT+4c43jQ0wWmQRR6mTCkY1q3VG05Y120ZzKOMBe6Vy7I5Vz4ygPB3yY4G0FP
       
  2359 8RxiMx985YJPXsgRU58EuHj75gygTzejP+W/zKGe78UQN3yOJ1aMQV9hFH+GAfLRsza84WlPLAI/
       
  2360 9G/5JdcHftEfH+Y3/fHUG7/o8bv98dzzy3e8S+XCvgqB+VUf7sH0yDHpONdbRE8tAg9NWOzcTJ7q
       
  2361 TuAxe/AJ07c1Rs9okJvl1/0G60qvbdDzz5zO0FuPFQIHNp9y9Bd1CufYVx7dB26mAxwa8GMNrN/U
       
  2362 oGbNZ3EQ7inLzHy5tRg9AXJrN8cB59cCUBeCiVO7zKM0jU0MamhnRThkg/NMmBOGb6StNeD9tDfA
       
  2363 7czsAWopDdnGoXUHtA+s/k0vNPkBcxEI13jVd/axp85va3LpwGggXXWw12Gwr/JGAH0b8CPboiZd
       
  2364 QO1l0mk/UHukud4C+w5uRoNzpCmoW6GbgbMyaQNkga2pQINB18lOXOCJzSWPFOhZcwzdgrsQnne7
       
  2365 nvjBi+7cP2BbtBeDOW5uOLGf3z94FasKIguOqJl+8ss/6Kumns4cuWbqq5592TN/RNIbn5Qo6qbi
       
  2366 O4F0P9txxPAwagqPlftztO8cWBzdN/jz3b7GD6JHYP/Zp4ToAMaA74M+EGSft3hEGMuf8EwjnTk/
       
  2367 nz/P7SLipB/ogQ6xNX0fDqNncMCfHqGLCMM0ZzFa+6lPJYQ5p81vW4HkCvidYf6kb+P/oB965g8K
       
  2368 C6uR0rdjX1DNKc5pOSTquI8uQ6KXxYaKBn+30/09tK4kMpJPgUIQkbENEPbuezNPPje2Um83SgyX
       
  2369 GTCJb6MnGVIpgncdQg1qz2bvPfxYD9fewCXDomx9S+HQJuX6W3VAL+v5WZMudRQZk9ZdOk6GIUtC
       
  2370 PqEb/uwSIrtR7/edzqgEdtpEwq7p2J5OQV+RLrmtTvFwFpf03M/VrRyTZ73qVod7v7Jh2Dwe5J25
       
  2371 JqFOU2qEu1sP+CRotklediycKfLjeIZzjJQsvKmiGSNQhxuJpKa+hoWUizaE1PuIRGzJqropwgVB
       
  2372 oo1hr870MZLgnXF5ZIpr6mF0L8aSy2gVnTAuoB4WEd4d5NPVC9TMotYXERKlTcwQ2KiB/C48AEfH
       
  2373 Qbyq4CN8xTFnTvf/ebOc3isnjD95s0QF0nx9s+y+zMmz782xL0SgEmRpA3x1w1Ff9/74xcxKEPdS
       
  2374 IEFTz6GgU0+BK/UZ5Gwbl4gZwycxEw+Kqa5QmMkh4OzgzEVPnDAiAOGBFaBW4wkDmj1G4RyElKgj
       
  2375 NlLCq8zsp085MNh/+R4t1Q8yxoSv8PUpTt7izZwf2BTHZZ3pIZpUIpuLkL1nNL6sYcHqcKm237wp
       
  2376 T2+RCjgXweXd2Zp7ZM8W6dG5bZsqo0nrJBTx8EC0+CQQdzEGnabTnkzofu1pYkWl4E7XSniECdxy
       
  2377 vLYavPMcL9LW5SToJFNnos+uqweOHriUZ1ntIYZUonc7ltEQ6oTRtwOHNwez2sVREskHN+bqG3ua
       
  2378 eaEbJ8XpyO8CeD9QJc8nbLP2C2R3A437ISUNyt5Yd0TbDNcl11/DSsOzdbi/VhCC0KE6v1vqVNkq
       
  2379 45ZnG6fiV2NwzInxCNth3BwL0+8814jE6+1W1EeWtpWbSZJOJNYXmWRXa7vLnAljE692eHjZ4y5u
       
  2380 y1u63De0IzKca7As48Z3XshVF+3XiLNz0JIMh/JOpbiNLlMi672uO0wYzOCZjRxcxj3D+gVenGIE
       
  2381 MvFUGGXuRps2RzMcgWIRolHXpGUP6sMsQt1hspUBnVKUn/WQj2u6j3SXd9Xz0QtEzoM7qTu5y7gR
       
  2382 q9gNNsrlEMLdikBt9bFvBnfbUIh6voTw7eDsyTmPKUvF0bHqWLbHe3VRHyRZnNeSGKsB73q66Vsk
       
  2383 taxWYmwz1tYVFG/vOQhlM0gUkyvIab3nv2caJ1udU1F3pDMty7stubTE4OJqm0i0ECfrJIkLtraC
       
  2384 HwRWKzlqpfhEIqYH09eT9WrOhQyt8YEoyBlnXtAT37WHIQ03TIuEHbnRxZDdLun0iok9PUC79prU
       
  2385 m5beZzfQUelEXnhzb/pIROKx3F7qCttYIFGh5dXNzFzID7u8vKykA8Uejf7XXz//S4nKvW//ofS/
       
  2386 QastYw==
       
  2387 """)
       
  2388 
       
  2389 ##file distutils-init.py
       
  2390 DISTUTILS_INIT = convert("""
       
  2391 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
       
  2413 GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ=
       
  2414 """)
       
  2415 
       
  2416 ##file distutils.cfg
       
  2417 DISTUTILS_CFG = convert("""
       
  2418 eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
       
  2419 xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
       
  2420 9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
       
  2421 """)
       
  2422 
       
  2423 ##file activate_this.py
       
  2424 ACTIVATE_THIS = convert("""
       
  2425 eJyNU01v2zAMvetXEB4K21jmDOstQA4dMGCHbeihlyEIDMWmG62yJEiKE//7kXKdpN2KzYBt8euR
       
  2426 fKSyLPs8wiEo8wh4wqZTGou4V6Hm0wJa1cSiTkJdr8+GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe
       
  2427 5a3p0cRKiAe2NtLADikftnDco0ko/SFEVgEZ8aRC5GLux7i3BpSJ6J1H+i7A2CjiHq9z7JRZuuQq
       
  2428 siwTIvpxJYCeuWaBpwZdhB+yxy/eWz+ZvVSU8C4E9FFZkyxFsvCT/ZzL8gcz9aXVE14Yyp2M+2W0
       
  2429 y7n5mp0qN+avKXvbsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCZN9UzlJr+/e/iab8WfqsmPI6pWeUPd
       
  2430 FrMsd4H/55poeO9n54COhUs+sZNEzNtg/wanpjpuqHJaxs76HtZryI/K3H7KJ/KDIhqcbJ7kI4ar
       
  2431 XL+sMgXnX0D+Te2Iy5xdP8yueSlQB/x/ED2BTAtyE3K4SYUN6AMNfbO63f4lBW3bUJPbTL+mjSxS
       
  2432 PyRfJkZRgj+VbFv+EzHFi5pKwUEepa4JslMnwkowSRCXI+m5XvEOvtuBrxHdhLalG0JofYBok6qj
       
  2433 YdN2dEngUlbC4PG60M1WEN0piu7Nq7on0mgyyUw3iV1etLo6r/81biWdQ9MWHFaePWZYaq+nmp+t
       
  2434 s3az+sj7eA0jfgPfeoN1
       
  2435 """)
       
  2436 
       
  2437 MH_MAGIC = 0xfeedface
       
  2438 MH_CIGAM = 0xcefaedfe
       
  2439 MH_MAGIC_64 = 0xfeedfacf
       
  2440 MH_CIGAM_64 = 0xcffaedfe
       
  2441 FAT_MAGIC = 0xcafebabe
       
  2442 BIG_ENDIAN = '>'
       
  2443 LITTLE_ENDIAN = '<'
       
  2444 LC_LOAD_DYLIB = 0xc
       
  2445 maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint')
       
  2446 
       
  2447 
       
  2448 class fileview(object):
       
  2449     """
       
  2450     A proxy for file-like objects that exposes a given view of a file.
       
  2451     Modified from macholib.
       
  2452     """
       
  2453 
       
  2454     def __init__(self, fileobj, start=0, size=maxint):
       
  2455         if isinstance(fileobj, fileview):
       
  2456             self._fileobj = fileobj._fileobj
       
  2457         else:
       
  2458             self._fileobj = fileobj
       
  2459         self._start = start
       
  2460         self._end = start + size
       
  2461         self._pos = 0
       
  2462 
       
  2463     def __repr__(self):
       
  2464         return '<fileview [%d, %d] %r>' % (
       
  2465             self._start, self._end, self._fileobj)
       
  2466 
       
  2467     def tell(self):
       
  2468         return self._pos
       
  2469 
       
  2470     def _checkwindow(self, seekto, op):
       
  2471         if not (self._start <= seekto <= self._end):
       
  2472             raise IOError("%s to offset %d is outside window [%d, %d]" % (
       
  2473                 op, seekto, self._start, self._end))
       
  2474 
       
  2475     def seek(self, offset, whence=0):
       
  2476         seekto = offset
       
  2477         if whence == os.SEEK_SET:
       
  2478             seekto += self._start
       
  2479         elif whence == os.SEEK_CUR:
       
  2480             seekto += self._start + self._pos
       
  2481         elif whence == os.SEEK_END:
       
  2482             seekto += self._end
       
  2483         else:
       
  2484             raise IOError("Invalid whence argument to seek: %r" % (whence,))
       
  2485         self._checkwindow(seekto, 'seek')
       
  2486         self._fileobj.seek(seekto)
       
  2487         self._pos = seekto - self._start
       
  2488 
       
  2489     def write(self, bytes):
       
  2490         here = self._start + self._pos
       
  2491         self._checkwindow(here, 'write')
       
  2492         self._checkwindow(here + len(bytes), 'write')
       
  2493         self._fileobj.seek(here, os.SEEK_SET)
       
  2494         self._fileobj.write(bytes)
       
  2495         self._pos += len(bytes)
       
  2496 
       
  2497     def read(self, size=maxint):
       
  2498         assert size >= 0
       
  2499         here = self._start + self._pos
       
  2500         self._checkwindow(here, 'read')
       
  2501         size = min(size, self._end - here)
       
  2502         self._fileobj.seek(here, os.SEEK_SET)
       
  2503         bytes = self._fileobj.read(size)
       
  2504         self._pos += len(bytes)
       
  2505         return bytes
       
  2506 
       
  2507 
       
  2508 def read_data(file, endian, num=1):
       
  2509     """
       
  2510     Read a given number of 32-bits unsigned integers from the given file
       
  2511     with the given endianness.
       
  2512     """
       
  2513     res = struct.unpack(endian + 'L' * num, file.read(num * 4))
       
  2514     if len(res) == 1:
       
  2515         return res[0]
       
  2516     return res
       
  2517 
       
  2518 
       
  2519 def mach_o_change(path, what, value):
       
  2520     """
       
  2521     Replace a given name (what) in any LC_LOAD_DYLIB command found in
       
  2522     the given binary with a new name (value), provided it's shorter.
       
  2523     """
       
  2524 
       
  2525     def do_macho(file, bits, endian):
       
  2526         # Read Mach-O header (the magic number is assumed read by the caller)
       
  2527         cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6)
       
  2528         # 64-bits header has one more field.
       
  2529         if bits == 64:
       
  2530             read_data(file, endian)
       
  2531         # The header is followed by ncmds commands
       
  2532         for n in range(ncmds):
       
  2533             where = file.tell()
       
  2534             # Read command header
       
  2535             cmd, cmdsize = read_data(file, endian, 2)
       
  2536             if cmd == LC_LOAD_DYLIB:
       
  2537                 # The first data field in LC_LOAD_DYLIB commands is the
       
  2538                 # offset of the name, starting from the beginning of the
       
  2539                 # command.
       
  2540                 name_offset = read_data(file, endian)
       
  2541                 file.seek(where + name_offset, os.SEEK_SET)
       
  2542                 # Read the NUL terminated string
       
  2543                 load = file.read(cmdsize - name_offset).decode()
       
  2544                 load = load[:load.index('\0')]
       
  2545                 # If the string is what is being replaced, overwrite it.
       
  2546                 if load == what:
       
  2547                     file.seek(where + name_offset, os.SEEK_SET)
       
  2548                     file.write(value.encode() + '\0'.encode())
       
  2549             # Seek to the next command
       
  2550             file.seek(where + cmdsize, os.SEEK_SET)
       
  2551 
       
  2552     def do_file(file, offset=0, size=maxint):
       
  2553         file = fileview(file, offset, size)
       
  2554         # Read magic number
       
  2555         magic = read_data(file, BIG_ENDIAN)
       
  2556         if magic == FAT_MAGIC:
       
  2557             # Fat binaries contain nfat_arch Mach-O binaries
       
  2558             nfat_arch = read_data(file, BIG_ENDIAN)
       
  2559             for n in range(nfat_arch):
       
  2560                 # Read arch header
       
  2561                 cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5)
       
  2562                 do_file(file, offset, size)
       
  2563         elif magic == MH_MAGIC:
       
  2564             do_macho(file, 32, BIG_ENDIAN)
       
  2565         elif magic == MH_CIGAM:
       
  2566             do_macho(file, 32, LITTLE_ENDIAN)
       
  2567         elif magic == MH_MAGIC_64:
       
  2568             do_macho(file, 64, BIG_ENDIAN)
       
  2569         elif magic == MH_CIGAM_64:
       
  2570             do_macho(file, 64, LITTLE_ENDIAN)
       
  2571 
       
  2572     assert(len(what) >= len(value))
       
  2573     do_file(open(path, 'r+b'))
       
  2574 
       
  2575 
       
  2576 if __name__ == '__main__':
       
  2577     main()
       
  2578 
       
  2579 ## TODO:
       
  2580 ## Copy python.exe.manifest
       
  2581 ## Monkeypatch distutils.sysconfig