python/virtualenv/virtualenv.py

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rwxr-xr-x

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial