~ubuntu-branches/ubuntu/quantal/enigmail/quantal-security

« back to all changes in this revision

Viewing changes to mozilla/python/virtualenv/virtualenv.py

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2013-09-13 16:02:15 UTC
  • mfrom: (0.12.16)
  • Revision ID: package-import@ubuntu.com-20130913160215-u3g8nmwa0pdwagwc
Tags: 2:1.5.2-0ubuntu0.12.10.1
* New upstream release v1.5.2 for Thunderbird 24

* Build enigmail using a stripped down Thunderbird 17 build system, as it's
  now quite difficult to build the way we were doing previously, with the
  latest Firefox build system
* Add debian/patches/no_libxpcom.patch - Don't link against libxpcom, as it
  doesn't exist anymore (but exists in the build system)
* Add debian/patches/use_sdk.patch - Use the SDK version of xpt.py and
  friends
* Drop debian/patches/ipc-pipe_rename.diff (not needed anymore)
* Drop debian/patches/makefile_depth.diff (not needed anymore)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
"""Create a "virtual" Python installation
 
3
"""
 
4
 
 
5
# If you change the version here, change it in setup.py
 
6
# and docs/conf.py as well.
 
7
__version__ = "1.8.4"  # following best practices
 
8
virtualenv_version = __version__  # legacy, again
 
9
 
 
10
import base64
 
11
import sys
 
12
import os
 
13
import codecs
 
14
import optparse
 
15
import re
 
16
import shutil
 
17
import logging
 
18
import tempfile
 
19
import zlib
 
20
import errno
 
21
import glob
 
22
import distutils.sysconfig
 
23
from distutils.util import strtobool
 
24
import struct
 
25
import subprocess
 
26
 
 
27
if sys.version_info < (2, 5):
 
28
    print('ERROR: %s' % sys.exc_info()[1])
 
29
    print('ERROR: this script requires Python 2.5 or greater.')
 
30
    sys.exit(101)
 
31
 
 
32
try:
 
33
    set
 
34
except NameError:
 
35
    from sets import Set as set
 
36
try:
 
37
    basestring
 
38
except NameError:
 
39
    basestring = str
 
40
 
 
41
try:
 
42
    import ConfigParser
 
43
except ImportError:
 
44
    import configparser as ConfigParser
 
45
 
 
46
join = os.path.join
 
47
py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
 
48
 
 
49
is_jython = sys.platform.startswith('java')
 
50
is_pypy = hasattr(sys, 'pypy_version_info')
 
51
is_win = (sys.platform == 'win32')
 
52
is_cygwin = (sys.platform == 'cygwin')
 
53
is_darwin = (sys.platform == 'darwin')
 
54
abiflags = getattr(sys, 'abiflags', '')
 
55
 
 
56
user_dir = os.path.expanduser('~')
 
57
if is_win:
 
58
    default_storage_dir = os.path.join(user_dir, 'virtualenv')
 
59
else:
 
60
    default_storage_dir = os.path.join(user_dir, '.virtualenv')
 
61
default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini')
 
62
 
 
63
if is_pypy:
 
64
    expected_exe = 'pypy'
 
65
elif is_jython:
 
66
    expected_exe = 'jython'
 
67
else:
 
68
    expected_exe = 'python'
 
69
 
 
70
 
 
71
REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
 
72
                    'fnmatch', 'locale', 'encodings', 'codecs',
 
73
                    'stat', 'UserDict', 'readline', 'copy_reg', 'types',
 
74
                    're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
 
75
                    'zlib']
 
76
 
 
77
REQUIRED_FILES = ['lib-dynload', 'config']
 
78
 
 
79
majver, minver = sys.version_info[:2]
 
80
if majver == 2:
 
81
    if minver >= 6:
 
82
        REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc'])
 
83
    if minver >= 7:
 
84
        REQUIRED_MODULES.extend(['_weakrefset'])
 
85
    if minver <= 3:
 
86
        REQUIRED_MODULES.extend(['sets', '__future__'])
 
87
elif majver == 3:
 
88
    # Some extra modules are needed for Python 3, but different ones
 
89
    # for different versions.
 
90
    REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
 
91
                             '_weakrefset', 'copyreg', 'tempfile', 'random',
 
92
                             '__future__', 'collections', 'keyword', 'tarfile',
 
93
                             'shutil', 'struct', 'copy', 'tokenize', 'token',
 
94
                             'functools', 'heapq', 'bisect', 'weakref',
 
95
                             'reprlib'])
 
96
    if minver >= 2:
 
97
        REQUIRED_FILES[-1] = 'config-%s' % majver
 
98
    if minver == 3:
 
99
        import sysconfig
 
100
        platdir = sysconfig.get_config_var('PLATDIR')
 
101
        REQUIRED_FILES.append(platdir)
 
102
        # The whole list of 3.3 modules is reproduced below - the current
 
103
        # uncommented ones are required for 3.3 as of now, but more may be
 
104
        # added as 3.3 development continues.
 
105
        REQUIRED_MODULES.extend([
 
106
            #"aifc",
 
107
            #"antigravity",
 
108
            #"argparse",
 
109
            #"ast",
 
110
            #"asynchat",
 
111
            #"asyncore",
 
112
            "base64",
 
113
            #"bdb",
 
114
            #"binhex",
 
115
            #"bisect",
 
116
            #"calendar",
 
117
            #"cgi",
 
118
            #"cgitb",
 
119
            #"chunk",
 
120
            #"cmd",
 
121
            #"codeop",
 
122
            #"code",
 
123
            #"colorsys",
 
124
            #"_compat_pickle",
 
125
            #"compileall",
 
126
            #"concurrent",
 
127
            #"configparser",
 
128
            #"contextlib",
 
129
            #"cProfile",
 
130
            #"crypt",
 
131
            #"csv",
 
132
            #"ctypes",
 
133
            #"curses",
 
134
            #"datetime",
 
135
            #"dbm",
 
136
            #"decimal",
 
137
            #"difflib",
 
138
            #"dis",
 
139
            #"doctest",
 
140
            #"dummy_threading",
 
141
            "_dummy_thread",
 
142
            #"email",
 
143
            #"filecmp",
 
144
            #"fileinput",
 
145
            #"formatter",
 
146
            #"fractions",
 
147
            #"ftplib",
 
148
            #"functools",
 
149
            #"getopt",
 
150
            #"getpass",
 
151
            #"gettext",
 
152
            #"glob",
 
153
            #"gzip",
 
154
            "hashlib",
 
155
            #"heapq",
 
156
            "hmac",
 
157
            #"html",
 
158
            #"http",
 
159
            #"idlelib",
 
160
            #"imaplib",
 
161
            #"imghdr",
 
162
            "imp",
 
163
            "importlib",
 
164
            #"inspect",
 
165
            #"json",
 
166
            #"lib2to3",
 
167
            #"logging",
 
168
            #"macpath",
 
169
            #"macurl2path",
 
170
            #"mailbox",
 
171
            #"mailcap",
 
172
            #"_markupbase",
 
173
            #"mimetypes",
 
174
            #"modulefinder",
 
175
            #"multiprocessing",
 
176
            #"netrc",
 
177
            #"nntplib",
 
178
            #"nturl2path",
 
179
            #"numbers",
 
180
            #"opcode",
 
181
            #"optparse",
 
182
            #"os2emxpath",
 
183
            #"pdb",
 
184
            #"pickle",
 
185
            #"pickletools",
 
186
            #"pipes",
 
187
            #"pkgutil",
 
188
            #"platform",
 
189
            #"plat-linux2",
 
190
            #"plistlib",
 
191
            #"poplib",
 
192
            #"pprint",
 
193
            #"profile",
 
194
            #"pstats",
 
195
            #"pty",
 
196
            #"pyclbr",
 
197
            #"py_compile",
 
198
            #"pydoc_data",
 
199
            #"pydoc",
 
200
            #"_pyio",
 
201
            #"queue",
 
202
            #"quopri",
 
203
            #"reprlib",
 
204
            "rlcompleter",
 
205
            #"runpy",
 
206
            #"sched",
 
207
            #"shelve",
 
208
            #"shlex",
 
209
            #"smtpd",
 
210
            #"smtplib",
 
211
            #"sndhdr",
 
212
            #"socket",
 
213
            #"socketserver",
 
214
            #"sqlite3",
 
215
            #"ssl",
 
216
            #"stringprep",
 
217
            #"string",
 
218
            #"_strptime",
 
219
            #"subprocess",
 
220
            #"sunau",
 
221
            #"symbol",
 
222
            #"symtable",
 
223
            #"sysconfig",
 
224
            #"tabnanny",
 
225
            #"telnetlib",
 
226
            #"test",
 
227
            #"textwrap",
 
228
            #"this",
 
229
            #"_threading_local",
 
230
            #"threading",
 
231
            #"timeit",
 
232
            #"tkinter",
 
233
            #"tokenize",
 
234
            #"token",
 
235
            #"traceback",
 
236
            #"trace",
 
237
            #"tty",
 
238
            #"turtledemo",
 
239
            #"turtle",
 
240
            #"unittest",
 
241
            #"urllib",
 
242
            #"uuid",
 
243
            #"uu",
 
244
            #"wave",
 
245
            #"weakref",
 
246
            #"webbrowser",
 
247
            #"wsgiref",
 
248
            #"xdrlib",
 
249
            #"xml",
 
250
            #"xmlrpc",
 
251
            #"zipfile",
 
252
        ])
 
253
 
 
254
if is_pypy:
 
255
    # these are needed to correctly display the exceptions that may happen
 
256
    # during the bootstrap
 
257
    REQUIRED_MODULES.extend(['traceback', 'linecache'])
 
258
 
 
259
class Logger(object):
 
260
 
 
261
    """
 
262
    Logging object for use in command-line script.  Allows ranges of
 
263
    levels, to avoid some redundancy of displayed information.
 
264
    """
 
265
 
 
266
    DEBUG = logging.DEBUG
 
267
    INFO = logging.INFO
 
268
    NOTIFY = (logging.INFO+logging.WARN)/2
 
269
    WARN = WARNING = logging.WARN
 
270
    ERROR = logging.ERROR
 
271
    FATAL = logging.FATAL
 
272
 
 
273
    LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
 
274
 
 
275
    def __init__(self, consumers):
 
276
        self.consumers = consumers
 
277
        self.indent = 0
 
278
        self.in_progress = None
 
279
        self.in_progress_hanging = False
 
280
 
 
281
    def debug(self, msg, *args, **kw):
 
282
        self.log(self.DEBUG, msg, *args, **kw)
 
283
    def info(self, msg, *args, **kw):
 
284
        self.log(self.INFO, msg, *args, **kw)
 
285
    def notify(self, msg, *args, **kw):
 
286
        self.log(self.NOTIFY, msg, *args, **kw)
 
287
    def warn(self, msg, *args, **kw):
 
288
        self.log(self.WARN, msg, *args, **kw)
 
289
    def error(self, msg, *args, **kw):
 
290
        self.log(self.ERROR, msg, *args, **kw)
 
291
    def fatal(self, msg, *args, **kw):
 
292
        self.log(self.FATAL, msg, *args, **kw)
 
293
    def log(self, level, msg, *args, **kw):
 
294
        if args:
 
295
            if kw:
 
296
                raise TypeError(
 
297
                    "You may give positional or keyword arguments, not both")
 
298
        args = args or kw
 
299
        rendered = None
 
300
        for consumer_level, consumer in self.consumers:
 
301
            if self.level_matches(level, consumer_level):
 
302
                if (self.in_progress_hanging
 
303
                    and consumer in (sys.stdout, sys.stderr)):
 
304
                    self.in_progress_hanging = False
 
305
                    sys.stdout.write('\n')
 
306
                    sys.stdout.flush()
 
307
                if rendered is None:
 
308
                    if args:
 
309
                        rendered = msg % args
 
310
                    else:
 
311
                        rendered = msg
 
312
                    rendered = ' '*self.indent + rendered
 
313
                if hasattr(consumer, 'write'):
 
314
                    consumer.write(rendered+'\n')
 
315
                else:
 
316
                    consumer(rendered)
 
317
 
 
318
    def start_progress(self, msg):
 
319
        assert not self.in_progress, (
 
320
            "Tried to start_progress(%r) while in_progress %r"
 
321
            % (msg, self.in_progress))
 
322
        if self.level_matches(self.NOTIFY, self._stdout_level()):
 
323
            sys.stdout.write(msg)
 
324
            sys.stdout.flush()
 
325
            self.in_progress_hanging = True
 
326
        else:
 
327
            self.in_progress_hanging = False
 
328
        self.in_progress = msg
 
329
 
 
330
    def end_progress(self, msg='done.'):
 
331
        assert self.in_progress, (
 
332
            "Tried to end_progress without start_progress")
 
333
        if self.stdout_level_matches(self.NOTIFY):
 
334
            if not self.in_progress_hanging:
 
335
                # Some message has been printed out since start_progress
 
336
                sys.stdout.write('...' + self.in_progress + msg + '\n')
 
337
                sys.stdout.flush()
 
338
            else:
 
339
                sys.stdout.write(msg + '\n')
 
340
                sys.stdout.flush()
 
341
        self.in_progress = None
 
342
        self.in_progress_hanging = False
 
343
 
 
344
    def show_progress(self):
 
345
        """If we are in a progress scope, and no log messages have been
 
346
        shown, write out another '.'"""
 
347
        if self.in_progress_hanging:
 
348
            sys.stdout.write('.')
 
349
            sys.stdout.flush()
 
350
 
 
351
    def stdout_level_matches(self, level):
 
352
        """Returns true if a message at this level will go to stdout"""
 
353
        return self.level_matches(level, self._stdout_level())
 
354
 
 
355
    def _stdout_level(self):
 
356
        """Returns the level that stdout runs at"""
 
357
        for level, consumer in self.consumers:
 
358
            if consumer is sys.stdout:
 
359
                return level
 
360
        return self.FATAL
 
361
 
 
362
    def level_matches(self, level, consumer_level):
 
363
        """
 
364
        >>> l = Logger([])
 
365
        >>> l.level_matches(3, 4)
 
366
        False
 
367
        >>> l.level_matches(3, 2)
 
368
        True
 
369
        >>> l.level_matches(slice(None, 3), 3)
 
370
        False
 
371
        >>> l.level_matches(slice(None, 3), 2)
 
372
        True
 
373
        >>> l.level_matches(slice(1, 3), 1)
 
374
        True
 
375
        >>> l.level_matches(slice(2, 3), 1)
 
376
        False
 
377
        """
 
378
        if isinstance(level, slice):
 
379
            start, stop = level.start, level.stop
 
380
            if start is not None and start > consumer_level:
 
381
                return False
 
382
            if stop is not None and stop <= consumer_level:
 
383
                return False
 
384
            return True
 
385
        else:
 
386
            return level >= consumer_level
 
387
 
 
388
    #@classmethod
 
389
    def level_for_integer(cls, level):
 
390
        levels = cls.LEVELS
 
391
        if level < 0:
 
392
            return levels[0]
 
393
        if level >= len(levels):
 
394
            return levels[-1]
 
395
        return levels[level]
 
396
 
 
397
    level_for_integer = classmethod(level_for_integer)
 
398
 
 
399
# create a silent logger just to prevent this from being undefined
 
400
# will be overridden with requested verbosity main() is called.
 
401
logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
 
402
 
 
403
def mkdir(path):
 
404
    if not os.path.exists(path):
 
405
        logger.info('Creating %s', path)
 
406
        os.makedirs(path)
 
407
    else:
 
408
        logger.info('Directory %s already exists', path)
 
409
 
 
410
def copyfileordir(src, dest):
 
411
    if os.path.isdir(src):
 
412
        shutil.copytree(src, dest, True)
 
413
    else:
 
414
        shutil.copy2(src, dest)
 
415
 
 
416
def copyfile(src, dest, symlink=True):
 
417
    if not os.path.exists(src):
 
418
        # Some bad symlink in the src
 
419
        logger.warn('Cannot find file %s (bad symlink)', src)
 
420
        return
 
421
    if os.path.exists(dest):
 
422
        logger.debug('File %s already exists', dest)
 
423
        return
 
424
    if not os.path.exists(os.path.dirname(dest)):
 
425
        logger.info('Creating parent directories for %s' % os.path.dirname(dest))
 
426
        os.makedirs(os.path.dirname(dest))
 
427
    if not os.path.islink(src):
 
428
        srcpath = os.path.abspath(src)
 
429
    else:
 
430
        srcpath = os.readlink(src)
 
431
    if symlink and hasattr(os, 'symlink') and not is_win:
 
432
        logger.info('Symlinking %s', dest)
 
433
        try:
 
434
            os.symlink(srcpath, dest)
 
435
        except (OSError, NotImplementedError):
 
436
            logger.info('Symlinking failed, copying to %s', dest)
 
437
            copyfileordir(src, dest)
 
438
    else:
 
439
        logger.info('Copying to %s', dest)
 
440
        copyfileordir(src, dest)
 
441
 
 
442
def writefile(dest, content, overwrite=True):
 
443
    if not os.path.exists(dest):
 
444
        logger.info('Writing %s', dest)
 
445
        f = open(dest, 'wb')
 
446
        f.write(content.encode('utf-8'))
 
447
        f.close()
 
448
        return
 
449
    else:
 
450
        f = open(dest, 'rb')
 
451
        c = f.read()
 
452
        f.close()
 
453
        if c != content.encode("utf-8"):
 
454
            if not overwrite:
 
455
                logger.notify('File %s exists with different content; not overwriting', dest)
 
456
                return
 
457
            logger.notify('Overwriting %s with new content', dest)
 
458
            f = open(dest, 'wb')
 
459
            f.write(content.encode('utf-8'))
 
460
            f.close()
 
461
        else:
 
462
            logger.info('Content %s already in place', dest)
 
463
 
 
464
def rmtree(dir):
 
465
    if os.path.exists(dir):
 
466
        logger.notify('Deleting tree %s', dir)
 
467
        shutil.rmtree(dir)
 
468
    else:
 
469
        logger.info('Do not need to delete %s; already gone', dir)
 
470
 
 
471
def make_exe(fn):
 
472
    if hasattr(os, 'chmod'):
 
473
        oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777
 
474
        newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777
 
475
        os.chmod(fn, newmode)
 
476
        logger.info('Changed mode of %s to %s', fn, oct(newmode))
 
477
 
 
478
def _find_file(filename, dirs):
 
479
    for dir in reversed(dirs):
 
480
        files = glob.glob(os.path.join(dir, filename))
 
481
        if files and os.path.isfile(files[0]):
 
482
            return True, files[0]
 
483
    return False, filename
 
484
 
 
485
def _install_req(py_executable, unzip=False, distribute=False,
 
486
                 search_dirs=None, never_download=False):
 
487
 
 
488
    if search_dirs is None:
 
489
        search_dirs = file_search_dirs()
 
490
 
 
491
    if not distribute:
 
492
        egg_path = 'setuptools-*-py%s.egg' % sys.version[:3]
 
493
        found, egg_path = _find_file(egg_path, search_dirs)
 
494
        project_name = 'setuptools'
 
495
        bootstrap_script = EZ_SETUP_PY
 
496
        tgz_path = None
 
497
    else:
 
498
        # Look for a distribute egg (these are not distributed by default,
 
499
        # but can be made available by the user)
 
500
        egg_path = 'distribute-*-py%s.egg' % sys.version[:3]
 
501
        found, egg_path = _find_file(egg_path, search_dirs)
 
502
        project_name = 'distribute'
 
503
        if found:
 
504
            tgz_path = None
 
505
            bootstrap_script = DISTRIBUTE_FROM_EGG_PY
 
506
        else:
 
507
            # Fall back to sdist
 
508
            # NB: egg_path is not None iff tgz_path is None
 
509
            # iff bootstrap_script is a generic setup script accepting
 
510
            # the standard arguments.
 
511
            egg_path = None
 
512
            tgz_path = 'distribute-*.tar.gz'
 
513
            found, tgz_path = _find_file(tgz_path, search_dirs)
 
514
            bootstrap_script = DISTRIBUTE_SETUP_PY
 
515
 
 
516
    if is_jython and os._name == 'nt':
 
517
        # Jython's .bat sys.executable can't handle a command line
 
518
        # argument with newlines
 
519
        fd, ez_setup = tempfile.mkstemp('.py')
 
520
        os.write(fd, bootstrap_script)
 
521
        os.close(fd)
 
522
        cmd = [py_executable, ez_setup]
 
523
    else:
 
524
        cmd = [py_executable, '-c', bootstrap_script]
 
525
    if unzip and egg_path:
 
526
        cmd.append('--always-unzip')
 
527
    env = {}
 
528
    remove_from_env = ['__PYVENV_LAUNCHER__']
 
529
    if logger.stdout_level_matches(logger.DEBUG) and egg_path:
 
530
        cmd.append('-v')
 
531
 
 
532
    old_chdir = os.getcwd()
 
533
    if egg_path is not None and os.path.exists(egg_path):
 
534
        logger.info('Using existing %s egg: %s' % (project_name, egg_path))
 
535
        cmd.append(egg_path)
 
536
        if os.environ.get('PYTHONPATH'):
 
537
            env['PYTHONPATH'] = egg_path + os.path.pathsep + os.environ['PYTHONPATH']
 
538
        else:
 
539
            env['PYTHONPATH'] = egg_path
 
540
    elif tgz_path is not None and os.path.exists(tgz_path):
 
541
        # Found a tgz source dist, let's chdir
 
542
        logger.info('Using existing %s egg: %s' % (project_name, tgz_path))
 
543
        os.chdir(os.path.dirname(tgz_path))
 
544
        # in this case, we want to be sure that PYTHONPATH is unset (not
 
545
        # just empty, really unset), else CPython tries to import the
 
546
        # site.py that it's in virtualenv_support
 
547
        remove_from_env.append('PYTHONPATH')
 
548
    elif never_download:
 
549
        logger.fatal("Can't find any local distributions of %s to install "
 
550
                     "and --never-download is set.  Either re-run virtualenv "
 
551
                     "without the --never-download option, or place a %s "
 
552
                     "distribution (%s) in one of these "
 
553
                     "locations: %r" % (project_name, project_name,
 
554
                                        egg_path or tgz_path,
 
555
                                        search_dirs))
 
556
        sys.exit(1)
 
557
    elif egg_path:
 
558
        logger.info('No %s egg found; downloading' % project_name)
 
559
        cmd.extend(['--always-copy', '-U', project_name])
 
560
    else:
 
561
        logger.info('No %s tgz found; downloading' % project_name)
 
562
    logger.start_progress('Installing %s...' % project_name)
 
563
    logger.indent += 2
 
564
    cwd = None
 
565
    if project_name == 'distribute':
 
566
        env['DONT_PATCH_SETUPTOOLS'] = 'true'
 
567
 
 
568
    def _filter_ez_setup(line):
 
569
        return filter_ez_setup(line, project_name)
 
570
 
 
571
    if not os.access(os.getcwd(), os.W_OK):
 
572
        cwd = tempfile.mkdtemp()
 
573
        if tgz_path is not None and os.path.exists(tgz_path):
 
574
            # the current working dir is hostile, let's copy the
 
575
            # tarball to a temp dir
 
576
            target = os.path.join(cwd, os.path.split(tgz_path)[-1])
 
577
            shutil.copy(tgz_path, target)
 
578
    try:
 
579
        call_subprocess(cmd, show_stdout=False,
 
580
                        filter_stdout=_filter_ez_setup,
 
581
                        extra_env=env,
 
582
                        remove_from_env=remove_from_env,
 
583
                        cwd=cwd)
 
584
    finally:
 
585
        logger.indent -= 2
 
586
        logger.end_progress()
 
587
        if cwd is not None:
 
588
            shutil.rmtree(cwd)
 
589
        if os.getcwd() != old_chdir:
 
590
            os.chdir(old_chdir)
 
591
        if is_jython and os._name == 'nt':
 
592
            os.remove(ez_setup)
 
593
 
 
594
def file_search_dirs():
 
595
    here = os.path.dirname(os.path.abspath(__file__))
 
596
    dirs = ['.', here,
 
597
            join(here, 'virtualenv_support')]
 
598
    if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
 
599
        # Probably some boot script; just in case virtualenv is installed...
 
600
        try:
 
601
            import virtualenv
 
602
        except ImportError:
 
603
            pass
 
604
        else:
 
605
            dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
 
606
    return [d for d in dirs if os.path.isdir(d)]
 
607
 
 
608
def install_setuptools(py_executable, unzip=False,
 
609
                       search_dirs=None, never_download=False):
 
610
    _install_req(py_executable, unzip,
 
611
                 search_dirs=search_dirs, never_download=never_download)
 
612
 
 
613
def install_distribute(py_executable, unzip=False,
 
614
                       search_dirs=None, never_download=False):
 
615
    _install_req(py_executable, unzip, distribute=True,
 
616
                 search_dirs=search_dirs, never_download=never_download)
 
617
 
 
618
_pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I)
 
619
def install_pip(py_executable, search_dirs=None, never_download=False):
 
620
    if search_dirs is None:
 
621
        search_dirs = file_search_dirs()
 
622
 
 
623
    filenames = []
 
624
    for dir in search_dirs:
 
625
        filenames.extend([join(dir, fn) for fn in os.listdir(dir)
 
626
                          if _pip_re.search(fn)])
 
627
    filenames = [(os.path.basename(filename).lower(), i, filename) for i, filename in enumerate(filenames)]
 
628
    filenames.sort()
 
629
    filenames = [filename for basename, i, filename in filenames]
 
630
    if not filenames:
 
631
        filename = 'pip'
 
632
    else:
 
633
        filename = filenames[-1]
 
634
    easy_install_script = 'easy_install'
 
635
    if is_win:
 
636
        easy_install_script = 'easy_install-script.py'
 
637
    # There's two subtle issues here when invoking easy_install.
 
638
    # 1. On unix-like systems the easy_install script can *only* be executed
 
639
    #    directly if its full filesystem path is no longer than 78 characters.
 
640
    # 2. A work around to [1] is to use the `python path/to/easy_install foo`
 
641
    #    pattern, but that breaks if the path contains non-ASCII characters, as
 
642
    #    you can't put the file encoding declaration before the shebang line.
 
643
    # The solution is to use Python's -x flag to skip the first line of the
 
644
    # script (and any ASCII decoding errors that may have occurred in that line)
 
645
    cmd = [py_executable, '-x', join(os.path.dirname(py_executable), easy_install_script), filename]
 
646
    # jython and pypy don't yet support -x
 
647
    if is_jython or is_pypy:
 
648
        cmd.remove('-x')
 
649
    if filename == 'pip':
 
650
        if never_download:
 
651
            logger.fatal("Can't find any local distributions of pip to install "
 
652
                         "and --never-download is set.  Either re-run virtualenv "
 
653
                         "without the --never-download option, or place a pip "
 
654
                         "source distribution (zip/tar.gz/tar.bz2) in one of these "
 
655
                         "locations: %r" % search_dirs)
 
656
            sys.exit(1)
 
657
        logger.info('Installing pip from network...')
 
658
    else:
 
659
        logger.info('Installing existing %s distribution: %s' % (
 
660
                os.path.basename(filename), filename))
 
661
    logger.start_progress('Installing pip...')
 
662
    logger.indent += 2
 
663
    def _filter_setup(line):
 
664
        return filter_ez_setup(line, 'pip')
 
665
    try:
 
666
        call_subprocess(cmd, show_stdout=False,
 
667
                        filter_stdout=_filter_setup)
 
668
    finally:
 
669
        logger.indent -= 2
 
670
        logger.end_progress()
 
671
 
 
672
def filter_ez_setup(line, project_name='setuptools'):
 
673
    if not line.strip():
 
674
        return Logger.DEBUG
 
675
    if project_name == 'distribute':
 
676
        for prefix in ('Extracting', 'Now working', 'Installing', 'Before',
 
677
                       'Scanning', 'Setuptools', 'Egg', 'Already',
 
678
                       'running', 'writing', 'reading', 'installing',
 
679
                       'creating', 'copying', 'byte-compiling', 'removing',
 
680
                       'Processing'):
 
681
            if line.startswith(prefix):
 
682
                return Logger.DEBUG
 
683
        return Logger.DEBUG
 
684
    for prefix in ['Reading ', 'Best match', 'Processing setuptools',
 
685
                   'Copying setuptools', 'Adding setuptools',
 
686
                   'Installing ', 'Installed ']:
 
687
        if line.startswith(prefix):
 
688
            return Logger.DEBUG
 
689
    return Logger.INFO
 
690
 
 
691
 
 
692
class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
 
693
    """
 
694
    Custom help formatter for use in ConfigOptionParser that updates
 
695
    the defaults before expanding them, allowing them to show up correctly
 
696
    in the help listing
 
697
    """
 
698
    def expand_default(self, option):
 
699
        if self.parser is not None:
 
700
            self.parser.update_defaults(self.parser.defaults)
 
701
        return optparse.IndentedHelpFormatter.expand_default(self, option)
 
702
 
 
703
 
 
704
class ConfigOptionParser(optparse.OptionParser):
 
705
    """
 
706
    Custom option parser which updates its defaults by by checking the
 
707
    configuration files and environmental variables
 
708
    """
 
709
    def __init__(self, *args, **kwargs):
 
710
        self.config = ConfigParser.RawConfigParser()
 
711
        self.files = self.get_config_files()
 
712
        self.config.read(self.files)
 
713
        optparse.OptionParser.__init__(self, *args, **kwargs)
 
714
 
 
715
    def get_config_files(self):
 
716
        config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False)
 
717
        if config_file and os.path.exists(config_file):
 
718
            return [config_file]
 
719
        return [default_config_file]
 
720
 
 
721
    def update_defaults(self, defaults):
 
722
        """
 
723
        Updates the given defaults with values from the config files and
 
724
        the environ. Does a little special handling for certain types of
 
725
        options (lists).
 
726
        """
 
727
        # Then go and look for the other sources of configuration:
 
728
        config = {}
 
729
        # 1. config files
 
730
        config.update(dict(self.get_config_section('virtualenv')))
 
731
        # 2. environmental variables
 
732
        config.update(dict(self.get_environ_vars()))
 
733
        # Then set the options with those values
 
734
        for key, val in config.items():
 
735
            key = key.replace('_', '-')
 
736
            if not key.startswith('--'):
 
737
                key = '--%s' % key  # only prefer long opts
 
738
            option = self.get_option(key)
 
739
            if option is not None:
 
740
                # ignore empty values
 
741
                if not val:
 
742
                    continue
 
743
                # handle multiline configs
 
744
                if option.action == 'append':
 
745
                    val = val.split()
 
746
                else:
 
747
                    option.nargs = 1
 
748
                if option.action == 'store_false':
 
749
                    val = not strtobool(val)
 
750
                elif option.action in ('store_true', 'count'):
 
751
                    val = strtobool(val)
 
752
                try:
 
753
                    val = option.convert_value(key, val)
 
754
                except optparse.OptionValueError:
 
755
                    e = sys.exc_info()[1]
 
756
                    print("An error occured during configuration: %s" % e)
 
757
                    sys.exit(3)
 
758
                defaults[option.dest] = val
 
759
        return defaults
 
760
 
 
761
    def get_config_section(self, name):
 
762
        """
 
763
        Get a section of a configuration
 
764
        """
 
765
        if self.config.has_section(name):
 
766
            return self.config.items(name)
 
767
        return []
 
768
 
 
769
    def get_environ_vars(self, prefix='VIRTUALENV_'):
 
770
        """
 
771
        Returns a generator with all environmental vars with prefix VIRTUALENV
 
772
        """
 
773
        for key, val in os.environ.items():
 
774
            if key.startswith(prefix):
 
775
                yield (key.replace(prefix, '').lower(), val)
 
776
 
 
777
    def get_default_values(self):
 
778
        """
 
779
        Overridding to make updating the defaults after instantiation of
 
780
        the option parser possible, update_defaults() does the dirty work.
 
781
        """
 
782
        if not self.process_default_values:
 
783
            # Old, pre-Optik 1.5 behaviour.
 
784
            return optparse.Values(self.defaults)
 
785
 
 
786
        defaults = self.update_defaults(self.defaults.copy())  # ours
 
787
        for option in self._get_all_options():
 
788
            default = defaults.get(option.dest)
 
789
            if isinstance(default, basestring):
 
790
                opt_str = option.get_opt_string()
 
791
                defaults[option.dest] = option.check_value(opt_str, default)
 
792
        return optparse.Values(defaults)
 
793
 
 
794
 
 
795
def main():
 
796
    parser = ConfigOptionParser(
 
797
        version=virtualenv_version,
 
798
        usage="%prog [OPTIONS] DEST_DIR",
 
799
        formatter=UpdatingDefaultsHelpFormatter())
 
800
 
 
801
    parser.add_option(
 
802
        '-v', '--verbose',
 
803
        action='count',
 
804
        dest='verbose',
 
805
        default=0,
 
806
        help="Increase verbosity")
 
807
 
 
808
    parser.add_option(
 
809
        '-q', '--quiet',
 
810
        action='count',
 
811
        dest='quiet',
 
812
        default=0,
 
813
        help='Decrease verbosity')
 
814
 
 
815
    parser.add_option(
 
816
        '-p', '--python',
 
817
        dest='python',
 
818
        metavar='PYTHON_EXE',
 
819
        help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
 
820
        'interpreter to create the new environment.  The default is the interpreter that '
 
821
        'virtualenv was installed with (%s)' % sys.executable)
 
822
 
 
823
    parser.add_option(
 
824
        '--clear',
 
825
        dest='clear',
 
826
        action='store_true',
 
827
        help="Clear out the non-root install and start from scratch")
 
828
 
 
829
    parser.set_defaults(system_site_packages=False)
 
830
    parser.add_option(
 
831
        '--no-site-packages',
 
832
        dest='system_site_packages',
 
833
        action='store_false',
 
834
        help="Don't give access to the global site-packages dir to the "
 
835
             "virtual environment (default)")
 
836
 
 
837
    parser.add_option(
 
838
        '--system-site-packages',
 
839
        dest='system_site_packages',
 
840
        action='store_true',
 
841
        help="Give access to the global site-packages dir to the "
 
842
             "virtual environment")
 
843
 
 
844
    parser.add_option(
 
845
        '--unzip-setuptools',
 
846
        dest='unzip_setuptools',
 
847
        action='store_true',
 
848
        help="Unzip Setuptools or Distribute when installing it")
 
849
 
 
850
    parser.add_option(
 
851
        '--relocatable',
 
852
        dest='relocatable',
 
853
        action='store_true',
 
854
        help='Make an EXISTING virtualenv environment relocatable.  '
 
855
        'This fixes up scripts and makes all .pth files relative')
 
856
 
 
857
    parser.add_option(
 
858
        '--distribute', '--use-distribute',  # the second option is for legacy reasons here. Hi Kenneth!
 
859
        dest='use_distribute',
 
860
        action='store_true',
 
861
        help='Use Distribute instead of Setuptools. Set environ variable '
 
862
        'VIRTUALENV_DISTRIBUTE to make it the default ')
 
863
 
 
864
    parser.add_option(
 
865
        '--setuptools',
 
866
        dest='use_distribute',
 
867
        action='store_false',
 
868
        help='Use Setuptools instead of Distribute.  Set environ variable '
 
869
        'VIRTUALENV_SETUPTOOLS to make it the default ')
 
870
 
 
871
    # Set this to True to use distribute by default, even in Python 2.
 
872
    parser.set_defaults(use_distribute=False)
 
873
 
 
874
    default_search_dirs = file_search_dirs()
 
875
    parser.add_option(
 
876
        '--extra-search-dir',
 
877
        dest="search_dirs",
 
878
        action="append",
 
879
        default=default_search_dirs,
 
880
        help="Directory to look for setuptools/distribute/pip distributions in. "
 
881
        "You can add any number of additional --extra-search-dir paths.")
 
882
 
 
883
    parser.add_option(
 
884
        '--never-download',
 
885
        dest="never_download",
 
886
        action="store_true",
 
887
        help="Never download anything from the network.  Instead, virtualenv will fail "
 
888
        "if local distributions of setuptools/distribute/pip are not present.")
 
889
 
 
890
    parser.add_option(
 
891
        '--prompt',
 
892
        dest='prompt',
 
893
        help='Provides an alternative prompt prefix for this environment')
 
894
 
 
895
    if 'extend_parser' in globals():
 
896
        extend_parser(parser)
 
897
 
 
898
    options, args = parser.parse_args()
 
899
 
 
900
    global logger
 
901
 
 
902
    if 'adjust_options' in globals():
 
903
        adjust_options(options, args)
 
904
 
 
905
    verbosity = options.verbose - options.quiet
 
906
    logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)])
 
907
 
 
908
    if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
 
909
        env = os.environ.copy()
 
910
        interpreter = resolve_interpreter(options.python)
 
911
        if interpreter == sys.executable:
 
912
            logger.warn('Already using interpreter %s' % interpreter)
 
913
        else:
 
914
            logger.notify('Running virtualenv with interpreter %s' % interpreter)
 
915
            env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
 
916
            file = __file__
 
917
            if file.endswith('.pyc'):
 
918
                file = file[:-1]
 
919
            popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
 
920
            raise SystemExit(popen.wait())
 
921
 
 
922
    # Force --distribute on Python 3, since setuptools is not available.
 
923
    if majver > 2:
 
924
        options.use_distribute = True
 
925
 
 
926
    if os.environ.get('PYTHONDONTWRITEBYTECODE') and not options.use_distribute:
 
927
        print(
 
928
            "The PYTHONDONTWRITEBYTECODE environment variable is "
 
929
            "not compatible with setuptools. Either use --distribute "
 
930
            "or unset PYTHONDONTWRITEBYTECODE.")
 
931
        sys.exit(2)
 
932
    if not args:
 
933
        print('You must provide a DEST_DIR')
 
934
        parser.print_help()
 
935
        sys.exit(2)
 
936
    if len(args) > 1:
 
937
        print('There must be only one argument: DEST_DIR (you gave %s)' % (
 
938
            ' '.join(args)))
 
939
        parser.print_help()
 
940
        sys.exit(2)
 
941
 
 
942
    home_dir = args[0]
 
943
 
 
944
    if os.environ.get('WORKING_ENV'):
 
945
        logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
 
946
        logger.fatal('Please deactivate your workingenv, then re-run this script')
 
947
        sys.exit(3)
 
948
 
 
949
    if 'PYTHONHOME' in os.environ:
 
950
        logger.warn('PYTHONHOME is set.  You *must* activate the virtualenv before using it')
 
951
        del os.environ['PYTHONHOME']
 
952
 
 
953
    if options.relocatable:
 
954
        make_environment_relocatable(home_dir)
 
955
        return
 
956
 
 
957
    create_environment(home_dir,
 
958
                       site_packages=options.system_site_packages,
 
959
                       clear=options.clear,
 
960
                       unzip_setuptools=options.unzip_setuptools,
 
961
                       use_distribute=options.use_distribute,
 
962
                       prompt=options.prompt,
 
963
                       search_dirs=options.search_dirs,
 
964
                       never_download=options.never_download)
 
965
    if 'after_install' in globals():
 
966
        after_install(options, home_dir)
 
967
 
 
968
def call_subprocess(cmd, show_stdout=True,
 
969
                    filter_stdout=None, cwd=None,
 
970
                    raise_on_returncode=True, extra_env=None,
 
971
                    remove_from_env=None):
 
972
    cmd_parts = []
 
973
    for part in cmd:
 
974
        if len(part) > 45:
 
975
            part = part[:20]+"..."+part[-20:]
 
976
        if ' ' in part or '\n' in part or '"' in part or "'" in part:
 
977
            part = '"%s"' % part.replace('"', '\\"')
 
978
        if hasattr(part, 'decode'):
 
979
            try:
 
980
                part = part.decode(sys.getdefaultencoding())
 
981
            except UnicodeDecodeError:
 
982
                part = part.decode(sys.getfilesystemencoding())
 
983
        cmd_parts.append(part)
 
984
    cmd_desc = ' '.join(cmd_parts)
 
985
    if show_stdout:
 
986
        stdout = None
 
987
    else:
 
988
        stdout = subprocess.PIPE
 
989
    logger.debug("Running command %s" % cmd_desc)
 
990
    if extra_env or remove_from_env:
 
991
        env = os.environ.copy()
 
992
        if extra_env:
 
993
            env.update(extra_env)
 
994
        if remove_from_env:
 
995
            for varname in remove_from_env:
 
996
                env.pop(varname, None)
 
997
    else:
 
998
        env = None
 
999
    try:
 
1000
        proc = subprocess.Popen(
 
1001
            cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
 
1002
            cwd=cwd, env=env)
 
1003
    except Exception:
 
1004
        e = sys.exc_info()[1]
 
1005
        logger.fatal(
 
1006
            "Error %s while executing command %s" % (e, cmd_desc))
 
1007
        raise
 
1008
    all_output = []
 
1009
    if stdout is not None:
 
1010
        stdout = proc.stdout
 
1011
        encoding = sys.getdefaultencoding()
 
1012
        fs_encoding = sys.getfilesystemencoding()
 
1013
        while 1:
 
1014
            line = stdout.readline()
 
1015
            try:
 
1016
                line = line.decode(encoding)
 
1017
            except UnicodeDecodeError:
 
1018
                line = line.decode(fs_encoding)
 
1019
            if not line:
 
1020
                break
 
1021
            line = line.rstrip()
 
1022
            all_output.append(line)
 
1023
            if filter_stdout:
 
1024
                level = filter_stdout(line)
 
1025
                if isinstance(level, tuple):
 
1026
                    level, line = level
 
1027
                logger.log(level, line)
 
1028
                if not logger.stdout_level_matches(level):
 
1029
                    logger.show_progress()
 
1030
            else:
 
1031
                logger.info(line)
 
1032
    else:
 
1033
        proc.communicate()
 
1034
    proc.wait()
 
1035
    if proc.returncode:
 
1036
        if raise_on_returncode:
 
1037
            if all_output:
 
1038
                logger.notify('Complete output from command %s:' % cmd_desc)
 
1039
                logger.notify('\n'.join(all_output) + '\n----------------------------------------')
 
1040
            raise OSError(
 
1041
                "Command %s failed with error code %s"
 
1042
                % (cmd_desc, proc.returncode))
 
1043
        else:
 
1044
            logger.warn(
 
1045
                "Command %s had error code %s"
 
1046
                % (cmd_desc, proc.returncode))
 
1047
 
 
1048
 
 
1049
def create_environment(home_dir, site_packages=False, clear=False,
 
1050
                       unzip_setuptools=False, use_distribute=False,
 
1051
                       prompt=None, search_dirs=None, never_download=False):
 
1052
    """
 
1053
    Creates a new environment in ``home_dir``.
 
1054
 
 
1055
    If ``site_packages`` is true, then the global ``site-packages/``
 
1056
    directory will be on the path.
 
1057
 
 
1058
    If ``clear`` is true (default False) then the environment will
 
1059
    first be cleared.
 
1060
    """
 
1061
    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
 
1062
 
 
1063
    py_executable = os.path.abspath(install_python(
 
1064
        home_dir, lib_dir, inc_dir, bin_dir,
 
1065
        site_packages=site_packages, clear=clear))
 
1066
 
 
1067
    install_distutils(home_dir)
 
1068
 
 
1069
    if use_distribute:
 
1070
        install_distribute(py_executable, unzip=unzip_setuptools,
 
1071
                           search_dirs=search_dirs, never_download=never_download)
 
1072
    else:
 
1073
        install_setuptools(py_executable, unzip=unzip_setuptools,
 
1074
                           search_dirs=search_dirs, never_download=never_download)
 
1075
 
 
1076
    install_pip(py_executable, search_dirs=search_dirs, never_download=never_download)
 
1077
 
 
1078
    install_activate(home_dir, bin_dir, prompt)
 
1079
 
 
1080
def is_executable_file(fpath):
 
1081
    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
 
1082
 
 
1083
def path_locations(home_dir):
 
1084
    """Return the path locations for the environment (where libraries are,
 
1085
    where scripts go, etc)"""
 
1086
    # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
 
1087
    # prefix arg is broken: http://bugs.python.org/issue3386
 
1088
    if is_win:
 
1089
        # Windows has lots of problems with executables with spaces in
 
1090
        # the name; this function will remove them (using the ~1
 
1091
        # format):
 
1092
        mkdir(home_dir)
 
1093
        if ' ' in home_dir:
 
1094
            import ctypes
 
1095
            GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW
 
1096
            size = max(len(home_dir)+1, 256)
 
1097
            buf = ctypes.create_unicode_buffer(size)
 
1098
            try:
 
1099
                u = unicode
 
1100
            except NameError:
 
1101
                u = str
 
1102
            ret = GetShortPathName(u(home_dir), buf, size)
 
1103
            if not ret:
 
1104
                print('Error: the path "%s" has a space in it' % home_dir)
 
1105
                print('We could not determine the short pathname for it.')
 
1106
                print('Exiting.')
 
1107
                sys.exit(3)
 
1108
            home_dir = str(buf.value)
 
1109
        lib_dir = join(home_dir, 'Lib')
 
1110
        inc_dir = join(home_dir, 'Include')
 
1111
        bin_dir = join(home_dir, 'Scripts')
 
1112
    if is_jython:
 
1113
        lib_dir = join(home_dir, 'Lib')
 
1114
        inc_dir = join(home_dir, 'Include')
 
1115
        bin_dir = join(home_dir, 'bin')
 
1116
    elif is_pypy:
 
1117
        lib_dir = home_dir
 
1118
        inc_dir = join(home_dir, 'include')
 
1119
        bin_dir = join(home_dir, 'bin')
 
1120
    elif not is_win:
 
1121
        lib_dir = join(home_dir, 'lib', py_version)
 
1122
        multiarch_exec = '/usr/bin/multiarch-platform'
 
1123
        if is_executable_file(multiarch_exec):
 
1124
            # In Mageia (2) and Mandriva distros the include dir must be like:
 
1125
            # virtualenv/include/multiarch-x86_64-linux/python2.7
 
1126
            # instead of being virtualenv/include/python2.7
 
1127
            p = subprocess.Popen(multiarch_exec, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
1128
            stdout, stderr = p.communicate()
 
1129
            # stdout.strip is needed to remove newline character
 
1130
            inc_dir = join(home_dir, 'include', stdout.strip(), py_version + abiflags)
 
1131
        else:
 
1132
            inc_dir = join(home_dir, 'include', py_version + abiflags)
 
1133
        bin_dir = join(home_dir, 'bin')
 
1134
    return home_dir, lib_dir, inc_dir, bin_dir
 
1135
 
 
1136
 
 
1137
def change_prefix(filename, dst_prefix):
 
1138
    prefixes = [sys.prefix]
 
1139
 
 
1140
    if is_darwin:
 
1141
        prefixes.extend((
 
1142
            os.path.join("/Library/Python", sys.version[:3], "site-packages"),
 
1143
            os.path.join(sys.prefix, "Extras", "lib", "python"),
 
1144
            os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"),
 
1145
            # Python 2.6 no-frameworks
 
1146
            os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"),
 
1147
            # System Python 2.7 on OSX Mountain Lion
 
1148
            os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages")))
 
1149
 
 
1150
    if hasattr(sys, 'real_prefix'):
 
1151
        prefixes.append(sys.real_prefix)
 
1152
    if hasattr(sys, 'base_prefix'):
 
1153
        prefixes.append(sys.base_prefix)
 
1154
    prefixes = list(map(os.path.expanduser, prefixes))
 
1155
    prefixes = list(map(os.path.abspath, prefixes))
 
1156
    # Check longer prefixes first so we don't split in the middle of a filename
 
1157
    prefixes = sorted(prefixes, key=len, reverse=True)
 
1158
    filename = os.path.abspath(filename)
 
1159
    for src_prefix in prefixes:
 
1160
        if filename.startswith(src_prefix):
 
1161
            _, relpath = filename.split(src_prefix, 1)
 
1162
            if src_prefix != os.sep: # sys.prefix == "/"
 
1163
                assert relpath[0] == os.sep
 
1164
                relpath = relpath[1:]
 
1165
            return join(dst_prefix, relpath)
 
1166
    assert False, "Filename %s does not start with any of these prefixes: %s" % \
 
1167
        (filename, prefixes)
 
1168
 
 
1169
def copy_required_modules(dst_prefix):
 
1170
    import imp
 
1171
    # If we are running under -p, we need to remove the current
 
1172
    # directory from sys.path temporarily here, so that we
 
1173
    # definitely get the modules from the site directory of
 
1174
    # the interpreter we are running under, not the one
 
1175
    # virtualenv.py is installed under (which might lead to py2/py3
 
1176
    # incompatibility issues)
 
1177
    _prev_sys_path = sys.path
 
1178
    if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
 
1179
        sys.path = sys.path[1:]
 
1180
    try:
 
1181
        for modname in REQUIRED_MODULES:
 
1182
            if modname in sys.builtin_module_names:
 
1183
                logger.info("Ignoring built-in bootstrap module: %s" % modname)
 
1184
                continue
 
1185
            try:
 
1186
                f, filename, _ = imp.find_module(modname)
 
1187
            except ImportError:
 
1188
                logger.info("Cannot import bootstrap module: %s" % modname)
 
1189
            else:
 
1190
                if f is not None:
 
1191
                    f.close()
 
1192
                # special-case custom readline.so on OS X:
 
1193
                if modname == 'readline' and sys.platform == 'darwin' and not filename.endswith(join('lib-dynload', 'readline.so')):
 
1194
                    dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so')
 
1195
                else:
 
1196
                    dst_filename = change_prefix(filename, dst_prefix)
 
1197
                copyfile(filename, dst_filename)
 
1198
                if filename.endswith('.pyc'):
 
1199
                    pyfile = filename[:-1]
 
1200
                    if os.path.exists(pyfile):
 
1201
                        copyfile(pyfile, dst_filename[:-1])
 
1202
    finally:
 
1203
        sys.path = _prev_sys_path
 
1204
 
 
1205
 
 
1206
def subst_path(prefix_path, prefix, home_dir):
 
1207
    prefix_path = os.path.normpath(prefix_path)
 
1208
    prefix = os.path.normpath(prefix)
 
1209
    home_dir = os.path.normpath(home_dir)
 
1210
    if not prefix_path.startswith(prefix):
 
1211
        logger.warn('Path not in prefix %r %r', prefix_path, prefix)
 
1212
        return
 
1213
    return prefix_path.replace(prefix, home_dir, 1)
 
1214
 
 
1215
 
 
1216
def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
 
1217
    """Install just the base environment, no distutils patches etc"""
 
1218
    if sys.executable.startswith(bin_dir):
 
1219
        print('Please use the *system* python to run this script')
 
1220
        return
 
1221
 
 
1222
    if clear:
 
1223
        rmtree(lib_dir)
 
1224
        ## FIXME: why not delete it?
 
1225
        ## Maybe it should delete everything with #!/path/to/venv/python in it
 
1226
        logger.notify('Not deleting %s', bin_dir)
 
1227
 
 
1228
    if hasattr(sys, 'real_prefix'):
 
1229
        logger.notify('Using real prefix %r' % sys.real_prefix)
 
1230
        prefix = sys.real_prefix
 
1231
    elif hasattr(sys, 'base_prefix'):
 
1232
        logger.notify('Using base prefix %r' % sys.base_prefix)
 
1233
        prefix = sys.base_prefix
 
1234
    else:
 
1235
        prefix = sys.prefix
 
1236
    mkdir(lib_dir)
 
1237
    fix_lib64(lib_dir)
 
1238
    stdlib_dirs = [os.path.dirname(os.__file__)]
 
1239
    if is_win:
 
1240
        stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
 
1241
    elif is_darwin:
 
1242
        stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
 
1243
    if hasattr(os, 'symlink'):
 
1244
        logger.info('Symlinking Python bootstrap modules')
 
1245
    else:
 
1246
        logger.info('Copying Python bootstrap modules')
 
1247
    logger.indent += 2
 
1248
    try:
 
1249
        # copy required files...
 
1250
        for stdlib_dir in stdlib_dirs:
 
1251
            if not os.path.isdir(stdlib_dir):
 
1252
                continue
 
1253
            for fn in os.listdir(stdlib_dir):
 
1254
                bn = os.path.splitext(fn)[0]
 
1255
                if fn != 'site-packages' and bn in REQUIRED_FILES:
 
1256
                    copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
 
1257
        # ...and modules
 
1258
        copy_required_modules(home_dir)
 
1259
    finally:
 
1260
        logger.indent -= 2
 
1261
    mkdir(join(lib_dir, 'site-packages'))
 
1262
    import site
 
1263
    site_filename = site.__file__
 
1264
    if site_filename.endswith('.pyc'):
 
1265
        site_filename = site_filename[:-1]
 
1266
    elif site_filename.endswith('$py.class'):
 
1267
        site_filename = site_filename.replace('$py.class', '.py')
 
1268
    site_filename_dst = change_prefix(site_filename, home_dir)
 
1269
    site_dir = os.path.dirname(site_filename_dst)
 
1270
    writefile(site_filename_dst, SITE_PY)
 
1271
    writefile(join(site_dir, 'orig-prefix.txt'), prefix)
 
1272
    site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
 
1273
    if not site_packages:
 
1274
        writefile(site_packages_filename, '')
 
1275
 
 
1276
    if is_pypy or is_win:
 
1277
        stdinc_dir = join(prefix, 'include')
 
1278
    else:
 
1279
        stdinc_dir = join(prefix, 'include', py_version + abiflags)
 
1280
    if os.path.exists(stdinc_dir):
 
1281
        copyfile(stdinc_dir, inc_dir)
 
1282
    else:
 
1283
        logger.debug('No include dir %s' % stdinc_dir)
 
1284
 
 
1285
    platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1)
 
1286
    if platinc_dir != stdinc_dir:
 
1287
        platinc_dest = distutils.sysconfig.get_python_inc(
 
1288
            plat_specific=1, prefix=home_dir)
 
1289
        if platinc_dir == platinc_dest:
 
1290
            # Do platinc_dest manually due to a CPython bug;
 
1291
            # not http://bugs.python.org/issue3386 but a close cousin
 
1292
            platinc_dest = subst_path(platinc_dir, prefix, home_dir)
 
1293
        if platinc_dest:
 
1294
            # PyPy's stdinc_dir and prefix are relative to the original binary
 
1295
            # (traversing virtualenvs), whereas the platinc_dir is relative to
 
1296
            # the inner virtualenv and ignores the prefix argument.
 
1297
            # This seems more evolved than designed.
 
1298
            copyfile(platinc_dir, platinc_dest)
 
1299
 
 
1300
    # pypy never uses exec_prefix, just ignore it
 
1301
    if sys.exec_prefix != prefix and not is_pypy:
 
1302
        if is_win:
 
1303
            exec_dir = join(sys.exec_prefix, 'lib')
 
1304
        elif is_jython:
 
1305
            exec_dir = join(sys.exec_prefix, 'Lib')
 
1306
        else:
 
1307
            exec_dir = join(sys.exec_prefix, 'lib', py_version)
 
1308
        for fn in os.listdir(exec_dir):
 
1309
            copyfile(join(exec_dir, fn), join(lib_dir, fn))
 
1310
 
 
1311
    if is_jython:
 
1312
        # Jython has either jython-dev.jar and javalib/ dir, or just
 
1313
        # jython.jar
 
1314
        for name in 'jython-dev.jar', 'javalib', 'jython.jar':
 
1315
            src = join(prefix, name)
 
1316
            if os.path.exists(src):
 
1317
                copyfile(src, join(home_dir, name))
 
1318
        # XXX: registry should always exist after Jython 2.5rc1
 
1319
        src = join(prefix, 'registry')
 
1320
        if os.path.exists(src):
 
1321
            copyfile(src, join(home_dir, 'registry'), symlink=False)
 
1322
        copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
 
1323
                 symlink=False)
 
1324
 
 
1325
    mkdir(bin_dir)
 
1326
    py_executable = join(bin_dir, os.path.basename(sys.executable))
 
1327
    if 'Python.framework' in prefix:
 
1328
        # OS X framework builds cause validation to break
 
1329
        # https://github.com/pypa/virtualenv/issues/322
 
1330
        if os.environ.get('__PYVENV_LAUNCHER__'):
 
1331
          os.unsetenv('__PYVENV_LAUNCHER__')
 
1332
        if re.search(r'/Python(?:-32|-64)*$', py_executable):
 
1333
            # The name of the python executable is not quite what
 
1334
            # we want, rename it.
 
1335
            py_executable = os.path.join(
 
1336
                    os.path.dirname(py_executable), 'python')
 
1337
 
 
1338
    logger.notify('New %s executable in %s', expected_exe, py_executable)
 
1339
    pcbuild_dir = os.path.dirname(sys.executable)
 
1340
    pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth')
 
1341
    if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')):
 
1342
        logger.notify('Detected python running from build directory %s', pcbuild_dir)
 
1343
        logger.notify('Writing .pth file linking to build directory for *.pyd files')
 
1344
        writefile(pyd_pth, pcbuild_dir)
 
1345
    else:
 
1346
        pcbuild_dir = None
 
1347
        if os.path.exists(pyd_pth):
 
1348
            logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth)
 
1349
            os.unlink(pyd_pth)
 
1350
 
 
1351
    if sys.executable != py_executable:
 
1352
        ## FIXME: could I just hard link?
 
1353
        executable = sys.executable
 
1354
        if is_cygwin and os.path.exists(executable + '.exe'):
 
1355
            # Cygwin misreports sys.executable sometimes
 
1356
            executable += '.exe'
 
1357
            py_executable += '.exe'
 
1358
            logger.info('Executable actually exists in %s' % executable)
 
1359
        shutil.copyfile(executable, py_executable)
 
1360
        make_exe(py_executable)
 
1361
        if is_win or is_cygwin:
 
1362
            pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
 
1363
            if os.path.exists(pythonw):
 
1364
                logger.info('Also created pythonw.exe')
 
1365
                shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
 
1366
            python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe')
 
1367
            python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe')
 
1368
            if os.path.exists(python_d):
 
1369
                logger.info('Also created python_d.exe')
 
1370
                shutil.copyfile(python_d, python_d_dest)
 
1371
            elif os.path.exists(python_d_dest):
 
1372
                logger.info('Removed python_d.exe as it is no longer at the source')
 
1373
                os.unlink(python_d_dest)
 
1374
            # we need to copy the DLL to enforce that windows will load the correct one.
 
1375
            # may not exist if we are cygwin.
 
1376
            py_executable_dll = 'python%s%s.dll' % (
 
1377
                sys.version_info[0], sys.version_info[1])
 
1378
            py_executable_dll_d = 'python%s%s_d.dll' % (
 
1379
                sys.version_info[0], sys.version_info[1])
 
1380
            pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll)
 
1381
            pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d)
 
1382
            pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d)
 
1383
            if os.path.exists(pythondll):
 
1384
                logger.info('Also created %s' % py_executable_dll)
 
1385
                shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll))
 
1386
            if os.path.exists(pythondll_d):
 
1387
                logger.info('Also created %s' % py_executable_dll_d)
 
1388
                shutil.copyfile(pythondll_d, pythondll_d_dest)
 
1389
            elif os.path.exists(pythondll_d_dest):
 
1390
                logger.info('Removed %s as the source does not exist' % pythondll_d_dest)
 
1391
                os.unlink(pythondll_d_dest)
 
1392
        if is_pypy:
 
1393
            # make a symlink python --> pypy-c
 
1394
            python_executable = os.path.join(os.path.dirname(py_executable), 'python')
 
1395
            if sys.platform in ('win32', 'cygwin'):
 
1396
                python_executable += '.exe'
 
1397
            logger.info('Also created executable %s' % python_executable)
 
1398
            copyfile(py_executable, python_executable)
 
1399
 
 
1400
            if is_win:
 
1401
                for name in 'libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', 'libeay32.dll', 'ssleay32.dll', 'sqlite.dll':
 
1402
                    src = join(prefix, name)
 
1403
                    if os.path.exists(src):
 
1404
                        copyfile(src, join(bin_dir, name))
 
1405
 
 
1406
    if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
 
1407
        secondary_exe = os.path.join(os.path.dirname(py_executable),
 
1408
                                     expected_exe)
 
1409
        py_executable_ext = os.path.splitext(py_executable)[1]
 
1410
        if py_executable_ext == '.exe':
 
1411
            # python2.4 gives an extension of '.4' :P
 
1412
            secondary_exe += py_executable_ext
 
1413
        if os.path.exists(secondary_exe):
 
1414
            logger.warn('Not overwriting existing %s script %s (you must use %s)'
 
1415
                        % (expected_exe, secondary_exe, py_executable))
 
1416
        else:
 
1417
            logger.notify('Also creating executable in %s' % secondary_exe)
 
1418
            shutil.copyfile(sys.executable, secondary_exe)
 
1419
            make_exe(secondary_exe)
 
1420
 
 
1421
    if '.framework' in prefix:
 
1422
        if 'Python.framework' in prefix:
 
1423
            logger.debug('MacOSX Python framework detected')
 
1424
            # Make sure we use the the embedded interpreter inside
 
1425
            # the framework, even if sys.executable points to
 
1426
            # the stub executable in ${sys.prefix}/bin
 
1427
            # See http://groups.google.com/group/python-virtualenv/
 
1428
            #                              browse_thread/thread/17cab2f85da75951
 
1429
            original_python = os.path.join(
 
1430
                prefix, 'Resources/Python.app/Contents/MacOS/Python')
 
1431
        if 'EPD' in prefix:
 
1432
            logger.debug('EPD framework detected')
 
1433
            original_python = os.path.join(prefix, 'bin/python')
 
1434
        shutil.copy(original_python, py_executable)
 
1435
 
 
1436
        # Copy the framework's dylib into the virtual
 
1437
        # environment
 
1438
        virtual_lib = os.path.join(home_dir, '.Python')
 
1439
 
 
1440
        if os.path.exists(virtual_lib):
 
1441
            os.unlink(virtual_lib)
 
1442
        copyfile(
 
1443
            os.path.join(prefix, 'Python'),
 
1444
            virtual_lib)
 
1445
 
 
1446
        # And then change the install_name of the copied python executable
 
1447
        try:
 
1448
            mach_o_change(py_executable,
 
1449
                          os.path.join(prefix, 'Python'),
 
1450
                          '@executable_path/../.Python')
 
1451
        except:
 
1452
            e = sys.exc_info()[1]
 
1453
            logger.warn("Could not call mach_o_change: %s. "
 
1454
                        "Trying to call install_name_tool instead." % e)
 
1455
            try:
 
1456
                call_subprocess(
 
1457
                    ["install_name_tool", "-change",
 
1458
                     os.path.join(prefix, 'Python'),
 
1459
                     '@executable_path/../.Python',
 
1460
                     py_executable])
 
1461
            except:
 
1462
                logger.fatal("Could not call install_name_tool -- you must "
 
1463
                             "have Apple's development tools installed")
 
1464
                raise
 
1465
 
 
1466
    if not is_win:
 
1467
        # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist
 
1468
        py_exe_version_major = 'python%s' % sys.version_info[0]
 
1469
        py_exe_version_major_minor = 'python%s.%s' % (
 
1470
            sys.version_info[0], sys.version_info[1])
 
1471
        py_exe_no_version = 'python'
 
1472
        required_symlinks = [ py_exe_no_version, py_exe_version_major,
 
1473
                         py_exe_version_major_minor ]
 
1474
 
 
1475
        py_executable_base = os.path.basename(py_executable)
 
1476
 
 
1477
        if py_executable_base in required_symlinks:
 
1478
            # Don't try to symlink to yourself.
 
1479
            required_symlinks.remove(py_executable_base)
 
1480
 
 
1481
        for pth in required_symlinks:
 
1482
            full_pth = join(bin_dir, pth)
 
1483
            if os.path.exists(full_pth):
 
1484
                os.unlink(full_pth)
 
1485
            os.symlink(py_executable_base, full_pth)
 
1486
 
 
1487
    if is_win and ' ' in py_executable:
 
1488
        # There's a bug with subprocess on Windows when using a first
 
1489
        # argument that has a space in it.  Instead we have to quote
 
1490
        # the value:
 
1491
        py_executable = '"%s"' % py_executable
 
1492
    # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks
 
1493
    cmd = [py_executable, '-c', 'import sys;out=sys.stdout;'
 
1494
        'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))']
 
1495
    logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
 
1496
    try:
 
1497
        proc = subprocess.Popen(cmd,
 
1498
                            stdout=subprocess.PIPE)
 
1499
        proc_stdout, proc_stderr = proc.communicate()
 
1500
    except OSError:
 
1501
        e = sys.exc_info()[1]
 
1502
        if e.errno == errno.EACCES:
 
1503
            logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e))
 
1504
            sys.exit(100)
 
1505
        else:
 
1506
            raise e
 
1507
 
 
1508
    proc_stdout = proc_stdout.strip().decode("utf-8")
 
1509
    proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
 
1510
    norm_home_dir = os.path.normcase(os.path.abspath(home_dir))
 
1511
    if hasattr(norm_home_dir, 'decode'):
 
1512
        norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding())
 
1513
    if proc_stdout != norm_home_dir:
 
1514
        logger.fatal(
 
1515
            'ERROR: The executable %s is not functioning' % py_executable)
 
1516
        logger.fatal(
 
1517
            'ERROR: It thinks sys.prefix is %r (should be %r)'
 
1518
            % (proc_stdout, norm_home_dir))
 
1519
        logger.fatal(
 
1520
            'ERROR: virtualenv is not compatible with this system or executable')
 
1521
        if is_win:
 
1522
            logger.fatal(
 
1523
                'Note: some Windows users have reported this error when they '
 
1524
                'installed Python for "Only this user" or have multiple '
 
1525
                'versions of Python installed. Copying the appropriate '
 
1526
                'PythonXX.dll to the virtualenv Scripts/ directory may fix '
 
1527
                'this problem.')
 
1528
        sys.exit(100)
 
1529
    else:
 
1530
        logger.info('Got sys.prefix result: %r' % proc_stdout)
 
1531
 
 
1532
    pydistutils = os.path.expanduser('~/.pydistutils.cfg')
 
1533
    if os.path.exists(pydistutils):
 
1534
        logger.notify('Please make sure you remove any previous custom paths from '
 
1535
                      'your %s file.' % pydistutils)
 
1536
    ## FIXME: really this should be calculated earlier
 
1537
 
 
1538
    fix_local_scheme(home_dir)
 
1539
 
 
1540
    if site_packages:
 
1541
        if os.path.exists(site_packages_filename):
 
1542
            logger.info('Deleting %s' % site_packages_filename)
 
1543
            os.unlink(site_packages_filename)
 
1544
 
 
1545
    return py_executable
 
1546
 
 
1547
 
 
1548
def install_activate(home_dir, bin_dir, prompt=None):
 
1549
    home_dir = os.path.abspath(home_dir)
 
1550
    if is_win or is_jython and os._name == 'nt':
 
1551
        files = {
 
1552
            'activate.bat': ACTIVATE_BAT,
 
1553
            'deactivate.bat': DEACTIVATE_BAT,
 
1554
            'activate.ps1': ACTIVATE_PS,
 
1555
        }
 
1556
 
 
1557
        # MSYS needs paths of the form /c/path/to/file
 
1558
        drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/'))
 
1559
        home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail)
 
1560
 
 
1561
        # Run-time conditional enables (basic) Cygwin compatibility
 
1562
        home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" %
 
1563
                       (home_dir, home_dir_msys))
 
1564
        files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh)
 
1565
 
 
1566
    else:
 
1567
        files = {'activate': ACTIVATE_SH}
 
1568
 
 
1569
        # suppling activate.fish in addition to, not instead of, the
 
1570
        # bash script support.
 
1571
        files['activate.fish'] = ACTIVATE_FISH
 
1572
 
 
1573
        # same for csh/tcsh support...
 
1574
        files['activate.csh'] = ACTIVATE_CSH
 
1575
 
 
1576
    files['activate_this.py'] = ACTIVATE_THIS
 
1577
    if hasattr(home_dir, 'decode'):
 
1578
        home_dir = home_dir.decode(sys.getfilesystemencoding())
 
1579
    vname = os.path.basename(home_dir)
 
1580
    for name, content in files.items():
 
1581
        content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
 
1582
        content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname)
 
1583
        content = content.replace('__VIRTUAL_ENV__', home_dir)
 
1584
        content = content.replace('__VIRTUAL_NAME__', vname)
 
1585
        content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
 
1586
        writefile(os.path.join(bin_dir, name), content)
 
1587
 
 
1588
def install_distutils(home_dir):
 
1589
    distutils_path = change_prefix(distutils.__path__[0], home_dir)
 
1590
    mkdir(distutils_path)
 
1591
    ## FIXME: maybe this prefix setting should only be put in place if
 
1592
    ## there's a local distutils.cfg with a prefix setting?
 
1593
    home_dir = os.path.abspath(home_dir)
 
1594
    ## FIXME: this is breaking things, removing for now:
 
1595
    #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
 
1596
    writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
 
1597
    writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
 
1598
 
 
1599
def fix_local_scheme(home_dir):
 
1600
    """
 
1601
    Platforms that use the "posix_local" install scheme (like Ubuntu with
 
1602
    Python 2.7) need to be given an additional "local" location, sigh.
 
1603
    """
 
1604
    try:
 
1605
        import sysconfig
 
1606
    except ImportError:
 
1607
        pass
 
1608
    else:
 
1609
        if sysconfig._get_default_scheme() == 'posix_local':
 
1610
            local_path = os.path.join(home_dir, 'local')
 
1611
            if not os.path.exists(local_path):
 
1612
                os.mkdir(local_path)
 
1613
                for subdir_name in os.listdir(home_dir):
 
1614
                    if subdir_name == 'local':
 
1615
                        continue
 
1616
                    os.symlink(os.path.abspath(os.path.join(home_dir, subdir_name)), \
 
1617
                                                            os.path.join(local_path, subdir_name))
 
1618
 
 
1619
def fix_lib64(lib_dir):
 
1620
    """
 
1621
    Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
 
1622
    instead of lib/pythonX.Y.  If this is such a platform we'll just create a
 
1623
    symlink so lib64 points to lib
 
1624
    """
 
1625
    if [p for p in distutils.sysconfig.get_config_vars().values()
 
1626
        if isinstance(p, basestring) and 'lib64' in p]:
 
1627
        logger.debug('This system uses lib64; symlinking lib64 to lib')
 
1628
        assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
 
1629
            "Unexpected python lib dir: %r" % lib_dir)
 
1630
        lib_parent = os.path.dirname(lib_dir)
 
1631
        top_level = os.path.dirname(lib_parent)
 
1632
        lib_dir = os.path.join(top_level, 'lib')
 
1633
        lib64_link = os.path.join(top_level, 'lib64')
 
1634
        assert os.path.basename(lib_parent) == 'lib', (
 
1635
            "Unexpected parent dir: %r" % lib_parent)
 
1636
        if os.path.lexists(lib64_link):
 
1637
            return
 
1638
        os.symlink('lib', lib64_link)
 
1639
 
 
1640
def resolve_interpreter(exe):
 
1641
    """
 
1642
    If the executable given isn't an absolute path, search $PATH for the interpreter
 
1643
    """
 
1644
    if os.path.abspath(exe) != exe:
 
1645
        paths = os.environ.get('PATH', '').split(os.pathsep)
 
1646
        for path in paths:
 
1647
            if os.path.exists(os.path.join(path, exe)):
 
1648
                exe = os.path.join(path, exe)
 
1649
                break
 
1650
    if not os.path.exists(exe):
 
1651
        logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
 
1652
        raise SystemExit(3)
 
1653
    if not is_executable(exe):
 
1654
        logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
 
1655
        raise SystemExit(3)
 
1656
    return exe
 
1657
 
 
1658
def is_executable(exe):
 
1659
    """Checks a file is executable"""
 
1660
    return os.access(exe, os.X_OK)
 
1661
 
 
1662
############################################################
 
1663
## Relocating the environment:
 
1664
 
 
1665
def make_environment_relocatable(home_dir):
 
1666
    """
 
1667
    Makes the already-existing environment use relative paths, and takes out
 
1668
    the #!-based environment selection in scripts.
 
1669
    """
 
1670
    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
 
1671
    activate_this = os.path.join(bin_dir, 'activate_this.py')
 
1672
    if not os.path.exists(activate_this):
 
1673
        logger.fatal(
 
1674
            'The environment doesn\'t have a file %s -- please re-run virtualenv '
 
1675
            'on this environment to update it' % activate_this)
 
1676
    fixup_scripts(home_dir)
 
1677
    fixup_pth_and_egg_link(home_dir)
 
1678
    ## FIXME: need to fix up distutils.cfg
 
1679
 
 
1680
OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
 
1681
                  'activate', 'activate.bat', 'activate_this.py']
 
1682
 
 
1683
def fixup_scripts(home_dir):
 
1684
    # This is what we expect at the top of scripts:
 
1685
    shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
 
1686
    # This is what we'll put:
 
1687
    new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
 
1688
    if is_win:
 
1689
        bin_suffix = 'Scripts'
 
1690
    else:
 
1691
        bin_suffix = 'bin'
 
1692
    bin_dir = os.path.join(home_dir, bin_suffix)
 
1693
    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
 
1694
    for filename in os.listdir(bin_dir):
 
1695
        filename = os.path.join(bin_dir, filename)
 
1696
        if not os.path.isfile(filename):
 
1697
            # ignore subdirs, e.g. .svn ones.
 
1698
            continue
 
1699
        f = open(filename, 'rb')
 
1700
        try:
 
1701
            try:
 
1702
                lines = f.read().decode('utf-8').splitlines()
 
1703
            except UnicodeDecodeError:
 
1704
                # This is probably a binary program instead
 
1705
                # of a script, so just ignore it.
 
1706
                continue
 
1707
        finally:
 
1708
            f.close()
 
1709
        if not lines:
 
1710
            logger.warn('Script %s is an empty file' % filename)
 
1711
            continue
 
1712
        if not lines[0].strip().startswith(shebang):
 
1713
            if os.path.basename(filename) in OK_ABS_SCRIPTS:
 
1714
                logger.debug('Cannot make script %s relative' % filename)
 
1715
            elif lines[0].strip() == new_shebang:
 
1716
                logger.info('Script %s has already been made relative' % filename)
 
1717
            else:
 
1718
                logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
 
1719
                            % (filename, shebang))
 
1720
            continue
 
1721
        logger.notify('Making script %s relative' % filename)
 
1722
        script = relative_script([new_shebang] + lines[1:])
 
1723
        f = open(filename, 'wb')
 
1724
        f.write('\n'.join(script).encode('utf-8'))
 
1725
        f.close()
 
1726
 
 
1727
def relative_script(lines):
 
1728
    "Return a script that'll work in a relocatable environment."
 
1729
    activate = "import os; activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this"
 
1730
    # Find the last future statement in the script. If we insert the activation
 
1731
    # line before a future statement, Python will raise a SyntaxError.
 
1732
    activate_at = None
 
1733
    for idx, line in reversed(list(enumerate(lines))):
 
1734
        if line.split()[:3] == ['from', '__future__', 'import']:
 
1735
            activate_at = idx + 1
 
1736
            break
 
1737
    if activate_at is None:
 
1738
        # Activate after the shebang.
 
1739
        activate_at = 1
 
1740
    return lines[:activate_at] + ['', activate, ''] + lines[activate_at:]
 
1741
 
 
1742
def fixup_pth_and_egg_link(home_dir, sys_path=None):
 
1743
    """Makes .pth and .egg-link files use relative paths"""
 
1744
    home_dir = os.path.normcase(os.path.abspath(home_dir))
 
1745
    if sys_path is None:
 
1746
        sys_path = sys.path
 
1747
    for path in sys_path:
 
1748
        if not path:
 
1749
            path = '.'
 
1750
        if not os.path.isdir(path):
 
1751
            continue
 
1752
        path = os.path.normcase(os.path.abspath(path))
 
1753
        if not path.startswith(home_dir):
 
1754
            logger.debug('Skipping system (non-environment) directory %s' % path)
 
1755
            continue
 
1756
        for filename in os.listdir(path):
 
1757
            filename = os.path.join(path, filename)
 
1758
            if filename.endswith('.pth'):
 
1759
                if not os.access(filename, os.W_OK):
 
1760
                    logger.warn('Cannot write .pth file %s, skipping' % filename)
 
1761
                else:
 
1762
                    fixup_pth_file(filename)
 
1763
            if filename.endswith('.egg-link'):
 
1764
                if not os.access(filename, os.W_OK):
 
1765
                    logger.warn('Cannot write .egg-link file %s, skipping' % filename)
 
1766
                else:
 
1767
                    fixup_egg_link(filename)
 
1768
 
 
1769
def fixup_pth_file(filename):
 
1770
    lines = []
 
1771
    prev_lines = []
 
1772
    f = open(filename)
 
1773
    prev_lines = f.readlines()
 
1774
    f.close()
 
1775
    for line in prev_lines:
 
1776
        line = line.strip()
 
1777
        if (not line or line.startswith('#') or line.startswith('import ')
 
1778
            or os.path.abspath(line) != line):
 
1779
            lines.append(line)
 
1780
        else:
 
1781
            new_value = make_relative_path(filename, line)
 
1782
            if line != new_value:
 
1783
                logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
 
1784
            lines.append(new_value)
 
1785
    if lines == prev_lines:
 
1786
        logger.info('No changes to .pth file %s' % filename)
 
1787
        return
 
1788
    logger.notify('Making paths in .pth file %s relative' % filename)
 
1789
    f = open(filename, 'w')
 
1790
    f.write('\n'.join(lines) + '\n')
 
1791
    f.close()
 
1792
 
 
1793
def fixup_egg_link(filename):
 
1794
    f = open(filename)
 
1795
    link = f.readline().strip()
 
1796
    f.close()
 
1797
    if os.path.abspath(link) != link:
 
1798
        logger.debug('Link in %s already relative' % filename)
 
1799
        return
 
1800
    new_link = make_relative_path(filename, link)
 
1801
    logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
 
1802
    f = open(filename, 'w')
 
1803
    f.write(new_link)
 
1804
    f.close()
 
1805
 
 
1806
def make_relative_path(source, dest, dest_is_directory=True):
 
1807
    """
 
1808
    Make a filename relative, where the filename is dest, and it is
 
1809
    being referred to from the filename source.
 
1810
 
 
1811
        >>> make_relative_path('/usr/share/something/a-file.pth',
 
1812
        ...                    '/usr/share/another-place/src/Directory')
 
1813
        '../another-place/src/Directory'
 
1814
        >>> make_relative_path('/usr/share/something/a-file.pth',
 
1815
        ...                    '/home/user/src/Directory')
 
1816
        '../../../home/user/src/Directory'
 
1817
        >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
 
1818
        './'
 
1819
    """
 
1820
    source = os.path.dirname(source)
 
1821
    if not dest_is_directory:
 
1822
        dest_filename = os.path.basename(dest)
 
1823
        dest = os.path.dirname(dest)
 
1824
    dest = os.path.normpath(os.path.abspath(dest))
 
1825
    source = os.path.normpath(os.path.abspath(source))
 
1826
    dest_parts = dest.strip(os.path.sep).split(os.path.sep)
 
1827
    source_parts = source.strip(os.path.sep).split(os.path.sep)
 
1828
    while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
 
1829
        dest_parts.pop(0)
 
1830
        source_parts.pop(0)
 
1831
    full_parts = ['..']*len(source_parts) + dest_parts
 
1832
    if not dest_is_directory:
 
1833
        full_parts.append(dest_filename)
 
1834
    if not full_parts:
 
1835
        # Special case for the current directory (otherwise it'd be '')
 
1836
        return './'
 
1837
    return os.path.sep.join(full_parts)
 
1838
 
 
1839
 
 
1840
 
 
1841
############################################################
 
1842
## Bootstrap script creation:
 
1843
 
 
1844
def create_bootstrap_script(extra_text, python_version=''):
 
1845
    """
 
1846
    Creates a bootstrap script, which is like this script but with
 
1847
    extend_parser, adjust_options, and after_install hooks.
 
1848
 
 
1849
    This returns a string that (written to disk of course) can be used
 
1850
    as a bootstrap script with your own customizations.  The script
 
1851
    will be the standard virtualenv.py script, with your extra text
 
1852
    added (your extra text should be Python code).
 
1853
 
 
1854
    If you include these functions, they will be called:
 
1855
 
 
1856
    ``extend_parser(optparse_parser)``:
 
1857
        You can add or remove options from the parser here.
 
1858
 
 
1859
    ``adjust_options(options, args)``:
 
1860
        You can change options here, or change the args (if you accept
 
1861
        different kinds of arguments, be sure you modify ``args`` so it is
 
1862
        only ``[DEST_DIR]``).
 
1863
 
 
1864
    ``after_install(options, home_dir)``:
 
1865
 
 
1866
        After everything is installed, this function is called.  This
 
1867
        is probably the function you are most likely to use.  An
 
1868
        example would be::
 
1869
 
 
1870
            def after_install(options, home_dir):
 
1871
                subprocess.call([join(home_dir, 'bin', 'easy_install'),
 
1872
                                 'MyPackage'])
 
1873
                subprocess.call([join(home_dir, 'bin', 'my-package-script'),
 
1874
                                 'setup', home_dir])
 
1875
 
 
1876
        This example immediately installs a package, and runs a setup
 
1877
        script from that package.
 
1878
 
 
1879
    If you provide something like ``python_version='2.5'`` then the
 
1880
    script will start with ``#!/usr/bin/env python2.5`` instead of
 
1881
    ``#!/usr/bin/env python``.  You can use this when the script must
 
1882
    be run with a particular Python version.
 
1883
    """
 
1884
    filename = __file__
 
1885
    if filename.endswith('.pyc'):
 
1886
        filename = filename[:-1]
 
1887
    f = codecs.open(filename, 'r', encoding='utf-8')
 
1888
    content = f.read()
 
1889
    f.close()
 
1890
    py_exe = 'python%s' % python_version
 
1891
    content = (('#!/usr/bin/env %s\n' % py_exe)
 
1892
               + '## WARNING: This file is generated\n'
 
1893
               + content)
 
1894
    return content.replace('##EXT' 'END##', extra_text)
 
1895
 
 
1896
##EXTEND##
 
1897
 
 
1898
def convert(s):
 
1899
    b = base64.b64decode(s.encode('ascii'))
 
1900
    return zlib.decompress(b).decode('utf-8')
 
1901
 
 
1902
##file site.py
 
1903
SITE_PY = convert("""
 
1904
eJzFPf1z2zaWv/OvwMqToeTKdOJ0eztO3RsncVrfuYm3SWdz63q0lARZrCmSJUjL6s3d337vAwAB
 
1905
kpLtTXdO04klEnh4eHhfeHgPHQwGp0Uhs7lY5fM6lULJuJwtRRFXSyUWeSmqZVLOD4q4rDbwdHYb
 
1906
30glqlyojYqwVRQE+1/4CfbFp2WiDArwLa6rfBVXySxO041IVkVeVnIu5nWZZDciyZIqidPkd2iR
 
1907
Z5HY/3IMgvNMwMzTRJbiTpYK4CqRL8TlplrmmRjWBc75RfTn+OVoLNSsTIoKGpQaZ6DIMq6CTMo5
 
1908
oAktawWkTCp5oAo5SxbJzDZc53U6F0Uaz6T4xz94atQ0DAOVr+R6KUspMkAGYEqAVSAe8DUpxSyf
 
1909
y0iI13IW4wD8vCFWwNDGuGYKyZjlIs2zG5hTJmdSqbjciOG0rggQoSzmOeCUAAZVkqbBOi9v1QiW
 
1910
lNZjDY9EzOzhT4bZA+aJ43c5B3D8kAU/Z8n9mGED9yC4aslsU8pFci9iBAs/5b2cTfSzYbIQ82Sx
 
1911
ABpk1QibBIyAEmkyPSxoOb7VK/TdIWFluTKGMSSizI35JfWIgvNKxKkCtq0LpJEizN/KaRJnQI3s
 
1912
DoYDiEDSoG+ceaIqOw7NTuQAoMR1rEBKVkoMV3GSAbP+GM8I7b8l2TxfqxFRAFZLiV9rVbnzH/YQ
 
1913
AFo7BBgHuFhmNessTW5luhkBAp8A+1KqOq1QIOZJKWdVXiZSEQBAbSPkPSA9FnEpNQmZM43cjon+
 
1914
RJMkw4VFAUOBx5dIkkVyU5ckYWKRAOcCV7z78JN4e/b6/PS95jEDjGX2ZgU4AxRaaAcnGEAc1qo8
 
1915
THMQ6Ci4wD8ins9RyG5wfMCraXD44EoHQ5h7EbX7OAsOZNeLq4eBOVagTGisgPr9N3QZqyXQ538e
 
1916
WO8gON1GFZo4f1svc5DJLF5JsYyZv5Azgm81nO+iolq+Am5QCKcCUilcHEQwQXhAEpdmwzyTogAW
 
1917
S5NMjgKg0JTa+qsIrPA+zw5orVucABDKIIOXzrMRjZhJmGgX1ivUF6bxhmammwR2nVd5SYoD+D+b
 
1918
kS5K4+yWcFTEUPxtKm+SLEOEkBeCcC+kgdVtApw4j8QFtSK9YBqJkLUXt0SRqIGXkOmAJ+V9vCpS
 
1919
OWbxRd26W43QYLISZq1T5jhoWZF6pVVrptrLe0fR5xbXEZrVspQAvJ56QrfI87GYgs4mbIp4xeJV
 
1920
rXPinKBHnqgT8gS1hL74HSh6qlS9kvYl8gpoFmKoYJGnab4Gkh0HgRB72MgYZZ854S28g38BLv6b
 
1921
ymq2DAJnJAtYg0Lkt4FCIGASZKa5WiPhcZtm5baSSTLWFHk5lyUN9ThiHzLij2yMcw3e55U2ajxd
 
1922
XOV8lVSokqbaZCZs8bKwYv34iucN0wDLrYhmpmlDpxVOLy2W8VQal2QqFygJepFe2WWHMYOeMckW
 
1923
V2LFVgbeAVlkwhakX7Gg0llUkpwAgMHCF2dJUafUSCGDiRgGWhUEfxWjSc+1swTszWY5QIXE5nsG
 
1924
9gdw+x3EaL1MgD4zgAAaBrUULN80qUp0EBp9FPhG3/Tn8YFTzxfaNvGQizhJtZWPs+CcHp6VJYnv
 
1925
TBbYa6yJoWCGWYWu3U0GdEQxHwwGQWDcoY0yX3MVVOXmGFhBmHEmk2mdoOGbTNDU6x8q4FGEM7DX
 
1926
zbaz8EBDmE7vgUpOl0WZr/C1ndtHUCYwFvYI9sQlaRnJDrLHia+QfK5KL0xTtN0OOwvUQ8HlT2fv
 
1927
zj+ffRQn4qpRaeO2PruGMc+yGNiaLAIwVWvYRpdBS1R8Ceo+8Q7MOzEF2DPqTeIr46oG3gXUP5U1
 
1928
vYZpzLyXwdn709cXZ5OfP579NPl4/ukMEAQ7I4M9mjKaxxocRhWBcABXzlWk7WvQ6UEPXp9+tA+C
 
1929
SaImxabYwAMwlMDC5RDmOxYhPpxoGzxJskUejqjxr+yEn7Ba0R7X1fHX1+LkRIS/xndxGIDX0zTl
 
1930
RfyRBODTppDQtYI/w1yNgmAuFyAstxJFarhPnuyIOwARoWWuLeuveZKZ98xH7hAk8UPqAThMJrM0
 
1931
VgobTyYhkJY69HygQ8TuMMrJEDoWG7frSKOCn1LCUmTYZYz/9KAYT6kfosEoul1MIxCw1SxWklvR
 
1932
9KHfZIJaZjIZ6gFB/IjHwUVixREK0wS1TJmAJ0q8glpnqvIUfyJ8lFsSGdwMoV7DRdKbneguTmup
 
1933
hs6kgIjDYYuMqBoTRRwETsUQbGezdKNRm5qGZ6AZkC/NQe+VLcrhZw88FFAwZtuFWzPeLTHNENP/
 
1934
4L0B4QBOYogKWqkWFNZn4vLsUrx8fnSADgjsEueWOl5ztKlJVkv7cAGrdSMrB2HuFY5JGEYuXRao
 
1935
GfHp8W6Yq8iuTJcVFnqJS7nK7+QcsEUGdlZZ/ERvYC8N85jFsIqgicmCs9Iznl6MO0eePUgLWnug
 
1936
3oqgmPU3S7/H23eZKVAdvBUmUut9OhuvoszvEnQPphv9EqwbqDe0ccYVCZyF85gMjRhoCPBbM6TU
 
1937
WoagwMqaXUzCG0Gihp83qjAicBeoW6/p622Wr7MJ711PUE0OR5Z1UbA082KDZgn2xDuwG4BkDlux
 
1938
hmgMBZx0gbJ1AMjD9GG6QFnaDQAgMM2KNlgOLLM5oynyPg+HRRijV4KEt5Ro4e/MELQ5MsRwINHb
 
1939
yD4wWgIhweSsgrOqQTMZypppBgM7JPG57iLiTaMPoEXFCAzdUEPjRoZ+V8egnMWFq5ScfmhDP3/+
 
1940
zGyjlhQRQcSmOGk0+gsyb1GxAVOYgE4wPhTHV4gN1uCOAphaadYUBx9FXrD/BOt5qWUbLDfsx6qq
 
1941
OD48XK/XkY4H5OXNoVoc/vkv33zzl+esE+dz4h+YjiMtOjgWHdI79EGjb40F+s6sXIsfk8znRoI1
 
1942
lORHkfOI+H1fJ/NcHB+MrP5ELm4MK/5rnA9QIBMzKFMZaDtoMHqmDp5FL9VAPBNDt+1wxJ6ENqnW
 
1943
ivlWF3pUOdhu8DRmeZ1VoaNIlfgKrBvsqedyWt+EdnDPRpofMFWU06HlgYMX14iBzxmGr4wpnqCW
 
1944
ILZAi++Q/idmm5j8Ga0hkLxoojr73U2/FjPEnT9e3q136AiNmWGikDtQIvwmjxZA27grOfjRzija
 
1945
PccZNR/PEBhLHxjm1a7gEAWHcMG1GLtS53A1+qggTWtWzaBgXNUIChrcuilTW4MjGxkiSPRuzPac
 
1946
F1a3ADq1Yn1mR29WAVq443SsXZsVHE8IeeBEvKAnEpza486757y0dZpSCKbFox5VGLC30Ginc+DL
 
1947
oQEwFoPy5wG3NBuLD61F4TXoAZZz1AYZbNFhJnzj+oCDvUEPO3Ws/rbeTOM+ELhIQ44ePQo6oXzC
 
1948
I5QKpKkY+j23sbglbnewnRaHmMosE4m02iJcbeXRK1Q7DdMiyVD3OosUzdIcvGKrFYmRmve+s0A7
 
1949
F3zcZ8y0BGoyNORwGp2Qt+cJYKjbYcDrpsbQgBs5QYxWiSLrhmRawj/gVlBEgsJHQEuCZsE8Vsr8
 
1950
if0BMmfnq79sYQ9LaGQIt+k2N6RjMTQc835PIBl1/ASkIAMSdoWRXEdWBylwmLNAnnDDa7lVuglG
 
1951
pEDOHAtCagZwp5feBgefRHhmQRKKkO8rJQvxlRjA8rVF9XG6+w/lUhM2GDoNyFXQ8YYTNxbhxCFO
 
1952
WnEJn6H9iASdbhQ5cPAUXB43NO+yuWFaGyYBZ91X3BYp0MgUORmMXFSvDWHc8O+fTpwWDbHMIIah
 
1953
vIG8Qxgz0iiwy61Bw4IbMN6at8fSj92IBfYdhrk6kqt72P+FZaJmuQpxg9uJXbgfzRVd2lhsL5Lp
 
1954
AP54CzAYXXuQZKrjFxhl+ScGCT3oYR90b7IYFpnH5TrJQlJgmn4n/tJ08LCk9Izc4UfaTh3CRDFG
 
1955
efiuBAGhw8pDECfUBLArl6HSbn8X7M4pDixc7j7w3Oar45fXXeKOt0V47Kd/qc7uqzJWuFopLxoL
 
1956
Ba5W14Cj0oXJxdlGHzfq42jcJpS5gl2k+PDxs0BCcCR2HW+eNvWG4RGbB+fkfQzqoNceJFdrdsQu
 
1957
gAhqRWSUw/DpHPl4ZJ86uR0TewKQJzHMjkUxkDSf/DNwdi0UjHEw32QYR2urDPzA62++nvRERl0k
 
1958
v/l68MAoLWL0if2w5QnakSkNQPRO23QpZZySr+F0oqhi1vCObVOMWKHT/k8z2XWP06nxonhmfK+S
 
1959
36X4Thzt77886m+LHwMP4+ES3IXn44aC3Vnjx/estsLTJmsHsM7G1Xz2aAqwzc+nv8JmWen42l2c
 
1960
pHQoAGQ4OEA9a/b5HLroVyQepJ26xiFB31ZMXT0Hxgg5sDDqTkf7Zacm9tyzITafIlZdVPZ0AkBz
 
1961
fuUd6rtnl12oetkNDz/nk4ajHi3lzbjPr/gSDYufP0QZWWAeDQZ9ZN/Kjv8fs3z+r5nkI6dijp3/
 
1962
QMP4REB/1EzYjjA0bUd8WP3L7ppgA+wRlmqLB7rDQ+wOzQeNC+PnsUpSYh91175YU64BhVnx0Aig
 
1963
zNkF7IGDy6hPrN/UZcnnzqQCC1ke4FnqWGCalXECKXurC+bwvawQE9tsRmFrJykn71MjoQ5E25mE
 
1964
zRaiX86WuQlfyewuKaEvKNxh+MOHH8/CfhOCIV3o9Hgr8ngXAuE+gWlDTZzwKX2YQk/p8s9LVXsX
 
1965
4xPUHOeb4LAmW6998GPCJqTQvwYPBIe8s1s+I8fN+mwpZ7cTSef+yKbY1YmPv8HXiIlNB/CTt1S8
 
1966
oAw0mMksrZFW7INj6uCizmZ0VFJJcLV0ni/m/dBpPkcCF2l8I4bUeY5RKM2NFKi6i0vtiBZljpml
 
1967
ok7mhzfJXMjf6jjFHb5cLAAXPMfSryIenoJR4i0nJHDGoZKzukyqDZAgVrk+BqTcBafhdMMTHXpI
 
1968
8okPExCzGY7FR5w2vmfCzQ25TJzAP/zASeIWHDuYc1rkLnoO77N8gqNOKEF3zEh1j+jpcdAeIQcA
 
1969
AwAK8x+MdBDPfyPplXvWSGvuEhW1pEdKN+iQkzOGUIYjDHrwb/rpM6LLW1uwvNmO5c1uLG/aWN70
 
1970
YnnjY3mzG0tXJHBhbfzKSEJfDKt9wtGbLOOGn3iYs3i25HaYuIkJmgBRFGavbWSK85e9IBcf9REQ
 
1971
UtvO2TM9bJJfEs4ILXOOhmuQyP14nqX39Sbz3OlMqTS6M0/FuLPbEoD8vodRRHleU+rO8jaPqzjy
 
1972
5OImzacgthbdcQNgLNq5QBw2ze4mUw70tizV4PK/Pv3w4T02R1ADk+lA3XAR0bDgVIb7cXmjutLU
 
1973
7AMLYEdq6efkUDcNcO+RQTYeZY//eUvJHsg4Yk3JCrkowAOglCzbzE1cCsPWc53hpJ8zk/O504kY
 
1974
ZNWgmdQWIp1eXr49/XQ6oOjf4H8HrsAY2vrS4eJjWtgGXf/NbW4pjn1AqHWYqzF+7pw8Wjcc8bCN
 
1975
NWA7PnzrwdFjDHZvxMCf5b+UUrAkQKhIx4GfQqhH74G+aJvQoY9hxE7mnnvIxs6KfefInuOiOKLf
 
1976
dwLRHsA/98Q9xgQIoF2oodkZNJupltK35nUHRR2gj/T1vngL1t56tXcyPkXtJHocQIeyttl29887
 
1977
smGjp2T1+uz78/cX568vTz/94LiA6Mp9+Hh4JM5+/CwoVQQNGPtEMWZJVJiUBIbFrVIS8xz+qzHy
 
1978
M68rjhdDr7cXF/rQZoV1Kpi4jDYnguec0WShcfiMA9L2oU5FQoxSvUFyCoIoc4cKhnC/tOJiFJXr
 
1979
5GaqM5qis1rrrZcu9DIFYXTEHYH0QWOXFAyCs83gFaWgV2ZXWPJhoC6S6kFK22ibI5JSeLCTOeAc
 
1980
hZmDFi9mSp3hSdNZK/qr0MU1vI5UkSawk3sVWlnS3TBTpmEc/dCedTNefRrQ6Q4j64Y8661YoNV6
 
1981
FfLcdP9Rw2i/1YBhw2BvYd6ZpEwRSp/GPDcRYiM+1AnlPXy1S6/XQMGC4ZlfhYtomC6B2cewuRbL
 
1982
BDYQwJNLsL64TwAIrZXwzwaOneiAzDFRI3yzmh/8NdQE8Vv/8ktP86pMD/4uCtgFCc4qCnuI6TZ+
 
1983
CxufSEbi7MO7UcjIUZau+GuNuf3gkFAA1JF2SmXiw/TJUMl0oVNNfH2AL7SfQK9b3UtZlLp7v2sc
 
1984
ogQ8U0PyGp4pQ78QM78s7DFOZdQCjWULFjMs/3MzEsxnT3xcyjTVyernby/OwHfESgqUID6CO4Ph
 
1985
OF6Cp+k6D4/LE1ug8KwdXpfIxiW6sJRvMY+8Zr1BaxQ56u2laNh1osBwt1cnClzGiXLRHuK0GZap
 
1986
BYiQlWEtzLIya7faIIXdNkRxlBlmicllSbmsPk8AL9PTmLdEsFfCOg0TgecD5SSrTPJimsxAj4LK
 
1987
BYU6BiFB4mIxInFennEMPC+VqWGCh8WmTG6WFZ5zQOeI6iew+Y+nny/O31NNwdHLxuvuYc4x7QTG
 
1988
nE9ygtmCGO2AL24GIHLVZNLHs/oVwkDtA3/arzhR5YQH6PTjwCL+ab/iIrITZyfIMwAFVRdt8cAN
 
1989
gNOtT24aWWBc7T4YP242YIOZD4ZikVizonM+3Pl1OdG2bJkSivuYl084wFkUNjtNd3az09ofPcdF
 
1990
gSde82F/I3jbJ1vmM4Wut5032/Lg3E9HCrGeFTDqtvbHMIlinaZ6Og6zbeMW2tZqG/tL5sRKnXaz
 
1991
DEUZiDh0O49cJutXwro5c6CXUd0BJr7V6BpJ7FXlg1+ygfYwPEwssTv7FNORKlrICGAkQ+rCnRp8
 
1992
KLQIoEAoEXjoSO54tH/kzdGxBg/PUesusI0/gCLUablU7pGXwInw5Td2HPkVoYV69FiEjqeSySy3
 
1993
KWP4WS/Rq3zhz7FXBiiIiWJXxtmNHDKssYH5lU/sLSFY0rYeqa+S6z7DIs7BOb3fwuFdueg/ODGo
 
1994
tRih0+5WbtrqyCcPNuitCtlJMB98Ga9B9xd1NeSV3HIO3VsItx3qwxAxERGa6nP4YYjhmN/CLevT
 
1995
AO6lhoaFHt5vW05heW2MI2vtY6vAKbQvtAc7K2FrVik6lnEqC40var2AxuCeNCZ/YJ/qnCH7u6dk
 
1996
zIkJWaA8uAvSm9tAN2iFEwZcucRlnwllxjeFNfrdXN7JFIwGGNkhFj78agsfRpENp/SmhH0xdpeb
 
1997
y00/bvSmwezYVGagZ6YKWL8ok9UhotMb8dmFWYMMLvUveksSZ7fkJb/52/lYvHn/E/z7Wn4AU4qV
 
1998
i2Pxd0BDvMlL2F9y6S3diYBFHRVvHPNaYXkjQaOjCr4+At22S4/OeCyiq038MhOrKQUm2JYrvrME
 
1999
UOQJUjl64yeYGgr4bYq8Wt6o8RT7FmWgXyINtte9YK3IoW4ZLatVivbCiZI0q3k1uDh/c/b+41lU
 
2000
3SOHm58DJ4ri52bhdPQZcYnnYWNhn8xqfHLtOM4/yLTo8Zv1ptPU0OCmU4SwLynsRpPvw4jt5iIu
 
2001
MXIgis08n0XYEliey/aqNTjSI2d/+aCh96wswhqO9Cla483jY6CG+KWtiAbQkProOVFPQiieYv0Y
 
2002
P44G/aZ4LCi0DX/2b9dzNzKuC4Fogm1Mm1kP/e5WFy6Zzhqe5STC68Qug6kNTZNYraYzt2bwQyb0
 
2003
dSag5eicQy7iOq2EzEByaZNP90qApnfL/FhCmFXYnFHtG4Vp0nW8UU4SUqzEAEcdUGk8HshQxBD2
 
2004
4D/Gt2wPsP5Q1FzIDNAJUdo/5U5XVc+WLMG8JSLq9SQerJPspZvPoynMg/IOedY4sjBPdBsZoxtZ
 
2005
6fnzg+Ho6kWT6UBR6ZlX5DsrwOq5bLIHqrPY398fiH9/2PthVKI0z2/BLQPYvV7LBb3eYrn15Oxq
 
2006
dT178yYCfpwt5RU8uKbouX1eZxSa3NGVFkTavwZGiGsTWmY07Vt2mYN2JR80cws+sNKW4+csoUuL
 
2007
MLQkUdnqu58w7GSkiVgSFEMYq1mShBymgPXY5DXW52GYUfOLvAeOTxDMGN/iCRlvtZfoYVIureUe
 
2008
i86JGBDgAeWW8WhU4EwVaoDn5HKj0ZycZ0nVlJY8dw9PdSF/Ze8i0nwl4jVKhplHixhOqafHqo2H
 
2009
ne9kUW/Hks+u3IBja5b8+iHcgbVB0vLFwmAKD80izXJZzow5xRVLZknlgDHtEA53piuYyPpEQQ9K
 
2010
A1DvZBXmVqLt2z/ZdXEx/UDnyAdmJJ0+VNlrrTg4FGetBMMoasanMJQlpOVb82UEo7ynsLb2BLyx
 
2011
xJ90UBXrCrzbN9wSxzrTt2pw/kZz1QbAoZucrIK07OjpCOf6MAufmXbLXRj4oS064XaXlFUdpxN9
 
2012
ecMEHbaJPVjXeNrSuJ1Fn9ZbASc/Bw/4QGfxg+NgsmyQnpiEa6o0TsRChygit9rML8wqcvTyjthX
 
2013
Ap8CKTOfmBppE0S6suxqi091zqaj4hHUV6agaYtnbippOkUoLuZjynMyJRBbvGiDS/tOC/HdiRi+
 
2014
GIs/tzZCs2KDtzIBys/m0bN56Ptk1PXq+KixM92NZwvCViAvr5883TSZ0vTCvvTzh/vqpEPcAK5A
 
2015
dhaJnB88U4gd4/ylUDWUZl7bOYVmjNXpezbrSRdmN+UqVJU2Ba9+3SgUR7UY/9MOYiq+tR7g4lgU
 
2016
WrZAtqDfJJ60kv/spWuYGKjR81cWPZdJ3+EUfsOLU+C9Jqjr6Gw9tNQZ9hZsz55cl1HyEVTTsOH4
 
2017
Bz2qJ4lSO0e80wqPJxuJc1n/CTwc0iUzxDRftY6F/5XMw0n72w4XO1h+8/UuPF0F01sx0bOgj61i
 
2018
4EVvly40C28+/UEvj2X6un6R6DhQGiEC/8/c4Uie2zFmBvNVL7nNEF7hLYl06otWJpWuJ8K7U74O
 
2019
C10D2o5TohasCjgn9QIPae/o0sdTRQlleBPM10cvxqYAlwHpCbyMXn6l70akbuaOAd9tHevtELzU
 
2020
/Y6if3OAJZXf277qbBBoWidu6uKYyu6dwUKKTI2iiaVDY0MerrFo1iwWeJlgQ0x2V+09G+/AgZiC
 
2021
62BuBc3BB4I9XtSHrqs7GjnepuS2ifLWOKL9bBOiR+SAuDoVsd4ld9v06C4d+mRZ0L36jQluy5H1
 
2022
lzG/QfeqLo5t2MqYFzxWHLqpkvipbnvru9i0oJ2tbsNd0+f+u+auWwR25iZToDN3v47TpYHuu92g
 
2023
9tGAQwaaEI+qP2iUf79dcU3CWCeo9Ie/9QfJ73bCmW6xMA+BMekwGEwn9tTYGw9gFc/c75htdcBX
 
2024
Fbtlu71+R2vaHfPR5vjHOA2cWYLPbSU/pQvNNQfyHoTunptwAupE3tyoSYz3Hk5o40rJUp0didkK
 
2025
vaNr62SsNmYHg5cDAQjDTTqt1c1cB8YAZcn3L3OukXMLjKChKSPXSfFVyZxtgt4uAbiIo5DU30S5
 
2026
OUd3kEoMHqu6LErYYQ70Lb2cBNOXN9wANUGxVaxuDeqmx1hf2kqalTKvTKkvxz5ZzXrUAUKwJe/Y
 
2027
h8nEvgN+ed5caZCMLUPIrF7JMq6a63z8I/cEvIhmBCrwxgV2wl6NZLY4xUUssfzhIIWBJ/v9K71h
 
2028
8zasO+4xGFmt93i2oh46nPqUKxIcq2S4Obm31/m510jN6fJn12G0zRrus1cYwVKYu+lIV+o4FL/V
 
2029
92XxLawcJUeX0+EjkHu3vNFP9bZqjR1ei4bzzFUM3QuSsEKfrHTfvYcdLujecNjatNrxfb1hmaXj
 
2030
am5pbKmo3fRexdOMNmqiM5iV+UB0xs+8f2J0xoP/yOiMvqUSDI7GR+uD3lz8B8I4rCbcKx8bRoA+
 
2031
EyASnhK3Lgw0JnPoZrYXuUruB/bKZdaZTrmcMRPIkd27wAgEX+2o3DRg7+q1XdEZX7ro8fcXH16f
 
2032
XhAtJpenb/7z9HvKfMKjiJbNenT4KssPmNoHXo61G8rS2Sp9gzfY9tyhyoVCGkLnfeegvwdCf1FY
 
2033
34K2FZn7eluHTnFNtxMgvnvaLajbVHYv5I5/pgs53ByVVjJ0oJ9y5qr55Rz/m0fmFIzFoTnlMu+b
 
2034
gwkto5247baFc3JIu+pE+6361s0tMeWRzWSmFcDzCOQvexxhylJs0Jsdlfb/CIPSr7Gkz9xYA1I4
 
2035
k87NiXRpIoOq/P/jRgnKLsZNHjuMY3t7NbXjoxdlr2XHc9WZjAxBvJq6QXd+rrDPZbqFCkHACk/f
 
2036
C8iIGP2nDyvt0f4zJa4OqHr3AJXNtf2Fa6ad3L8leIBf2fu1FGcB8REmNF7UqXsob/t0OpDzRyc9
 
2037
+cIpFwHNdwh0bsRTAXujz8QKcboRIWwg9eEzZqASHfXleA7yaDcd7A2tnouDbbWdbm2jEC+2N5y3
 
2038
yid1jyPuoR7ooWpTQedYYEyF3Fa0Kb4jyHxUKOhCLc/5wPNpvf+Hr3dXL45t4B75HV87ioRStgaO
 
2039
Yb9yUh53XuLodCdmKceUE4d7NqfkV7e4dqCyT7Btj9Op+9iyDzI5BAxp4L3vj52ZHt7l9IM2ppb1
 
2040
jmFKYvhMjWhaTqWMxt0+GXWn26itLhCu+nkEkI4KBFgIpqMbnSzMDadSD5/rXeG0putv3dOb0JEK
 
2041
ysjyOYJ7GN+vwa/dnap1H9WdUTT9uUGbA/WSg3Cz78CtRl5IZLtJaE+94YMtLgAXPvf3f/GI/t1c
 
2042
Qdv9aJdfbVu97C22Y18W00sx66ZFIvM4AiMDenNI2hprEoyg410vDR1dhmrmhnyBjh+lrOLl1rTB
 
2043
IGd2oj0AaxSC/wPOBKoy
 
2044
""")
 
2045
 
 
2046
##file ez_setup.py
 
2047
EZ_SETUP_PY = convert("""
 
2048
eJzNWmmP20YS/a5fwSgYSIJlDu9DhrzIJg5gIMgGuYCFPavpc8SYIhWS8li7yH/f181DJDWcJIt8
 
2049
WAbOzJDN6qpXVa+qWvr8s+O52ufZbD6f/z3Pq7IqyNEoRXU6VnmelkaSlRVJU1IlWDR7K41zfjIe
 
2050
SVYZVW6cSjFcq54WxpGwD+RBLMr6oXk8r41fTmWFBSw9cWFU+6ScySQV6pVqDyHkIAyeFIJVeXE2
 
2051
HpNqbyTV2iAZNwjn+gW1oVpb5Ucjl/VOrfzNZjYzcMkiPxji3zt930gOx7yolJa7i5Z63fDWcnVl
 
2052
WSF+PUEdgxjlUbBEJsz4KIoSIKi9L6+u1e9YxfPHLM0Jnx2SosiLtZEXGh2SGSStRJGRSnSLLpau
 
2053
9aYMq3hulLlBz0Z5Oh7Tc5I9zJSx5Hgs8mORqNfzo3KCxuH+fmzB/b05m/2oYNK4Mr2xkiiM4oTf
 
2054
S2UKK5KjNq/xqtby+FAQ3vejqYJh1oBXnsvZV2++/uKnb37c/fzm+x/e/uNbY2vMLTNgtj3vHv30
 
2055
/TcKV/VoX1XHze3t8XxMzDq4zLx4uG2Cory9KW/xX7fb7dy4UbuYDb7vNu7dbHbg/o6TikDgf7TH
 
2056
Fpc3XmJzar88nh3TNcXDw2JjLKLIcRiRsWU7vsUjL6JxHNBQOj4LRMDIYv2MFK+VQsOYRMSzXOH5
 
2057
liMpjXwhXGnHnh26PqMTUpyhLn7gh6Ef84gEPJLM86zQIjG3Qid0eBw/L6XTxYMBJOJ2EHOHiiCw
 
2058
JXEdEgjfEZ6MnCmL3KEulLo2syQL3TgmgeuHcRz6jPBY+sQK7OhZKZ0ubkQihrs8EIw7juOF0g5j
 
2059
GXISBLEkbEKKN9QlcCzPJ44nuCdsQVkYSmG5MSGeCGQo/GelXHBh1CF25EOPiBMmJXW4DX0sl7rU
 
2060
Zt7TUtgoXqgrHer7bswD+DWUoUd4GNsOBJHYiiYsYuN4gT1ccCAZhNzhjpTC9iwrdgNPOsSb8DSz
 
2061
raEyDHA4hPrcJZbjB54fwD/MdiPLIqEVW8+L6bTxQ44X4aOYRlYYOsyPie+SyHNd4nM+iUwtxm/F
 
2062
cOEFhEXAMg5ZFPt+6AhfRD7CUdCIhc+LCTptIoFMIkJaAQBymAg824M0B0YC8Alvg1SG2DiUCIIc
 
2063
tl2O95FGTiRCSnzqE2jExfNiLp7igRvLmFoQ5jHP8eLQcj0umCOYxZxJT9lDbAKPxZ50qQxJiCh0
 
2064
BYtcYVEH7g69mDrPi+mwoZLEjm1ZlMNNHDkBSYJzF44PPCsKJsSMeEZaVuBRGRDi0JBbUAvIeghs
 
2065
K7JD5kw5asQzgR3YsSMEc33phQJeswPGA2I7kOqEU1JGPCPtCAQF8uUSoUIcP2YxpEibhzSM5ARb
 
2066
sRHPCEvw0Asih8VxRCUNgXRkIXot+Dy0p5ztDp1EqJB2IDmHYb7v217k2SwEf/E4igN/SsqIrahF
 
2067
Y9u1CSPUdSyAAZ4LpecxH0QR2vJZKZ1FCBKJPQPuSSpdZBSVsRcwC1CB9cRUwHhDiyLF1iB+12Gc
 
2068
xix0KJMe6MsJpBMROcVW/tAiIWLJIwvqICERsdIV4HQ/BGHwyA6mPO0PLSISXMUlqoodWrYQADdE
 
2069
cfIpQ8EjwRTL+CMfRdyVAQjBY4yQKLQ9BA53Q8oYd7nPJ6QEQ4uQMBGqfGTbASpRFHmhAxGomL4X
 
2070
I7WniDMYVTfmB0T6IQW+6B6QDYEFQzzPRYL5ZIobgqFF1JERCX0HxR60S10UaQuu5sKXaCV8d0JK
 
2071
OKI7Cz6SMeHMJYHtC9+2faQhWooIFDgZL+GoEpBIxr6HKsDB5ZakQcikLR24AY+cqQwIhxZ5qLEE
 
2072
fCvRMiABPdezbVtyEbk2/oVTukSjbshSvZATA5GYo36oEASBR66lGivreSmdRYwSNwI3oOfwIpdZ
 
2073
KmYRbQCbobJMloFoaJEdOnYIkoOjY85s3/Jji/gRdQXyPPanPB0PLYLuzLPQzNgKYerFgfCYpMKK
 
2074
YCuzpjwdj5gBQYbGDrXVjSIegJ2IEFYA8mKB6031d42UziIp4FpX+MQOqe0wuIn5nk1D1F5UfjFV
 
2075
SeJhPWIEaWNLxZrEERzEZMcuKltI/dhBjwMpv816EwHGm3JWFedNPXDtSblPE9rOW+jdZ+ITExg1
 
2076
3uo7b9RI1KzFw/66GRfS2H0kaYJuX+xwawmddhnmwbWhBoDVRhuQSKO9r2bGdjyoH6qLJ5gtKowL
 
2077
SoR+0dyLT/VdzHftMshpVn627aS8a0XfXeSpC3MXpsHXr9V0UlZcFJjrloMV6porkxoLmvnwBlMY
 
2078
wRjGPzOM5Xd5WSY07Y1/GOnw9+Fvq/mVsJvOzMGj1eAvpY/4lFRLp75fwLlFpuGqAR0Nh3pRM15t
 
2079
R8PculNrR0kptr2Bbo1JcYdRdZuXJjsV+K0Opu4FLlJy3tr+rHESxsYvTlV+AA4M0+UZo2jGbzuz
 
2080
eycFaq4/kA/wJYbnj4CKKIAAnjLtSKp9Pc7fN0rfG+U+P6VcTbOkxrovrZ3Ms9OBisKo9qQyMAh3
 
2081
grUsNQFnCl1DYurtlDplXL8ijPsBEPeGGmmXj/uE7dvdBbRWRxO1PGNxu1iZULJG6V5tqeT0jjH2
 
2082
ohgckDwmmLnpJRIEXyMi6wDXKmc58EgLQfj5oj72eCt76mnY9XbN2YQWUzVaamlUaFUaQPSJBcsz
 
2083
XtbYtGocCQJFgQpEVFolVQLXZQ+984za4439eSb0eUJ9NsJrvQBqnioMnzwfUVo2hw2iEabPcor8
 
2084
hJ1ErUqdZ8Q4iLIkD6I+4Lgk3f29jpeCJKUwfjiXlTi8+aTwympHZAapcK8+2SBUUYsyXoWgMqY+
 
2085
9TDbCNU/H0m5q1kI9m+NxfHDw64QZX4qmCgXimHU9oecn1JRqlOSHoGOH9c5gazjiIMGtuXqwiQq
 
2086
5LaXpOnlZYPYKAXbtFuPEu3CAW2SmEBWFNXSWqtNeiTXEHW306v+6Q5tj/l2jWN2mpi3SkbtIBD7
 
2087
WNYAIP3wCYbvXmoJqQ9I8+h6h4Foswmu5fyi8evt/EUD1epVI7uvwlDAz/XKL/NMpgmrAM2mz/59
 
2088
z/9Ztp//uL9E/0S8L19vb8pVl8ttDuujzPfZkPDnjGSLSqVUlyLgDHV8p3OkOa5T2XLKMoSyaXyX
 
2089
CkRIu/xKnsohlcogIAFbWg1lUpQA4lSqdFhAwrl1vfHyp57yC3Mk7332Plt+eSoKSAOd1wJuilHd
 
2090
WqFqXWJZmKR4KN9Zd8/XrCd991WCwEzoSdXRb/Pq6xzs3AsUUpazJtvS4ZvrfkK+G6XznXrlc4Ci
 
2091
CT//MKiZ/RCti+dTmfpXV1CVz8i4Qen86ok6qTOTXHjeSHNWdxmaEWsbkqo+9NVdw/9p3axZVx3r
 
2092
t3Xz98qmuqd2va6ZNZXfX8rgRKnL6wLX1jdVJ1h1IunFiKZuDGtD+6lBgfJBHUTWHvGY1kHbtqBb
 
2093
o8dPL29KtNM3peqm5/1cGJ1q14EPuf1yoDAzXgy7vpJ8FNB+iy675vlf8iRbtlWhXVqLKwumxOnW
 
2094
91sU6LZbVuzTvo68K6tyWYtdbVQyfPExT1QAHQVRJbBVp+ySbUDR6tKhyCFIoVG2KKX5w2CV6q+V
 
2095
X4bvqgsrzUdSZEuF88u/7qo/9Gi4siHn8qkov9EhoT4MWYqPIlN/wJwjlJ3tRXpUrdzbOtp67UQX
 
2096
Kug3VPyrj2uWCooZWH5tgKpm6tYB6ZwJAIlXkIeqmQXpikdFsQQTalnqt/u0rknZnDVbgo2btuWy
 
2097
I1TmbTSbs9kSjCg2CmEt5kDYXnVQPBd1rdnDvVCiesyLD82ma+NYF4ycVqT5qE0xhWaJG5CpYhEg
 
2098
wHQjrhdA8iUTm8wpRFOA+gaYq7/SiwiK9VXI9Ej3qkfSUbZW2XT1GpoEHaxVoobFphdKhTi+qn8s
 
2099
R+3UMDpbGtalrpzrLUalTKdcww8mfuZHkS2vln1ufI8+/vaxSCqQD3wMfHUHDQ7/sFaf9j0q76kO
 
2100
gBUqDUGNLC+Kkw6OVIyEab/3w0M11pXQ61tObK/mk7OpuRoGmGrGWK6GGtcsoq2puWI9f6RzwIkH
 
2101
prajnqy7lzDfqTlvM6YAbLDRu7A0L8VydUURZbXRQvvPm2rWkhYUTNUvLW3N/sil6vcBkb5ED/Jx
 
2102
PVWxLzX37XOfg+oa+wbdUrOqLRBP9cejz5efa47reaDj6iuJlzXPzwx6+Lauu6zhZDAYDLTPVGr0
 
2103
xgGWHw4w1By0he0JDWlmrPZqfKQhTlELNM6rF+oA5W6lw/RRLAod1sJQZfx3Q0VZqnAe1Sql9nUN
 
2104
waJThqHuw7IzS6TlsMHvmbbbNWjtdsYWU55lWqa9+NNd/z9B8Jpc1ahLyzwVyNWJabft41FM6l79
 
2105
qkcvxCH/qPlWe6L+GoMealE5KlBv+ju8O2q+J7vsJql+HTYrvWGq3+1cz3d/YEbDz2ea+dEgtpmO
 
2106
9v85JJ9Ls07w70q5iuan8q5Nt7vhGK7BtlYIfFilqj8cx3SkqCdPR6ja5S8CoFNfa37BZbCldqAO
 
2107
8/kPV23RfN0yyhwk+KALUaFOdBGEaJIuAT1/Qt5i+T3aqXn7hRvzeB4OlPP6qzTX3zYxV4vmpPLY
 
2108
1ad2hCkv9PyTfmqoFKGnJK1e1ke/EPmgJsWzYuR+FBfN/KN6rfaouBN7AUT33JfuWv2pViwvXbUW
 
2109
0tZCXTQXBV1cnnUnx+rdu+bUWbZF9cmTZ9kVu3oErEv0u7n646bY4N8aXIHxoek064as3chE8T2U
 
2110
y9Vd97JZwuKudB7VUDGf15NCXaT7wMADGCGrdmLQXxHatnfNB1HVSavuL/uT9E53DLtdE/UdJI2M
 
2111
taFhedW0RC0Ar8bGHkiFaXALPc1SkILtl/P3Wf8rPu+z5bt//Xb3YvXbXLcnq/4Yo9/ucdETjI1C
 
2112
rr9klRpCscBn8+skbRmxVhX/f7fRgk3dei/t1R3GMA3kC/20fojRFY82d0+bv3hsYkI27VGneg+A
 
2113
GcxocdxuF7udStjdbtF9sJEqiVBT5/BrR5fD9u939h3eefkSYNWp0itfvdzpljubu6fqouaIi0y1
 
2114
qL7+C1AkCcw=
 
2115
""")
 
2116
 
 
2117
##file distribute_from_egg.py
 
2118
DISTRIBUTE_FROM_EGG_PY = convert("""
 
2119
eJw9j8tqAzEMRfcG/4MgmxQyptkGusonZBmGoGTUGYFfWPKE6dfXTkM3gqt7rh47OKP3NMF3SQFW
 
2120
LlrRU1zhybpAxoKBlIqcrNnBdRjQP3GTocYfzmNrrCPQPN9iwzpxSQfQhWBi0cL3qtRtYIG/4Mv0
 
2121
KApY5hooqrOGQ05FQTaxptF9Fnx16Rq0XofjaE1XGXVxHIWK7j8P8EY/rHndLqQ1a0pe3COFgHFy
 
2122
hLLdWkDbi/DeEpCjNb3u/zccT2Ob8gtnwVyI
 
2123
""")
 
2124
 
 
2125
##file distribute_setup.py
 
2126
DISTRIBUTE_SETUP_PY = convert("""
 
2127
eJztPF1z2ziS7/oVOLlcpHISE2fm5q5cp6nKTDyzrs0mqTjZfUhcMkRCEsf8GpC0ov31190ACICk
 
2128
ZOdm9uGqzrtjS0Sj0ejvboA5+7fq0OzKYjKdTn8qy6ZuJK9YksLfdN02gqVF3fAs400KQJPrDTuU
 
2129
LdvzomFNydpasFo0bdWUZVYDLI5KVvH4nm9FUKvBqDrM2W9t3QBAnLWJYM0urSebNEP08AWQ8FzA
 
2130
qlLETSkPbJ82O5Y2c8aLhPEkoQm4IMI2ZcXKjVrJ4L+8nEwY/GxkmTvUr2icpXlVygapXVlqCd5/
 
2131
FM4GO5Ti9xbIYpzVlYjTTRqzByFrYAbSYKfO8TNAJeW+yEqeTPJUylLOWSmJS7xgPGuELDjw1ADZ
 
2132
Hc9p0RigkpLVJVsfWN1WVXZIi+0EN82rSpaVTHF6WaEwiB93d/0d3N1Fk8lHZBfxN6aFEaNgsoXP
 
2133
NW4llmlF29PSJSqrreSJK88IlWKimVfW5lO9a5s0674duoEmzYX5vCly3sS7bkjkFdLTfefS/Qo7
 
2134
qrisxWTSCRDXqI3ksnI7mTTycGmFXKeonGr4083Vh9XN9cerifgaC9jZNT2/QgmoKR0EW7K3ZSEc
 
2135
bGYf7Ro4HIu6VpqUiA1bKdtYxXkSPuNyW8/UFPzBr4AshP1H4quI24avMzGfsX+noQ5OAjtl4aCP
 
2136
YmB4SNjYcsleTI4SfQZ2ALIByYGQE7YBISmC2Mvouz+VyDP2e1s2oGv4uM1F0QDrN7B8AapqweAR
 
2137
YqrAGwAxOZIfAMx3LwO7pCELEQrc5swf03gC+B/YPowPhx22BdPzehqwcwQcwGmY/pDe9GdLAbEO
 
2138
PugV69u+dMo6qisORhnCp/erf7y6/jhnPaaxZ67MXl/98urTm4+rv199uLl+9xbWm76Ifoi+u5h2
 
2139
Q58+vMHHu6apLp8/rw5VGilRRaXcPtc+sn5egx+LxfPkuXVbz6eTm6uPn95/fPfuzc3ql1d/vXrd
 
2140
Wyi+gIVcoPd//XV1/faXdzg+nX6Z/E00POENX/xdeatLdhG9mLwFN3vpWPikGz2vJzdtnnOwCvYV
 
2141
fiZ/KXOxqIBC+j551QLl0v28EDlPM/XkTRqLotagr4XyL4QXHwBBIMFjO5pMJqTG2hWF4BrW8Hdu
 
2142
fNMK2b4MZzNjFOIrxKiYtJXCgYKnwSavwKUCD4y/ifL7BD+DZ8dx8CPRnssiDK4sElCK8zqY68kK
 
2143
sMyS1T4BRKAPW9HE+0Rj6NwGQYEx72BO6E4lKE5EKCcXlZUozLYszErvQ+/ZmxzFWVkLDEfWQrel
 
2144
JhY33QWODgAcjNo6EFXxZhf9BvCasDk+zEC9HFo/v7idDTeisNgBy7C35Z7tS3nvcsxAO1RqoWHY
 
2145
GuK47gbZ607Zg5nrX4qy8TxaYCI8LBdo5PDxmascPQ9j17sBHYbMAZbbg0tje1nCx6SVRnXc3CZy
 
2146
6OhhEYKgBXpmloMLB6tgfF0+iP4kVM60iUsIo8Z1v/QAtL9RDzdpAauP6ZNSP4tbhdxI5o0UotM2
 
2147
bTjrNgVwsd2G8N+cdfbTlCsE+3+z+T9gNiRDir8FAymOIPqpg3BsB2GtIJS8LaeOmdHid/y9xniD
 
2148
akOPFvgNfkkH0Z+ipGp/Su+N7klRt1njqxYQooC1EzDyAIOqm5qGLQ2Sp5BTX7+jZCkMfi7bLKFZ
 
2149
xEdlrdstWqe2kQS2pJPuUOfv8y4NX615Lcy2nceJyPhBr4qM7iuJhg9s4F6c14vqcJ5E8H/k7Ghq
 
2150
Az/nzFKBaYb+AjFwU4KGjTy8uJ09nT3aaIDgbi9OiXBk/8do7f0c4ZLVukfcEQFSFonkgwcWsglf
 
2151
zJmVv87H/ULNqUrWpkw1KcOKCoIlGY6Sd68o0jte9pK2HgeWTuI2yg21gyUaQCtHmLC8+I85CGe1
 
2152
4fdi+VG2ovO9OScHULdQSe4pnScd5eu6zNCMkRcTu4SjaQCCf0OXe3terxSXBPraoLrfrsCkKI+s
 
2153
Ka1G/uZl0maixtLuS7ebwHKlDzj0094XRzTeej6AUs4dr3nTyNADBENZJU7UHy0LcLbm4HhdQEN+
 
2154
yd4H0c7BVlMdxLFCq5upovMf8RbHmecxI9J9hXBqWfLjcgp1mV5vNkJYfx8+Rp3K/1wWmyyNG39x
 
2155
AXqi6pmY/Ek4A4/SF52rV0Pu43QIhZAFRXsJxXc4gJh+JN9OG0vcNonTTgp/XJ5DEZXWJGr+ACUE
 
2156
VVdfiukQH3Z/Yl4EDSZS2tgB836HnQ1qCelOBnySbYHxJWLvMwECGsVnuh2c5aVEUmNMCw2hm1TW
 
2157
zRyME9CMTg8A8cE4Hbb45OwriEbgvxRfivDnVkpYJTsoxOxczgC5FwFEhFksZhZDZVZCS5vwpT8m
 
2158
snrEQkAHWc/oHAv/3PMUtzgFYzP1osr7YwX2t9jDk6LIMZsZ1esu24FV35bNL2VbJH/YbB8lc4zE
 
2159
QSp0ymGtYil4I/r+aoWbIwvssiyKWCcC9R8NW/QzErt0yNKOGIr017Yt2dkrhdau+QnGl5Ux1UvU
 
2160
mtWcTxvVbSx4LlTWeKdpv4OskJKzNbZQH3iWetiN6RVtvhYSTJqTLXdugXBhy5KyYmrjdL1TUAOa
 
2161
Itidx487ho2XEJxEvDOriyJRkRP7ypwFz4NZxO4UT+5wRa84AAcjpDBZZFfJmVVEEqk9Ege76XoP
 
2162
1BWOyyKh/mzFMdavxQb9DbZi46blme0S0/4aLLWayIjhX5IzeOGIhNpKqMTXFIgEtuZ1j1xmWHdN
 
2163
HHMcDZcOipdjc5vtP1eoDtiP8vLjCOu07T/RA2rpq0a89NJVFCQEQ4NFpYD8QQBLj2ThBlQnmDJG
 
2164
dLAv3e91zLWXOiu0s0vk+auHMkWtrtB0k44cm+QMonpXv3TWQ06+ns5xS77PVkRpLoWD4TP2QfDk
 
2165
OQVXhhEG8jMgna3B5O7neCqwRyXEcKh8C2hyXEoJ7oKsr4cMdktabewlxfOZRhC8UWHzg51CzBBk
 
2166
DPrAk15SpdhIRCtmzdl0v54OgHRegMjs2MBpaknAWiM5BhBgavgePOAfiXewqAtv27kkYdhLRpag
 
2167
ZWyqQXDYNbivdfk13LRFjO5Me0Eadsep6Ttnz57d72cnMmN1JGFrFD3dWMZr41pu1PNTSXMfFvNm
 
2168
KLXHEmak9iEtVQNr0Px3fype14OB/koRrgOSHj7vFnkCjg4WMB2fV+HpEJUvWCg9IbWxE37hAPDk
 
2169
nL4/77gMtfIYjfBE/6g662WGdJ9m0KgIRtO6cUhX6129NZpOZK3QO4RoCHNwGOADisYG/X9QdOPx
 
2170
fVuRv9io3FoUaksQ201IIn8J3m2lcRifgIhnrt8Adgxhl2Zpy6Iz8HI47WC4N9L2euVDuA1XvW2r
 
2171
DnbWe4TGaiAyEyChxOiwIndAFKuUzt0EWNo+GAuX2rEZ3o0ng5sxT0TKPXHEAOu57sUZ6bwTnoUb
 
2172
vo1KzXi5PvMdJhtcg10rDIXYm+iMTyHSBtG7N6+j8xrP2vAcN8Jfg/bvB0SnAhxmN9R2VBQajLoP
 
2173
jAUufg3HRjX95qGlNS8fIGEG41i5nfmwyngsdqDuwnSze5E8rbEfOQTzif9U3EMs9Jr+kHvpTThz
 
2174
jyvYBmsPzwNhRmruMTjN4nFSgGp9LB7pvyHOnbtdmWfYN1xggdB3+Gbxgb9cg/TvXbZs/BLJcsD2
 
2175
SSmLd8/63XV7DJj0lOBv5QOqgMiEOigu2wazXnQee36wJmcqnX7G5jBnzpTma+J78tTzHT5YZ64N
 
2176
B4heebDKU3kRZDBJuUM9Y85GTlF171vzc+DbLS/ADnjfQ82ZT82oKp0B5j3LRBPUDNW+8719fnZq
 
2177
pvmNmha6bbx5rwGom/x4PwI/OtwzGE7JQ8N4Z3L9XrMG6dW7rqsZYBnG9DGtBJ+qmvfAVkOs5sSR
 
2178
VnpwY28fJU6jIOjtxHfHxzxN3zkfg+tcNd9AQt2dXCMBmitOAEOQ7p5N17vujMQyHwsWwIAHZ+D+
 
2179
8xyoWJXr38Lu2HMWmYZ3BUUhVF4qsj3WaPB8myb8W+Z4LtelF5RypJ56zA2PiNtwx/QWhi6IWHV4
 
2180
ICaB0elAFT757EQVhXajOhQ7dqSPbmrrB2GBL57WhceuMMwVbd/g9nqkDDyg4eXQBY76HgV+wvP0
 
2181
ffjPKH8VyAez/NynS5A6f9klSTr1vioeUlkWaGy9/NstjrFs3UEZxioh87SuzQ02Ve6eY6fyPq0q
 
2182
oGl6YhtD+nRuNurECeB4nqbE1XSJ2XFxOXoSwYSgnxf12NnsHKlaDurHj6WZHhlOw66vM4/v7zEz
 
2183
7/m7J7mTycyvLboIbLPLMx3XIBzG96jVKX4by/WP2orKxq9+/XWBksR4BlJVn7/BVtJBNn0y6B8L
 
2184
UE8N8lZPnUB/pPAA4vP7jm/+o5OsmD3iZR7l3CmL/tNMy2GFVwJpbRmvgvSgvdhCbdMuvA5C60+q
 
2185
rXo0to6cFWrM1DteVVJs0q+hiTo20HURl8KUPiblcvtw2fNHNhnXlw4N4GfzAUJ2Ir46MRxqrYvL
 
2186
2y6ro+G5uZwoijYXkqtri24vB0HVtV+V/y0WEnarbm6obfTLBdgG4IhgVdnU2PdGPV5iUFN4RhpF
 
2187
TVlp4dDMKkubMMB1lsHs86J3XugwwTDQXUzj6h9aKaqwUFVUjB4CZ6Cc6q7lj4o/4z0tj9z6M0Ei
 
2188
d4d0fiutlkpgb1sLGdBph71ErI8vsbM82kMaW6WbPWIdSisH6tpX+JuY0yGncxZqrpGOGfDR4/pT
 
2189
PbMzthcBWFUMJIwkHU6+DSrp3ERKSqGYUguRY2B3j2yHbRv6ukeT8YsXfVcK2TDckBOOMFOGyfs6
 
2190
wizSP4v2MX5QB9KYnkR0ybxXPUlBoR7Hl+S2fZ31Up2Ph0oM+IVNU+dM69X7638lwZY6W6T2lwH1
 
2191
9FXTvY/mvrDhlkyqbTAuqDOWiEboe38Yz/GuQBcUUW+TfobdnRMu++RFZqiv3e6LJE5RppYGXTfN
 
2192
mpFVNC/o1EP5RlRP8o3pVyK2kuVDmohEvVOSbjS8+/ZK7bRGEn1lMJ/bUxfTEHXrIT+UjFE2LgWN
 
2193
DRg67xMMiNRhzdhl2aFvU/fogZYdVEfHKygvMwMbVXKs3QuHeksjm4hEkeggQvfajmyqWKj7iFZ4
 
2194
Hh1o7ce7fKNSNZM1aYBjzN+ONH2cK6vHSTqWRI2Qcjqn0iSGx1JS1Dm/W/INaenRvPREb7zHG3/e
 
2195
sDvu6kZ3tohmTQfgykPSYbTj/QvRF61fEPxReQ7phZiUV0CkcJr6GW+LeGczO/ukHzw/6BFv4xjt
 
2196
VFlK73opCOpJmJeBFFSVVizn8h5vHJSM0zExtxPW7VYXT3lyge+eBIvYv7AOiQRe/8nEQrcmFuIr
 
2197
vQ4GCfQi5wXE8CS47ZC8PIZEiriUBlK/j0MJ5+V3t5iwKArAlYwNvHRCqRl+cdv1QbBd6Cazn/03
 
2198
YG4huTLTJgYH3U0afbmpE4lzYbsW2UadGCynEdT5ucA7E/USo5U9ktKXzOkMXEOoA1a6/yBBhEpe
 
2199
+DVW16vMHWuzP3uXA709vppX7gus5PMywZf4VGTBMw4CcHsS9rDSIElBvanTB4qU1BG7ww0E3Z0Y
 
2200
fKMOkG4EETK4Yg6Eag7AR5isdxSgj1dJMM+IiBzfkKR7MsBPIplanwYPni1o+4DotD6wrWg0rnDm
 
2201
Xx7RiV9cVgf3O1R9UFvo+5CKoeqqvQHQjLeXJl0OgD7cdhmHEcsg0zADGPWzzaSrc2Al8rQQqzSI
 
2202
V6brYd3573m8M0OYR4++y1PzjUCpit6NBgsZ8QrK3STUa/hO0tC1JG5F+OskIN6lw17R99//l0qL
 
2203
4jQH+VF9BgS++M8XL5zsL9tEWvYGqdL+Ll35INAdCFYj+12aXft2m5nsv1n4cs6+d1iERobzhQwB
 
2204
w8Uc8bycjdYlcV4RTIQtCQUY2XO5Pt8QaagwjwNIRX04duoyQHQvDkujgRHedAD9RZoDJCCYYSJO
 
2205
2NTNacMgSArpkgvg6ky4M1vUXZIHZol95vW0zhn3iKTzz9EmipG4z6DBtQGScrwD4qyMNd7ZELCl
 
2206
c9UnAMY72NkJQNN8dUz2f3HlV6koTs6A+xkU3BfDYpsuVPcK+bErGoRslay3ISjhVPsWfLUQL3uJ
 
2207
3vtK7gtcoX6j2YYA+vtT9zKHfSsVvGmgX4I1MYt13ZrSvOXTFWO6PPa9o7Oy8mqaGZqKCCt+Q5/n
 
2208
pY4Y4w/HMrSp6h6YO9E1e29e3/0BQzTko0L2rlGpy+s3h7oR+RXG1gsnaXIIN07NNCi8poIL2DVr
 
2209
wbQUs3tcfo8jKpaqQyeINIVwOk61B06I6Lahfmc7ekdQhEZqV6CAIp4kK4XD1ruGYLyAWjfLwGU2
 
2210
POR092YZ1A22/hpwBQS54W2my3N7x3Unsmpp0iO0cWI2vRiu5c7CU6yfBU+h1lygW+CdxI5s76Zi
 
2211
gJlMwx+4XE4/fXgztSQaykfv6Cr6zT8LgEkN3lylwKxvoJb2+t64YusdaEHNTeamd+QK3SSyJfBH
 
2212
5xydUXHsom4L4HjiqpERP2lQzsExHrmRbDXq+tS/J0A++4rXBw1lVMr8ewZLX01V/+fkq0z+RWhj
 
2213
v95TzzCGLxmf8kbgsVK6Doi12oragasV8mG10i+8dxkwcQcm/A9nRa43
 
2214
""")
 
2215
 
 
2216
##file activate.sh
 
2217
ACTIVATE_SH = convert("""
 
2218
eJytVVFvokAQfudXTLEPtTlLeo9tvMSmJpq02hSvl7u2wRUG2QR2DSxSe7n/frOACEVNLlceRHa+
 
2219
nfl25pvZDswCnoDPQ4QoTRQsENIEPci4CsBMZBq7CAsuLOYqvmYKTTj3YxnBgiXBudGBjUzBZUJI
 
2220
BXEqgCvweIyuCjeG4eF2F5x14bcB9KQiQQWrjSddI1/oQIx6SYYeoFjzWIoIhYI1izlbhJjkKO7D
 
2221
M/QEmKfO9O7WeRo/zr4P7pyHwWxkwitcgwpQ5Ej96OX+PmiFwLeVjFUOrNYKaq1Nud3nR2n8nI2m
 
2222
k9H0friPTGVsUdptaxGrTEfpNVFEskxpXtUkkCkl1UNF9cgLBkx48J4EXyALuBtAwNYIjF5kcmUU
 
2223
abMKmMq1ULoiRbgsDEkTSsKSGFCJ6Z8vY/2xYiSacmtyAfCDdCNTVZoVF8vSTQOoEwSnOrngBkws
 
2224
MYGMBMg8/bMBLSYKS7pYEXP0PqT+ZmBT0Xuy+Pplj5yn4aM9nk72JD8/Wi+Gr98sD9eWSMOwkapD
 
2225
BbUv91XSvmyVkICt2tmXR4tWmrcUCsjWOpw87YidEC8i0gdTSOFhouJUNxR+4NYBG0MftoCTD9F7
 
2226
2rTtxG3oPwY1b2HncYwhrlmj6Wq924xtGDWqfdNxap+OYxplEurnMVo9RWks+rH8qKEtx7kZT5zJ
 
2227
4H7oOFclrN6uFe+d+nW2aIUsSgs/42EIPuOhXq+jEo3S6tX6w2ilNkDnIpHCWdEQhFgwj9pkk7FN
 
2228
l/y5eQvRSIQ5+TrL05lewxWpt/Lbhes5cJF3mLET1MGhcKCF+40tNWnUulxrpojwDo2sObdje3Bz
 
2229
N3QeHqf3D7OjEXMVV8LN3ZlvuzoWHqiUcNKHtwNd0IbvPGKYYM31nPKCgkUILw3KL+Y8l7aO1ArS
 
2230
Ad37nIU0fCj5NE5gQCuC5sOSu+UdI2NeXg/lFkQIlFpdWVaWZRfvqGiirC9o6liJ9FXGYrSY9mI1
 
2231
D/Ncozgn13vJvsznr7DnkJWXsyMH7e42ljdJ+aqNDF1bFnKWFLdj31xtaJYK6EXFgqmV/ymD/ROG
 
2232
+n8O9H8f5vsGOWXsL1+1k3g=
 
2233
""")
 
2234
 
 
2235
##file activate.fish
 
2236
ACTIVATE_FISH = convert("""
 
2237
eJyVVWFv2jAQ/c6vuBoqQVWC9nVSNVGVCaS2VC2rNLWVZZILWAs2s52wVvvxsyEJDrjbmgpK7PP5
 
2238
3bt3d22YLbmGlGcIq1wbmCPkGhPYcLMEEsGciwGLDS+YwSjlekngLFVyBe73GXSXxqw/DwbuTS8x
 
2239
yyKpFr1WG15lDjETQhpQuQBuIOEKY5O9tlppLqxHKSDByjVAPwEy+mXtCq5MzjIUBTCRgEKTKwFG
 
2240
gpBqxTLYXgN2myspVigMaYF92tZSowGZJf4mFExxNs9Qb614CgZtmH0BpEOn11f0cXI/+za8pnfD
 
2241
2ZjA1sg9zlV/8QvcMhxbNu0QwgYokn/d+n02nt6Opzcjcnx1vXcIoN74O4ymWQXmHURfJw9jenc/
 
2242
vbmb0enj6P5+cuVhqlKm3S0u2XRtRbA2QQAhV7VhBF0rsgUX9Ur1rBUXJgVSy8O751k8mzY5OrKH
 
2243
RW3eaQhYGTr8hrXO59ALhxQ83mCsDLAid3T72CCSdJhaFE+fXgicXAARUiR2WeVO37gH3oYHzFKo
 
2244
9k7CaPZ1UeNwH1tWuXA4uFKYYcEa8vaKqXl7q1UpygMPhFLvlVKyNzsSM3S2km7UBOl4xweUXk5u
 
2245
6e3wZmQ9leY1XE/Ili670tr9g/5POBBpGIJXCCF79L1siarl/dbESa8mD8PL61GpzqpzuMS7tqeB
 
2246
1YkALrRBloBMbR9yLcVx7frQAgUqR7NZIuzkEu110gbNit1enNs82Rx5utq7Z3prU78HFRgulqNC
 
2247
OTwbqJa9vkJFclQgZSjbKeBgSsUtCtt9D8OwAbIVJuewQdfvQRaoFE9wd1TmCuRG7OgJ1bVXGHc7
 
2248
z5WDL/WW36v2oi37CyVBak61+yPBA9C1qqGxzKQqZ0oPuocU9hpud0PIp8sDHkXR1HKkNlzjuUWA
 
2249
a0enFUyzOWZA4yXGP+ZMI3Tdt2OuqU/SO4q64526cPE0A7ZyW2PMbWZiZ5HamIZ2RcCKLXhcDl2b
 
2250
vXL+eccQoRzem80mekPDEiyiWK4GWqZmwxQOmPM0eIfgp1P9cqrBsewR2p/DPMtt+pfcYM+Ls2uh
 
2251
hALufTAdmGl8B1H3VPd2af8fQAc4PgqjlIBL9cGQqNpXaAwe3LrtVn8AkZTUxg==
 
2252
""")
 
2253
 
 
2254
##file activate.csh
 
2255
ACTIVATE_CSH = convert("""
 
2256
eJx9VG1P2zAQ/u5fcYQKNgTNPtN1WxlIQ4KCUEGaxuQ6yYVYSuzKdhqVX7+zk3bpy5YPUXL3PPfc
 
2257
ne98DLNCWshliVDV1kGCUFvMoJGugMjq2qQIiVSxSJ1cCofD1BYRnOVGV0CfZ0N2DD91DalQSjsw
 
2258
tQLpIJMGU1euvPe7QeJlkKzgWixlhnAt4aoUVsLnLBiy5NtbJWQ5THX1ZciYKKWwkOFaE04dUm6D
 
2259
r/zh7pq/3D7Nnid3/HEy+wFHY/gEJydg0aFaQrBFgz1c5DG1IhTs+UZgsBC2GMFBlaeH+8dZXwcW
 
2260
VPvCjXdlAvCfQsE7al0+07XjZvrSCUevR5dnkVeKlFYZmUztG4BdzL2u9KyLVabTU0bdfg7a0hgs
 
2261
cSmUg6UwUiQl2iHrcbcVGNvPCiLOe7+cRwG13z9qRGgx2z6DHjfm/Op2yqeT+xvOLzs0PTKHDz2V
 
2262
tkckFHoQfQRXoGJAj9el0FyJCmEMhzgMS4sB7KPOE2ExoLcSieYwDvR+cP8cg11gKkVJc2wRcm1g
 
2263
QhYFlXiTaTfO2ki0fQoiFM4tLuO4aZrhOzqR4dIPcWx17hphMBY+Srwh7RTyN83XOWkcSPh1Pg/k
 
2264
TXX/jbJTbMtUmcxZ+/bbqOsy82suFQg/BhdSOTRhMNBHlUarCpU7JzBhmkKmRejKOQzayQe6MWoa
 
2265
n1wqWmuh6LZAaHxcdeqIlVLhIBJdO9/kbl0It2oEXQj+eGjJOuvOIR/YGRqvFhttUB2XTvLXYN2H
 
2266
37CBdbW2W7j2r2+VsCn0doVWcFG1/4y1VwBjfwAyoZhD
 
2267
""")
 
2268
 
 
2269
##file activate.bat
 
2270
ACTIVATE_BAT = convert("""
 
2271
eJx9UdEKgjAUfW6wfxjiIH+hEDKUFHSKLCMI7kNOEkIf9P9pTJ3OLJ/03HPPPed4Es9XS9qqwqgT
 
2272
PbGKKOdXL4aAFS7A4gvAwgijuiKlqOpGlATS2NeMLE+TjJM9RkQ+SmqAXLrBo1LLIeLdiWlD6jZt
 
2273
r7VNubWkndkXaxg5GO3UaOOKS6drO3luDDiO5my3iA0YAKGzPRV1ack8cOdhysI0CYzIPzjSiH5X
 
2274
0QcvC8Lfaj0emsVKYF2rhL5L3fCkVjV76kShi59NHwDniAHzkgDgqBcwOgTMx+gDQQqXCw==
 
2275
""")
 
2276
 
 
2277
##file deactivate.bat
 
2278
DEACTIVATE_BAT = convert("""
 
2279
eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgUliIit
 
2280
KhZlqkpcnCA1WKRsuTTxWBIZ4uHv5+Hv64piEVwU3TK4BNBCmHIcKvDb6xjigWIjkI9uF1AIu7dA
 
2281
akGGW7n6uXABALCXXUI=
 
2282
""")
 
2283
 
 
2284
##file activate.ps1
 
2285
ACTIVATE_PS = convert("""
 
2286
eJylWdmS40Z2fVeE/oHT6rCloNUEAXDThB6wAyQAEjsB29GBjdgXYiWgmC/zgz/Jv+AEWNVd3S2N
 
2287
xuOKYEUxM+/Jmzfvcm7W//zXf/+wUMOoXtyi1F9kbd0sHH/hFc2iLtrK9b3FrSqyxaVQwr8uhqJd
 
2288
uHaeg9mqzRdR8/13Pyy8qPLdJh0+LMhi0QCoXxYfFh9WtttEnd34H8p6/f1300KauwrULws39e18
 
2289
0ZaLNm9rgN/ZVf3h++/e124Vlc0vKsspHy+Yyi5+XbzPhijvCtduoiL/kA1ukWV27n0o7Sb8LIFj
 
2290
CvWR5GQgUJdp1Pw8TS9+rPy6SDv/+e3d+0+4qw8f3v20+PliV37efEYBAB9FTKC+RHn/Cfxn3rdv
 
2291
00Fube5O+iyCtHDs9BfPfz3q4sfFv9d91Ljhfy7ei0VO+nVTtdOkv/jpt0l2AX6iG1jXgKnnDuD4
 
2292
ke2k/i8fzzz5UedkVcP4pwF+Wvz2FJl+3vt598urXf5Y6LNA5WcFOP7r0sW7b9a+W/xcu0Xpv5zk
 
2293
Kfq3P9Dz9di/fCxS72MXVU1rpx9L4Bxl85Wmn5a+zP76Zuh3pL9ROWr87PN+//GHIl+oOtvn9XSU
 
2294
qH+p0gQBFnx1uV+JLH5O5zv+PXW+WepXVVHZT0+oQezkIATcIm+ivPV/z5J/+cYj3ir4w0Lx09vC
 
2295
e5n/y5/Y5LPPfdrqb88ga/PabxZRVfmp39l588m/6u+/e+OpP+dF7n1WZpJ9//Z4v372fDDz9eHB
 
2296
7Juvs/BLMHzrxL9+9twXpJfhd1/DrpQ5Euu/vlss3wp9HXC/54C/Ld69m6zwdx3tC0d8daSv0V8B
 
2297
n4b9YYF53sJelJV/ix6LZspw/sJtqyl5LJ5r/23htA1Imfm/gt9R7dqVB1LjhydAX4Gb+zksQF59
 
2298
9+P7H//U+376afFuvh2/T6P85Xr/5c8C6OXyFY4BGuN+EE0+GeR201b+wkkLN5mmBY5TfMw8ngqL
 
2299
CztXxCSXKMCYrRIElWkEJlEPYsSOeKBVZCAQTKBhApMwRFQzmCThE0YQu2CdEhgjbgmk9GluHpfR
 
2300
/hhwJCZhGI5jt5FsAkOrObVyE6g2y1snyhMGFlDY1x+BoHpCMulTj5JYWNAYJmnKpvLxXgmQ8az1
 
2301
4fUGxxcitMbbhDFcsiAItg04E+OSBIHTUYD1HI4FHH4kMREPknuYRMyhh3AARWMkfhCketqD1CWJ
 
2302
mTCo/nhUScoQcInB1hpFhIKoIXLo5jLpwFCgsnLCx1QlEMlz/iFEGqzH3vWYcpRcThgWnEKm0QcS
 
2303
rA8ek2a2IYYeowUanOZOlrbWSJUC4c7y2EMI3uJPMnMF/SSXdk6E495VLhzkWHps0rOhKwqk+xBI
 
2304
DhJirhdUCTamMfXz2Hy303hM4DFJ8QL21BcPBULR+gcdYxoeiDqOFSqpi5B5PUISfGg46gFZBPo4
 
2305
jdh8lueaWuVSMTURfbAUnLINr/QYuuYoMQV6l1aWxuZVTjlaLC14UzqZ+ziTGDzJzhiYoPLrt3uI
 
2306
tXkVR47kAo09lo5BD76CH51cTt1snVpMOttLhY93yxChCQPI4OBecS7++h4p4Bdn4H97bJongtPk
 
2307
s9gQnXku1vzsjjmX4/o4YUDkXkjHwDg5FXozU0fW4y5kyeYW0uJWlh536BKr0kMGjtzTkng6Ep62
 
2308
uTWnQtiIqKnEsx7e1hLtzlXs7Upw9TwEnp0t9yzCGgUJIZConx9OHJArLkRYW0dW42G9OeR5Nzwk
 
2309
yk1mX7du5RGHT7dka7N3AznmSif7y6tuKe2N1Al/1TUPRqH6E2GLVc27h9IptMLkCKQYRqPQJgzV
 
2310
2m6WLsSipS3v3b1/WmXEYY1meLEVIU/arOGVkyie7ZsH05ZKpjFW4cpY0YkjySpSExNG2TS8nnJx
 
2311
nrQmWh2WY3cP1eISP9wbaVK35ZXc60yC3VN/j9n7UFoK6zvjSTE2+Pvz6Mx322rnftfP8Y0XKIdv
 
2312
Qd7AfK0nexBTMqRiErvCMa3Hegpfjdh58glW2oNMsKeAX8x6YJLZs9K8/ozjJkWL+JmECMvhQ54x
 
2313
9rsTHwcoGrDi6Y4I+H7yY4/rJVPAbYymUH7C2D3uiUS3KQ1nrCAUkE1dJMneDQIJMQQx5SONxoEO
 
2314
OEn1/Ig1eBBUeEDRuOT2WGGGE4bNypBLFh2PeIg3bEbg44PHiqNDbGIQm50LW6MJU62JHCGBrmc9
 
2315
2F7WBJrrj1ssnTAK4sxwRgh5LLblhwNAclv3Gd+jC/etCfyfR8TMhcWQz8TBIbG8IIyAQ81w2n/C
 
2316
mHWAwRzxd3WoBY7BZnsqGOWrOCKwGkMMNfO0Kci/joZgEocLjNnzgcmdehPHJY0FudXgsr+v44TB
 
2317
I3jnMGnsK5veAhgi9iXGifkHMOC09Rh9cAw9sQ0asl6wKMk8mpzFYaaDSgG4F0wisQDDBRpjCINg
 
2318
FIxhlhQ31xdSkkk6odXZFpTYOQpOOgw9ugM2cDQ+2MYa7JsEirGBrOuxsQy5nPMRdYjsTJ/j1iNw
 
2319
FeSt1jY2+dd5yx1/pzZMOQXUIDcXeAzR7QlDRM8AMkUldXOmGmvYXPABjxqkYKO7VAY6JRU7kpXr
 
2320
+Epu2BU3qFFXClFi27784LrDZsJwbNlDw0JzhZ6M0SMXE4iBHehCpHVkrQhpTFn2dsvsZYkiPEEB
 
2321
GSEAwdiur9LS1U6P2U9JhGp4hnFpJo4FfkdJHcwV6Q5dV1Q9uNeeu7rV8PAjwdFg9RLtroifOr0k
 
2322
uOiRTo/obNPhQIf42Fr4mtThWoSjitEdAmFW66UCe8WFjPk1YVNpL9srFbond7jrLg8tqAasIMpy
 
2323
zkH0SY/6zVAwJrEc14zt14YRXdY+fcJ4qOd2XKB0/Kghw1ovd11t2o+zjt+txndo1ZDZ2T+uMVHT
 
2324
VSXhedBAHoJIID9xm6wPQI3cXY+HR7vxtrJuCKh6kbXaW5KkVeJsdsjqsYsOwYSh0w5sMbu7LF8J
 
2325
5T7U6LJdiTx+ca7RKlulGgS5Z1JSU2Llt32cHFipkaurtBrvNX5UtvNZjkufZ/r1/XyLl6yOpytL
 
2326
Km8Fn+y4wkhlqZP5db0rooqy7xdL4wxzFVTX+6HaxuQJK5E5B1neSSovZ9ALB8091dDbbjVxhWNY
 
2327
Ve5hn1VnI9OF0wpvaRm7SZuC1IRczwC7GnkhPt3muHV1YxUJfo+uh1sYnJy+vI0ZwuPV2uqWJYUH
 
2328
bmBsi1zmFSxHrqwA+WIzLrHkwW4r+bad7xbOzJCnKIa3S3YvrzEBK1Dc0emzJW+SqysQfdEDorQG
 
2329
9ZJlbQzEHQV8naPaF440YXzJk/7vHGK2xwuP+Gc5xITxyiP+WQ4x18oXHjFzCBy9kir1EFTAm0Zq
 
2330
LYwS8MpiGhtfxiBRDXpxDWxk9g9Q2fzPPAhS6VFDAc/aiNGatUkPtZIStZFQ1qD0IlJa/5ZPAi5J
 
2331
ySp1ETDomZMnvgiysZSBfMikrSDte/K5lqV6iwC5q7YN9I1dBZXUytDJNqU74MJsUyNNLAPopWK3
 
2332
tzmLkCiDyl7WQnj9sm7Kd5kzgpoccdNeMw/6zPVB3pUwMgi4C7hj4AMFAf4G27oXH8NNT9zll/sK
 
2333
S6wVlQwazjxWKWy20ZzXb9ne8ngGalPBWSUSj9xkc1drsXkZ8oOyvYT3e0rnYsGwx85xZB9wKeKg
 
2334
cJKZnamYwiaMymZvzk6wtDUkxmdUg0mPad0YHtvzpjEfp2iMxvORhnx0kCVLf5Qa43WJsVoyfEyI
 
2335
pzmf8ruM6xBr7dnBgzyxpqXuUPYaKahOaz1LrxNkS/Q3Ae5AC+xl6NbxAqXXlzghZBZHmOrM6Y6Y
 
2336
ctAkltwlF7SKEsShjVh7QHuxMU0a08/eiu3x3M+07OijMcKFFltByXrpk8w+JNnZpnp3CfgjV1Ax
 
2337
gUYCnWwYow42I5wHCcTzLXK0hMZN2DrPM/zCSqe9jRSlJnr70BPE4+zrwbk/xVIDHy2FAQyHoomT
 
2338
Tt5jiM68nBQut35Y0qLclLiQrutxt/c0OlSqXAC8VrxW97lGoRWzhOnifE2zbF05W4xuyhg7JTUL
 
2339
aqJ7SWDywhjlal0b+NLTpERBgnPW0+Nw99X2Ws72gOL27iER9jgzj7Uu09JaZ3n+hmCjjvZpjNst
 
2340
vOWWTbuLrg+/1ltX8WpPauEDEvcunIgTxuMEHweWKCx2KQ9DU/UKdO/3za4Szm2iHYL+ss9AAttm
 
2341
gZHq2pkUXFbV+FiJCKrpBms18zH75vax5jSo7FNunrVWY3Chvd8KKnHdaTt/6ealwaA1x17yTlft
 
2342
8VBle3nAE+7R0MScC3MJofNCCkA9PGKBgGMYEwfB2QO5j8zUqa8F/EkWKCzGQJ5EZ05HTly1B01E
 
2343
z813G5BY++RZ2sxbQS8ZveGPJNabp5kXAeoign6Tlt5+L8i5ZquY9+S+KEUHkmYMRFBxRrHnbl2X
 
2344
rVemKnG+oB1yd9+zT+4c43jQ0wWmQRR6mTCkY1q3VG05Y120ZzKOMBe6Vy7I5Vz4ygPB3yY4G0FP
 
2345
8RxiMx985YJPXsgRU58EuHj75gygTzejP+W/zKGe78UQN3yOJ1aMQV9hFH+GAfLRsza84WlPLAI/
 
2346
9G/5JdcHftEfH+Y3/fHUG7/o8bv98dzzy3e8S+XCvgqB+VUf7sH0yDHpONdbRE8tAg9NWOzcTJ7q
 
2347
TuAxe/AJ07c1Rs9okJvl1/0G60qvbdDzz5zO0FuPFQIHNp9y9Bd1CufYVx7dB26mAxwa8GMNrN/U
 
2348
oGbNZ3EQ7inLzHy5tRg9AXJrN8cB59cCUBeCiVO7zKM0jU0MamhnRThkg/NMmBOGb6StNeD9tDfA
 
2349
7czsAWopDdnGoXUHtA+s/k0vNPkBcxEI13jVd/axp85va3LpwGggXXWw12Gwr/JGAH0b8CPboiZd
 
2350
QO1l0mk/UHukud4C+w5uRoNzpCmoW6GbgbMyaQNkga2pQINB18lOXOCJzSWPFOhZcwzdgrsQnne7
 
2351
nvjBi+7cP2BbtBeDOW5uOLGf3z94FasKIguOqJl+8ss/6Kumns4cuWbqq5592TN/RNIbn5Qo6qbi
 
2352
O4F0P9txxPAwagqPlftztO8cWBzdN/jz3b7GD6JHYP/Zp4ToAMaA74M+EGSft3hEGMuf8EwjnTk/
 
2353
nz/P7SLipB/ogQ6xNX0fDqNncMCfHqGLCMM0ZzFa+6lPJYQ5p81vW4HkCvidYf6kb+P/oB965g8K
 
2354
C6uR0rdjX1DNKc5pOSTquI8uQ6KXxYaKBn+30/09tK4kMpJPgUIQkbENEPbuezNPPje2Um83SgyX
 
2355
GTCJb6MnGVIpgncdQg1qz2bvPfxYD9fewCXDomx9S+HQJuX6W3VAL+v5WZMudRQZk9ZdOk6GIUtC
 
2356
PqEb/uwSIrtR7/edzqgEdtpEwq7p2J5OQV+RLrmtTvFwFpf03M/VrRyTZ73qVod7v7Jh2Dwe5J25
 
2357
JqFOU2qEu1sP+CRotklediycKfLjeIZzjJQsvKmiGSNQhxuJpKa+hoWUizaE1PuIRGzJqropwgVB
 
2358
oo1hr870MZLgnXF5ZIpr6mF0L8aSy2gVnTAuoB4WEd4d5NPVC9TMotYXERKlTcwQ2KiB/C48AEfH
 
2359
Qbyq4CN8xTFnTvf/ebOc3isnjD95s0QF0nx9s+y+zMmz782xL0SgEmRpA3x1w1Ff9/74xcxKEPdS
 
2360
IEFTz6GgU0+BK/UZ5Gwbl4gZwycxEw+Kqa5QmMkh4OzgzEVPnDAiAOGBFaBW4wkDmj1G4RyElKgj
 
2361
NlLCq8zsp085MNh/+R4t1Q8yxoSv8PUpTt7izZwf2BTHZZ3pIZpUIpuLkL1nNL6sYcHqcKm237wp
 
2362
T2+RCjgXweXd2Zp7ZM8W6dG5bZsqo0nrJBTx8EC0+CQQdzEGnabTnkzofu1pYkWl4E7XSniECdxy
 
2363
vLYavPMcL9LW5SToJFNnos+uqweOHriUZ1ntIYZUonc7ltEQ6oTRtwOHNwez2sVREskHN+bqG3ua
 
2364
eaEbJ8XpyO8CeD9QJc8nbLP2C2R3A437ISUNyt5Yd0TbDNcl11/DSsOzdbi/VhCC0KE6v1vqVNkq
 
2365
45ZnG6fiV2NwzInxCNth3BwL0+8814jE6+1W1EeWtpWbSZJOJNYXmWRXa7vLnAljE692eHjZ4y5u
 
2366
y1u63De0IzKca7As48Z3XshVF+3XiLNz0JIMh/JOpbiNLlMi672uO0wYzOCZjRxcxj3D+gVenGIE
 
2367
MvFUGGXuRps2RzMcgWIRolHXpGUP6sMsQt1hspUBnVKUn/WQj2u6j3SXd9Xz0QtEzoM7qTu5y7gR
 
2368
q9gNNsrlEMLdikBt9bFvBnfbUIh6voTw7eDsyTmPKUvF0bHqWLbHe3VRHyRZnNeSGKsB73q66Vsk
 
2369
taxWYmwz1tYVFG/vOQhlM0gUkyvIab3nv2caJ1udU1F3pDMty7stubTE4OJqm0i0ECfrJIkLtraC
 
2370
HwRWKzlqpfhEIqYH09eT9WrOhQyt8YEoyBlnXtAT37WHIQ03TIuEHbnRxZDdLun0iok9PUC79prU
 
2371
m5beZzfQUelEXnhzb/pIROKx3F7qCttYIFGh5dXNzFzID7u8vKykA8Uejf7XXz//S4nKvW//ofS/
 
2372
QastYw==
 
2373
""")
 
2374
 
 
2375
##file distutils-init.py
 
2376
DISTUTILS_INIT = convert("""
 
2377
eJytV1uL4zYUfvevOE0ottuMW9q3gVDa3aUMXXbLMlDKMBiNrSTqOJKRlMxkf33PkXyRbGe7Dw2E
 
2378
UXTu37lpxLFV2oIyifAncxmOL0xLIfcG+gv80x9VW6maw7o/CANSWWBwFtqeWMPlGY6qPjV8A0bB
 
2379
C4eKSTgZ5LRgFeyErMEeOBhbN+Ipgeizhjtnhkn7DdyjuNLPoCS0l/ayQTG0djwZC08cLXozeMss
 
2380
aG5EzQ0IScpnWtHSTXuxByV/QCmxE7y+eS0uxWeoheaVVfqSJHiU7Mhhi6gULbOHorshkrEnKxpT
 
2381
0n3A8Y8SMpuwZx6aoix3ouFlmW8gHRSkeSJ2g7hU+kiHLDaQw3bmRDaTGfTnty7gPm0FHbIBg9U9
 
2382
oh1kZzAFLaue2R6htPCtAda2nGlDSUJ4PZBgCJBGVcwKTAMz/vJiLD+Oin5Z5QlvDPdulC6EsiyE
 
2383
NFzb7McNTKJzbJqzphx92VKRFY1idenzmq3K0emRcbWBD0ryqc4NZGmKOOOX9Pz5x+/l27tP797c
 
2384
f/z0d+4NruGNai8uAM0bfsYaw8itFk8ny41jsfpyO+BWlpqfhcG4yxLdi/0tQqoT4a8Vby382mt8
 
2385
p7XSo7aWGdPBc+b6utaBmCQ7rQKQoWtAuthQCiold2KfJIPTT8xwg9blPumc+YDZC/wYGdAyHpJk
 
2386
vUbHbHWAp5No6pK/WhhLEWrFjUwtPEv1Agf8YmnsuXUQYkeZoHm8ogP16gt2uHoxcEMdf2C6pmbw
 
2387
hUMsWGhanboh4IzzmsIpWs134jVPqD/c74bZHdY69UKKSn/+KfVhxLgUlToemayLMYQOqfEC61bh
 
2388
cbhwaqoGUzIyZRFHPmau5juaWqwRn3mpWmoEA5nhzS5gog/5jbcFQqOZvmBasZtwYlG93k5GEiyw
 
2389
buHhMWLjDarEGpMGB2LFs5nIJkhp/nUmZneFaRth++lieJtHepIvKgx6PJqIlD9X2j6pG1i9x3pZ
 
2390
5bHuCPFiirGHeO7McvoXkz786GaKVzC9DSpnOxJdc4xm6NSVq7lNEnKdVlnpu9BNYoKX2Iq3wvgh
 
2391
gGEUM66kK6j4NiyoneuPLSwaCWDxczgaolEWpiMyDVDb7dNuLAbriL8ig8mmeju31oNvQdpnvEPC
 
2392
1vAXbWacGRVrGt/uXN/gU0CDDwgooKRrHfTBb1/s9lYZ8ZqOBU0yLvpuP6+K9hLFsvIjeNhBi0KL
 
2393
MlOuWRn3FRwx5oHXjl0YImUx0+gLzjGchrgzca026ETmYJzPD+IpuKzNi8AFn048Thd63OdD86M6
 
2394
84zE8yQm0VqXdbbgvub2pKVnS76icBGdeTHHXTKspUmr4NYo/furFLKiMdQzFjHJNcdAnMhltBJK
 
2395
0/IKX3DVFqvPJ2dLE7bDBkH0l/PJ29074+F0CsGYOxsb7U3myTUncYfXqnLLfa6sJybX4g+hmcjO
 
2396
kMRBfA1JellfRRKJcyRpxdS4rIl6FdmQCWjo/o9Qz7yKffoP4JHjOvABcRn4CZIT2RH4jnxmfpVG
 
2397
qgLaAvQBNfuO6X0/Ux02nb4FKx3vgP+XnkX0QW9pLy/NsXgdN24dD3LxO2Nwil7Zlc1dqtP3d7/h
 
2398
kzp1/+7hGBuY4pk0XD/0Ao/oTe/XGrfyM773aB7iUhgkpy+dwAMalxMP0DrBcsVw/6p25+/hobP9
 
2399
GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ=
 
2400
""")
 
2401
 
 
2402
##file distutils.cfg
 
2403
DISTUTILS_CFG = convert("""
 
2404
eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
 
2405
xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
 
2406
9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
 
2407
""")
 
2408
 
 
2409
##file activate_this.py
 
2410
ACTIVATE_THIS = convert("""
 
2411
eJyNU01v2zAMvetXEB4K21jmDOstQA4dMGCHbeihlyEIDMWmG62yJEiKE//7kXKdpN2KzYBt8euR
 
2412
fKSyLPs8wiEo8wh4wqZTGou4V6Hm0wJa1cSiTkJdr8+GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe
 
2413
5a3p0cRKiAe2NtLADikftnDco0ko/SFEVgEZ8aRC5GLux7i3BpSJ6J1H+i7A2CjiHq9z7JRZuuQq
 
2414
siwTIvpxJYCeuWaBpwZdhB+yxy/eWz+ZvVSU8C4E9FFZkyxFsvCT/ZzL8gcz9aXVE14Yyp2M+2W0
 
2415
y7n5mp0qN+avKXvbsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCZN9UzlJr+/e/iab8WfqsmPI6pWeUPd
 
2416
FrMsd4H/55poeO9n54COhUs+sZNEzNtg/wanpjpuqHJaxs76HtZryI/K3H7KJ/KDIhqcbJ7kI4ar
 
2417
XL+sMgXnX0D+Te2Iy5xdP8yueSlQB/x/ED2BTAtyE3K4SYUN6AMNfbO63f4lBW3bUJPbTL+mjSxS
 
2418
PyRfJkZRgj+VbFv+EzHFi5pKwUEepa4JslMnwkowSRCXI+m5XvEOvtuBrxHdhLalG0JofYBok6qj
 
2419
YdN2dEngUlbC4PG60M1WEN0piu7Nq7on0mgyyUw3iV1etLo6r/81biWdQ9MWHFaePWZYaq+nmp+t
 
2420
s3az+sj7eA0jfgPfeoN1
 
2421
""")
 
2422
 
 
2423
MH_MAGIC = 0xfeedface
 
2424
MH_CIGAM = 0xcefaedfe
 
2425
MH_MAGIC_64 = 0xfeedfacf
 
2426
MH_CIGAM_64 = 0xcffaedfe
 
2427
FAT_MAGIC = 0xcafebabe
 
2428
BIG_ENDIAN = '>'
 
2429
LITTLE_ENDIAN = '<'
 
2430
LC_LOAD_DYLIB = 0xc
 
2431
maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint')
 
2432
 
 
2433
 
 
2434
class fileview(object):
 
2435
    """
 
2436
    A proxy for file-like objects that exposes a given view of a file.
 
2437
    Modified from macholib.
 
2438
    """
 
2439
 
 
2440
    def __init__(self, fileobj, start=0, size=maxint):
 
2441
        if isinstance(fileobj, fileview):
 
2442
            self._fileobj = fileobj._fileobj
 
2443
        else:
 
2444
            self._fileobj = fileobj
 
2445
        self._start = start
 
2446
        self._end = start + size
 
2447
        self._pos = 0
 
2448
 
 
2449
    def __repr__(self):
 
2450
        return '<fileview [%d, %d] %r>' % (
 
2451
            self._start, self._end, self._fileobj)
 
2452
 
 
2453
    def tell(self):
 
2454
        return self._pos
 
2455
 
 
2456
    def _checkwindow(self, seekto, op):
 
2457
        if not (self._start <= seekto <= self._end):
 
2458
            raise IOError("%s to offset %d is outside window [%d, %d]" % (
 
2459
                op, seekto, self._start, self._end))
 
2460
 
 
2461
    def seek(self, offset, whence=0):
 
2462
        seekto = offset
 
2463
        if whence == os.SEEK_SET:
 
2464
            seekto += self._start
 
2465
        elif whence == os.SEEK_CUR:
 
2466
            seekto += self._start + self._pos
 
2467
        elif whence == os.SEEK_END:
 
2468
            seekto += self._end
 
2469
        else:
 
2470
            raise IOError("Invalid whence argument to seek: %r" % (whence,))
 
2471
        self._checkwindow(seekto, 'seek')
 
2472
        self._fileobj.seek(seekto)
 
2473
        self._pos = seekto - self._start
 
2474
 
 
2475
    def write(self, bytes):
 
2476
        here = self._start + self._pos
 
2477
        self._checkwindow(here, 'write')
 
2478
        self._checkwindow(here + len(bytes), 'write')
 
2479
        self._fileobj.seek(here, os.SEEK_SET)
 
2480
        self._fileobj.write(bytes)
 
2481
        self._pos += len(bytes)
 
2482
 
 
2483
    def read(self, size=maxint):
 
2484
        assert size >= 0
 
2485
        here = self._start + self._pos
 
2486
        self._checkwindow(here, 'read')
 
2487
        size = min(size, self._end - here)
 
2488
        self._fileobj.seek(here, os.SEEK_SET)
 
2489
        bytes = self._fileobj.read(size)
 
2490
        self._pos += len(bytes)
 
2491
        return bytes
 
2492
 
 
2493
 
 
2494
def read_data(file, endian, num=1):
 
2495
    """
 
2496
    Read a given number of 32-bits unsigned integers from the given file
 
2497
    with the given endianness.
 
2498
    """
 
2499
    res = struct.unpack(endian + 'L' * num, file.read(num * 4))
 
2500
    if len(res) == 1:
 
2501
        return res[0]
 
2502
    return res
 
2503
 
 
2504
 
 
2505
def mach_o_change(path, what, value):
 
2506
    """
 
2507
    Replace a given name (what) in any LC_LOAD_DYLIB command found in
 
2508
    the given binary with a new name (value), provided it's shorter.
 
2509
    """
 
2510
 
 
2511
    def do_macho(file, bits, endian):
 
2512
        # Read Mach-O header (the magic number is assumed read by the caller)
 
2513
        cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6)
 
2514
        # 64-bits header has one more field.
 
2515
        if bits == 64:
 
2516
            read_data(file, endian)
 
2517
        # The header is followed by ncmds commands
 
2518
        for n in range(ncmds):
 
2519
            where = file.tell()
 
2520
            # Read command header
 
2521
            cmd, cmdsize = read_data(file, endian, 2)
 
2522
            if cmd == LC_LOAD_DYLIB:
 
2523
                # The first data field in LC_LOAD_DYLIB commands is the
 
2524
                # offset of the name, starting from the beginning of the
 
2525
                # command.
 
2526
                name_offset = read_data(file, endian)
 
2527
                file.seek(where + name_offset, os.SEEK_SET)
 
2528
                # Read the NUL terminated string
 
2529
                load = file.read(cmdsize - name_offset).decode()
 
2530
                load = load[:load.index('\0')]
 
2531
                # If the string is what is being replaced, overwrite it.
 
2532
                if load == what:
 
2533
                    file.seek(where + name_offset, os.SEEK_SET)
 
2534
                    file.write(value.encode() + '\0'.encode())
 
2535
            # Seek to the next command
 
2536
            file.seek(where + cmdsize, os.SEEK_SET)
 
2537
 
 
2538
    def do_file(file, offset=0, size=maxint):
 
2539
        file = fileview(file, offset, size)
 
2540
        # Read magic number
 
2541
        magic = read_data(file, BIG_ENDIAN)
 
2542
        if magic == FAT_MAGIC:
 
2543
            # Fat binaries contain nfat_arch Mach-O binaries
 
2544
            nfat_arch = read_data(file, BIG_ENDIAN)
 
2545
            for n in range(nfat_arch):
 
2546
                # Read arch header
 
2547
                cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5)
 
2548
                do_file(file, offset, size)
 
2549
        elif magic == MH_MAGIC:
 
2550
            do_macho(file, 32, BIG_ENDIAN)
 
2551
        elif magic == MH_CIGAM:
 
2552
            do_macho(file, 32, LITTLE_ENDIAN)
 
2553
        elif magic == MH_MAGIC_64:
 
2554
            do_macho(file, 64, BIG_ENDIAN)
 
2555
        elif magic == MH_CIGAM_64:
 
2556
            do_macho(file, 64, LITTLE_ENDIAN)
 
2557
 
 
2558
    assert(len(what) >= len(value))
 
2559
    do_file(open(path, 'r+b'))
 
2560
 
 
2561
 
 
2562
if __name__ == '__main__':
 
2563
    main()
 
2564
 
 
2565
## TODO:
 
2566
## Copy python.exe.manifest
 
2567
## Monkeypatch distutils.sysconfig