source: bootstrap.py @ d42516889b53e13cc8cea3b4d30d83d06708e07c

Revision d42516889b53e13cc8cea3b4d30d83d06708e07c, 68.5 KB checked in by Paul Winkler <slinkp@…>, 9 days ago (diff)

Update the bootstrap script from bootstrap.py.in. We usually want global site packages, because Mapnik is a pain otherwise.

  • 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
7virtualenv_version = "1.4.9"
8
9import sys
10import os
11import optparse
12import re
13import shutil
14import logging
15import distutils.sysconfig
16try:
17    import subprocess
18except ImportError, e:
19    if sys.version_info <= (2, 3):
20        print 'ERROR: %s' % e
21        print 'ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.'
22        print 'If you copy subprocess.py from a newer version of Python this script will probably work'
23        sys.exit(101)
24    else:
25        raise
26try:
27    set
28except NameError:
29    from sets import Set as set
30
31join = os.path.join
32py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
33is_jython = sys.platform.startswith('java')
34expected_exe = is_jython and 'jython' or 'python'
35
36REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
37                    'fnmatch', 'locale', 'encodings', 'codecs',
38                    'stat', 'UserDict', 'readline', 'copy_reg', 'types',
39                    're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
40                    'lib-dynload', 'config', 'zlib']
41
42if sys.version_info[:2] >= (2, 6):
43    REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc'])
44if sys.version_info[:2] <= (2, 3):
45    REQUIRED_MODULES.extend(['sets', '__future__'])
46
47class Logger(object):
48
49    """
50    Logging object for use in command-line script.  Allows ranges of
51    levels, to avoid some redundancy of displayed information.
52    """
53
54    DEBUG = logging.DEBUG
55    INFO = logging.INFO
56    NOTIFY = (logging.INFO+logging.WARN)/2
57    WARN = WARNING = logging.WARN
58    ERROR = logging.ERROR
59    FATAL = logging.FATAL
60
61    LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
62
63    def __init__(self, consumers):
64        self.consumers = consumers
65        self.indent = 0
66        self.in_progress = None
67        self.in_progress_hanging = False
68
69    def debug(self, msg, *args, **kw):
70        self.log(self.DEBUG, msg, *args, **kw)
71    def info(self, msg, *args, **kw):
72        self.log(self.INFO, msg, *args, **kw)
73    def notify(self, msg, *args, **kw):
74        self.log(self.NOTIFY, msg, *args, **kw)
75    def warn(self, msg, *args, **kw):
76        self.log(self.WARN, msg, *args, **kw)
77    def error(self, msg, *args, **kw):
78        self.log(self.WARN, msg, *args, **kw)
79    def fatal(self, msg, *args, **kw):
80        self.log(self.FATAL, msg, *args, **kw)
81    def log(self, level, msg, *args, **kw):
82        if args:
83            if kw:
84                raise TypeError(
85                    "You may give positional or keyword arguments, not both")
86        args = args or kw
87        rendered = None
88        for consumer_level, consumer in self.consumers:
89            if self.level_matches(level, consumer_level):
90                if (self.in_progress_hanging
91                    and consumer in (sys.stdout, sys.stderr)):
92                    self.in_progress_hanging = False
93                    sys.stdout.write('\n')
94                    sys.stdout.flush()
95                if rendered is None:
96                    if args:
97                        rendered = msg % args
98                    else:
99                        rendered = msg
100                    rendered = ' '*self.indent + rendered
101                if hasattr(consumer, 'write'):
102                    consumer.write(rendered+'\n')
103                else:
104                    consumer(rendered)
105
106    def start_progress(self, msg):
107        assert not self.in_progress, (
108            "Tried to start_progress(%r) while in_progress %r"
109            % (msg, self.in_progress))
110        if self.level_matches(self.NOTIFY, self._stdout_level()):
111            sys.stdout.write(msg)
112            sys.stdout.flush()
113            self.in_progress_hanging = True
114        else:
115            self.in_progress_hanging = False
116        self.in_progress = msg
117
118    def end_progress(self, msg='done.'):
119        assert self.in_progress, (
120            "Tried to end_progress without start_progress")
121        if self.stdout_level_matches(self.NOTIFY):
122            if not self.in_progress_hanging:
123                # Some message has been printed out since start_progress
124                sys.stdout.write('...' + self.in_progress + msg + '\n')
125                sys.stdout.flush()
126            else:
127                sys.stdout.write(msg + '\n')
128                sys.stdout.flush()
129        self.in_progress = None
130        self.in_progress_hanging = False
131
132    def show_progress(self):
133        """If we are in a progress scope, and no log messages have been
134        shown, write out another '.'"""
135        if self.in_progress_hanging:
136            sys.stdout.write('.')
137            sys.stdout.flush()
138
139    def stdout_level_matches(self, level):
140        """Returns true if a message at this level will go to stdout"""
141        return self.level_matches(level, self._stdout_level())
142
143    def _stdout_level(self):
144        """Returns the level that stdout runs at"""
145        for level, consumer in self.consumers:
146            if consumer is sys.stdout:
147                return level
148        return self.FATAL
149
150    def level_matches(self, level, consumer_level):
151        """
152        >>> l = Logger()
153        >>> l.level_matches(3, 4)
154        False
155        >>> l.level_matches(3, 2)
156        True
157        >>> l.level_matches(slice(None, 3), 3)
158        False
159        >>> l.level_matches(slice(None, 3), 2)
160        True
161        >>> l.level_matches(slice(1, 3), 1)
162        True
163        >>> l.level_matches(slice(2, 3), 1)
164        False
165        """
166        if isinstance(level, slice):
167            start, stop = level.start, level.stop
168            if start is not None and start > consumer_level:
169                return False
170            if stop is not None or stop <= consumer_level:
171                return False
172            return True
173        else:
174            return level >= consumer_level
175
176    #@classmethod
177    def level_for_integer(cls, level):
178        levels = cls.LEVELS
179        if level < 0:
180            return levels[0]
181        if level >= len(levels):
182            return levels[-1]
183        return levels[level]
184
185    level_for_integer = classmethod(level_for_integer)
186
187def mkdir(path):
188    if not os.path.exists(path):
189        logger.info('Creating %s', path)
190        os.makedirs(path)
191    else:
192        logger.info('Directory %s already exists', path)
193
194def copyfile(src, dest, symlink=True):
195    if not os.path.exists(src):
196        # Some bad symlink in the src
197        logger.warn('Cannot find file %s (bad symlink)', src)
198        return
199    if os.path.exists(dest):
200        logger.debug('File %s already exists', dest)
201        return
202    if not os.path.exists(os.path.dirname(dest)):
203        logger.info('Creating parent directories for %s' % os.path.dirname(dest))
204        os.makedirs(os.path.dirname(dest))
205    if symlink and hasattr(os, 'symlink'):
206        logger.info('Symlinking %s', dest)
207        os.symlink(os.path.abspath(src), dest)
208    else:
209        logger.info('Copying to %s', dest)
210        if os.path.isdir(src):
211            shutil.copytree(src, dest, True)
212        else:
213            shutil.copy2(src, dest)
214
215def writefile(dest, content, overwrite=True):
216    if not os.path.exists(dest):
217        logger.info('Writing %s', dest)
218        f = open(dest, 'wb')
219        f.write(content)
220        f.close()
221        return
222    else:
223        f = open(dest, 'rb')
224        c = f.read()
225        f.close()
226        if c != content:
227            if not overwrite:
228                logger.notify('File %s exists with different content; not overwriting', dest)
229                return
230            logger.notify('Overwriting %s with new content', dest)
231            f = open(dest, 'wb')
232            f.write(content)
233            f.close()
234        else:
235            logger.info('Content %s already in place', dest)
236
237def rmtree(dir):
238    if os.path.exists(dir):
239        logger.notify('Deleting tree %s', dir)
240        shutil.rmtree(dir)
241    else:
242        logger.info('Do not need to delete %s; already gone', dir)
243
244def make_exe(fn):
245    if hasattr(os, 'chmod'):
246        oldmode = os.stat(fn).st_mode & 07777
247        newmode = (oldmode | 0555) & 07777
248        os.chmod(fn, newmode)
249        logger.info('Changed mode of %s to %s', fn, oct(newmode))
250
251def _find_file(filename, dirs):
252    for dir in dirs:
253        if os.path.exists(join(dir, filename)):
254            return join(dir, filename)
255    return filename
256
257def _install_req(py_executable, unzip=False, distribute=False):
258    if not distribute:
259        setup_fn = 'setuptools-0.6c11-py%s.egg' % sys.version[:3]
260        project_name = 'setuptools'
261        bootstrap_script = EZ_SETUP_PY
262        source = None
263    else:
264        setup_fn = None
265        source = 'distribute-0.6.8.tar.gz'
266        project_name = 'distribute'
267        bootstrap_script = DISTRIBUTE_SETUP_PY
268        try:
269            # check if the global Python has distribute installed or plain
270            # setuptools
271            import pkg_resources
272            if not hasattr(pkg_resources, '_distribute'):
273                location = os.path.dirname(pkg_resources.__file__)
274                logger.notify("A globally installed setuptools was found (in %s)" % location)
275                logger.notify("Use the --no-site-packages option to use distribute in "
276                              "the virtualenv.")
277        except ImportError:
278            pass
279
280    search_dirs = file_search_dirs()
281
282    if setup_fn is not None:
283        setup_fn = _find_file(setup_fn, search_dirs)
284
285    if source is not None:
286        source = _find_file(source, search_dirs)
287
288    if is_jython and os._name == 'nt':
289        # Jython's .bat sys.executable can't handle a command line
290        # argument with newlines
291        import tempfile
292        fd, ez_setup = tempfile.mkstemp('.py')
293        os.write(fd, bootstrap_script)
294        os.close(fd)
295        cmd = [py_executable, ez_setup]
296    else:
297        cmd = [py_executable, '-c', bootstrap_script]
298    if unzip:
299        cmd.append('--always-unzip')
300    env = {}
301    if logger.stdout_level_matches(logger.DEBUG):
302        cmd.append('-v')
303
304    old_chdir = os.getcwd()
305    if setup_fn is not None and os.path.exists(setup_fn):
306        logger.info('Using existing %s egg: %s' % (project_name, setup_fn))
307        cmd.append(setup_fn)
308        if os.environ.get('PYTHONPATH'):
309            env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH']
310        else:
311            env['PYTHONPATH'] = setup_fn
312    else:
313        # the source is found, let's chdir
314        if source is not None and os.path.exists(source):
315            os.chdir(os.path.dirname(source))
316        else:
317            logger.info('No %s egg found; downloading' % project_name)
318        cmd.extend(['--always-copy', '-U', project_name])
319    logger.start_progress('Installing %s...' % project_name)
320    logger.indent += 2
321    cwd = None
322    if project_name == 'distribute':
323        env['DONT_PATCH_SETUPTOOLS'] = 'true'
324
325    def _filter_ez_setup(line):
326        return filter_ez_setup(line, project_name)
327
328    if not os.access(os.getcwd(), os.W_OK):
329        cwd = '/tmp'
330        if source is not None and os.path.exists(source):
331            # the current working dir is hostile, let's copy the
332            # tarball to /tmp
333            target = os.path.join(cwd, os.path.split(source)[-1])
334            shutil.copy(source, target)
335    try:
336        call_subprocess(cmd, show_stdout=False,
337                        filter_stdout=_filter_ez_setup,
338                        extra_env=env,
339                        cwd=cwd)
340    finally:
341        logger.indent -= 2
342        logger.end_progress()
343        if os.getcwd() != old_chdir:
344            os.chdir(old_chdir)
345        if is_jython and os._name == 'nt':
346            os.remove(ez_setup)
347
348def file_search_dirs():
349    here = os.path.dirname(os.path.abspath(__file__))
350    dirs = ['.', here,
351            join(here, 'virtualenv_support')]
352    if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
353        # Probably some boot script; just in case virtualenv is installed...
354        try:
355            import virtualenv
356        except ImportError:
357            pass
358        else:
359            dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
360    return [d for d in dirs if os.path.isdir(d)]
361
362def install_setuptools(py_executable, unzip=False):
363    _install_req(py_executable, unzip)
364
365def install_distribute(py_executable, unzip=False):
366    _install_req(py_executable, unzip, distribute=True)
367
368_pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I)
369def install_pip(py_executable):
370    filenames = []
371    for dir in file_search_dirs():
372        filenames.extend([join(dir, fn) for fn in os.listdir(dir)
373                          if _pip_re.search(fn)])
374    filenames.sort(key=lambda x: os.path.basename(x).lower())
375    if not filenames:
376        filename = 'pip'
377    else:
378        filename = filenames[-1]
379    easy_install_script = 'easy_install'
380    if sys.platform == 'win32':
381        easy_install_script = 'easy_install-script.py'
382    cmd = [py_executable, join(os.path.dirname(py_executable), easy_install_script), filename]
383    if filename == 'pip':
384        logger.info('Installing pip from network...')
385    else:
386        logger.info('Installing %s' % os.path.basename(filename))
387    logger.indent += 2
388    def _filter_setup(line):
389        return filter_ez_setup(line, 'pip')
390    try:
391        call_subprocess(cmd, show_stdout=False,
392                        filter_stdout=_filter_setup)
393    finally:
394        logger.indent -= 2
395
396def filter_ez_setup(line, project_name='setuptools'):
397    if not line.strip():
398        return Logger.DEBUG
399    if project_name == 'distribute':
400        for prefix in ('Extracting', 'Now working', 'Installing', 'Before',
401                       'Scanning', 'Setuptools', 'Egg', 'Already',
402                       'running', 'writing', 'reading', 'installing',
403                       'creating', 'copying', 'byte-compiling', 'removing',
404                       'Processing'):
405            if line.startswith(prefix):
406                return Logger.DEBUG
407        return Logger.DEBUG
408    for prefix in ['Reading ', 'Best match', 'Processing setuptools',
409                   'Copying setuptools', 'Adding setuptools',
410                   'Installing ', 'Installed ']:
411        if line.startswith(prefix):
412            return Logger.DEBUG
413    return Logger.INFO
414
415def main():
416    parser = optparse.OptionParser(
417        version=virtualenv_version,
418        usage="%prog [OPTIONS] DEST_DIR")
419
420    parser.add_option(
421        '-v', '--verbose',
422        action='count',
423        dest='verbose',
424        default=0,
425        help="Increase verbosity")
426
427    parser.add_option(
428        '-q', '--quiet',
429        action='count',
430        dest='quiet',
431        default=0,
432        help='Decrease verbosity')
433
434    parser.add_option(
435        '-p', '--python',
436        dest='python',
437        metavar='PYTHON_EXE',
438        help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
439        'interpreter to create the new environment.  The default is the interpreter that '
440        'virtualenv was installed with (%s)' % sys.executable)
441
442    parser.add_option(
443        '--clear',
444        dest='clear',
445        action='store_true',
446        help="Clear out the non-root install and start from scratch")
447
448    parser.add_option(
449        '--no-site-packages',
450        dest='no_site_packages',
451        action='store_true',
452        help="Don't give access to the global site-packages dir to the "
453             "virtual environment")
454
455    parser.add_option(
456        '--unzip-setuptools',
457        dest='unzip_setuptools',
458        action='store_true',
459        help="Unzip Setuptools or Distribute when installing it")
460
461    parser.add_option(
462        '--relocatable',
463        dest='relocatable',
464        action='store_true',
465        help='Make an EXISTING virtualenv environment relocatable.  '
466        'This fixes up scripts and makes all .pth files relative')
467
468    parser.add_option(
469        '--distribute',
470        dest='use_distribute',
471        action='store_true',
472        help='Use Distribute instead of Setuptools. Set environ variable'
473        'VIRTUALENV_USE_DISTRIBUTE to make it the default ')
474
475    if 'extend_parser' in globals():
476        extend_parser(parser)
477
478    options, args = parser.parse_args()
479
480    global logger
481
482    if 'adjust_options' in globals():
483        adjust_options(options, args)
484
485    verbosity = options.verbose - options.quiet
486    logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)])
487
488    if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
489        env = os.environ.copy()
490        interpreter = resolve_interpreter(options.python)
491        if interpreter == sys.executable:
492            logger.warn('Already using interpreter %s' % interpreter)
493        else:
494            logger.notify('Running virtualenv with interpreter %s' % interpreter)
495            env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
496            file = __file__
497            if file.endswith('.pyc'):
498                file = file[:-1]
499            os.execvpe(interpreter, [interpreter, file] + sys.argv[1:], env)
500
501    if not args:
502        print 'You must provide a DEST_DIR'
503        parser.print_help()
504        sys.exit(2)
505    if len(args) > 1:
506        print 'There must be only one argument: DEST_DIR (you gave %s)' % (
507            ' '.join(args))
508        parser.print_help()
509        sys.exit(2)
510
511    home_dir = args[0]
512
513    if os.environ.get('WORKING_ENV'):
514        logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
515        logger.fatal('Please deactivate your workingenv, then re-run this script')
516        sys.exit(3)
517
518    if 'PYTHONHOME' in os.environ:
519        logger.warn('PYTHONHOME is set.  You *must* activate the virtualenv before using it')
520        del os.environ['PYTHONHOME']
521
522    if options.relocatable:
523        make_environment_relocatable(home_dir)
524        return
525
526    create_environment(home_dir, site_packages=not options.no_site_packages, clear=options.clear,
527                       unzip_setuptools=options.unzip_setuptools,
528                       use_distribute=options.use_distribute)
529    if 'after_install' in globals():
530        after_install(options, home_dir)
531
532def call_subprocess(cmd, show_stdout=True,
533                    filter_stdout=None, cwd=None,
534                    raise_on_returncode=True, extra_env=None):
535    cmd_parts = []
536    for part in cmd:
537        if len(part) > 40:
538            part = part[:30]+"..."+part[-5:]
539        if ' ' in part or '\n' in part or '"' in part or "'" in part:
540            part = '"%s"' % part.replace('"', '\\"')
541        cmd_parts.append(part)
542    cmd_desc = ' '.join(cmd_parts)
543    if show_stdout:
544        stdout = None
545    else:
546        stdout = subprocess.PIPE
547    logger.debug("Running command %s" % cmd_desc)
548    if extra_env:
549        env = os.environ.copy()
550        env.update(extra_env)
551    else:
552        env = None
553    try:
554        proc = subprocess.Popen(
555            cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
556            cwd=cwd, env=env)
557    except Exception, e:
558        logger.fatal(
559            "Error %s while executing command %s" % (e, cmd_desc))
560        raise
561    all_output = []
562    if stdout is not None:
563        stdout = proc.stdout
564        while 1:
565            line = stdout.readline()
566            if not line:
567                break
568            line = line.rstrip()
569            all_output.append(line)
570            if filter_stdout:
571                level = filter_stdout(line)
572                if isinstance(level, tuple):
573                    level, line = level
574                logger.log(level, line)
575                if not logger.stdout_level_matches(level):
576                    logger.show_progress()
577            else:
578                logger.info(line)
579    else:
580        proc.communicate()
581    proc.wait()
582    if proc.returncode:
583        if raise_on_returncode:
584            if all_output:
585                logger.notify('Complete output from command %s:' % cmd_desc)
586                logger.notify('\n'.join(all_output) + '\n----------------------------------------')
587            raise OSError(
588                "Command %s failed with error code %s"
589                % (cmd_desc, proc.returncode))
590        else:
591            logger.warn(
592                "Command %s had error code %s"
593                % (cmd_desc, proc.returncode))
594
595
596def create_environment(home_dir, site_packages=True, clear=False,
597                       unzip_setuptools=False, use_distribute=False):
598    """
599    Creates a new environment in ``home_dir``.
600
601    If ``site_packages`` is true (the default) then the global
602    ``site-packages/`` directory will be on the path.
603
604    If ``clear`` is true (default False) then the environment will
605    first be cleared.
606    """
607    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
608
609    py_executable = os.path.abspath(install_python(
610        home_dir, lib_dir, inc_dir, bin_dir,
611        site_packages=site_packages, clear=clear))
612
613    install_distutils(lib_dir, home_dir)
614
615    if use_distribute or os.environ.get('VIRTUALENV_USE_DISTRIBUTE'):
616        install_distribute(py_executable, unzip=unzip_setuptools)
617    else:
618        install_setuptools(py_executable, unzip=unzip_setuptools)
619
620    install_pip(py_executable)
621
622    install_activate(home_dir, bin_dir)
623
624def path_locations(home_dir):
625    """Return the path locations for the environment (where libraries are,
626    where scripts go, etc)"""
627    # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
628    # prefix arg is broken: http://bugs.python.org/issue3386
629    if sys.platform == 'win32':
630        # Windows has lots of problems with executables with spaces in
631        # the name; this function will remove them (using the ~1
632        # format):
633        mkdir(home_dir)
634        if ' ' in home_dir:
635            try:
636                import win32api
637            except ImportError:
638                print 'Error: the path "%s" has a space in it' % home_dir
639                print 'To handle these kinds of paths, the win32api module must be installed:'
640                print '  http://sourceforge.net/projects/pywin32/'
641                sys.exit(3)
642            home_dir = win32api.GetShortPathName(home_dir)
643        lib_dir = join(home_dir, 'Lib')
644        inc_dir = join(home_dir, 'Include')
645        bin_dir = join(home_dir, 'Scripts')
646    elif is_jython:
647        lib_dir = join(home_dir, 'Lib')
648        inc_dir = join(home_dir, 'Include')
649        bin_dir = join(home_dir, 'bin')
650    else:
651        lib_dir = join(home_dir, 'lib', py_version)
652        inc_dir = join(home_dir, 'include', py_version)
653        bin_dir = join(home_dir, 'bin')
654    return home_dir, lib_dir, inc_dir, bin_dir
655
656def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
657    """Install just the base environment, no distutils patches etc"""
658    if sys.executable.startswith(bin_dir):
659        print 'Please use the *system* python to run this script'
660        return
661
662    if clear:
663        rmtree(lib_dir)
664        ## FIXME: why not delete it?
665        ## Maybe it should delete everything with #!/path/to/venv/python in it
666        logger.notify('Not deleting %s', bin_dir)
667
668    if hasattr(sys, 'real_prefix'):
669        logger.notify('Using real prefix %r' % sys.real_prefix)
670        prefix = sys.real_prefix
671    else:
672        prefix = sys.prefix
673    mkdir(lib_dir)
674    fix_lib64(lib_dir)
675    stdlib_dirs = [os.path.dirname(os.__file__)]
676    if sys.platform == 'win32':
677        stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
678    elif sys.platform == 'darwin':
679        stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
680    for stdlib_dir in stdlib_dirs:
681        if not os.path.isdir(stdlib_dir):
682            continue
683        if hasattr(os, 'symlink'):
684            logger.info('Symlinking Python bootstrap modules')
685        else:
686            logger.info('Copying Python bootstrap modules')
687        logger.indent += 2
688        try:
689            for fn in os.listdir(stdlib_dir):
690                if fn != 'site-packages' and os.path.splitext(fn)[0] in REQUIRED_MODULES:
691                    copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
692        finally:
693            logger.indent -= 2
694    mkdir(join(lib_dir, 'site-packages'))
695    writefile(join(lib_dir, 'site.py'), SITE_PY)
696    writefile(join(lib_dir, 'orig-prefix.txt'), prefix)
697    site_packages_filename = join(lib_dir, 'no-global-site-packages.txt')
698    if not site_packages:
699        writefile(site_packages_filename, '')
700    else:
701        if os.path.exists(site_packages_filename):
702            logger.info('Deleting %s' % site_packages_filename)
703            os.unlink(site_packages_filename)
704
705    stdinc_dir = join(prefix, 'include', py_version)
706    if os.path.exists(stdinc_dir):
707        copyfile(stdinc_dir, inc_dir)
708    else:
709        logger.debug('No include dir %s' % stdinc_dir)
710
711    if sys.exec_prefix != prefix:
712        if sys.platform == 'win32':
713            exec_dir = join(sys.exec_prefix, 'lib')
714        elif is_jython:
715            exec_dir = join(sys.exec_prefix, 'Lib')
716        else:
717            exec_dir = join(sys.exec_prefix, 'lib', py_version)
718        for fn in os.listdir(exec_dir):
719            copyfile(join(exec_dir, fn), join(lib_dir, fn))
720
721    if is_jython:
722        # Jython has either jython-dev.jar and javalib/ dir, or just
723        # jython.jar
724        for name in 'jython-dev.jar', 'javalib', 'jython.jar':
725            src = join(prefix, name)
726            if os.path.exists(src):
727                copyfile(src, join(home_dir, name))
728        # XXX: registry should always exist after Jython 2.5rc1
729        src = join(prefix, 'registry')
730        if os.path.exists(src):
731            copyfile(src, join(home_dir, 'registry'), symlink=False)
732        copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
733                 symlink=False)
734
735    mkdir(bin_dir)
736    py_executable = join(bin_dir, os.path.basename(sys.executable))
737    if 'Python.framework' in prefix:
738        if re.search(r'/Python(?:-32|-64)*$', py_executable):
739            # The name of the python executable is not quite what
740            # we want, rename it.
741            py_executable = os.path.join(
742                    os.path.dirname(py_executable), 'python')
743
744    logger.notify('New %s executable in %s', expected_exe, py_executable)
745    if sys.executable != py_executable:
746        ## FIXME: could I just hard link?
747        executable = sys.executable
748        if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'):
749            # Cygwin misreports sys.executable sometimes
750            executable += '.exe'
751            py_executable += '.exe'
752            logger.info('Executable actually exists in %s' % executable)
753        shutil.copyfile(executable, py_executable)
754        make_exe(py_executable)
755        if sys.platform == 'win32' or sys.platform == 'cygwin':
756            pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
757            if os.path.exists(pythonw):
758                logger.info('Also created pythonw.exe')
759                shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
760
761    if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
762        secondary_exe = os.path.join(os.path.dirname(py_executable),
763                                     expected_exe)
764        py_executable_ext = os.path.splitext(py_executable)[1]
765        if py_executable_ext == '.exe':
766            # python2.4 gives an extension of '.4' :P
767            secondary_exe += py_executable_ext
768        if os.path.exists(secondary_exe):
769            logger.warn('Not overwriting existing %s script %s (you must use %s)'
770                        % (expected_exe, secondary_exe, py_executable))
771        else:
772            logger.notify('Also creating executable in %s' % secondary_exe)
773            shutil.copyfile(sys.executable, secondary_exe)
774            make_exe(secondary_exe)
775
776    if 'Python.framework' in prefix:
777        logger.debug('MacOSX Python framework detected')
778
779        # Make sure we use the the embedded interpreter inside
780        # the framework, even if sys.executable points to
781        # the stub executable in ${sys.prefix}/bin
782        # See http://groups.google.com/group/python-virtualenv/
783        #                              browse_thread/thread/17cab2f85da75951
784        shutil.copy(
785                os.path.join(
786                    prefix, 'Resources/Python.app/Contents/MacOS/%s' % os.path.basename(sys.executable)),
787                py_executable)
788
789        # Copy the framework's dylib into the virtual
790        # environment
791        virtual_lib = os.path.join(home_dir, '.Python')
792
793        if os.path.exists(virtual_lib):
794            os.unlink(virtual_lib)
795        copyfile(
796            os.path.join(prefix, 'Python'),
797            virtual_lib)
798
799        # And then change the install_name of the copied python executable
800        try:
801            call_subprocess(
802                ["install_name_tool", "-change",
803                 os.path.join(prefix, 'Python'),
804                 '@executable_path/../.Python',
805                 py_executable])
806        except:
807            logger.fatal(
808                "Could not call install_name_tool -- you must have Apple's development tools installed")
809            raise
810
811        # Some tools depend on pythonX.Y being present
812        py_executable_version = '%s.%s' % (
813            sys.version_info[0], sys.version_info[1])
814        if not py_executable.endswith(py_executable_version):
815            # symlinking pythonX.Y > python
816            pth = py_executable + '%s.%s' % (
817                    sys.version_info[0], sys.version_info[1])
818            if os.path.exists(pth):
819                os.unlink(pth)
820            os.symlink('python', pth)
821        else:
822            # reverse symlinking python -> pythonX.Y (with --python)
823            pth = join(bin_dir, 'python')
824            if os.path.exists(pth):
825                os.unlink(pth)
826            os.symlink(os.path.basename(py_executable), pth)
827
828    if sys.platform == 'win32' and ' ' in py_executable:
829        # There's a bug with subprocess on Windows when using a first
830        # argument that has a space in it.  Instead we have to quote
831        # the value:
832        py_executable = '"%s"' % py_executable
833    cmd = [py_executable, '-c', 'import sys; print sys.prefix']
834    logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
835    proc = subprocess.Popen(cmd,
836                            stdout=subprocess.PIPE)
837    proc_stdout, proc_stderr = proc.communicate()
838    proc_stdout = os.path.normcase(os.path.abspath(proc_stdout.strip()))
839    if proc_stdout != os.path.normcase(os.path.abspath(home_dir)):
840        logger.fatal(
841            'ERROR: The executable %s is not functioning' % py_executable)
842        logger.fatal(
843            'ERROR: It thinks sys.prefix is %r (should be %r)'
844            % (proc_stdout, os.path.normcase(os.path.abspath(home_dir))))
845        logger.fatal(
846            'ERROR: virtualenv is not compatible with this system or executable')
847        if sys.platform == 'win32':
848            logger.fatal(
849                '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)')
850        sys.exit(100)
851    else:
852        logger.info('Got sys.prefix result: %r' % proc_stdout)
853
854    pydistutils = os.path.expanduser('~/.pydistutils.cfg')
855    if os.path.exists(pydistutils):
856        logger.notify('Please make sure you remove any previous custom paths from '
857                      'your %s file.' % pydistutils)
858    ## FIXME: really this should be calculated earlier
859    return py_executable
860
861def install_activate(home_dir, bin_dir):
862    if sys.platform == 'win32' or is_jython and os._name == 'nt':
863        files = {'activate.bat': ACTIVATE_BAT,
864                 'deactivate.bat': DEACTIVATE_BAT}
865        if os.environ.get('OS') == 'Windows_NT' and os.environ.get('OSTYPE') == 'cygwin':
866            files['activate'] = ACTIVATE_SH
867    else:
868        files = {'activate': ACTIVATE_SH}
869    files['activate_this.py'] = ACTIVATE_THIS
870    for name, content in files.items():
871        content = content.replace('__VIRTUAL_ENV__', os.path.abspath(home_dir))
872        content = content.replace('__VIRTUAL_NAME__', os.path.basename(os.path.abspath(home_dir)))
873        content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
874        writefile(os.path.join(bin_dir, name), content)
875
876def install_distutils(lib_dir, home_dir):
877    distutils_path = os.path.join(lib_dir, 'distutils')
878    mkdir(distutils_path)
879    ## FIXME: maybe this prefix setting should only be put in place if
880    ## there's a local distutils.cfg with a prefix setting?
881    home_dir = os.path.abspath(home_dir)
882    ## FIXME: this is breaking things, removing for now:
883    #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
884    writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
885    writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
886
887def fix_lib64(lib_dir):
888    """
889    Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
890    instead of lib/pythonX.Y.  If this is such a platform we'll just create a
891    symlink so lib64 points to lib
892    """
893    if [p for p in distutils.sysconfig.get_config_vars().values()
894        if isinstance(p, basestring) and 'lib64' in p]:
895        logger.debug('This system uses lib64; symlinking lib64 to lib')
896        assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
897            "Unexpected python lib dir: %r" % lib_dir)
898        lib_parent = os.path.dirname(lib_dir)
899        assert os.path.basename(lib_parent) == 'lib', (
900            "Unexpected parent dir: %r" % lib_parent)
901        copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64'))
902
903def resolve_interpreter(exe):
904    """
905    If the executable given isn't an absolute path, search $PATH for the interpreter
906    """
907    if os.path.abspath(exe) != exe:
908        paths = os.environ.get('PATH', '').split(os.pathsep)
909        for path in paths:
910            if os.path.exists(os.path.join(path, exe)):
911                exe = os.path.join(path, exe)
912                break
913    if not os.path.exists(exe):
914        logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
915        sys.exit(3)
916    return exe
917
918############################################################
919## Relocating the environment:
920
921def make_environment_relocatable(home_dir):
922    """
923    Makes the already-existing environment use relative paths, and takes out
924    the #!-based environment selection in scripts.
925    """
926    activate_this = os.path.join(home_dir, 'bin', 'activate_this.py')
927    if not os.path.exists(activate_this):
928        logger.fatal(
929            'The environment doesn\'t have a file %s -- please re-run virtualenv '
930            'on this environment to update it' % activate_this)
931    fixup_scripts(home_dir)
932    fixup_pth_and_egg_link(home_dir)
933    ## FIXME: need to fix up distutils.cfg
934
935OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
936                  'activate', 'activate.bat', 'activate_this.py']
937
938def fixup_scripts(home_dir):
939    # This is what we expect at the top of scripts:
940    shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
941    # This is what we'll put:
942    new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
943    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"
944    bin_dir = os.path.join(home_dir, 'bin')
945    for filename in os.listdir(bin_dir):
946        filename = os.path.join(bin_dir, filename)
947        if not os.path.isfile(filename):
948            # ignore subdirs, e.g. .svn ones.
949            continue
950        f = open(filename, 'rb')
951        lines = f.readlines()
952        f.close()
953        if not lines:
954            logger.warn('Script %s is an empty file' % filename)
955            continue
956        if not lines[0].strip().startswith(shebang):
957            if os.path.basename(filename) in OK_ABS_SCRIPTS:
958                logger.debug('Cannot make script %s relative' % filename)
959            elif lines[0].strip() == new_shebang:
960                logger.info('Script %s has already been made relative' % filename)
961            else:
962                logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
963                            % (filename, shebang))
964            continue
965        logger.notify('Making script %s relative' % filename)
966        lines = [new_shebang+'\n', activate+'\n'] + lines[1:]
967        f = open(filename, 'wb')
968        f.writelines(lines)
969        f.close()
970
971def fixup_pth_and_egg_link(home_dir, sys_path=None):
972    """Makes .pth and .egg-link files use relative paths"""
973    home_dir = os.path.normcase(os.path.abspath(home_dir))
974    if sys_path is None:
975        sys_path = sys.path
976    for path in sys_path:
977        if not path:
978            path = '.'
979        if not os.path.isdir(path):
980            continue
981        path = os.path.normcase(os.path.abspath(path))
982        if not path.startswith(home_dir):
983            logger.debug('Skipping system (non-environment) directory %s' % path)
984            continue
985        for filename in os.listdir(path):
986            filename = os.path.join(path, filename)
987            if filename.endswith('.pth'):
988                if not os.access(filename, os.W_OK):
989                    logger.warn('Cannot write .pth file %s, skipping' % filename)
990                else:
991                    fixup_pth_file(filename)
992            if filename.endswith('.egg-link'):
993                if not os.access(filename, os.W_OK):
994                    logger.warn('Cannot write .egg-link file %s, skipping' % filename)
995                else:
996                    fixup_egg_link(filename)
997
998def fixup_pth_file(filename):
999    lines = []
1000    prev_lines = []
1001    f = open(filename)
1002    prev_lines = f.readlines()
1003    f.close()
1004    for line in prev_lines:
1005        line = line.strip()
1006        if (not line or line.startswith('#') or line.startswith('import ')
1007            or os.path.abspath(line) != line):
1008            lines.append(line)
1009        else:
1010            new_value = make_relative_path(filename, line)
1011            if line != new_value:
1012                logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
1013            lines.append(new_value)
1014    if lines == prev_lines:
1015        logger.info('No changes to .pth file %s' % filename)
1016        return
1017    logger.notify('Making paths in .pth file %s relative' % filename)
1018    f = open(filename, 'w')
1019    f.write('\n'.join(lines) + '\n')
1020    f.close()
1021
1022def fixup_egg_link(filename):
1023    f = open(filename)
1024    link = f.read().strip()
1025    f.close()
1026    if os.path.abspath(link) != link:
1027        logger.debug('Link in %s already relative' % filename)
1028        return
1029    new_link = make_relative_path(filename, link)
1030    logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
1031    f = open(filename, 'w')
1032    f.write(new_link)
1033    f.close()
1034
1035def make_relative_path(source, dest, dest_is_directory=True):
1036    """
1037    Make a filename relative, where the filename is dest, and it is
1038    being referred to from the filename source.
1039
1040        >>> make_relative_path('/usr/share/something/a-file.pth',
1041        ...                    '/usr/share/another-place/src/Directory')
1042        '../another-place/src/Directory'
1043        >>> make_relative_path('/usr/share/something/a-file.pth',
1044        ...                    '/home/user/src/Directory')
1045        '../../../home/user/src/Directory'
1046        >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
1047        './'
1048    """
1049    source = os.path.dirname(source)
1050    if not dest_is_directory:
1051        dest_filename = os.path.basename(dest)
1052        dest = os.path.dirname(dest)
1053    dest = os.path.normpath(os.path.abspath(dest))
1054    source = os.path.normpath(os.path.abspath(source))
1055    dest_parts = dest.strip(os.path.sep).split(os.path.sep)
1056    source_parts = source.strip(os.path.sep).split(os.path.sep)
1057    while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
1058        dest_parts.pop(0)
1059        source_parts.pop(0)
1060    full_parts = ['..']*len(source_parts) + dest_parts
1061    if not dest_is_directory:
1062        full_parts.append(dest_filename)
1063    if not full_parts:
1064        # Special case for the current directory (otherwise it'd be '')
1065        return './'
1066    return os.path.sep.join(full_parts)
1067
1068
1069
1070############################################################
1071## Bootstrap script creation:
1072
1073def create_bootstrap_script(extra_text, python_version=''):
1074    """
1075    Creates a bootstrap script, which is like this script but with
1076    extend_parser, adjust_options, and after_install hooks.
1077
1078    This returns a string that (written to disk of course) can be used
1079    as a bootstrap script with your own customizations.  The script
1080    will be the standard virtualenv.py script, with your extra text
1081    added (your extra text should be Python code).
1082
1083    If you include these functions, they will be called:
1084
1085    ``extend_parser(optparse_parser)``:
1086        You can add or remove options from the parser here.
1087
1088    ``adjust_options(options, args)``:
1089        You can change options here, or change the args (if you accept
1090        different kinds of arguments, be sure you modify ``args`` so it is
1091        only ``[DEST_DIR]``).
1092
1093    ``after_install(options, home_dir)``:
1094
1095        After everything is installed, this function is called.  This
1096        is probably the function you are most likely to use.  An
1097        example would be::
1098
1099            def after_install(options, home_dir):
1100                subprocess.call([join(home_dir, 'bin', 'easy_install'),
1101                                 'MyPackage'])
1102                subprocess.call([join(home_dir, 'bin', 'my-package-script'),
1103                                 'setup', home_dir])
1104
1105        This example immediately installs a package, and runs a setup
1106        script from that package.
1107
1108    If you provide something like ``python_version='2.4'`` then the
1109    script will start with ``#!/usr/bin/env python2.4`` instead of
1110    ``#!/usr/bin/env python``.  You can use this when the script must
1111    be run with a particular Python version.
1112    """
1113    filename = __file__
1114    if filename.endswith('.pyc'):
1115        filename = filename[:-1]
1116    f = open(filename, 'rb')
1117    content = f.read()
1118    f.close()
1119    py_exe = 'python%s' % python_version
1120    content = (('#!/usr/bin/env %s\n' % py_exe)
1121               + '## WARNING: This file is generated\n'
1122               + content)
1123    return content.replace('##EXT' 'END##', extra_text)
1124
1125import os, subprocess
1126
1127def after_install(options, home_dir):
1128    def call(*args):
1129        retcode = subprocess.call(*args)
1130        if retcode:
1131            sys.stderr.write("Exit status %d from command args %s\n" % (retcode, args))
1132            sys.exit(retcode)
1133
1134    call([join(home_dir, 'bin', 'easy_install'), 'virtualenv>=1.4.9'])
1135    call([join(home_dir, 'bin', 'easy_install'), 'pip'])
1136    call([join(home_dir, 'bin', 'easy_install'), 'paver'])
1137
1138    source_root = os.path.dirname(__file__)
1139    pavement_file = join(source_root, 'obutil', 'obutil', 'pavement.py')
1140    call([join(home_dir, 'bin', 'paver'), '-f', pavement_file,  'post_bootstrap'])
1141
1142    # link source code
1143    if not os.path.abspath(source_root).startswith(os.path.abspath(home_dir)):
1144        source_link = join(home_dir, 'src', 'openblock')
1145        print "symlinking openblock source in %s to %s" % (source_root, source_link)
1146        copyfile(source_root, source_link, symlink=True)
1147
1148
1149def adjust_options(options, args):
1150    # assume build in place unless otherwise specified
1151    if len(args) == 0:
1152        args[:] = ['./']
1153
1154def extend_parser(optparse_parser):
1155    # flip-flop the default on whether to utilize site packages
1156    optparse_parser.remove_option('--no-site-packages')
1157    optparse_parser.add_option('--use-site-packages',
1158                               dest='no_site_packages',
1159                               action='store_false',
1160                               default=True)
1161    # Use distribute by default.
1162    optparse_parser.set_defaults(use_distribute=True)
1163
1164
1165
1166##file site.py
1167SITE_PY = """
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
1298yBXo8FFND74JkgILcmKn2vJbYxD8H2/QG9E=
1299""".decode("base64").decode("zlib")
1300
1301##file ez_setup.py
1302EZ_SETUP_PY = """
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
1369178BYnMUkw==
1370""".decode("base64").decode("zlib")
1371
1372##file distribute_setup.py
1373DISTRIBUTE_SETUP_PY = """
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
1451""".decode("base64").decode("zlib")
1452
1453##file activate.sh
1454ACTIVATE_SH = """
1455eJytVFFv2jAQfs+vuIU+QDWK+tqKB6oigdRC1bBOW1sZk1yIpWAj2yGj0/77ziFAUijStPIA2Hc+
1456f/7u+64Bk0QYiEWKsMiMhRlCZjCCXNgEfKMyHSLMhOzw0IoVt+jDeazVAmbcJOdeA9Yqg5BLqSzo
1457TIKwEAmNoU3Xnhfh9hQ0W/DbA/o0QKNBCyqNAOVKaCUXKC2suBZ8lqIpskQMz9CW4J+x8d0texo+
1458Tr717thDbzLw4RWuwSYoi0z3cdvdY6m7DPy1VNoWibu9TDocB4eKeCxOwvgxGYxHg/F9/xiYXfAA
14590v7YAbBd6CS8ehaBLCktmmgSlRGpEVqiv+gPcBnBm0m+Qp6IMIGErxA4/VAoVIuFC9uE26L1ZSkS
1460QMjTlCRgFcwJAXWU/sVKu8WSk0bKo+YC4DvJRGW2DFsh52WZWqIjCM4cuRAmXM7RQE5645H7WoPT
1461Dl1LulgScozeUX/TC6jpbbVZ/QwG7Kn/GAzHoyPkF09r6xo9HzUxuDzWveDyoG2UeNCv4PJko8rw
1462FsImZRvtj572wL4QLgLSBV8qGaGxOnOewXfYGhBgGsM24cu729sutDXb9uo/HvlzExdaY0rdrxmt
1463Ys/63Z5Xgdr1GassGfO9koTqe7wDHxGNGw+Wi0p2h7Gb4YiNevd9xq7KtKpFd7j3inds0Q5FrBN7
1464LtIUYi5St1/NMi7LKdZpDhdLuwZ6FwkTmhsTUMaMR2SNdc7XLaoXFrahqQdTqtUs6Myu4YoUu6vb
1465guspCFm4ytsL6sNB8IFtu7UjFWlUnO00s7nhDWqssdth0Lu567OHx/H9w+TkjYWKd8ItyvlTAo+S
1466LxBeanVf/GmhP+rsoR8a4EwpeEpTgRgin0OPdiQZdy7CctYrLcq5XR5BhMTa5VWnk+f5xRtasvrq
1467gsZBx6jY5lxjh7sqnbrvnisQp1T6KNiX6fQV9m/D1GC9SvPEQ1v7g+WIrxjaMf9Js/QT5uh/ztB/
1468n5/b2Uk0/AXm/2MV
1469""".decode("base64").decode("zlib")
1470
1471##file activate.bat
1472ACTIVATE_BAT = """
1473eJyFUssKgzAQvAfyD3swYH+hItSiVKlGsalQKOyhauvFHOr/U+MzFcWc9jEzO7vkVLw+EmRZUvIt
1474GsiCVNydED2e2YhahkgJJVUJtWwgL8qqLnJI0jhKBJiUQPsUv6/YRmJcKDkMlBGOcehOmptctgJj
1475e2IP4cfcjyNvFOwVp/JSdWqMygq+MthmkwHNojmfhjuRh3iAGffncsPYhpl2mm5sbY+9QzjC7ylt
1476sFy6LTEL3rKRcLsGicrXV++4HVz1jzN4Vta+BnsingM+nMLSiB53KfkBsnmnEA==
1477""".decode("base64").decode("zlib")
1478
1479##file deactivate.bat
1480DEACTIVATE_BAT = """
1481eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q
1482FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL
1483i2dASrm4rFz9XLgAwJNbyQ==
1484""".decode("base64").decode("zlib")
1485
1486##file distutils-init.py
1487DISTUTILS_INIT = """
1488eJytVl2L6zYQffevGBKK7XavKe3bhVBo78uFSyml0IdlEVpbTtR1JCMpm6S/vjOSY0v+uO1DDbs4
14890tF8nJk5sjz32jjQNpPhzd7H1ys3SqqjhcfCL1q18vgbN1YY2Kc/pQWlHXB4l8ZdeCfUO5x1c+nE
1490E1gNVwE1V3CxAqQDp6GVqgF3EmBd08nXLGukUfws4IDBVD13p2pYoS3rLk52ltF6hPhLS1XM4EUc
1491VsVYKzvBWPkE+WgmLzPZjkaUNmd6KVI3JRwWoRSLM6P98mMG+Dw4q+il8Ev07P7ATCNmRlfQ8/qN
1492HwVwB99Y4H0vMHAi6BWZUoEhoqXTNXdSK+A2LN6tE+fJ0E+7MhOdFSEM5lNgrJIKWXDF908wy87D
1493xE3UoHsxkegZTaHIHGNSSYfm+ntelpURvCnK7NEWBI/ap/b8Z1m232N2rj7B60V2DRM3B5NpaLSw
1494KnfwpvQVTviHOR+F88lhQyBAGlE7be6DoRNg9ldsG3218IHa6MRNU+tGBEYIggwafRk6yzsXDcVU
14959Ua08kYxt+F3x12LRaQi52j0xx/ywFxrdMRqVevzmaummlIYEp0WsCAaX8cFb6buuLUTqEgQQ6/Q
149604iWRoF38m/BdE8VtlBY0bURiB6KG1crpMZwc2fIjqWh+1UrkSLpWUIP8PySwLKv4qPGSVqDuMPy
1497dywQ+gS7L1irXVkm5pJsq3l+Ib1lMOvUrxI+/mBBY4KB+WpUtcO06RtzckNvQ6vYj1lGoZM2sdDG
1498fryJPYJVn/Cfka8XSqNaoLKhmOlqXMzW9+YBVp1EtIThZtOwzCRvMaARa+0xD0b2kcaJGwJsMbc7
1499hLUfY4vKvsCOBdvDnyfuRbzmXRdGTZgPF7oGQkJACWVD22IMQdhx0npt5S2f+pXO+OwH6d+hwiS5
15007IJOjcK2emj1zBy1aONHByfAMoraw6WlrSIFTbGghqASoRCjVncYROFpXM4uYSqhGnuVeGvks4jz
1501cjnCoR5GnPW7KOh4maVbdFeoplgJ3wh3MSrAsv/QuMjOspnTKRl1fTYqqNisv7uTVnhF1GhoBFbp
1502lh+OcXN2riA5ZrYXtWxlfcDuC8U5kLoN3CCJYXGpesO6dx6rU0zGMtjU6cNlmW0Fid8Sja4ZG+Z3
1503fTPbyj+mZnZ2wSQK8RaT9Km0ySRuLpm0DkUUL0ra3WQ2BgGJ7v9I9SKqNKZ/IR4R28RHm+vEz5ic
1504nZ2IH7bfub8pU1PR3gr10W7xLTfHh6Z6bgZ7K14G7Mj/1z5J6MFo6V5e07H0Ou78dTyeI+mxKOpI
1505eC2KMSj6HKxd6Uudf/n886fPv+f++x1lbASlmjQuPz8OvGA0j7j2eCu/4bcW6SFeCuNJ0W1GQHI5
1506iwC9Ey0bjtHd9P4dPA++XxLnZDVuxvFEtlm3lf5a2c02u2LRYXHH/AOs8pIa
1507""".decode("base64").decode("zlib")
1508
1509##file distutils.cfg
1510DISTUTILS_CFG = """
1511eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
1512xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
15139FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
1514""".decode("base64").decode("zlib")
1515
1516##file activate_this.py
1517ACTIVATE_THIS = """
1518eJyNUk2L3DAMvftXiCxLEphmSvc2MIcu9NaWHnopwxCcRNlRN7GD7clM/n0lp5mPZQs1JLb8pKcn
1519WUmSPE9w9GReAM9Yt9RhFg7kSzmtoKE6ZGU0ynJ7AfIcJnuEE3Wd0nWgUQcEQWEkF466QzMCf+Ss
15206dGEQqmfgtbaQIWcDxs4HdBElv7og1wBg3gmH0TMjykcrAEyAd3gkP8rMDaocMDbHBWZ9RBdVZIk
1521SgU3bRTwWjQrPNc4BPiue/zinHUz7DRxws/eowtkTUSyiMhKfi2y3NHMdXX0itcOpYMOh3Ww61g8
1522luJSDFP6tmH3ftyki2eeJ7mifrAugJ/8crReqUqztC0fC4kuGnKGxWf/snXlZb8kzXMmboW0GDod
1523Wut62G4hPZF5+pTO5XtiKYOuX/UL+ptcvy2ZTPKvIP1KFdeTiuuHxTXNFXYe/5+km0nmJ3r0KTxG
1524YSM6z23fbZ7276Tg9x5LdiuFjok7noks1sP2tWscpeRX6KaRnRuT3WnKlQQ51F3JlC2dmSvSRENd
1525j3wvetUDfLOjDDLPYtPwjDJb7yHYeNXyMPMLtdEQKRtl8HQrdLdX3O4YxZP7RvfcNH6ZCPMsi8td
1526qZvLAN7yFnoY0DSZhOUXj4WWy+tZ8190ud1tPu5Zzy2N+gOGaVfA
1527""".decode("base64").decode("zlib")
1528
1529if __name__ == '__main__':
1530    main()
1531
1532## TODO:
1533## Copy python.exe.manifest
1534## Monkeypatch distutils.sysconfig
Note: See TracBrowser for help on using the repository browser.