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