virtualenv/web/virtualenv.py
changeset 0 87104b7cb3d6
child 1 5778de052a1b
equal deleted inserted replaced
-1:000000000000 0:87104b7cb3d6
       
     1 #!/usr/bin/env python
       
     2 """Create a "virtual" Python installation
       
     3 """
       
     4 
       
     5 # If you change the version here, change it in setup.py
       
     6 # and docs/conf.py as well.
       
     7 __version__ = "1.8.2"  # 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         # The whole list of 3.3 modules is reproduced below - the current
       
   100         # uncommented ones are required for 3.3 as of now, but more may be
       
   101         # added as 3.3 development continues.
       
   102         REQUIRED_MODULES.extend([
       
   103             #"aifc",
       
   104             #"antigravity",
       
   105             #"argparse",
       
   106             #"ast",
       
   107             #"asynchat",
       
   108             #"asyncore",
       
   109             "base64",
       
   110             #"bdb",
       
   111             #"binhex",
       
   112             #"bisect",
       
   113             #"calendar",
       
   114             #"cgi",
       
   115             #"cgitb",
       
   116             #"chunk",
       
   117             #"cmd",
       
   118             #"codeop",
       
   119             #"code",
       
   120             #"colorsys",
       
   121             #"_compat_pickle",
       
   122             #"compileall",
       
   123             #"concurrent",
       
   124             #"configparser",
       
   125             #"contextlib",
       
   126             #"cProfile",
       
   127             #"crypt",
       
   128             #"csv",
       
   129             #"ctypes",
       
   130             #"curses",
       
   131             #"datetime",
       
   132             #"dbm",
       
   133             #"decimal",
       
   134             #"difflib",
       
   135             #"dis",
       
   136             #"doctest",
       
   137             #"dummy_threading",
       
   138             "_dummy_thread",
       
   139             #"email",
       
   140             #"filecmp",
       
   141             #"fileinput",
       
   142             #"formatter",
       
   143             #"fractions",
       
   144             #"ftplib",
       
   145             #"functools",
       
   146             #"getopt",
       
   147             #"getpass",
       
   148             #"gettext",
       
   149             #"glob",
       
   150             #"gzip",
       
   151             "hashlib",
       
   152             #"heapq",
       
   153             "hmac",
       
   154             #"html",
       
   155             #"http",
       
   156             #"idlelib",
       
   157             #"imaplib",
       
   158             #"imghdr",
       
   159             #"importlib",
       
   160             #"inspect",
       
   161             #"json",
       
   162             #"lib2to3",
       
   163             #"logging",
       
   164             #"macpath",
       
   165             #"macurl2path",
       
   166             #"mailbox",
       
   167             #"mailcap",
       
   168             #"_markupbase",
       
   169             #"mimetypes",
       
   170             #"modulefinder",
       
   171             #"multiprocessing",
       
   172             #"netrc",
       
   173             #"nntplib",
       
   174             #"nturl2path",
       
   175             #"numbers",
       
   176             #"opcode",
       
   177             #"optparse",
       
   178             #"os2emxpath",
       
   179             #"pdb",
       
   180             #"pickle",
       
   181             #"pickletools",
       
   182             #"pipes",
       
   183             #"pkgutil",
       
   184             #"platform",
       
   185             #"plat-linux2",
       
   186             #"plistlib",
       
   187             #"poplib",
       
   188             #"pprint",
       
   189             #"profile",
       
   190             #"pstats",
       
   191             #"pty",
       
   192             #"pyclbr",
       
   193             #"py_compile",
       
   194             #"pydoc_data",
       
   195             #"pydoc",
       
   196             #"_pyio",
       
   197             #"queue",
       
   198             #"quopri",
       
   199             #"reprlib",
       
   200             "rlcompleter",
       
   201             #"runpy",
       
   202             #"sched",
       
   203             #"shelve",
       
   204             #"shlex",
       
   205             #"smtpd",
       
   206             #"smtplib",
       
   207             #"sndhdr",
       
   208             #"socket",
       
   209             #"socketserver",
       
   210             #"sqlite3",
       
   211             #"ssl",
       
   212             #"stringprep",
       
   213             #"string",
       
   214             #"_strptime",
       
   215             #"subprocess",
       
   216             #"sunau",
       
   217             #"symbol",
       
   218             #"symtable",
       
   219             #"sysconfig",
       
   220             #"tabnanny",
       
   221             #"telnetlib",
       
   222             #"test",
       
   223             #"textwrap",
       
   224             #"this",
       
   225             #"_threading_local",
       
   226             #"threading",
       
   227             #"timeit",
       
   228             #"tkinter",
       
   229             #"tokenize",
       
   230             #"token",
       
   231             #"traceback",
       
   232             #"trace",
       
   233             #"tty",
       
   234             #"turtledemo",
       
   235             #"turtle",
       
   236             #"unittest",
       
   237             #"urllib",
       
   238             #"uuid",
       
   239             #"uu",
       
   240             #"wave",
       
   241             #"weakref",
       
   242             #"webbrowser",
       
   243             #"wsgiref",
       
   244             #"xdrlib",
       
   245             #"xml",
       
   246             #"xmlrpc",
       
   247             #"zipfile",
       
   248         ])
       
   249 
       
   250 if is_pypy:
       
   251     # these are needed to correctly display the exceptions that may happen
       
   252     # during the bootstrap
       
   253     REQUIRED_MODULES.extend(['traceback', 'linecache'])
       
   254 
       
   255 class Logger(object):
       
   256 
       
   257     """
       
   258     Logging object for use in command-line script.  Allows ranges of
       
   259     levels, to avoid some redundancy of displayed information.
       
   260     """
       
   261 
       
   262     DEBUG = logging.DEBUG
       
   263     INFO = logging.INFO
       
   264     NOTIFY = (logging.INFO+logging.WARN)/2
       
   265     WARN = WARNING = logging.WARN
       
   266     ERROR = logging.ERROR
       
   267     FATAL = logging.FATAL
       
   268 
       
   269     LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
       
   270 
       
   271     def __init__(self, consumers):
       
   272         self.consumers = consumers
       
   273         self.indent = 0
       
   274         self.in_progress = None
       
   275         self.in_progress_hanging = False
       
   276 
       
   277     def debug(self, msg, *args, **kw):
       
   278         self.log(self.DEBUG, msg, *args, **kw)
       
   279     def info(self, msg, *args, **kw):
       
   280         self.log(self.INFO, msg, *args, **kw)
       
   281     def notify(self, msg, *args, **kw):
       
   282         self.log(self.NOTIFY, msg, *args, **kw)
       
   283     def warn(self, msg, *args, **kw):
       
   284         self.log(self.WARN, msg, *args, **kw)
       
   285     def error(self, msg, *args, **kw):
       
   286         self.log(self.ERROR, msg, *args, **kw)
       
   287     def fatal(self, msg, *args, **kw):
       
   288         self.log(self.FATAL, msg, *args, **kw)
       
   289     def log(self, level, msg, *args, **kw):
       
   290         if args:
       
   291             if kw:
       
   292                 raise TypeError(
       
   293                     "You may give positional or keyword arguments, not both")
       
   294         args = args or kw
       
   295         rendered = None
       
   296         for consumer_level, consumer in self.consumers:
       
   297             if self.level_matches(level, consumer_level):
       
   298                 if (self.in_progress_hanging
       
   299                     and consumer in (sys.stdout, sys.stderr)):
       
   300                     self.in_progress_hanging = False
       
   301                     sys.stdout.write('\n')
       
   302                     sys.stdout.flush()
       
   303                 if rendered is None:
       
   304                     if args:
       
   305                         rendered = msg % args
       
   306                     else:
       
   307                         rendered = msg
       
   308                     rendered = ' '*self.indent + rendered
       
   309                 if hasattr(consumer, 'write'):
       
   310                     consumer.write(rendered+'\n')
       
   311                 else:
       
   312                     consumer(rendered)
       
   313 
       
   314     def start_progress(self, msg):
       
   315         assert not self.in_progress, (
       
   316             "Tried to start_progress(%r) while in_progress %r"
       
   317             % (msg, self.in_progress))
       
   318         if self.level_matches(self.NOTIFY, self._stdout_level()):
       
   319             sys.stdout.write(msg)
       
   320             sys.stdout.flush()
       
   321             self.in_progress_hanging = True
       
   322         else:
       
   323             self.in_progress_hanging = False
       
   324         self.in_progress = msg
       
   325 
       
   326     def end_progress(self, msg='done.'):
       
   327         assert self.in_progress, (
       
   328             "Tried to end_progress without start_progress")
       
   329         if self.stdout_level_matches(self.NOTIFY):
       
   330             if not self.in_progress_hanging:
       
   331                 # Some message has been printed out since start_progress
       
   332                 sys.stdout.write('...' + self.in_progress + msg + '\n')
       
   333                 sys.stdout.flush()
       
   334             else:
       
   335                 sys.stdout.write(msg + '\n')
       
   336                 sys.stdout.flush()
       
   337         self.in_progress = None
       
   338         self.in_progress_hanging = False
       
   339 
       
   340     def show_progress(self):
       
   341         """If we are in a progress scope, and no log messages have been
       
   342         shown, write out another '.'"""
       
   343         if self.in_progress_hanging:
       
   344             sys.stdout.write('.')
       
   345             sys.stdout.flush()
       
   346 
       
   347     def stdout_level_matches(self, level):
       
   348         """Returns true if a message at this level will go to stdout"""
       
   349         return self.level_matches(level, self._stdout_level())
       
   350 
       
   351     def _stdout_level(self):
       
   352         """Returns the level that stdout runs at"""
       
   353         for level, consumer in self.consumers:
       
   354             if consumer is sys.stdout:
       
   355                 return level
       
   356         return self.FATAL
       
   357 
       
   358     def level_matches(self, level, consumer_level):
       
   359         """
       
   360         >>> l = Logger([])
       
   361         >>> l.level_matches(3, 4)
       
   362         False
       
   363         >>> l.level_matches(3, 2)
       
   364         True
       
   365         >>> l.level_matches(slice(None, 3), 3)
       
   366         False
       
   367         >>> l.level_matches(slice(None, 3), 2)
       
   368         True
       
   369         >>> l.level_matches(slice(1, 3), 1)
       
   370         True
       
   371         >>> l.level_matches(slice(2, 3), 1)
       
   372         False
       
   373         """
       
   374         if isinstance(level, slice):
       
   375             start, stop = level.start, level.stop
       
   376             if start is not None and start > consumer_level:
       
   377                 return False
       
   378             if stop is not None and stop <= consumer_level:
       
   379                 return False
       
   380             return True
       
   381         else:
       
   382             return level >= consumer_level
       
   383 
       
   384     #@classmethod
       
   385     def level_for_integer(cls, level):
       
   386         levels = cls.LEVELS
       
   387         if level < 0:
       
   388             return levels[0]
       
   389         if level >= len(levels):
       
   390             return levels[-1]
       
   391         return levels[level]
       
   392 
       
   393     level_for_integer = classmethod(level_for_integer)
       
   394 
       
   395 # create a silent logger just to prevent this from being undefined
       
   396 # will be overridden with requested verbosity main() is called.
       
   397 logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
       
   398 
       
   399 def mkdir(path):
       
   400     if not os.path.exists(path):
       
   401         logger.info('Creating %s', path)
       
   402         os.makedirs(path)
       
   403     else:
       
   404         logger.info('Directory %s already exists', path)
       
   405 
       
   406 def copyfileordir(src, dest):
       
   407     if os.path.isdir(src):
       
   408         shutil.copytree(src, dest, True)
       
   409     else:
       
   410         shutil.copy2(src, dest)
       
   411 
       
   412 def copyfile(src, dest, symlink=True):
       
   413     if not os.path.exists(src):
       
   414         # Some bad symlink in the src
       
   415         logger.warn('Cannot find file %s (bad symlink)', src)
       
   416         return
       
   417     if os.path.exists(dest):
       
   418         logger.debug('File %s already exists', dest)
       
   419         return
       
   420     if not os.path.exists(os.path.dirname(dest)):
       
   421         logger.info('Creating parent directories for %s' % os.path.dirname(dest))
       
   422         os.makedirs(os.path.dirname(dest))
       
   423     if not os.path.islink(src):
       
   424         srcpath = os.path.abspath(src)
       
   425     else:
       
   426         srcpath = os.readlink(src)
       
   427     if symlink and hasattr(os, 'symlink') and not is_win:
       
   428         logger.info('Symlinking %s', dest)
       
   429         try:
       
   430             os.symlink(srcpath, dest)
       
   431         except (OSError, NotImplementedError):
       
   432             logger.info('Symlinking failed, copying to %s', dest)
       
   433             copyfileordir(src, dest)
       
   434     else:
       
   435         logger.info('Copying to %s', dest)
       
   436         copyfileordir(src, dest)
       
   437 
       
   438 def writefile(dest, content, overwrite=True):
       
   439     if not os.path.exists(dest):
       
   440         logger.info('Writing %s', dest)
       
   441         f = open(dest, 'wb')
       
   442         f.write(content.encode('utf-8'))
       
   443         f.close()
       
   444         return
       
   445     else:
       
   446         f = open(dest, 'rb')
       
   447         c = f.read()
       
   448         f.close()
       
   449         if c != content.encode("utf-8"):
       
   450             if not overwrite:
       
   451                 logger.notify('File %s exists with different content; not overwriting', dest)
       
   452                 return
       
   453             logger.notify('Overwriting %s with new content', dest)
       
   454             f = open(dest, 'wb')
       
   455             f.write(content.encode('utf-8'))
       
   456             f.close()
       
   457         else:
       
   458             logger.info('Content %s already in place', dest)
       
   459 
       
   460 def rmtree(dir):
       
   461     if os.path.exists(dir):
       
   462         logger.notify('Deleting tree %s', dir)
       
   463         shutil.rmtree(dir)
       
   464     else:
       
   465         logger.info('Do not need to delete %s; already gone', dir)
       
   466 
       
   467 def make_exe(fn):
       
   468     if hasattr(os, 'chmod'):
       
   469         oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777
       
   470         newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777
       
   471         os.chmod(fn, newmode)
       
   472         logger.info('Changed mode of %s to %s', fn, oct(newmode))
       
   473 
       
   474 def _find_file(filename, dirs):
       
   475     for dir in reversed(dirs):
       
   476         files = glob.glob(os.path.join(dir, filename))
       
   477         if files and os.path.exists(files[0]):
       
   478             return files[0]
       
   479     return filename
       
   480 
       
   481 def _install_req(py_executable, unzip=False, distribute=False,
       
   482                  search_dirs=None, never_download=False):
       
   483 
       
   484     if search_dirs is None:
       
   485         search_dirs = file_search_dirs()
       
   486 
       
   487     if not distribute:
       
   488         setup_fn = 'setuptools-*-py%s.egg' % sys.version[:3]
       
   489         project_name = 'setuptools'
       
   490         bootstrap_script = EZ_SETUP_PY
       
   491         source = None
       
   492     else:
       
   493         setup_fn = None
       
   494         source = 'distribute-*.tar.gz'
       
   495         project_name = 'distribute'
       
   496         bootstrap_script = DISTRIBUTE_SETUP_PY
       
   497 
       
   498     if setup_fn is not None:
       
   499         setup_fn = _find_file(setup_fn, search_dirs)
       
   500 
       
   501     if source is not None:
       
   502         source = _find_file(source, search_dirs)
       
   503 
       
   504     if is_jython and os._name == 'nt':
       
   505         # Jython's .bat sys.executable can't handle a command line
       
   506         # argument with newlines
       
   507         fd, ez_setup = tempfile.mkstemp('.py')
       
   508         os.write(fd, bootstrap_script)
       
   509         os.close(fd)
       
   510         cmd = [py_executable, ez_setup]
       
   511     else:
       
   512         cmd = [py_executable, '-c', bootstrap_script]
       
   513     if unzip:
       
   514         cmd.append('--always-unzip')
       
   515     env = {}
       
   516     remove_from_env = ['__PYVENV_LAUNCHER__']
       
   517     if logger.stdout_level_matches(logger.DEBUG):
       
   518         cmd.append('-v')
       
   519 
       
   520     old_chdir = os.getcwd()
       
   521     if setup_fn is not None and os.path.exists(setup_fn):
       
   522         logger.info('Using existing %s egg: %s' % (project_name, setup_fn))
       
   523         cmd.append(setup_fn)
       
   524         if os.environ.get('PYTHONPATH'):
       
   525             env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH']
       
   526         else:
       
   527             env['PYTHONPATH'] = setup_fn
       
   528     else:
       
   529         # the source is found, let's chdir
       
   530         if source is not None and os.path.exists(source):
       
   531             logger.info('Using existing %s egg: %s' % (project_name, source))
       
   532             os.chdir(os.path.dirname(source))
       
   533             # in this case, we want to be sure that PYTHONPATH is unset (not
       
   534             # just empty, really unset), else CPython tries to import the
       
   535             # site.py that it's in virtualenv_support
       
   536             remove_from_env.append('PYTHONPATH')
       
   537         else:
       
   538             if never_download:
       
   539                 logger.fatal("Can't find any local distributions of %s to install "
       
   540                              "and --never-download is set.  Either re-run virtualenv "
       
   541                              "without the --never-download option, or place a %s "
       
   542                              "distribution (%s) in one of these "
       
   543                              "locations: %r" % (project_name, project_name,
       
   544                                                 setup_fn or source,
       
   545                                                 search_dirs))
       
   546                 sys.exit(1)
       
   547 
       
   548             logger.info('No %s egg found; downloading' % project_name)
       
   549         cmd.extend(['--always-copy', '-U', project_name])
       
   550     logger.start_progress('Installing %s...' % project_name)
       
   551     logger.indent += 2
       
   552     cwd = None
       
   553     if project_name == 'distribute':
       
   554         env['DONT_PATCH_SETUPTOOLS'] = 'true'
       
   555 
       
   556     def _filter_ez_setup(line):
       
   557         return filter_ez_setup(line, project_name)
       
   558 
       
   559     if not os.access(os.getcwd(), os.W_OK):
       
   560         cwd = tempfile.mkdtemp()
       
   561         if source is not None and os.path.exists(source):
       
   562             # the current working dir is hostile, let's copy the
       
   563             # tarball to a temp dir
       
   564             target = os.path.join(cwd, os.path.split(source)[-1])
       
   565             shutil.copy(source, target)
       
   566     try:
       
   567         call_subprocess(cmd, show_stdout=False,
       
   568                         filter_stdout=_filter_ez_setup,
       
   569                         extra_env=env,
       
   570                         remove_from_env=remove_from_env,
       
   571                         cwd=cwd)
       
   572     finally:
       
   573         logger.indent -= 2
       
   574         logger.end_progress()
       
   575         if cwd is not None:
       
   576             shutil.rmtree(cwd)
       
   577         if os.getcwd() != old_chdir:
       
   578             os.chdir(old_chdir)
       
   579         if is_jython and os._name == 'nt':
       
   580             os.remove(ez_setup)
       
   581 
       
   582 def file_search_dirs():
       
   583     here = os.path.dirname(os.path.abspath(__file__))
       
   584     dirs = ['.', here,
       
   585             join(here, 'virtualenv_support')]
       
   586     if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
       
   587         # Probably some boot script; just in case virtualenv is installed...
       
   588         try:
       
   589             import virtualenv
       
   590         except ImportError:
       
   591             pass
       
   592         else:
       
   593             dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
       
   594     return [d for d in dirs if os.path.isdir(d)]
       
   595 
       
   596 def install_setuptools(py_executable, unzip=False,
       
   597                        search_dirs=None, never_download=False):
       
   598     _install_req(py_executable, unzip,
       
   599                  search_dirs=search_dirs, never_download=never_download)
       
   600 
       
   601 def install_distribute(py_executable, unzip=False,
       
   602                        search_dirs=None, never_download=False):
       
   603     _install_req(py_executable, unzip, distribute=True,
       
   604                  search_dirs=search_dirs, never_download=never_download)
       
   605 
       
   606 _pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I)
       
   607 def install_pip(py_executable, search_dirs=None, never_download=False):
       
   608     if search_dirs is None:
       
   609         search_dirs = file_search_dirs()
       
   610 
       
   611     filenames = []
       
   612     for dir in search_dirs:
       
   613         filenames.extend([join(dir, fn) for fn in os.listdir(dir)
       
   614                           if _pip_re.search(fn)])
       
   615     filenames = [(os.path.basename(filename).lower(), i, filename) for i, filename in enumerate(filenames)]
       
   616     filenames.sort()
       
   617     filenames = [filename for basename, i, filename in filenames]
       
   618     if not filenames:
       
   619         filename = 'pip'
       
   620     else:
       
   621         filename = filenames[-1]
       
   622     easy_install_script = 'easy_install'
       
   623     if is_win:
       
   624         easy_install_script = 'easy_install-script.py'
       
   625     # There's two subtle issues here when invoking easy_install.
       
   626     # 1. On unix-like systems the easy_install script can *only* be executed
       
   627     #    directly if its full filesystem path is no longer than 78 characters.
       
   628     # 2. A work around to [1] is to use the `python path/to/easy_install foo`
       
   629     #    pattern, but that breaks if the path contains non-ASCII characters, as
       
   630     #    you can't put the file encoding declaration before the shebang line.
       
   631     # The solution is to use Python's -x flag to skip the first line of the
       
   632     # script (and any ASCII decoding errors that may have occurred in that line)
       
   633     cmd = [py_executable, '-x', join(os.path.dirname(py_executable), easy_install_script), filename]
       
   634     # jython and pypy don't yet support -x
       
   635     if is_jython or is_pypy:
       
   636         cmd.remove('-x')
       
   637     if filename == 'pip':
       
   638         if never_download:
       
   639             logger.fatal("Can't find any local distributions of pip to install "
       
   640                          "and --never-download is set.  Either re-run virtualenv "
       
   641                          "without the --never-download option, or place a pip "
       
   642                          "source distribution (zip/tar.gz/tar.bz2) in one of these "
       
   643                          "locations: %r" % search_dirs)
       
   644             sys.exit(1)
       
   645         logger.info('Installing pip from network...')
       
   646     else:
       
   647         logger.info('Installing existing %s distribution: %s' % (
       
   648                 os.path.basename(filename), filename))
       
   649     logger.start_progress('Installing pip...')
       
   650     logger.indent += 2
       
   651     def _filter_setup(line):
       
   652         return filter_ez_setup(line, 'pip')
       
   653     try:
       
   654         call_subprocess(cmd, show_stdout=False,
       
   655                         filter_stdout=_filter_setup)
       
   656     finally:
       
   657         logger.indent -= 2
       
   658         logger.end_progress()
       
   659 
       
   660 def filter_ez_setup(line, project_name='setuptools'):
       
   661     if not line.strip():
       
   662         return Logger.DEBUG
       
   663     if project_name == 'distribute':
       
   664         for prefix in ('Extracting', 'Now working', 'Installing', 'Before',
       
   665                        'Scanning', 'Setuptools', 'Egg', 'Already',
       
   666                        'running', 'writing', 'reading', 'installing',
       
   667                        'creating', 'copying', 'byte-compiling', 'removing',
       
   668                        'Processing'):
       
   669             if line.startswith(prefix):
       
   670                 return Logger.DEBUG
       
   671         return Logger.DEBUG
       
   672     for prefix in ['Reading ', 'Best match', 'Processing setuptools',
       
   673                    'Copying setuptools', 'Adding setuptools',
       
   674                    'Installing ', 'Installed ']:
       
   675         if line.startswith(prefix):
       
   676             return Logger.DEBUG
       
   677     return Logger.INFO
       
   678 
       
   679 
       
   680 class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
       
   681     """
       
   682     Custom help formatter for use in ConfigOptionParser that updates
       
   683     the defaults before expanding them, allowing them to show up correctly
       
   684     in the help listing
       
   685     """
       
   686     def expand_default(self, option):
       
   687         if self.parser is not None:
       
   688             self.parser.update_defaults(self.parser.defaults)
       
   689         return optparse.IndentedHelpFormatter.expand_default(self, option)
       
   690 
       
   691 
       
   692 class ConfigOptionParser(optparse.OptionParser):
       
   693     """
       
   694     Custom option parser which updates its defaults by by checking the
       
   695     configuration files and environmental variables
       
   696     """
       
   697     def __init__(self, *args, **kwargs):
       
   698         self.config = ConfigParser.RawConfigParser()
       
   699         self.files = self.get_config_files()
       
   700         self.config.read(self.files)
       
   701         optparse.OptionParser.__init__(self, *args, **kwargs)
       
   702 
       
   703     def get_config_files(self):
       
   704         config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False)
       
   705         if config_file and os.path.exists(config_file):
       
   706             return [config_file]
       
   707         return [default_config_file]
       
   708 
       
   709     def update_defaults(self, defaults):
       
   710         """
       
   711         Updates the given defaults with values from the config files and
       
   712         the environ. Does a little special handling for certain types of
       
   713         options (lists).
       
   714         """
       
   715         # Then go and look for the other sources of configuration:
       
   716         config = {}
       
   717         # 1. config files
       
   718         config.update(dict(self.get_config_section('virtualenv')))
       
   719         # 2. environmental variables
       
   720         config.update(dict(self.get_environ_vars()))
       
   721         # Then set the options with those values
       
   722         for key, val in config.items():
       
   723             key = key.replace('_', '-')
       
   724             if not key.startswith('--'):
       
   725                 key = '--%s' % key  # only prefer long opts
       
   726             option = self.get_option(key)
       
   727             if option is not None:
       
   728                 # ignore empty values
       
   729                 if not val:
       
   730                     continue
       
   731                 # handle multiline configs
       
   732                 if option.action == 'append':
       
   733                     val = val.split()
       
   734                 else:
       
   735                     option.nargs = 1
       
   736                 if option.action == 'store_false':
       
   737                     val = not strtobool(val)
       
   738                 elif option.action in ('store_true', 'count'):
       
   739                     val = strtobool(val)
       
   740                 try:
       
   741                     val = option.convert_value(key, val)
       
   742                 except optparse.OptionValueError:
       
   743                     e = sys.exc_info()[1]
       
   744                     print("An error occured during configuration: %s" % e)
       
   745                     sys.exit(3)
       
   746                 defaults[option.dest] = val
       
   747         return defaults
       
   748 
       
   749     def get_config_section(self, name):
       
   750         """
       
   751         Get a section of a configuration
       
   752         """
       
   753         if self.config.has_section(name):
       
   754             return self.config.items(name)
       
   755         return []
       
   756 
       
   757     def get_environ_vars(self, prefix='VIRTUALENV_'):
       
   758         """
       
   759         Returns a generator with all environmental vars with prefix VIRTUALENV
       
   760         """
       
   761         for key, val in os.environ.items():
       
   762             if key.startswith(prefix):
       
   763                 yield (key.replace(prefix, '').lower(), val)
       
   764 
       
   765     def get_default_values(self):
       
   766         """
       
   767         Overridding to make updating the defaults after instantiation of
       
   768         the option parser possible, update_defaults() does the dirty work.
       
   769         """
       
   770         if not self.process_default_values:
       
   771             # Old, pre-Optik 1.5 behaviour.
       
   772             return optparse.Values(self.defaults)
       
   773 
       
   774         defaults = self.update_defaults(self.defaults.copy())  # ours
       
   775         for option in self._get_all_options():
       
   776             default = defaults.get(option.dest)
       
   777             if isinstance(default, basestring):
       
   778                 opt_str = option.get_opt_string()
       
   779                 defaults[option.dest] = option.check_value(opt_str, default)
       
   780         return optparse.Values(defaults)
       
   781 
       
   782 
       
   783 def main():
       
   784     parser = ConfigOptionParser(
       
   785         version=virtualenv_version,
       
   786         usage="%prog [OPTIONS] DEST_DIR",
       
   787         formatter=UpdatingDefaultsHelpFormatter())
       
   788 
       
   789     parser.add_option(
       
   790         '-v', '--verbose',
       
   791         action='count',
       
   792         dest='verbose',
       
   793         default=0,
       
   794         help="Increase verbosity")
       
   795 
       
   796     parser.add_option(
       
   797         '-q', '--quiet',
       
   798         action='count',
       
   799         dest='quiet',
       
   800         default=0,
       
   801         help='Decrease verbosity')
       
   802 
       
   803     parser.add_option(
       
   804         '-p', '--python',
       
   805         dest='python',
       
   806         metavar='PYTHON_EXE',
       
   807         help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
       
   808         'interpreter to create the new environment.  The default is the interpreter that '
       
   809         'virtualenv was installed with (%s)' % sys.executable)
       
   810 
       
   811     parser.add_option(
       
   812         '--clear',
       
   813         dest='clear',
       
   814         action='store_true',
       
   815         help="Clear out the non-root install and start from scratch")
       
   816 
       
   817     parser.set_defaults(system_site_packages=False)
       
   818     parser.add_option(
       
   819         '--no-site-packages',
       
   820         dest='system_site_packages',
       
   821         action='store_false',
       
   822         help="Don't give access to the global site-packages dir to the "
       
   823              "virtual environment (default)")
       
   824 
       
   825     parser.add_option(
       
   826         '--system-site-packages',
       
   827         dest='system_site_packages',
       
   828         action='store_true',
       
   829         help="Give access to the global site-packages dir to the "
       
   830              "virtual environment")
       
   831 
       
   832     parser.add_option(
       
   833         '--unzip-setuptools',
       
   834         dest='unzip_setuptools',
       
   835         action='store_true',
       
   836         help="Unzip Setuptools or Distribute when installing it")
       
   837 
       
   838     parser.add_option(
       
   839         '--relocatable',
       
   840         dest='relocatable',
       
   841         action='store_true',
       
   842         help='Make an EXISTING virtualenv environment relocatable.  '
       
   843         'This fixes up scripts and makes all .pth files relative')
       
   844 
       
   845     parser.add_option(
       
   846         '--distribute', '--use-distribute',  # the second option is for legacy reasons here. Hi Kenneth!
       
   847         dest='use_distribute',
       
   848         action='store_true',
       
   849         help='Use Distribute instead of Setuptools. Set environ variable '
       
   850         'VIRTUALENV_DISTRIBUTE to make it the default ')
       
   851 
       
   852     default_search_dirs = file_search_dirs()
       
   853     parser.add_option(
       
   854         '--extra-search-dir',
       
   855         dest="search_dirs",
       
   856         action="append",
       
   857         default=default_search_dirs,
       
   858         help="Directory to look for setuptools/distribute/pip distributions in. "
       
   859         "You can add any number of additional --extra-search-dir paths.")
       
   860 
       
   861     parser.add_option(
       
   862         '--never-download',
       
   863         dest="never_download",
       
   864         action="store_true",
       
   865         help="Never download anything from the network.  Instead, virtualenv will fail "
       
   866         "if local distributions of setuptools/distribute/pip are not present.")
       
   867 
       
   868     parser.add_option(
       
   869         '--prompt',
       
   870         dest='prompt',
       
   871         help='Provides an alternative prompt prefix for this environment')
       
   872 
       
   873     if 'extend_parser' in globals():
       
   874         extend_parser(parser)
       
   875 
       
   876     options, args = parser.parse_args()
       
   877 
       
   878     global logger
       
   879 
       
   880     if 'adjust_options' in globals():
       
   881         adjust_options(options, args)
       
   882 
       
   883     verbosity = options.verbose - options.quiet
       
   884     logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)])
       
   885 
       
   886     if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
       
   887         env = os.environ.copy()
       
   888         interpreter = resolve_interpreter(options.python)
       
   889         if interpreter == sys.executable:
       
   890             logger.warn('Already using interpreter %s' % interpreter)
       
   891         else:
       
   892             logger.notify('Running virtualenv with interpreter %s' % interpreter)
       
   893             env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
       
   894             file = __file__
       
   895             if file.endswith('.pyc'):
       
   896                 file = file[:-1]
       
   897             popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
       
   898             raise SystemExit(popen.wait())
       
   899 
       
   900     # Force --distribute on Python 3, since setuptools is not available.
       
   901     if majver > 2:
       
   902         options.use_distribute = True
       
   903 
       
   904     if os.environ.get('PYTHONDONTWRITEBYTECODE') and not options.use_distribute:
       
   905         print(
       
   906             "The PYTHONDONTWRITEBYTECODE environment variable is "
       
   907             "not compatible with setuptools. Either use --distribute "
       
   908             "or unset PYTHONDONTWRITEBYTECODE.")
       
   909         sys.exit(2)
       
   910     if not args:
       
   911         print('You must provide a DEST_DIR')
       
   912         parser.print_help()
       
   913         sys.exit(2)
       
   914     if len(args) > 1:
       
   915         print('There must be only one argument: DEST_DIR (you gave %s)' % (
       
   916             ' '.join(args)))
       
   917         parser.print_help()
       
   918         sys.exit(2)
       
   919 
       
   920     home_dir = args[0]
       
   921 
       
   922     if os.environ.get('WORKING_ENV'):
       
   923         logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
       
   924         logger.fatal('Please deactivate your workingenv, then re-run this script')
       
   925         sys.exit(3)
       
   926 
       
   927     if 'PYTHONHOME' in os.environ:
       
   928         logger.warn('PYTHONHOME is set.  You *must* activate the virtualenv before using it')
       
   929         del os.environ['PYTHONHOME']
       
   930 
       
   931     if options.relocatable:
       
   932         make_environment_relocatable(home_dir)
       
   933         return
       
   934 
       
   935     create_environment(home_dir,
       
   936                        site_packages=options.system_site_packages,
       
   937                        clear=options.clear,
       
   938                        unzip_setuptools=options.unzip_setuptools,
       
   939                        use_distribute=options.use_distribute,
       
   940                        prompt=options.prompt,
       
   941                        search_dirs=options.search_dirs,
       
   942                        never_download=options.never_download)
       
   943     if 'after_install' in globals():
       
   944         after_install(options, home_dir)
       
   945 
       
   946 def call_subprocess(cmd, show_stdout=True,
       
   947                     filter_stdout=None, cwd=None,
       
   948                     raise_on_returncode=True, extra_env=None,
       
   949                     remove_from_env=None):
       
   950     cmd_parts = []
       
   951     for part in cmd:
       
   952         if len(part) > 45:
       
   953             part = part[:20]+"..."+part[-20:]
       
   954         if ' ' in part or '\n' in part or '"' in part or "'" in part:
       
   955             part = '"%s"' % part.replace('"', '\\"')
       
   956         if hasattr(part, 'decode'):
       
   957             try:
       
   958                 part = part.decode(sys.getdefaultencoding())
       
   959             except UnicodeDecodeError:
       
   960                 part = part.decode(sys.getfilesystemencoding())
       
   961         cmd_parts.append(part)
       
   962     cmd_desc = ' '.join(cmd_parts)
       
   963     if show_stdout:
       
   964         stdout = None
       
   965     else:
       
   966         stdout = subprocess.PIPE
       
   967     logger.debug("Running command %s" % cmd_desc)
       
   968     if extra_env or remove_from_env:
       
   969         env = os.environ.copy()
       
   970         if extra_env:
       
   971             env.update(extra_env)
       
   972         if remove_from_env:
       
   973             for varname in remove_from_env:
       
   974                 env.pop(varname, None)
       
   975     else:
       
   976         env = None
       
   977     try:
       
   978         proc = subprocess.Popen(
       
   979             cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
       
   980             cwd=cwd, env=env)
       
   981     except Exception:
       
   982         e = sys.exc_info()[1]
       
   983         logger.fatal(
       
   984             "Error %s while executing command %s" % (e, cmd_desc))
       
   985         raise
       
   986     all_output = []
       
   987     if stdout is not None:
       
   988         stdout = proc.stdout
       
   989         encoding = sys.getdefaultencoding()
       
   990         fs_encoding = sys.getfilesystemencoding()
       
   991         while 1:
       
   992             line = stdout.readline()
       
   993             try:
       
   994                 line = line.decode(encoding)
       
   995             except UnicodeDecodeError:
       
   996                 line = line.decode(fs_encoding)
       
   997             if not line:
       
   998                 break
       
   999             line = line.rstrip()
       
  1000             all_output.append(line)
       
  1001             if filter_stdout:
       
  1002                 level = filter_stdout(line)
       
  1003                 if isinstance(level, tuple):
       
  1004                     level, line = level
       
  1005                 logger.log(level, line)
       
  1006                 if not logger.stdout_level_matches(level):
       
  1007                     logger.show_progress()
       
  1008             else:
       
  1009                 logger.info(line)
       
  1010     else:
       
  1011         proc.communicate()
       
  1012     proc.wait()
       
  1013     if proc.returncode:
       
  1014         if raise_on_returncode:
       
  1015             if all_output:
       
  1016                 logger.notify('Complete output from command %s:' % cmd_desc)
       
  1017                 logger.notify('\n'.join(all_output) + '\n----------------------------------------')
       
  1018             raise OSError(
       
  1019                 "Command %s failed with error code %s"
       
  1020                 % (cmd_desc, proc.returncode))
       
  1021         else:
       
  1022             logger.warn(
       
  1023                 "Command %s had error code %s"
       
  1024                 % (cmd_desc, proc.returncode))
       
  1025 
       
  1026 
       
  1027 def create_environment(home_dir, site_packages=False, clear=False,
       
  1028                        unzip_setuptools=False, use_distribute=False,
       
  1029                        prompt=None, search_dirs=None, never_download=False):
       
  1030     """
       
  1031     Creates a new environment in ``home_dir``.
       
  1032 
       
  1033     If ``site_packages`` is true, then the global ``site-packages/``
       
  1034     directory will be on the path.
       
  1035 
       
  1036     If ``clear`` is true (default False) then the environment will
       
  1037     first be cleared.
       
  1038     """
       
  1039     home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
       
  1040 
       
  1041     py_executable = os.path.abspath(install_python(
       
  1042         home_dir, lib_dir, inc_dir, bin_dir,
       
  1043         site_packages=site_packages, clear=clear))
       
  1044 
       
  1045     install_distutils(home_dir)
       
  1046 
       
  1047     if use_distribute:
       
  1048         install_distribute(py_executable, unzip=unzip_setuptools,
       
  1049                            search_dirs=search_dirs, never_download=never_download)
       
  1050     else:
       
  1051         install_setuptools(py_executable, unzip=unzip_setuptools,
       
  1052                            search_dirs=search_dirs, never_download=never_download)
       
  1053 
       
  1054     install_pip(py_executable, search_dirs=search_dirs, never_download=never_download)
       
  1055 
       
  1056     install_activate(home_dir, bin_dir, prompt)
       
  1057 
       
  1058 def is_executable_file(fpath):
       
  1059     return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
       
  1060 
       
  1061 def path_locations(home_dir):
       
  1062     """Return the path locations for the environment (where libraries are,
       
  1063     where scripts go, etc)"""
       
  1064     # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
       
  1065     # prefix arg is broken: http://bugs.python.org/issue3386
       
  1066     if is_win:
       
  1067         # Windows has lots of problems with executables with spaces in
       
  1068         # the name; this function will remove them (using the ~1
       
  1069         # format):
       
  1070         mkdir(home_dir)
       
  1071         if ' ' in home_dir:
       
  1072             try:
       
  1073                 import win32api
       
  1074             except ImportError:
       
  1075                 print('Error: the path "%s" has a space in it' % home_dir)
       
  1076                 print('To handle these kinds of paths, the win32api module must be installed:')
       
  1077                 print('  http://sourceforge.net/projects/pywin32/')
       
  1078                 sys.exit(3)
       
  1079             home_dir = win32api.GetShortPathName(home_dir)
       
  1080         lib_dir = join(home_dir, 'Lib')
       
  1081         inc_dir = join(home_dir, 'Include')
       
  1082         bin_dir = join(home_dir, 'Scripts')
       
  1083     if is_jython:
       
  1084         lib_dir = join(home_dir, 'Lib')
       
  1085         inc_dir = join(home_dir, 'Include')
       
  1086         bin_dir = join(home_dir, 'bin')
       
  1087     elif is_pypy:
       
  1088         lib_dir = home_dir
       
  1089         inc_dir = join(home_dir, 'include')
       
  1090         bin_dir = join(home_dir, 'bin')
       
  1091     elif not is_win:
       
  1092         lib_dir = join(home_dir, 'lib', py_version)
       
  1093         multiarch_exec = '/usr/bin/multiarch-platform'
       
  1094         if is_executable_file(multiarch_exec):
       
  1095             # In Mageia (2) and Mandriva distros the include dir must be like:
       
  1096             # virtualenv/include/multiarch-x86_64-linux/python2.7
       
  1097             # instead of being virtualenv/include/python2.7
       
  1098             p = subprocess.Popen(multiarch_exec, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
       
  1099             stdout, stderr = p.communicate()
       
  1100             # stdout.strip is needed to remove newline character
       
  1101             inc_dir = join(home_dir, 'include', stdout.strip(), py_version + abiflags)
       
  1102         else:
       
  1103             inc_dir = join(home_dir, 'include', py_version + abiflags)
       
  1104         bin_dir = join(home_dir, 'bin')
       
  1105     return home_dir, lib_dir, inc_dir, bin_dir
       
  1106 
       
  1107 
       
  1108 def change_prefix(filename, dst_prefix):
       
  1109     prefixes = [sys.prefix]
       
  1110 
       
  1111     if is_darwin:
       
  1112         prefixes.extend((
       
  1113             os.path.join("/Library/Python", sys.version[:3], "site-packages"),
       
  1114             os.path.join(sys.prefix, "Extras", "lib", "python"),
       
  1115             os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"),
       
  1116             # Python 2.6 no-frameworks
       
  1117             os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"),
       
  1118             # System Python 2.7 on OSX Mountain Lion
       
  1119             os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages")))
       
  1120 
       
  1121     if hasattr(sys, 'real_prefix'):
       
  1122         prefixes.append(sys.real_prefix)
       
  1123     prefixes = list(map(os.path.expanduser, prefixes))
       
  1124     prefixes = list(map(os.path.abspath, prefixes))
       
  1125     filename = os.path.abspath(filename)
       
  1126     for src_prefix in prefixes:
       
  1127         if filename.startswith(src_prefix):
       
  1128             _, relpath = filename.split(src_prefix, 1)
       
  1129             if src_prefix != os.sep: # sys.prefix == "/"
       
  1130                 assert relpath[0] == os.sep
       
  1131                 relpath = relpath[1:]
       
  1132             return join(dst_prefix, relpath)
       
  1133     assert False, "Filename %s does not start with any of these prefixes: %s" % \
       
  1134         (filename, prefixes)
       
  1135 
       
  1136 def copy_required_modules(dst_prefix):
       
  1137     import imp
       
  1138     # If we are running under -p, we need to remove the current
       
  1139     # directory from sys.path temporarily here, so that we
       
  1140     # definitely get the modules from the site directory of
       
  1141     # the interpreter we are running under, not the one
       
  1142     # virtualenv.py is installed under (which might lead to py2/py3
       
  1143     # incompatibility issues)
       
  1144     _prev_sys_path = sys.path
       
  1145     if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
       
  1146         sys.path = sys.path[1:]
       
  1147     try:
       
  1148         for modname in REQUIRED_MODULES:
       
  1149             if modname in sys.builtin_module_names:
       
  1150                 logger.info("Ignoring built-in bootstrap module: %s" % modname)
       
  1151                 continue
       
  1152             try:
       
  1153                 f, filename, _ = imp.find_module(modname)
       
  1154             except ImportError:
       
  1155                 logger.info("Cannot import bootstrap module: %s" % modname)
       
  1156             else:
       
  1157                 if f is not None:
       
  1158                     f.close()
       
  1159                 dst_filename = change_prefix(filename, dst_prefix)
       
  1160                 copyfile(filename, dst_filename)
       
  1161                 if filename.endswith('.pyc'):
       
  1162                     pyfile = filename[:-1]
       
  1163                     if os.path.exists(pyfile):
       
  1164                         copyfile(pyfile, dst_filename[:-1])
       
  1165     finally:
       
  1166         sys.path = _prev_sys_path
       
  1167 
       
  1168 def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
       
  1169     """Install just the base environment, no distutils patches etc"""
       
  1170     if sys.executable.startswith(bin_dir):
       
  1171         print('Please use the *system* python to run this script')
       
  1172         return
       
  1173 
       
  1174     if clear:
       
  1175         rmtree(lib_dir)
       
  1176         ## FIXME: why not delete it?
       
  1177         ## Maybe it should delete everything with #!/path/to/venv/python in it
       
  1178         logger.notify('Not deleting %s', bin_dir)
       
  1179 
       
  1180     if hasattr(sys, 'real_prefix'):
       
  1181         logger.notify('Using real prefix %r' % sys.real_prefix)
       
  1182         prefix = sys.real_prefix
       
  1183     else:
       
  1184         prefix = sys.prefix
       
  1185     mkdir(lib_dir)
       
  1186     fix_lib64(lib_dir)
       
  1187     stdlib_dirs = [os.path.dirname(os.__file__)]
       
  1188     if is_win:
       
  1189         stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
       
  1190     elif is_darwin:
       
  1191         stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
       
  1192     if hasattr(os, 'symlink'):
       
  1193         logger.info('Symlinking Python bootstrap modules')
       
  1194     else:
       
  1195         logger.info('Copying Python bootstrap modules')
       
  1196     logger.indent += 2
       
  1197     try:
       
  1198         # copy required files...
       
  1199         for stdlib_dir in stdlib_dirs:
       
  1200             if not os.path.isdir(stdlib_dir):
       
  1201                 continue
       
  1202             for fn in os.listdir(stdlib_dir):
       
  1203                 bn = os.path.splitext(fn)[0]
       
  1204                 if fn != 'site-packages' and bn in REQUIRED_FILES:
       
  1205                     copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
       
  1206         # ...and modules
       
  1207         copy_required_modules(home_dir)
       
  1208     finally:
       
  1209         logger.indent -= 2
       
  1210     mkdir(join(lib_dir, 'site-packages'))
       
  1211     import site
       
  1212     site_filename = site.__file__
       
  1213     if site_filename.endswith('.pyc'):
       
  1214         site_filename = site_filename[:-1]
       
  1215     elif site_filename.endswith('$py.class'):
       
  1216         site_filename = site_filename.replace('$py.class', '.py')
       
  1217     site_filename_dst = change_prefix(site_filename, home_dir)
       
  1218     site_dir = os.path.dirname(site_filename_dst)
       
  1219     writefile(site_filename_dst, SITE_PY)
       
  1220     writefile(join(site_dir, 'orig-prefix.txt'), prefix)
       
  1221     site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
       
  1222     if not site_packages:
       
  1223         writefile(site_packages_filename, '')
       
  1224 
       
  1225     if is_pypy or is_win:
       
  1226         stdinc_dir = join(prefix, 'include')
       
  1227     else:
       
  1228         stdinc_dir = join(prefix, 'include', py_version + abiflags)
       
  1229     if os.path.exists(stdinc_dir):
       
  1230         copyfile(stdinc_dir, inc_dir)
       
  1231     else:
       
  1232         logger.debug('No include dir %s' % stdinc_dir)
       
  1233 
       
  1234     # pypy never uses exec_prefix, just ignore it
       
  1235     if sys.exec_prefix != prefix and not is_pypy:
       
  1236         if is_win:
       
  1237             exec_dir = join(sys.exec_prefix, 'lib')
       
  1238         elif is_jython:
       
  1239             exec_dir = join(sys.exec_prefix, 'Lib')
       
  1240         else:
       
  1241             exec_dir = join(sys.exec_prefix, 'lib', py_version)
       
  1242         for fn in os.listdir(exec_dir):
       
  1243             copyfile(join(exec_dir, fn), join(lib_dir, fn))
       
  1244 
       
  1245     if is_jython:
       
  1246         # Jython has either jython-dev.jar and javalib/ dir, or just
       
  1247         # jython.jar
       
  1248         for name in 'jython-dev.jar', 'javalib', 'jython.jar':
       
  1249             src = join(prefix, name)
       
  1250             if os.path.exists(src):
       
  1251                 copyfile(src, join(home_dir, name))
       
  1252         # XXX: registry should always exist after Jython 2.5rc1
       
  1253         src = join(prefix, 'registry')
       
  1254         if os.path.exists(src):
       
  1255             copyfile(src, join(home_dir, 'registry'), symlink=False)
       
  1256         copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
       
  1257                  symlink=False)
       
  1258 
       
  1259     mkdir(bin_dir)
       
  1260     py_executable = join(bin_dir, os.path.basename(sys.executable))
       
  1261     if 'Python.framework' in prefix:
       
  1262         # OS X framework builds cause validation to break
       
  1263         # https://github.com/pypa/virtualenv/issues/322
       
  1264         if os.environ.get('__PYVENV_LAUNCHER__'):
       
  1265           os.unsetenv('__PYVENV_LAUNCHER__')
       
  1266         if re.search(r'/Python(?:-32|-64)*$', py_executable):
       
  1267             # The name of the python executable is not quite what
       
  1268             # we want, rename it.
       
  1269             py_executable = os.path.join(
       
  1270                     os.path.dirname(py_executable), 'python')
       
  1271 
       
  1272     logger.notify('New %s executable in %s', expected_exe, py_executable)
       
  1273     pcbuild_dir = os.path.dirname(sys.executable)
       
  1274     pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth')
       
  1275     if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')):
       
  1276         logger.notify('Detected python running from build directory %s', pcbuild_dir)
       
  1277         logger.notify('Writing .pth file linking to build directory for *.pyd files')
       
  1278         writefile(pyd_pth, pcbuild_dir)
       
  1279     else:
       
  1280         pcbuild_dir = None
       
  1281         if os.path.exists(pyd_pth):
       
  1282             logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth)
       
  1283             os.unlink(pyd_pth)
       
  1284 
       
  1285     if sys.executable != py_executable:
       
  1286         ## FIXME: could I just hard link?
       
  1287         executable = sys.executable
       
  1288         if is_cygwin and os.path.exists(executable + '.exe'):
       
  1289             # Cygwin misreports sys.executable sometimes
       
  1290             executable += '.exe'
       
  1291             py_executable += '.exe'
       
  1292             logger.info('Executable actually exists in %s' % executable)
       
  1293         shutil.copyfile(executable, py_executable)
       
  1294         make_exe(py_executable)
       
  1295         if is_win or is_cygwin:
       
  1296             pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
       
  1297             if os.path.exists(pythonw):
       
  1298                 logger.info('Also created pythonw.exe')
       
  1299                 shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
       
  1300             python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe')
       
  1301             python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe')
       
  1302             if os.path.exists(python_d):
       
  1303                 logger.info('Also created python_d.exe')
       
  1304                 shutil.copyfile(python_d, python_d_dest)
       
  1305             elif os.path.exists(python_d_dest):
       
  1306                 logger.info('Removed python_d.exe as it is no longer at the source')
       
  1307                 os.unlink(python_d_dest)
       
  1308             # we need to copy the DLL to enforce that windows will load the correct one.
       
  1309             # may not exist if we are cygwin.
       
  1310             py_executable_dll = 'python%s%s.dll' % (
       
  1311                 sys.version_info[0], sys.version_info[1])
       
  1312             py_executable_dll_d = 'python%s%s_d.dll' % (
       
  1313                 sys.version_info[0], sys.version_info[1])
       
  1314             pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll)
       
  1315             pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d)
       
  1316             pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d)
       
  1317             if os.path.exists(pythondll):
       
  1318                 logger.info('Also created %s' % py_executable_dll)
       
  1319                 shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll))
       
  1320             if os.path.exists(pythondll_d):
       
  1321                 logger.info('Also created %s' % py_executable_dll_d)
       
  1322                 shutil.copyfile(pythondll_d, pythondll_d_dest)
       
  1323             elif os.path.exists(pythondll_d_dest):
       
  1324                 logger.info('Removed %s as the source does not exist' % pythondll_d_dest)
       
  1325                 os.unlink(pythondll_d_dest)
       
  1326         if is_pypy:
       
  1327             # make a symlink python --> pypy-c
       
  1328             python_executable = os.path.join(os.path.dirname(py_executable), 'python')
       
  1329             if sys.platform in ('win32', 'cygwin'):
       
  1330                 python_executable += '.exe'
       
  1331             logger.info('Also created executable %s' % python_executable)
       
  1332             copyfile(py_executable, python_executable)
       
  1333 
       
  1334             if is_win:
       
  1335                 for name in 'libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', 'libeay32.dll', 'ssleay32.dll', 'sqlite.dll':
       
  1336                     src = join(prefix, name)
       
  1337                     if os.path.exists(src):
       
  1338                         copyfile(src, join(bin_dir, name))
       
  1339 
       
  1340     if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
       
  1341         secondary_exe = os.path.join(os.path.dirname(py_executable),
       
  1342                                      expected_exe)
       
  1343         py_executable_ext = os.path.splitext(py_executable)[1]
       
  1344         if py_executable_ext == '.exe':
       
  1345             # python2.4 gives an extension of '.4' :P
       
  1346             secondary_exe += py_executable_ext
       
  1347         if os.path.exists(secondary_exe):
       
  1348             logger.warn('Not overwriting existing %s script %s (you must use %s)'
       
  1349                         % (expected_exe, secondary_exe, py_executable))
       
  1350         else:
       
  1351             logger.notify('Also creating executable in %s' % secondary_exe)
       
  1352             shutil.copyfile(sys.executable, secondary_exe)
       
  1353             make_exe(secondary_exe)
       
  1354 
       
  1355     if '.framework' in prefix:
       
  1356         if 'Python.framework' in prefix:
       
  1357             logger.debug('MacOSX Python framework detected')
       
  1358             # Make sure we use the the embedded interpreter inside
       
  1359             # the framework, even if sys.executable points to
       
  1360             # the stub executable in ${sys.prefix}/bin
       
  1361             # See http://groups.google.com/group/python-virtualenv/
       
  1362             #                              browse_thread/thread/17cab2f85da75951
       
  1363             original_python = os.path.join(
       
  1364                 prefix, 'Resources/Python.app/Contents/MacOS/Python')
       
  1365         if 'EPD' in prefix:
       
  1366             logger.debug('EPD framework detected')
       
  1367             original_python = os.path.join(prefix, 'bin/python')
       
  1368         shutil.copy(original_python, py_executable)
       
  1369 
       
  1370         # Copy the framework's dylib into the virtual
       
  1371         # environment
       
  1372         virtual_lib = os.path.join(home_dir, '.Python')
       
  1373 
       
  1374         if os.path.exists(virtual_lib):
       
  1375             os.unlink(virtual_lib)
       
  1376         copyfile(
       
  1377             os.path.join(prefix, 'Python'),
       
  1378             virtual_lib)
       
  1379 
       
  1380         # And then change the install_name of the copied python executable
       
  1381         try:
       
  1382             mach_o_change(py_executable,
       
  1383                           os.path.join(prefix, 'Python'),
       
  1384                           '@executable_path/../.Python')
       
  1385         except:
       
  1386             e = sys.exc_info()[1]
       
  1387             logger.warn("Could not call mach_o_change: %s. "
       
  1388                         "Trying to call install_name_tool instead." % e)
       
  1389             try:
       
  1390                 call_subprocess(
       
  1391                     ["install_name_tool", "-change",
       
  1392                      os.path.join(prefix, 'Python'),
       
  1393                      '@executable_path/../.Python',
       
  1394                      py_executable])
       
  1395             except:
       
  1396                 logger.fatal("Could not call install_name_tool -- you must "
       
  1397                              "have Apple's development tools installed")
       
  1398                 raise
       
  1399 
       
  1400         # Some tools depend on pythonX.Y being present
       
  1401         py_executable_version = '%s.%s' % (
       
  1402             sys.version_info[0], sys.version_info[1])
       
  1403         if not py_executable.endswith(py_executable_version):
       
  1404             # symlinking pythonX.Y > python
       
  1405             pth = py_executable + '%s.%s' % (
       
  1406                     sys.version_info[0], sys.version_info[1])
       
  1407             if os.path.exists(pth):
       
  1408                 os.unlink(pth)
       
  1409             os.symlink('python', pth)
       
  1410         else:
       
  1411             # reverse symlinking python -> pythonX.Y (with --python)
       
  1412             pth = join(bin_dir, 'python')
       
  1413             if os.path.exists(pth):
       
  1414                 os.unlink(pth)
       
  1415             os.symlink(os.path.basename(py_executable), pth)
       
  1416 
       
  1417     if is_win and ' ' in py_executable:
       
  1418         # There's a bug with subprocess on Windows when using a first
       
  1419         # argument that has a space in it.  Instead we have to quote
       
  1420         # the value:
       
  1421         py_executable = '"%s"' % py_executable
       
  1422     # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks
       
  1423     cmd = [py_executable, '-c', 'import sys;out=sys.stdout;'
       
  1424         'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))']
       
  1425     logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
       
  1426     try:
       
  1427         proc = subprocess.Popen(cmd,
       
  1428                             stdout=subprocess.PIPE)
       
  1429         proc_stdout, proc_stderr = proc.communicate()
       
  1430     except OSError:
       
  1431         e = sys.exc_info()[1]
       
  1432         if e.errno == errno.EACCES:
       
  1433             logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e))
       
  1434             sys.exit(100)
       
  1435         else:
       
  1436             raise e
       
  1437 
       
  1438     proc_stdout = proc_stdout.strip().decode("utf-8")
       
  1439     proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
       
  1440     norm_home_dir = os.path.normcase(os.path.abspath(home_dir))
       
  1441     if hasattr(norm_home_dir, 'decode'):
       
  1442         norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding())
       
  1443     if proc_stdout != norm_home_dir:
       
  1444         logger.fatal(
       
  1445             'ERROR: The executable %s is not functioning' % py_executable)
       
  1446         logger.fatal(
       
  1447             'ERROR: It thinks sys.prefix is %r (should be %r)'
       
  1448             % (proc_stdout, norm_home_dir))
       
  1449         logger.fatal(
       
  1450             'ERROR: virtualenv is not compatible with this system or executable')
       
  1451         if is_win:
       
  1452             logger.fatal(
       
  1453                 'Note: some Windows users have reported this error when they '
       
  1454                 'installed Python for "Only this user" or have multiple '
       
  1455                 'versions of Python installed. Copying the appropriate '
       
  1456                 'PythonXX.dll to the virtualenv Scripts/ directory may fix '
       
  1457                 'this problem.')
       
  1458         sys.exit(100)
       
  1459     else:
       
  1460         logger.info('Got sys.prefix result: %r' % proc_stdout)
       
  1461 
       
  1462     pydistutils = os.path.expanduser('~/.pydistutils.cfg')
       
  1463     if os.path.exists(pydistutils):
       
  1464         logger.notify('Please make sure you remove any previous custom paths from '
       
  1465                       'your %s file.' % pydistutils)
       
  1466     ## FIXME: really this should be calculated earlier
       
  1467 
       
  1468     fix_local_scheme(home_dir)
       
  1469 
       
  1470     if site_packages:
       
  1471         if os.path.exists(site_packages_filename):
       
  1472             logger.info('Deleting %s' % site_packages_filename)
       
  1473             os.unlink(site_packages_filename)
       
  1474 
       
  1475     return py_executable
       
  1476 
       
  1477 
       
  1478 def install_activate(home_dir, bin_dir, prompt=None):
       
  1479     home_dir = os.path.abspath(home_dir)
       
  1480     if is_win or is_jython and os._name == 'nt':
       
  1481         files = {
       
  1482             'activate.bat': ACTIVATE_BAT,
       
  1483             'deactivate.bat': DEACTIVATE_BAT,
       
  1484             'activate.ps1': ACTIVATE_PS,
       
  1485         }
       
  1486 
       
  1487         # MSYS needs paths of the form /c/path/to/file
       
  1488         drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/'))
       
  1489         home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail)
       
  1490 
       
  1491         # Run-time conditional enables (basic) Cygwin compatibility
       
  1492         home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" %
       
  1493                        (home_dir, home_dir_msys))
       
  1494         files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh)
       
  1495 
       
  1496     else:
       
  1497         files = {'activate': ACTIVATE_SH}
       
  1498 
       
  1499         # suppling activate.fish in addition to, not instead of, the
       
  1500         # bash script support.
       
  1501         files['activate.fish'] = ACTIVATE_FISH
       
  1502 
       
  1503         # same for csh/tcsh support...
       
  1504         files['activate.csh'] = ACTIVATE_CSH
       
  1505 
       
  1506     files['activate_this.py'] = ACTIVATE_THIS
       
  1507     if hasattr(home_dir, 'decode'):
       
  1508         home_dir = home_dir.decode(sys.getfilesystemencoding())
       
  1509     vname = os.path.basename(home_dir)
       
  1510     for name, content in files.items():
       
  1511         content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
       
  1512         content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname)
       
  1513         content = content.replace('__VIRTUAL_ENV__', home_dir)
       
  1514         content = content.replace('__VIRTUAL_NAME__', vname)
       
  1515         content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
       
  1516         writefile(os.path.join(bin_dir, name), content)
       
  1517 
       
  1518 def install_distutils(home_dir):
       
  1519     distutils_path = change_prefix(distutils.__path__[0], home_dir)
       
  1520     mkdir(distutils_path)
       
  1521     ## FIXME: maybe this prefix setting should only be put in place if
       
  1522     ## there's a local distutils.cfg with a prefix setting?
       
  1523     home_dir = os.path.abspath(home_dir)
       
  1524     ## FIXME: this is breaking things, removing for now:
       
  1525     #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
       
  1526     writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
       
  1527     writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
       
  1528 
       
  1529 def fix_local_scheme(home_dir):
       
  1530     """
       
  1531     Platforms that use the "posix_local" install scheme (like Ubuntu with
       
  1532     Python 2.7) need to be given an additional "local" location, sigh.
       
  1533     """
       
  1534     try:
       
  1535         import sysconfig
       
  1536     except ImportError:
       
  1537         pass
       
  1538     else:
       
  1539         if sysconfig._get_default_scheme() == 'posix_local':
       
  1540             local_path = os.path.join(home_dir, 'local')
       
  1541             if not os.path.exists(local_path):
       
  1542                 os.mkdir(local_path)
       
  1543                 for subdir_name in os.listdir(home_dir):
       
  1544                     if subdir_name == 'local':
       
  1545                         continue
       
  1546                     os.symlink(os.path.abspath(os.path.join(home_dir, subdir_name)), \
       
  1547                                                             os.path.join(local_path, subdir_name))
       
  1548 
       
  1549 def fix_lib64(lib_dir):
       
  1550     """
       
  1551     Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
       
  1552     instead of lib/pythonX.Y.  If this is such a platform we'll just create a
       
  1553     symlink so lib64 points to lib
       
  1554     """
       
  1555     if [p for p in distutils.sysconfig.get_config_vars().values()
       
  1556         if isinstance(p, basestring) and 'lib64' in p]:
       
  1557         logger.debug('This system uses lib64; symlinking lib64 to lib')
       
  1558         assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
       
  1559             "Unexpected python lib dir: %r" % lib_dir)
       
  1560         lib_parent = os.path.dirname(lib_dir)
       
  1561         assert os.path.basename(lib_parent) == 'lib', (
       
  1562             "Unexpected parent dir: %r" % lib_parent)
       
  1563         os.symlink(os.path.join('.', os.path.basename(lib_parent)),
       
  1564                    os.path.join(os.path.dirname(lib_parent), 'lib64'))
       
  1565 
       
  1566 def resolve_interpreter(exe):
       
  1567     """
       
  1568     If the executable given isn't an absolute path, search $PATH for the interpreter
       
  1569     """
       
  1570     if os.path.abspath(exe) != exe:
       
  1571         paths = os.environ.get('PATH', '').split(os.pathsep)
       
  1572         for path in paths:
       
  1573             if os.path.exists(os.path.join(path, exe)):
       
  1574                 exe = os.path.join(path, exe)
       
  1575                 break
       
  1576     if not os.path.exists(exe):
       
  1577         logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
       
  1578         raise SystemExit(3)
       
  1579     if not is_executable(exe):
       
  1580         logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
       
  1581         raise SystemExit(3)
       
  1582     return exe
       
  1583 
       
  1584 def is_executable(exe):
       
  1585     """Checks a file is executable"""
       
  1586     return os.access(exe, os.X_OK)
       
  1587 
       
  1588 ############################################################
       
  1589 ## Relocating the environment:
       
  1590 
       
  1591 def make_environment_relocatable(home_dir):
       
  1592     """
       
  1593     Makes the already-existing environment use relative paths, and takes out
       
  1594     the #!-based environment selection in scripts.
       
  1595     """
       
  1596     home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
       
  1597     activate_this = os.path.join(bin_dir, 'activate_this.py')
       
  1598     if not os.path.exists(activate_this):
       
  1599         logger.fatal(
       
  1600             'The environment doesn\'t have a file %s -- please re-run virtualenv '
       
  1601             'on this environment to update it' % activate_this)
       
  1602     fixup_scripts(home_dir)
       
  1603     fixup_pth_and_egg_link(home_dir)
       
  1604     ## FIXME: need to fix up distutils.cfg
       
  1605 
       
  1606 OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
       
  1607                   'activate', 'activate.bat', 'activate_this.py']
       
  1608 
       
  1609 def fixup_scripts(home_dir):
       
  1610     # This is what we expect at the top of scripts:
       
  1611     shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
       
  1612     # This is what we'll put:
       
  1613     new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
       
  1614     if is_win:
       
  1615         bin_suffix = 'Scripts'
       
  1616     else:
       
  1617         bin_suffix = 'bin'
       
  1618     bin_dir = os.path.join(home_dir, bin_suffix)
       
  1619     home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
       
  1620     for filename in os.listdir(bin_dir):
       
  1621         filename = os.path.join(bin_dir, filename)
       
  1622         if not os.path.isfile(filename):
       
  1623             # ignore subdirs, e.g. .svn ones.
       
  1624             continue
       
  1625         f = open(filename, 'rb')
       
  1626         try:
       
  1627             try:
       
  1628                 lines = f.read().decode('utf-8').splitlines()
       
  1629             except UnicodeDecodeError:
       
  1630                 # This is probably a binary program instead
       
  1631                 # of a script, so just ignore it.
       
  1632                 continue
       
  1633         finally:
       
  1634             f.close()
       
  1635         if not lines:
       
  1636             logger.warn('Script %s is an empty file' % filename)
       
  1637             continue
       
  1638         if not lines[0].strip().startswith(shebang):
       
  1639             if os.path.basename(filename) in OK_ABS_SCRIPTS:
       
  1640                 logger.debug('Cannot make script %s relative' % filename)
       
  1641             elif lines[0].strip() == new_shebang:
       
  1642                 logger.info('Script %s has already been made relative' % filename)
       
  1643             else:
       
  1644                 logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
       
  1645                             % (filename, shebang))
       
  1646             continue
       
  1647         logger.notify('Making script %s relative' % filename)
       
  1648         script = relative_script([new_shebang] + lines[1:])
       
  1649         f = open(filename, 'wb')
       
  1650         f.write('\n'.join(script).encode('utf-8'))
       
  1651         f.close()
       
  1652 
       
  1653 def relative_script(lines):
       
  1654     "Return a script that'll work in a relocatable environment."
       
  1655     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"
       
  1656     # Find the last future statement in the script. If we insert the activation
       
  1657     # line before a future statement, Python will raise a SyntaxError.
       
  1658     activate_at = None
       
  1659     for idx, line in reversed(list(enumerate(lines))):
       
  1660         if line.split()[:3] == ['from', '__future__', 'import']:
       
  1661             activate_at = idx + 1
       
  1662             break
       
  1663     if activate_at is None:
       
  1664         # Activate after the shebang.
       
  1665         activate_at = 1
       
  1666     return lines[:activate_at] + ['', activate, ''] + lines[activate_at:]
       
  1667 
       
  1668 def fixup_pth_and_egg_link(home_dir, sys_path=None):
       
  1669     """Makes .pth and .egg-link files use relative paths"""
       
  1670     home_dir = os.path.normcase(os.path.abspath(home_dir))
       
  1671     if sys_path is None:
       
  1672         sys_path = sys.path
       
  1673     for path in sys_path:
       
  1674         if not path:
       
  1675             path = '.'
       
  1676         if not os.path.isdir(path):
       
  1677             continue
       
  1678         path = os.path.normcase(os.path.abspath(path))
       
  1679         if not path.startswith(home_dir):
       
  1680             logger.debug('Skipping system (non-environment) directory %s' % path)
       
  1681             continue
       
  1682         for filename in os.listdir(path):
       
  1683             filename = os.path.join(path, filename)
       
  1684             if filename.endswith('.pth'):
       
  1685                 if not os.access(filename, os.W_OK):
       
  1686                     logger.warn('Cannot write .pth file %s, skipping' % filename)
       
  1687                 else:
       
  1688                     fixup_pth_file(filename)
       
  1689             if filename.endswith('.egg-link'):
       
  1690                 if not os.access(filename, os.W_OK):
       
  1691                     logger.warn('Cannot write .egg-link file %s, skipping' % filename)
       
  1692                 else:
       
  1693                     fixup_egg_link(filename)
       
  1694 
       
  1695 def fixup_pth_file(filename):
       
  1696     lines = []
       
  1697     prev_lines = []
       
  1698     f = open(filename)
       
  1699     prev_lines = f.readlines()
       
  1700     f.close()
       
  1701     for line in prev_lines:
       
  1702         line = line.strip()
       
  1703         if (not line or line.startswith('#') or line.startswith('import ')
       
  1704             or os.path.abspath(line) != line):
       
  1705             lines.append(line)
       
  1706         else:
       
  1707             new_value = make_relative_path(filename, line)
       
  1708             if line != new_value:
       
  1709                 logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
       
  1710             lines.append(new_value)
       
  1711     if lines == prev_lines:
       
  1712         logger.info('No changes to .pth file %s' % filename)
       
  1713         return
       
  1714     logger.notify('Making paths in .pth file %s relative' % filename)
       
  1715     f = open(filename, 'w')
       
  1716     f.write('\n'.join(lines) + '\n')
       
  1717     f.close()
       
  1718 
       
  1719 def fixup_egg_link(filename):
       
  1720     f = open(filename)
       
  1721     link = f.readline().strip()
       
  1722     f.close()
       
  1723     if os.path.abspath(link) != link:
       
  1724         logger.debug('Link in %s already relative' % filename)
       
  1725         return
       
  1726     new_link = make_relative_path(filename, link)
       
  1727     logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
       
  1728     f = open(filename, 'w')
       
  1729     f.write(new_link)
       
  1730     f.close()
       
  1731 
       
  1732 def make_relative_path(source, dest, dest_is_directory=True):
       
  1733     """
       
  1734     Make a filename relative, where the filename is dest, and it is
       
  1735     being referred to from the filename source.
       
  1736 
       
  1737         >>> make_relative_path('/usr/share/something/a-file.pth',
       
  1738         ...                    '/usr/share/another-place/src/Directory')
       
  1739         '../another-place/src/Directory'
       
  1740         >>> make_relative_path('/usr/share/something/a-file.pth',
       
  1741         ...                    '/home/user/src/Directory')
       
  1742         '../../../home/user/src/Directory'
       
  1743         >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
       
  1744         './'
       
  1745     """
       
  1746     source = os.path.dirname(source)
       
  1747     if not dest_is_directory:
       
  1748         dest_filename = os.path.basename(dest)
       
  1749         dest = os.path.dirname(dest)
       
  1750     dest = os.path.normpath(os.path.abspath(dest))
       
  1751     source = os.path.normpath(os.path.abspath(source))
       
  1752     dest_parts = dest.strip(os.path.sep).split(os.path.sep)
       
  1753     source_parts = source.strip(os.path.sep).split(os.path.sep)
       
  1754     while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
       
  1755         dest_parts.pop(0)
       
  1756         source_parts.pop(0)
       
  1757     full_parts = ['..']*len(source_parts) + dest_parts
       
  1758     if not dest_is_directory:
       
  1759         full_parts.append(dest_filename)
       
  1760     if not full_parts:
       
  1761         # Special case for the current directory (otherwise it'd be '')
       
  1762         return './'
       
  1763     return os.path.sep.join(full_parts)
       
  1764 
       
  1765 
       
  1766 
       
  1767 ############################################################
       
  1768 ## Bootstrap script creation:
       
  1769 
       
  1770 def create_bootstrap_script(extra_text, python_version=''):
       
  1771     """
       
  1772     Creates a bootstrap script, which is like this script but with
       
  1773     extend_parser, adjust_options, and after_install hooks.
       
  1774 
       
  1775     This returns a string that (written to disk of course) can be used
       
  1776     as a bootstrap script with your own customizations.  The script
       
  1777     will be the standard virtualenv.py script, with your extra text
       
  1778     added (your extra text should be Python code).
       
  1779 
       
  1780     If you include these functions, they will be called:
       
  1781 
       
  1782     ``extend_parser(optparse_parser)``:
       
  1783         You can add or remove options from the parser here.
       
  1784 
       
  1785     ``adjust_options(options, args)``:
       
  1786         You can change options here, or change the args (if you accept
       
  1787         different kinds of arguments, be sure you modify ``args`` so it is
       
  1788         only ``[DEST_DIR]``).
       
  1789 
       
  1790     ``after_install(options, home_dir)``:
       
  1791 
       
  1792         After everything is installed, this function is called.  This
       
  1793         is probably the function you are most likely to use.  An
       
  1794         example would be::
       
  1795 
       
  1796             def after_install(options, home_dir):
       
  1797                 subprocess.call([join(home_dir, 'bin', 'easy_install'),
       
  1798                                  'MyPackage'])
       
  1799                 subprocess.call([join(home_dir, 'bin', 'my-package-script'),
       
  1800                                  'setup', home_dir])
       
  1801 
       
  1802         This example immediately installs a package, and runs a setup
       
  1803         script from that package.
       
  1804 
       
  1805     If you provide something like ``python_version='2.4'`` then the
       
  1806     script will start with ``#!/usr/bin/env python2.4`` instead of
       
  1807     ``#!/usr/bin/env python``.  You can use this when the script must
       
  1808     be run with a particular Python version.
       
  1809     """
       
  1810     filename = __file__
       
  1811     if filename.endswith('.pyc'):
       
  1812         filename = filename[:-1]
       
  1813     f = codecs.open(filename, 'r', encoding='utf-8')
       
  1814     content = f.read()
       
  1815     f.close()
       
  1816     py_exe = 'python%s' % python_version
       
  1817     content = (('#!/usr/bin/env %s\n' % py_exe)
       
  1818                + '## WARNING: This file is generated\n'
       
  1819                + content)
       
  1820     return content.replace('##EXT' 'END##', extra_text)
       
  1821 
       
  1822 ##EXTEND##
       
  1823 
       
  1824 def convert(s):
       
  1825     b = base64.b64decode(s.encode('ascii'))
       
  1826     return zlib.decompress(b).decode('utf-8')
       
  1827 
       
  1828 ##file site.py
       
  1829 SITE_PY = convert("""
       
  1830 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
       
  1965 YAowyJmdag/AGoXg/wBaZusT
       
  1966 """)
       
  1967 
       
  1968 ##file ez_setup.py
       
  1969 EZ_SETUP_PY = convert("""
       
  1970 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
       
  2026 +G+mirJU+fmCq5Ta1xyCRccC897nZW+WyGsxiMawF7e329Zb2621wQDo2I7tLv7jrv9/AfAaXNUU
       
  2027 TOsyF6jViUG46+NBJqZXv+rRK7Evv2i81ZEw33DQ8y6YowH05r+BuxfN92SX3RbVP8bNymDOGnY7
       
  2028 16PfvzG+4ecrzfzkjPZya/H/ScnXyqwX/JtSrrL5pbrryu1hPKFrZzsrJD6sUuyPwDGdKerJyxmq
       
  2029 dvmdHNCrrzU/+2W0pQ6gSvPl/Mertmi+7hBlDhB80kRUqcNeJCGapHNCz1cvCFwsf0A/Ne++jGMf
       
  2030 TuOJcm6+ZnP9TRR7tWjHreOhZ6huiKnPAP2zfmqpIqHHLG/emnNhyHxSs+JJYfIwj6t2AlLdVneO
       
  2031 3Is9u0R33ef+Wv2pVizPfbUW0rGhps1FRRfnZ/2xsnr3oT2Slh2tvngsLXu6M0OgIen7ufrjprrD
       
  2032 vzXQAgNE22ualqzbyAb97uvl6qF/2a5hcU+eBzVWzOdmVjA0PXQMQoAhsulmBv39oU13134SjSlb
       
  2033 dX85nKW3umfYbtu8713Sylhb2i3v2qaoc8C7S2P3pME8uIGedi1IxXbL+adi+P2fT8Xy/m+/PrxZ
       
  2034 /TrXDcpqOMjotwdo9AJmg8r1N7BySygc+Gp+XaYdJhpV8f/7Oy3Y1s330l09YBDTjnyjn5qHGF7x
       
  2035 6O7hZfMXz21OyLZB6lUfOGAGMzo/bjaL7VaV7Ha76D/1yJVEqKmr+L2nCbH7+959wDtv38JZplQG
       
  2036 BDaonX65d/fwEjNqlDjLVIvM9X+XVxF7
       
  2037 """)
       
  2038 
       
  2039 ##file distribute_setup.py
       
  2040 DISTRIBUTE_SETUP_PY = convert("""
       
  2041 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
       
  2123 9g==
       
  2124 """)
       
  2125 
       
  2126 ##file activate.sh
       
  2127 ACTIVATE_SH = convert("""
       
  2128 eJytVVFvokAQfudXTLEPtTlLeo9tvMSmJpq02hSvl7u2wRUG2QR2DSxSe7n/frOACEVNLlceRHa+
       
  2129 nfl25pvZDswCnoDPQ4QoTRQsENIEPci4CsBMZBq7CAsuLOYqvmYKTTj3YxnBgiXBudGBjUzBZUJI
       
  2130 BXEqgCvweIyuCjeG4eF2F5x14bcB9KQiQQWrjSddI1/oQIx6SYYeoFjzWIoIhYI1izlbhJjkKO7D
       
  2131 M/QEmKfO9O7WeRo/zr4P7pyHwWxkwitcgwpQ5Ej96OX+PmiFwLeVjFUOrNYKaq1Nud3nR2n8nI2m
       
  2132 k9H0friPTGVsUdptaxGrTEfpNVFEskxpXtUkkCkl1UNF9cgLBkx48J4EXyALuBtAwNYIjF5kcmUU
       
  2133 abMKmMq1ULoiRbgsDEkTSsKSGFCJ6Z8vY/2xYiSacmtyAfCDdCNTVZoVF8vSTQOoEwSnOrngBkws
       
  2134 MYGMBMg8/bMBLSYKS7pYEXP0PqT+ZmBT0Xuy+Pplj5yn4aM9nk72JD8/Wi+Gr98sD9eWSMOwkapD
       
  2135 BbUv91XSvmyVkICt2tmXR4tWmrcUCsjWOpw87YidEC8i0gdTSOFhouJUNxR+4NYBG0MftoCTD9F7
       
  2136 2rTtxG3oPwY1b2HncYwhrlmj6Wq924xtGDWqfdNxap+OYxplEurnMVo9RWks+rH8qKEtx7kZT5zJ
       
  2137 4H7oOFclrN6uFe+d+nW2aIUsSgs/42EIPuOhXq+jEo3S6tX6w2ilNkDnIpHCWdEQhFgwj9pkk7FN
       
  2138 l/y5eQvRSIQ5+TrL05lewxWpt/Lbhes5cJF3mLET1MGhcKCF+40tNWnUulxrpojwDo2sObdje3Bz
       
  2139 N3QeHqf3D7OjEXMVV8LN3ZlvuzoWHqiUcNKHtwNd0IbvPGKYYM31nPKCgkUILw3KL+Y8l7aO1ArS
       
  2140 Ad37nIU0fCj5NE5gQCuC5sOSu+UdI2NeXg/lFkQIlFpdWVaWZRfvqGiirC9o6liJ9FXGYrSY9mI1
       
  2141 D/Ncozgn13vJvsznr7DnkJWXsyMH7e42ljdJ+aqNDF1bFnKWFLdj31xtaJYK6EXFgqmV/ymD/ROG
       
  2142 +n8O9H8f5vsGOWXsL1+1k3g=
       
  2143 """)
       
  2144 
       
  2145 ##file activate.fish
       
  2146 ACTIVATE_FISH = convert("""
       
  2147 eJyVVWFv2jAQ/c6vuBoqQVWC9nVSNVGVCaS2VC2rNLWVZZILWAs2s52wVvvxsyEJDrjbmgpK7PP5
       
  2148 3bt3d22YLbmGlGcIq1wbmCPkGhPYcLMEEsGciwGLDS+YwSjlekngLFVyBe73GXSXxqw/DwbuTS8x
       
  2149 yyKpFr1WG15lDjETQhpQuQBuIOEKY5O9tlppLqxHKSDByjVAPwEy+mXtCq5MzjIUBTCRgEKTKwFG
       
  2150 gpBqxTLYXgN2myspVigMaYF92tZSowGZJf4mFExxNs9Qb614CgZtmH0BpEOn11f0cXI/+za8pnfD
       
  2151 2ZjA1sg9zlV/8QvcMhxbNu0QwgYokn/d+n02nt6Opzcjcnx1vXcIoN74O4ymWQXmHURfJw9jenc/
       
  2152 vbmb0enj6P5+cuVhqlKm3S0u2XRtRbA2QQAhV7VhBF0rsgUX9Ur1rBUXJgVSy8O751k8mzY5OrKH
       
  2153 RW3eaQhYGTr8hrXO59ALhxQ83mCsDLAid3T72CCSdJhaFE+fXgicXAARUiR2WeVO37gH3oYHzFKo
       
  2154 9k7CaPZ1UeNwH1tWuXA4uFKYYcEa8vaKqXl7q1UpygMPhFLvlVKyNzsSM3S2km7UBOl4xweUXk5u
       
  2155 6e3wZmQ9leY1XE/Ili670tr9g/5POBBpGIJXCCF79L1siarl/dbESa8mD8PL61GpzqpzuMS7tqeB
       
  2156 1YkALrRBloBMbR9yLcVx7frQAgUqR7NZIuzkEu110gbNit1enNs82Rx5utq7Z3prU78HFRgulqNC
       
  2157 OTwbqJa9vkJFclQgZSjbKeBgSsUtCtt9D8OwAbIVJuewQdfvQRaoFE9wd1TmCuRG7OgJ1bVXGHc7
       
  2158 z5WDL/WW36v2oi37CyVBak61+yPBA9C1qqGxzKQqZ0oPuocU9hpud0PIp8sDHkXR1HKkNlzjuUWA
       
  2159 a0enFUyzOWZA4yXGP+ZMI3Tdt2OuqU/SO4q64526cPE0A7ZyW2PMbWZiZ5HamIZ2RcCKLXhcDl2b
       
  2160 vXL+eccQoRzem80mekPDEiyiWK4GWqZmwxQOmPM0eIfgp1P9cqrBsewR2p/DPMtt+pfcYM+Ls2uh
       
  2161 hALufTAdmGl8B1H3VPd2af8fQAc4PgqjlIBL9cGQqNpXaAwe3LrtVn8AkZTUxg==
       
  2162 """)
       
  2163 
       
  2164 ##file activate.csh
       
  2165 ACTIVATE_CSH = convert("""
       
  2166 eJx9U11v2jAUffevOA2o3ZBG9gxjGx2VVqmlVUUrTWMyTnLTWEocZDsg+uvnOEDDx5aHKLn3fFyf
       
  2167 3HQwy6RBKnNCURmLiFAZSrCWNkNgykrHhEiqUMRWroSlfmyyAL1UlwXcY6/POvhVVoiFUqWFrhSk
       
  2168 RSI1xTbf1N0fmhwvQbTBRKxkQphIXOfCSHxJfCGJvr8WQub9uCy+9hkTuRQGCe08cWXJzdb9xh/u
       
  2169 Jvzl9mn2PL7jj+PZT1yM8BmXlzBkSa3ga0H3BBfUmEo5FE56Q2jKhMmGOOvy9HD/OGv7YOnOvrSj
       
  2170 YxsP/KeR7w6bVj3prnEzfdkaB/OLQS+onQJVqsSVdFUHQFvNk1Ra1eUmKeMr5tJ+9t5Sa8ppJZTF
       
  2171 SmgpopxMn7W4hw6MnU6FgPPWK+eBR53m54LwEbPDb9Dihpxf3075dHx/w/lgiz4j5jNyck3ADiJT
       
  2172 fGiN0QDcJD6k4CNsRorBXbWW8+ZKFIQRznEY5YY8uFZdRMKQRx9MGiww8vS2eH11YJYUS5G7RTeE
       
  2173 tNQYu4pCIV5lvN33UksybQoRMmuXgzBcr9f9N7IioVW95aEpU7sWmkJRq4R70tFB3secL5zHmYHn
       
  2174 i4Un70/3X5WjwzZMlciUNff39a5T/N3difzB/qM0y71r7H5Wv4DubrNS4VPRvDPW/FmM/QUd8WEa
       
  2175 """)
       
  2176 
       
  2177 ##file activate.bat
       
  2178 ACTIVATE_BAT = convert("""
       
  2179 eJyFUkEKgzAQvAfyhz0YaL9QEWpRqlSjWGspFPZQTevFHOr/adQaU1GaUzI7Mzu7ZF89XhKkEJS8
       
  2180 qxaKMMsvboQ+LxxE44VICSW1gEa2UFaibqoS0iyJ0xw2lIA6nX5AHCu1jpRsv5KRjknkac9VLVug
       
  2181 sX9mtzxIeJDE/mg4OGp47qoLo3NHX2jsMB3AiDht5hryAUOEifoTdCXbSh7V0My2NMq/Xbh5MEjU
       
  2182 ZT63gpgNT9lKOJ/CtHsvT99re3pX303kydn4HeyOeAg5cjf2EW1D6HOPkg9NGKhu
       
  2183 """)
       
  2184 
       
  2185 ##file deactivate.bat
       
  2186 DEACTIVATE_BAT = convert("""
       
  2187 eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q
       
  2188 FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL
       
  2189 i2dASrm4rFz9XLgAwJNbyQ==
       
  2190 """)
       
  2191 
       
  2192 ##file activate.ps1
       
  2193 ACTIVATE_PS = convert("""
       
  2194 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
       
  2280 QastYw==
       
  2281 """)
       
  2282 
       
  2283 ##file distutils-init.py
       
  2284 DISTUTILS_INIT = convert("""
       
  2285 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
       
  2307 GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ=
       
  2308 """)
       
  2309 
       
  2310 ##file distutils.cfg
       
  2311 DISTUTILS_CFG = convert("""
       
  2312 eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
       
  2313 xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
       
  2314 9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
       
  2315 """)
       
  2316 
       
  2317 ##file activate_this.py
       
  2318 ACTIVATE_THIS = convert("""
       
  2319 eJyNU01v2zAMvetXEB4K21jmDOstQA4dMGCHbeihlyEIDMWmG62yJEiKE//7kXKdpN2KzYBt8euR
       
  2320 fKSyLPs8wiEo8wh4wqZTGou4V6Hm0wJa1cSiTkJdr8+GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe
       
  2321 5a3p0cRKiAe2NtLADikftnDco0ko/SFEVgEZ8aRC5GLux7i3BpSJ6J1H+i7A2CjiHq9z7JRZuuQq
       
  2322 siwTIvpxJYCeuWaBpwZdhB+yxy/eWz+ZvVSU8C4E9FFZkyxFsvCT/ZzL8gcz9aXVE14Yyp2M+2W0
       
  2323 y7n5mp0qN+avKXvbsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCZN9UzlJr+/e/iab8WfqsmPI6pWeUPd
       
  2324 FrMsd4H/55poeO9n54COhUs+sZNEzNtg/wanpjpuqHJaxs76HtZryI/K3H7KJ/KDIhqcbJ7kI4ar
       
  2325 XL+sMgXnX0D+Te2Iy5xdP8yueSlQB/x/ED2BTAtyE3K4SYUN6AMNfbO63f4lBW3bUJPbTL+mjSxS
       
  2326 PyRfJkZRgj+VbFv+EzHFi5pKwUEepa4JslMnwkowSRCXI+m5XvEOvtuBrxHdhLalG0JofYBok6qj
       
  2327 YdN2dEngUlbC4PG60M1WEN0piu7Nq7on0mgyyUw3iV1etLo6r/81biWdQ9MWHFaePWZYaq+nmp+t
       
  2328 s3az+sj7eA0jfgPfeoN1
       
  2329 """)
       
  2330 
       
  2331 MH_MAGIC = 0xfeedface
       
  2332 MH_CIGAM = 0xcefaedfe
       
  2333 MH_MAGIC_64 = 0xfeedfacf
       
  2334 MH_CIGAM_64 = 0xcffaedfe
       
  2335 FAT_MAGIC = 0xcafebabe
       
  2336 BIG_ENDIAN = '>'
       
  2337 LITTLE_ENDIAN = '<'
       
  2338 LC_LOAD_DYLIB = 0xc
       
  2339 maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint')
       
  2340 
       
  2341 
       
  2342 class fileview(object):
       
  2343     """
       
  2344     A proxy for file-like objects that exposes a given view of a file.
       
  2345     Modified from macholib.
       
  2346     """
       
  2347 
       
  2348     def __init__(self, fileobj, start=0, size=maxint):
       
  2349         if isinstance(fileobj, fileview):
       
  2350             self._fileobj = fileobj._fileobj
       
  2351         else:
       
  2352             self._fileobj = fileobj
       
  2353         self._start = start
       
  2354         self._end = start + size
       
  2355         self._pos = 0
       
  2356 
       
  2357     def __repr__(self):
       
  2358         return '<fileview [%d, %d] %r>' % (
       
  2359             self._start, self._end, self._fileobj)
       
  2360 
       
  2361     def tell(self):
       
  2362         return self._pos
       
  2363 
       
  2364     def _checkwindow(self, seekto, op):
       
  2365         if not (self._start <= seekto <= self._end):
       
  2366             raise IOError("%s to offset %d is outside window [%d, %d]" % (
       
  2367                 op, seekto, self._start, self._end))
       
  2368 
       
  2369     def seek(self, offset, whence=0):
       
  2370         seekto = offset
       
  2371         if whence == os.SEEK_SET:
       
  2372             seekto += self._start
       
  2373         elif whence == os.SEEK_CUR:
       
  2374             seekto += self._start + self._pos
       
  2375         elif whence == os.SEEK_END:
       
  2376             seekto += self._end
       
  2377         else:
       
  2378             raise IOError("Invalid whence argument to seek: %r" % (whence,))
       
  2379         self._checkwindow(seekto, 'seek')
       
  2380         self._fileobj.seek(seekto)
       
  2381         self._pos = seekto - self._start
       
  2382 
       
  2383     def write(self, bytes):
       
  2384         here = self._start + self._pos
       
  2385         self._checkwindow(here, 'write')
       
  2386         self._checkwindow(here + len(bytes), 'write')
       
  2387         self._fileobj.seek(here, os.SEEK_SET)
       
  2388         self._fileobj.write(bytes)
       
  2389         self._pos += len(bytes)
       
  2390 
       
  2391     def read(self, size=maxint):
       
  2392         assert size >= 0
       
  2393         here = self._start + self._pos
       
  2394         self._checkwindow(here, 'read')
       
  2395         size = min(size, self._end - here)
       
  2396         self._fileobj.seek(here, os.SEEK_SET)
       
  2397         bytes = self._fileobj.read(size)
       
  2398         self._pos += len(bytes)
       
  2399         return bytes
       
  2400 
       
  2401 
       
  2402 def read_data(file, endian, num=1):
       
  2403     """
       
  2404     Read a given number of 32-bits unsigned integers from the given file
       
  2405     with the given endianness.
       
  2406     """
       
  2407     res = struct.unpack(endian + 'L' * num, file.read(num * 4))
       
  2408     if len(res) == 1:
       
  2409         return res[0]
       
  2410     return res
       
  2411 
       
  2412 
       
  2413 def mach_o_change(path, what, value):
       
  2414     """
       
  2415     Replace a given name (what) in any LC_LOAD_DYLIB command found in
       
  2416     the given binary with a new name (value), provided it's shorter.
       
  2417     """
       
  2418 
       
  2419     def do_macho(file, bits, endian):
       
  2420         # Read Mach-O header (the magic number is assumed read by the caller)
       
  2421         cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6)
       
  2422         # 64-bits header has one more field.
       
  2423         if bits == 64:
       
  2424             read_data(file, endian)
       
  2425         # The header is followed by ncmds commands
       
  2426         for n in range(ncmds):
       
  2427             where = file.tell()
       
  2428             # Read command header
       
  2429             cmd, cmdsize = read_data(file, endian, 2)
       
  2430             if cmd == LC_LOAD_DYLIB:
       
  2431                 # The first data field in LC_LOAD_DYLIB commands is the
       
  2432                 # offset of the name, starting from the beginning of the
       
  2433                 # command.
       
  2434                 name_offset = read_data(file, endian)
       
  2435                 file.seek(where + name_offset, os.SEEK_SET)
       
  2436                 # Read the NUL terminated string
       
  2437                 load = file.read(cmdsize - name_offset).decode()
       
  2438                 load = load[:load.index('\0')]
       
  2439                 # If the string is what is being replaced, overwrite it.
       
  2440                 if load == what:
       
  2441                     file.seek(where + name_offset, os.SEEK_SET)
       
  2442                     file.write(value.encode() + '\0'.encode())
       
  2443             # Seek to the next command
       
  2444             file.seek(where + cmdsize, os.SEEK_SET)
       
  2445 
       
  2446     def do_file(file, offset=0, size=maxint):
       
  2447         file = fileview(file, offset, size)
       
  2448         # Read magic number
       
  2449         magic = read_data(file, BIG_ENDIAN)
       
  2450         if magic == FAT_MAGIC:
       
  2451             # Fat binaries contain nfat_arch Mach-O binaries
       
  2452             nfat_arch = read_data(file, BIG_ENDIAN)
       
  2453             for n in range(nfat_arch):
       
  2454                 # Read arch header
       
  2455                 cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5)
       
  2456                 do_file(file, offset, size)
       
  2457         elif magic == MH_MAGIC:
       
  2458             do_macho(file, 32, BIG_ENDIAN)
       
  2459         elif magic == MH_CIGAM:
       
  2460             do_macho(file, 32, LITTLE_ENDIAN)
       
  2461         elif magic == MH_MAGIC_64:
       
  2462             do_macho(file, 64, BIG_ENDIAN)
       
  2463         elif magic == MH_CIGAM_64:
       
  2464             do_macho(file, 64, LITTLE_ENDIAN)
       
  2465 
       
  2466     assert(len(what) >= len(value))
       
  2467     do_file(open(path, 'r+b'))
       
  2468 
       
  2469 
       
  2470 if __name__ == '__main__':
       
  2471     main()
       
  2472 
       
  2473 ## TODO:
       
  2474 ## Copy python.exe.manifest
       
  2475 ## Monkeypatch distutils.sysconfig