~ubuntu-branches/ubuntu/precise/enigmail/precise-security

« back to all changes in this revision

Viewing changes to python/virtualenv/virtualenv.py

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2012-11-12 16:36:01 UTC
  • mfrom: (0.12.15)
  • Revision ID: package-import@ubuntu.com-20121112163601-t8e8skdfi3ni9iqp
Tags: 2:1.4.6-0ubuntu0.12.04.1
* New upstream release v1.4.6
  - see LP: #1080212 for USN information
* Drop unneeded patches
  - remove debian/patches/correct-version-number.diff
  - remove debian/patches/dont_register_cids_multiple_times.diff
  - update debian/patches/series
* Support building in an objdir
  - update debian/rules

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.7.2"  # 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 distutils.sysconfig
 
22
from distutils.util import strtobool
 
23
import struct
 
24
 
 
25
try:
 
26
    import subprocess
 
27
except ImportError:
 
28
    if sys.version_info <= (2, 3):
 
29
        print('ERROR: %s' % sys.exc_info()[1])
 
30
        print('ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.')
 
31
        print('If you copy subprocess.py from a newer version of Python this script will probably work')
 
32
        sys.exit(101)
 
33
    else:
 
34
        raise
 
35
try:
 
36
    set
 
37
except NameError:
 
38
    from sets import Set as set
 
39
try:
 
40
    basestring
 
41
except NameError:
 
42
    basestring = str
 
43
 
 
44
try:
 
45
    import ConfigParser
 
46
except ImportError:
 
47
    import configparser as ConfigParser
 
48
 
 
49
join = os.path.join
 
50
py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
 
51
 
 
52
is_jython = sys.platform.startswith('java')
 
53
is_pypy = hasattr(sys, 'pypy_version_info')
 
54
is_win  = (sys.platform == 'win32')
 
55
abiflags = getattr(sys, 'abiflags', '')
 
56
 
 
57
user_dir = os.path.expanduser('~')
 
58
if sys.platform == 'win32':
 
59
    user_dir = os.environ.get('APPDATA', user_dir)  # Use %APPDATA% for roaming
 
60
    default_storage_dir = os.path.join(user_dir, 'virtualenv')
 
61
else:
 
62
    default_storage_dir = os.path.join(user_dir, '.virtualenv')
 
63
default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini')
 
64
 
 
65
if is_pypy:
 
66
    expected_exe = 'pypy'
 
67
elif is_jython:
 
68
    expected_exe = 'jython'
 
69
else:
 
70
    expected_exe = 'python'
 
71
 
 
72
 
 
73
REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
 
74
                    'fnmatch', 'locale', 'encodings', 'codecs',
 
75
                    'stat', 'UserDict', 'readline', 'copy_reg', 'types',
 
76
                    're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
 
77
                    'zlib']
 
78
 
 
79
REQUIRED_FILES = ['lib-dynload', 'config']
 
80
 
 
81
majver, minver = sys.version_info[:2]
 
82
if majver == 2:
 
83
    if minver >= 6:
 
84
        REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc'])
 
85
    if minver >= 7:
 
86
        REQUIRED_MODULES.extend(['_weakrefset'])
 
87
    if minver <= 3:
 
88
        REQUIRED_MODULES.extend(['sets', '__future__'])
 
89
elif majver == 3:
 
90
    # Some extra modules are needed for Python 3, but different ones
 
91
    # for different versions.
 
92
    REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
 
93
                             '_weakrefset', 'copyreg', 'tempfile', 'random',
 
94
                             '__future__', 'collections', 'keyword', 'tarfile',
 
95
                             'shutil', 'struct', 'copy'])
 
96
    if minver >= 2:
 
97
        REQUIRED_FILES[-1] = 'config-%s' % majver
 
98
    if minver == 3:
 
99
        # The whole list of 3.3 modules is reproduced below - the current
 
100
        # uncommented ones are required for 3.3 as of now, but more may be
 
101
        # added as 3.3 development continues.
 
102
        REQUIRED_MODULES.extend([
 
103
            #"aifc",
 
104
            #"antigravity",
 
105
            #"argparse",
 
106
            #"ast",
 
107
            #"asynchat",
 
108
            #"asyncore",
 
109
            "base64",
 
110
            #"bdb",
 
111
            #"binhex",
 
112
            "bisect",
 
113
            #"calendar",
 
114
            #"cgi",
 
115
            #"cgitb",
 
116
            #"chunk",
 
117
            #"cmd",
 
118
            #"codeop",
 
119
            #"code",
 
120
            #"colorsys",
 
121
            #"_compat_pickle",
 
122
            #"compileall",
 
123
            #"concurrent",
 
124
            #"configparser",
 
125
            #"contextlib",
 
126
            #"cProfile",
 
127
            #"crypt",
 
128
            #"csv",
 
129
            #"ctypes",
 
130
            #"curses",
 
131
            #"datetime",
 
132
            #"dbm",
 
133
            #"decimal",
 
134
            #"difflib",
 
135
            #"dis",
 
136
            #"doctest",
 
137
            #"dummy_threading",
 
138
            "_dummy_thread",
 
139
            #"email",
 
140
            #"filecmp",
 
141
            #"fileinput",
 
142
            #"formatter",
 
143
            #"fractions",
 
144
            #"ftplib",
 
145
            #"functools",
 
146
            #"getopt",
 
147
            #"getpass",
 
148
            #"gettext",
 
149
            #"glob",
 
150
            #"gzip",
 
151
            "hashlib",
 
152
            "heapq",
 
153
            "hmac",
 
154
            #"html",
 
155
            #"http",
 
156
            #"idlelib",
 
157
            #"imaplib",
 
158
            #"imghdr",
 
159
            #"importlib",
 
160
            #"inspect",
 
161
            #"json",
 
162
            #"lib2to3",
 
163
            #"logging",
 
164
            #"macpath",
 
165
            #"macurl2path",
 
166
            #"mailbox",
 
167
            #"mailcap",
 
168
            #"_markupbase",
 
169
            #"mimetypes",
 
170
            #"modulefinder",
 
171
            #"multiprocessing",
 
172
            #"netrc",
 
173
            #"nntplib",
 
174
            #"nturl2path",
 
175
            #"numbers",
 
176
            #"opcode",
 
177
            #"optparse",
 
178
            #"os2emxpath",
 
179
            #"pdb",
 
180
            #"pickle",
 
181
            #"pickletools",
 
182
            #"pipes",
 
183
            #"pkgutil",
 
184
            #"platform",
 
185
            #"plat-linux2",
 
186
            #"plistlib",
 
187
            #"poplib",
 
188
            #"pprint",
 
189
            #"profile",
 
190
            #"pstats",
 
191
            #"pty",
 
192
            #"pyclbr",
 
193
            #"py_compile",
 
194
            #"pydoc_data",
 
195
            #"pydoc",
 
196
            #"_pyio",
 
197
            #"queue",
 
198
            #"quopri",
 
199
            "reprlib",
 
200
            "rlcompleter",
 
201
            #"runpy",
 
202
            #"sched",
 
203
            #"shelve",
 
204
            #"shlex",
 
205
            #"smtpd",
 
206
            #"smtplib",
 
207
            #"sndhdr",
 
208
            #"socket",
 
209
            #"socketserver",
 
210
            #"sqlite3",
 
211
            #"ssl",
 
212
            #"stringprep",
 
213
            #"string",
 
214
            #"_strptime",
 
215
            #"subprocess",
 
216
            #"sunau",
 
217
            #"symbol",
 
218
            #"symtable",
 
219
            #"sysconfig",
 
220
            #"tabnanny",
 
221
            #"telnetlib",
 
222
            #"test",
 
223
            #"textwrap",
 
224
            #"this",
 
225
            #"_threading_local",
 
226
            #"threading",
 
227
            #"timeit",
 
228
            #"tkinter",
 
229
            #"tokenize",
 
230
            #"token",
 
231
            #"traceback",
 
232
            #"trace",
 
233
            #"tty",
 
234
            #"turtledemo",
 
235
            #"turtle",
 
236
            #"unittest",
 
237
            #"urllib",
 
238
            #"uuid",
 
239
            #"uu",
 
240
            #"wave",
 
241
            "weakref",
 
242
            #"webbrowser",
 
243
            #"wsgiref",
 
244
            #"xdrlib",
 
245
            #"xml",
 
246
            #"xmlrpc",
 
247
            #"zipfile",
 
248
        ])
 
249
 
 
250
if is_pypy:
 
251
    # these are needed to correctly display the exceptions that may happen
 
252
    # during the bootstrap
 
253
    REQUIRED_MODULES.extend(['traceback', 'linecache'])
 
254
 
 
255
class Logger(object):
 
256
 
 
257
    """
 
258
    Logging object for use in command-line script.  Allows ranges of
 
259
    levels, to avoid some redundancy of displayed information.
 
260
    """
 
261
 
 
262
    DEBUG = logging.DEBUG
 
263
    INFO = logging.INFO
 
264
    NOTIFY = (logging.INFO+logging.WARN)/2
 
265
    WARN = WARNING = logging.WARN
 
266
    ERROR = logging.ERROR
 
267
    FATAL = logging.FATAL
 
268
 
 
269
    LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
 
270
 
 
271
    def __init__(self, consumers):
 
272
        self.consumers = consumers
 
273
        self.indent = 0
 
274
        self.in_progress = None
 
275
        self.in_progress_hanging = False
 
276
 
 
277
    def debug(self, msg, *args, **kw):
 
278
        self.log(self.DEBUG, msg, *args, **kw)
 
279
    def info(self, msg, *args, **kw):
 
280
        self.log(self.INFO, msg, *args, **kw)
 
281
    def notify(self, msg, *args, **kw):
 
282
        self.log(self.NOTIFY, msg, *args, **kw)
 
283
    def warn(self, msg, *args, **kw):
 
284
        self.log(self.WARN, msg, *args, **kw)
 
285
    def error(self, msg, *args, **kw):
 
286
        self.log(self.WARN, msg, *args, **kw)
 
287
    def fatal(self, msg, *args, **kw):
 
288
        self.log(self.FATAL, msg, *args, **kw)
 
289
    def log(self, level, msg, *args, **kw):
 
290
        if args:
 
291
            if kw:
 
292
                raise TypeError(
 
293
                    "You may give positional or keyword arguments, not both")
 
294
        args = args or kw
 
295
        rendered = None
 
296
        for consumer_level, consumer in self.consumers:
 
297
            if self.level_matches(level, consumer_level):
 
298
                if (self.in_progress_hanging
 
299
                    and consumer in (sys.stdout, sys.stderr)):
 
300
                    self.in_progress_hanging = False
 
301
                    sys.stdout.write('\n')
 
302
                    sys.stdout.flush()
 
303
                if rendered is None:
 
304
                    if args:
 
305
                        rendered = msg % args
 
306
                    else:
 
307
                        rendered = msg
 
308
                    rendered = ' '*self.indent + rendered
 
309
                if hasattr(consumer, 'write'):
 
310
                    consumer.write(rendered+'\n')
 
311
                else:
 
312
                    consumer(rendered)
 
313
 
 
314
    def start_progress(self, msg):
 
315
        assert not self.in_progress, (
 
316
            "Tried to start_progress(%r) while in_progress %r"
 
317
            % (msg, self.in_progress))
 
318
        if self.level_matches(self.NOTIFY, self._stdout_level()):
 
319
            sys.stdout.write(msg)
 
320
            sys.stdout.flush()
 
321
            self.in_progress_hanging = True
 
322
        else:
 
323
            self.in_progress_hanging = False
 
324
        self.in_progress = msg
 
325
 
 
326
    def end_progress(self, msg='done.'):
 
327
        assert self.in_progress, (
 
328
            "Tried to end_progress without start_progress")
 
329
        if self.stdout_level_matches(self.NOTIFY):
 
330
            if not self.in_progress_hanging:
 
331
                # Some message has been printed out since start_progress
 
332
                sys.stdout.write('...' + self.in_progress + msg + '\n')
 
333
                sys.stdout.flush()
 
334
            else:
 
335
                sys.stdout.write(msg + '\n')
 
336
                sys.stdout.flush()
 
337
        self.in_progress = None
 
338
        self.in_progress_hanging = False
 
339
 
 
340
    def show_progress(self):
 
341
        """If we are in a progress scope, and no log messages have been
 
342
        shown, write out another '.'"""
 
343
        if self.in_progress_hanging:
 
344
            sys.stdout.write('.')
 
345
            sys.stdout.flush()
 
346
 
 
347
    def stdout_level_matches(self, level):
 
348
        """Returns true if a message at this level will go to stdout"""
 
349
        return self.level_matches(level, self._stdout_level())
 
350
 
 
351
    def _stdout_level(self):
 
352
        """Returns the level that stdout runs at"""
 
353
        for level, consumer in self.consumers:
 
354
            if consumer is sys.stdout:
 
355
                return level
 
356
        return self.FATAL
 
357
 
 
358
    def level_matches(self, level, consumer_level):
 
359
        """
 
360
        >>> l = Logger([])
 
361
        >>> l.level_matches(3, 4)
 
362
        False
 
363
        >>> l.level_matches(3, 2)
 
364
        True
 
365
        >>> l.level_matches(slice(None, 3), 3)
 
366
        False
 
367
        >>> l.level_matches(slice(None, 3), 2)
 
368
        True
 
369
        >>> l.level_matches(slice(1, 3), 1)
 
370
        True
 
371
        >>> l.level_matches(slice(2, 3), 1)
 
372
        False
 
373
        """
 
374
        if isinstance(level, slice):
 
375
            start, stop = level.start, level.stop
 
376
            if start is not None and start > consumer_level:
 
377
                return False
 
378
            if stop is not None and stop <= consumer_level:
 
379
                return False
 
380
            return True
 
381
        else:
 
382
            return level >= consumer_level
 
383
 
 
384
    #@classmethod
 
385
    def level_for_integer(cls, level):
 
386
        levels = cls.LEVELS
 
387
        if level < 0:
 
388
            return levels[0]
 
389
        if level >= len(levels):
 
390
            return levels[-1]
 
391
        return levels[level]
 
392
 
 
393
    level_for_integer = classmethod(level_for_integer)
 
394
 
 
395
# create a silent logger just to prevent this from being undefined
 
396
# will be overridden with requested verbosity main() is called.
 
397
logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
 
398
 
 
399
def mkdir(path):
 
400
    if not os.path.exists(path):
 
401
        logger.info('Creating %s', path)
 
402
        os.makedirs(path)
 
403
    else:
 
404
        logger.info('Directory %s already exists', path)
 
405
 
 
406
def copyfileordir(src, dest):
 
407
    if os.path.isdir(src):
 
408
        shutil.copytree(src, dest, True)
 
409
    else:
 
410
        shutil.copy2(src, dest)
 
411
 
 
412
def copyfile(src, dest, symlink=True):
 
413
    if not os.path.exists(src):
 
414
        # Some bad symlink in the src
 
415
        logger.warn('Cannot find file %s (bad symlink)', src)
 
416
        return
 
417
    if os.path.exists(dest):
 
418
        logger.debug('File %s already exists', dest)
 
419
        return
 
420
    if not os.path.exists(os.path.dirname(dest)):
 
421
        logger.info('Creating parent directories for %s' % os.path.dirname(dest))
 
422
        os.makedirs(os.path.dirname(dest))
 
423
    if not os.path.islink(src):
 
424
        srcpath = os.path.abspath(src)
 
425
    else:
 
426
        srcpath = os.readlink(src)
 
427
    if symlink and hasattr(os, 'symlink') and not is_win:
 
428
        logger.info('Symlinking %s', dest)
 
429
        try:
 
430
            os.symlink(srcpath, dest)
 
431
        except (OSError, NotImplementedError):
 
432
            logger.info('Symlinking failed, copying to %s', dest)
 
433
            copyfileordir(src, dest)
 
434
    else:
 
435
        logger.info('Copying to %s', dest)
 
436
        copyfileordir(src, dest)
 
437
 
 
438
def writefile(dest, content, overwrite=True):
 
439
    if not os.path.exists(dest):
 
440
        logger.info('Writing %s', dest)
 
441
        f = open(dest, 'wb')
 
442
        f.write(content.encode('utf-8'))
 
443
        f.close()
 
444
        return
 
445
    else:
 
446
        f = open(dest, 'rb')
 
447
        c = f.read()
 
448
        f.close()
 
449
        if c != content.encode("utf-8"):
 
450
            if not overwrite:
 
451
                logger.notify('File %s exists with different content; not overwriting', dest)
 
452
                return
 
453
            logger.notify('Overwriting %s with new content', dest)
 
454
            f = open(dest, 'wb')
 
455
            f.write(content.encode('utf-8'))
 
456
            f.close()
 
457
        else:
 
458
            logger.info('Content %s already in place', dest)
 
459
 
 
460
def rmtree(dir):
 
461
    if os.path.exists(dir):
 
462
        logger.notify('Deleting tree %s', dir)
 
463
        shutil.rmtree(dir)
 
464
    else:
 
465
        logger.info('Do not need to delete %s; already gone', dir)
 
466
 
 
467
def make_exe(fn):
 
468
    if hasattr(os, 'chmod'):
 
469
        oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777
 
470
        newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777
 
471
        os.chmod(fn, newmode)
 
472
        logger.info('Changed mode of %s to %s', fn, oct(newmode))
 
473
 
 
474
def _find_file(filename, dirs):
 
475
    for dir in reversed(dirs):
 
476
        if os.path.exists(join(dir, filename)):
 
477
            return join(dir, filename)
 
478
    return filename
 
479
 
 
480
def _install_req(py_executable, unzip=False, distribute=False,
 
481
                 search_dirs=None, never_download=False):
 
482
 
 
483
    if search_dirs is None:
 
484
        search_dirs = file_search_dirs()
 
485
 
 
486
    if not distribute:
 
487
        setup_fn = 'setuptools-0.6c11-py%s.egg' % sys.version[:3]
 
488
        project_name = 'setuptools'
 
489
        bootstrap_script = EZ_SETUP_PY
 
490
        source = None
 
491
    else:
 
492
        setup_fn = None
 
493
        source = 'distribute-0.6.27.tar.gz'
 
494
        project_name = 'distribute'
 
495
        bootstrap_script = DISTRIBUTE_SETUP_PY
 
496
 
 
497
    if setup_fn is not None:
 
498
        setup_fn = _find_file(setup_fn, search_dirs)
 
499
 
 
500
    if source is not None:
 
501
        source = _find_file(source, search_dirs)
 
502
 
 
503
    if is_jython and os._name == 'nt':
 
504
        # Jython's .bat sys.executable can't handle a command line
 
505
        # argument with newlines
 
506
        fd, ez_setup = tempfile.mkstemp('.py')
 
507
        os.write(fd, bootstrap_script)
 
508
        os.close(fd)
 
509
        cmd = [py_executable, ez_setup]
 
510
    else:
 
511
        cmd = [py_executable, '-c', bootstrap_script]
 
512
    if unzip:
 
513
        cmd.append('--always-unzip')
 
514
    env = {}
 
515
    remove_from_env = []
 
516
    if logger.stdout_level_matches(logger.DEBUG):
 
517
        cmd.append('-v')
 
518
 
 
519
    old_chdir = os.getcwd()
 
520
    if setup_fn is not None and os.path.exists(setup_fn):
 
521
        logger.info('Using existing %s egg: %s' % (project_name, setup_fn))
 
522
        cmd.append(setup_fn)
 
523
        if os.environ.get('PYTHONPATH'):
 
524
            env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH']
 
525
        else:
 
526
            env['PYTHONPATH'] = setup_fn
 
527
    else:
 
528
        # the source is found, let's chdir
 
529
        if source is not None and os.path.exists(source):
 
530
            logger.info('Using existing %s egg: %s' % (project_name, source))
 
531
            os.chdir(os.path.dirname(source))
 
532
            # in this case, we want to be sure that PYTHONPATH is unset (not
 
533
            # just empty, really unset), else CPython tries to import the
 
534
            # site.py that it's in virtualenv_support
 
535
            remove_from_env.append('PYTHONPATH')
 
536
        else:
 
537
            if never_download:
 
538
                logger.fatal("Can't find any local distributions of %s to install "
 
539
                             "and --never-download is set.  Either re-run virtualenv "
 
540
                             "without the --never-download option, or place a %s "
 
541
                             "distribution (%s) in one of these "
 
542
                             "locations: %r" % (project_name, project_name,
 
543
                                                setup_fn or source,
 
544
                                                search_dirs))
 
545
                sys.exit(1)
 
546
 
 
547
            logger.info('No %s egg found; downloading' % project_name)
 
548
        cmd.extend(['--always-copy', '-U', project_name])
 
549
    logger.start_progress('Installing %s...' % project_name)
 
550
    logger.indent += 2
 
551
    cwd = None
 
552
    if project_name == 'distribute':
 
553
        env['DONT_PATCH_SETUPTOOLS'] = 'true'
 
554
 
 
555
    def _filter_ez_setup(line):
 
556
        return filter_ez_setup(line, project_name)
 
557
 
 
558
    if not os.access(os.getcwd(), os.W_OK):
 
559
        cwd = tempfile.mkdtemp()
 
560
        if source is not None and os.path.exists(source):
 
561
            # the current working dir is hostile, let's copy the
 
562
            # tarball to a temp dir
 
563
            target = os.path.join(cwd, os.path.split(source)[-1])
 
564
            shutil.copy(source, target)
 
565
    try:
 
566
        call_subprocess(cmd, show_stdout=False,
 
567
                        filter_stdout=_filter_ez_setup,
 
568
                        extra_env=env,
 
569
                        remove_from_env=remove_from_env,
 
570
                        cwd=cwd)
 
571
    finally:
 
572
        logger.indent -= 2
 
573
        logger.end_progress()
 
574
        if cwd is not None:
 
575
            shutil.rmtree(cwd)
 
576
        if os.getcwd() != old_chdir:
 
577
            os.chdir(old_chdir)
 
578
        if is_jython and os._name == 'nt':
 
579
            os.remove(ez_setup)
 
580
 
 
581
def file_search_dirs():
 
582
    here = os.path.dirname(os.path.abspath(__file__))
 
583
    dirs = ['.', here,
 
584
            join(here, 'virtualenv_support')]
 
585
    if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
 
586
        # Probably some boot script; just in case virtualenv is installed...
 
587
        try:
 
588
            import virtualenv
 
589
        except ImportError:
 
590
            pass
 
591
        else:
 
592
            dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
 
593
    return [d for d in dirs if os.path.isdir(d)]
 
594
 
 
595
def install_setuptools(py_executable, unzip=False,
 
596
                       search_dirs=None, never_download=False):
 
597
    _install_req(py_executable, unzip,
 
598
                 search_dirs=search_dirs, never_download=never_download)
 
599
 
 
600
def install_distribute(py_executable, unzip=False,
 
601
                       search_dirs=None, never_download=False):
 
602
    _install_req(py_executable, unzip, distribute=True,
 
603
                 search_dirs=search_dirs, never_download=never_download)
 
604
 
 
605
_pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I)
 
606
def install_pip(py_executable, search_dirs=None, never_download=False):
 
607
    if search_dirs is None:
 
608
        search_dirs = file_search_dirs()
 
609
 
 
610
    filenames = []
 
611
    for dir in search_dirs:
 
612
        filenames.extend([join(dir, fn) for fn in os.listdir(dir)
 
613
                          if _pip_re.search(fn)])
 
614
    filenames = [(os.path.basename(filename).lower(), i, filename) for i, filename in enumerate(filenames)]
 
615
    filenames.sort()
 
616
    filenames = [filename for basename, i, filename in filenames]
 
617
    if not filenames:
 
618
        filename = 'pip'
 
619
    else:
 
620
        filename = filenames[-1]
 
621
    easy_install_script = 'easy_install'
 
622
    if sys.platform == 'win32':
 
623
        easy_install_script = 'easy_install-script.py'
 
624
    # There's two subtle issues here when invoking easy_install.
 
625
    # 1. On unix-like systems the easy_install script can *only* be executed
 
626
    #    directly if its full filesystem path is no longer than 78 characters.
 
627
    # 2. A work around to [1] is to use the `python path/to/easy_install foo`
 
628
    #    pattern, but that breaks if the path contains non-ASCII characters, as
 
629
    #    you can't put the file encoding declaration before the shebang line.
 
630
    # The solution is to use Python's -x flag to skip the first line of the
 
631
    # script (and any ASCII decoding errors that may have occurred in that line)
 
632
    cmd = [py_executable, '-x', join(os.path.dirname(py_executable), easy_install_script), filename]
 
633
    # jython and pypy don't yet support -x
 
634
    if is_jython or is_pypy:
 
635
        cmd.remove('-x')
 
636
    if filename == 'pip':
 
637
        if never_download:
 
638
            logger.fatal("Can't find any local distributions of pip to install "
 
639
                         "and --never-download is set.  Either re-run virtualenv "
 
640
                         "without the --never-download option, or place a pip "
 
641
                         "source distribution (zip/tar.gz/tar.bz2) in one of these "
 
642
                         "locations: %r" % search_dirs)
 
643
            sys.exit(1)
 
644
        logger.info('Installing pip from network...')
 
645
    else:
 
646
        logger.info('Installing existing %s distribution: %s' % (
 
647
                os.path.basename(filename), filename))
 
648
    logger.start_progress('Installing pip...')
 
649
    logger.indent += 2
 
650
    def _filter_setup(line):
 
651
        return filter_ez_setup(line, 'pip')
 
652
    try:
 
653
        call_subprocess(cmd, show_stdout=False,
 
654
                        filter_stdout=_filter_setup)
 
655
    finally:
 
656
        logger.indent -= 2
 
657
        logger.end_progress()
 
658
 
 
659
def filter_ez_setup(line, project_name='setuptools'):
 
660
    if not line.strip():
 
661
        return Logger.DEBUG
 
662
    if project_name == 'distribute':
 
663
        for prefix in ('Extracting', 'Now working', 'Installing', 'Before',
 
664
                       'Scanning', 'Setuptools', 'Egg', 'Already',
 
665
                       'running', 'writing', 'reading', 'installing',
 
666
                       'creating', 'copying', 'byte-compiling', 'removing',
 
667
                       'Processing'):
 
668
            if line.startswith(prefix):
 
669
                return Logger.DEBUG
 
670
        return Logger.DEBUG
 
671
    for prefix in ['Reading ', 'Best match', 'Processing setuptools',
 
672
                   'Copying setuptools', 'Adding setuptools',
 
673
                   'Installing ', 'Installed ']:
 
674
        if line.startswith(prefix):
 
675
            return Logger.DEBUG
 
676
    return Logger.INFO
 
677
 
 
678
 
 
679
class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
 
680
    """
 
681
    Custom help formatter for use in ConfigOptionParser that updates
 
682
    the defaults before expanding them, allowing them to show up correctly
 
683
    in the help listing
 
684
    """
 
685
    def expand_default(self, option):
 
686
        if self.parser is not None:
 
687
            self.parser.update_defaults(self.parser.defaults)
 
688
        return optparse.IndentedHelpFormatter.expand_default(self, option)
 
689
 
 
690
 
 
691
class ConfigOptionParser(optparse.OptionParser):
 
692
    """
 
693
    Custom option parser which updates its defaults by by checking the
 
694
    configuration files and environmental variables
 
695
    """
 
696
    def __init__(self, *args, **kwargs):
 
697
        self.config = ConfigParser.RawConfigParser()
 
698
        self.files = self.get_config_files()
 
699
        self.config.read(self.files)
 
700
        optparse.OptionParser.__init__(self, *args, **kwargs)
 
701
 
 
702
    def get_config_files(self):
 
703
        config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False)
 
704
        if config_file and os.path.exists(config_file):
 
705
            return [config_file]
 
706
        return [default_config_file]
 
707
 
 
708
    def update_defaults(self, defaults):
 
709
        """
 
710
        Updates the given defaults with values from the config files and
 
711
        the environ. Does a little special handling for certain types of
 
712
        options (lists).
 
713
        """
 
714
        # Then go and look for the other sources of configuration:
 
715
        config = {}
 
716
        # 1. config files
 
717
        config.update(dict(self.get_config_section('virtualenv')))
 
718
        # 2. environmental variables
 
719
        config.update(dict(self.get_environ_vars()))
 
720
        # Then set the options with those values
 
721
        for key, val in config.items():
 
722
            key = key.replace('_', '-')
 
723
            if not key.startswith('--'):
 
724
                key = '--%s' % key  # only prefer long opts
 
725
            option = self.get_option(key)
 
726
            if option is not None:
 
727
                # ignore empty values
 
728
                if not val:
 
729
                    continue
 
730
                # handle multiline configs
 
731
                if option.action == 'append':
 
732
                    val = val.split()
 
733
                else:
 
734
                    option.nargs = 1
 
735
                if option.action in ('store_true', 'store_false', 'count'):
 
736
                    val = strtobool(val)
 
737
                try:
 
738
                    val = option.convert_value(key, val)
 
739
                except optparse.OptionValueError:
 
740
                    e = sys.exc_info()[1]
 
741
                    print("An error occured during configuration: %s" % e)
 
742
                    sys.exit(3)
 
743
                defaults[option.dest] = val
 
744
        return defaults
 
745
 
 
746
    def get_config_section(self, name):
 
747
        """
 
748
        Get a section of a configuration
 
749
        """
 
750
        if self.config.has_section(name):
 
751
            return self.config.items(name)
 
752
        return []
 
753
 
 
754
    def get_environ_vars(self, prefix='VIRTUALENV_'):
 
755
        """
 
756
        Returns a generator with all environmental vars with prefix VIRTUALENV
 
757
        """
 
758
        for key, val in os.environ.items():
 
759
            if key.startswith(prefix):
 
760
                yield (key.replace(prefix, '').lower(), val)
 
761
 
 
762
    def get_default_values(self):
 
763
        """
 
764
        Overridding to make updating the defaults after instantiation of
 
765
        the option parser possible, update_defaults() does the dirty work.
 
766
        """
 
767
        if not self.process_default_values:
 
768
            # Old, pre-Optik 1.5 behaviour.
 
769
            return optparse.Values(self.defaults)
 
770
 
 
771
        defaults = self.update_defaults(self.defaults.copy())  # ours
 
772
        for option in self._get_all_options():
 
773
            default = defaults.get(option.dest)
 
774
            if isinstance(default, basestring):
 
775
                opt_str = option.get_opt_string()
 
776
                defaults[option.dest] = option.check_value(opt_str, default)
 
777
        return optparse.Values(defaults)
 
778
 
 
779
 
 
780
def main():
 
781
    parser = ConfigOptionParser(
 
782
        version=virtualenv_version,
 
783
        usage="%prog [OPTIONS] DEST_DIR",
 
784
        formatter=UpdatingDefaultsHelpFormatter())
 
785
 
 
786
    parser.add_option(
 
787
        '-v', '--verbose',
 
788
        action='count',
 
789
        dest='verbose',
 
790
        default=0,
 
791
        help="Increase verbosity")
 
792
 
 
793
    parser.add_option(
 
794
        '-q', '--quiet',
 
795
        action='count',
 
796
        dest='quiet',
 
797
        default=0,
 
798
        help='Decrease verbosity')
 
799
 
 
800
    parser.add_option(
 
801
        '-p', '--python',
 
802
        dest='python',
 
803
        metavar='PYTHON_EXE',
 
804
        help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
 
805
        'interpreter to create the new environment.  The default is the interpreter that '
 
806
        'virtualenv was installed with (%s)' % sys.executable)
 
807
 
 
808
    parser.add_option(
 
809
        '--clear',
 
810
        dest='clear',
 
811
        action='store_true',
 
812
        help="Clear out the non-root install and start from scratch")
 
813
 
 
814
    parser.set_defaults(system_site_packages=False)
 
815
    parser.add_option(
 
816
        '--no-site-packages',
 
817
        dest='system_site_packages',
 
818
        action='store_false',
 
819
        help="Don't give access to the global site-packages dir to the "
 
820
             "virtual environment (default)")
 
821
 
 
822
    parser.add_option(
 
823
        '--system-site-packages',
 
824
        dest='system_site_packages',
 
825
        action='store_true',
 
826
        help="Give access to the global site-packages dir to the "
 
827
             "virtual environment")
 
828
 
 
829
    parser.add_option(
 
830
        '--unzip-setuptools',
 
831
        dest='unzip_setuptools',
 
832
        action='store_true',
 
833
        help="Unzip Setuptools or Distribute when installing it")
 
834
 
 
835
    parser.add_option(
 
836
        '--relocatable',
 
837
        dest='relocatable',
 
838
        action='store_true',
 
839
        help='Make an EXISTING virtualenv environment relocatable.  '
 
840
        'This fixes up scripts and makes all .pth files relative')
 
841
 
 
842
    parser.add_option(
 
843
        '--distribute', '--use-distribute',  # the second option is for legacy reasons here. Hi Kenneth!
 
844
        dest='use_distribute',
 
845
        action='store_true',
 
846
        help='Use Distribute instead of Setuptools. Set environ variable '
 
847
        'VIRTUALENV_DISTRIBUTE to make it the default ')
 
848
 
 
849
    default_search_dirs = file_search_dirs()
 
850
    parser.add_option(
 
851
        '--extra-search-dir',
 
852
        dest="search_dirs",
 
853
        action="append",
 
854
        default=default_search_dirs,
 
855
        help="Directory to look for setuptools/distribute/pip distributions in. "
 
856
        "You can add any number of additional --extra-search-dir paths.")
 
857
 
 
858
    parser.add_option(
 
859
        '--never-download',
 
860
        dest="never_download",
 
861
        action="store_true",
 
862
        help="Never download anything from the network.  Instead, virtualenv will fail "
 
863
        "if local distributions of setuptools/distribute/pip are not present.")
 
864
 
 
865
    parser.add_option(
 
866
        '--prompt',
 
867
        dest='prompt',
 
868
        help='Provides an alternative prompt prefix for this environment')
 
869
 
 
870
    if 'extend_parser' in globals():
 
871
        extend_parser(parser)
 
872
 
 
873
    options, args = parser.parse_args()
 
874
 
 
875
    global logger
 
876
 
 
877
    if 'adjust_options' in globals():
 
878
        adjust_options(options, args)
 
879
 
 
880
    verbosity = options.verbose - options.quiet
 
881
    logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)])
 
882
 
 
883
    if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
 
884
        env = os.environ.copy()
 
885
        interpreter = resolve_interpreter(options.python)
 
886
        if interpreter == sys.executable:
 
887
            logger.warn('Already using interpreter %s' % interpreter)
 
888
        else:
 
889
            logger.notify('Running virtualenv with interpreter %s' % interpreter)
 
890
            env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
 
891
            file = __file__
 
892
            if file.endswith('.pyc'):
 
893
                file = file[:-1]
 
894
            popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
 
895
            raise SystemExit(popen.wait())
 
896
 
 
897
    # Force --distribute on Python 3, since setuptools is not available.
 
898
    if majver > 2:
 
899
        options.use_distribute = True
 
900
 
 
901
    if os.environ.get('PYTHONDONTWRITEBYTECODE') and not options.use_distribute:
 
902
        print(
 
903
            "The PYTHONDONTWRITEBYTECODE environment variable is "
 
904
            "not compatible with setuptools. Either use --distribute "
 
905
            "or unset PYTHONDONTWRITEBYTECODE.")
 
906
        sys.exit(2)
 
907
    if not args:
 
908
        print('You must provide a DEST_DIR')
 
909
        parser.print_help()
 
910
        sys.exit(2)
 
911
    if len(args) > 1:
 
912
        print('There must be only one argument: DEST_DIR (you gave %s)' % (
 
913
            ' '.join(args)))
 
914
        parser.print_help()
 
915
        sys.exit(2)
 
916
 
 
917
    home_dir = args[0]
 
918
 
 
919
    if os.environ.get('WORKING_ENV'):
 
920
        logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
 
921
        logger.fatal('Please deactivate your workingenv, then re-run this script')
 
922
        sys.exit(3)
 
923
 
 
924
    if 'PYTHONHOME' in os.environ:
 
925
        logger.warn('PYTHONHOME is set.  You *must* activate the virtualenv before using it')
 
926
        del os.environ['PYTHONHOME']
 
927
 
 
928
    if options.relocatable:
 
929
        make_environment_relocatable(home_dir)
 
930
        return
 
931
 
 
932
    create_environment(home_dir,
 
933
                       site_packages=options.system_site_packages,
 
934
                       clear=options.clear,
 
935
                       unzip_setuptools=options.unzip_setuptools,
 
936
                       use_distribute=options.use_distribute,
 
937
                       prompt=options.prompt,
 
938
                       search_dirs=options.search_dirs,
 
939
                       never_download=options.never_download)
 
940
    if 'after_install' in globals():
 
941
        after_install(options, home_dir)
 
942
 
 
943
def call_subprocess(cmd, show_stdout=True,
 
944
                    filter_stdout=None, cwd=None,
 
945
                    raise_on_returncode=True, extra_env=None,
 
946
                    remove_from_env=None):
 
947
    cmd_parts = []
 
948
    for part in cmd:
 
949
        if len(part) > 45:
 
950
            part = part[:20]+"..."+part[-20:]
 
951
        if ' ' in part or '\n' in part or '"' in part or "'" in part:
 
952
            part = '"%s"' % part.replace('"', '\\"')
 
953
        if hasattr(part, 'decode'):
 
954
            try:
 
955
                part = part.decode(sys.getdefaultencoding())
 
956
            except UnicodeDecodeError:
 
957
                part = part.decode(sys.getfilesystemencoding())
 
958
        cmd_parts.append(part)
 
959
    cmd_desc = ' '.join(cmd_parts)
 
960
    if show_stdout:
 
961
        stdout = None
 
962
    else:
 
963
        stdout = subprocess.PIPE
 
964
    logger.debug("Running command %s" % cmd_desc)
 
965
    if extra_env or remove_from_env:
 
966
        env = os.environ.copy()
 
967
        if extra_env:
 
968
            env.update(extra_env)
 
969
        if remove_from_env:
 
970
            for varname in remove_from_env:
 
971
                env.pop(varname, None)
 
972
    else:
 
973
        env = None
 
974
    try:
 
975
        proc = subprocess.Popen(
 
976
            cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
 
977
            cwd=cwd, env=env)
 
978
    except Exception:
 
979
        e = sys.exc_info()[1]
 
980
        logger.fatal(
 
981
            "Error %s while executing command %s" % (e, cmd_desc))
 
982
        raise
 
983
    all_output = []
 
984
    if stdout is not None:
 
985
        stdout = proc.stdout
 
986
        encoding = sys.getdefaultencoding()
 
987
        fs_encoding = sys.getfilesystemencoding()
 
988
        while 1:
 
989
            line = stdout.readline()
 
990
            try:
 
991
                line = line.decode(encoding)
 
992
            except UnicodeDecodeError:
 
993
                line = line.decode(fs_encoding)
 
994
            if not line:
 
995
                break
 
996
            line = line.rstrip()
 
997
            all_output.append(line)
 
998
            if filter_stdout:
 
999
                level = filter_stdout(line)
 
1000
                if isinstance(level, tuple):
 
1001
                    level, line = level
 
1002
                logger.log(level, line)
 
1003
                if not logger.stdout_level_matches(level):
 
1004
                    logger.show_progress()
 
1005
            else:
 
1006
                logger.info(line)
 
1007
    else:
 
1008
        proc.communicate()
 
1009
    proc.wait()
 
1010
    if proc.returncode:
 
1011
        if raise_on_returncode:
 
1012
            if all_output:
 
1013
                logger.notify('Complete output from command %s:' % cmd_desc)
 
1014
                logger.notify('\n'.join(all_output) + '\n----------------------------------------')
 
1015
            raise OSError(
 
1016
                "Command %s failed with error code %s"
 
1017
                % (cmd_desc, proc.returncode))
 
1018
        else:
 
1019
            logger.warn(
 
1020
                "Command %s had error code %s"
 
1021
                % (cmd_desc, proc.returncode))
 
1022
 
 
1023
 
 
1024
def create_environment(home_dir, site_packages=False, clear=False,
 
1025
                       unzip_setuptools=False, use_distribute=False,
 
1026
                       prompt=None, search_dirs=None, never_download=False):
 
1027
    """
 
1028
    Creates a new environment in ``home_dir``.
 
1029
 
 
1030
    If ``site_packages`` is true, then the global ``site-packages/``
 
1031
    directory will be on the path.
 
1032
 
 
1033
    If ``clear`` is true (default False) then the environment will
 
1034
    first be cleared.
 
1035
    """
 
1036
    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
 
1037
 
 
1038
    py_executable = os.path.abspath(install_python(
 
1039
        home_dir, lib_dir, inc_dir, bin_dir,
 
1040
        site_packages=site_packages, clear=clear))
 
1041
 
 
1042
    install_distutils(home_dir)
 
1043
 
 
1044
    if use_distribute:
 
1045
        install_distribute(py_executable, unzip=unzip_setuptools,
 
1046
                           search_dirs=search_dirs, never_download=never_download)
 
1047
    else:
 
1048
        install_setuptools(py_executable, unzip=unzip_setuptools,
 
1049
                           search_dirs=search_dirs, never_download=never_download)
 
1050
 
 
1051
    install_pip(py_executable, search_dirs=search_dirs, never_download=never_download)
 
1052
 
 
1053
    install_activate(home_dir, bin_dir, prompt)
 
1054
 
 
1055
def path_locations(home_dir):
 
1056
    """Return the path locations for the environment (where libraries are,
 
1057
    where scripts go, etc)"""
 
1058
    # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
 
1059
    # prefix arg is broken: http://bugs.python.org/issue3386
 
1060
    if sys.platform == 'win32':
 
1061
        # Windows has lots of problems with executables with spaces in
 
1062
        # the name; this function will remove them (using the ~1
 
1063
        # format):
 
1064
        mkdir(home_dir)
 
1065
        if ' ' in home_dir:
 
1066
            try:
 
1067
                import win32api
 
1068
            except ImportError:
 
1069
                print('Error: the path "%s" has a space in it' % home_dir)
 
1070
                print('To handle these kinds of paths, the win32api module must be installed:')
 
1071
                print('  http://sourceforge.net/projects/pywin32/')
 
1072
                sys.exit(3)
 
1073
            home_dir = win32api.GetShortPathName(home_dir)
 
1074
        lib_dir = join(home_dir, 'Lib')
 
1075
        inc_dir = join(home_dir, 'Include')
 
1076
        bin_dir = join(home_dir, 'Scripts')
 
1077
    if is_jython:
 
1078
        lib_dir = join(home_dir, 'Lib')
 
1079
        inc_dir = join(home_dir, 'Include')
 
1080
        bin_dir = join(home_dir, 'bin')
 
1081
    elif is_pypy:
 
1082
        lib_dir = home_dir
 
1083
        inc_dir = join(home_dir, 'include')
 
1084
        bin_dir = join(home_dir, 'bin')
 
1085
    elif sys.platform != 'win32':
 
1086
        lib_dir = join(home_dir, 'lib', py_version)
 
1087
        inc_dir = join(home_dir, 'include', py_version + abiflags)
 
1088
        bin_dir = join(home_dir, 'bin')
 
1089
    return home_dir, lib_dir, inc_dir, bin_dir
 
1090
 
 
1091
 
 
1092
def change_prefix(filename, dst_prefix):
 
1093
    prefixes = [sys.prefix]
 
1094
 
 
1095
    if sys.platform == "darwin":
 
1096
        prefixes.extend((
 
1097
            os.path.join("/Library/Python", sys.version[:3], "site-packages"),
 
1098
            os.path.join(sys.prefix, "Extras", "lib", "python"),
 
1099
            os.path.join("~", "Library", "Python", sys.version[:3], "site-packages")))
 
1100
 
 
1101
    if hasattr(sys, 'real_prefix'):
 
1102
        prefixes.append(sys.real_prefix)
 
1103
    prefixes = list(map(os.path.abspath, prefixes))
 
1104
    filename = os.path.abspath(filename)
 
1105
    for src_prefix in prefixes:
 
1106
        if filename.startswith(src_prefix):
 
1107
            _, relpath = filename.split(src_prefix, 1)
 
1108
            if src_prefix != os.sep: # sys.prefix == "/"
 
1109
                assert relpath[0] == os.sep
 
1110
                relpath = relpath[1:]
 
1111
            return join(dst_prefix, relpath)
 
1112
    assert False, "Filename %s does not start with any of these prefixes: %s" % \
 
1113
        (filename, prefixes)
 
1114
 
 
1115
def copy_required_modules(dst_prefix):
 
1116
    import imp
 
1117
    # If we are running under -p, we need to remove the current
 
1118
    # directory from sys.path temporarily here, so that we
 
1119
    # definitely get the modules from the site directory of
 
1120
    # the interpreter we are running under, not the one
 
1121
    # virtualenv.py is installed under (which might lead to py2/py3
 
1122
    # incompatibility issues)
 
1123
    _prev_sys_path = sys.path
 
1124
    if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
 
1125
        sys.path = sys.path[1:]
 
1126
    try:
 
1127
        for modname in REQUIRED_MODULES:
 
1128
            if modname in sys.builtin_module_names:
 
1129
                logger.info("Ignoring built-in bootstrap module: %s" % modname)
 
1130
                continue
 
1131
            try:
 
1132
                f, filename, _ = imp.find_module(modname)
 
1133
            except ImportError:
 
1134
                logger.info("Cannot import bootstrap module: %s" % modname)
 
1135
            else:
 
1136
                if f is not None:
 
1137
                    f.close()
 
1138
                dst_filename = change_prefix(filename, dst_prefix)
 
1139
                copyfile(filename, dst_filename)
 
1140
                if filename.endswith('.pyc'):
 
1141
                    pyfile = filename[:-1]
 
1142
                    if os.path.exists(pyfile):
 
1143
                        copyfile(pyfile, dst_filename[:-1])
 
1144
    finally:
 
1145
        sys.path = _prev_sys_path
 
1146
 
 
1147
def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
 
1148
    """Install just the base environment, no distutils patches etc"""
 
1149
    if sys.executable.startswith(bin_dir):
 
1150
        print('Please use the *system* python to run this script')
 
1151
        return
 
1152
 
 
1153
    if clear:
 
1154
        rmtree(lib_dir)
 
1155
        ## FIXME: why not delete it?
 
1156
        ## Maybe it should delete everything with #!/path/to/venv/python in it
 
1157
        logger.notify('Not deleting %s', bin_dir)
 
1158
 
 
1159
    if hasattr(sys, 'real_prefix'):
 
1160
        logger.notify('Using real prefix %r' % sys.real_prefix)
 
1161
        prefix = sys.real_prefix
 
1162
    else:
 
1163
        prefix = sys.prefix
 
1164
    mkdir(lib_dir)
 
1165
    fix_lib64(lib_dir)
 
1166
    stdlib_dirs = [os.path.dirname(os.__file__)]
 
1167
    if sys.platform == 'win32':
 
1168
        stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
 
1169
    elif sys.platform == 'darwin':
 
1170
        stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
 
1171
    if hasattr(os, 'symlink'):
 
1172
        logger.info('Symlinking Python bootstrap modules')
 
1173
    else:
 
1174
        logger.info('Copying Python bootstrap modules')
 
1175
    logger.indent += 2
 
1176
    try:
 
1177
        # copy required files...
 
1178
        for stdlib_dir in stdlib_dirs:
 
1179
            if not os.path.isdir(stdlib_dir):
 
1180
                continue
 
1181
            for fn in os.listdir(stdlib_dir):
 
1182
                bn = os.path.splitext(fn)[0]
 
1183
                if fn != 'site-packages' and bn in REQUIRED_FILES:
 
1184
                    copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
 
1185
        # ...and modules
 
1186
        copy_required_modules(home_dir)
 
1187
    finally:
 
1188
        logger.indent -= 2
 
1189
    mkdir(join(lib_dir, 'site-packages'))
 
1190
    import site
 
1191
    site_filename = site.__file__
 
1192
    if site_filename.endswith('.pyc'):
 
1193
        site_filename = site_filename[:-1]
 
1194
    elif site_filename.endswith('$py.class'):
 
1195
        site_filename = site_filename.replace('$py.class', '.py')
 
1196
    site_filename_dst = change_prefix(site_filename, home_dir)
 
1197
    site_dir = os.path.dirname(site_filename_dst)
 
1198
    writefile(site_filename_dst, SITE_PY)
 
1199
    writefile(join(site_dir, 'orig-prefix.txt'), prefix)
 
1200
    site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
 
1201
    if not site_packages:
 
1202
        writefile(site_packages_filename, '')
 
1203
    else:
 
1204
        if os.path.exists(site_packages_filename):
 
1205
            logger.info('Deleting %s' % site_packages_filename)
 
1206
            os.unlink(site_packages_filename)
 
1207
 
 
1208
    if is_pypy or is_win:
 
1209
        stdinc_dir = join(prefix, 'include')
 
1210
    else:
 
1211
        stdinc_dir = join(prefix, 'include', py_version + abiflags)
 
1212
    if os.path.exists(stdinc_dir):
 
1213
        copyfile(stdinc_dir, inc_dir)
 
1214
    else:
 
1215
        logger.debug('No include dir %s' % stdinc_dir)
 
1216
 
 
1217
    # pypy never uses exec_prefix, just ignore it
 
1218
    if sys.exec_prefix != prefix and not is_pypy:
 
1219
        if sys.platform == 'win32':
 
1220
            exec_dir = join(sys.exec_prefix, 'lib')
 
1221
        elif is_jython:
 
1222
            exec_dir = join(sys.exec_prefix, 'Lib')
 
1223
        else:
 
1224
            exec_dir = join(sys.exec_prefix, 'lib', py_version)
 
1225
        for fn in os.listdir(exec_dir):
 
1226
            copyfile(join(exec_dir, fn), join(lib_dir, fn))
 
1227
 
 
1228
    if is_jython:
 
1229
        # Jython has either jython-dev.jar and javalib/ dir, or just
 
1230
        # jython.jar
 
1231
        for name in 'jython-dev.jar', 'javalib', 'jython.jar':
 
1232
            src = join(prefix, name)
 
1233
            if os.path.exists(src):
 
1234
                copyfile(src, join(home_dir, name))
 
1235
        # XXX: registry should always exist after Jython 2.5rc1
 
1236
        src = join(prefix, 'registry')
 
1237
        if os.path.exists(src):
 
1238
            copyfile(src, join(home_dir, 'registry'), symlink=False)
 
1239
        copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
 
1240
                 symlink=False)
 
1241
 
 
1242
    mkdir(bin_dir)
 
1243
    py_executable = join(bin_dir, os.path.basename(sys.executable))
 
1244
    if 'Python.framework' in prefix:
 
1245
        if re.search(r'/Python(?:-32|-64)*$', py_executable):
 
1246
            # The name of the python executable is not quite what
 
1247
            # we want, rename it.
 
1248
            py_executable = os.path.join(
 
1249
                    os.path.dirname(py_executable), 'python')
 
1250
 
 
1251
    logger.notify('New %s executable in %s', expected_exe, py_executable)
 
1252
    pcbuild_dir = os.path.dirname(sys.executable)
 
1253
    pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth')
 
1254
    if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')):
 
1255
        logger.notify('Detected python running from build directory %s', pcbuild_dir)
 
1256
        logger.notify('Writing .pth file linking to build directory for *.pyd files')
 
1257
        writefile(pyd_pth, pcbuild_dir)
 
1258
    else:
 
1259
        pcbuild_dir = None
 
1260
        if os.path.exists(pyd_pth):
 
1261
            logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth)
 
1262
            os.unlink(pyd_pth)
 
1263
 
 
1264
    if sys.executable != py_executable:
 
1265
        ## FIXME: could I just hard link?
 
1266
        executable = sys.executable
 
1267
        if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'):
 
1268
            # Cygwin misreports sys.executable sometimes
 
1269
            executable += '.exe'
 
1270
            py_executable += '.exe'
 
1271
            logger.info('Executable actually exists in %s' % executable)
 
1272
        shutil.copyfile(executable, py_executable)
 
1273
        make_exe(py_executable)
 
1274
        if sys.platform == 'win32' or sys.platform == 'cygwin':
 
1275
            pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
 
1276
            if os.path.exists(pythonw):
 
1277
                logger.info('Also created pythonw.exe')
 
1278
                shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
 
1279
            python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe')
 
1280
            python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe')
 
1281
            if os.path.exists(python_d):
 
1282
                logger.info('Also created python_d.exe')
 
1283
                shutil.copyfile(python_d, python_d_dest)
 
1284
            elif os.path.exists(python_d_dest):
 
1285
                logger.info('Removed python_d.exe as it is no longer at the source')
 
1286
                os.unlink(python_d_dest)
 
1287
            # we need to copy the DLL to enforce that windows will load the correct one.
 
1288
            # may not exist if we are cygwin.
 
1289
            py_executable_dll = 'python%s%s.dll' % (
 
1290
                sys.version_info[0], sys.version_info[1])
 
1291
            py_executable_dll_d = 'python%s%s_d.dll' % (
 
1292
                sys.version_info[0], sys.version_info[1])
 
1293
            pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll)
 
1294
            pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d)
 
1295
            pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d)
 
1296
            if os.path.exists(pythondll):
 
1297
                logger.info('Also created %s' % py_executable_dll)
 
1298
                shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll))
 
1299
            if os.path.exists(pythondll_d):
 
1300
                logger.info('Also created %s' % py_executable_dll_d)
 
1301
                shutil.copyfile(pythondll_d, pythondll_d_dest)
 
1302
            elif os.path.exists(pythondll_d_dest):
 
1303
                logger.info('Removed %s as the source does not exist' % pythondll_d_dest)
 
1304
                os.unlink(pythondll_d_dest)
 
1305
        if is_pypy:
 
1306
            # make a symlink python --> pypy-c
 
1307
            python_executable = os.path.join(os.path.dirname(py_executable), 'python')
 
1308
            if sys.platform in ('win32', 'cygwin'):
 
1309
                python_executable += '.exe'
 
1310
            logger.info('Also created executable %s' % python_executable)
 
1311
            copyfile(py_executable, python_executable)
 
1312
 
 
1313
            if sys.platform == 'win32':
 
1314
                for name in 'libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', 'libeay32.dll', 'ssleay32.dll', 'sqlite.dll':
 
1315
                    src = join(prefix, name)
 
1316
                    if os.path.exists(src):
 
1317
                        copyfile(src, join(bin_dir, name))
 
1318
 
 
1319
    if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
 
1320
        secondary_exe = os.path.join(os.path.dirname(py_executable),
 
1321
                                     expected_exe)
 
1322
        py_executable_ext = os.path.splitext(py_executable)[1]
 
1323
        if py_executable_ext == '.exe':
 
1324
            # python2.4 gives an extension of '.4' :P
 
1325
            secondary_exe += py_executable_ext
 
1326
        if os.path.exists(secondary_exe):
 
1327
            logger.warn('Not overwriting existing %s script %s (you must use %s)'
 
1328
                        % (expected_exe, secondary_exe, py_executable))
 
1329
        else:
 
1330
            logger.notify('Also creating executable in %s' % secondary_exe)
 
1331
            shutil.copyfile(sys.executable, secondary_exe)
 
1332
            make_exe(secondary_exe)
 
1333
 
 
1334
    if '.framework' in prefix:
 
1335
        if 'Python.framework' in prefix:
 
1336
            logger.debug('MacOSX Python framework detected')
 
1337
            # Make sure we use the the embedded interpreter inside
 
1338
            # the framework, even if sys.executable points to
 
1339
            # the stub executable in ${sys.prefix}/bin
 
1340
            # See http://groups.google.com/group/python-virtualenv/
 
1341
            #                              browse_thread/thread/17cab2f85da75951
 
1342
            original_python = os.path.join(
 
1343
                prefix, 'Resources/Python.app/Contents/MacOS/Python')
 
1344
        if 'EPD' in prefix:
 
1345
            logger.debug('EPD framework detected')
 
1346
            original_python = os.path.join(prefix, 'bin/python')
 
1347
        shutil.copy(original_python, py_executable)
 
1348
 
 
1349
        # Copy the framework's dylib into the virtual
 
1350
        # environment
 
1351
        virtual_lib = os.path.join(home_dir, '.Python')
 
1352
 
 
1353
        if os.path.exists(virtual_lib):
 
1354
            os.unlink(virtual_lib)
 
1355
        copyfile(
 
1356
            os.path.join(prefix, 'Python'),
 
1357
            virtual_lib)
 
1358
 
 
1359
        # And then change the install_name of the copied python executable
 
1360
        try:
 
1361
            mach_o_change(py_executable,
 
1362
                          os.path.join(prefix, 'Python'),
 
1363
                          '@executable_path/../.Python')
 
1364
        except:
 
1365
            e = sys.exc_info()[1]
 
1366
            logger.warn("Could not call mach_o_change: %s. "
 
1367
                        "Trying to call install_name_tool instead." % e)
 
1368
            try:
 
1369
                call_subprocess(
 
1370
                    ["install_name_tool", "-change",
 
1371
                     os.path.join(prefix, 'Python'),
 
1372
                     '@executable_path/../.Python',
 
1373
                     py_executable])
 
1374
            except:
 
1375
                logger.fatal("Could not call install_name_tool -- you must "
 
1376
                             "have Apple's development tools installed")
 
1377
                raise
 
1378
 
 
1379
        # Some tools depend on pythonX.Y being present
 
1380
        py_executable_version = '%s.%s' % (
 
1381
            sys.version_info[0], sys.version_info[1])
 
1382
        if not py_executable.endswith(py_executable_version):
 
1383
            # symlinking pythonX.Y > python
 
1384
            pth = py_executable + '%s.%s' % (
 
1385
                    sys.version_info[0], sys.version_info[1])
 
1386
            if os.path.exists(pth):
 
1387
                os.unlink(pth)
 
1388
            os.symlink('python', pth)
 
1389
        else:
 
1390
            # reverse symlinking python -> pythonX.Y (with --python)
 
1391
            pth = join(bin_dir, 'python')
 
1392
            if os.path.exists(pth):
 
1393
                os.unlink(pth)
 
1394
            os.symlink(os.path.basename(py_executable), pth)
 
1395
 
 
1396
    if sys.platform == 'win32' and ' ' in py_executable:
 
1397
        # There's a bug with subprocess on Windows when using a first
 
1398
        # argument that has a space in it.  Instead we have to quote
 
1399
        # the value:
 
1400
        py_executable = '"%s"' % py_executable
 
1401
    # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks
 
1402
    cmd = [py_executable, '-c', 'import sys;out=sys.stdout;'
 
1403
        'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))']
 
1404
    logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
 
1405
    try:
 
1406
        proc = subprocess.Popen(cmd,
 
1407
                            stdout=subprocess.PIPE)
 
1408
        proc_stdout, proc_stderr = proc.communicate()
 
1409
    except OSError:
 
1410
        e = sys.exc_info()[1]
 
1411
        if e.errno == errno.EACCES:
 
1412
            logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e))
 
1413
            sys.exit(100)
 
1414
        else:
 
1415
            raise e
 
1416
 
 
1417
    proc_stdout = proc_stdout.strip().decode("utf-8")
 
1418
    proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
 
1419
    norm_home_dir = os.path.normcase(os.path.abspath(home_dir))
 
1420
    if hasattr(norm_home_dir, 'decode'):
 
1421
        norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding())
 
1422
    if proc_stdout != norm_home_dir:
 
1423
        logger.fatal(
 
1424
            'ERROR: The executable %s is not functioning' % py_executable)
 
1425
        logger.fatal(
 
1426
            'ERROR: It thinks sys.prefix is %r (should be %r)'
 
1427
            % (proc_stdout, norm_home_dir))
 
1428
        logger.fatal(
 
1429
            'ERROR: virtualenv is not compatible with this system or executable')
 
1430
        if sys.platform == 'win32':
 
1431
            logger.fatal(
 
1432
                'Note: some Windows users have reported this error when they '
 
1433
                'installed Python for "Only this user" or have multiple '
 
1434
                'versions of Python installed. Copying the appropriate '
 
1435
                'PythonXX.dll to the virtualenv Scripts/ directory may fix '
 
1436
                'this problem.')
 
1437
        sys.exit(100)
 
1438
    else:
 
1439
        logger.info('Got sys.prefix result: %r' % proc_stdout)
 
1440
 
 
1441
    pydistutils = os.path.expanduser('~/.pydistutils.cfg')
 
1442
    if os.path.exists(pydistutils):
 
1443
        logger.notify('Please make sure you remove any previous custom paths from '
 
1444
                      'your %s file.' % pydistutils)
 
1445
    ## FIXME: really this should be calculated earlier
 
1446
 
 
1447
    fix_local_scheme(home_dir)
 
1448
 
 
1449
    return py_executable
 
1450
 
 
1451
 
 
1452
def install_activate(home_dir, bin_dir, prompt=None):
 
1453
    home_dir = os.path.abspath(home_dir)
 
1454
    if sys.platform == 'win32' or is_jython and os._name == 'nt':
 
1455
        files = {
 
1456
            'activate.bat': ACTIVATE_BAT,
 
1457
            'deactivate.bat': DEACTIVATE_BAT,
 
1458
            'activate.ps1': ACTIVATE_PS,
 
1459
        }
 
1460
 
 
1461
        # MSYS needs paths of the form /c/path/to/file
 
1462
        drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/'))
 
1463
        home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail)
 
1464
 
 
1465
        # Run-time conditional enables (basic) Cygwin compatibility
 
1466
        home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" %
 
1467
                       (home_dir, home_dir_msys))
 
1468
        files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh)
 
1469
 
 
1470
    else:
 
1471
        files = {'activate': ACTIVATE_SH}
 
1472
 
 
1473
        # suppling activate.fish in addition to, not instead of, the
 
1474
        # bash script support.
 
1475
        files['activate.fish'] = ACTIVATE_FISH
 
1476
 
 
1477
        # same for csh/tcsh support...
 
1478
        files['activate.csh'] = ACTIVATE_CSH
 
1479
 
 
1480
    files['activate_this.py'] = ACTIVATE_THIS
 
1481
    if hasattr(home_dir, 'decode'):
 
1482
        home_dir = home_dir.decode(sys.getfilesystemencoding())
 
1483
    vname = os.path.basename(home_dir)
 
1484
    for name, content in files.items():
 
1485
        content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
 
1486
        content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname)
 
1487
        content = content.replace('__VIRTUAL_ENV__', home_dir)
 
1488
        content = content.replace('__VIRTUAL_NAME__', vname)
 
1489
        content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
 
1490
        writefile(os.path.join(bin_dir, name), content)
 
1491
 
 
1492
def install_distutils(home_dir):
 
1493
    distutils_path = change_prefix(distutils.__path__[0], home_dir)
 
1494
    mkdir(distutils_path)
 
1495
    ## FIXME: maybe this prefix setting should only be put in place if
 
1496
    ## there's a local distutils.cfg with a prefix setting?
 
1497
    home_dir = os.path.abspath(home_dir)
 
1498
    ## FIXME: this is breaking things, removing for now:
 
1499
    #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
 
1500
    writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
 
1501
    writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
 
1502
 
 
1503
def fix_local_scheme(home_dir):
 
1504
    """
 
1505
    Platforms that use the "posix_local" install scheme (like Ubuntu with
 
1506
    Python 2.7) need to be given an additional "local" location, sigh.
 
1507
    """
 
1508
    try:
 
1509
        import sysconfig
 
1510
    except ImportError:
 
1511
        pass
 
1512
    else:
 
1513
        if sysconfig._get_default_scheme() == 'posix_local':
 
1514
            local_path = os.path.join(home_dir, 'local')
 
1515
            if not os.path.exists(local_path):
 
1516
                os.mkdir(local_path)
 
1517
                for subdir_name in os.listdir(home_dir):
 
1518
                    if subdir_name == 'local':
 
1519
                        continue
 
1520
                    os.symlink(os.path.abspath(os.path.join(home_dir, subdir_name)), \
 
1521
                                                            os.path.join(local_path, subdir_name))
 
1522
 
 
1523
def fix_lib64(lib_dir):
 
1524
    """
 
1525
    Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
 
1526
    instead of lib/pythonX.Y.  If this is such a platform we'll just create a
 
1527
    symlink so lib64 points to lib
 
1528
    """
 
1529
    if [p for p in distutils.sysconfig.get_config_vars().values()
 
1530
        if isinstance(p, basestring) and 'lib64' in p]:
 
1531
        logger.debug('This system uses lib64; symlinking lib64 to lib')
 
1532
        assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
 
1533
            "Unexpected python lib dir: %r" % lib_dir)
 
1534
        lib_parent = os.path.dirname(lib_dir)
 
1535
        assert os.path.basename(lib_parent) == 'lib', (
 
1536
            "Unexpected parent dir: %r" % lib_parent)
 
1537
        copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64'))
 
1538
 
 
1539
def resolve_interpreter(exe):
 
1540
    """
 
1541
    If the executable given isn't an absolute path, search $PATH for the interpreter
 
1542
    """
 
1543
    if os.path.abspath(exe) != exe:
 
1544
        paths = os.environ.get('PATH', '').split(os.pathsep)
 
1545
        for path in paths:
 
1546
            if os.path.exists(os.path.join(path, exe)):
 
1547
                exe = os.path.join(path, exe)
 
1548
                break
 
1549
    if not os.path.exists(exe):
 
1550
        logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
 
1551
        raise SystemExit(3)
 
1552
    if not is_executable(exe):
 
1553
        logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
 
1554
        raise SystemExit(3)
 
1555
    return exe
 
1556
 
 
1557
def is_executable(exe):
 
1558
    """Checks a file is executable"""
 
1559
    return os.access(exe, os.X_OK)
 
1560
 
 
1561
############################################################
 
1562
## Relocating the environment:
 
1563
 
 
1564
def make_environment_relocatable(home_dir):
 
1565
    """
 
1566
    Makes the already-existing environment use relative paths, and takes out
 
1567
    the #!-based environment selection in scripts.
 
1568
    """
 
1569
    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
 
1570
    activate_this = os.path.join(bin_dir, 'activate_this.py')
 
1571
    if not os.path.exists(activate_this):
 
1572
        logger.fatal(
 
1573
            'The environment doesn\'t have a file %s -- please re-run virtualenv '
 
1574
            'on this environment to update it' % activate_this)
 
1575
    fixup_scripts(home_dir)
 
1576
    fixup_pth_and_egg_link(home_dir)
 
1577
    ## FIXME: need to fix up distutils.cfg
 
1578
 
 
1579
OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
 
1580
                  'activate', 'activate.bat', 'activate_this.py']
 
1581
 
 
1582
def fixup_scripts(home_dir):
 
1583
    # This is what we expect at the top of scripts:
 
1584
    shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
 
1585
    # This is what we'll put:
 
1586
    new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
 
1587
    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"
 
1588
    if sys.platform == 'win32':
 
1589
        bin_suffix = 'Scripts'
 
1590
    else:
 
1591
        bin_suffix = 'bin'
 
1592
    bin_dir = os.path.join(home_dir, bin_suffix)
 
1593
    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
 
1594
    for filename in os.listdir(bin_dir):
 
1595
        filename = os.path.join(bin_dir, filename)
 
1596
        if not os.path.isfile(filename):
 
1597
            # ignore subdirs, e.g. .svn ones.
 
1598
            continue
 
1599
        f = open(filename, 'rb')
 
1600
        try:
 
1601
            try:
 
1602
                lines = f.read().decode('utf-8').splitlines()
 
1603
            except UnicodeDecodeError:
 
1604
                # This is probably a binary program instead
 
1605
                # of a script, so just ignore it.
 
1606
                continue
 
1607
        finally:
 
1608
            f.close()
 
1609
        if not lines:
 
1610
            logger.warn('Script %s is an empty file' % filename)
 
1611
            continue
 
1612
        if not lines[0].strip().startswith(shebang):
 
1613
            if os.path.basename(filename) in OK_ABS_SCRIPTS:
 
1614
                logger.debug('Cannot make script %s relative' % filename)
 
1615
            elif lines[0].strip() == new_shebang:
 
1616
                logger.info('Script %s has already been made relative' % filename)
 
1617
            else:
 
1618
                logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
 
1619
                            % (filename, shebang))
 
1620
            continue
 
1621
        logger.notify('Making script %s relative' % filename)
 
1622
        lines = [new_shebang+'\n', activate+'\n'] + lines[1:]
 
1623
        f = open(filename, 'wb')
 
1624
        f.write('\n'.join(lines).encode('utf-8'))
 
1625
        f.close()
 
1626
 
 
1627
def fixup_pth_and_egg_link(home_dir, sys_path=None):
 
1628
    """Makes .pth and .egg-link files use relative paths"""
 
1629
    home_dir = os.path.normcase(os.path.abspath(home_dir))
 
1630
    if sys_path is None:
 
1631
        sys_path = sys.path
 
1632
    for path in sys_path:
 
1633
        if not path:
 
1634
            path = '.'
 
1635
        if not os.path.isdir(path):
 
1636
            continue
 
1637
        path = os.path.normcase(os.path.abspath(path))
 
1638
        if not path.startswith(home_dir):
 
1639
            logger.debug('Skipping system (non-environment) directory %s' % path)
 
1640
            continue
 
1641
        for filename in os.listdir(path):
 
1642
            filename = os.path.join(path, filename)
 
1643
            if filename.endswith('.pth'):
 
1644
                if not os.access(filename, os.W_OK):
 
1645
                    logger.warn('Cannot write .pth file %s, skipping' % filename)
 
1646
                else:
 
1647
                    fixup_pth_file(filename)
 
1648
            if filename.endswith('.egg-link'):
 
1649
                if not os.access(filename, os.W_OK):
 
1650
                    logger.warn('Cannot write .egg-link file %s, skipping' % filename)
 
1651
                else:
 
1652
                    fixup_egg_link(filename)
 
1653
 
 
1654
def fixup_pth_file(filename):
 
1655
    lines = []
 
1656
    prev_lines = []
 
1657
    f = open(filename)
 
1658
    prev_lines = f.readlines()
 
1659
    f.close()
 
1660
    for line in prev_lines:
 
1661
        line = line.strip()
 
1662
        if (not line or line.startswith('#') or line.startswith('import ')
 
1663
            or os.path.abspath(line) != line):
 
1664
            lines.append(line)
 
1665
        else:
 
1666
            new_value = make_relative_path(filename, line)
 
1667
            if line != new_value:
 
1668
                logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
 
1669
            lines.append(new_value)
 
1670
    if lines == prev_lines:
 
1671
        logger.info('No changes to .pth file %s' % filename)
 
1672
        return
 
1673
    logger.notify('Making paths in .pth file %s relative' % filename)
 
1674
    f = open(filename, 'w')
 
1675
    f.write('\n'.join(lines) + '\n')
 
1676
    f.close()
 
1677
 
 
1678
def fixup_egg_link(filename):
 
1679
    f = open(filename)
 
1680
    link = f.readline().strip()
 
1681
    f.close()
 
1682
    if os.path.abspath(link) != link:
 
1683
        logger.debug('Link in %s already relative' % filename)
 
1684
        return
 
1685
    new_link = make_relative_path(filename, link)
 
1686
    logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
 
1687
    f = open(filename, 'w')
 
1688
    f.write(new_link)
 
1689
    f.close()
 
1690
 
 
1691
def make_relative_path(source, dest, dest_is_directory=True):
 
1692
    """
 
1693
    Make a filename relative, where the filename is dest, and it is
 
1694
    being referred to from the filename source.
 
1695
 
 
1696
        >>> make_relative_path('/usr/share/something/a-file.pth',
 
1697
        ...                    '/usr/share/another-place/src/Directory')
 
1698
        '../another-place/src/Directory'
 
1699
        >>> make_relative_path('/usr/share/something/a-file.pth',
 
1700
        ...                    '/home/user/src/Directory')
 
1701
        '../../../home/user/src/Directory'
 
1702
        >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
 
1703
        './'
 
1704
    """
 
1705
    source = os.path.dirname(source)
 
1706
    if not dest_is_directory:
 
1707
        dest_filename = os.path.basename(dest)
 
1708
        dest = os.path.dirname(dest)
 
1709
    dest = os.path.normpath(os.path.abspath(dest))
 
1710
    source = os.path.normpath(os.path.abspath(source))
 
1711
    dest_parts = dest.strip(os.path.sep).split(os.path.sep)
 
1712
    source_parts = source.strip(os.path.sep).split(os.path.sep)
 
1713
    while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
 
1714
        dest_parts.pop(0)
 
1715
        source_parts.pop(0)
 
1716
    full_parts = ['..']*len(source_parts) + dest_parts
 
1717
    if not dest_is_directory:
 
1718
        full_parts.append(dest_filename)
 
1719
    if not full_parts:
 
1720
        # Special case for the current directory (otherwise it'd be '')
 
1721
        return './'
 
1722
    return os.path.sep.join(full_parts)
 
1723
 
 
1724
 
 
1725
 
 
1726
############################################################
 
1727
## Bootstrap script creation:
 
1728
 
 
1729
def create_bootstrap_script(extra_text, python_version=''):
 
1730
    """
 
1731
    Creates a bootstrap script, which is like this script but with
 
1732
    extend_parser, adjust_options, and after_install hooks.
 
1733
 
 
1734
    This returns a string that (written to disk of course) can be used
 
1735
    as a bootstrap script with your own customizations.  The script
 
1736
    will be the standard virtualenv.py script, with your extra text
 
1737
    added (your extra text should be Python code).
 
1738
 
 
1739
    If you include these functions, they will be called:
 
1740
 
 
1741
    ``extend_parser(optparse_parser)``:
 
1742
        You can add or remove options from the parser here.
 
1743
 
 
1744
    ``adjust_options(options, args)``:
 
1745
        You can change options here, or change the args (if you accept
 
1746
        different kinds of arguments, be sure you modify ``args`` so it is
 
1747
        only ``[DEST_DIR]``).
 
1748
 
 
1749
    ``after_install(options, home_dir)``:
 
1750
 
 
1751
        After everything is installed, this function is called.  This
 
1752
        is probably the function you are most likely to use.  An
 
1753
        example would be::
 
1754
 
 
1755
            def after_install(options, home_dir):
 
1756
                subprocess.call([join(home_dir, 'bin', 'easy_install'),
 
1757
                                 'MyPackage'])
 
1758
                subprocess.call([join(home_dir, 'bin', 'my-package-script'),
 
1759
                                 'setup', home_dir])
 
1760
 
 
1761
        This example immediately installs a package, and runs a setup
 
1762
        script from that package.
 
1763
 
 
1764
    If you provide something like ``python_version='2.4'`` then the
 
1765
    script will start with ``#!/usr/bin/env python2.4`` instead of
 
1766
    ``#!/usr/bin/env python``.  You can use this when the script must
 
1767
    be run with a particular Python version.
 
1768
    """
 
1769
    filename = __file__
 
1770
    if filename.endswith('.pyc'):
 
1771
        filename = filename[:-1]
 
1772
    f = codecs.open(filename, 'r', encoding='utf-8')
 
1773
    content = f.read()
 
1774
    f.close()
 
1775
    py_exe = 'python%s' % python_version
 
1776
    content = (('#!/usr/bin/env %s\n' % py_exe)
 
1777
               + '## WARNING: This file is generated\n'
 
1778
               + content)
 
1779
    return content.replace('##EXT' 'END##', extra_text)
 
1780
 
 
1781
##EXTEND##
 
1782
 
 
1783
def convert(s):
 
1784
    b = base64.b64decode(s.encode('ascii'))
 
1785
    return zlib.decompress(b).decode('utf-8')
 
1786
 
 
1787
##file site.py
 
1788
SITE_PY = convert("""
 
1789
eJzFPf1z2zaWv/OvwMqTIZXKdD66nR2n7o2TOK333MTbpLO5dT1aSoIs1hTJEqRl7c3d337vAwAB
 
1790
kvLHpp3TdGKJBB4eHt43HtDRaHRcljJfiHWxaDIplEyq+UqUSb1SYllUol6l1WK/TKp6C0/n18mV
 
1791
VKIuhNqqGFvFQfD0Cz/BU/FplSqDAnxLmrpYJ3U6T7JsK9J1WVS1XIhFU6X5lUjztE6TLP0XtCjy
 
1792
WDz9cgyC01zAzLNUVuJGVgrgKlEsxfm2XhW5iJoS5/w8/nPycjwRal6lZQ0NKo0zUGSV1EEu5QLQ
 
1793
hJaNAlKmtdxXpZyny3RuG26KJluIMkvmUvzznzw1ahqGgSrWcrOSlRQ5IAMwJcAqEQ/4mlZiXixk
 
1794
LMRrOU9wAH7eEitgaBNcM4VkzAuRFfkVzCmXc6lUUm1FNGtqAkQoi0UBOKWAQZ1mWbApqms1hiWl
 
1795
9djAI5Ewe/iTYfaAeeL4fc4BHD/kwc95ejth2MA9CK5eMdtUcpneigTBwk95K+dT/SxKl2KRLpdA
 
1796
g7weY5OAEVAiS2cHJS3Ht3qFvjsgrCxXJjCGRJS5Mb+kHnFwWoskU8C2TYk0UoT5WzlLkxyokd/A
 
1797
cAARSBoMjbNIVW3HodmJAgBUuI41SMlaiWidpDkw64/JnND+e5ovio0aEwVgtZT4tVG1O/9ogADQ
 
1798
2iHAJMDFMqvZ5Fl6LbPtGBD4BNhXUjVZjQKxSCs5r4sqlYoAAGpbIW8B6YlIKqlJyJxp5HZC9Cea
 
1799
pDkuLAoYCjy+RJIs06umIgkTyxQ4F7ji3YefxNuT16fH7zWPGWAss1drwBmg0EI7OMEA4qBR1UFW
 
1800
gEDHwRn+EcligUJ2heMDXm2Dg3tXOohg7mXc7eMsOJBdL64eBuZYgzKhsQLq99/QZaJWQJ//uWe9
 
1801
g+B4F1Vo4vxtsypAJvNkLcUqYf5Czgi+1XC+i8t69Qq4QSGcGkilcHEQwRThAUlcmkVFLkUJLJal
 
1802
uRwHQKEZtfVXEVjhfZHv01p3OAEgVEEOL51nYxoxlzDRPqxXqC9M4y3NTDcJ7Dqvi4oUB/B/Pidd
 
1803
lCX5NeGoiKH420xepXmOCCEvBOFeSAOr6xQ4cRGLM2pFesE0EiFrL26JItEALyHTAU/K22RdZnLC
 
1804
4ou69W41QoPJWpi1zpjjoGVN6pVWrZ3qIO+9iD93uI7QrFeVBODNzBO6ZVFMxAx0NmFTJmsWr3pT
 
1805
EOcEA/JEnZAnqCX0xe9A0WOlmrW0L5FXQLMQQwXLIsuKDZDsMAiE2MNGxij7zAlv4R38C3Dx30zW
 
1806
81UQOCNZwBoUIr8LFAIBkyBzzdUaCY/bNCt3lUyas6YoqoWsaKiHEfuAEX9gY5xr8L6otVHj6eIq
 
1807
F+u0RpU00yYzZYuXhzXrx1c8b5gGWG5FNDNNWzqtcXpZuUpm0rgkM7lESdCL9MouO4wZDIxJtrgW
 
1808
a7Yy8A7IIlO2IMOKBZXOspbkBAAMFr4kT8smo0YKGUwkMNC6JPjrBE16oZ0lYG82ywEqJDbfc7A/
 
1809
gNu/QIw2qxToMwcIoGFQS8HyzdK6Qgeh1UeBb/RNfx4fOPV0qW0TD7lM0kxb+SQPTunhSVWR+M5l
 
1810
ib0mmhgKZpjX6Npd5UBHFPPRaBQExh3aKvO1UEFdbQ+BFYQZZzqdNSkavukUTb3+oQIeRTgDe91s
 
1811
OwsPNITp9B6o5HRZVsUaX9u5fQRlAmNhj2BPnJOWkewge5z4CsnnqvTSNEXb7bCzQD0UnP908u70
 
1812
88lHcSQuWpU26eqzSxjzJE+ArckiAFN1hm11GbRExZei7hPvwLwTU4A9o94kvjKpG+BdQP1T1dBr
 
1813
mMbcexmcvD9+fXYy/fnjyU/Tj6efTgBBsDMy2KMpo3lswGFUMQgHcOVCxdq+Br0e9OD18Uf7IJim
 
1814
alpuyy08AEMJLFxFMN+JCPHhVNvgaZovi3BMjX9lJ/yI1Yr2uC4Ov74UR0ci/DW5ScIAvJ62KS/i
 
1815
jyQAn7alhK41/IkKNQ6ChVyCsFxLFKnoKXmyY+4ARISWhbasvxZpbt4zH7lDkMRH1ANwmE7nWaIU
 
1816
Np5OQyAtdRj4QIeY3WGUkwg6llu361ijgp9KwlLk2GWC/wygmMyoH6LBKLpdTCMQsPU8UZJb0fSh
 
1817
33SKWmY6jfSAIH7E4+AiseIIhWmCWqZKwRMlXkGtM1NFhj8RPsotiQwGQ6jXcJF0sBPfJFkjVeRM
 
1818
CogYRR0yompMFXEQOBUR2M526cbjLjUNz0AzIF9WgN6rOpTDzx54KKBgTNiFoRlHS0wzxPSvHBsQ
 
1819
DuAkhqiglepAYX0mzk/OxctnL/bRAYEocWGp4zVHm5rmjbQPl7BaV7J2EOZe4YSEYezSZYmaEZ8e
 
1820
3g1zHduV6bPCUi9xJdfFjVwAtsjAziqLn+gNxNIwj3kCqwiamCw4Kz3j6SUYOfLsQVrQ2gP11gTF
 
1821
rL9Z+j0O32WuQHVwKEyk1nE6G6+yKm5SdA9mW/0SrBuoN7RxxhUJnIXzmAyNGGgI8FtzpNRGhqDA
 
1822
qoZdTMIbQaKGX7SqMCZwZ6hbL+nrdV5s8inHrkeoJqOxZV0ULM282KBdgj3xDuwGIFlAKNYSjaGA
 
1823
ky5QtvYBeZg+TBcoS9EAAALTrCjAcmCZ4IymyHEeDoswxq8ECW8l0cLfmCEoODLEcCDR29g+MFoC
 
1824
IcHkrIKzqkEzGcqaaQYDOyTxue4s5qDRB9ChYgyGLtLQuJGh38UhKGdx5iolpx/a0M+fPzPbqBVl
 
1825
RBCxGU4ajf6SzFtcbsEUpqATjA/F+RVigw24owCmUZo1xf5HUZTsP8F6nmvZBssN8Vhdl4cHB5vN
 
1826
Jtb5gKK6OlDLgz//5Ztv/vKMdeJiQfwD03GkRSfH4gN6hz5o/K2xQN+ZlevwY5r73EiwIkl+FDmP
 
1827
iN/3TbooxOH+2OpP5OLWsOK/xvkABTI1gzKVgbajFqMnav9J/FKNxBMRuW2jMXsS2qRaK+ZbXehR
 
1828
F2C7wdOYF01eh44iVeIrsG4QUy/krLkK7eCejTQ/YKoop5Hlgf3nl4iBzxmGr4wpnqKWILZAi++Q
 
1829
/idmm4T8Ga0hkLxoonrx7nZYixniLh4u79Y7dITGzDBVyB0oEX6TBwugbdyXHPxoZxTtnuOMmo9n
 
1830
CIylDwzzalcwQsEhXHAtJq7UOVyNPipI04ZVMygYVzWCgga3bsbU1uDIRoYIEr0bE57zwuoWQKdO
 
1831
rs9E9GYVoIU7Ts/adVnB8YSQB47Ec3oiwak97L17xkvbZBmlYDo86lGFAXsLjXa6AL6MDICJGFU/
 
1832
j7ilCSw+dBaF12AAWMFZG2SwZY+Z8I3rA472RgPs1LP6u3ozjYdA4CJFnD16EHRC+YhHqBRIUxn5
 
1833
PXexuCVuf7A7LQ4xlVkmEmm1Q7i6ymNQqO40TMs0R93rLFI8zwrwiq1WJEZq3/vOAkUu+HjImGkJ
 
1834
1GRoyeE0OiJvzxPAULfDhNdVg6kBN3OCGK1TRdYNybSCf8CtoIwEpY+AlgTNgnmolPkT+x1kzs5X
 
1835
f9nBHpbQyBBu011uSM9iaDjm/Z5AMur8CUhBDiTsCyO5jqwOMuAwZ4E84YbXcqd0E4xYgZw5FoTU
 
1836
DOBOL70AB5/EuGdBEoqQb2slS/GVGMHydUX1Ybr7d+VSkzaInAbkKuh8w5Gbi3DyEEedvITP0H5G
 
1837
gnY3ygI4eAYuj5uad9ncMK1Nk4Cz7ituixRoZMqcjMYuqpeGMG76909HTouWWGYQw1DeQN4mjBlp
 
1838
HNjl1qBhwQ0Yb827Y+nHbsYC+0ZhoV7I9S3Ef2GVqnmhQgxwe7kL96O5ok8bi+1ZOhvBH28BRuNL
 
1839
D5LMdP4Csyz/xiChBz0cgu5NFtMii6TapHlICkzT78hfmh4elpSekTv4SOHUAUwUc5QH7yoQENqs
 
1840
PABxQk0AUbkMlXb7+2DvnOLIwuXuI89tvjh8edkn7mRXhsd+hpfq5LauEoWrlfGisVDgavUNOCpd
 
1841
mFySb/V2o96OxjChKhREkeLDx88CCcGZ2E2yfdzUW4ZHbO6dk/cxqINeu5dcndkRuwAiqBWRUQ7C
 
1842
x3Pkw5F97OTumNgjgDyKYe5YFANJ88m/A+euhYIx9hfbHPNoXZWBH3j9zdfTgcyoi+Q3X4/uGaVD
 
1843
jCGxjzqeoB2ZygDE4LRNl0omGfkaTifKKuYt79g25ZgVOsV/mskuB5xO/Jj3xmS08HvNe4Gj+ewR
 
1844
PSDMLma/QrCqdH7rJkkzSsoDGvv7qOdMnM2pg2F8PEh3o4w5KfBYnk0GQyF18QwWJuTAftyfjvaL
 
1845
jk3udyAgNZ8yUX1U9vQGfLt/5G2qu3uHfajamBgeesaZ/hcDWsKb8ZBd/xINh5/fRRlYYB4NRkNk
 
1846
9xzt/+9ZPvtjJvnAqZht39/RMD0S0O81E9bjDE3r8XHHIA4tu2sCDbAHWIodHuAdHlp/aN7oWxo/
 
1847
i1WSEk9Rdz0VG9rrpzQnbtoAlAW7YANwcBn1jvGbpqp435dUYCmrfdzLnAgsczJOGFVP9cEcvJc1
 
1848
YmKbzSlt7BTFFENqJNSJYDuTsHXhh+VsVZj0kcxv0gr6gsKNwh8+/HgS9hlAD4OdhsG562i45OEm
 
1849
HOE+gmlDTZzwMX2YQo/p8u9LVTeK8AlqttNNclaTbdA++DlZE9IPr8E9yRlv75T3qDFYnq/k/Hoq
 
1850
ad8d2RS7OvnpN/gaMbHb8X7xlEqWVAEGM5lnDdKKfWAs3Vs2+Zy2KmoJro6us8W6G9pN50zcMkuu
 
1851
RESdF5gF0txIiaKbpNKOYFkVWNkpmnRxcJUuhPytSTKMsOVyCbjgPpJ+FfPwlAwSb7kggCv+lJw3
 
1852
VVpvgQSJKvQ2HNUOOA1nW55o5CHJOy5MQKwmOBQfcdr4ngm3MOQycbq/+YCTxBAYO5h9UuQueg7v
 
1853
82KKo06pQHbCSPW3yOlx0B2hAAAjAArzH411Es1/I+mVu9dHa+4SFbWkR0o36C/IGUMo0RiTDvyb
 
1854
fvqM6PLWDiyvdmN5dTeWV10srwaxvPKxvLobS1ckcGFt/shIwlAOqbvDMFis4qZ/eJiTZL7idlg4
 
1855
iQWSAFGUJtY1MsX1w16SibfaCAipbWfvlx62xScpV2RWBWejNUjkftxP0nG1qfx2OlMpi+7MUzHu
 
1856
7K4CHL/vQRxTndWMurO8LZI6iT25uMqKGYitRXfSApiIbi0Opy3zm+mME60dSzU6/69PP3x4j80R
 
1857
1MhUGlA3XEQ0LDiV6GlSXam+NLVxWAnsSC39mhjqpgHuPTDJxaPs8T9vqdgCGUdsqFigECV4AFQS
 
1858
ZZu5hUNh2HmuK4z0c2Zy3vc5EqO8HrWT2kGk4/Pzt8efjkeUfRv978gVGENbXzpcfEwL26Dvv7nN
 
1859
LcWxDwi1TjO1xs+dk0frliPut7EGbM+H7zx48RCDPRix+7P8QykFSwKEinUe9jGEenAM9EVhQo8+
 
1860
hhF7lXPuJhc7K/adI3uOi+KI/tAOQHcAf98RY4wpEEC7UJGJDNpgqqP0rXm9g6IO0Af6el8cgnVD
 
1861
r24k41PUTmLAAXQoa5vtdv+8LRM2ekrWr0++P31/dvr6/PjTD44LiK7ch48HL8TJj58FlWqgAWOf
 
1862
KMEqhRqLgsCwuKeExKKA/xrM/CyamvO10Ovt2ZneNFnjOREsHEabE8Nzriiy0Dh9xQlh+1CXAiFG
 
1863
mQ6QnAM5VDlDB3YwXlrzYRBV6OJiOuczQ2e10aGXPmhlDmTRFnMM0geNXVIwCK72gldUAl6bqLDi
 
1864
zTh9SGkAKW2jbY1GRum53s69sxVlNjq8nCV1hidtZ63oL0IX1/AyVmWWQiT3KrSypLthpUrLOPqh
 
1865
3WtmvIY0oNMdRtYNedY7sUCr9Srkuen+45bRfmsAw5bB3sK8c0mVGlS+jHVmIsRGvKkSylv4apde
 
1866
r4GCBcM9txoX0TBdCrNPILgWqxQCCODJFVhfjBMAQmcl/Nz8oZMdkAUWSoRv1ov9v4WaIH7rX34Z
 
1867
aF5X2f4/RAlRkOCqnnCAmG7jtxD4xDIWJx/ejUNGjqpkxd8arK0Hh4QSoI60UykRb2ZPIyWzpS71
 
1868
8PUBvtB+Ar3udK9kWenuw65xiBLwREXkNTxRhn4hVl5Z2BOcyrgDGo8NWMzw+J1bEWA+e+LjSmaZ
 
1869
LhY/fXt2Ar4jnmRACeItsBMYjvMluJut6+D4eGAHFO51w+sK2bhCF5bqHRax12wwaY0iR729Egm7
 
1870
TpQY7vfqZYGrJFUu2hFOm2GZWvwYWRnWwiwrs3anDVLYbUMUR5lhlpieV1RL6vME8DI9TTgkglgJ
 
1871
z0mYDDxv6KZ5bYoHs3QOehRULijUCQgJEhcPAxLnFTnnwItKmTNE8LDcVunVqsZ9Bugc0/kFbP7j
 
1872
8eez0/dU0//iZet1DzDnhCKBCddzHGG1HmY74ItbgYdcNZ0O8ax+hTBQ+8Cf7isuFDniAXr9OLGI
 
1873
f7qv+BDXkRMJ8gxAQTVlVzwwAHC6DclNKwuMq42D8eNW47WY+WAoF4lnRnTNhTu/Pifalh1TQnkf
 
1874
8/IRGzjL0laH6c5udVj3o+e4LHHHaRENN4K3Q7JlPjPoet17s6sOzf30pBDPkwJG/db+GKZQq9dU
 
1875
T8dhtl3cQmGttrG/5E6u1Gk3z1GUgYiR23nsMtmwEtbNmQO9iuYeMPGtRtdI4qAqH/2Sj7SH4WFi
 
1876
id2LU0xHOlFCRgAzGVIfnGnAh0KLAAqECnEjR3In46cvvDk61uD+OWrdBbbxB1CEuiyWjlsUFXAi
 
1877
fPmNHUd+RWihHj0UoeOp5DIvbMkWfjYr9Cqf+3MclAFKYqLYVUl+JSOGNTEwv/KJvSMFS9rWI/VF
 
1878
ejlkWMQpOKe3Ozi8LxfDGycGtQ4j9Npdy21XHfnkwQaDpzLuJJgPvko2oPvLpo54JYdFfvgg2m6o
 
1879
90PEQkBoqvfBoxDTMb+FO9anBTxIDQ0LPbzfduzC8toYR9bax84Bo9C+0B7svILQrFa0LeOc7DO+
 
1880
qPUCWoN71Jr8kX2qa3bs74EjW05OyALlwV2Q3txGukEnnTDik0N87DKlyvT2YIt+t5A3MgOjAUY2
 
1881
woMHv9qDB+PYplMGS7K+GLvz7fl2GDd602J2aE5GoGemSli/OJf1AaIzmPG5C7MWGVzqX3RIkuTX
 
1882
5CW/+fvpRLx5/xP8+1p+AFOKJwcn4h+AhnhTVBBf8tFXupMAD1XUHDgWjcLjhQSNtir4+gZ02849
 
1883
OuO2iD7t4R/zsJpSYIFrteY7QwBFniAdB2/9BHOGAX6bQ1Ydb9R4ikOLMtIvkQa7z53gWY0D3TJe
 
1884
1esM7YWTJWlX82J0dvrm5P3Hk7i+RQ43P0dOFsWvjcLp6D3iCvfDJsI+mTf45NJxnH+QWTngN+ug
 
1885
05xhwaBThBCXlDbQ5PsoEhtcJBVmDkS5XRTzGFsCy/OxuXoDjvTYiS/vNfSelUVY0VjvorXePD4G
 
1886
aohfuopoBA2pj54T9SSEkhme3+LH8WjYFE8Epbbhz9PrzcLNjOuDODTBLqbtrCO/u9WFK6azhmc5
 
1887
ifA6sstgzmZmaaLWs7l7Zu9DLvR1IqDlaJ9DLpMmq4XMQXIpyKd7HUDTu8fsWEKYVdic0dkzStNk
 
1888
m2SrnCKkRIkRjjqio+m4IUMZQ4jBf0yu2R7g+T/R8EFigE6IUvxUOF1VM1+xBHNIRNQbKDzYpPlL
 
1889
t55HU5gH5Qh53jqyME90GxmjK1nr+fODaHzxvK10oKz03DtkOy/B6rlssgeqs3z69OlI/Mf93g+j
 
1890
EmdFcQ1uGcAe9FrO6PUOy60nZ1er79mbNzHw43wlL+DBJWXP7fMmp9TkHV1pQaT9a2CEuDahZUbT
 
1891
vmOXOWlX8UYzt+ANK205fs5TujQIU0sSla2+ewnTTkaaiCVBMYSJmqdpyGkKWI9t0eD5OEwzan6R
 
1892
t8DxKYKZ4FvcIeNQe4UeJtWyWu6x6ByJEQEeUW0Zj0YHjOmEGOA5Pd9qNKeneVq3RzueuZun+iB9
 
1893
be8C0nwlkg1KhplHhxjOUUuPVVsPu7iTRb2IpZhfuAnHziz59X24A2uDpBXLpcEUHppFmheymhtz
 
1894
iiuWztPaAWPaIRzuTFcgkfWJgwGURqDeySosrETbt3+y6+Ji+oH2kffNSLp8qLbXSnFyKMk7BYZx
 
1895
3I5PaShLSMu35ssYRnlPaW3tCXhjiT/ppCrW9Xu3X7hHDJtc32rB9RvtVRcAh25SsgrSsqOnI5zr
 
1896
uyx8Ztodd1Hgh0J0wu0mreomyab68oQpOmxTu7Gu8bRH0+48dGm9FXDyC/CA93UVPTgOpsoG6YlF
 
1897
sOaUxJFY6hRF7J728g9GlQV6eS/YVwKfAimzmJozyiaJdGHZ1R7+1DWbjopHUF+ZA0U7PHNzkqV3
 
1898
CMTFfEJ1TuYIwg4v2uDSvVNCfHckoucT8edOIDQvt3grEqD8ZBE/WYS+T0ZdLw5ftHamH3h2IOwE
 
1899
8vLy0dPN0hlNLxwq/76/ry46xABwDbKzTOVi/4lC7BjnL4WqobTz2s0pNGM8Hb5nq570wej2uAid
 
1900
CpuBV79pFYqjWoz/aQcxJ661HuDDqSi0bIHsgXpTeNIp/rOXnmFhoEbPX1n0XKZDm1P4DS8ugfea
 
1901
oK6js3PTUle4W7ADMbk+xshbUG3DluPv9ageJUrdGvFeK9yebCXOZf1H8HBIl7wQ03zV2Rb+I5mH
 
1902
i/Z3bS72sPzm67vwdBXM4ImFgQX1FtNp9Qcy9U6WfezCPGC//n7+fzjv38X3j6aS7jVMKwylsJB5
 
1903
lfAbNIlNeWhTDUYl4FZQ5Ja34ae+HjwTw+oAdWN9Hd41fe5/19x1i8DO3Ozu9ubun31zaaD77uaX
 
1904
IRpwmKcJ8aCa8VZgh3WBK8YTXVQwnLLUHyS/2wlnukMr3AfGlDBgApTYVGNvtPY6mbvfsUJmn693
 
1905
dY86DtqKzrR7Zz+7HP8QRc/VAPjcnn6mEo+F5kD2G+m+rikXDU7l1ZWaJnhX3JSCDSpw6XmRxn19
 
1906
R1d9yURtjdeJF6oACMNNuhTRrTYGxoCAhu+s5foQ5+YMQUNTFaVTlqnSBWeQtIsL4GLOHFF/k5nk
 
1907
uspRJjHhp5qqrCAqGOmbTblwYajWswVqEhnrRF0b1E2Pib7oEofgahlzPJLzVRxpeNQBQvCpKefa
 
1908
Ji5Unk7tO+CXZ+0x8HRiGULmzVpWSd1egeJvk6biO2cEOhSLC+ykKlrJ7HCKi1hq+cNBCpMF9vtX
 
1909
2sn2gow7zn6PrdZ7OFtRD50Ce8yxcsf2GG5Ob+0VaO7VOwu6MNc18rZZy3322hdYCnOfF+lKnTvg
 
1910
t/qOIb65kjOb6CY4fARy7x5J88tzrVpjJ8Wi4TxzFUP/Uhk81Uy2eOiuuB4X9G+F6wQadnxfb1hm
 
1911
6YUmOxpbKmrXalDxtKON24gaK+nuiaj9aulHRtQe/AdG1PpmPzA4Gh+tDwbrp+8JvVlNuNfktYwA
 
1912
faZAJNzZ61yyZkxm5FYjQ9ib3o7sNbWsM50jTsZMIEf2708iEHwdnnJLN73rqu6KqH3posffn314
 
1913
fXxGtJieH7/5z+PvqVoF08cdm/XglENe7DO19726WDf9oCsMhgZvsR24d5IPd2gIvfe9zdkBCMMH
 
1914
eYYWtKvI3Ne7OvQORPQ7AeJ3T7sDdZfKHoTc88908b1bV9ApYA30U642NL+cLVvzyOxcsDi0OxPm
 
1915
fZtM1jLay7XtWjin7q+vTrTfqm8q3JEHHNvqU1oBzCEjf9kUsjlKYBOV7Kh0/+cBVDKLx7DMLR8g
 
1916
hXPp3DZHF80xqNr/vxRUoOwS3Adjh3Fib/yldpwuV/Yqa9wLm8vYEMQ7BzXqz88V9oXMdlAhCFjh
 
1917
6bvUGBGj//QGk92OfaLExT6duNxHZXNpf+GaaSf37yluutb2TiLFlRu87QSNl03mbqTaPr0O5PxR
 
1918
dr5YOiX+oPkOgM6teCpgb/SZWCHOtiKEQFJvGGLVINFRXyjmII9208He0OqZ2N91Hs89jybE890N
 
1919
F50jb7rHC+6h7umhGnPqybHAWL6266Cd+I4g8/aOoEuIPOcD9xT13bfw9ebi+aFNtiK/42tHkVCZ
 
1920
zcgx7BdOmdqdF9853YlZqgnVMWHM5hzT1C0uHajsE+yKcXq1+jviILPvy5BG3vvhIh/Tw7vQe9TF
 
1921
1LLeIUxJRE/UmKblnG7QuNsn4/50W7XVB8InNR4ApKcCARaC6elGp3Juy+Wv0TMdFc4aujLUzbiH
 
1922
jlRQFY3PEdzD+H4tft3udMLyQd0ZRdOfG3Q5UC85CDf7Dtxq7KVEdpuE7tRbPtjhAvBh1eH+zx/Q
 
1923
v1/fZbu/uMuvtq1eDh6QYl8WSwKxUqJDIvM4BiMDejMibY115EbQ8X6Olo4uQ7VzQ75Ax4/KDPFC
 
1924
YAowyJmdag/AGoXg/wBaZusT
 
1925
""")
 
1926
 
 
1927
##file ez_setup.py
 
1928
EZ_SETUP_PY = convert("""
 
1929
eJzNWmtv49a1/a5fwSgwJGE0NN8PDzRFmkyBAYrcIo8CFx5XPk+LHYpUSWoctch/v+ucQ1KkZDrt
 
1930
RT6UwcQ2ebjPfq6195G+/upwanZlMZvP538sy6ZuKnKwatEcD01Z5rWVFXVD8pw0GRbNPkrrVB6t
 
1931
Z1I0VlNax1qM16qnlXUg7DN5EovaPLQPp7X192PdYAHLj1xYzS6rZzLLhXql2UEI2QuLZ5VgTVmd
 
1932
rOes2VlZs7ZIwS3CuX5BbajWNuXBKqXZqZN/dzebWbhkVe4t8c+tvm9l+0NZNUrL7VlLvW58a7m6
 
1933
sqwS/zhCHYtY9UGwTGbM+iKqGk5Qe59fXavfsYqXz0VeEj7bZ1VVVmurrLR3SGGRvBFVQRrRLzpb
 
1934
utabMqzipVWXFj1Z9fFwyE9Z8TRTxpLDoSoPVaZeLw8qCNoPj4+XFjw+2rPZT8pN2q9Mb6wkCqs6
 
1935
4vdamcKq7KDNa6OqtTw8VYQP42irZJi1zqtP9ey7D3/65uc//7T964cffvz4P99bG2vu2BFz3Xn/
 
1936
6Ocf/qz8qh7tmuZwd3t7OB0y2ySXXVZPt21S1Lc39S3+63e7nVs3ahe79e/9nf8wm+15uOWkIRD4
 
1937
Lx2xxfmNt9icum8PJ8/2bfH0tLizFknieYzI1HG90OFJkNA0jWgsvZBFImJksX5FStBJoXFKEhI4
 
1938
vghCx5OUJqEQvnTTwI39kNEJKd5YlzAK4zhMeUIinkgWBE7skJQ7sRd7PE1fl9LrEsAAknA3SrlH
 
1939
RRS5kvgeiUToiUAm3pRF/lgXSn2XOZLFfpqSyA/jNI1DRngqQ+JEbvKqlF4XPyEJw10eCcY9zwti
 
1940
6capjDmJolQSNiElGOsSeU4QEi8QPBCuoCyOpXD8lJBARDIW4atSzn5h1CNuEkKPhBMmJfW4C30c
 
1941
n/rUZcHLUthFvlBfejQM/ZRHiGss44DwOHU9CCKpk0xYxC7zBfZwweHJKOYe96QUbuA4qR8F0iPB
 
1942
RKSZ64yVYXCHR2jIfeJ4YRSEEeLDXD9xHBI7qfO6mF6bMOZ4ETFKaeLEscfClIQ+SQLfJyHnk54x
 
1943
YsJODBdBRFgCX6YxS9IwjD0RiiREOgqasPh1MVGvTSJQSURIJ4KDPCaiwA0gzYORcPhEtAEqY994
 
1944
lAiCGnZ9jvdRRl4iYkpCGhJoxMXrYs6R4pGfypQ6EBawwAvS2PEDLpgnmMO8yUi5Y99EAUsD6VMZ
 
1945
kxhZ6AuW+MKhHsIdByn1XhfT+4ZKknqu41COMHHUBCQJzn0EPgqcJJoQc4Ez0nGigMqIEI/G3IFa
 
1946
8GyAxHYSN2beVKAucCZyIzf1hGB+KINYIGpuxHhEXA9SvXhKygXOSDcBQAF8uUSqEC9MWQop0uUx
 
1947
jRM5gVbsAmeEI3gcRInH0jShksbwdOIgex3EPHangu2Pg0SokG4kOYdhYRi6QRK4LAZ+8TRJo3BK
 
1948
ygVaUYemru8SRqjvOXAGcC6WQcBCAEXsylel9BYhSST2jHggqfRRUVSmQcQcuAqoJ6YSJhhblCi0
 
1949
BvD7HuM0ZbFHmQwAX14kvYTIKbQKxxYJkUqeOFAHBYmMlb4ApocxAIMnbjQV6XBsEZHAKi7BKm7s
 
1950
uELAuTHIKaQMhEeiKZQJL2KUcF9GAISAMUKS2A2QONyPKWPc5yGfkBKNLULBJGD5xHUjMFGSBLEH
 
1951
EWDMMEhR2lPAGV2wGwsjIsOYwr/oHlANkQNDgsBHgYVkChuisUXUkwmJQw9kD9ilPkjaQai5CCVa
 
1952
idCfkBJfwJ2DGMmUcOaTyA1F6LohyhAtRQIInMyX+IIJSCLTMAALcGC5I2kUM+lKD2HAI2+qAuKx
 
1953
RQE4lgBvJVoGFGDgB67rSi4S38W/eEqX5KIbclQv5KXwSMrBHyoFAeCJ76jGynldSm8Ro8RPgA3o
 
1954
OYLEZ47KWWQbnM3ALJM0kIwtcmPPjQFyCHTKmRs6YeqQMKG+QJ2n4VSk07FF0J0FDpoZV3mYBmkk
 
1955
AiapcBLYypypSKcXyIAkQ2MHbvWThEdAJyKEEwG8WOQHU/1dK6W3SAqE1hchcWPqegxhYmHg0hjc
 
1956
C+YXU0ySjvmIEZSNKxVqEk9wAJOb+mC2mIaphx4HUn6dDSYCjDf1rKlOd2bg2pF6l2e0m7fQu8/E
 
1957
L0xg1Pio73xQI1G7Fg+H62ZcSGv7heQZun2xxa0ldNoWmAfXlhoAVnfagExa3X01M3bjgXmoLp5h
 
1958
tmgwLigR+kV7J34xdzHfdcsgp1351aaXct+JfjjLUxfmLkyD79+r6aRuuKgw1y1HK9Q1Vya1FrTz
 
1959
4Q2mMIIxjH9lWcu/lHWd0Xww/mGkw9/7P6zmV8JuejNHj1ajv5Q+4pesWXrmfoXgVoV2l3HoxXCo
 
1960
F7Xj1eZimFv3am0pqcVmMNCtMSluMapuytpmxwq/mWTqX+AiJ6eNG87aIGFs/ObYlHv4gWG6PGEU
 
1961
Lfhtb/bgpEDN9XvyGbHE8PwFriLKQXCeMu1Amp0Z5x9bpR+telcec66mWWJ8PZTWTebFcU9FZTU7
 
1962
0lgYhHvBWpaagAvlXUti6u2VOhZcvyKsx5EjHi010i6fdxnbdbsLaK2OJow8a3G7WNlQ0njpUW2p
 
1963
5AyOMXaiGh2QPGeYuek5EwRfIyNNgmuVixL+yCtB+OmsPvb4KAfqabfr7dqzCS2mabXU0qjQqrQO
 
1964
0ScWrCx4bXzTqXEgSBTlVHhElVXWZAhd8TQ4zzARb+0vC6HPE8zZCDd6wallrnz44vmI0rI9bBCt
 
1965
MH2WU5VH7CSMKqbOiLUXdU2ehDngOBfd46POl4pktbB+PNWN2H/4RfmrMIEoLNLgnjnZIFRBizJe
 
1966
paAyxpx62F2G6p/PpN4aFIL9G2tx+Py0rURdHism6oVCGLX9vuTHXNTqlGQAoJePTU2g6jjyoHXb
 
1967
cnVGEpVym3PRDOqy9dhFCXZlt74otDMGdEViw7OiapbOWm0yALkWqPud3g1Pd2h3zLdtA7PVwLxR
 
1968
MkyAAOyXskYO0g9fQPj+pQ6Qhg5pH13vMBJtt8m1nJ81fr+Zv2ldtXrXyh6qMBbwV7Py27KQecaa
 
1969
QRxgokFOBstluVzduw9DYhgmxX9KBPOfdufCmCiF5fvNTb3qy7wrb33K+akYc8GckWLRqGrrqwdw
 
1970
ok72dPm0J3mqkI5FgSy3rb/kAsnTLb+Sp8pLVTmwScCWTkOZVXWzBmGoSllAwqnLCuvtzwPlF/aF
 
1971
vE/Fp2L57bGqIA1IbwTcVBeUtgKhndNc2KR6qu+dh9fp7MWwfpchZzN6VBT7fdn8qQRwD3KI1PWs
 
1972
LcR8/OZ6WKv3F5X+oF75Gk7RXFB+HtHpMHsNr75UxL83uapSR6aOWPW7FyhUFy05U4CVl8w0IBos
 
1973
jQ1ZY86DdUPxX0qpBpDViX9Hqb/FqOqe2vWaTg3KP54ZcoIFS8N9HfUpCmHNkeRnI1pKGdNG94FC
 
1974
BWahHjJrh3zMTdJ23enGGkDX25sanfZNrRrt+bAWLg68TeJD7pAplM+sN+OGsCZfBLTfoAE3FPD3
 
1975
MiuWHWF0S424umJKnO6Kvwd3d420Qp/uddRd3dRLI3Z1p4rhmy9lphLoIIhix06dui+2EXqrS6ci
 
1976
hyDljbrzUl4+jVap1lvFZfyuurDSfiZVsVR+fvv7XebzkBYrW3CuX8ryG50S6nOSpfgiCvUHzDlA
 
1977
2dlO5AfV5X002TboNPpUQSui8l99krNUrpgB5dcWoGqmbu1RzoWAI/EK6lD1uQBd8awglmB4rWv9
 
1978
9hDWNSjbs3ZLoHHb0Zx3hMq8y2Z7NlsCEcWd8rAWsydsp5orXgrDNTuEF0o0z2X1ud10bR0MYZS0
 
1979
Ie2ncAopNErcAEwVisADTPfoegEknyuxrZxKtAQ0NMBe/Z5RRFKsr1JmALpX7ZPOsrWqpqvX0D/o
 
1980
ZG0yNUe2bVIuxOGd+bG86LTG2dnBsKa6eq63uKAyXXItPtj4WR5Esbxa9rX1A1r82+cqawA+iDH8
 
1981
q5trYPjntfog8FlFT3UArFJlCGhkZVUddXLk4kKYjvswPVTP3Qi9vsPE7mo/VJsauWGArcaP5Wqs
 
1982
sUERbY3BivX8mc7hTjywtR1m6O5fwuinRsC7SwjABnd6F5aXtViuriCibu600OHzls060IKCufql
 
1983
g63Zv3Mp/t4j05foQb6spxj7zLkfX/uIVHPsB3RL7aqOIF5qnS8+en6tbzajQo/VVxLPa14fJ/Rc
 
1984
7lx3WeOhYTQz6Jip0hhMCqzc72GoPWoLu8Mb0o5f3dXGSLs4BxdoP6/eqLOVh5VO02exqHRaC0vR
 
1985
+G+mirJU+fmCq5Ta1xyCRccC897nZW+WyGsxiMawF7e329Zb2621wQDo2I7tLv7jrv9/AfAaXNUU
 
1986
TOsyF6jViUG46+NBJqZXv+rRK7Evv2i81ZEw33DQ8y6YowH05r+BuxfN92SX3RbVP8bNymDOGnY7
 
1987
16PfvzG+4ecrzfzkjPZya/H/ScnXyqwX/JtSrrL5pbrryu1hPKFrZzsrJD6sUuyPwDGdKerJyxmq
 
1988
dvmdHNCrrzU/+2W0pQ6gSvPl/Mertmi+7hBlDhB80kRUqcNeJCGapHNCz1cvCFwsf0A/Ne++jGMf
 
1989
TuOJcm6+ZnP9TRR7tWjHreOhZ6huiKnPAP2zfmqpIqHHLG/emnNhyHxSs+JJYfIwj6t2AlLdVneO
 
1990
3Is9u0R33ef+Wv2pVizPfbUW0rGhps1FRRfnZ/2xsnr3oT2Slh2tvngsLXu6M0OgIen7ufrjprrD
 
1991
vzXQAgNE22ualqzbyAb97uvl6qF/2a5hcU+eBzVWzOdmVjA0PXQMQoAhsulmBv39oU13134SjSlb
 
1992
dX85nKW3umfYbtu8713Sylhb2i3v2qaoc8C7S2P3pME8uIGedi1IxXbL+adi+P2fT8Xy/m+/PrxZ
 
1993
/TrXDcpqOMjotwdo9AJmg8r1N7BySygc+Gp+XaYdJhpV8f/7Oy3Y1s330l09YBDTjnyjn5qHGF7x
 
1994
6O7hZfMXz21OyLZB6lUfOGAGMzo/bjaL7VaV7Ha76D/1yJVEqKmr+L2nCbH7+959wDtv38JZplQG
 
1995
BDaonX65d/fwEjNqlDjLVIvM9X+XVxF7
 
1996
""")
 
1997
 
 
1998
##file distribute_setup.py
 
1999
DISTRIBUTE_SETUP_PY = convert("""
 
2000
eJztO21v20bS3/Ur9pFhkEok2k57vYPxqEDaOD2juSSIneuHxKBX5EpizbfyxbL6629m9oVLcmUn
 
2001
1z4PcMDpro7EnZ2dnfeZXR79T7lvtkU+mU6nPxRFUzcVL1mcwL/Jqm0ES/K64WnKmwSAJpdrti9a
 
2002
tuN5w5qCtbVgtWjasimKtAZYHK1YyaM7vhFeLQeDcj9nv7Z1AwBR2saCNduknqyTFNHDD0DCMwGr
 
2003
ViJqimrPdkmzZUkzZzyPGY9jmoALImxTlKxYy5U0/vPzyYTBZ10VmUV9SOMsycqiapDasKOW4PuP
 
2004
/Nloh5X4rQWyGGd1KaJknUTsXlQ1MANp6KbO8TtAxcUuTwseT7KkqopqzoqKuMRzxtNGVDkHnmqg
 
2005
bsdzWjQCqLhgdcFWe1a3ZZnuk3wzwU3zsqyKskpwelGiMIgft7fDHdzeBpPJNbKL+BvRwohRsKqF
 
2006
7zVuJaqSkranpEtUlpuKx7Y8A1SKiWJeUetv9bZtktT82puBJsmE/r7OM95EWzMkshLpMb95RT+N
 
2007
vBBlrQWVFpvJpKn2551M6wR1UQ5/vLr4EF5dXl9MxEMkYCOX9PwCGS6nGAi2ZG+LXFjYNNntChga
 
2008
ibqWihOLNQulKYRRFvvPeLWpZ3IKfvAnIPNhu4F4EFHb8FUq5jP2nIYMXAXcq3ILfRABf33CxpZL
 
2009
djo5SPQRqD2IAgQFMo3ZGmQiCWIvgm/+VCKP2G9t0YBq4eM2E3kDrF/D8jloZgcGjxBTCcYPxGRI
 
2010
vgcw37zwuiU1WYhQ4DZn/TGFx4P/ganD+HjYYps3Pa6nHjtGwBGcghkOqU1/6igg1sEXtWJ9M5RO
 
2011
UQd1ycEGffj2Pvzl5eX1nA2Yxp7ZMnt18frlxzfX4T8vPlxdvnsL601Pg++CF3+dmqGPH97g423T
 
2012
lOcnJ+W+TAIpqqCoNifKJdYnNbitSJzEJ52XOplOri6uP76/fvfuzVX4+uXPF68GC0VnZ9OJDfT+
 
2013
55/Cy7ev3+H4dPp58g/R8Jg3fPFP6ZzO2VlwOnkLXvXcMuiJGT2uJ1dtlnGwCvYAn8nfi0wsSqCQ
 
2014
fk9etkB5ZX9fiIwnqXzyJolEXivQV0K6E8KLD4AgkOChHU0mE1Jj5Xl88AQr+HeuXVGIbF/6s5k2
 
2015
CvEAISkibSXvL+FpsMlK8KDAA+1eguwuxu/gyHEc/Eiw41XuexcdElCK49qbq8kSsEjjcBcDItCH
 
2016
jWiiXawwGLdBUGDMW5jj21MJihMR0qcFRSlyva0OJlT7UHvuTQ6itKgFRp/OQjeFIhY3beKEAQAH
 
2017
I7cORJW82Qa/ArwibI4PU1Avi9ZPpzez8UYklm6gY9jbYsd2RXVnc0xDW1QqoWGUGuO4NIPslVF2
 
2018
b2b7l7xoeh7N0wEdlvMUcvj6zFaOgYfp1rsCHYZEAZbbgUtju6qAr3FbadWxU5nAomOARQiCFuiZ
 
2019
WQYuHKyC8VVxL/SkdZIDHpdmSEXqUMtYGVRZUwlh9EaZwKpNAFxsNj78N2fGEpoiRLD/GsB/gAGQ
 
2020
DCmS5gyk6ED0g4GwrABhO0FIeXecOmQQi9/w7wojB6oNPVrgL/hTWYj+FCWV+5MRU+teJeo2bfqq
 
2021
BYRIYGXOWh7iAQirabijoeIJJMOX7yjt8b0fizaNaRbxUdrdZoN2pmwkhi2pbNlXiffc5M/hitdC
 
2022
b9t6HIuU79WqyOihkih4rwvBi+N6Ue6P4wD+j5x1JinwOWYdFZgwqB8QzdYFaJjj4dnN7MvZo4wG
 
2023
CDZ7sXL7A/s/ROvgc4BLndY94Y4IkPJBJB98qaga/3TOOvmrzLpfYVnlxErXlzr4h5TaL8lwpLwH
 
2024
1Yza8XKQfg04sLRSMCc35A6WaABt5WDC8uwvcxBOuOZ3YnldtcL43oyTA6hbKAF3lJiTjvJVXaRo
 
2025
xsiLSbeEpWkAgv/6Nvd2vA4llwT6Wq+824RgUpQR1pQgI3+zIm5TUWNN9tnsxuu4MgQc++neD0s0
 
2026
vfX6AFI5t7zmTVP5PUAwlDC24rczwcfZioPuDJ+G+rX2EEQ5h64uMhCHSiYzU+b1f8RbHGZejxmB
 
2027
agj4044l3y+nz9VqMwdZw1308amU/MciX6dJ1PSXFqAlsi6JyJv4M/AnQ8HZWjXmPU6HQAjZTLCr
 
2028
oIj2RxDTa/LstK3Y7m5YXSD/++UxFENJTYLm91AKUJX0OZ+O8WHTJuK512Atq0wdMO+22JCgTo5q
 
2029
QMC3qs0xugTsfSpAPE58uknBWVZUSGqE6Z0mdJ1UdTMH0wQ0zukeIN5rl8MWH619eYED/nP+Ofd/
 
2030
bKsKVkn3EjE7rmaAvOf/RYDZKOYVY1WWQksa/0V/TKS1wz5AA9nA5Cz7/jTwEzc4BSMztZCKu0OF
 
2031
8tdYwxfFkEMW49Rrk+vAqm+L5nXR5vEfNtonyXSROEqEHnNXYVQJ3oihtwpxc2SBJsfCcPVIlP6j
 
2032
MYs+jsCl4pXywlBrv+qaicZcKa6aliXYXlpEVPZQQ1UxPmlkjzDnmZAp462i/RZSQsrMVtj4vOdp
 
2033
0sOuLS9vs5WowKI5mbLxCoQLG42UElM3xnQ8QQtoimC3PX7cMuyf+OAjoq1eXeSxDJvYDebMO/Fm
 
2034
AbuVPLnFFXuVAfgXUQmdQppeml5FxIHcI3HQTFd7oF5uVOQxdVVLjoF+JdbobrCBGjUtT7veLu2v
 
2035
wTqrCbQY/k8Shl4sIqG2FRTUK4pCAhvqqrNdpVh0TSxrdMZKC8UL19xm83uI6oBtpV5yHGCRtvkd
 
2036
HaCSvmyfV71cFQXJnhssMv/j9wJYeiAF16Aqu6wiRAf7Um1by1oHebNEOztHnr+8LxLU6hItNzbk
 
2037
dBnOKKSb4sVYD/n4ejrHLfVdtiRKcckfDR+xD4LHJxRbGQYYSM6AdLYCk7ubYy9/h0qI0VC6FtDk
 
2038
qKgqcBdkfQNksFvSam0vCZ6qNILgtQrrDzb8MEGoItAHHg8yKslGIloya86mu9V0BKTSAkTWjY18
 
2039
ppIErOVIMYAAXcAP4AG/I9zBojZ815UlCcNeUrIEJWNVCYK7rsF7rYoHf93mEXoz5QRp2B6n1u2c
 
2040
PXt2t5s9khXLg4WuPlHTtWG80p7lSj5/LGEewmLODGW2K1lGau+TQrahRi18+1Pyuh4NDFcKcB0Q
 
2041
9Pi5WeQLcBhYwHR4XolHOlS6YJH0BYlNN+E1B4AvzueH8w7LUOmO1oie6J/UZrXMmO7HGeQUgTOp
 
2042
c0PaSm/rrVJ0oipE3+CjGczBXYAHyJsu5P9CsY1Hd21J3mItE2uRyx1BZNcBibwl+LZQ4dAeARHP
 
2043
bK8B3BjDLvXSHYeOwMfhtL1mnqPj9bIPYbda1a47behmvUdoLAUCPQGySYwNITkDoljmc/YmwNB2
 
2044
nitYKremeefOBNcuP0S6PbHEAOvZ3sUa0b4Jj68125xC0y5uyHuLxwrVaM8SQS52OjLjU4iyXvDu
 
2045
zavguMbjMjx5DfDPqO/7AdHJ4IaBpJAdR0mixqlawFjb4k/fNao2oB8aYrPiHpJlMI3Q7q77Zcoj
 
2046
sQVlF7qPPQjjSY2dyDFYn/qP+R0Ewl7jHhIvtQdr7mH9WmPd0fM/mI7qqwdWm9hNClCtTrID9a+P
 
2047
c+d2P+YZdgwXWBwM3b1efOQtVyD9O5st63551HGg65BSCm8fz9vrDhgwGWkByAm1QKRCHvcWbYNJ
 
2048
L3qPHd93NqfrnGHCZrFnzqTqK/IHElXzLU50zlxZDpAd9mClq+pFkNEk6Q/VjDlznIWqvrfi6Mi3
 
2049
d9wAU+BDFzVnfWqcynQEmHcsFY1XM1R843yH/DSKpviNuubbLbz5oPmnGvx4ywG/WtzTGB6Th4Lp
 
2050
nawN+8wKZFDt2t5mhGUc0116CU5VNu6BrZpYxYkDbXTvqrsyFFttAm+wk74/PuRrht75EJz21XwN
 
2051
6bQ5fsb1FVOsAIYg5m6MaVsbG+l4j+UKYMAzM/D/WQZEhMXqV9+cXc4C3esuoSSEuktGtqe6DD3n
 
2052
Jun+mik9l2uTCyrpKKaecsMOYWvm6MbC2AURp/b3xCMwORWp/C8+NZEVYbdRFYktK1KHNnXnB2GB
 
2053
zz2d8w9dQ5hL2r7C6Q1IGfk/zcuxA3R6Hgn+iN/peTNYhEd4nchygfDsl/Ddz66FoKzFgnMLBRQr
 
2054
RZUlda1vjMlC9RhbjHdJWUJQmNo0DCzhR1Q6mT6MSO3yMEPS47mY02cTwOG8TMqnMYnYYflYihHA
 
2055
BG+YCQ220mwtMXZbUY+f2kqPDKs9N1SSp/f3lF0P3dsT4LNeEWEibZdIHqn4BWEvukP1SvCXK6k/
 
2056
aBUy7b746acFihDjFohTfv8Kq0hGefOjwf1QIPrSYN4ZlhXQD1QYQHx2Z/jWf/QoK2ZP+JMnOff/
 
2057
YlMWK3q1jtIWd7mjBrV+yeaoCaOjEPqDbJ4ejKGO40CFmTrEYVmJdfLg6/DSRTQTWckvqpNQKPrv
 
2058
rUsG1t7wt7ohqAE/6S8QmmPxYMXq52fnNyZ1o8G5vkco8jYTFZc3DO2GDYLKC7kyyVssKtirvJoh
 
2059
NzGsCmATgCOANaumxt42KvESY5fE4+gGNUWpJEMzyzRpfA/XWXqzT4vBkaDFAs0+ezGFa3guJanC
 
2060
elRS4TzlTUEz5bXI7yV/3I2rHrn1J4J87qDyayntaATmtrWoPDrP6G77qvNJ7B0720SuVcxsh2FI
 
2061
jRyp6lDZryJOp5jWYae+7+my3YOn8Y+1xY7YTnhgURGQ4MgsrJQaFNK6aBQXQjKlFiLDBMA+kx23
 
2062
ZujnDs2lX5+oq1DIhvGGrDiE2TBM3tUBpor9iwTBB3nIjBk+eMUKnFGvJnJXCwNtoZiPGJbkxpXH
 
2063
VZy73pdixDfsj1qnVy/fX/7JhM+6ynOIEBSyr4z2BTP71Qm7DpLdALdojlgsGqEu8mHwxuN/EwFR
 
2064
U+Nh4mzO/pZD8gI9NNRn+5UOq9KSS4N26x6MYxXFCzrJkL4QFZJ8YfJAxJZVcZ/EIpZvdyRrBW+/
 
2065
R1JbHY9Y3QHM5t1Jim5z2ilyP3C4KHNLQWEDhs6HBAMieQDjusc61lZ5xR1o2ULRc7gw6qVhYJVS
 
2066
jrV9g1BtybGJQOSxChp0Ue3ApvKFvGDYCa9HB9r34eadU6p6siINcLg8rKOTY91BPUzSoYzJQcrj
 
2067
CZQi0T+Uf6LO9VsgX5GDHkxCH+l4D3jTnzfuedu6Yc4L0azpUFu6Pzpgtvx9Loai7Wf/f1SeA3rp
 
2068
iDUXVpc+5W0ebbsUrnsyjJQf1EhvzxjaZK1KL1xJCOoy6Fd0JFSZlCzj1R1eICgYp1Nf3k1YtcZ4
 
2069
TKp3/s0NpgufvEXUv1EOCQTe60nFQvUdFuKBXs+CnHmR8Rxid+zdWCFOYzy9MU0I7NTZCean/isk
 
2070
N+y5mTbROOhSkPPtIMM96550LdK17NYvpwHU6ZnA2wr1EmNKdxyk7nbT6bOCkGebdPOgAm5L1uLP
 
2071
SN5r0leb9f66WxTok/FVtmKXY1WdFTG+9Cb9P54wEIDdU+jOCTWSBJSQumwg87gO2C1uwDO3UfAN
 
2072
NEC6FkTI6GY3EKo4AF9hstqRh55YpqY8JSIyfKOQbqgAP4lk6jpqPNjYV1oMGrvas41oFC5/1r+2
 
2073
oRKyqCj39m8oxCDjV9cQJUPlDXcNoBjf3VW0OQD6cGPyAi2WUT6gBzA2p+uJqT5gJfKHEFEUSK9y
 
2074
VsOq6T7wS0easB496hZNzdcCpSoGdwk6yICXUIHGvlqj78o0XUviVoB/HgXES2zYt/n2279R7hIl
 
2075
GYiPiiag7/Svp6dWMpauAyV6jVMqv8kpPgi0VsFq5L5Nsm34diOR/S/zX8zZtxaH0MZwvqh8wHA2
 
2076
RzwvZs5yIcpKggmwSSABg+5IbMg2ROpLzG6ASlLvu847RojuxH6pFTDAOwagvkizhwR4szlT2OR9
 
2077
Zc0gyNzodgngMhZsrBZVl8SBqdyQeQOls8Z7RNLho7OtoQXeZ9DowJ6kHG2BuE7GCu9sDNjSoeYX
 
2078
AEZb2NkjgKpAsC3237hqK1UUJ6fA/RSq4LNxBUzXmAfVtetyBCEL49XGByWcKteCr+bhLStztCxv
 
2079
5dvvP2G4uNcNEeu59Dj4FEtjc+HVKpbl+5D32lh6YOT3ndbznbPDLHHqe8M1e69fVf0O02dI8ERl
 
2080
3TWSV7uv9nUjsgsMgWczFxWWj7M2ph2S3kevULcBJcsynlCX4n7ODtzF7ELn5WPvPxNPLni9V1A6
 
2081
XDz+lobKikbvNx6UJAb+hG4wYSYaUnsjDHEXYajetKUtmRTk7PxmNvkXFrmZPg==
 
2082
""")
 
2083
 
 
2084
##file activate.sh
 
2085
ACTIVATE_SH = convert("""
 
2086
eJytVVFv2jAQfs+vuIY+lGo06h5bMYmqSCC1UDWs09ZWwSQOseTYKHZI6bT/vnMSQtIA0rTmgRDf
 
2087
57vPd9+dOzCLmIKQcQpxqjQsKKSKBpAxHYGtZJr4FBZMOMTXbE00teE8TGQMC6Kic6sDG5mCT4SQ
 
2088
GpJUANMQsIT6mm8sK6DbXXDWhd8W4JMKRTWsNoH0rXyhAwk1S5IHQMWaJVLEVGhYk4SRBacqR7EQ
 
2089
nqEnwD71pne33tP4cfZ9cOc9DGYjG17hGnRERY40j1nu74NWCPq2konOgdVaQa21KbeH7CiNn7PR
 
2090
dDKa3g/3kamMLUq7bS1ilekovSYKSZYpzauqIpliUgOqsR55wYCIAN5V9AWyiPkRRGRNgeALTb6M
 
2091
Y2PWEdG5FkpXqAifcI6a0BKWyABLjP9CmZiPFUHRlFvVBcAP1I1MdWnWTCxLNw2gSRCcmuSCHxGx
 
2092
pAoyFCAJzM8GjJgwLOpihcxp8CH1NwMXi96Txdcvd+Q9DR/d8XSyJ/n50XoJfP3mBHTtiJTzRqoO
 
2093
FdS93FdJ97JVQgS2audeHi1aad5SKCBb63DytCN2gryQSB9sIUVAlU5S01D0A7cOuJSHsAWcfIje
 
2094
M6ZtJ25D/7GweQs7SxLKUQmNpqv1bjO2ZdWo9m3Pq316nm2VSaifx2r1FKax6Mfyo4Z2PO9mPPEm
 
2095
g/uh512VsHq7Vrx36jfZwhW0aCP8jHEOIWHcrNdRyqCMeo3+aLzSG8BzoUjhrGgIRCxIgG2yycim
 
2096
i/78vIVwJMIcfZ3l6Uyv4QrVW/ntwvUcmMg7zNoJ6uBQONDC/caWmjRqXW40U0R4h0bWvNuxO7i5
 
2097
G3oPj9P7h9nRiLmKK+Hm7uy3XR0LD1hKOOnD24EuaMN3HilXtOZ6jnmhgsQUXhqUX+x5Lm0TqRWk
 
2098
A6b3GeE4fDD5OE5ggCsC58OS+eUdIxNWXg/lFkoh0np15ThZll28U40TZX2BU8dRMtQZSahDjBen
 
2099
eZjnGsU5ut5L9mU+f4U9h6y8nB05aHe3sbxJyldtZJjaEs6IKm7Hvr3a4CwV0IuLBdso/1MG+ycM
 
2100
9f8c6P8+zPcNcszYX1+tk3g=
 
2101
""")
 
2102
 
 
2103
##file activate.fish
 
2104
ACTIVATE_FISH = convert("""
 
2105
eJyVVWFv2jAQ/c6vuBoqQVWC9nVSNVGVCaS2VC2rNLWVZZILWAs2sx1Yq/342SEJDrjbmgpK7PP5
 
2106
3bt3d22YLbmGlGcIq1wbmCPkGhPYcrMEEsGciwGLDd8wg1HK9ZLAWarkCtzvM+gujVl/Hgzcm15i
 
2107
lkVSLXqtNrzKHGImhDSgcgHcQMIVxiZ7bbXSXFiPUkCClWuAfgJk9MvabbgyOctQbICJBBSaXAkw
 
2108
EoRUK5ZBcQ3Yba6kWKEwpAX2aVtLjQZklvibsGGKs3mGurDiKRi0YfYFkA6dXl/Rx8n97Nvwmt4N
 
2109
Z2MChZF7nKv+4he4ZTi2bNohhA1QJP+69ftsPL0dT29G5Pjqeu8QQL3xdxhNswrMO4i+Th7G9O5+
 
2110
enM3o9PH0f395MrDVKVMu1tcsunaimBtggBCrmrDCLpWZAsu6pXqWSsuTAqklod3z7N4Nm1ydGQP
 
2111
i9q80xCwMnT4DWudz6EXDil4vMFYGWBF7uj2sUEk6TC12Dx9eiFwcgFESJHYZZU7feMeeBseMEuh
 
2112
2jsJo9nXRY3DfWxZ5cLh4EphxjZNeXvF1Ly91aoU5YEHQqn3SinZmx2JGTqFpBs1QTre8QGll5Nb
 
2113
eju8GVlPpXkN1xOypcuutHb/oP8TDkQahuAVQsgefS8FUbW835o46dXkYXh5PSrVWXUOl3jX9jSw
 
2114
OhHAhTbIEpCp7UOupTiuXR9aoEDlaDZLhJ1cor1O2qBtZoq9OLd5sjnydLV3z3RhU78HFRgulqNC
 
2115
OTwbqJa9vkJFclQgZSjFFHAwpeIWhe2+h2HYANkKk3PYouv3IDeoFE9wd1TmCuRW7OgJ1bVXGHc7
 
2116
z5WDL/WW36v2oi37CyVBak61+yPBA9C1qqGxzKQqZ0oPuocU9hpud0PIp8sDHkXR1HKktlzjuUWA
 
2117
a0enFUyzOWZA4yXGP+ZMI3Tdt2OuqU/SO4q64526cPE0A7ZyW2PMbWZiZ5HamIZ2RcCKLXhcDl2b
 
2118
vXL+eccQoRze2+02ekPDEtxEsVwNtEzNlikcMOdp8A7BT6f65VSDY9kjtD+HeZbb9C+5wZ4XZ9dC
 
2119
CQXc+2A6MNP4DqLuqe7t0v4/gA5wfBRGKQGX6oMhUbWv0Bg8uLXoVn8AkYzUxg==
 
2120
""")
 
2121
 
 
2122
##file activate.csh
 
2123
ACTIVATE_CSH = convert("""
 
2124
eJx9U11v2jAUffevOA2o3ZBG9gxjGx2VVqmlVUUrTWMyTnLTWEocZDsg+uvnOEDDx5aHKLn3fFyf
 
2125
3HQwy6RBKnNCURmLiFAZSrCWNkNgykrHhEiqUMRWroSlfmyyAL1UlwXcY6/POvhVVoiFUqWFrhSk
 
2126
RSI1xTbf1N0fmhwvQbTBRKxkQphIXOfCSHxJfCGJvr8WQub9uCy+9hkTuRQGCe08cWXJzdb9xh/u
 
2127
Jvzl9mn2PL7jj+PZT1yM8BmXlzBkSa3ga0H3BBfUmEo5FE56Q2jKhMmGOOvy9HD/OGv7YOnOvrSj
 
2128
YxsP/KeR7w6bVj3prnEzfdkaB/OLQS+onQJVqsSVdFUHQFvNk1Ra1eUmKeMr5tJ+9t5Sa8rFipTF
 
2129
SmgpopxMn7W4hw6MnU6FgPPWK+eBR53m54LwEbPDb9Dihpxf3075dHx/w/lgiz4j5jNyck3ADiJT
 
2130
fGiN0QDcJD6k4CNsRorBXbWW8+ZKFIQRznEY5YY8uFZdRMKQRx9MGiww8vS2eH11YJYUS5G7RTeE
 
2131
tNQYu4pCIV5lvN33UksybQoRMmuXgzBcr9f9N7IioVW95aEpU7sWmkJRq4R70tFB3secL5zHmYHn
 
2132
i4Un70/3X5WjwzZMlciUNff39a5T/N3difzB/qM0y71r7H5Wv4DubrNS4VPRvDPW/FmM/QUd6WEa
 
2133
""")
 
2134
 
 
2135
##file activate.bat
 
2136
ACTIVATE_BAT = convert("""
 
2137
eJyFUkEKgzAQvAfyhz0YaL9QEWpRqlSjWGspFPZQTevFHOr/adQaU1GaUzI7Mzu7ZF89XhKkEJS8
 
2138
qxaKMMsvboQ+LxxE44VICSW1gEa2UFaibqoS0iyJ0xw2lIA6nX5AHCu1jpRsv5KRjknkac9VLVug
 
2139
sX9mtzxIeJDE/mg4OGp47qoLo3NHX2jsMB3AiDht5hryAUOEifoTdCXbSh7V0My2NMq/Xbh5MEjU
 
2140
ZT63gpgNT9lKOJ/CtHsvT99re3pX303kydn4HeyOeAg5cjf2EW1D6HOPkg9NGKhu
 
2141
""")
 
2142
 
 
2143
##file deactivate.bat
 
2144
DEACTIVATE_BAT = convert("""
 
2145
eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q
 
2146
FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL
 
2147
i2dASrm4rFz9XLgAwJNbyQ==
 
2148
""")
 
2149
 
 
2150
##file activate.ps1
 
2151
ACTIVATE_PS = convert("""
 
2152
eJylWdmS40Z2fVeE/oHT6rCloNUEAXDThB6wAyQAEjsB29GBjdgXYiWgmC/zgz/Jv+AEWNVd3S2N
 
2153
xuOKYEUxM+/Jmzfvcm7W//zXf/+wUMOoXtyi1F9kbd0sHH/hFc2iLtrK9b3FrSqyxaVQwr8uhqJd
 
2154
uHaeg9mqzRdR8/13Pyy8qPLdJh0+LMhi0QCoXxYfFh9WtttEnd34H8p6/f1300KauwrULws39e18
 
2155
0ZaLNm9rgN/ZVf3h++/e124Vlc0vKsspHy+Yyi5+XbzPhijvCtduoiL/kA1ukWV27n0o7Sb8LIFj
 
2156
CvWR5GQgUJdp1Pw8TS9+rPy6SDv/+e3d+0+4qw8f3v20+PliV37efEYBAB9FTKC+RHn/Cfxn3rdv
 
2157
00Fube5O+iyCtHDs9BfPfz3q4sfFv9d91Ljhfy7ei0VO+nVTtdOkv/jpt0l2AX6iG1jXgKnnDuD4
 
2158
ke2k/i8fzzz5UedkVcP4pwF+Wvz2FJl+3vt598urXf5Y6LNA5WcFOP7r0sW7b9a+W/xcu0Xpv5zk
 
2159
Kfq3P9Dz9di/fCxS72MXVU1rpx9L4Bxl85Wmn5a+zP76Zuh3pL9ROWr87PN+//GHIl+oOtvn9XSU
 
2160
qH+p0gQBFnx1uV+JLH5O5zv+PXW+WepXVVHZT0+oQezkIATcIm+ivPV/z5J/+cYj3ir4w0Lx09vC
 
2161
e5n/y5/Y5LPPfdrqb88ga/PabxZRVfmp39l588m/6u+/e+OpP+dF7n1WZpJ9//Z4v372fDDz9eHB
 
2162
7Juvs/BLMHzrxL9+9twXpJfhd1/DrpQ5Euu/vlss3wp9HXC/54C/Ld69m6zwdx3tC0d8daSv0V8B
 
2163
n4b9YYF53sJelJV/ix6LZspw/sJtqyl5LJ5r/23htA1Imfm/gt9R7dqVB1LjhydAX4Gb+zksQF59
 
2164
9+P7H//U+376afFuvh2/T6P85Xr/5c8C6OXyFY4BGuN+EE0+GeR201b+wkkLN5mmBY5TfMw8ngqL
 
2165
CztXxCSXKMCYrRIElWkEJlEPYsSOeKBVZCAQTKBhApMwRFQzmCThE0YQu2CdEhgjbgmk9GluHpfR
 
2166
/hhwJCZhGI5jt5FsAkOrObVyE6g2y1snyhMGFlDY1x+BoHpCMulTj5JYWNAYJmnKpvLxXgmQ8az1
 
2167
4fUGxxcitMbbhDFcsiAItg04E+OSBIHTUYD1HI4FHH4kMREPknuYRMyhh3AARWMkfhCketqD1CWJ
 
2168
mTCo/nhUScoQcInB1hpFhIKoIXLo5jLpwFCgsnLCx1QlEMlz/iFEGqzH3vWYcpRcThgWnEKm0QcS
 
2169
rA8ek2a2IYYeowUanOZOlrbWSJUC4c7y2EMI3uJPMnMF/SSXdk6E495VLhzkWHps0rOhKwqk+xBI
 
2170
DhJirhdUCTamMfXz2Hy303hM4DFJ8QL21BcPBULR+gcdYxoeiDqOFSqpi5B5PUISfGg46gFZBPo4
 
2171
jdh8lueaWuVSMTURfbAUnLINr/QYuuYoMQV6l1aWxuZVTjlaLC14UzqZ+ziTGDzJzhiYoPLrt3uI
 
2172
tXkVR47kAo09lo5BD76CH51cTt1snVpMOttLhY93yxChCQPI4OBecS7++h4p4Bdn4H97bJongtPk
 
2173
s9gQnXku1vzsjjmX4/o4YUDkXkjHwDg5FXozU0fW4y5kyeYW0uJWlh536BKr0kMGjtzTkng6Ep62
 
2174
uTWnQtiIqKnEsx7e1hLtzlXs7Upw9TwEnp0t9yzCGgUJIZConx9OHJArLkRYW0dW42G9OeR5Nzwk
 
2175
yk1mX7du5RGHT7dka7N3AznmSif7y6tuKe2N1Al/1TUPRqH6E2GLVc27h9IptMLkCKQYRqPQJgzV
 
2176
2m6WLsSipS3v3b1/WmXEYY1meLEVIU/arOGVkyie7ZsH05ZKpjFW4cpY0YkjySpSExNG2TS8nnJx
 
2177
nrQmWh2WY3cP1eISP9wbaVK35ZXc60yC3VN/j9n7UFoK6zvjSTE2+Pvz6Mx322rnftfP8Y0XKIdv
 
2178
Qd7AfK0nexBTMqRiErvCMa3Hegpfjdh58glW2oNMsKeAX8x6YJLZs9K8/ozjJkWL+JmECMvhQ54x
 
2179
9rsTHwcoGrDi6Y4I+H7yY4/rJVPAbYymUH7C2D3uiUS3KQ1nrCAUkE1dJMneDQIJMQQx5SONxoEO
 
2180
OEn1/Ig1eBBUeEDRuOT2WGGGE4bNypBLFh2PeIg3bEbg44PHiqNDbGIQm50LW6MJU62JHCGBrmc9
 
2181
2F7WBJrrj1ssnTAK4sxwRgh5LLblhwNAclv3Gd+jC/etCfyfR8TMhcWQz8TBIbG8IIyAQ81w2n/C
 
2182
mHWAwRzxd3WoBY7BZnsqGOWrOCKwGkMMNfO0Kci/joZgEocLjNnzgcmdehPHJY0FudXgsr+v44TB
 
2183
I3jnMGnsK5veAhgi9iXGifkHMOC09Rh9cAw9sQ0asl6wKMk8mpzFYaaDSgG4F0wisQDDBRpjCINg
 
2184
FIxhlhQ31xdSkkk6odXZFpTYOQpOOgw9ugM2cDQ+2MYa7JsEirGBrOuxsQy5nPMRdYjsTJ/j1iNw
 
2185
FeSt1jY2+dd5yx1/pzZMOQXUIDcXeAzR7QlDRM8AMkUldXOmGmvYXPABjxqkYKO7VAY6JRU7kpXr
 
2186
+Epu2BU3qFFXClFi27784LrDZsJwbNlDw0JzhZ6M0SMXE4iBHehCpHVkrQhpTFn2dsvsZYkiPEEB
 
2187
GSEAwdiur9LS1U6P2U9JhGp4hnFpJo4FfkdJHcwV6Q5dV1Q9uNeeu7rV8PAjwdFg9RLtroifOr0k
 
2188
uOiRTo/obNPhQIf42Fr4mtThWoSjitEdAmFW66UCe8WFjPk1YVNpL9srFbond7jrLg8tqAasIMpy
 
2189
zkH0SY/6zVAwJrEc14zt14YRXdY+fcJ4qOd2XKB0/Kghw1ovd11t2o+zjt+txndo1ZDZ2T+uMVHT
 
2190
VSXhedBAHoJIID9xm6wPQI3cXY+HR7vxtrJuCKh6kbXaW5KkVeJsdsjqsYsOwYSh0w5sMbu7LF8J
 
2191
5T7U6LJdiTx+ca7RKlulGgS5Z1JSU2Llt32cHFipkaurtBrvNX5UtvNZjkufZ/r1/XyLl6yOpytL
 
2192
Km8Fn+y4wkhlqZP5db0rooqy7xdL4wxzFVTX+6HaxuQJK5E5B1neSSovZ9ALB8091dDbbjVxhWNY
 
2193
Ve5hn1VnI9OF0wpvaRm7SZuC1IRczwC7GnkhPt3muHV1YxUJfo+uh1sYnJy+vI0ZwuPV2uqWJYUH
 
2194
bmBsi1zmFSxHrqwA+WIzLrHkwW4r+bad7xbOzJCnKIa3S3YvrzEBK1Dc0emzJW+SqysQfdEDorQG
 
2195
9ZJlbQzEHQV8naPaF440YXzJk/7vHGK2xwuP+Gc5xITxyiP+WQ4x18oXHjFzCBy9kir1EFTAm0Zq
 
2196
LYwS8MpiGhtfxiBRDXpxDWxk9g9Q2fzPPAhS6VFDAc/aiNGatUkPtZIStZFQ1qD0IlJa/5ZPAi5J
 
2197
ySp1ETDomZMnvgiysZSBfMikrSDte/K5lqV6iwC5q7YN9I1dBZXUytDJNqU74MJsUyNNLAPopWK3
 
2198
tzmLkCiDyl7WQnj9sm7Kd5kzgpoccdNeMw/6zPVB3pUwMgi4C7hj4AMFAf4G27oXH8NNT9zll/sK
 
2199
S6wVlQwazjxWKWy20ZzXb9ne8ngGalPBWSUSj9xkc1drsXkZ8oOyvYT3e0rnYsGwx85xZB9wKeKg
 
2200
cJKZnamYwiaMymZvzk6wtDUkxmdUg0mPad0YHtvzpjEfp2iMxvORhnx0kCVLf5Qa43WJsVoyfEyI
 
2201
pzmf8ruM6xBr7dnBgzyxpqXuUPYaKahOaz1LrxNkS/Q3Ae5AC+xl6NbxAqXXlzghZBZHmOrM6Y6Y
 
2202
ctAkltwlF7SKEsShjVh7QHuxMU0a08/eiu3x3M+07OijMcKFFltByXrpk8w+JNnZpnp3CfgjV1Ax
 
2203
gUYCnWwYow42I5wHCcTzLXK0hMZN2DrPM/zCSqe9jRSlJnr70BPE4+zrwbk/xVIDHy2FAQyHoomT
 
2204
Tt5jiM68nBQut35Y0qLclLiQrutxt/c0OlSqXAC8VrxW97lGoRWzhOnifE2zbF05W4xuyhg7JTUL
 
2205
aqJ7SWDywhjlal0b+NLTpERBgnPW0+Nw99X2Ws72gOL27iER9jgzj7Uu09JaZ3n+hmCjjvZpjNst
 
2206
vOWWTbuLrg+/1ltX8WpPauEDEvcunIgTxuMEHweWKCx2KQ9DU/UKdO/3za4Szm2iHYL+ss9AAttm
 
2207
gZHq2pkUXFbV+FiJCKrpBms18zH75vax5jSo7FNunrVWY3Chvd8KKnHdaTt/6ealwaA1x17yTlft
 
2208
8VBle3nAE+7R0MScC3MJofNCCkA9PGKBgGMYEwfB2QO5j8zUqa8F/EkWKCzGQJ5EZ05HTly1B01E
 
2209
z813G5BY++RZ2sxbQS8ZveGPJNabp5kXAeoign6Tlt5+L8i5ZquY9+S+KEUHkmYMRFBxRrHnbl2X
 
2210
rVemKnG+oB1yd9+zT+4c43jQ0wWmQRR6mTCkY1q3VG05Y120ZzKOMBe6Vy7I5Vz4ygPB3yY4G0FP
 
2211
8RxiMx985YJPXsgRU58EuHj75gygTzejP+W/zKGe78UQN3yOJ1aMQV9hFH+GAfLRsza84WlPLAI/
 
2212
9G/5JdcHftEfH+Y3/fHUG7/o8bv98dzzy3e8S+XCvgqB+VUf7sH0yDHpONdbRE8tAg9NWOzcTJ7q
 
2213
TuAxe/AJ07c1Rs9okJvl1/0G60qvbdDzz5zO0FuPFQIHNp9y9Bd1CufYVx7dB26mAxwa8GMNrN/U
 
2214
oGbNZ3EQ7inLzHy5tRg9AXJrN8cB59cCUBeCiVO7zKM0jU0MamhnRThkg/NMmBOGb6StNeD9tDfA
 
2215
7czsAWopDdnGoXUHtA+s/k0vNPkBcxEI13jVd/axp85va3LpwGggXXWw12Gwr/JGAH0b8CPboiZd
 
2216
QO1l0mk/UHukud4C+w5uRoNzpCmoW6GbgbMyaQNkga2pQINB18lOXOCJzSWPFOhZcwzdgrsQnne7
 
2217
nvjBi+7cP2BbtBeDOW5uOLGf3z94FasKIguOqJl+8ss/6Kumns4cuWbqq5592TN/RNIbn5Qo6qbi
 
2218
O4F0P9txxPAwagqPlftztO8cWBzdN/jz3b7GD6JHYP/Zp4ToAMaA74M+EGSft3hEGMuf8EwjnTk/
 
2219
nz/P7SLipB/ogQ6xNX0fDqNncMCfHqGLCMM0ZzFa+6lPJYQ5p81vW4HkCvidYf6kb+P/oB965g8K
 
2220
C6uR0rdjX1DNKc5pOSTquI8uQ6KXxYaKBn+30/09tK4kMpJPgUIQkbENEPbuezNPPje2Um83SgyX
 
2221
GTCJb6MnGVIpgncdQg1qz2bvPfxYD9fewCXDomx9S+HQJuX6W3VAL+v5WZMudRQZk9ZdOk6GIUtC
 
2222
PqEb/uwSIrtR7/edzqgEdtpEwq7p2J5OQV+RLrmtTvFwFpf03M/VrRyTZ73qVod7v7Jh2Dwe5J25
 
2223
JqFOU2qEu1sP+CRotklediycKfLjeIZzjJQsvKmiGSNQhxuJpKa+hoWUizaE1PuIRGzJqropwgVB
 
2224
oo1hr870MZLgnXF5ZIpr6mF0L8aSy2gVnTAuoB4WEd4d5NPVC9TMotYXERKlTcwQ2KiB/C48AEfH
 
2225
Qbyq4CN8xTFnTvf/ebOc3isnjD95s0QF0nx9s+y+zMmz782xL0SgEmRpA3x1w1Ff9/74xcxKEPdS
 
2226
IEFTz6GgU0+BK/UZ5Gwbl4gZwycxEw+Kqa5QmMkh4OzgzEVPnDAiAOGBFaBW4wkDmj1G4RyElKgj
 
2227
NlLCq8zsp085MNh/+R4t1Q8yxoSv8PUpTt7izZwf2BTHZZ3pIZpUIpuLkL1nNL6sYcHqcKm237wp
 
2228
T2+RCjgXweXd2Zp7ZM8W6dG5bZsqo0nrJBTx8EC0+CQQdzEGnabTnkzofu1pYkWl4E7XSniECdxy
 
2229
vLYavPMcL9LW5SToJFNnos+uqweOHriUZ1ntIYZUonc7ltEQ6oTRtwOHNwez2sVREskHN+bqG3ua
 
2230
eaEbJ8XpyO8CeD9QJc8nbLP2C2R3A437ISUNyt5Yd0TbDNcl11/DSsOzdbi/VhCC0KE6v1vqVNkq
 
2231
45ZnG6fiV2NwzInxCNth3BwL0+8814jE6+1W1EeWtpWbSZJOJNYXmWRXa7vLnAljE692eHjZ4y5u
 
2232
y1u63De0IzKca7As48Z3XshVF+3XiLNz0JIMh/JOpbiNLlMi672uO0wYzOCZjRxcxj3D+gVenGIE
 
2233
MvFUGGXuRps2RzMcgWIRolHXpGUP6sMsQt1hspUBnVKUn/WQj2u6j3SXd9Xz0QtEzoM7qTu5y7gR
 
2234
q9gNNsrlEMLdikBt9bFvBnfbUIh6voTw7eDsyTmPKUvF0bHqWLbHe3VRHyRZnNeSGKsB73q66Vsk
 
2235
taxWYmwz1tYVFG/vOQhlM0gUkyvIab3nv2caJ1udU1F3pDMty7stubTE4OJqm0i0ECfrJIkLtraC
 
2236
HwRWKzlqpfhEIqYH09eT9WrOhQyt8YEoyBlnXtAT37WHIQ03TIuEHbnRxZDdLun0iok9PUC79prU
 
2237
m5beZzfQUelEXnhzb/pIROKx3F7qCttYIFGh5dXNzFzID7u8vKykA8Uejf7XXz//S4nKvW//ofS/
 
2238
QastYw==
 
2239
""")
 
2240
 
 
2241
##file distutils-init.py
 
2242
DISTUTILS_INIT = convert("""
 
2243
eJytV92L4zYQf9dfMU0ottuse7RvC6FQrg8Lxz2Ugz4si9HacqKuIxlJ2ST313fG8odkO9d7qGFB
 
2244
keZLv/nNjFaeWm0caMukX9nbuLxwo6Q6WBg2dFvqSsB2WEgLSjvg8C6NO/NGqHc46erciB1YDRcB
 
2245
JVdwtijpwGmoparAHQVYVzXylUH0beGpc8OV+wG+oLo2b6AVtLf2tkM19HY6WwevAj16N7jLHRhh
 
2246
ZSUsSEXGF1bR00N7c0etfkEtWUtRPVzzW/4VKmlE6bS5MYZLxU8C9ghF3nJ3zPsdOrLu7GRjC9oP
 
2247
JP7RUqUz8dRDkxdFLRtRFNkOktFAkjFZj+pKmxMt0thBBvtFEOlCZ7SfPXYXHnKV0yIdMdh8QbSD
 
2248
7IyuoOXlGz8glA5+tMDbVnBjKUkIrwcSLAHS6JI7iWng1m/erBOnydDvm4yJxgofRtFdoShyqaww
 
2249
Lv2wg9ntOjFxFSUiJSb4OixjUUSuKKSSDs21tyTLciN4lWYZY7XRQQjQ05M2dhRgqVUtD4w5c/Nh
 
2250
vXIrrDMIEBPXUrQOPuPd/jRGm7kA5hcXjG23CJErj/B6lk1ViKuDKT6otLAqcfCm9AWO+IfAHYTr
 
2251
EEK+2YBa3tCRmHxB/uuLhQeqhyM3FVHFw0oimAajz32JdM5FRdfJWyNqecV7I3u63w13NTKBmJKg
 
2252
0d9+Tfw1YlzyUp9OXFX5dIUeqWkDs6pxOW50ZsqGWzsJpZFETzj6KlFTTfNGfhWFbokmFlIrmjoQ
 
2253
oo/ixt0coTHc3ApEx1L3+KyVeJwVLKyI7uH5JRITDZqUFlmG7aIU6UJlF6Q0+z4Xi73cto10A0Wt
 
2254
aLPIDvumwaACIo5T/pDHTeGTuoPNJ+TLJottR4jnc4w9xMtg1tO/mvTxR9F3Ul8Gs92AOfvpsCuO
 
2255
yQ2terraR8YodGr0ha/Crk8RvCSWf5SUktczXSNfSLGeUPFuSKi6q489rDoJYPFdqpgKdta1F50m
 
2256
QK0+JN7INmjW4ooCNp3b7cPajrEFaV/Ijgnbwt80t7BnlLxpfLkL84CD0oC/ENCFWF86GIOfTVjt
 
2257
rbbymkyEJp3u9v302mCrjO6y8Q137NCrSqs6c6kFjQcGR4JZEHUnLi0dpbHQFAv2MeyGOFFw6DQY
 
2258
RNrBuOwfJJMLVdmLxPGXzCJOVmrc58OIk34XKalnLD6ioaeqdCV8I9zZKC/GvoO4iM6SzHGVjGNp
 
2259
Vio4NQr/OsFZV1IbGgTz+KgrjvFwppfSSChsK0p835R7ZJ9Pzp46bI8Ngug3l5233++ch90pBGMZ
 
2260
bOx0cJmxe0Hio6jSZVH09bt+yO7dP4RmprtAEhvxPSTp3XkXSTxcIkkjpsJhTad3kQ2FgJru/wj1
 
2261
Iqo4pv8AHiXuAx8crgM/Q3KmOwHfH79zP0ojU8HZCvTBafoTN4ehp3bY9PZWvPSyI/7fehbRh9HS
 
2262
XF7rY/E4brpxPOrF74wxKHrXli7rUp18evrj49NfSffPELaxUSjuSeP286DwgtEMcW1xKr/he4/6
 
2263
IQ6FUXP+0gkioHY5iwC9Eyx3HKO7af0zPPe+XyLnZDUk46jB7uZthV8rp+wuKxYMCxnzL9Vk9s4=
 
2264
""")
 
2265
 
 
2266
##file distutils.cfg
 
2267
DISTUTILS_CFG = convert("""
 
2268
eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
 
2269
xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
 
2270
9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
 
2271
""")
 
2272
 
 
2273
##file activate_this.py
 
2274
ACTIVATE_THIS = convert("""
 
2275
eJyNU01v2zAMvetXEB4K21jmDOstQA4dMGCHbeihlyEIDMWmG62yJEiKE//7kXKdpN2KzYBt8euR
 
2276
fKSyLPs8wiEo8wh4wqZTGou4V6Hm0wJa1cSiTkJdr8+GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe
 
2277
5a3p0cRKiAe2NtLADikftnDco0ko/SFEVgEZ8aRC5GLux7i3BpSJ6J1H+i7A2CjiHq9z7JRZuuQq
 
2278
siwTIvpxJYCeuWaBpwZdhB+yxy/eWz+ZvVSU8C4E9FFZkyxFsvCT/ZzL8gcz9aXVE14Yyp2M+2W0
 
2279
y7n5mp0qN+avKXvbsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCZN9UzlJr+/e/iab8WfqsmPI6pWeUPd
 
2280
FrMsd4H/55poeO9n54COhUs+sZNEzNtg/wanpjpuqHJaxs76HtZryI/K3H7KJ/KDIhqcbJ7kI4ar
 
2281
XL+sMgXnX0D+Te2Iy5xdP8yueSlQB/x/ED2BTAtyE3K4SYUN6AMNfbO63f4lBW3bUJPbTL+mjSxS
 
2282
PyRfJkZRgj+VbFv+EzHFi5pKwUEepa4JslMnwkowSRCXI+m5XvEOvtuBrxHdhLalG0JofYBok6qj
 
2283
YdN2dEngUlbC4PG60M1WEN0piu7Nq7on0mgyyUw3iV1etLo6r/81biWdQ9MWHFaePWZYaq+nmp+t
 
2284
s3az+sj7eA0jfgPfeoN1
 
2285
""")
 
2286
 
 
2287
MH_MAGIC = 0xfeedface
 
2288
MH_CIGAM = 0xcefaedfe
 
2289
MH_MAGIC_64 = 0xfeedfacf
 
2290
MH_CIGAM_64 = 0xcffaedfe
 
2291
FAT_MAGIC = 0xcafebabe
 
2292
BIG_ENDIAN = '>'
 
2293
LITTLE_ENDIAN = '<'
 
2294
LC_LOAD_DYLIB = 0xc
 
2295
maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint')
 
2296
 
 
2297
 
 
2298
class fileview(object):
 
2299
    """
 
2300
    A proxy for file-like objects that exposes a given view of a file.
 
2301
    Modified from macholib.
 
2302
    """
 
2303
 
 
2304
    def __init__(self, fileobj, start=0, size=maxint):
 
2305
        if isinstance(fileobj, fileview):
 
2306
            self._fileobj = fileobj._fileobj
 
2307
        else:
 
2308
            self._fileobj = fileobj
 
2309
        self._start = start
 
2310
        self._end = start + size
 
2311
        self._pos = 0
 
2312
 
 
2313
    def __repr__(self):
 
2314
        return '<fileview [%d, %d] %r>' % (
 
2315
            self._start, self._end, self._fileobj)
 
2316
 
 
2317
    def tell(self):
 
2318
        return self._pos
 
2319
 
 
2320
    def _checkwindow(self, seekto, op):
 
2321
        if not (self._start <= seekto <= self._end):
 
2322
            raise IOError("%s to offset %d is outside window [%d, %d]" % (
 
2323
                op, seekto, self._start, self._end))
 
2324
 
 
2325
    def seek(self, offset, whence=0):
 
2326
        seekto = offset
 
2327
        if whence == os.SEEK_SET:
 
2328
            seekto += self._start
 
2329
        elif whence == os.SEEK_CUR:
 
2330
            seekto += self._start + self._pos
 
2331
        elif whence == os.SEEK_END:
 
2332
            seekto += self._end
 
2333
        else:
 
2334
            raise IOError("Invalid whence argument to seek: %r" % (whence,))
 
2335
        self._checkwindow(seekto, 'seek')
 
2336
        self._fileobj.seek(seekto)
 
2337
        self._pos = seekto - self._start
 
2338
 
 
2339
    def write(self, bytes):
 
2340
        here = self._start + self._pos
 
2341
        self._checkwindow(here, 'write')
 
2342
        self._checkwindow(here + len(bytes), 'write')
 
2343
        self._fileobj.seek(here, os.SEEK_SET)
 
2344
        self._fileobj.write(bytes)
 
2345
        self._pos += len(bytes)
 
2346
 
 
2347
    def read(self, size=maxint):
 
2348
        assert size >= 0
 
2349
        here = self._start + self._pos
 
2350
        self._checkwindow(here, 'read')
 
2351
        size = min(size, self._end - here)
 
2352
        self._fileobj.seek(here, os.SEEK_SET)
 
2353
        bytes = self._fileobj.read(size)
 
2354
        self._pos += len(bytes)
 
2355
        return bytes
 
2356
 
 
2357
 
 
2358
def read_data(file, endian, num=1):
 
2359
    """
 
2360
    Read a given number of 32-bits unsigned integers from the given file
 
2361
    with the given endianness.
 
2362
    """
 
2363
    res = struct.unpack(endian + 'L' * num, file.read(num * 4))
 
2364
    if len(res) == 1:
 
2365
        return res[0]
 
2366
    return res
 
2367
 
 
2368
 
 
2369
def mach_o_change(path, what, value):
 
2370
    """
 
2371
    Replace a given name (what) in any LC_LOAD_DYLIB command found in
 
2372
    the given binary with a new name (value), provided it's shorter.
 
2373
    """
 
2374
 
 
2375
    def do_macho(file, bits, endian):
 
2376
        # Read Mach-O header (the magic number is assumed read by the caller)
 
2377
        cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6)
 
2378
        # 64-bits header has one more field.
 
2379
        if bits == 64:
 
2380
            read_data(file, endian)
 
2381
        # The header is followed by ncmds commands
 
2382
        for n in range(ncmds):
 
2383
            where = file.tell()
 
2384
            # Read command header
 
2385
            cmd, cmdsize = read_data(file, endian, 2)
 
2386
            if cmd == LC_LOAD_DYLIB:
 
2387
                # The first data field in LC_LOAD_DYLIB commands is the
 
2388
                # offset of the name, starting from the beginning of the
 
2389
                # command.
 
2390
                name_offset = read_data(file, endian)
 
2391
                file.seek(where + name_offset, os.SEEK_SET)
 
2392
                # Read the NUL terminated string
 
2393
                load = file.read(cmdsize - name_offset)
 
2394
                load = load[:load.index('\0')]
 
2395
                # If the string is what is being replaced, overwrite it.
 
2396
                if load == what:
 
2397
                    file.seek(where + name_offset, os.SEEK_SET)
 
2398
                    file.write(value + '\0')
 
2399
            # Seek to the next command
 
2400
            file.seek(where + cmdsize, os.SEEK_SET)
 
2401
 
 
2402
    def do_file(file, offset=0, size=maxint):
 
2403
        file = fileview(file, offset, size)
 
2404
        # Read magic number
 
2405
        magic = read_data(file, BIG_ENDIAN)
 
2406
        if magic == FAT_MAGIC:
 
2407
            # Fat binaries contain nfat_arch Mach-O binaries
 
2408
            nfat_arch = read_data(file, BIG_ENDIAN)
 
2409
            for n in range(nfat_arch):
 
2410
                # Read arch header
 
2411
                cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5)
 
2412
                do_file(file, offset, size)
 
2413
        elif magic == MH_MAGIC:
 
2414
            do_macho(file, 32, BIG_ENDIAN)
 
2415
        elif magic == MH_CIGAM:
 
2416
            do_macho(file, 32, LITTLE_ENDIAN)
 
2417
        elif magic == MH_MAGIC_64:
 
2418
            do_macho(file, 64, BIG_ENDIAN)
 
2419
        elif magic == MH_CIGAM_64:
 
2420
            do_macho(file, 64, LITTLE_ENDIAN)
 
2421
 
 
2422
    assert(len(what) >= len(value))
 
2423
    do_file(open(path, 'r+b'))
 
2424
 
 
2425
 
 
2426
if __name__ == '__main__':
 
2427
    main()
 
2428
 
 
2429
## TODO:
 
2430
## Copy python.exe.manifest
 
2431
## Monkeypatch distutils.sysconfig