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