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