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