source: bootstrap.py @ 35e7986bd30948a0b50f69d8aeb4e97ddbcf1a79

Revision 35e7986bd30948a0b50f69d8aeb4e97ddbcf1a79, 85.2 KB checked in by Paul Winkler <slinkp@…>, 9 months ago (diff)

Updated boostrap script, using virtualenv 1.6.4; fixes a broken upstream doctest

  • Property mode set to 100644
Line 
1#!/usr/bin/env python
2## WARNING: This file is generated
3#!/usr/bin/env python
4"""Create a "virtual" Python installation
5"""
6
7# If you change the version here, change it in setup.py
8# and docs/conf.py as well.
9virtualenv_version = "1.6.4"
10
11import base64
12import sys
13import os
14import optparse
15import re
16import shutil
17import logging
18import tempfile
19import zlib
20import errno
21import distutils.sysconfig
22try:
23    import subprocess
24except ImportError:
25    if sys.version_info <= (2, 3):
26        print('ERROR: %s' % sys.exc_info()[1])
27        print('ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.')
28        print('If you copy subprocess.py from a newer version of Python this script will probably work')
29        sys.exit(101)
30    else:
31        raise
32try:
33    set
34except NameError:
35    from sets import Set as set
36try:
37    basestring
38except NameError:
39    basestring = str
40
41join = os.path.join
42py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
43
44is_jython = sys.platform.startswith('java')
45is_pypy = hasattr(sys, 'pypy_version_info')
46is_win  = (sys.platform == 'win32')
47abiflags = getattr(sys, 'abiflags', '')
48
49if is_pypy:
50    expected_exe = 'pypy'
51elif is_jython:
52    expected_exe = 'jython'
53else:
54    expected_exe = 'python'
55
56
57REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
58                    'fnmatch', 'locale', 'encodings', 'codecs',
59                    'stat', 'UserDict', 'readline', 'copy_reg', 'types',
60                    're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
61                    'zlib']
62
63REQUIRED_FILES = ['lib-dynload', 'config']
64
65majver, minver = sys.version_info[:2]
66if majver == 2:
67    if minver >= 6:
68        REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc'])
69    if minver >= 7:
70        REQUIRED_MODULES.extend(['_weakrefset'])
71    if minver <= 3:
72        REQUIRED_MODULES.extend(['sets', '__future__'])
73elif majver == 3:
74    # Some extra modules are needed for Python 3, but different ones
75    # for different versions.
76    REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
77                             '_weakrefset', 'copyreg', 'tempfile', 'random',
78                             '__future__', 'collections', 'keyword', 'tarfile',
79                             'shutil', 'struct', 'copy'])
80    if minver >= 2:
81        REQUIRED_FILES[-1] = 'config-%s' % majver
82    if minver == 3:
83        # The whole list of 3.3 modules is reproduced below - the current
84        # uncommented ones are required for 3.3 as of now, but more may be
85        # added as 3.3 development continues.
86        REQUIRED_MODULES.extend([
87            #"aifc",
88            #"antigravity",
89            #"argparse",
90            #"ast",
91            #"asynchat",
92            #"asyncore",
93            "base64",
94            #"bdb",
95            #"binhex",
96            "bisect",
97            #"calendar",
98            #"cgi",
99            #"cgitb",
100            #"chunk",
101            #"cmd",
102            #"codeop",
103            #"code",
104            #"colorsys",
105            #"_compat_pickle",
106            #"compileall",
107            #"concurrent",
108            #"configparser",
109            #"contextlib",
110            #"cProfile",
111            #"crypt",
112            #"csv",
113            #"ctypes",
114            #"curses",
115            #"datetime",
116            #"dbm",
117            #"decimal",
118            #"difflib",
119            #"dis",
120            #"doctest",
121            #"dummy_threading",
122            "_dummy_thread",
123            #"email",
124            #"filecmp",
125            #"fileinput",
126            #"formatter",
127            #"fractions",
128            #"ftplib",
129            #"functools",
130            #"getopt",
131            #"getpass",
132            #"gettext",
133            #"glob",
134            #"gzip",
135            "hashlib",
136            "heapq",
137            "hmac",
138            #"html",
139            #"http",
140            #"idlelib",
141            #"imaplib",
142            #"imghdr",
143            #"importlib",
144            #"inspect",
145            #"json",
146            #"lib2to3",
147            #"logging",
148            #"macpath",
149            #"macurl2path",
150            #"mailbox",
151            #"mailcap",
152            #"_markupbase",
153            #"mimetypes",
154            #"modulefinder",
155            #"multiprocessing",
156            #"netrc",
157            #"nntplib",
158            #"nturl2path",
159            #"numbers",
160            #"opcode",
161            #"optparse",
162            #"os2emxpath",
163            #"pdb",
164            #"pickle",
165            #"pickletools",
166            #"pipes",
167            #"pkgutil",
168            #"platform",
169            #"plat-linux2",
170            #"plistlib",
171            #"poplib",
172            #"pprint",
173            #"profile",
174            #"pstats",
175            #"pty",
176            #"pyclbr",
177            #"py_compile",
178            #"pydoc_data",
179            #"pydoc",
180            #"_pyio",
181            #"queue",
182            #"quopri",
183            "reprlib",
184            "rlcompleter",
185            #"runpy",
186            #"sched",
187            #"shelve",
188            #"shlex",
189            #"smtpd",
190            #"smtplib",
191            #"sndhdr",
192            #"socket",
193            #"socketserver",
194            #"sqlite3",
195            #"ssl",
196            #"stringprep",
197            #"string",
198            #"_strptime",
199            #"subprocess",
200            #"sunau",
201            #"symbol",
202            #"symtable",
203            #"sysconfig",
204            #"tabnanny",
205            #"telnetlib",
206            #"test",
207            #"textwrap",
208            #"this",
209            #"_threading_local",
210            #"threading",
211            #"timeit",
212            #"tkinter",
213            #"tokenize",
214            #"token",
215            #"traceback",
216            #"trace",
217            #"tty",
218            #"turtledemo",
219            #"turtle",
220            #"unittest",
221            #"urllib",
222            #"uuid",
223            #"uu",
224            #"wave",
225            "weakref",
226            #"webbrowser",
227            #"wsgiref",
228            #"xdrlib",
229            #"xml",
230            #"xmlrpc",
231            #"zipfile",
232        ])
233
234if is_pypy:
235    # these are needed to correctly display the exceptions that may happen
236    # during the bootstrap
237    REQUIRED_MODULES.extend(['traceback', 'linecache'])
238
239class Logger(object):
240
241    """
242    Logging object for use in command-line script.  Allows ranges of
243    levels, to avoid some redundancy of displayed information.
244    """
245
246    DEBUG = logging.DEBUG
247    INFO = logging.INFO
248    NOTIFY = (logging.INFO+logging.WARN)/2
249    WARN = WARNING = logging.WARN
250    ERROR = logging.ERROR
251    FATAL = logging.FATAL
252
253    LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
254
255    def __init__(self, consumers):
256        self.consumers = consumers
257        self.indent = 0
258        self.in_progress = None
259        self.in_progress_hanging = False
260
261    def debug(self, msg, *args, **kw):
262        self.log(self.DEBUG, msg, *args, **kw)
263    def info(self, msg, *args, **kw):
264        self.log(self.INFO, msg, *args, **kw)
265    def notify(self, msg, *args, **kw):
266        self.log(self.NOTIFY, msg, *args, **kw)
267    def warn(self, msg, *args, **kw):
268        self.log(self.WARN, msg, *args, **kw)
269    def error(self, msg, *args, **kw):
270        self.log(self.WARN, msg, *args, **kw)
271    def fatal(self, msg, *args, **kw):
272        self.log(self.FATAL, msg, *args, **kw)
273    def log(self, level, msg, *args, **kw):
274        if args:
275            if kw:
276                raise TypeError(
277                    "You may give positional or keyword arguments, not both")
278        args = args or kw
279        rendered = None
280        for consumer_level, consumer in self.consumers:
281            if self.level_matches(level, consumer_level):
282                if (self.in_progress_hanging
283                    and consumer in (sys.stdout, sys.stderr)):
284                    self.in_progress_hanging = False
285                    sys.stdout.write('\n')
286                    sys.stdout.flush()
287                if rendered is None:
288                    if args:
289                        rendered = msg % args
290                    else:
291                        rendered = msg
292                    rendered = ' '*self.indent + rendered
293                if hasattr(consumer, 'write'):
294                    consumer.write(rendered+'\n')
295                else:
296                    consumer(rendered)
297
298    def start_progress(self, msg):
299        assert not self.in_progress, (
300            "Tried to start_progress(%r) while in_progress %r"
301            % (msg, self.in_progress))
302        if self.level_matches(self.NOTIFY, self._stdout_level()):
303            sys.stdout.write(msg)
304            sys.stdout.flush()
305            self.in_progress_hanging = True
306        else:
307            self.in_progress_hanging = False
308        self.in_progress = msg
309
310    def end_progress(self, msg='done.'):
311        assert self.in_progress, (
312            "Tried to end_progress without start_progress")
313        if self.stdout_level_matches(self.NOTIFY):
314            if not self.in_progress_hanging:
315                # Some message has been printed out since start_progress
316                sys.stdout.write('...' + self.in_progress + msg + '\n')
317                sys.stdout.flush()
318            else:
319                sys.stdout.write(msg + '\n')
320                sys.stdout.flush()
321        self.in_progress = None
322        self.in_progress_hanging = False
323
324    def show_progress(self):
325        """If we are in a progress scope, and no log messages have been
326        shown, write out another '.'"""
327        if self.in_progress_hanging:
328            sys.stdout.write('.')
329            sys.stdout.flush()
330
331    def stdout_level_matches(self, level):
332        """Returns true if a message at this level will go to stdout"""
333        return self.level_matches(level, self._stdout_level())
334
335    def _stdout_level(self):
336        """Returns the level that stdout runs at"""
337        for level, consumer in self.consumers:
338            if consumer is sys.stdout:
339                return level
340        return self.FATAL
341
342    def level_matches(self, level, consumer_level):
343        """
344        >>> l = Logger([])
345        >>> l.level_matches(3, 4)
346        False
347        >>> l.level_matches(3, 2)
348        True
349        >>> l.level_matches(slice(None, 3), 3)
350        False
351        >>> l.level_matches(slice(None, 3), 2)
352        True
353        >>> l.level_matches(slice(1, 3), 1)
354        True
355        >>> l.level_matches(slice(2, 3), 1)
356        False
357        """
358        if isinstance(level, slice):
359            start, stop = level.start, level.stop
360            if start is not None and start > consumer_level:
361                return False
362            if stop is not None and stop <= consumer_level:
363                return False
364            return True
365        else:
366            return level >= consumer_level
367
368    #@classmethod
369    def level_for_integer(cls, level):
370        levels = cls.LEVELS
371        if level < 0:
372            return levels[0]
373        if level >= len(levels):
374            return levels[-1]
375        return levels[level]
376
377    level_for_integer = classmethod(level_for_integer)
378
379# create a silent logger just to prevent this from being undefined
380# will be overridden with requested verbosity main() is called.
381logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
382
383def mkdir(path):
384    if not os.path.exists(path):
385        logger.info('Creating %s', path)
386        os.makedirs(path)
387    else:
388        logger.info('Directory %s already exists', path)
389
390def copyfileordir(src, dest):
391    if os.path.isdir(src):
392        shutil.copytree(src, dest, True)
393    else:
394        shutil.copy2(src, dest)
395
396def copyfile(src, dest, symlink=True):
397    if not os.path.exists(src):
398        # Some bad symlink in the src
399        logger.warn('Cannot find file %s (bad symlink)', src)
400        return
401    if os.path.exists(dest):
402        logger.debug('File %s already exists', dest)
403        return
404    if not os.path.exists(os.path.dirname(dest)):
405        logger.info('Creating parent directories for %s' % os.path.dirname(dest))
406        os.makedirs(os.path.dirname(dest))
407    if not os.path.islink(src):
408        srcpath = os.path.abspath(src)
409    else:
410        srcpath = os.readlink(src)
411    if symlink and hasattr(os, 'symlink'):
412        logger.info('Symlinking %s', dest)
413        try:
414            os.symlink(srcpath, dest)
415        except (OSError, NotImplementedError):
416            logger.info('Symlinking failed, copying to %s', dest)
417            copyfileordir(src, dest)
418    else:
419        logger.info('Copying to %s', dest)
420        copyfileordir(src, dest)
421
422def writefile(dest, content, overwrite=True):
423    if not os.path.exists(dest):
424        logger.info('Writing %s', dest)
425        f = open(dest, 'wb')
426        f.write(content.encode('utf-8'))
427        f.close()
428        return
429    else:
430        f = open(dest, 'rb')
431        c = f.read()
432        f.close()
433        if c != content:
434            if not overwrite:
435                logger.notify('File %s exists with different content; not overwriting', dest)
436                return
437            logger.notify('Overwriting %s with new content', dest)
438            f = open(dest, 'wb')
439            f.write(content.encode('utf-8'))
440            f.close()
441        else:
442            logger.info('Content %s already in place', dest)
443
444def rmtree(dir):
445    if os.path.exists(dir):
446        logger.notify('Deleting tree %s', dir)
447        shutil.rmtree(dir)
448    else:
449        logger.info('Do not need to delete %s; already gone', dir)
450
451def make_exe(fn):
452    if hasattr(os, 'chmod'):
453        oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777
454        newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777
455        os.chmod(fn, newmode)
456        logger.info('Changed mode of %s to %s', fn, oct(newmode))
457
458def _find_file(filename, dirs):
459    for dir in dirs:
460        if os.path.exists(join(dir, filename)):
461            return join(dir, filename)
462    return filename
463
464def _install_req(py_executable, unzip=False, distribute=False,
465                 search_dirs=None, never_download=False):
466
467    if search_dirs is None:
468        search_dirs = file_search_dirs()
469
470    if not distribute:
471        setup_fn = 'setuptools-0.6c11-py%s.egg' % sys.version[:3]
472        project_name = 'setuptools'
473        bootstrap_script = EZ_SETUP_PY
474        source = None
475    else:
476        setup_fn = None
477        source = 'distribute-0.6.19.tar.gz'
478        project_name = 'distribute'
479        bootstrap_script = DISTRIBUTE_SETUP_PY
480
481        # If we are running under -p, we need to remove the current
482        # directory from sys.path temporarily here, so that we
483        # definitely get the pkg_resources from the site directory of
484        # the interpreter we are running under, not the one
485        # virtualenv.py is installed under (which might lead to py2/py3
486        # incompatibility issues)
487        _prev_sys_path = sys.path
488        if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
489            sys.path = sys.path[1:]
490
491        try:
492            try:
493                # check if the global Python has distribute installed or plain
494                # setuptools
495                import pkg_resources
496                if not hasattr(pkg_resources, '_distribute'):
497                    location = os.path.dirname(pkg_resources.__file__)
498                    logger.notify("A globally installed setuptools was found (in %s)" % location)
499                    logger.notify("Use the --no-site-packages option to use distribute in "
500                                  "the virtualenv.")
501            except ImportError:
502                pass
503        finally:
504            sys.path = _prev_sys_path
505
506    if setup_fn is not None:
507        setup_fn = _find_file(setup_fn, search_dirs)
508
509    if source is not None:
510        source = _find_file(source, search_dirs)
511
512    if is_jython and os._name == 'nt':
513        # Jython's .bat sys.executable can't handle a command line
514        # argument with newlines
515        fd, ez_setup = tempfile.mkstemp('.py')
516        os.write(fd, bootstrap_script)
517        os.close(fd)
518        cmd = [py_executable, ez_setup]
519    else:
520        cmd = [py_executable, '-c', bootstrap_script]
521    if unzip:
522        cmd.append('--always-unzip')
523    env = {}
524    remove_from_env = []
525    if logger.stdout_level_matches(logger.DEBUG):
526        cmd.append('-v')
527
528    old_chdir = os.getcwd()
529    if setup_fn is not None and os.path.exists(setup_fn):
530        logger.info('Using existing %s egg: %s' % (project_name, setup_fn))
531        cmd.append(setup_fn)
532        if os.environ.get('PYTHONPATH'):
533            env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH']
534        else:
535            env['PYTHONPATH'] = setup_fn
536    else:
537        # the source is found, let's chdir
538        if source is not None and os.path.exists(source):
539            logger.info('Using existing %s egg: %s' % (project_name, source))
540            os.chdir(os.path.dirname(source))
541            # in this case, we want to be sure that PYTHONPATH is unset (not
542            # just empty, really unset), else CPython tries to import the
543            # site.py that it's in virtualenv_support
544            remove_from_env.append('PYTHONPATH')
545        else:
546            if never_download:
547                logger.fatal("Can't find any local distributions of %s to install "
548                             "and --never-download is set.  Either re-run virtualenv "
549                             "without the --never-download option, or place a %s "
550                             "distribution (%s) in one of these "
551                             "locations: %r" % (project_name, project_name, 
552                                                setup_fn or source,
553                                                search_dirs))
554                sys.exit(1)
555
556            logger.info('No %s egg found; downloading' % project_name)
557        cmd.extend(['--always-copy', '-U', project_name])
558    logger.start_progress('Installing %s...' % project_name)
559    logger.indent += 2
560    cwd = None
561    if project_name == 'distribute':
562        env['DONT_PATCH_SETUPTOOLS'] = 'true'
563
564    def _filter_ez_setup(line):
565        return filter_ez_setup(line, project_name)
566
567    if not os.access(os.getcwd(), os.W_OK):
568        cwd = tempfile.mkdtemp()
569        if source is not None and os.path.exists(source):
570            # the current working dir is hostile, let's copy the
571            # tarball to a temp dir
572            target = os.path.join(cwd, os.path.split(source)[-1])
573            shutil.copy(source, target)
574    try:
575        call_subprocess(cmd, show_stdout=False,
576                        filter_stdout=_filter_ez_setup,
577                        extra_env=env,
578                        remove_from_env=remove_from_env,
579                        cwd=cwd)
580    finally:
581        logger.indent -= 2
582        logger.end_progress()
583        if os.getcwd() != old_chdir:
584            os.chdir(old_chdir)
585        if is_jython and os._name == 'nt':
586            os.remove(ez_setup)
587
588def file_search_dirs():
589    here = os.path.dirname(os.path.abspath(__file__))
590    dirs = ['.', here,
591            join(here, 'virtualenv_support')]
592    if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
593        # Probably some boot script; just in case virtualenv is installed...
594        try:
595            import virtualenv
596        except ImportError:
597            pass
598        else:
599            dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
600    return [d for d in dirs if os.path.isdir(d)]
601
602def install_setuptools(py_executable, unzip=False,
603                       search_dirs=None, never_download=False):
604    _install_req(py_executable, unzip, 
605                 search_dirs=search_dirs, never_download=never_download)
606
607def install_distribute(py_executable, unzip=False, 
608                       search_dirs=None, never_download=False):
609    _install_req(py_executable, unzip, distribute=True, 
610                 search_dirs=search_dirs, never_download=never_download)
611
612_pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I)
613def install_pip(py_executable, search_dirs=None, never_download=False):   
614    if search_dirs is None:
615        search_dirs = file_search_dirs()
616
617    filenames = []
618    for dir in search_dirs:
619        filenames.extend([join(dir, fn) for fn in os.listdir(dir)
620                          if _pip_re.search(fn)])
621    filenames = [(os.path.basename(filename).lower(), i, filename) for i, filename in enumerate(filenames)]
622    filenames.sort()
623    filenames = [filename for basename, i, filename in filenames]
624    if not filenames:
625        filename = 'pip'
626    else:
627        filename = filenames[-1]
628    easy_install_script = 'easy_install'
629    if sys.platform == 'win32':
630        easy_install_script = 'easy_install-script.py'
631    cmd = [py_executable, join(os.path.dirname(py_executable), easy_install_script), filename]
632    if filename == 'pip':
633        if never_download:
634            logger.fatal("Can't find any local distributions of pip to install "
635                         "and --never-download is set.  Either re-run virtualenv "
636                         "without the --never-download option, or place a pip "
637                         "source distribution (zip/tar.gz/tar.bz2) in one of these "
638                         "locations: %r" % search_dirs)
639            sys.exit(1)
640        logger.info('Installing pip from network...')
641    else:
642        logger.info('Installing existing %s distribution: %s' % (
643                os.path.basename(filename), filename))
644    logger.start_progress('Installing pip...')
645    logger.indent += 2
646    def _filter_setup(line):
647        return filter_ez_setup(line, 'pip')
648    try:
649        call_subprocess(cmd, show_stdout=False,
650                        filter_stdout=_filter_setup)
651    finally:
652        logger.indent -= 2
653        logger.end_progress()
654
655def filter_ez_setup(line, project_name='setuptools'):
656    if not line.strip():
657        return Logger.DEBUG
658    if project_name == 'distribute':
659        for prefix in ('Extracting', 'Now working', 'Installing', 'Before',
660                       'Scanning', 'Setuptools', 'Egg', 'Already',
661                       'running', 'writing', 'reading', 'installing',
662                       'creating', 'copying', 'byte-compiling', 'removing',
663                       'Processing'):
664            if line.startswith(prefix):
665                return Logger.DEBUG
666        return Logger.DEBUG
667    for prefix in ['Reading ', 'Best match', 'Processing setuptools',
668                   'Copying setuptools', 'Adding setuptools',
669                   'Installing ', 'Installed ']:
670        if line.startswith(prefix):
671            return Logger.DEBUG
672    return Logger.INFO
673
674def main():
675    parser = optparse.OptionParser(
676        version=virtualenv_version,
677        usage="%prog [OPTIONS] DEST_DIR")
678
679    parser.add_option(
680        '-v', '--verbose',
681        action='count',
682        dest='verbose',
683        default=0,
684        help="Increase verbosity")
685
686    parser.add_option(
687        '-q', '--quiet',
688        action='count',
689        dest='quiet',
690        default=0,
691        help='Decrease verbosity')
692
693    parser.add_option(
694        '-p', '--python',
695        dest='python',
696        metavar='PYTHON_EXE',
697        help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
698        'interpreter to create the new environment.  The default is the interpreter that '
699        'virtualenv was installed with (%s)' % sys.executable)
700
701    parser.add_option(
702        '--clear',
703        dest='clear',
704        action='store_true',
705        help="Clear out the non-root install and start from scratch")
706
707    parser.add_option(
708        '--no-site-packages',
709        dest='no_site_packages',
710        action='store_true',
711        help="Don't give access to the global site-packages dir to the "
712             "virtual environment")
713
714    parser.add_option(
715        '--unzip-setuptools',
716        dest='unzip_setuptools',
717        action='store_true',
718        help="Unzip Setuptools or Distribute when installing it")
719
720    parser.add_option(
721        '--relocatable',
722        dest='relocatable',
723        action='store_true',
724        help='Make an EXISTING virtualenv environment relocatable.  '
725        'This fixes up scripts and makes all .pth files relative')
726
727    parser.add_option(
728        '--distribute',
729        dest='use_distribute',
730        action='store_true',
731        help='Use Distribute instead of Setuptools. Set environ variable '
732        'VIRTUALENV_USE_DISTRIBUTE to make it the default ')
733
734    default_search_dirs = file_search_dirs()
735    parser.add_option(
736        '--extra-search-dir',
737        dest="search_dirs",
738        action="append",
739        default=default_search_dirs,
740        help="Directory to look for setuptools/distribute/pip distributions in. "
741        "You can add any number of additional --extra-search-dir paths.")
742
743    parser.add_option(
744        '--never-download',
745        dest="never_download",
746        action="store_true",
747        help="Never download anything from the network.  Instead, virtualenv will fail "
748        "if local distributions of setuptools/distribute/pip are not present.")
749
750    parser.add_option(
751        '--prompt=',
752        dest='prompt',
753        help='Provides an alternative prompt prefix for this environment')
754
755    if 'extend_parser' in globals():
756        extend_parser(parser)
757
758    options, args = parser.parse_args()
759
760    global logger
761
762    if 'adjust_options' in globals():
763        adjust_options(options, args)
764
765    verbosity = options.verbose - options.quiet
766    logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)])
767
768    if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
769        env = os.environ.copy()
770        interpreter = resolve_interpreter(options.python)
771        if interpreter == sys.executable:
772            logger.warn('Already using interpreter %s' % interpreter)
773        else:
774            logger.notify('Running virtualenv with interpreter %s' % interpreter)
775            env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
776            file = __file__
777            if file.endswith('.pyc'):
778                file = file[:-1]
779            popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
780            raise SystemExit(popen.wait())
781
782    if not args:
783        print('You must provide a DEST_DIR')
784        parser.print_help()
785        sys.exit(2)
786    if len(args) > 1:
787        print('There must be only one argument: DEST_DIR (you gave %s)' % (
788            ' '.join(args)))
789        parser.print_help()
790        sys.exit(2)
791
792    home_dir = args[0]
793
794    if os.environ.get('WORKING_ENV'):
795        logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
796        logger.fatal('Please deactivate your workingenv, then re-run this script')
797        sys.exit(3)
798
799    if 'PYTHONHOME' in os.environ:
800        logger.warn('PYTHONHOME is set.  You *must* activate the virtualenv before using it')
801        del os.environ['PYTHONHOME']
802
803    if options.relocatable:
804        make_environment_relocatable(home_dir)
805        return
806
807    create_environment(home_dir, site_packages=not options.no_site_packages, clear=options.clear,
808                       unzip_setuptools=options.unzip_setuptools,
809                       use_distribute=options.use_distribute or majver > 2,
810                       prompt=options.prompt,
811                       search_dirs=options.search_dirs,
812                       never_download=options.never_download)
813    if 'after_install' in globals():
814        after_install(options, home_dir)
815
816def call_subprocess(cmd, show_stdout=True,
817                    filter_stdout=None, cwd=None,
818                    raise_on_returncode=True, extra_env=None,
819                    remove_from_env=None):
820    cmd_parts = []
821    for part in cmd:
822        if len(part) > 45:
823            part = part[:20]+"..."+part[-20:]
824        if ' ' in part or '\n' in part or '"' in part or "'" in part:
825            part = '"%s"' % part.replace('"', '\\"')
826        cmd_parts.append(part)
827    cmd_desc = ' '.join(cmd_parts)
828    if show_stdout:
829        stdout = None
830    else:
831        stdout = subprocess.PIPE
832    logger.debug("Running command %s" % cmd_desc)
833    if extra_env or remove_from_env:
834        env = os.environ.copy()
835        if extra_env:
836            env.update(extra_env)
837        if remove_from_env:
838            for varname in remove_from_env:
839                env.pop(varname, None)
840    else:
841        env = None
842    try:
843        proc = subprocess.Popen(
844            cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
845            cwd=cwd, env=env)
846    except Exception:
847        e = sys.exc_info()[1]
848        logger.fatal(
849            "Error %s while executing command %s" % (e, cmd_desc))
850        raise
851    all_output = []
852    if stdout is not None:
853        stdout = proc.stdout
854        encoding = sys.getdefaultencoding()
855        while 1:
856            line = stdout.readline().decode(encoding)
857            if not line:
858                break
859            line = line.rstrip()
860            all_output.append(line)
861            if filter_stdout:
862                level = filter_stdout(line)
863                if isinstance(level, tuple):
864                    level, line = level
865                logger.log(level, line)
866                if not logger.stdout_level_matches(level):
867                    logger.show_progress()
868            else:
869                logger.info(line)
870    else:
871        proc.communicate()
872    proc.wait()
873    if proc.returncode:
874        if raise_on_returncode:
875            if all_output:
876                logger.notify('Complete output from command %s:' % cmd_desc)
877                logger.notify('\n'.join(all_output) + '\n----------------------------------------')
878            raise OSError(
879                "Command %s failed with error code %s"
880                % (cmd_desc, proc.returncode))
881        else:
882            logger.warn(
883                "Command %s had error code %s"
884                % (cmd_desc, proc.returncode))
885
886
887def create_environment(home_dir, site_packages=True, clear=False,
888                       unzip_setuptools=False, use_distribute=False,
889                       prompt=None, search_dirs=None, never_download=False):
890    """
891    Creates a new environment in ``home_dir``.
892
893    If ``site_packages`` is true (the default) then the global
894    ``site-packages/`` directory will be on the path.
895
896    If ``clear`` is true (default False) then the environment will
897    first be cleared.
898    """
899    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
900
901    py_executable = os.path.abspath(install_python(
902        home_dir, lib_dir, inc_dir, bin_dir,
903        site_packages=site_packages, clear=clear))
904
905    install_distutils(home_dir)
906
907    if use_distribute or os.environ.get('VIRTUALENV_USE_DISTRIBUTE'):
908        install_distribute(py_executable, unzip=unzip_setuptools, 
909                           search_dirs=search_dirs, never_download=never_download)
910    else:
911        install_setuptools(py_executable, unzip=unzip_setuptools, 
912                           search_dirs=search_dirs, never_download=never_download)
913
914    install_pip(py_executable, search_dirs=search_dirs, never_download=never_download)
915
916    install_activate(home_dir, bin_dir, prompt)
917
918def path_locations(home_dir):
919    """Return the path locations for the environment (where libraries are,
920    where scripts go, etc)"""
921    # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
922    # prefix arg is broken: http://bugs.python.org/issue3386
923    if sys.platform == 'win32':
924        # Windows has lots of problems with executables with spaces in
925        # the name; this function will remove them (using the ~1
926        # format):
927        mkdir(home_dir)
928        if ' ' in home_dir:
929            try:
930                import win32api
931            except ImportError:
932                print('Error: the path "%s" has a space in it' % home_dir)
933                print('To handle these kinds of paths, the win32api module must be installed:')
934                print('  http://sourceforge.net/projects/pywin32/')
935                sys.exit(3)
936            home_dir = win32api.GetShortPathName(home_dir)
937        lib_dir = join(home_dir, 'Lib')
938        inc_dir = join(home_dir, 'Include')
939        bin_dir = join(home_dir, 'Scripts')
940    elif is_jython:
941        lib_dir = join(home_dir, 'Lib')
942        inc_dir = join(home_dir, 'Include')
943        bin_dir = join(home_dir, 'bin')
944    elif is_pypy:
945        lib_dir = home_dir
946        inc_dir = join(home_dir, 'include')
947        bin_dir = join(home_dir, 'bin')
948    else:
949        lib_dir = join(home_dir, 'lib', py_version)
950        inc_dir = join(home_dir, 'include', py_version + abiflags)
951        bin_dir = join(home_dir, 'bin')
952    return home_dir, lib_dir, inc_dir, bin_dir
953
954
955def change_prefix(filename, dst_prefix):
956    prefixes = [sys.prefix]
957
958    if sys.platform == "darwin":
959        prefixes.extend((
960            os.path.join("/Library/Python", sys.version[:3], "site-packages"),
961            os.path.join(sys.prefix, "Extras", "lib", "python"),
962            os.path.join("~", "Library", "Python", sys.version[:3], "site-packages")))
963
964    if hasattr(sys, 'real_prefix'):
965        prefixes.append(sys.real_prefix)
966    prefixes = list(map(os.path.abspath, prefixes))
967    filename = os.path.abspath(filename)
968    for src_prefix in prefixes:
969        if filename.startswith(src_prefix):
970            _, relpath = filename.split(src_prefix, 1)
971            assert relpath[0] == os.sep
972            relpath = relpath[1:]
973            return join(dst_prefix, relpath)
974    assert False, "Filename %s does not start with any of these prefixes: %s" % \
975        (filename, prefixes)
976
977def copy_required_modules(dst_prefix):
978    import imp
979    for modname in REQUIRED_MODULES:
980        if modname in sys.builtin_module_names:
981            logger.info("Ignoring built-in bootstrap module: %s" % modname)
982            continue
983        try:
984            f, filename, _ = imp.find_module(modname)
985        except ImportError:
986            logger.info("Cannot import bootstrap module: %s" % modname)
987        else:
988            if f is not None:
989                f.close()
990            dst_filename = change_prefix(filename, dst_prefix)
991            copyfile(filename, dst_filename)
992            if filename.endswith('.pyc'):
993                pyfile = filename[:-1]
994                if os.path.exists(pyfile):
995                    copyfile(pyfile, dst_filename[:-1])
996
997
998def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
999    """Install just the base environment, no distutils patches etc"""
1000    if sys.executable.startswith(bin_dir):
1001        print('Please use the *system* python to run this script')
1002        return
1003
1004    if clear:
1005        rmtree(lib_dir)
1006        ## FIXME: why not delete it?
1007        ## Maybe it should delete everything with #!/path/to/venv/python in it
1008        logger.notify('Not deleting %s', bin_dir)
1009
1010    if hasattr(sys, 'real_prefix'):
1011        logger.notify('Using real prefix %r' % sys.real_prefix)
1012        prefix = sys.real_prefix
1013    else:
1014        prefix = sys.prefix
1015    mkdir(lib_dir)
1016    fix_lib64(lib_dir)
1017    fix_local_scheme(home_dir)
1018    stdlib_dirs = [os.path.dirname(os.__file__)]
1019    if sys.platform == 'win32':
1020        stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
1021    elif sys.platform == 'darwin':
1022        stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
1023    if hasattr(os, 'symlink'):
1024        logger.info('Symlinking Python bootstrap modules')
1025    else:
1026        logger.info('Copying Python bootstrap modules')
1027    logger.indent += 2
1028    try:
1029        # copy required files...
1030        for stdlib_dir in stdlib_dirs:
1031            if not os.path.isdir(stdlib_dir):
1032                continue
1033            for fn in os.listdir(stdlib_dir):
1034                bn = os.path.splitext(fn)[0]
1035                if fn != 'site-packages' and bn in REQUIRED_FILES:
1036                    copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
1037        # ...and modules
1038        copy_required_modules(home_dir)
1039    finally:
1040        logger.indent -= 2
1041    mkdir(join(lib_dir, 'site-packages'))
1042    import site
1043    site_filename = site.__file__
1044    if site_filename.endswith('.pyc'):
1045        site_filename = site_filename[:-1]
1046    elif site_filename.endswith('$py.class'):
1047        site_filename = site_filename.replace('$py.class', '.py')
1048    site_filename_dst = change_prefix(site_filename, home_dir)
1049    site_dir = os.path.dirname(site_filename_dst)
1050    writefile(site_filename_dst, SITE_PY)
1051    writefile(join(site_dir, 'orig-prefix.txt'), prefix)
1052    site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
1053    if not site_packages:
1054        writefile(site_packages_filename, '')
1055    else:
1056        if os.path.exists(site_packages_filename):
1057            logger.info('Deleting %s' % site_packages_filename)
1058            os.unlink(site_packages_filename)
1059
1060    if is_pypy or is_win:
1061        stdinc_dir = join(prefix, 'include')
1062    else:
1063        stdinc_dir = join(prefix, 'include', py_version + abiflags)
1064    if os.path.exists(stdinc_dir):
1065        copyfile(stdinc_dir, inc_dir)
1066    else:
1067        logger.debug('No include dir %s' % stdinc_dir)
1068
1069    # pypy never uses exec_prefix, just ignore it
1070    if sys.exec_prefix != prefix and not is_pypy:
1071        if sys.platform == 'win32':
1072            exec_dir = join(sys.exec_prefix, 'lib')
1073        elif is_jython:
1074            exec_dir = join(sys.exec_prefix, 'Lib')
1075        else:
1076            exec_dir = join(sys.exec_prefix, 'lib', py_version)
1077        for fn in os.listdir(exec_dir):
1078            copyfile(join(exec_dir, fn), join(lib_dir, fn))
1079
1080    if is_jython:
1081        # Jython has either jython-dev.jar and javalib/ dir, or just
1082        # jython.jar
1083        for name in 'jython-dev.jar', 'javalib', 'jython.jar':
1084            src = join(prefix, name)
1085            if os.path.exists(src):
1086                copyfile(src, join(home_dir, name))
1087        # XXX: registry should always exist after Jython 2.5rc1
1088        src = join(prefix, 'registry')
1089        if os.path.exists(src):
1090            copyfile(src, join(home_dir, 'registry'), symlink=False)
1091        copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
1092                 symlink=False)
1093
1094    mkdir(bin_dir)
1095    py_executable = join(bin_dir, os.path.basename(sys.executable))
1096    if 'Python.framework' in prefix:
1097        if re.search(r'/Python(?:-32|-64)*$', py_executable):
1098            # The name of the python executable is not quite what
1099            # we want, rename it.
1100            py_executable = os.path.join(
1101                    os.path.dirname(py_executable), 'python')
1102
1103    logger.notify('New %s executable in %s', expected_exe, py_executable)
1104    if sys.executable != py_executable:
1105        ## FIXME: could I just hard link?
1106        executable = sys.executable
1107        if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'):
1108            # Cygwin misreports sys.executable sometimes
1109            executable += '.exe'
1110            py_executable += '.exe'
1111            logger.info('Executable actually exists in %s' % executable)
1112        shutil.copyfile(executable, py_executable)
1113        make_exe(py_executable)
1114        if sys.platform == 'win32' or sys.platform == 'cygwin':
1115            pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
1116            if os.path.exists(pythonw):
1117                logger.info('Also created pythonw.exe')
1118                shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
1119        if is_pypy:
1120            # make a symlink python --> pypy-c
1121            python_executable = os.path.join(os.path.dirname(py_executable), 'python')
1122            logger.info('Also created executable %s' % python_executable)
1123            copyfile(py_executable, python_executable)
1124
1125    if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
1126        secondary_exe = os.path.join(os.path.dirname(py_executable),
1127                                     expected_exe)
1128        py_executable_ext = os.path.splitext(py_executable)[1]
1129        if py_executable_ext == '.exe':
1130            # python2.4 gives an extension of '.4' :P
1131            secondary_exe += py_executable_ext
1132        if os.path.exists(secondary_exe):
1133            logger.warn('Not overwriting existing %s script %s (you must use %s)'
1134                        % (expected_exe, secondary_exe, py_executable))
1135        else:
1136            logger.notify('Also creating executable in %s' % secondary_exe)
1137            shutil.copyfile(sys.executable, secondary_exe)
1138            make_exe(secondary_exe)
1139
1140    if 'Python.framework' in prefix:
1141        logger.debug('MacOSX Python framework detected')
1142
1143        # Make sure we use the the embedded interpreter inside
1144        # the framework, even if sys.executable points to
1145        # the stub executable in ${sys.prefix}/bin
1146        # See http://groups.google.com/group/python-virtualenv/
1147        #                              browse_thread/thread/17cab2f85da75951
1148        original_python = os.path.join(
1149            prefix, 'Resources/Python.app/Contents/MacOS/Python')
1150        shutil.copy(original_python, py_executable)
1151
1152        # Copy the framework's dylib into the virtual
1153        # environment
1154        virtual_lib = os.path.join(home_dir, '.Python')
1155
1156        if os.path.exists(virtual_lib):
1157            os.unlink(virtual_lib)
1158        copyfile(
1159            os.path.join(prefix, 'Python'),
1160            virtual_lib)
1161
1162        # And then change the install_name of the copied python executable
1163        try:
1164            call_subprocess(
1165                ["install_name_tool", "-change",
1166                 os.path.join(prefix, 'Python'),
1167                 '@executable_path/../.Python',
1168                 py_executable])
1169        except:
1170            logger.fatal(
1171                "Could not call install_name_tool -- you must have Apple's development tools installed")
1172            raise
1173
1174        # Some tools depend on pythonX.Y being present
1175        py_executable_version = '%s.%s' % (
1176            sys.version_info[0], sys.version_info[1])
1177        if not py_executable.endswith(py_executable_version):
1178            # symlinking pythonX.Y > python
1179            pth = py_executable + '%s.%s' % (
1180                    sys.version_info[0], sys.version_info[1])
1181            if os.path.exists(pth):
1182                os.unlink(pth)
1183            os.symlink('python', pth)
1184        else:
1185            # reverse symlinking python -> pythonX.Y (with --python)
1186            pth = join(bin_dir, 'python')
1187            if os.path.exists(pth):
1188                os.unlink(pth)
1189            os.symlink(os.path.basename(py_executable), pth)
1190
1191    if sys.platform == 'win32' and ' ' in py_executable:
1192        # There's a bug with subprocess on Windows when using a first
1193        # argument that has a space in it.  Instead we have to quote
1194        # the value:
1195        py_executable = '"%s"' % py_executable
1196    cmd = [py_executable, '-c', 'import sys; print(sys.prefix)']
1197    logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
1198    try:
1199        proc = subprocess.Popen(cmd,
1200                            stdout=subprocess.PIPE)
1201        proc_stdout, proc_stderr = proc.communicate()
1202    except OSError:
1203        e = sys.exc_info()[1]
1204        if e.errno == errno.EACCES:
1205            logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e))
1206            sys.exit(100)
1207        else:
1208          raise e
1209
1210    proc_stdout = proc_stdout.strip().decode(sys.getdefaultencoding())
1211    proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
1212    if proc_stdout != os.path.normcase(os.path.abspath(home_dir)):
1213        logger.fatal(
1214            'ERROR: The executable %s is not functioning' % py_executable)
1215        logger.fatal(
1216            'ERROR: It thinks sys.prefix is %r (should be %r)'
1217            % (proc_stdout, os.path.normcase(os.path.abspath(home_dir))))
1218        logger.fatal(
1219            'ERROR: virtualenv is not compatible with this system or executable')
1220        if sys.platform == 'win32':
1221            logger.fatal(
1222                'Note: some Windows users have reported this error when they installed Python for "Only this user".  The problem may be resolvable if you install Python "For all users".  (See https://bugs.launchpad.net/virtualenv/+bug/352844)')
1223        sys.exit(100)
1224    else:
1225        logger.info('Got sys.prefix result: %r' % proc_stdout)
1226
1227    pydistutils = os.path.expanduser('~/.pydistutils.cfg')
1228    if os.path.exists(pydistutils):
1229        logger.notify('Please make sure you remove any previous custom paths from '
1230                      'your %s file.' % pydistutils)
1231    ## FIXME: really this should be calculated earlier
1232    return py_executable
1233
1234def install_activate(home_dir, bin_dir, prompt=None):
1235    if sys.platform == 'win32' or is_jython and os._name == 'nt':
1236        files = {'activate.bat': ACTIVATE_BAT,
1237                 'deactivate.bat': DEACTIVATE_BAT}
1238        if os.environ.get('OS') == 'Windows_NT' and os.environ.get('OSTYPE') == 'cygwin':
1239            files['activate'] = ACTIVATE_SH
1240    else:
1241        files = {'activate': ACTIVATE_SH}
1242
1243        # suppling activate.fish in addition to, not instead of, the
1244        # bash script support.
1245        files['activate.fish'] = ACTIVATE_FISH
1246
1247        # same for csh/tcsh support...
1248        files['activate.csh'] = ACTIVATE_CSH
1249
1250
1251
1252    files['activate_this.py'] = ACTIVATE_THIS
1253    vname = os.path.basename(os.path.abspath(home_dir))
1254    for name, content in files.items():
1255        content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
1256        content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname)
1257        content = content.replace('__VIRTUAL_ENV__', os.path.abspath(home_dir))
1258        content = content.replace('__VIRTUAL_NAME__', vname)
1259        content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
1260        writefile(os.path.join(bin_dir, name), content)
1261
1262def install_distutils(home_dir):
1263    distutils_path = change_prefix(distutils.__path__[0], home_dir)
1264    mkdir(distutils_path)
1265    ## FIXME: maybe this prefix setting should only be put in place if
1266    ## there's a local distutils.cfg with a prefix setting?
1267    home_dir = os.path.abspath(home_dir)
1268    ## FIXME: this is breaking things, removing for now:
1269    #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
1270    writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
1271    writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
1272
1273def fix_local_scheme(home_dir):
1274    """
1275    Platforms that use the "posix_local" install scheme (like Ubuntu with
1276    Python 2.7) need to be given an additional "local" location, sigh.
1277    """
1278    try:
1279        import sysconfig
1280    except ImportError:
1281        pass
1282    else:
1283        if sysconfig._get_default_scheme() == 'posix_local':
1284            local_path = os.path.join(home_dir, 'local')
1285            if not os.path.exists(local_path):
1286                os.symlink(os.path.abspath(home_dir), local_path)
1287
1288def fix_lib64(lib_dir):
1289    """
1290    Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
1291    instead of lib/pythonX.Y.  If this is such a platform we'll just create a
1292    symlink so lib64 points to lib
1293    """
1294    if [p for p in distutils.sysconfig.get_config_vars().values()
1295        if isinstance(p, basestring) and 'lib64' in p]:
1296        logger.debug('This system uses lib64; symlinking lib64 to lib')
1297        assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
1298            "Unexpected python lib dir: %r" % lib_dir)
1299        lib_parent = os.path.dirname(lib_dir)
1300        assert os.path.basename(lib_parent) == 'lib', (
1301            "Unexpected parent dir: %r" % lib_parent)
1302        copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64'))
1303
1304def resolve_interpreter(exe):
1305    """
1306    If the executable given isn't an absolute path, search $PATH for the interpreter
1307    """
1308    if os.path.abspath(exe) != exe:
1309        paths = os.environ.get('PATH', '').split(os.pathsep)
1310        for path in paths:
1311            if os.path.exists(os.path.join(path, exe)):
1312                exe = os.path.join(path, exe)
1313                break
1314    if not os.path.exists(exe):
1315        logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
1316        raise SystemExit(3)
1317    if not is_executable(exe):
1318        logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
1319        raise SystemExit(3)
1320    return exe
1321
1322def is_executable(exe):
1323    """Checks a file is executable"""
1324    return os.access(exe, os.X_OK)
1325
1326############################################################
1327## Relocating the environment:
1328
1329def make_environment_relocatable(home_dir):
1330    """
1331    Makes the already-existing environment use relative paths, and takes out
1332    the #!-based environment selection in scripts.
1333    """
1334    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
1335    activate_this = os.path.join(bin_dir, 'activate_this.py')
1336    if not os.path.exists(activate_this):
1337        logger.fatal(
1338            'The environment doesn\'t have a file %s -- please re-run virtualenv '
1339            'on this environment to update it' % activate_this)
1340    fixup_scripts(home_dir)
1341    fixup_pth_and_egg_link(home_dir)
1342    ## FIXME: need to fix up distutils.cfg
1343
1344OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
1345                  'activate', 'activate.bat', 'activate_this.py']
1346
1347def fixup_scripts(home_dir):
1348    # This is what we expect at the top of scripts:
1349    shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
1350    # This is what we'll put:
1351    new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
1352    activate = "import os; activate_this=os.path.join(os.path.dirname(__file__), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this"
1353    if sys.platform == 'win32':
1354        bin_suffix = 'Scripts'
1355    else:
1356        bin_suffix = 'bin'
1357    bin_dir = os.path.join(home_dir, bin_suffix)
1358    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
1359    for filename in os.listdir(bin_dir):
1360        filename = os.path.join(bin_dir, filename)
1361        if not os.path.isfile(filename):
1362            # ignore subdirs, e.g. .svn ones.
1363            continue
1364        f = open(filename, 'rb')
1365        lines = f.readlines()
1366        f.close()
1367        if not lines:
1368            logger.warn('Script %s is an empty file' % filename)
1369            continue
1370        if not lines[0].strip().startswith(shebang):
1371            if os.path.basename(filename) in OK_ABS_SCRIPTS:
1372                logger.debug('Cannot make script %s relative' % filename)
1373            elif lines[0].strip() == new_shebang:
1374                logger.info('Script %s has already been made relative' % filename)
1375            else:
1376                logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
1377                            % (filename, shebang))
1378            continue
1379        logger.notify('Making script %s relative' % filename)
1380        lines = [new_shebang+'\n', activate+'\n'] + lines[1:]
1381        f = open(filename, 'wb')
1382        f.writelines(lines)
1383        f.close()
1384
1385def fixup_pth_and_egg_link(home_dir, sys_path=None):
1386    """Makes .pth and .egg-link files use relative paths"""
1387    home_dir = os.path.normcase(os.path.abspath(home_dir))
1388    if sys_path is None:
1389        sys_path = sys.path
1390    for path in sys_path:
1391        if not path:
1392            path = '.'
1393        if not os.path.isdir(path):
1394            continue
1395        path = os.path.normcase(os.path.abspath(path))
1396        if not path.startswith(home_dir):
1397            logger.debug('Skipping system (non-environment) directory %s' % path)
1398            continue
1399        for filename in os.listdir(path):
1400            filename = os.path.join(path, filename)
1401            if filename.endswith('.pth'):
1402                if not os.access(filename, os.W_OK):
1403                    logger.warn('Cannot write .pth file %s, skipping' % filename)
1404                else:
1405                    fixup_pth_file(filename)
1406            if filename.endswith('.egg-link'):
1407                if not os.access(filename, os.W_OK):
1408                    logger.warn('Cannot write .egg-link file %s, skipping' % filename)
1409                else:
1410                    fixup_egg_link(filename)
1411
1412def fixup_pth_file(filename):
1413    lines = []
1414    prev_lines = []
1415    f = open(filename)
1416    prev_lines = f.readlines()
1417    f.close()
1418    for line in prev_lines:
1419        line = line.strip()
1420        if (not line or line.startswith('#') or line.startswith('import ')
1421            or os.path.abspath(line) != line):
1422            lines.append(line)
1423        else:
1424            new_value = make_relative_path(filename, line)
1425            if line != new_value:
1426                logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
1427            lines.append(new_value)
1428    if lines == prev_lines:
1429        logger.info('No changes to .pth file %s' % filename)
1430        return
1431    logger.notify('Making paths in .pth file %s relative' % filename)
1432    f = open(filename, 'w')
1433    f.write('\n'.join(lines) + '\n')
1434    f.close()
1435
1436def fixup_egg_link(filename):
1437    f = open(filename)
1438    link = f.read().strip()
1439    f.close()
1440    if os.path.abspath(link) != link:
1441        logger.debug('Link in %s already relative' % filename)
1442        return
1443    new_link = make_relative_path(filename, link)
1444    logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
1445    f = open(filename, 'w')
1446    f.write(new_link)
1447    f.close()
1448
1449def make_relative_path(source, dest, dest_is_directory=True):
1450    """
1451    Make a filename relative, where the filename is dest, and it is
1452    being referred to from the filename source.
1453
1454        >>> make_relative_path('/usr/share/something/a-file.pth',
1455        ...                    '/usr/share/another-place/src/Directory')
1456        '../another-place/src/Directory'
1457        >>> make_relative_path('/usr/share/something/a-file.pth',
1458        ...                    '/home/user/src/Directory')
1459        '../../../home/user/src/Directory'
1460        >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
1461        './'
1462    """
1463    source = os.path.dirname(source)
1464    if not dest_is_directory:
1465        dest_filename = os.path.basename(dest)
1466        dest = os.path.dirname(dest)
1467    dest = os.path.normpath(os.path.abspath(dest))
1468    source = os.path.normpath(os.path.abspath(source))
1469    dest_parts = dest.strip(os.path.sep).split(os.path.sep)
1470    source_parts = source.strip(os.path.sep).split(os.path.sep)
1471    while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
1472        dest_parts.pop(0)
1473        source_parts.pop(0)
1474    full_parts = ['..']*len(source_parts) + dest_parts
1475    if not dest_is_directory:
1476        full_parts.append(dest_filename)
1477    if not full_parts:
1478        # Special case for the current directory (otherwise it'd be '')
1479        return './'
1480    return os.path.sep.join(full_parts)
1481
1482
1483
1484############################################################
1485## Bootstrap script creation:
1486
1487def create_bootstrap_script(extra_text, python_version=''):
1488    """
1489    Creates a bootstrap script, which is like this script but with
1490    extend_parser, adjust_options, and after_install hooks.
1491
1492    This returns a string that (written to disk of course) can be used
1493    as a bootstrap script with your own customizations.  The script
1494    will be the standard virtualenv.py script, with your extra text
1495    added (your extra text should be Python code).
1496
1497    If you include these functions, they will be called:
1498
1499    ``extend_parser(optparse_parser)``:
1500        You can add or remove options from the parser here.
1501
1502    ``adjust_options(options, args)``:
1503        You can change options here, or change the args (if you accept
1504        different kinds of arguments, be sure you modify ``args`` so it is
1505        only ``[DEST_DIR]``).
1506
1507    ``after_install(options, home_dir)``:
1508
1509        After everything is installed, this function is called.  This
1510        is probably the function you are most likely to use.  An
1511        example would be::
1512
1513            def after_install(options, home_dir):
1514                subprocess.call([join(home_dir, 'bin', 'easy_install'),
1515                                 'MyPackage'])
1516                subprocess.call([join(home_dir, 'bin', 'my-package-script'),
1517                                 'setup', home_dir])
1518
1519        This example immediately installs a package, and runs a setup
1520        script from that package.
1521
1522    If you provide something like ``python_version='2.4'`` then the
1523    script will start with ``#!/usr/bin/env python2.4`` instead of
1524    ``#!/usr/bin/env python``.  You can use this when the script must
1525    be run with a particular Python version.
1526    """
1527    filename = __file__
1528    if filename.endswith('.pyc'):
1529        filename = filename[:-1]
1530    f = open(filename, 'rb')
1531    content = f.read()
1532    f.close()
1533    py_exe = 'python%s' % python_version
1534    content = (('#!/usr/bin/env %s\n' % py_exe)
1535               + '## WARNING: This file is generated\n'
1536               + content)
1537    return content.replace('##EXT' 'END##', extra_text)
1538
1539import os, subprocess
1540
1541def after_install(options, home_dir):
1542    def call(*args):
1543        retcode = subprocess.call(*args)
1544        if retcode:
1545            sys.stderr.write("Exit status %d from command args %s\n" % (retcode, args))
1546            sys.exit(retcode)
1547
1548    call([join(home_dir, 'bin', 'easy_install'), 'virtualenv>=1.6.1'])
1549    call([join(home_dir, 'bin', 'easy_install'), '--upgrade', 'pip'])
1550    call([join(home_dir, 'bin', 'easy_install'), 'paver'])
1551
1552    source_root = os.path.dirname(__file__)
1553    pavement_file = join(source_root, 'obadmin', 'obadmin', 'pavement.py')
1554    call([join(home_dir, 'bin', 'paver'), '-f', pavement_file,  'post_bootstrap'])
1555
1556    # link source code
1557    if not os.path.abspath(source_root).startswith(os.path.abspath(home_dir)):
1558        source_link = join(home_dir, 'src', 'openblock')
1559        print "symlinking openblock source in %s to %s" % (source_root, source_link)
1560        copyfile(source_root, source_link, symlink=True)
1561
1562
1563def adjust_options(options, args):
1564    # Sanity-checking Python version here b/c we want to do this early and
1565    # there's no more appropriate hook in a virtualenv bootstrap
1566    # script.
1567    import sys
1568    if not ((2, 6) <= sys.version_info[:2] < (3, 0)):
1569        raise EnvironmentError(
1570            "Incompatible Python version, we need Python >= 2.6"
1571            " and less than 3.0.")
1572    # assume build in place unless otherwise specified
1573    if len(args) == 0:
1574        args[:] = ['./']
1575
1576
1577def convert(s):
1578    b = base64.b64decode(s.encode('ascii'))
1579    return zlib.decompress(b).decode('utf-8')
1580   
1581##file site.py
1582SITE_PY = convert("""
1583eJzVPP1z2zaWv/OvwMqTIZXKdD66nR2n7o2TOK3v3MTbpLO5dT06SoIk1hTJEqQV7c3d337vAwAB
1584kvLHdvvDaTKxRAIPDw/vGw8YjUanZSnzhdgUiyaTQsmkmq9FmdRrJZZFJep1Wi0Oy6Sqd/B0fpOs
1585pBJ1IdROxdgqDoKnv/MTPBWf1qkyKMC3pKmLTVKn8yTLdiLdlEVVy4VYNFWar0Sap3WaZOk/oEWR
1586x+Lp78cgOM8FzDxLZSVuZaUArhLFUlzu6nWRi6gpcc7P4z8nL8cToeZVWtbQoNI4A0XWSR3kUi4A
1587TWjZKCBlWstDVcp5ukzntuG2aLKFKLNkLsV//RdPjZqGYaCKjdyuZSVFDsgATAmwSsQDvqaVmBcL
1588GQvxWs4THICft8QKGNoE10whGfNCZEW+gjnlci6VSqqdiGZNTYAIZbEoAKcUMKjTLAu2RXWjxrCk
1589tB5beCQSZg9/MsweME8cv885gOOHPPg5T79MGDZwD4Kr18w2lVymX0SCYOGn/CLnU/0sSpdikS6X
1590QIO8HmOTgBFQIktnRyUtx7d6hb47IqwsVyYwhkSUuTG/pB5xcF6LJFPAtk2JNFKE+Vs5S5McqJHf
1591wnAAEUgaDI2zSFVtx6HZiQIAVLiONUjJRolok6Q5MOuPyZzQ/luaL4qtGhMFYLWU+LVRtTv/aIAA
15920NohwCTAxTKr2eRZeiOz3RgQ+ATYV1I1WY0CsUgrOa+LKpWKAABqOyG/ANITkVRSk5A508jthOhP
1593NElzXFgUMBR4fIkkWaarpiIJE8sUOBe44t2Hn8Tbs9fnp+81jxlgLLOrDeAMUGihHZxgAHHUqOoo
1594K0Cg4+AC/4hksUAhW+H4gFfb4OjelQ4imHsZd/s4Cw5k14urh4E51qBMaKyA+v03dJmoNdDnf+5Z
15957yA43UcVmjh/264LkMk82UixTpi/kDOCbzWc7+KyXr8CblAIpwZSKVwcRDBFeEASl2ZRkUtRAotl
1596aS7HAVBoRm39VQRWeF/kh7TWHU4ACFWQw0vn2ZhGzCVMtA/rFeoL03hHM9NNArvOm6IixQH8n89J
1597F2VJfkM4KmIo/jaTqzTPESHkhSA8CGlgdZMCJy5icUGtSC+YRiJk7cUtUSQa4CVkOuBJ+SXZlJmc
1598sPiibr1bjdBgshZmrTPmOGhZk3qlVWunOsh7L+LPHa4jNOt1JQF4M/OEblkUEzEDnU3YlMmGxave
1599FsQ5wYA8USfkCWoJffE7UPRUqWYj7UvkFdAsxFDBssiyYgskOw4CIQ6wkTHKPnPCW3gH/wNc/D+T
16009XwdBM5IFrAGhcjvA4VAwCTIXHO1RsLjNs3KXSWT5qwpimohKxrqYcQ+YsQf2BjnGrwvam3UeLq4
1601ysUmrVElzbTJTNni5WHN+vEVzxumAZZbEc1M05ZOG5xeVq6TmTQuyUwuURL0Ir2yyw5jBgNjki2u
1602xYatDLwDssiULciwYkGls6wlOQEAg4UvydOyyaiRQgYTCQy0KQn+JkGTXmhnCdibzXKAConN9xzs
1603D+D2DxCj7ToF+swBAmgY1FKwfLO0rtBBaPVR4Bt905/HB049X2rbxEMukzTTVj7Jg3N6eFZVJL5z
1604WWKviSaGghnmNbp2qxzoiGI+Go2CwLhDO2W+Fiqoq90xsIIw40ynsyZFwzedoqnXP1TAowhnYK+b
1605bWfhgYYwnd4DlZwuy6rY4Gs7t4+gTGAs7BEciEvSMpIdZI8TXyH5XJVemqZoux12FqiHgsufzt6d
1606fz77KE7EVavSJl19dg1jnuUJsDVZBGCqzrCtLoOWqPhS1H3iHZh3YgqwZ9SbxFcmdQO8C6h/qhp6
1607DdOYey+Ds/enry/Opj9/PPtp+vH80xkgCHZGBgc0ZTSPDTiMKgbhAK5cqFjb16DXgx68Pv1oHwTT
1608VE3LXbmDB2AogYWrCOY7ESE+nGobPE3zZRGOqfGv7ISfsFrRHtfV8dfX4uREhL8mt0kYgNfTNuVF
1609/JEE4NOulNC1hj9RocZBsJBLEJYbiSIVPSVPdswdgIjQstCW9dcizc175iN3CJL4iHoADtPpPEuU
1610wsbTaQikpQ4DH+gQszuMchJBx3Lndh1rVPBTSViKHLtM8L8BFJMZ9UM0GEW3i2kEAraZJ0pyK5o+
16119JtOUctMp5EeEMSPeBxcJFYcoTBNUMtUKXiixCuodWaqyPAnwke5JZHBYAj1Gi6SDnbi2yRrpIqc
1612SQERo6hDRlSNqSIOAqciAtvZLt143KWm4RloBuTLCtB7VYdy+DkADwUUjAm7MDTjaIlphpj+O8cG
1613hAM4iSEqaKU6UFificuzS/Hy2YtDdEAgSlxY6njN0aameSPtwyWs1krWDsLcK5yQMIxduixRM+LT
161447thbmK7Mn1WWOolruSmuJULwBYZ2Fll8RO9gVga5jFPYBVBE5MFZ6VnPL0EI0eePUgLWnug3oag
1615mPU3S3/A4bvMFagODoWJ1DpOZ+NVVsVtiu7BbKdfgnUD9YY2zrgigbNwHpOhEQMNAX5rjpTayhAU
1616WNWwi0l4I0jU8ItWFcYE7gJ16zV9vcmLbT7l2PUE1WQ0tqyLgqWZFxu0S3Ag3oHdACQLCMVaojEU
1617cNIFytYhIA/Th+kCZSkaAEBgmhUFWA4sE5zRFDnOw2ERxviVIOGtJFr4WzMEBUeGGA4kehvbB0ZL
1618ICSYnFVwVjVoJkNZM81gYIckPtddxBw0+gA6VIzB0EUaGjcy9Ls6BuUsLlyl5PRDG/r582dmG7Wm
1619jAgiNsNJo9FfknmLyx2YwhR0gvGhOL9CbLAFdxTANEqzpjj8KIqS/SdYz0st22C5IR6r6/L46Gi7
16203cY6H1BUqyO1PPrzX7755i/PWCcuFsQ/MB1HWnRyLD6id+iDxt8aC/SdWbkOP6a5z40EK5LkR5Hz
1621iPh936SLQhwfjq3+RC5uDSv+b5wPUCBTMyhTGWg7ajF6og6fxC/VSDwRkds2GrMnoU2qtWK+1YUe
1622dQG2GzyNedHkdegoUiW+AusGMfVCzppVaAf3bKT5AVNFOY0sDxw+v0YMfM4wfGVM8RS1BLEFWnyH
16239D8x2yTkz2gNgeRFE9WLd3fDWswQd/FwebfeoSM0ZoapQu5AifCbPFgAbeO+5OBHO6No9xxn1Hw8
1624Q2AsfWCYV7uCEQoO4YJrMXGlzuFq9FFBmrasmkHBuKoRFDS4dTOmtgZHNjJEkOjdmPCcF1a3ADp1
1625cn0mojerAC3ccXrWrssKjieEPHAintMTCU7tce/dM17aJssoBdPhUY8qDNhbaLTTBfBlZABMxKj6
1626ecQtTWDxobMovAYDwArO2iCDLXvMhG9cH3B0MBpgp57V39ebaTwEAhcp4uzRg6ATyic8QqVAmsrI
162777mPxS1x+4PdaXGIqcwykUirPcLVVR6DQnWnYVqmOepeZ5HieVaAV2y1IjFS+953FihywcdDxkxL
1628oCZDSw6n0Ql5e54AhrodJrxWDaYG3MwJYrRJFVk3JNMa/gO3gjISlD4CWhI0C+ahUuZP7F8gc3a+
1629+sse9rCERoZwm+5zQ3oWQ8Mx7w8EklHnT0AKciBhXxjJdWR1kAGHOQvkCTe8lnulm2DECuTMsSCk
1630ZgB3eukFOPgkxj0LklCE/KVWshRfiREsX1dUH6a7/6VcatIGkdOAXAWdbzhxcxFOHuKkk5fwGdrP
1631SNDuRlkAB8/A5XFT8y6bG6a1aRJw1n3FbZECjUyZk9HYRfXaEMZN//7pxGnREssMYhjKG8jbhDEj
1632jQO73Bo0LLgB4615dyz92M1YYN8oLNQLufkC8V9YpWpeqBAD3F7uwv1orujTxmJ7kc5G8MdbgNH4
16332oMkM52/wCzLPzFI6EEPh6B7k8W0yCKptmkekgLT9Dvxl6aHhyWlZ+SOPlI4dQQTxRzl0bsKBIQ2
1634K49AnFATQFQuQ6Xd/j7YO6c4snC5+8hzm6+OX173iTvZl+Gxn+GlOvtSV4nC1cp40VgocLX6BhyV
1635LkwuyXd6u1FvR2OYUBUKokjx4eNngYTgTOw22T1u6i3DIzb3zsn7GNRBr91Lrs7siF0AEdSKyChH
16364eM58uHIPnZyd0zsEUAexTB3LIqBpPnkn4Fz10LBGIeLXY55tK7KwA+8/ubr6UBm1EXym69H94zS
1637IcaQ2EcdT9COTGUAYnDapkslk4x8DacTZRXzlndsm3LMCp3iP81k1wNOJ37Me2MyWvi95r3A0XwO
1638iB4QZhezXyFYVTq/dZukGSXlAY3DQ9RzJs7m1MEwPh6ku1HGnBR4LM8mg6GQunoGCxNyYD/uT0f7
1639Racm9zsQkJpPmag+Kgd6A77dP/I21d29w/2yP2ip/yCd9UhA3mxGAwR84BzM3ub//5mwsmJoWlmN
1640O1pfybv1vAH2AHW4x825ww3pD827WUvjTLDcKfEUBfSp2NKGNuXycGcCoCzYzxiAg8uot0XfNFXF
1641m5sk56WsDnHDbiKwlsd4GlQi1Adz9F7WiIltNqfcqFP5UQypzlBnO+1MwtZPHRbZdWFyJDK/TSvo
1642C1olCn/48ONZ2GcAPQx2GgbnrqPhkofbKYT7CKYNNXHCx/RhCj2myz8vVV1X2Seo2TM2GUhNtj5h
1643e4lHE7cOr8E9GQhvg5A3YjEinK/l/GYqaXMZ2RS7OknYN/gaMbF7zn6FkEqWVOYEM5lnDdKKHT2s
1644T1s2+Zzy8bUEe66LSbG4hLaMOd20zJKViKjzAlMdmhspG3KbVNrbKasCyxdFky6OVulCyN+aJMMw
1645Ui6XgAtuluhXMQ9PGQ/xlne9uaxNyXlTpfUOSJCoQu810Qa503C244lGHpK8rcAExC3zY/ERp43v
1646mXALQy4TjPoZdpwkxnnYwWwGInfRc3ifF1McdUpVoBNGqr8PTI+D7ggFABgBUJj/aKwzRf4bSa/c
1647DS1ac5eoqCU9UrqRbUEeB0KJxhhZ82/66TOiy1t7sFztx3J1N5arLparQSxXPparu7F0RQIX1iZJ
1648jCQMJUq6afTBigw3x8HDnCXzNbfD6kCsAgSIojQBnZEpLpL1Mim8n0RASG07G5z0sK2wSLnssCo4
16495apBIvfjpokOHk15s9OZ6jV0Z56K8dn2VZn4fY/imIqJZtSd5W2R1EnsycUqK2YgthbdSQtgIroF
1650J5yby2+nM84mdizV6PI/P/3w4T02R1Ajs51O3XAR0bDgVKKnSbVSfWlqg40S2JFa+oUf1E0DPHhg
1651JodHOeD/3lJFATKO2NKOeCFK8ACo7sc2c6tjwrDzXJfR6OfM5Ly5cSJGeT1qJ7WHSKeXl29PP52O
1652KMU0+t+RKzCGtr50uPiYFrZB339zm1uKYx8Qap1LaY2fOyeP1i1H3G9jDdiO2/vsuvPgxUMM9mBY
16536s/yD6UULAkQKtbJxscQ6sHBz+8KE3r0MYzYKw9zd3LYWbHvHNlzXBRH9IfS3N0B/M01jDGmQADt
1654QkUmMmiDqY7St+b1Doo6QB/o6/3uEKwbenUjGZ+idhIDDqBDWdtsv/vn7Quw0VOyfn32/fn7i/PX
1655l6effnBcQHTlPnw8eiHOfvwsqB4BDRj7RAluxddY+QKGxT0KIxYF/GswvbFoak5KQq+3Fxd6Z2CD
1656hyGwOhZtTgzPuWzGQuMcDWc97UNd74IYZTpAck6dUHkInUrBeGnDJx5UoSto6TDLDJ3VRode+jSR
1657OXVE+6gxSB80dknBILikCV5RnXNtosKKd5z0SZwBpLSNtoUIGeWgetvTzn6LyeZ7iTnqDE/azlrR
1658X4UuruF1rMoshUjuVWhlSXfDcoyWcfRDu6HKeA1pQKc7jKwb8qz3YoFW61XIc9P9xy2j/dYAhi2D
1659vYV555LKEahGF4upRIiNeOcglF/gq116vQYKFgw3lmpcRMN0Kcw+geBarFMIIIAn12B9MU4ACJ2V
16608BPQx052QBZYDRC+2SwO/xpqgvitf/lloHldZYd/FyVEQYJLV8IBYrqN30LgE8tYnH14Nw4ZOSoF
1661FX9tsIAcHBLK8jnSTvUyvGM7jZTMlrqewdcH+EL7CfS6072SZaW7D7vGIUrAExWR1/BEGfqFWF5k
1662YU9wKuMOaKyNt5jhGTN329t8DsTHtcwyXRF9/vbiDHxHLNdHCeJ9njMYjvMluGWri734DFwHFG7o
1663wusK2bhCF5Y29Rex12wwM4siR729OgC7TpT97PfqpTqrJFUu2hFOm2GZgvMYWRnWwiwrs3anDVLY
1664bUMUR5lhlpheVlQw6fME8DI9TTgkglgJDwOYNDPvWqZ5bSrksnQOehRULijUCQgJEhdPvBHnFTkn
1665eotKmYMy8LDcVelqXWMyHTrHVKSPzX88/Xxx/p4K11+8bL3uAeacUCQw4aKFEyxJw2wHfHHLzJCr
1666ptMhntWvEAZqH/jTfcXVECc8QK8fJxbxT/cVn1Q6cSJBngEoqKbsigcGAE63IblpZYFxtXEwftyS
1667sxYzHwzlIvFghC4scOfX50TbsmNKKO9jXj5il2JZahpGprNbAtX96DkuS9xWWUTDjeDtkGyZzwy6
16683vTe7Cu2cj89KcRDk4BRv7U/hqlG6jXV03GYbR+3UFirbewvuZMrddrNcxRlIGLkdh67TDashHVz
16695kCvbLcHTHyr0TWSOKjKR7/kI+1heJhYYvfiFNORjk2QEcBMhtSnQxrwodAigAKhatPIkdzJ+OkL
1670b46ONbh/jlp3gW38ARShrv2kMwVFBZwIX35jx5FfEVqoR49F6HgqucwLW5eEn+0avcrn/hwHZYCS
1671mCh2VZKvZMSwJgbmVz6x96RgSdt6pL5Kr4cMizgH5/TLHg7vy8XwxolBrcMIvXY3ctdVRz55sMHg
16720YM7CeaDr5It6P6yqSNeyWGRHz5ttR/q/RCx2g2a6s3eKMR0zG/hnvVpAQ9SQ8NCD++3gd0i/PDa
1673GEfW2sfOKZrQvtAe7LyC0KxWtC3jHF8zvqj1AlqDe9Ka/JF9qgtT7O+Bc0lOTsgC5cFdkN7cRrpB
1674J50w4uMxfLYwpfLr9vSGfreQtzIrwPWCqA6r63+11fXj2KZTBuuOfjd2l7vL3TBu9KbF7NiU/6Nn
1675pkpYvziX9RGiM5jxuQuzFhlc6l90SJLkN+Qlv/nb+US8ef8T/P9afoC4Co/HTcTfAQ3xpqggvuTz
1676nXTwHk8O1Bw4Fo3CM3QEjbYq+I4CdNsuPTrjtog+0uCfZbCaUmAVZ7XhizEARZ4gnXlu/QRTqA+/
1677zUmijjdqPMWhRRnpl0iD/Ycr8EDCkW4Zr+tNhvbCyZK0q3k1ujh/c/b+41lcf0EONz9HThbFLwDC
16786eg94gr3wybCPpk3+OTacZx/kFk54DfroNMc1MCgU4QQl5Q20ORLFxIbXCQVZg5EuVsU8xhbAsvz
16792bB6C4702Ikv7zX0npVFWNFY76K13jw+BmqIX7qKaAQNqY+eE/UkhJIZHlLix/Fo2BRPBKW24c/T
1680m+3CzYzr0yY0wS6m7awjv7vVhWums4ZnOYnwOrHLYA4gZmmiNrO5ezDtQy70nRmg5WifQy6TJquF
1681zEFyKcinywtA07tnyVhCmFXYnNEBK0rTZNtkp5xKm0SJEY46ovPXuCFDGUOIwX9Mbtge4CE30fBp
1682WYBOiFL8VDhdVTNfswRzSETUGyg82Kb5yxdhj8I8KEfI89aRhXmi28gYrWSt588PovHV87bSgbLS
1683c+8k6bwEq+eyyQGozvLp06cj8W/3ez+MSpwVxQ24ZQB70Gu5oNd7LLeenF2tvmdv3sTAj/O1vIIH
168415Q9t8+bnFKTd3SlBZH2r4ER4tqElhlN+45d5qRdxRvN3II3rLTl+DlP6WYcTC1JVLb6giFMOxlp
1685IpYExRAmap6mIacpYD12RYOHwDDNqPlFfgGOTxHMBN/iDhmH2mv0MKlg03KPRedEjAjwiAqoeDQ6
1686RUvHoADP6eVOozk9z9O6Pb/wzN081afFa3vhjeYrkWxRMsw8OsRwzhN6rNp62MWdLOpFLMX8yk04
1687dmbJr+/DHVgbJK1YLg2m8NAs0ryQ1dyYU1yxdJ7WDhjTDuFwZ7rnh6xPHAygNAL1TlZhYSXavv2T
1688XRcX0w+0j3xoRtLlQ7W9O4mTQ0neqaKL43Z8SkNZQlq+NV/GMMp7SmtrT8AbS/xJJ1WxeN274sE9
1689R9fk+uoGrt9o73MAOHRdkFWQlh09HeHcUWXhM9PuuXABPxSiE263aVU3STbVNwRM0WGb2o11jac9
1690f3XnyULrrYCTX4AHfKhLxcFxMFU2SE+s9DRHAU7EUqcoYvdIk3/6pyzQy3vBvhL4FEiZxdQcxDVJ
1691pCvLrvaE4zO+gsBR8QjqK3Nq5iE2wZzd6B17cKcxoaKncNwt5ey1wg0WU5tvPe9uZPCoITuwfC/e
1692TLB7cYP47kREzyfiz51AbF7u8OohIMOTRfxkEfo+IXW9On7R2rl+4NuBsBfIy+tHTzdLZzS9cKjG
1693+v6+uugRA9ANyO4ylYvDJwqxY5x/L1QNpZ3Xfk6lGeMR7ANbdaVPH7dnMujo1Qyiim2r0BzVZvxf
1694O4g51qz1EJ8ARaXBFtCeWjeFL53iQ3uzGBYmavT8lUUpmQ5tjuE3vB0E3muCukK1d9NUl5FbsAM5
1695AX1WkLfA2oYDQeEjeCikm0xo0b7qbAv/kYvHlen7Nhd7WH7z9V14ugI+WJY/QFCPmE6rP5Cp9rLM
1696YxfmAfv19/Pfw3nvLr57NJV0r2FaYSiFhczrhN+gSWzKY5tqMCKJW0GRW96Gn/pm8OAHiyPqpvom
1697vGv63P+uuesWgZ252d3tzd0/4OXSQPfdzy9DNOAwTxPiQTXjrcAO6wJXjCe6qGA4Zak/SH63E850
1698j1a4D4wpYcAEKLGpxt5ozU0yd79jhcwh32Hqnucb1NWdafcOOHY5/iGKlqsB8Lk94kslHgvNgew3
16990qVUUy4anMrVSk0TvBBtSsEGFbj0vEjjvr6j+6xkonbG68RbQwCE4SZdiuhWGwNjQEDDF7NyfYhz
1700PYSgoamK0inLVOmCM0jaxQVwMWeOqL/JTHJd5SiTmPBTTVVWEBWM9PWdXLgwVOvZAjWJjE2ibgzq
1701psdE3+aIQ3C1jDkDyPkqjjQ86gAh+GiQczcRFypPp/Yd8Muz9qxzOrEMIfNmI6ukbu/58LdJU/Gd
1702MwKd/MQFdlIVrWR2OMVFLLX84SCFyQL7/SvtZHtBxh0HnMdW6z2craiHToE95uy0Y3sMN6df7D1f
17037v0yC7oV1jXytlnLffZuE1gKc2kV6UqdO+C3+iIdvp6RM5voJjh8BHLvnrvyy3OtWmMnxaLhPHMV
1704Q//mFDy6S7Z46EK0Hhf0rz7rOPp2fF9vWGbphQZ7GlsqatdqUPG0o43biBor6e6JqP1q6UdG1B78
1705B0bU+vo6MDgaH60PBuun7wm9WU24d8G1jAB9pkAk3Nnr3CRmTGbkViND2Jt+Gdm7WFlnOkecjJlA
1706juxfEkQg+M435ZZuencymXGHIlpfuujx9xcfXp9eEC2ml6dv/uP0e6pWwfRxx2Y9OOWQF4dM7UOv
1707LtZNP+gKg6HBW2wHLlfkwx0aQu99b3N2AMLwQZ6hBe0qMvf1vg69AxH9ToD43dPuQN2nsgch9/wz
1708XXzv1hV0ClgD/ZSrDc0vZ8vWPDI7FywO7c6Eed8mk7WM9nJt+xbOqfvrqxPtt+rr+PbkAce2+pRW
1709AHPIyF82hWyOEthEJTsq3RvyqWQWj2GZqyxACufSuVKNblNjULV/FX8Fyi7BfTB2GCf2Wltqx+ly
1710Ze9rxr2wuYwNQbxzUKP+/FxhX8hsDxWCgBWevjCMETH6T28w2e3YJ0pcHdKJy0NUNtf2F66ZdnL/
1711luKma20v3lFcucHbTtB42WTuRqrt0+tAzh9l54ulU+IPmu8I6NyKpwL2Rp+JFeJsJ0IIJPWGIVYN
1712Eh31rVkO8mg3HewNrZ6Jw33n8dzzaEI8399w0Tnypnu84B7qnh6qMaeeHAuM5Wv7DtqJ7wgyb+8I
1713umnHcz5wT1Ff8Apfb6+eH9tkK/I7vnYUCZXZjBzDfuWUqd15u5vTnZilmlAdE8ZszjFN3eLagco+
1714wb4Yp1ervycOMvu+DGnkvR8u8jE9vFurR11MLesdw5RE9ESNaVrO6QaNu30y7k+3VVt9IHxS4wFA
1715eioQYCGYnm50Kud2XP4aPdNR4ayhezHdjHvoSAVV0fgcwT2M79fi1+1OJywf1J1RNP25QZcD9ZKD
1716cLPvwK3GXkpkv0noTr3lgz0uAB9WHe7//AH9+/VdtvuLu/xq2+rl4AEp9mWxJBArJTokMo9jMDKg
1717NyPS1lhHbgQdL6Fo6egyVDs35At0/KjMEG+9pQCDnNmp9gCsUQj+D1/Qrqc=
1718""")
1719
1720##file ez_setup.py
1721EZ_SETUP_PY = convert("""
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
1788BDaonX65d/fwEjNqlDjLVIvM9X+XVxF7
1789""")
1790
1791##file distribute_setup.py
1792DISTRIBUTE_SETUP_PY = convert("""
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
1872""")
1873
1874##file activate.sh
1875ACTIVATE_SH = convert("""
1876eJytVU1v4jAQPW9+xTT0ANVS1GsrDlRFAqmFqmG72m0rY5IJsRRslDiktNr/vuMQ8tFQpNU2B4I9
1877H36eeW/SglkgYvBFiLBKYg0LhCRGD1KhA7BjlUQuwkLIHne12HCNNpz5kVrBgsfBmdWCrUrA5VIq
1878DVEiQWjwRISuDreW5eE+CtodeLeAnhZEGKMGFXqAciMiJVcoNWx4JPgixDjzEj48QVeCfcqmtzfs
1879cfww+zG4ZfeD2ciGF7gCHaDMPM1jtvuHXAsPfF2rSGeOxV4iDY5GUGb3xVEYv2aj6WQ0vRseAlMY
1880G5DKsAawwnQUXt2LQOYlzZoYByqhonqoqfxZf4BLD97i4DukgXADCPgGgdOLTK5arYxZB1xnrc9T
1881EQFcHoZEAa1gSQioo/TPV5FZrDlxJA+NzwF+Ek1UonOzFnKZp6k5mgLBqSkuuAGXS4whJb5xz/xs
1882wXCHjiVerAk5eh9Kfz1wqOldtVv9dkbscfjgjKeTA8XPrtaNauX5rInOxaHuOReNtpFjo1/OxdFG
18835eY9hJ3L3jqcPJbATggXAemDLZX0MNZRYjSDH7C1wMHQh73DyYfTu8a0F9v+6D8W6XNnF1GEIXW/
1884JrSKPOtnW1YFat9mrLJkzLbyIlTvYzV0RGXcaTBfVLx7jF2PJ2wyuBsydpm7VSVa4C4Zb6pFO2TR
1885huypCEPwuQjNftUrNl6GsYZzuFrrLdC9iJjQ3omAPBbcI2lsU77tUD43kw1NPZhTrnZWzuQKLomx
1886Rd4OXM1ByExVVkmoTwfBJ7Lt10Iq1Kgo23Bmd8Ib1KrGbsbO4Pp2yO4fpnf3s6MnZiwuiJuls1/L
1887Pu4yUCvhpA+vZaJvWWDTr0yFYYyVnHMqCEq+QniuYX225xmnzRENjbXACF3wkCYNVZ1mBwxoR9Iw
1888WAo3/36oSOTfgjwEEQKt15e9Xpqm52+oaXxszmnE9GLl65RH2OMmS6+u5acKxDmlPgj2eT5/gQOX
1889LLK0j1y0Uwbmn438VZkVpqlfNKa/YET/53j+99G8H8tUhr9ZSXs2
1890""")
1891
1892##file activate.fish
1893ACTIVATE_FISH = convert("""
1894eJydVm1v4jgQ/s6vmA1wBxUE7X2stJVYlVWR2lK13d6d9laRk0yIr8HmbIe0++tvnIQQB9pbXT5A
1895Ys/LM55nZtyHx5RrSHiGsMm1gRAh1xhDwU0Kng8hFzMWGb5jBv2E69SDs0TJDdj3MxilxmzPZzP7
1896pVPMMl+q9bjXh1eZQ8SEkAZULoAbiLnCyGSvvV6SC7IoBcS4Nw0wjcFbvJDcjiuTswzFDpiIQaHJ
1897lQAjQUi1YRmUboC2uZJig8J4PaCnT5IaDcgsbm/CjinOwgx1KcUTMEhhTgV4g2B1fRk8Le8fv86v
1898g7v545UHpZB9rKnp+gXsMhxLunIIpwVQxP/l9c/Hq9Xt1epm4R27bva6AJqN92G4YhbMG2i+LB+u
1899grv71c3dY7B6WtzfLy9bePbp0taDTXSwJQJszUnnp0y57mvpPcrF7ZODyhswtd59+/jdgw+fwBNS
1900xLSscksUPIDqwwNmCez3PpxGeyBYg6HE0YdcWBxcKczYzuVJi5Wu915vn5oWePCCoPUZBN5B7IgV
1901MCi54ZDLG7TUZ0HweXkb3M5vFmSpFm/gthhBx0UrveoPpv9AJ9unIbQYdUoe21bKg2q48sPFGVwu
1902H+afrxd1qvclaNlRFyh1EQ2sSccEuNAGWQwysfVpz1tPajUqbqJUnEcIJkWo6OXDaodK8ZiLdbmM
1903L1wb+9H0D+pcyPSrX5u5kgWSygRYXCnJUi/KKcuU4cqsAyTKZBiissLc7NFwizvjxtieKBVCIdWz
1904fzilzPaYyljZN0cGN1v7NnaIPNCGmVy3GKuJaQ6iVjE1Qfm+36hglErwmnAD8hu0dDy4uICBA8ZV
1905pQr/q/+O0KFW2kjelu9Dgb9SDBsWV4F4x5CswgS0zBVlk5tDMP5bVtUGpslbm81Lu2sdKq7uNMGh
1906MVQ4fy9xhogC1lS5guhISa0DlBWv0O8odT6/LP+4WZzDV6FzIkEqC0uolGZSZoMnlpxplmD2euaT
1907O4hkTpPnbztDccey0bhjDaBIqaWQa0uwEtQEwtyU56i4fq54F9IE3ORR6mKriODM4XOYZwaVYLYz
19087SPbKkz4i7VkB6/Ot1upDE3znNqYKpM8raa0Bx8vfvntJ32UENsM4aI6gJL+jJwhxhh3jVIDOcpi
1909m0r2hmEtS8XXXNBk71QCDXTBNhhPiHX2LtHkrVIlhoEshH/EZgdq53Eirqs5iFKMnkOmqZTtr3Xq
1910djvPTWZT4S3NT5aVLgurMPUWI07BRVYqkQrmtCKohNY8qu9EdACoT6ki0a66XxVF4f9AQ3W38yO5
1911mWmZmIIpnDFrbXakvKWeZhLwhvrbUH8fahhqD0YUcBDJjEBMQwiznE4y5QbHrbhHBOnUAYzb2tVN
1912jJa65e+eE2Ya30E2GurxUP8ssA6e/wOnvo3V78d3vTcvMB3n7l3iX1JXWqk=
1913""")
1914
1915##file activate.csh
1916ACTIVATE_CSH = convert("""
1917eJx9U11vmzAUffevOCVRu+UB9pws29Kl0iq1aVWllaZlcgxciiViItsQdb9+xiQp+dh4QOB7Pu49
1918XHqY59IgkwVhVRmLmFAZSrGRNkdgykonhFiqSCRW1sJSmJg8wCDT5QrucRCyHn6WFRKhVGmhKwVp
1919kUpNiS3emup3TY6XIn7DVNQyJUwlrgthJD6n/iCNv72uhCzCpFx9CRkThRQGKe08cWXJ9db/yh/u
1920pvzl9mn+PLnjj5P5D1yM8QmXlzBkSdXwZ0H/BBc0mEo5FE5qI2jKhclHOOvy9HD/OO/6YO1mX9vx
1921sY0H/tPIV0dtqel0V7iZvWyNg8XFcBA0ToEqVeqOdNUEQFvN41SumAv32VtJrakQNSmLWmgp4oJM
1922yDoBHgoydtoEAs47r5wHHnUal5vbJ8oOI+9wI86vb2d8Nrm/4Xy4RZ8R85E4uTZPB5EZPnTaaAGu
1923E59J8BE2J8XgrkbLeXMlVoQxznEYFYY8uFFdxsKQRx90Giwx9vSueHP1YNaUSFG4vTaErNSYuBOF
1924lXiVyXa9Sy3JdClEyK1dD6Nos9mEf8iKlOpmqSNTZnYjNEWiUYn2pKNB3ttcLJ3HmYYXy6Un76f7
1925r8rRsC1TpTJj7f19m5sUf/V3Ir+x/yjtLu8KjLX/CmN/AcVGUUo=
1926""")
1927
1928##file activate.bat
1929ACTIVATE_BAT = convert("""
1930eJyFUkEKgzAQvAfyhz0YaL9QEWpRqlSjWGspFPZQTevFHOr/adQaU1GaUzI7Mzu7ZF89XhKkEJS8
1931qxaKMMsvboQ+LxxE44VICSW1gEa2UFaibqoS0iyJ0xw2lIA6nX5AHCu1jpRsv5KRjknkac9VLVug
1932sX9mtzxIeJDE/mg4OGp47qoLo3NHX2jsMB3AiDht5hryAUOEifoTdCXbSh7V0My2NMq/Xbh5MEjU
1933ZT63gpgNT9lKOJ/CtHsvT99re3pX303kydn4HeyOeAg5cjf2EW1D6HOPkg9NGKhu
1934""")
1935
1936##file deactivate.bat
1937DEACTIVATE_BAT = convert("""
1938eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q
1939FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL
1940i2dASrm4rFz9XLgAwJNbyQ==
1941""")
1942
1943##file distutils-init.py
1944DISTUTILS_INIT = convert("""
1945eJytV92L4zYQf/dfMU0ottuse7RvC6FQrg8Lxz2Ugz4si9HacqKuIxlJ2ST313dG8odkO9d7aGBB
1946luZLv/nNjFacOqUtKJMIvzK3cXlhWgp5MDBsqK5SNYftsBAGpLLA4F1oe2Ytl+9wUvW55TswCi4c
1947KibhbFDSglXQCFmDPXIwtm7FawLRbwtPzg2T9gf4gupKv4GS0N262w7V0NvpbCy8cvTo3eAus6C5
1948ETU3ICQZX1hFTw/dzR6V/AW1RCN4/XAtbsVXqIXmlVX6liS4lOzEYY9QFB2zx6LfoSNjz1a0pqT9
1949QOIfJWQ2E888NEVZNqLlZZnvIB0NpHkimlFdKn2iRRY7yGG/CCJb6Iz280d34SFXBS2yEYPNF0Q7
1950yM7oCjpWvbEDQmnhRwOs6zjThpKE8HogwRAgraqYFZgGZvzmzVh+mgz9vskT3hruwyjdFcqyENJw
1951bbMPO5jdzonxK68QKT7B57CMRRG5shRSWDTX3dI8LzRndZbnSWL1zfvriUmK4TcGWSnZiEPCrxXv
1952bM+sP7VW2is2WgWXCO3sAu3Rzysz3FiNCA8WPyM4gb1JAAmCiyTZbhFjWx3h9SzauuRXC9MFoVbc
1953yNTCm1QXOOIfIn/g1kGMhDUBN72hI5XCBQtIXQw8UEEdma6Jaz4vJIJ51Orc15hzzmu6TdFp3ogr
1954Aof0c98tsw1SiaiWotHffk3XYCkqdToxWRfTFXqgpg2khcLluOHMVC0zZhLKIomesfSreUNNgbXi
1955Ky9VRzwzkBneNoGQyyvGjbsFQqOZvpWIjqH281lJ/jireFgR3cPzSyTGWzQpDNIU+03Fs4XKLkhp
1956/n0uFnuF6VphB44b3uWRneSbBoMSioqE8oeF0JY+qTvYfEK+bPLYdoR4McfYQ7wMZj39q0kfP8q+
1957FfsymO0GzNlPh644Jje06ulqHpOEQqdJUfoidI2O4CWx4qOglLye6RrFQirpCRXvhoRqXH3sYdVJ
1958AItvc+VUsLO2v2hVAWrNIfVGtkG351cUMNncbh/WdowtSPtCdkzYFv6mwYc9o2Jt68ud6wectBr8
1959hYAulPSlgzH44YbV3ikjrulEaNJxt+/H3wZ7bXSXje/YY4tfVVrVmUstaDwwOBLMg6iduDB0lMVC
1960UyzYx7Ab4kjCqdViEJmDcdk/SKbgsjYXgfMznUWcrtS4z4fmJ/XOM1LPk/iIpqass5XwNbdnLb1Y
19618h3ERXSWZI6rZJxKs1LBqVH65w0Oy4ra0CBYxEeuOMbDmV5GI6E0Ha/wgVTtkX0+OXvqsD02CKLf
1962XHbeft85D7tTCMYy2Njp4DJP7gWJr6paVWXZ1+/6YXLv/iE0M90FktiI7yFJD9e7SOLhEkkaMTUO
1963azq9i2woBNR0/0eoF1HFMf0H8ChxH/jgcB34GZIz3Qn4/vid+VEamQrOVqAPTrOfmD4MPdVh09tb
19648dLLjvh/61lEP4yW5vJaH4vHcevG8agXvzPGoOhhXNncpTr99PTHx6e/UvffFLaxUSjuSeP286Dw
1965gtEMcW1xKr/he4/6IQ6FUXP+0gkioHY5iwC9Eyx3HKO7af0zPPe+XyLn7fAY78k4aiR387bCr5XT
19665C4rFgwLGfMvJuAMew==
1967""")
1968
1969##file distutils.cfg
1970DISTUTILS_CFG = convert("""
1971eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
1972xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
19739FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
1974""")
1975
1976##file activate_this.py
1977ACTIVATE_THIS = convert("""
1978eJyNUlGL2zAMfvevEBlHEujSsXsL9GGDvW1jD3sZpQQ3Ua7aJXawnbT595Ocpe0dO5ghseVP+vRJ
1979VpIkn2cYPZknwAvWLXWYhRP5Sk4baKgOWRWNqtpdgTyH2Y5wpq5Tug406YAgKEzkwqg7NBPwR86a
1980Hk0olPopaK0NHJHzYQPnE5rI0o8+yBUwiBfyQcT8mMPJGiAT0A0O+b8BY4MKJ7zPcSSzHaKrSpJE
1981qeDmUgGvVbPCS41DgO+6xy/OWbfAThMn/OQ9ukDWRCSLiKzk1yrLjWapq6NnvHUoHXQ4bYPdrsVX
19824lQMc/q6ZW975nmSK+oH6wL42a9H65U6aha342Mh0UVDzrD87C1bH73s16R5zsStkBZDp0NrXQ+7
1983HaRnMo8f06UBnljKoOtn/YT+LtdvSyaT/BtIv9KR60nF9f3qmuYKO4//T9ItJMsjPfgUHqKwCZ3n
1984xu/Lx8M/UvCLTxW7VULHxB1PRRbrYfvWNY5S8it008jOjcleaMqVBDnUXcWULV2YK9JEQ92OfC96
19851Tv4ZicZZZ7GpuEpZbbeQ7DxquVx5hdqoyFSSmXwfC90f1Dc7hjFs/tK99I0fpkI8zSLy4tSy+sI
19863vMWehjQNJmE5VePlZbL61nzX3S93ZcfDqznnkb9AZ3GWJU=
1987""")
1988
1989if __name__ == '__main__':
1990    main()
1991
1992## TODO:
1993## Copy python.exe.manifest
1994## Monkeypatch distutils.sysconfig
Note: See TracBrowser for help on using the repository browser.