Zine

open source content publishing system


source: scripts/setup-virtualenv @ 1375:01b77c91b28e

Revision 1375:01b77c91b28e, 68.5 KB checked in by mitsuhiko, 2 years ago (diff)

Merged

  • Property exe set to *
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.6"
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, 4):
20        print 'ERROR: %s' % e
21        print 'ERROR: this script requires Python 2.5 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 os.environ.get('PYTHONHOME'):
519        if sys.platform == 'win32':
520            name = '%PYTHONHOME%'
521        else:
522            name = '$PYTHONHOME'
523        logger.warn('%s is set; this can cause problems creating environments' % name)
524
525    if options.relocatable:
526        make_environment_relocatable(home_dir)
527        return
528
529    create_environment(home_dir, site_packages=not options.no_site_packages, clear=options.clear,
530                       unzip_setuptools=options.unzip_setuptools,
531                       use_distribute=options.use_distribute)
532    if 'after_install' in globals():
533        after_install(options, home_dir)
534
535def call_subprocess(cmd, show_stdout=True,
536                    filter_stdout=None, cwd=None,
537                    raise_on_returncode=True, extra_env=None):
538    cmd_parts = []
539    for part in cmd:
540        if len(part) > 40:
541            part = part[:30]+"..."+part[-5:]
542        if ' ' in part or '\n' in part or '"' in part or "'" in part:
543            part = '"%s"' % part.replace('"', '\\"')
544        cmd_parts.append(part)
545    cmd_desc = ' '.join(cmd_parts)
546    if show_stdout:
547        stdout = None
548    else:
549        stdout = subprocess.PIPE
550    logger.debug("Running command %s" % cmd_desc)
551    if extra_env:
552        env = os.environ.copy()
553        env.update(extra_env)
554    else:
555        env = None
556    try:
557        proc = subprocess.Popen(
558            cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
559            cwd=cwd, env=env)
560    except Exception, e:
561        logger.fatal(
562            "Error %s while executing command %s" % (e, cmd_desc))
563        raise
564    all_output = []
565    if stdout is not None:
566        stdout = proc.stdout
567        while 1:
568            line = stdout.readline()
569            if not line:
570                break
571            line = line.rstrip()
572            all_output.append(line)
573            if filter_stdout:
574                level = filter_stdout(line)
575                if isinstance(level, tuple):
576                    level, line = level
577                logger.log(level, line)
578                if not logger.stdout_level_matches(level):
579                    logger.show_progress()
580            else:
581                logger.info(line)
582    else:
583        proc.communicate()
584    proc.wait()
585    if proc.returncode:
586        if raise_on_returncode:
587            if all_output:
588                logger.notify('Complete output from command %s:' % cmd_desc)
589                logger.notify('\n'.join(all_output) + '\n----------------------------------------')
590            raise OSError(
591                "Command %s failed with error code %s"
592                % (cmd_desc, proc.returncode))
593        else:
594            logger.warn(
595                "Command %s had error code %s"
596                % (cmd_desc, proc.returncode))
597
598
599def create_environment(home_dir, site_packages=True, clear=False,
600                       unzip_setuptools=False, use_distribute=False):
601    """
602    Creates a new environment in ``home_dir``.
603
604    If ``site_packages`` is true (the default) then the global
605    ``site-packages/`` directory will be on the path.
606
607    If ``clear`` is true (default False) then the environment will
608    first be cleared.
609    """
610    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
611
612    py_executable = os.path.abspath(install_python(
613        home_dir, lib_dir, inc_dir, bin_dir,
614        site_packages=site_packages, clear=clear))
615
616    install_distutils(lib_dir, home_dir)
617
618    if use_distribute or os.environ.get('VIRTUALENV_USE_DISTRIBUTE'):
619        install_distribute(py_executable, unzip=unzip_setuptools)
620    else:
621        install_setuptools(py_executable, unzip=unzip_setuptools)
622
623    install_pip(py_executable)
624
625    install_activate(home_dir, bin_dir)
626
627def path_locations(home_dir):
628    """Return the path locations for the environment (where libraries are,
629    where scripts go, etc)"""
630    # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
631    # prefix arg is broken: http://bugs.python.org/issue3386
632    if sys.platform == 'win32':
633        # Windows has lots of problems with executables with spaces in
634        # the name; this function will remove them (using the ~1
635        # format):
636        mkdir(home_dir)
637        if ' ' in home_dir:
638            try:
639                import win32api
640            except ImportError:
641                print 'Error: the path "%s" has a space in it' % home_dir
642                print 'To handle these kinds of paths, the win32api module must be installed:'
643                print '  http://sourceforge.net/projects/pywin32/'
644                sys.exit(3)
645            home_dir = win32api.GetShortPathName(home_dir)
646        lib_dir = join(home_dir, 'Lib')
647        inc_dir = join(home_dir, 'Include')
648        bin_dir = join(home_dir, 'Scripts')
649    elif is_jython:
650        lib_dir = join(home_dir, 'Lib')
651        inc_dir = join(home_dir, 'Include')
652        bin_dir = join(home_dir, 'bin')
653    else:
654        lib_dir = join(home_dir, 'lib', py_version)
655        inc_dir = join(home_dir, 'include', py_version)
656        bin_dir = join(home_dir, 'bin')
657    return home_dir, lib_dir, inc_dir, bin_dir
658
659def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
660    """Install just the base environment, no distutils patches etc"""
661    if sys.executable.startswith(bin_dir):
662        print 'Please use the *system* python to run this script'
663        return
664
665    if clear:
666        rmtree(lib_dir)
667        ## FIXME: why not delete it?
668        ## Maybe it should delete everything with #!/path/to/venv/python in it
669        logger.notify('Not deleting %s', bin_dir)
670
671    if hasattr(sys, 'real_prefix'):
672        logger.notify('Using real prefix %r' % sys.real_prefix)
673        prefix = sys.real_prefix
674    else:
675        prefix = sys.prefix
676    mkdir(lib_dir)
677    fix_lib64(lib_dir)
678    stdlib_dirs = [os.path.dirname(os.__file__)]
679    if sys.platform == 'win32':
680        stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
681    elif sys.platform == 'darwin':
682        stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
683    for stdlib_dir in stdlib_dirs:
684        if not os.path.isdir(stdlib_dir):
685            continue
686        if hasattr(os, 'symlink'):
687            logger.info('Symlinking Python bootstrap modules')
688        else:
689            logger.info('Copying Python bootstrap modules')
690        logger.indent += 2
691        try:
692            for fn in os.listdir(stdlib_dir):
693                if fn != 'site-packages' and os.path.splitext(fn)[0] in REQUIRED_MODULES:
694                    copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
695        finally:
696            logger.indent -= 2
697    mkdir(join(lib_dir, 'site-packages'))
698    writefile(join(lib_dir, 'site.py'), SITE_PY)
699    writefile(join(lib_dir, 'orig-prefix.txt'), prefix)
700    site_packages_filename = join(lib_dir, 'no-global-site-packages.txt')
701    if not site_packages:
702        writefile(site_packages_filename, '')
703    else:
704        if os.path.exists(site_packages_filename):
705            logger.info('Deleting %s' % site_packages_filename)
706            os.unlink(site_packages_filename)
707
708    stdinc_dir = join(prefix, 'include', py_version)
709    if os.path.exists(stdinc_dir):
710        copyfile(stdinc_dir, inc_dir)
711    else:
712        logger.debug('No include dir %s' % stdinc_dir)
713
714    if sys.exec_prefix != prefix:
715        if sys.platform == 'win32':
716            exec_dir = join(sys.exec_prefix, 'lib')
717        elif is_jython:
718            exec_dir = join(sys.exec_prefix, 'Lib')
719        else:
720            exec_dir = join(sys.exec_prefix, 'lib', py_version)
721        for fn in os.listdir(exec_dir):
722            copyfile(join(exec_dir, fn), join(lib_dir, fn))
723
724    if is_jython:
725        # Jython has either jython-dev.jar and javalib/ dir, or just
726        # jython.jar
727        for name in 'jython-dev.jar', 'javalib', 'jython.jar':
728            src = join(prefix, name)
729            if os.path.exists(src):
730                copyfile(src, join(home_dir, name))
731        # XXX: registry should always exist after Jython 2.5rc1
732        src = join(prefix, 'registry')
733        if os.path.exists(src):
734            copyfile(src, join(home_dir, 'registry'), symlink=False)
735        copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
736                 symlink=False)
737
738    mkdir(bin_dir)
739    py_executable = join(bin_dir, os.path.basename(sys.executable))
740    if 'Python.framework' in prefix:
741        if py_executable.endswith('/Python'):
742            # The name of the python executable is not quite what
743            # we want, rename it.
744            py_executable = os.path.join(
745                    os.path.dirname(py_executable), 'python')
746
747    logger.notify('New %s executable in %s', expected_exe, py_executable)
748    if sys.executable != py_executable:
749        ## FIXME: could I just hard link?
750        executable = sys.executable
751        if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'):
752            # Cygwin misreports sys.executable sometimes
753            executable += '.exe'
754            py_executable += '.exe'
755            logger.info('Executable actually exists in %s' % executable)
756        shutil.copyfile(executable, py_executable)
757        make_exe(py_executable)
758        if sys.platform == 'win32' or sys.platform == 'cygwin':
759            pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
760            if os.path.exists(pythonw):
761                logger.info('Also created pythonw.exe')
762                shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
763
764    if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
765        secondary_exe = os.path.join(os.path.dirname(py_executable),
766                                     expected_exe)
767        py_executable_ext = os.path.splitext(py_executable)[1]
768        if py_executable_ext == '.exe':
769            # python2.4 gives an extension of '.4' :P
770            secondary_exe += py_executable_ext
771        if os.path.exists(secondary_exe):
772            logger.warn('Not overwriting existing %s script %s (you must use %s)'
773                        % (expected_exe, secondary_exe, py_executable))
774        else:
775            logger.notify('Also creating executable in %s' % secondary_exe)
776            shutil.copyfile(sys.executable, secondary_exe)
777            make_exe(secondary_exe)
778
779    if 'Python.framework' in prefix:
780        logger.debug('MacOSX Python framework detected')
781
782        # Make sure we use the the embedded interpreter inside
783        # the framework, even if sys.executable points to
784        # the stub executable in ${sys.prefix}/bin
785        # See http://groups.google.com/group/python-virtualenv/
786        #                              browse_thread/thread/17cab2f85da75951
787        shutil.copy(
788                os.path.join(
789                    prefix, 'Resources/Python.app/Contents/MacOS/Python'),
790                py_executable)
791
792        # Copy the framework's dylib into the virtual
793        # environment
794        virtual_lib = os.path.join(home_dir, '.Python')
795
796        if os.path.exists(virtual_lib):
797            os.unlink(virtual_lib)
798        copyfile(
799            os.path.join(prefix, 'Python'),
800            virtual_lib)
801
802        # And then change the install_name of the copied python executable
803        try:
804            call_subprocess(
805                ["install_name_tool", "-change",
806                 os.path.join(prefix, 'Python'),
807                 '@executable_path/../.Python',
808                 py_executable])
809        except:
810            logger.fatal(
811                "Could not call install_name_tool -- you must have Apple's development tools installed")
812            raise
813
814        # Some tools depend on pythonX.Y being present
815        py_executable_version = '%s.%s' % (
816            sys.version_info[0], sys.version_info[1])
817        if not py_executable.endswith(py_executable_version):
818            # symlinking pythonX.Y > python
819            pth = py_executable + '%s.%s' % (
820                    sys.version_info[0], sys.version_info[1])
821            if os.path.exists(pth):
822                os.unlink(pth)
823            os.symlink('python', pth)
824        else:
825            # reverse symlinking python -> pythonX.Y (with --python)
826            pth = join(bin_dir, 'python')
827            if os.path.exists(pth):
828                os.unlink(pth)
829            os.symlink(os.path.basename(py_executable), pth)
830
831    if sys.platform == 'win32' and ' ' in py_executable:
832        # There's a bug with subprocess on Windows when using a first
833        # argument that has a space in it.  Instead we have to quote
834        # the value:
835        py_executable = '"%s"' % py_executable
836    cmd = [py_executable, '-c', 'import sys; print sys.prefix']
837    logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
838    proc = subprocess.Popen(cmd,
839                            stdout=subprocess.PIPE)
840    proc_stdout, proc_stderr = proc.communicate()
841    proc_stdout = os.path.normcase(os.path.abspath(proc_stdout.strip()))
842    if proc_stdout != os.path.normcase(os.path.abspath(home_dir)):
843        logger.fatal(
844            'ERROR: The executable %s is not functioning' % py_executable)
845        logger.fatal(
846            'ERROR: It thinks sys.prefix is %r (should be %r)'
847            % (proc_stdout, os.path.normcase(os.path.abspath(home_dir))))
848        logger.fatal(
849            'ERROR: virtualenv is not compatible with this system or executable')
850        if sys.platform == 'win32':
851            logger.fatal(
852                '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)')
853        sys.exit(100)
854    else:
855        logger.info('Got sys.prefix result: %r' % proc_stdout)
856
857    pydistutils = os.path.expanduser('~/.pydistutils.cfg')
858    if os.path.exists(pydistutils):
859        logger.notify('Please make sure you remove any previous custom paths from '
860                      'your %s file.' % pydistutils)
861    ## FIXME: really this should be calculated earlier
862    return py_executable
863
864def install_activate(home_dir, bin_dir):
865    if sys.platform == 'win32' or is_jython and os._name == 'nt':
866        files = {'activate.bat': ACTIVATE_BAT,
867                 'deactivate.bat': DEACTIVATE_BAT}
868        if os.environ.get('OS') == 'Windows_NT' and os.environ.get('OSTYPE') == 'cygwin':
869            files['activate'] = ACTIVATE_SH
870    else:
871        files = {'activate': ACTIVATE_SH}
872    files['activate_this.py'] = ACTIVATE_THIS
873    for name, content in files.items():
874        content = content.replace('__VIRTUAL_ENV__', os.path.abspath(home_dir))
875        content = content.replace('__VIRTUAL_NAME__', os.path.basename(os.path.abspath(home_dir)))
876        content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
877        writefile(os.path.join(bin_dir, name), content)
878
879def install_distutils(lib_dir, home_dir):
880    distutils_path = os.path.join(lib_dir, 'distutils')
881    mkdir(distutils_path)
882    ## FIXME: maybe this prefix setting should only be put in place if
883    ## there's a local distutils.cfg with a prefix setting?
884    home_dir = os.path.abspath(home_dir)
885    ## FIXME: this is breaking things, removing for now:
886    #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
887    writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
888    writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
889
890def fix_lib64(lib_dir):
891    """
892    Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
893    instead of lib/pythonX.Y.  If this is such a platform we'll just create a
894    symlink so lib64 points to lib
895    """
896    if [p for p in distutils.sysconfig.get_config_vars().values()
897        if isinstance(p, basestring) and 'lib64' in p]:
898        logger.debug('This system uses lib64; symlinking lib64 to lib')
899        assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
900            "Unexpected python lib dir: %r" % lib_dir)
901        lib_parent = os.path.dirname(lib_dir)
902        assert os.path.basename(lib_parent) == 'lib', (
903            "Unexpected parent dir: %r" % lib_parent)
904        copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64'))
905
906def resolve_interpreter(exe):
907    """
908    If the executable given isn't an absolute path, search $PATH for the interpreter
909    """
910    if os.path.abspath(exe) != exe:
911        paths = os.environ.get('PATH', '').split(os.pathsep)
912        for path in paths:
913            if os.path.exists(os.path.join(path, exe)):
914                exe = os.path.join(path, exe)
915                break
916    if not os.path.exists(exe):
917        logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
918        sys.exit(3)
919    return exe
920
921############################################################
922## Relocating the environment:
923
924def make_environment_relocatable(home_dir):
925    """
926    Makes the already-existing environment use relative paths, and takes out
927    the #!-based environment selection in scripts.
928    """
929    activate_this = os.path.join(home_dir, 'bin', 'activate_this.py')
930    if not os.path.exists(activate_this):
931        logger.fatal(
932            'The environment doesn\'t have a file %s -- please re-run virtualenv '
933            'on this environment to update it' % activate_this)
934    fixup_scripts(home_dir)
935    fixup_pth_and_egg_link(home_dir)
936    ## FIXME: need to fix up distutils.cfg
937
938OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
939                  'activate', 'activate.bat', 'activate_this.py']
940
941def fixup_scripts(home_dir):
942    # This is what we expect at the top of scripts:
943    shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
944    # This is what we'll put:
945    new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
946    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"
947    bin_dir = os.path.join(home_dir, 'bin')
948    for filename in os.listdir(bin_dir):
949        filename = os.path.join(bin_dir, filename)
950        if not os.path.isfile(filename):
951            # ignore subdirs, e.g. .svn ones.
952            continue
953        f = open(filename, 'rb')
954        lines = f.readlines()
955        f.close()
956        if not lines:
957            logger.warn('Script %s is an empty file' % filename)
958            continue
959        if not lines[0].strip().startswith(shebang):
960            if os.path.basename(filename) in OK_ABS_SCRIPTS:
961                logger.debug('Cannot make script %s relative' % filename)
962            elif lines[0].strip() == new_shebang:
963                logger.info('Script %s has already been made relative' % filename)
964            else:
965                logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
966                            % (filename, shebang))
967            continue
968        logger.notify('Making script %s relative' % filename)
969        lines = [new_shebang+'\n', activate+'\n'] + lines[1:]
970        f = open(filename, 'wb')
971        f.writelines(lines)
972        f.close()
973
974def fixup_pth_and_egg_link(home_dir, sys_path=None):
975    """Makes .pth and .egg-link files use relative paths"""
976    home_dir = os.path.normcase(os.path.abspath(home_dir))
977    if sys_path is None:
978        sys_path = sys.path
979    for path in sys_path:
980        if not path:
981            path = '.'
982        if not os.path.isdir(path):
983            continue
984        path = os.path.normcase(os.path.abspath(path))
985        if not path.startswith(home_dir):
986            logger.debug('Skipping system (non-environment) directory %s' % path)
987            continue
988        for filename in os.listdir(path):
989            filename = os.path.join(path, filename)
990            if filename.endswith('.pth'):
991                if not os.access(filename, os.W_OK):
992                    logger.warn('Cannot write .pth file %s, skipping' % filename)
993                else:
994                    fixup_pth_file(filename)
995            if filename.endswith('.egg-link'):
996                if not os.access(filename, os.W_OK):
997                    logger.warn('Cannot write .egg-link file %s, skipping' % filename)
998                else:
999                    fixup_egg_link(filename)
1000
1001def fixup_pth_file(filename):
1002    lines = []
1003    prev_lines = []
1004    f = open(filename)
1005    prev_lines = f.readlines()
1006    f.close()
1007    for line in prev_lines:
1008        line = line.strip()
1009        if (not line or line.startswith('#') or line.startswith('import ')
1010            or os.path.abspath(line) != line):
1011            lines.append(line)
1012        else:
1013            new_value = make_relative_path(filename, line)
1014            if line != new_value:
1015                logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
1016            lines.append(new_value)
1017    if lines == prev_lines:
1018        logger.info('No changes to .pth file %s' % filename)
1019        return
1020    logger.notify('Making paths in .pth file %s relative' % filename)
1021    f = open(filename, 'w')
1022    f.write('\n'.join(lines) + '\n')
1023    f.close()
1024
1025def fixup_egg_link(filename):
1026    f = open(filename)
1027    link = f.read().strip()
1028    f.close()
1029    if os.path.abspath(link) != link:
1030        logger.debug('Link in %s already relative' % filename)
1031        return
1032    new_link = make_relative_path(filename, link)
1033    logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
1034    f = open(filename, 'w')
1035    f.write(new_link)
1036    f.close()
1037
1038def make_relative_path(source, dest, dest_is_directory=True):
1039    """
1040    Make a filename relative, where the filename is dest, and it is
1041    being referred to from the filename source.
1042
1043        >>> make_relative_path('/usr/share/something/a-file.pth',
1044        ...                    '/usr/share/another-place/src/Directory')
1045        '../another-place/src/Directory'
1046        >>> make_relative_path('/usr/share/something/a-file.pth',
1047        ...                    '/home/user/src/Directory')
1048        '../../../home/user/src/Directory'
1049        >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
1050        './'
1051    """
1052    source = os.path.dirname(source)
1053    if not dest_is_directory:
1054        dest_filename = os.path.basename(dest)
1055        dest = os.path.dirname(dest)
1056    dest = os.path.normpath(os.path.abspath(dest))
1057    source = os.path.normpath(os.path.abspath(source))
1058    dest_parts = dest.strip(os.path.sep).split(os.path.sep)
1059    source_parts = source.strip(os.path.sep).split(os.path.sep)
1060    while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
1061        dest_parts.pop(0)
1062        source_parts.pop(0)
1063    full_parts = ['..']*len(source_parts) + dest_parts
1064    if not dest_is_directory:
1065        full_parts.append(dest_filename)
1066    if not full_parts:
1067        # Special case for the current directory (otherwise it'd be '')
1068        return './'
1069    return os.path.sep.join(full_parts)
1070
1071
1072
1073############################################################
1074## Bootstrap script creation:
1075
1076def create_bootstrap_script(extra_text, python_version=''):
1077    """
1078    Creates a bootstrap script, which is like this script but with
1079    extend_parser, adjust_options, and after_install hooks.
1080
1081    This returns a string that (written to disk of course) can be used
1082    as a bootstrap script with your own customizations.  The script
1083    will be the standard virtualenv.py script, with your extra text
1084    added (your extra text should be Python code).
1085
1086    If you include these functions, they will be called:
1087
1088    ``extend_parser(optparse_parser)``:
1089        You can add or remove options from the parser here.
1090
1091    ``adjust_options(options, args)``:
1092        You can change options here, or change the args (if you accept
1093        different kinds of arguments, be sure you modify ``args`` so it is
1094        only ``[DEST_DIR]``).
1095
1096    ``after_install(options, home_dir)``:
1097
1098        After everything is installed, this function is called.  This
1099        is probably the function you are most likely to use.  An
1100        example would be::
1101
1102            def after_install(options, home_dir):
1103                subprocess.call([join(home_dir, 'bin', 'easy_install'),
1104                                 'MyPackage'])
1105                subprocess.call([join(home_dir, 'bin', 'my-package-script'),
1106                                 'setup', home_dir])
1107
1108        This example immediately installs a package, and runs a setup
1109        script from that package.
1110
1111    If you provide something like ``python_version='2.4'`` then the
1112    script will start with ``#!/usr/bin/env python2.4`` instead of
1113    ``#!/usr/bin/env python``.  You can use this when the script must
1114    be run with a particular Python version.
1115    """
1116    filename = __file__
1117    if filename.endswith('.pyc'):
1118        filename = filename[:-1]
1119    f = open(filename, 'rb')
1120    content = f.read()
1121    f.close()
1122    py_exe = 'python%s' % python_version
1123    content = (('#!/usr/bin/env %s\n' % py_exe)
1124               + '## WARNING: This file is generated\n'
1125               + content)
1126    return content.replace('##EXT' 'END##', extra_text)
1127
1128
1129import os
1130import sys
1131from subprocess import call
1132
1133# requirements without lxml, because lxml is special for OS X
1134REQUIREMENTS = [
1135    'Werkzeug>=0.6',
1136    'Jinja2>=2.1',
1137    'SQLAlchemy>=0.6',
1138    'pytz',
1139    'Babel>=0.9.4',
1140    'sqlalchemy-migrate>=0.6'
1141]
1142
1143# for python 2.4/2.5 we want simplejson installed too.
1144if sys.version_info < (2, 6):
1145    REQUIREMENTS.append('simplejson')
1146
1147# os x has some problems with lxml, make sure the user has port installed
1148# so that we can compile lxml
1149lxml_static_deps=False
1150if sys.platform == 'darwin':
1151    print '=' * 60
1152    print 'It appears that you are using OS X.  If an installation error'
1153    print 'occurs on installing lxml, please make sure you have port'
1154    print 'installed.'
1155    print '=' * 60
1156
1157    # no idea if that actually helps, but let's hope it does :D
1158    _dyld_path = os.environ.get('DYLD_LIBRARY_PATH', '')
1159    if _dyld_path:
1160        _dyld_path += ':'
1161    _dyld_path += '/opt/local/lib'
1162    os.environ['DYLD_LIBRARY_PATH']= _dyld_path
1163    lxml_static_deps = True
1164
1165def install(home_dir, *args, **kw):
1166    static_deps = kw.pop('static_deps', False)
1167    if kw:
1168        raise TypeError('too many keyword arguments')
1169    env = None
1170    if static_deps:
1171        env = dict(os.environ.items())
1172        env['STATIC_DEPS'] = 'true'
1173    call([os.path.join(home_dir, 'bin', 'easy_install')] + list(args), env=env)
1174
1175def after_install(options, home_dir):
1176    site_packages = os.path.normpath(os.path.join(home_dir, 'lib', 'python%d.%d'
1177        % sys.version_info[:2], 'site-packages'))
1178    for requirement in REQUIREMENTS:
1179        install(home_dir, requirement)
1180    install(home_dir, 'lxml>=2.0', static_deps=lxml_static_deps)
1181    call(['ln', '-s', '../zine', os.path.join(site_packages, 'zine')])
1182
1183
1184##file site.py
1185SITE_PY = """
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
1316yBXo8FFND74JkgILcmKn2vJbYxD8H2/QG9E=
1317""".decode("base64").decode("zlib")
1318
1319##file ez_setup.py
1320EZ_SETUP_PY = """
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
1387178BYnMUkw==
1388""".decode("base64").decode("zlib")
1389
1390##file distribute_setup.py
1391DISTRIBUTE_SETUP_PY = """
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
1469""".decode("base64").decode("zlib")
1470
1471##file activate.sh
1472ACTIVATE_SH = """
1473eJytVF1v2jAUfc+vuA19aKvRiNdOPFAVqUgtrQhj0kplTHJDLAUb2Q5ZO+2/7zokbQKs0rTmgeDc
147473OObwemqTCQiAxhnRsLS4TcYAyFsCn4RuU6QlgKGfDIii236MNFotUaltykF14HXlQOEZdSWdC5
1475BGEhFhojm714Xox1FJydwy8P6BEJPEFXgn/KHu5u2Gw0mX4b3LHHwfTWh2f4CjZFWXq6x33uH3N9
147688CfG6Vt6fj2LZcGLRwElfZEeOW7s5vcpCrPYojRUs/lUMBlDK8m/QJFKqIUUr5F4PQiU6TWa2e2
1477KbclXlUqQi3iWUa4WQUrqk0w0L9EaXfYcAK2CjWXAN8JW5XbymyFXFVpWo4OCDh1fUOUcrlCAwWR
1478xGP38wIOcCqr0Wyoc4z3wL0ehIRnV+1OP8JbNhtOwtHD+AjI5Whd3YLnbzSFvWMshb0DksjxgKOw
14799yFFlbluYedSW4fj2XtjJ9QXNdIHXyoZo7E6d0LDvd46EGKWQO1wsle960y1QuvSvz0S9c4utMaM
14802JcWtlwLvszQNDXdru15jVb7PmONI2O+V4HQnMc7kCjBuJN3dWh4B4xdj8ZsPLgfMnZVuTXV7+04
1481e4VWGLsZhYPruyF7nDzcP073ENonwNWvmSvT+Qu6Eyj5GmHeyjv3FyUBNNqhIDrgVCl4RtfCoBM6
1482DOiLJOWuRFRtCKUF4dkIQYTU2s1VEBRFcfmKlrS+vaT7EBiV2IJrDLjLErSF99RocUGpjzY7Xyye
14834X02zAy2s5x9MOj5eyApZE/RTq6ftEw+YZH85xL59wVSLw+C4Q8Om94M
1484""".decode("base64").decode("zlib")
1485
1486##file activate.bat
1487ACTIVATE_BAT = """
1488eJx9kE0OgjAQhfdNeodZ0ASuICERA1EilAaRlckspFU2dCH3jxSQNgad1fx87+W1e3l/atBKUfKS
1489AzRZVV/jHFPeRIjOhEgJJZ2CXg/QStX1sgVRlYWowacExjL6eRN5wjtSEiySD45lnqyeP7VsA2OL
1490mcE2zhFbMcfItw/gcZEiBmC5P8Hi+jTnGZvvNOOKhfDQg4bLORNm3s41aSfc3HcWts7O77Ib4iHj
1491S87QEaY8oeQNhWR0fg==
1492""".decode("base64").decode("zlib")
1493
1494##file deactivate.bat
1495DEACTIVATE_BAT = """
1496eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q
1497FlWqXJpcICVYpGzx2OAY4gExGchANxcopMqFxVCQUi4uK1c/Fy4AyB051w==
1498""".decode("base64").decode("zlib")
1499
1500##file distutils-init.py
1501DISTUTILS_INIT = """
1502eJytVl2L6zYQffevGBKK7XavKe3bhVBo78uFSyml0IdlEVpbTtR1JCMpm6S/vjOSY0v+uO1DDbs4
15030tF8nJk5sjz32jjQNpPhzd7H1ys3SqqjhcfCL1q18vgbN1YY2Kc/pQWlHXB4l8ZdeCfUO5x1c+nE
1504E1gNVwE1V3CxAqQDp6GVqgF3EmBd08nXLGukUfws4IDBVD13p2pYoS3rLk52ltF6hPhLS1XM4EUc
1505VsVYKzvBWPkE+WgmLzPZjkaUNmd6KVI3JRwWoRSLM6P98mMG+Dw4q+il8Ev07P7ATCNmRlfQ8/qN
1506HwVwB99Y4H0vMHAi6BWZUoEhoqXTNXdSK+A2LN6tE+fJ0E+7MhOdFSEM5lNgrJIKWXDF908wy87D
1507xE3UoHsxkegZTaHIHGNSSYfm+ntelpURvCnK7NEWBI/ap/b8Z1m232N2rj7B60V2DRM3B5NpaLSw
1508KnfwpvQVTviHOR+F88lhQyBAGlE7be6DoRNg9ldsG3218IHa6MRNU+tGBEYIggwafRk6yzsXDcVU
15099Ua08kYxt+F3x12LRaQi52j0xx/ywFxrdMRqVevzmaummlIYEp0WsCAaX8cFb6buuLUTqEgQQ6/Q
151004iWRoF38m/BdE8VtlBY0bURiB6KG1crpMZwc2fIjqWh+1UrkSLpWUIP8PySwLKv4qPGSVqDuMPy
1511dywQ+gS7L1irXVkm5pJsq3l+Ib1lMOvUrxI+/mBBY4KB+WpUtcO06RtzckNvQ6vYj1lGoZM2sdDG
1512fryJPYJVn/Cfka8XSqNaoLKhmOlqXMzW9+YBVp1EtIThZtOwzCRvMaARa+0xD0b2kcaJGwJsMbc7
1513hLUfY4vKvsCOBdvDnyfuRbzmXRdGTZgPF7oGQkJACWVD22IMQdhx0npt5S2f+pXO+OwH6d+hwiS5
15147IJOjcK2emj1zBy1aONHByfAMoraw6WlrSIFTbGghqASoRCjVncYROFpXM4uYSqhGnuVeGvks4jz
1515cjnCoR5GnPW7KOh4maVbdFeoplgJ3wh3MSrAsv/QuMjOspnTKRl1fTYqqNisv7uTVnhF1GhoBFbp
1516lh+OcXN2riA5ZrYXtWxlfcDuC8U5kLoN3CCJYXGpesO6dx6rU0zGMtjU6cNlmW0Fid8Sja4ZG+Z3
1517fTPbyj+mZnZ2wSQK8RaT9Km0ySRuLpm0DkUUL0ra3WQ2BgGJ7v9I9SKqNKZ/IR4R28RHm+vEz5ic
1518nZ2IH7bfub8pU1PR3gr10W7xLTfHh6Z6bgZ7K14G7Mj/1z5J6MFo6V5e07H0Ou78dTyeI+mxKOpI
1519eC2KMSj6HKxd6Uudf/n886fPv+f++x1lbASlmjQuPz8OvGA0j7j2eCu/4bcW6SFeCuNJ0W1GQHI5
1520iwC9Ey0bjtHd9P4dPA++XxLnZDVuxvFEtlm3lf5a2c02u2LRYXHH/AOs8pIa
1521""".decode("base64").decode("zlib")
1522
1523##file distutils.cfg
1524DISTUTILS_CFG = """
1525eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
1526xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
15279FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
1528""".decode("base64").decode("zlib")
1529
1530##file activate_this.py
1531ACTIVATE_THIS = """
1532eJx1UsGOnDAMvecrIlYriDRlKvU20h5aaY+teuilGo1QALO4CwlKAjP8fe1QGGalRoLEefbzs+Mk
1533Sb7NcvRo3iTcoGqwgyy06As+HWSNVciKaBTFywYoJWc7yit2ndBVwEkHkIzKCV0YdQdmkvShs6YH
1534E3IhfjFaaSNLoHxQy2sLJrL0ow98JQmEG/rAYn7OobVGogngBgf0P0hjgwgt7HOUaI5DdBVJkggR
15353HwSktaqWcCtgiHIH7qHV+esW2CnkRJ+9R5cQGsikkWEV/J7leVGs9TV4TvcO5QOOrTHYI+xeCjY
1536JR/m9GPDHv2oSZunUokS2A/WBelnvx6tF6LUJO2FjjlH5zU6Q+Kz/9m69LxvSZVSwiOlGnT1rt/A
153777j+WDQZ8x9k2mFJetOle88+lc8sJJ/AeerI+fTlQigTfVqJUiXoKaaC3AqmI+KOnivjMLbvBVFU
15381JDruuadNGcPmkgiBTnQXUGUDd6IK9JEQ9yPdM96xZP8bieeMRqTuqbxIbbey2DjVUNzRs1rosFS
1539TsLAdS/0fBGNdTGKhuqD7mUmsFlgGjN2eSj1tM3GnjfXwwCmzjhMbR4rLZXXk+Z/6Hp7Pn2+kJ49
1540jfgLHgI4Jg==
1541""".decode("base64").decode("zlib")
1542
1543if __name__ == '__main__':
1544    main()
1545
1546## TODO:
1547## Copy python.exe.manifest
1548## Monkeypatch distutils.sysconfig
Note: See TracBrowser for help on using the repository browser.