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.
7virtualenv_version = "1.7"
8
9import base64
10import sys
11import os
12import optparse
13import re
14import shutil
15import logging
16import tempfile
17import zlib
18import errno
19import distutils.sysconfig
20from distutils.util import strtobool
21
22try:
23    import subprocess
24except ImportError:
25    if sys.version_info <= (2, 3):
26        print('ERROR: %s' % sys.exc_info()[1])
27        print('ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.')
28        print('If you copy subprocess.py from a newer version of Python this script will probably work')
29        sys.exit(101)
30    else:
31        raise
32try:
33    set
34except NameError:
35    from sets import Set as set
36try:
37    basestring
38except NameError:
39    basestring = str
40
41try:
42    import ConfigParser
43except ImportError:
44    import configparser as ConfigParser
45
46join = os.path.join
47py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
48
49is_jython = sys.platform.startswith('java')
50is_pypy = hasattr(sys, 'pypy_version_info')
51is_win  = (sys.platform == 'win32')
52abiflags = getattr(sys, 'abiflags', '')
53
54user_dir = os.path.expanduser('~')
55if sys.platform == 'win32':
56    user_dir = os.environ.get('APPDATA', user_dir)  # Use %APPDATA% for roaming
57    default_storage_dir = os.path.join(user_dir, 'virtualenv')
58else:
59    default_storage_dir = os.path.join(user_dir, '.virtualenv')
60default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini')
61
62if is_pypy:
63    expected_exe = 'pypy'
64elif is_jython:
65    expected_exe = 'jython'
66else:
67    expected_exe = 'python'
68
69
70REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
71                    'fnmatch', 'locale', 'encodings', 'codecs',
72                    'stat', 'UserDict', 'readline', 'copy_reg', 'types',
73                    're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
74                    'zlib']
75
76REQUIRED_FILES = ['lib-dynload', 'config']
77
78majver, minver = sys.version_info[:2]
79if majver == 2:
80    if minver >= 6:
81        REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc'])
82    if minver >= 7:
83        REQUIRED_MODULES.extend(['_weakrefset'])
84    if minver <= 3:
85        REQUIRED_MODULES.extend(['sets', '__future__'])
86elif majver == 3:
87    # Some extra modules are needed for Python 3, but different ones
88    # for different versions.
89    REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
90                             '_weakrefset', 'copyreg', 'tempfile', 'random',
91                             '__future__', 'collections', 'keyword', 'tarfile',
92                             'shutil', 'struct', 'copy'])
93    if minver >= 2:
94        REQUIRED_FILES[-1] = 'config-%s' % majver
95    if minver == 3:
96        # The whole list of 3.3 modules is reproduced below - the current
97        # uncommented ones are required for 3.3 as of now, but more may be
98        # added as 3.3 development continues.
99        REQUIRED_MODULES.extend([
100            #"aifc",
101            #"antigravity",
102            #"argparse",
103            #"ast",
104            #"asynchat",
105            #"asyncore",
106            "base64",
107            #"bdb",
108            #"binhex",
109            "bisect",
110            #"calendar",
111            #"cgi",
112            #"cgitb",
113            #"chunk",
114            #"cmd",
115            #"codeop",
116            #"code",
117            #"colorsys",
118            #"_compat_pickle",
119            #"compileall",
120            #"concurrent",
121            #"configparser",
122            #"contextlib",
123            #"cProfile",
124            #"crypt",
125            #"csv",
126            #"ctypes",
127            #"curses",
128            #"datetime",
129            #"dbm",
130            #"decimal",
131            #"difflib",
132            #"dis",
133            #"doctest",
134            #"dummy_threading",
135            "_dummy_thread",
136            #"email",
137            #"filecmp",
138            #"fileinput",
139            #"formatter",
140            #"fractions",
141            #"ftplib",
142            #"functools",
143            #"getopt",
144            #"getpass",
145            #"gettext",
146            #"glob",
147            #"gzip",
148            "hashlib",
149            "heapq",
150            "hmac",
151            #"html",
152            #"http",
153            #"idlelib",
154            #"imaplib",
155            #"imghdr",
156            #"importlib",
157            #"inspect",
158            #"json",
159            #"lib2to3",
160            #"logging",
161            #"macpath",
162            #"macurl2path",
163            #"mailbox",
164            #"mailcap",
165            #"_markupbase",
166            #"mimetypes",
167            #"modulefinder",
168            #"multiprocessing",
169            #"netrc",
170            #"nntplib",
171            #"nturl2path",
172            #"numbers",
173            #"opcode",
174            #"optparse",
175            #"os2emxpath",
176            #"pdb",
177            #"pickle",
178            #"pickletools",
179            #"pipes",
180            #"pkgutil",
181            #"platform",
182            #"plat-linux2",
183            #"plistlib",
184            #"poplib",
185            #"pprint",
186            #"profile",
187            #"pstats",
188            #"pty",
189            #"pyclbr",
190            #"py_compile",
191            #"pydoc_data",
192            #"pydoc",
193            #"_pyio",
194            #"queue",
195            #"quopri",
196            "reprlib",
197            "rlcompleter",
198            #"runpy",
199            #"sched",
200            #"shelve",
201            #"shlex",
202            #"smtpd",
203            #"smtplib",
204            #"sndhdr",
205            #"socket",
206            #"socketserver",
207            #"sqlite3",
208            #"ssl",
209            #"stringprep",
210            #"string",
211            #"_strptime",
212            #"subprocess",
213            #"sunau",
214            #"symbol",
215            #"symtable",
216            #"sysconfig",
217            #"tabnanny",
218            #"telnetlib",
219            #"test",
220            #"textwrap",
221            #"this",
222            #"_threading_local",
223            #"threading",
224            #"timeit",
225            #"tkinter",
226            #"tokenize",
227            #"token",
228            #"traceback",
229            #"trace",
230            #"tty",
231            #"turtledemo",
232            #"turtle",
233            #"unittest",
234            #"urllib",
235            #"uuid",
236            #"uu",
237            #"wave",
238            "weakref",
239            #"webbrowser",
240            #"wsgiref",
241            #"xdrlib",
242            #"xml",
243            #"xmlrpc",
244            #"zipfile",
245        ])
246
247if is_pypy:
248    # these are needed to correctly display the exceptions that may happen
249    # during the bootstrap
250    REQUIRED_MODULES.extend(['traceback', 'linecache'])
251
252class Logger(object):
253
254    """
255    Logging object for use in command-line script.  Allows ranges of
256    levels, to avoid some redundancy of displayed information.
257    """
258
259    DEBUG = logging.DEBUG
260    INFO = logging.INFO
261    NOTIFY = (logging.INFO+logging.WARN)/2
262    WARN = WARNING = logging.WARN
263    ERROR = logging.ERROR
264    FATAL = logging.FATAL
265
266    LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
267
268    def __init__(self, consumers):
269        self.consumers = consumers
270        self.indent = 0
271        self.in_progress = None
272        self.in_progress_hanging = False
273
274    def debug(self, msg, *args, **kw):
275        self.log(self.DEBUG, msg, *args, **kw)
276    def info(self, msg, *args, **kw):
277        self.log(self.INFO, msg, *args, **kw)
278    def notify(self, msg, *args, **kw):
279        self.log(self.NOTIFY, msg, *args, **kw)
280    def warn(self, msg, *args, **kw):
281        self.log(self.WARN, msg, *args, **kw)
282    def error(self, msg, *args, **kw):
283        self.log(self.WARN, msg, *args, **kw)
284    def fatal(self, msg, *args, **kw):
285        self.log(self.FATAL, msg, *args, **kw)
286    def log(self, level, msg, *args, **kw):
287        if args:
288            if kw:
289                raise TypeError(
290                    "You may give positional or keyword arguments, not both")
291        args = args or kw
292        rendered = None
293        for consumer_level, consumer in self.consumers:
294            if self.level_matches(level, consumer_level):
295                if (self.in_progress_hanging
296                    and consumer in (sys.stdout, sys.stderr)):
297                    self.in_progress_hanging = False
298                    sys.stdout.write('\n')
299                    sys.stdout.flush()
300                if rendered is None:
301                    if args:
302                        rendered = msg % args
303                    else:
304                        rendered = msg
305                    rendered = ' '*self.indent + rendered
306                if hasattr(consumer, 'write'):
307                    consumer.write(rendered+'\n')
308                else:
309                    consumer(rendered)
310
311    def start_progress(self, msg):
312        assert not self.in_progress, (
313            "Tried to start_progress(%r) while in_progress %r"
314            % (msg, self.in_progress))
315        if self.level_matches(self.NOTIFY, self._stdout_level()):
316            sys.stdout.write(msg)
317            sys.stdout.flush()
318            self.in_progress_hanging = True
319        else:
320            self.in_progress_hanging = False
321        self.in_progress = msg
322
323    def end_progress(self, msg='done.'):
324        assert self.in_progress, (
325            "Tried to end_progress without start_progress")
326        if self.stdout_level_matches(self.NOTIFY):
327            if not self.in_progress_hanging:
328                # Some message has been printed out since start_progress
329                sys.stdout.write('...' + self.in_progress + msg + '\n')
330                sys.stdout.flush()
331            else:
332                sys.stdout.write(msg + '\n')
333                sys.stdout.flush()
334        self.in_progress = None
335        self.in_progress_hanging = False
336
337    def show_progress(self):
338        """If we are in a progress scope, and no log messages have been
339        shown, write out another '.'"""
340        if self.in_progress_hanging:
341            sys.stdout.write('.')
342            sys.stdout.flush()
343
344    def stdout_level_matches(self, level):
345        """Returns true if a message at this level will go to stdout"""
346        return self.level_matches(level, self._stdout_level())
347
348    def _stdout_level(self):
349        """Returns the level that stdout runs at"""
350        for level, consumer in self.consumers:
351            if consumer is sys.stdout:
352                return level
353        return self.FATAL
354
355    def level_matches(self, level, consumer_level):
356        """
357        >>> l = Logger([])
358        >>> l.level_matches(3, 4)
359        False
360        >>> l.level_matches(3, 2)
361        True
362        >>> l.level_matches(slice(None, 3), 3)
363        False
364        >>> l.level_matches(slice(None, 3), 2)
365        True
366        >>> l.level_matches(slice(1, 3), 1)
367        True
368        >>> l.level_matches(slice(2, 3), 1)
369        False
370        """
371        if isinstance(level, slice):
372            start, stop = level.start, level.stop
373            if start is not None and start > consumer_level:
374                return False
375            if stop is not None and stop <= consumer_level:
376                return False
377            return True
378        else:
379            return level >= consumer_level
380
381    #@classmethod
382    def level_for_integer(cls, level):
383        levels = cls.LEVELS
384        if level < 0:
385            return levels[0]
386        if level >= len(levels):
387            return levels[-1]
388        return levels[level]
389
390    level_for_integer = classmethod(level_for_integer)
391
392# create a silent logger just to prevent this from being undefined
393# will be overridden with requested verbosity main() is called.
394logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
395
396def mkdir(path):
397    if not os.path.exists(path):
398        logger.info('Creating %s', path)
399        os.makedirs(path)
400    else:
401        logger.info('Directory %s already exists', path)
402
403def copyfileordir(src, dest):
404    if os.path.isdir(src):
405        shutil.copytree(src, dest, True)
406    else:
407        shutil.copy2(src, dest)
408
409def copyfile(src, dest, symlink=True):
410    if not os.path.exists(src):
411        # Some bad symlink in the src
412        logger.warn('Cannot find file %s (bad symlink)', src)
413        return
414    if os.path.exists(dest):
415        logger.debug('File %s already exists', dest)
416        return
417    if not os.path.exists(os.path.dirname(dest)):
418        logger.info('Creating parent directories for %s' % os.path.dirname(dest))
419        os.makedirs(os.path.dirname(dest))
420    if not os.path.islink(src):
421        srcpath = os.path.abspath(src)
422    else:
423        srcpath = os.readlink(src)
424    if symlink and hasattr(os, 'symlink'):
425        logger.info('Symlinking %s', dest)
426        try:
427            os.symlink(srcpath, dest)
428        except (OSError, NotImplementedError):
429            logger.info('Symlinking failed, copying to %s', dest)
430            copyfileordir(src, dest)
431    else:
432        logger.info('Copying to %s', dest)
433        copyfileordir(src, dest)
434
435def writefile(dest, content, overwrite=True):
436    if not os.path.exists(dest):
437        logger.info('Writing %s', dest)
438        f = open(dest, 'wb')
439        f.write(content.encode('utf-8'))
440        f.close()
441        return
442    else:
443        f = open(dest, 'rb')
444        c = f.read()
445        f.close()
446        if c != content:
447            if not overwrite:
448                logger.notify('File %s exists with different content; not overwriting', dest)
449                return
450            logger.notify('Overwriting %s with new content', dest)
451            f = open(dest, 'wb')
452            f.write(content.encode('utf-8'))
453            f.close()
454        else:
455            logger.info('Content %s already in place', dest)
456
457def rmtree(dir):
458    if os.path.exists(dir):
459        logger.notify('Deleting tree %s', dir)
460        shutil.rmtree(dir)
461    else:
462        logger.info('Do not need to delete %s; already gone', dir)
463
464def make_exe(fn):
465    if hasattr(os, 'chmod'):
466        oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777
467        newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777
468        os.chmod(fn, newmode)
469        logger.info('Changed mode of %s to %s', fn, oct(newmode))
470
471def _find_file(filename, dirs):
472    for dir in dirs:
473        if os.path.exists(join(dir, filename)):
474            return join(dir, filename)
475    return filename
476
477def _install_req(py_executable, unzip=False, distribute=False,
478                 search_dirs=None, never_download=False):
479
480    if search_dirs is None:
481        search_dirs = file_search_dirs()
482
483    if not distribute:
484        setup_fn = 'setuptools-0.6c11-py%s.egg' % sys.version[:3]
485        project_name = 'setuptools'
486        bootstrap_script = EZ_SETUP_PY
487        source = None
488    else:
489        setup_fn = None
490        source = 'distribute-0.6.24.tar.gz'
491        project_name = 'distribute'
492        bootstrap_script = DISTRIBUTE_SETUP_PY
493
494    if setup_fn is not None:
495        setup_fn = _find_file(setup_fn, search_dirs)
496
497    if source is not None:
498        source = _find_file(source, search_dirs)
499
500    if is_jython and os._name == 'nt':
501        # Jython's .bat sys.executable can't handle a command line
502        # argument with newlines
503        fd, ez_setup = tempfile.mkstemp('.py')
504        os.write(fd, bootstrap_script)
505        os.close(fd)
506        cmd = [py_executable, ez_setup]
507    else:
508        cmd = [py_executable, '-c', bootstrap_script]
509    if unzip:
510        cmd.append('--always-unzip')
511    env = {}
512    remove_from_env = []
513    if logger.stdout_level_matches(logger.DEBUG):
514        cmd.append('-v')
515
516    old_chdir = os.getcwd()
517    if setup_fn is not None and os.path.exists(setup_fn):
518        logger.info('Using existing %s egg: %s' % (project_name, setup_fn))
519        cmd.append(setup_fn)
520        if os.environ.get('PYTHONPATH'):
521            env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH']
522        else:
523            env['PYTHONPATH'] = setup_fn
524    else:
525        # the source is found, let's chdir
526        if source is not None and os.path.exists(source):
527            logger.info('Using existing %s egg: %s' % (project_name, source))
528            os.chdir(os.path.dirname(source))
529            # in this case, we want to be sure that PYTHONPATH is unset (not
530            # just empty, really unset), else CPython tries to import the
531            # site.py that it's in virtualenv_support
532            remove_from_env.append('PYTHONPATH')
533        else:
534            if never_download:
535                logger.fatal("Can't find any local distributions of %s to install "
536                             "and --never-download is set.  Either re-run virtualenv "
537                             "without the --never-download option, or place a %s "
538                             "distribution (%s) in one of these "
539                             "locations: %r" % (project_name, project_name,
540                                                setup_fn or source,
541                                                search_dirs))
542                sys.exit(1)
543
544            logger.info('No %s egg found; downloading' % project_name)
545        cmd.extend(['--always-copy', '-U', project_name])
546    logger.start_progress('Installing %s...' % project_name)
547    logger.indent += 2
548    cwd = None
549    if project_name == 'distribute':
550        env['DONT_PATCH_SETUPTOOLS'] = 'true'
551
552    def _filter_ez_setup(line):
553        return filter_ez_setup(line, project_name)
554
555    if not os.access(os.getcwd(), os.W_OK):
556        cwd = tempfile.mkdtemp()
557        if source is not None and os.path.exists(source):
558            # the current working dir is hostile, let's copy the
559            # tarball to a temp dir
560            target = os.path.join(cwd, os.path.split(source)[-1])
561            shutil.copy(source, target)
562    try:
563        call_subprocess(cmd, show_stdout=False,
564                        filter_stdout=_filter_ez_setup,
565                        extra_env=env,
566                        remove_from_env=remove_from_env,
567                        cwd=cwd)
568    finally:
569        logger.indent -= 2
570        logger.end_progress()
571        if os.getcwd() != old_chdir:
572            os.chdir(old_chdir)
573        if is_jython and os._name == 'nt':
574            os.remove(ez_setup)
575
576def file_search_dirs():
577    here = os.path.dirname(os.path.abspath(__file__))
578    dirs = ['.', here,
579            join(here, 'virtualenv_support')]
580    if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
581        # Probably some boot script; just in case virtualenv is installed...
582        try:
583            import virtualenv
584        except ImportError:
585            pass
586        else:
587            dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
588    return [d for d in dirs if os.path.isdir(d)]
589
590def install_setuptools(py_executable, unzip=False,
591                       search_dirs=None, never_download=False):
592    _install_req(py_executable, unzip,
593                 search_dirs=search_dirs, never_download=never_download)
594
595def install_distribute(py_executable, unzip=False,
596                       search_dirs=None, never_download=False):
597    _install_req(py_executable, unzip, distribute=True,
598                 search_dirs=search_dirs, never_download=never_download)
599
600_pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I)
601def install_pip(py_executable, search_dirs=None, never_download=False):
602    if search_dirs is None:
603        search_dirs = file_search_dirs()
604
605    filenames = []
606    for dir in search_dirs:
607        filenames.extend([join(dir, fn) for fn in os.listdir(dir)
608                          if _pip_re.search(fn)])
609    filenames = [(os.path.basename(filename).lower(), i, filename) for i, filename in enumerate(filenames)]
610    filenames.sort()
611    filenames = [filename for basename, i, filename in filenames]
612    if not filenames:
613        filename = 'pip'
614    else:
615        filename = filenames[-1]
616    easy_install_script = 'easy_install'
617    if sys.platform == 'win32':
618        easy_install_script = 'easy_install-script.py'
619    cmd = [join(os.path.dirname(py_executable), easy_install_script), filename]
620    if sys.platform == 'win32':
621        cmd.insert(0, py_executable)
622    if filename == 'pip':
623        if never_download:
624            logger.fatal("Can't find any local distributions of pip to install "
625                         "and --never-download is set.  Either re-run virtualenv "
626                         "without the --never-download option, or place a pip "
627                         "source distribution (zip/tar.gz/tar.bz2) in one of these "
628                         "locations: %r" % search_dirs)
629            sys.exit(1)
630        logger.info('Installing pip from network...')
631    else:
632        logger.info('Installing existing %s distribution: %s' % (
633                os.path.basename(filename), filename))
634    logger.start_progress('Installing pip...')
635    logger.indent += 2
636    def _filter_setup(line):
637        return filter_ez_setup(line, 'pip')
638    try:
639        call_subprocess(cmd, show_stdout=False,
640                        filter_stdout=_filter_setup)
641    finally:
642        logger.indent -= 2
643        logger.end_progress()
644
645def filter_ez_setup(line, project_name='setuptools'):
646    if not line.strip():
647        return Logger.DEBUG
648    if project_name == 'distribute':
649        for prefix in ('Extracting', 'Now working', 'Installing', 'Before',
650                       'Scanning', 'Setuptools', 'Egg', 'Already',
651                       'running', 'writing', 'reading', 'installing',
652                       'creating', 'copying', 'byte-compiling', 'removing',
653                       'Processing'):
654            if line.startswith(prefix):
655                return Logger.DEBUG
656        return Logger.DEBUG
657    for prefix in ['Reading ', 'Best match', 'Processing setuptools',
658                   'Copying setuptools', 'Adding setuptools',
659                   'Installing ', 'Installed ']:
660        if line.startswith(prefix):
661            return Logger.DEBUG
662    return Logger.INFO
663
664
665class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
666    """
667    Custom help formatter for use in ConfigOptionParser that updates
668    the defaults before expanding them, allowing them to show up correctly
669    in the help listing
670    """
671    def expand_default(self, option):
672        if self.parser is not None:
673            self.parser.update_defaults(self.parser.defaults)
674        return optparse.IndentedHelpFormatter.expand_default(self, option)
675
676
677class ConfigOptionParser(optparse.OptionParser):
678    """
679    Custom option parser which updates its defaults by by checking the
680    configuration files and environmental variables
681    """
682    def __init__(self, *args, **kwargs):
683        self.config = ConfigParser.RawConfigParser()
684        self.files = self.get_config_files()
685        self.config.read(self.files)
686        optparse.OptionParser.__init__(self, *args, **kwargs)
687
688    def get_config_files(self):
689        config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False)
690        if config_file and os.path.exists(config_file):
691            return [config_file]
692        return [default_config_file]
693
694    def update_defaults(self, defaults):
695        """
696        Updates the given defaults with values from the config files and
697        the environ. Does a little special handling for certain types of
698        options (lists).
699        """
700        # Then go and look for the other sources of configuration:
701        config = {}
702        # 1. config files
703        config.update(dict(self.get_config_section('virtualenv')))
704        # 2. environmental variables
705        config.update(dict(self.get_environ_vars()))
706        # Then set the options with those values
707        for key, val in config.items():
708            key = key.replace('_', '-')
709            if not key.startswith('--'):
710                key = '--%s' % key  # only prefer long opts
711            option = self.get_option(key)
712            if option is not None:
713                # ignore empty values
714                if not val:
715                    continue
716                # handle multiline configs
717                if option.action == 'append':
718                    val = val.split()
719                else:
720                    option.nargs = 1
721                if option.action in ('store_true', 'store_false', 'count'):
722                    val = strtobool(val)
723                try:
724                    val = option.convert_value(key, val)
725                except optparse.OptionValueError:
726                    e = sys.exc_info()[1]
727                    print("An error occured during configuration: %s" % e)
728                    sys.exit(3)
729                defaults[option.dest] = val
730        return defaults
731
732    def get_config_section(self, name):
733        """
734        Get a section of a configuration
735        """
736        if self.config.has_section(name):
737            return self.config.items(name)
738        return []
739
740    def get_environ_vars(self, prefix='VIRTUALENV_'):
741        """
742        Returns a generator with all environmental vars with prefix VIRTUALENV
743        """
744        for key, val in os.environ.items():
745            if key.startswith(prefix):
746                yield (key.replace(prefix, '').lower(), val)
747
748    def get_default_values(self):
749        """
750        Overridding to make updating the defaults after instantiation of
751        the option parser possible, update_defaults() does the dirty work.
752        """
753        if not self.process_default_values:
754            # Old, pre-Optik 1.5 behaviour.
755            return optparse.Values(self.defaults)
756
757        defaults = self.update_defaults(self.defaults.copy()) # ours
758        for option in self._get_all_options():
759            default = defaults.get(option.dest)
760            if isinstance(default, basestring):
761                opt_str = option.get_opt_string()
762                defaults[option.dest] = option.check_value(opt_str, default)
763        return optparse.Values(defaults)
764
765
766def main():
767    parser = ConfigOptionParser(
768        version=virtualenv_version,
769        usage="%prog [OPTIONS] DEST_DIR",
770        formatter=UpdatingDefaultsHelpFormatter())
771
772    parser.add_option(
773        '-v', '--verbose',
774        action='count',
775        dest='verbose',
776        default=0,
777        help="Increase verbosity")
778
779    parser.add_option(
780        '-q', '--quiet',
781        action='count',
782        dest='quiet',
783        default=0,
784        help='Decrease verbosity')
785
786    parser.add_option(
787        '-p', '--python',
788        dest='python',
789        metavar='PYTHON_EXE',
790        help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
791        'interpreter to create the new environment.  The default is the interpreter that '
792        'virtualenv was installed with (%s)' % sys.executable)
793
794    parser.add_option(
795        '--clear',
796        dest='clear',
797        action='store_true',
798        help="Clear out the non-root install and start from scratch")
799
800    parser.add_option(
801        '--no-site-packages',
802        dest='no_site_packages',
803        action='store_true',
804        help="Don't give access to the global site-packages dir to the "
805             "virtual environment")
806
807    parser.add_option(
808        '--system-site-packages',
809        dest='system_site_packages',
810        action='store_true',
811        help="Give access to the global site-packages dir to the "
812             "virtual environment")
813
814    parser.add_option(
815        '--unzip-setuptools',
816        dest='unzip_setuptools',
817        action='store_true',
818        help="Unzip Setuptools or Distribute when installing it")
819
820    parser.add_option(
821        '--relocatable',
822        dest='relocatable',
823        action='store_true',
824        help='Make an EXISTING virtualenv environment relocatable.  '
825        'This fixes up scripts and makes all .pth files relative')
826
827    parser.add_option(
828        '--distribute',
829        dest='use_distribute',
830        action='store_true',
831        help='Use Distribute instead of Setuptools. Set environ variable '
832        'VIRTUALENV_DISTRIBUTE to make it the default ')
833
834    default_search_dirs = file_search_dirs()
835    parser.add_option(
836        '--extra-search-dir',
837        dest="search_dirs",
838        action="append",
839        default=default_search_dirs,
840        help="Directory to look for setuptools/distribute/pip distributions in. "
841        "You can add any number of additional --extra-search-dir paths.")
842
843    parser.add_option(
844        '--never-download',
845        dest="never_download",
846        action="store_true",
847        help="Never download anything from the network.  Instead, virtualenv will fail "
848        "if local distributions of setuptools/distribute/pip are not present.")
849
850    parser.add_option(
851        '--prompt=',
852        dest='prompt',
853        help='Provides an alternative prompt prefix for this environment')
854
855    if 'extend_parser' in globals():
856        extend_parser(parser)
857
858    options, args = parser.parse_args()
859
860    global logger
861
862    if 'adjust_options' in globals():
863        adjust_options(options, args)
864
865    verbosity = options.verbose - options.quiet
866    logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)])
867
868    if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
869        env = os.environ.copy()
870        interpreter = resolve_interpreter(options.python)
871        if interpreter == sys.executable:
872            logger.warn('Already using interpreter %s' % interpreter)
873        else:
874            logger.notify('Running virtualenv with interpreter %s' % interpreter)
875            env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
876            file = __file__
877            if file.endswith('.pyc'):
878                file = file[:-1]
879            popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
880            raise SystemExit(popen.wait())
881
882    # Force --use-distribute on Python 3, since setuptools is not available.
883    if majver > 2:
884        options.use_distribute = True
885
886    if os.environ.get('PYTHONDONTWRITEBYTECODE') and not options.use_distribute:
887        print(
888            "The PYTHONDONTWRITEBYTECODE environment variable is "
889            "not compatible with setuptools. Either use --distribute "
890            "or unset PYTHONDONTWRITEBYTECODE.")
891        sys.exit(2)
892    if not args:
893        print('You must provide a DEST_DIR')
894        parser.print_help()
895        sys.exit(2)
896    if len(args) > 1:
897        print('There must be only one argument: DEST_DIR (you gave %s)' % (
898            ' '.join(args)))
899        parser.print_help()
900        sys.exit(2)
901
902    home_dir = args[0]
903
904    if os.environ.get('WORKING_ENV'):
905        logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
906        logger.fatal('Please deactivate your workingenv, then re-run this script')
907        sys.exit(3)
908
909    if 'PYTHONHOME' in os.environ:
910        logger.warn('PYTHONHOME is set.  You *must* activate the virtualenv before using it')
911        del os.environ['PYTHONHOME']
912
913    if options.relocatable:
914        make_environment_relocatable(home_dir)
915        return
916
917    if options.no_site_packages:
918        logger.warn('The --no-site-packages flag is deprecated; it is now '
919                    'the default behavior.')
920
921    create_environment(home_dir,
922                       site_packages=options.system_site_packages,
923                       clear=options.clear,
924                       unzip_setuptools=options.unzip_setuptools,
925                       use_distribute=options.use_distribute,
926                       prompt=options.prompt,
927                       search_dirs=options.search_dirs,
928                       never_download=options.never_download)
929    if 'after_install' in globals():
930        after_install(options, home_dir)
931
932def call_subprocess(cmd, show_stdout=True,
933                    filter_stdout=None, cwd=None,
934                    raise_on_returncode=True, extra_env=None,
935                    remove_from_env=None):
936    cmd_parts = []
937    for part in cmd:
938        if len(part) > 45:
939            part = part[:20]+"..."+part[-20:]
940        if ' ' in part or '\n' in part or '"' in part or "'" in part:
941            part = '"%s"' % part.replace('"', '\\"')
942        if hasattr(part, 'decode'):
943            try:
944                part = part.decode(sys.getdefaultencoding())
945            except UnicodeDecodeError:
946                part = part.decode(sys.getfilesystemencoding())
947        cmd_parts.append(part)
948    cmd_desc = ' '.join(cmd_parts)
949    if show_stdout:
950        stdout = None
951    else:
952        stdout = subprocess.PIPE
953    logger.debug("Running command %s" % cmd_desc)
954    if extra_env or remove_from_env:
955        env = os.environ.copy()
956        if extra_env:
957            env.update(extra_env)
958        if remove_from_env:
959            for varname in remove_from_env:
960                env.pop(varname, None)
961    else:
962        env = None
963    try:
964        proc = subprocess.Popen(
965            cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
966            cwd=cwd, env=env)
967    except Exception:
968        e = sys.exc_info()[1]
969        logger.fatal(
970            "Error %s while executing command %s" % (e, cmd_desc))
971        raise
972    all_output = []
973    if stdout is not None:
974        stdout = proc.stdout
975        encoding = sys.getdefaultencoding()
976        fs_encoding = sys.getfilesystemencoding()
977        while 1:
978            line = stdout.readline()
979            try:
980                line = line.decode(encoding)
981            except UnicodeDecodeError:
982                line = line.decode(fs_encoding)
983            if not line:
984                break
985            line = line.rstrip()
986            all_output.append(line)
987            if filter_stdout:
988                level = filter_stdout(line)
989                if isinstance(level, tuple):
990                    level, line = level
991                logger.log(level, line)
992                if not logger.stdout_level_matches(level):
993                    logger.show_progress()
994            else:
995                logger.info(line)
996    else:
997        proc.communicate()
998    proc.wait()
999    if proc.returncode:
1000        if raise_on_returncode:
1001            if all_output:
1002                logger.notify('Complete output from command %s:' % cmd_desc)
1003                logger.notify('\n'.join(all_output) + '\n----------------------------------------')
1004            raise OSError(
1005                "Command %s failed with error code %s"
1006                % (cmd_desc, proc.returncode))
1007        else:
1008            logger.warn(
1009                "Command %s had error code %s"
1010                % (cmd_desc, proc.returncode))
1011
1012
1013def create_environment(home_dir, site_packages=False, clear=False,
1014                       unzip_setuptools=False, use_distribute=False,
1015                       prompt=None, search_dirs=None, never_download=False):
1016    """
1017    Creates a new environment in ``home_dir``.
1018
1019    If ``site_packages`` is true, then the global ``site-packages/``
1020    directory will be on the path.
1021
1022    If ``clear`` is true (default False) then the environment will
1023    first be cleared.
1024    """
1025    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
1026
1027    py_executable = os.path.abspath(install_python(
1028        home_dir, lib_dir, inc_dir, bin_dir,
1029        site_packages=site_packages, clear=clear))
1030
1031    install_distutils(home_dir)
1032
1033    # use_distribute also is True if VIRTUALENV_DISTRIBUTE env var is set
1034    # we also check VIRTUALENV_USE_DISTRIBUTE for backwards compatibility
1035    if use_distribute or os.environ.get('VIRTUALENV_USE_DISTRIBUTE'):
1036        install_distribute(py_executable, unzip=unzip_setuptools,
1037                           search_dirs=search_dirs, never_download=never_download)
1038    else:
1039        install_setuptools(py_executable, unzip=unzip_setuptools,
1040                           search_dirs=search_dirs, never_download=never_download)
1041
1042    install_pip(py_executable, search_dirs=search_dirs, never_download=never_download)
1043
1044    install_activate(home_dir, bin_dir, prompt)
1045
1046def path_locations(home_dir):
1047    """Return the path locations for the environment (where libraries are,
1048    where scripts go, etc)"""
1049    # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
1050    # prefix arg is broken: http://bugs.python.org/issue3386
1051    if sys.platform == 'win32':
1052        # Windows has lots of problems with executables with spaces in
1053        # the name; this function will remove them (using the ~1
1054        # format):
1055        mkdir(home_dir)
1056        if ' ' in home_dir:
1057            try:
1058                import win32api
1059            except ImportError:
1060                print('Error: the path "%s" has a space in it' % home_dir)
1061                print('To handle these kinds of paths, the win32api module must be installed:')
1062                print('  http://sourceforge.net/projects/pywin32/')
1063                sys.exit(3)
1064            home_dir = win32api.GetShortPathName(home_dir)
1065        lib_dir = join(home_dir, 'Lib')
1066        inc_dir = join(home_dir, 'Include')
1067        bin_dir = join(home_dir, 'Scripts')
1068    elif is_jython:
1069        lib_dir = join(home_dir, 'Lib')
1070        inc_dir = join(home_dir, 'Include')
1071        bin_dir = join(home_dir, 'bin')
1072    elif is_pypy:
1073        lib_dir = home_dir
1074        inc_dir = join(home_dir, 'include')
1075        bin_dir = join(home_dir, 'bin')
1076    else:
1077        lib_dir = join(home_dir, 'lib', py_version)
1078        inc_dir = join(home_dir, 'include', py_version + abiflags)
1079        bin_dir = join(home_dir, 'bin')
1080    return home_dir, lib_dir, inc_dir, bin_dir
1081
1082
1083def change_prefix(filename, dst_prefix):
1084    prefixes = [sys.prefix]
1085
1086    if sys.platform == "darwin":
1087        prefixes.extend((
1088            os.path.join("/Library/Python", sys.version[:3], "site-packages"),
1089            os.path.join(sys.prefix, "Extras", "lib", "python"),
1090            os.path.join("~", "Library", "Python", sys.version[:3], "site-packages")))
1091
1092    if hasattr(sys, 'real_prefix'):
1093        prefixes.append(sys.real_prefix)
1094    prefixes = list(map(os.path.abspath, prefixes))
1095    filename = os.path.abspath(filename)
1096    for src_prefix in prefixes:
1097        if filename.startswith(src_prefix):
1098            _, relpath = filename.split(src_prefix, 1)
1099            assert relpath[0] == os.sep
1100            relpath = relpath[1:]
1101            return join(dst_prefix, relpath)
1102    assert False, "Filename %s does not start with any of these prefixes: %s" % \
1103        (filename, prefixes)
1104
1105def copy_required_modules(dst_prefix):
1106    import imp
1107    for modname in REQUIRED_MODULES:
1108        if modname in sys.builtin_module_names:
1109            logger.info("Ignoring built-in bootstrap module: %s" % modname)
1110            continue
1111        try:
1112            f, filename, _ = imp.find_module(modname)
1113        except ImportError:
1114            logger.info("Cannot import bootstrap module: %s" % modname)
1115        else:
1116            if f is not None:
1117                f.close()
1118            dst_filename = change_prefix(filename, dst_prefix)
1119            copyfile(filename, dst_filename)
1120            if filename.endswith('.pyc'):
1121                pyfile = filename[:-1]
1122                if os.path.exists(pyfile):
1123                    copyfile(pyfile, dst_filename[:-1])
1124
1125
1126def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
1127    """Install just the base environment, no distutils patches etc"""
1128    if sys.executable.startswith(bin_dir):
1129        print('Please use the *system* python to run this script')
1130        return
1131
1132    if clear:
1133        rmtree(lib_dir)
1134        ## FIXME: why not delete it?
1135        ## Maybe it should delete everything with #!/path/to/venv/python in it
1136        logger.notify('Not deleting %s', bin_dir)
1137
1138    if hasattr(sys, 'real_prefix'):
1139        logger.notify('Using real prefix %r' % sys.real_prefix)
1140        prefix = sys.real_prefix
1141    else:
1142        prefix = sys.prefix
1143    mkdir(lib_dir)
1144    fix_lib64(lib_dir)
1145    fix_local_scheme(home_dir)
1146    stdlib_dirs = [os.path.dirname(os.__file__)]
1147    if sys.platform == 'win32':
1148        stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
1149    elif sys.platform == 'darwin':
1150        stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
1151    if hasattr(os, 'symlink'):
1152        logger.info('Symlinking Python bootstrap modules')
1153    else:
1154        logger.info('Copying Python bootstrap modules')
1155    logger.indent += 2
1156    try:
1157        # copy required files...
1158        for stdlib_dir in stdlib_dirs:
1159            if not os.path.isdir(stdlib_dir):
1160                continue
1161            for fn in os.listdir(stdlib_dir):
1162                bn = os.path.splitext(fn)[0]
1163                if fn != 'site-packages' and bn in REQUIRED_FILES:
1164                    copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
1165        # ...and modules
1166        copy_required_modules(home_dir)
1167    finally:
1168        logger.indent -= 2
1169    mkdir(join(lib_dir, 'site-packages'))
1170    import site
1171    site_filename = site.__file__
1172    if site_filename.endswith('.pyc'):
1173        site_filename = site_filename[:-1]
1174    elif site_filename.endswith('$py.class'):
1175        site_filename = site_filename.replace('$py.class', '.py')
1176    site_filename_dst = change_prefix(site_filename, home_dir)
1177    site_dir = os.path.dirname(site_filename_dst)
1178    writefile(site_filename_dst, SITE_PY)
1179    writefile(join(site_dir, 'orig-prefix.txt'), prefix)
1180    site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
1181    if not site_packages:
1182        writefile(site_packages_filename, '')
1183    else:
1184        if os.path.exists(site_packages_filename):
1185            logger.info('Deleting %s' % site_packages_filename)
1186            os.unlink(site_packages_filename)
1187
1188    if is_pypy or is_win:
1189        stdinc_dir = join(prefix, 'include')
1190    else:
1191        stdinc_dir = join(prefix, 'include', py_version + abiflags)
1192    if os.path.exists(stdinc_dir):
1193        copyfile(stdinc_dir, inc_dir)
1194    else:
1195        logger.debug('No include dir %s' % stdinc_dir)
1196
1197    # pypy never uses exec_prefix, just ignore it
1198    if sys.exec_prefix != prefix and not is_pypy:
1199        if sys.platform == 'win32':
1200            exec_dir = join(sys.exec_prefix, 'lib')
1201        elif is_jython:
1202            exec_dir = join(sys.exec_prefix, 'Lib')
1203        else:
1204            exec_dir = join(sys.exec_prefix, 'lib', py_version)
1205        for fn in os.listdir(exec_dir):
1206            copyfile(join(exec_dir, fn), join(lib_dir, fn))
1207
1208    if is_jython:
1209        # Jython has either jython-dev.jar and javalib/ dir, or just
1210        # jython.jar
1211        for name in 'jython-dev.jar', 'javalib', 'jython.jar':
1212            src = join(prefix, name)
1213            if os.path.exists(src):
1214                copyfile(src, join(home_dir, name))
1215        # XXX: registry should always exist after Jython 2.5rc1
1216        src = join(prefix, 'registry')
1217        if os.path.exists(src):
1218            copyfile(src, join(home_dir, 'registry'), symlink=False)
1219        copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
1220                 symlink=False)
1221
1222    mkdir(bin_dir)
1223    py_executable = join(bin_dir, os.path.basename(sys.executable))
1224    if 'Python.framework' in prefix:
1225        if re.search(r'/Python(?:-32|-64)*$', py_executable):
1226            # The name of the python executable is not quite what
1227            # we want, rename it.
1228            py_executable = os.path.join(
1229                    os.path.dirname(py_executable), 'python')
1230
1231    logger.notify('New %s executable in %s', expected_exe, py_executable)
1232    if sys.executable != py_executable:
1233        ## FIXME: could I just hard link?
1234        executable = sys.executable
1235        if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'):
1236            # Cygwin misreports sys.executable sometimes
1237            executable += '.exe'
1238            py_executable += '.exe'
1239            logger.info('Executable actually exists in %s' % executable)
1240        shutil.copyfile(executable, py_executable)
1241        make_exe(py_executable)
1242        if sys.platform == 'win32' or sys.platform == 'cygwin':
1243            pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
1244            if os.path.exists(pythonw):
1245                logger.info('Also created pythonw.exe')
1246                shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
1247        if is_pypy:
1248            # make a symlink python --> pypy-c
1249            python_executable = os.path.join(os.path.dirname(py_executable), 'python')
1250            logger.info('Also created executable %s' % python_executable)
1251            copyfile(py_executable, python_executable)
1252
1253    if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
1254        secondary_exe = os.path.join(os.path.dirname(py_executable),
1255                                     expected_exe)
1256        py_executable_ext = os.path.splitext(py_executable)[1]
1257        if py_executable_ext == '.exe':
1258            # python2.4 gives an extension of '.4' :P
1259            secondary_exe += py_executable_ext
1260        if os.path.exists(secondary_exe):
1261            logger.warn('Not overwriting existing %s script %s (you must use %s)'
1262                        % (expected_exe, secondary_exe, py_executable))
1263        else:
1264            logger.notify('Also creating executable in %s' % secondary_exe)
1265            shutil.copyfile(sys.executable, secondary_exe)
1266            make_exe(secondary_exe)
1267
1268    if 'Python.framework' in prefix:
1269        logger.debug('MacOSX Python framework detected')
1270
1271        # Make sure we use the the embedded interpreter inside
1272        # the framework, even if sys.executable points to
1273        # the stub executable in ${sys.prefix}/bin
1274        # See http://groups.google.com/group/python-virtualenv/
1275        #                              browse_thread/thread/17cab2f85da75951
1276        original_python = os.path.join(
1277            prefix, 'Resources/Python.app/Contents/MacOS/Python')
1278        shutil.copy(original_python, py_executable)
1279
1280        # Copy the framework's dylib into the virtual
1281        # environment
1282        virtual_lib = os.path.join(home_dir, '.Python')
1283
1284        if os.path.exists(virtual_lib):
1285            os.unlink(virtual_lib)
1286        copyfile(
1287            os.path.join(prefix, 'Python'),
1288            virtual_lib)
1289
1290        # And then change the install_name of the copied python executable
1291        try:
1292            call_subprocess(
1293                ["install_name_tool", "-change",
1294                 os.path.join(prefix, 'Python'),
1295                 '@executable_path/../.Python',
1296                 py_executable])
1297        except:
1298            logger.fatal(
1299                "Could not call install_name_tool -- you must have Apple's development tools installed")
1300            raise
1301
1302        # Some tools depend on pythonX.Y being present
1303        py_executable_version = '%s.%s' % (
1304            sys.version_info[0], sys.version_info[1])
1305        if not py_executable.endswith(py_executable_version):
1306            # symlinking pythonX.Y > python
1307            pth = py_executable + '%s.%s' % (
1308                    sys.version_info[0], sys.version_info[1])
1309            if os.path.exists(pth):
1310                os.unlink(pth)
1311            os.symlink('python', pth)
1312        else:
1313            # reverse symlinking python -> pythonX.Y (with --python)
1314            pth = join(bin_dir, 'python')
1315            if os.path.exists(pth):
1316                os.unlink(pth)
1317            os.symlink(os.path.basename(py_executable), pth)
1318
1319    if sys.platform == 'win32' and ' ' in py_executable:
1320        # There's a bug with subprocess on Windows when using a first
1321        # argument that has a space in it.  Instead we have to quote
1322        # the value:
1323        py_executable = '"%s"' % py_executable
1324    cmd = [py_executable, '-c', """
1325import sys
1326prefix = sys.prefix
1327if sys.version_info[0] == 3:
1328    prefix = prefix.encode('utf8')
1329if hasattr(sys.stdout, 'detach'):
1330    sys.stdout = sys.stdout.detach()
1331elif hasattr(sys.stdout, 'buffer'):
1332    sys.stdout = sys.stdout.buffer
1333sys.stdout.write(prefix)
1334"""]
1335    logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
1336    try:
1337        proc = subprocess.Popen(cmd,
1338                            stdout=subprocess.PIPE)
1339        proc_stdout, proc_stderr = proc.communicate()
1340    except OSError:
1341        e = sys.exc_info()[1]
1342        if e.errno == errno.EACCES:
1343            logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e))
1344            sys.exit(100)
1345        else:
1346          raise e
1347
1348    proc_stdout = proc_stdout.strip().decode("utf-8")
1349    proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
1350    norm_home_dir = os.path.normcase(os.path.abspath(home_dir))
1351    if hasattr(norm_home_dir, 'decode'):
1352        norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding())
1353    if proc_stdout != norm_home_dir:
1354        logger.fatal(
1355            'ERROR: The executable %s is not functioning' % py_executable)
1356        logger.fatal(
1357            'ERROR: It thinks sys.prefix is %r (should be %r)'
1358            % (proc_stdout, norm_home_dir))
1359        logger.fatal(
1360            'ERROR: virtualenv is not compatible with this system or executable')
1361        if sys.platform == 'win32':
1362            logger.fatal(
1363                'Note: some Windows users have reported this error when they installed Python for "Only this user".  The problem may be resolvable if you install Python "For all users".  (See https://bugs.launchpad.net/virtualenv/+bug/352844)')
1364        sys.exit(100)
1365    else:
1366        logger.info('Got sys.prefix result: %r' % proc_stdout)
1367
1368    pydistutils = os.path.expanduser('~/.pydistutils.cfg')
1369    if os.path.exists(pydistutils):
1370        logger.notify('Please make sure you remove any previous custom paths from '
1371                      'your %s file.' % pydistutils)
1372    ## FIXME: really this should be calculated earlier
1373    return py_executable
1374
1375def install_activate(home_dir, bin_dir, prompt=None):
1376    if sys.platform == 'win32' or is_jython and os._name == 'nt':
1377        files = {'activate.bat': ACTIVATE_BAT,
1378                 'deactivate.bat': DEACTIVATE_BAT}
1379        if os.environ.get('OS') == 'Windows_NT' and os.environ.get('OSTYPE') == 'cygwin':
1380            files['activate'] = ACTIVATE_SH
1381    else:
1382        files = {'activate': ACTIVATE_SH}
1383
1384        # suppling activate.fish in addition to, not instead of, the
1385        # bash script support.
1386        files['activate.fish'] = ACTIVATE_FISH
1387
1388        # same for csh/tcsh support...
1389        files['activate.csh'] = ACTIVATE_CSH
1390
1391
1392
1393    files['activate_this.py'] = ACTIVATE_THIS
1394    home_dir = os.path.abspath(home_dir)
1395    if hasattr(home_dir, 'decode'):
1396        home_dir = home_dir.decode(sys.getfilesystemencoding())
1397    vname = os.path.basename(home_dir)
1398    for name, content in files.items():
1399        content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
1400        content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname)
1401        content = content.replace('__VIRTUAL_ENV__', home_dir)
1402        content = content.replace('__VIRTUAL_NAME__', vname)
1403        content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
1404        writefile(os.path.join(bin_dir, name), content)
1405
1406def install_distutils(home_dir):
1407    distutils_path = change_prefix(distutils.__path__[0], home_dir)
1408    mkdir(distutils_path)
1409    ## FIXME: maybe this prefix setting should only be put in place if
1410    ## there's a local distutils.cfg with a prefix setting?
1411    home_dir = os.path.abspath(home_dir)
1412    ## FIXME: this is breaking things, removing for now:
1413    #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
1414    writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
1415    writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
1416
1417def fix_local_scheme(home_dir):
1418    """
1419    Platforms that use the "posix_local" install scheme (like Ubuntu with
1420    Python 2.7) need to be given an additional "local" location, sigh.
1421    """
1422    try:
1423        import sysconfig
1424    except ImportError:
1425        pass
1426    else:
1427        if sysconfig._get_default_scheme() == 'posix_local':
1428            local_path = os.path.join(home_dir, 'local')
1429            if not os.path.exists(local_path):
1430                os.symlink(os.path.abspath(home_dir), local_path)
1431
1432def fix_lib64(lib_dir):
1433    """
1434    Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
1435    instead of lib/pythonX.Y.  If this is such a platform we'll just create a
1436    symlink so lib64 points to lib
1437    """
1438    if [p for p in distutils.sysconfig.get_config_vars().values()
1439        if isinstance(p, basestring) and 'lib64' in p]:
1440        logger.debug('This system uses lib64; symlinking lib64 to lib')
1441        assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
1442            "Unexpected python lib dir: %r" % lib_dir)
1443        lib_parent = os.path.dirname(lib_dir)
1444        assert os.path.basename(lib_parent) == 'lib', (
1445            "Unexpected parent dir: %r" % lib_parent)
1446        copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64'))
1447
1448def resolve_interpreter(exe):
1449    """
1450    If the executable given isn't an absolute path, search $PATH for the interpreter
1451    """
1452    if os.path.abspath(exe) != exe:
1453        paths = os.environ.get('PATH', '').split(os.pathsep)
1454        for path in paths:
1455            if os.path.exists(os.path.join(path, exe)):
1456                exe = os.path.join(path, exe)
1457                break
1458    if not os.path.exists(exe):
1459        logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
1460        raise SystemExit(3)
1461    if not is_executable(exe):
1462        logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
1463        raise SystemExit(3)
1464    return exe
1465
1466def is_executable(exe):
1467    """Checks a file is executable"""
1468    return os.access(exe, os.X_OK)
1469
1470############################################################
1471## Relocating the environment:
1472
1473def make_environment_relocatable(home_dir):
1474    """
1475    Makes the already-existing environment use relative paths, and takes out
1476    the #!-based environment selection in scripts.
1477    """
1478    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
1479    activate_this = os.path.join(bin_dir, 'activate_this.py')
1480    if not os.path.exists(activate_this):
1481        logger.fatal(
1482            'The environment doesn\'t have a file %s -- please re-run virtualenv '
1483            'on this environment to update it' % activate_this)
1484    fixup_scripts(home_dir)
1485    fixup_pth_and_egg_link(home_dir)
1486    ## FIXME: need to fix up distutils.cfg
1487
1488OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
1489                  'activate', 'activate.bat', 'activate_this.py']
1490
1491def fixup_scripts(home_dir):
1492    # This is what we expect at the top of scripts:
1493    shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
1494    # This is what we'll put:
1495    new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
1496    activate = "import os; activate_this=os.path.join(os.path.dirname(__file__), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this"
1497    if sys.platform == 'win32':
1498        bin_suffix = 'Scripts'
1499    else:
1500        bin_suffix = 'bin'
1501    bin_dir = os.path.join(home_dir, bin_suffix)
1502    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
1503    for filename in os.listdir(bin_dir):
1504        filename = os.path.join(bin_dir, filename)
1505        if not os.path.isfile(filename):
1506            # ignore subdirs, e.g. .svn ones.
1507            continue
1508        f = open(filename, 'rb')
1509        lines = f.readlines()
1510        f.close()
1511        if not lines:
1512            logger.warn('Script %s is an empty file' % filename)
1513            continue
1514        if not lines[0].strip().startswith(shebang):
1515            if os.path.basename(filename) in OK_ABS_SCRIPTS:
1516                logger.debug('Cannot make script %s relative' % filename)
1517            elif lines[0].strip() == new_shebang:
1518                logger.info('Script %s has already been made relative' % filename)
1519            else:
1520                logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
1521                            % (filename, shebang))
1522            continue
1523        logger.notify('Making script %s relative' % filename)
1524        lines = [new_shebang+'\n', activate+'\n'] + lines[1:]
1525        f = open(filename, 'wb')
1526        f.writelines(lines)
1527        f.close()
1528
1529def fixup_pth_and_egg_link(home_dir, sys_path=None):
1530    """Makes .pth and .egg-link files use relative paths"""
1531    home_dir = os.path.normcase(os.path.abspath(home_dir))
1532    if sys_path is None:
1533        sys_path = sys.path
1534    for path in sys_path:
1535        if not path:
1536            path = '.'
1537        if not os.path.isdir(path):
1538            continue
1539        path = os.path.normcase(os.path.abspath(path))
1540        if not path.startswith(home_dir):
1541            logger.debug('Skipping system (non-environment) directory %s' % path)
1542            continue
1543        for filename in os.listdir(path):
1544            filename = os.path.join(path, filename)
1545            if filename.endswith('.pth'):
1546                if not os.access(filename, os.W_OK):
1547                    logger.warn('Cannot write .pth file %s, skipping' % filename)
1548                else:
1549                    fixup_pth_file(filename)
1550            if filename.endswith('.egg-link'):
1551                if not os.access(filename, os.W_OK):
1552                    logger.warn('Cannot write .egg-link file %s, skipping' % filename)
1553                else:
1554                    fixup_egg_link(filename)
1555
1556def fixup_pth_file(filename):
1557    lines = []
1558    prev_lines = []
1559    f = open(filename)
1560    prev_lines = f.readlines()
1561    f.close()
1562    for line in prev_lines:
1563        line = line.strip()
1564        if (not line or line.startswith('#') or line.startswith('import ')
1565            or os.path.abspath(line) != line):
1566            lines.append(line)
1567        else:
1568            new_value = make_relative_path(filename, line)
1569            if line != new_value:
1570                logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
1571            lines.append(new_value)
1572    if lines == prev_lines:
1573        logger.info('No changes to .pth file %s' % filename)
1574        return
1575    logger.notify('Making paths in .pth file %s relative' % filename)
1576    f = open(filename, 'w')
1577    f.write('\n'.join(lines) + '\n')
1578    f.close()
1579
1580def fixup_egg_link(filename):
1581    f = open(filename)
1582    link = f.read().strip()
1583    f.close()
1584    if os.path.abspath(link) != link:
1585        logger.debug('Link in %s already relative' % filename)
1586        return
1587    new_link = make_relative_path(filename, link)
1588    logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
1589    f = open(filename, 'w')
1590    f.write(new_link)
1591    f.close()
1592
1593def make_relative_path(source, dest, dest_is_directory=True):
1594    """
1595    Make a filename relative, where the filename is dest, and it is
1596    being referred to from the filename source.
1597
1598        >>> make_relative_path('/usr/share/something/a-file.pth',
1599        ...                    '/usr/share/another-place/src/Directory')
1600        '../another-place/src/Directory'
1601        >>> make_relative_path('/usr/share/something/a-file.pth',
1602        ...                    '/home/user/src/Directory')
1603        '../../../home/user/src/Directory'
1604        >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
1605        './'
1606    """
1607    source = os.path.dirname(source)
1608    if not dest_is_directory:
1609        dest_filename = os.path.basename(dest)
1610        dest = os.path.dirname(dest)
1611    dest = os.path.normpath(os.path.abspath(dest))
1612    source = os.path.normpath(os.path.abspath(source))
1613    dest_parts = dest.strip(os.path.sep).split(os.path.sep)
1614    source_parts = source.strip(os.path.sep).split(os.path.sep)
1615    while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
1616        dest_parts.pop(0)
1617        source_parts.pop(0)
1618    full_parts = ['..']*len(source_parts) + dest_parts
1619    if not dest_is_directory:
1620        full_parts.append(dest_filename)
1621    if not full_parts:
1622        # Special case for the current directory (otherwise it'd be '')
1623        return './'
1624    return os.path.sep.join(full_parts)
1625
1626
1627
1628############################################################
1629## Bootstrap script creation:
1630
1631def create_bootstrap_script(extra_text, python_version=''):
1632    """
1633    Creates a bootstrap script, which is like this script but with
1634    extend_parser, adjust_options, and after_install hooks.
1635
1636    This returns a string that (written to disk of course) can be used
1637    as a bootstrap script with your own customizations.  The script
1638    will be the standard virtualenv.py script, with your extra text
1639    added (your extra text should be Python code).
1640
1641    If you include these functions, they will be called:
1642
1643    ``extend_parser(optparse_parser)``:
1644        You can add or remove options from the parser here.
1645
1646    ``adjust_options(options, args)``:
1647        You can change options here, or change the args (if you accept
1648        different kinds of arguments, be sure you modify ``args`` so it is
1649        only ``[DEST_DIR]``).
1650
1651    ``after_install(options, home_dir)``:
1652
1653        After everything is installed, this function is called.  This
1654        is probably the function you are most likely to use.  An
1655        example would be::
1656
1657            def after_install(options, home_dir):
1658                subprocess.call([join(home_dir, 'bin', 'easy_install'),
1659                                 'MyPackage'])
1660                subprocess.call([join(home_dir, 'bin', 'my-package-script'),
1661                                 'setup', home_dir])
1662
1663        This example immediately installs a package, and runs a setup
1664        script from that package.
1665
1666    If you provide something like ``python_version='2.4'`` then the
1667    script will start with ``#!/usr/bin/env python2.4`` instead of
1668    ``#!/usr/bin/env python``.  You can use this when the script must
1669    be run with a particular Python version.
1670    """
1671    filename = __file__
1672    if filename.endswith('.pyc'):
1673        filename = filename[:-1]
1674    f = open(filename, 'rb')
1675    content = f.read()
1676    f.close()
1677    py_exe = 'python%s' % python_version
1678    content = (('#!/usr/bin/env %s\n' % py_exe)
1679               + '## WARNING: This file is generated\n'
1680               + content)
1681    return content.replace('##EXT' 'END##', extra_text)
1682
1683##EXTEND##
1684
1685def convert(s):
1686    b = base64.b64decode(s.encode('ascii'))
1687    return zlib.decompress(b).decode('utf-8')
1688
1689##file site.py
1690SITE_PY = convert("""
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
1766X4UuruF1rMoshUjuVWhlSXfDcoyWcfRDu6HKeA1pQKc7jKwb8qz3YoFW61XIc9P9xy2j/dYAhi2D
1767vYV555LKEahGF4upRIiNeOcglF/gq116vQYKFgw3lmpcRMN0Kcw+geBarFMIIIAn12B9MU4ACJ2V
17688BPQx052QBZYDRC+2SwO/xpqgvitf/lloHldZYd/FyVEQYJLV8IBYrqN30LgE8tYnH14Nw4ZOSoF
1769FX9tsIAcHBLK8jnSTvUyvGM7jZTMlrqewdcH+EL7CfS6072SZaW7D7vGIUrAExWR1/BEGfqFWF5k
1770YU9wKuMOaKyNt5jhGTN329t8DsTHtcwyXRF9/vbiDHxHLNdHCeJ9njMYjvMluGWri734DFwHFG7o
1771wusK2bhCF5Y29Rex12wwM4siR729OgC7TpT97PfqpTqrJFUu2hFOm2GZgvMYWRnWwiwrs3anDVLY
1772bUMUR5lhlpheVlQw6fME8DI9TTgkglgJDwOYNDPvWqZ5bSrksnQOehRULijUCQgJEhdPvBHnFTkn
1773eotKmYMy8LDcVelqXWMyHTrHVKSPzX88/Xxx/p4K11+8bL3uAeacUCQw4aKFEyxJw2wHfHHLzJCr
1774ptMhntWvEAZqH/jTfcXVECc8QK8fJxbxT/cVn1Q6cSJBngEoqKbsigcGAE63IblpZYFxtXEwftyS
1775sxYzHwzlIvFghC4scOfX50TbsmNKKO9jXj5il2JZahpGprNbAtX96DkuS9xWWUTDjeDtkGyZzwy6
17763vTe7Cu2cj89KcRDk4BRv7U/hqlG6jXV03GYbR+3UFirbewvuZMrddrNcxRlIGLkdh67TDashHVz
17775kCvbLcHTHyr0TWSOKjKR7/kI+1heJhYYvfiFNORjk2QEcBMhtSnQxrwodAigAKhatPIkdzJ+OkL
1778b46ONbh/jlp3gW38ARShrv2kMwVFBZwIX35jx5FfEVqoR49F6HgqucwLW5eEn+0avcrn/hwHZYCS
1779mCh2VZKvZMSwJgbmVz6x96RgSdt6pL5Kr4cMizgH5/TLHg7vy8XwxolBrcMIvXY3ctdVRz55sMHg
17800YM7CeaDr5It6P6yqSNeyWGRHz5ttR/q/RCx2g2a6s3eKMR0zG/hnvVpAQ9SQ8NCD++3gd0i/PDa
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
1826""")
1827
1828##file ez_setup.py
1829EZ_SETUP_PY = convert("""
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
1896BDaonX65d/fwEjNqlDjLVIvM9X+XVxF7
1897""")
1898
1899##file distribute_setup.py
1900DISTRIBUTE_SETUP_PY = convert("""
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
1980""")
1981
1982##file activate.sh
1983ACTIVATE_SH = convert("""
1984eJytVU1v4jAQPW9+xTT0ANVS1GsrDlRFAqmFqmG72m0rY5IJsRRslDiktNr/vuMQ8tFQpNU2B4I9
1985H36eeW/SglkgYvBFiLBKYg0LhCRGD1KhA7BjlUQuwkLIHne12HCNNpz5kVrBgsfBmdWCrUrA5VIq
1986DVEiQWjwRISuDreW5eE+CtodeLeAnhZEGKMGFXqAciMiJVcoNWx4JPgixDjzEj48QVeCfcqmtzfs
1987cfww+zG4ZfeD2ciGF7gCHaDMPM1jtvuHXAsPfF2rSGeOxV4iDY5GUGb3xVEYv2aj6WQ0vRseAlMY
1988G5DKsAawwnQUXt2LQOYlzZoYByqhonqoqfxZf4BLD97i4DukgXADCPgGgdOLTK5arYxZB1xnrc9T
1989EQFcHoZEAa1gSQioo/TPV5FZrDlxJA+NzwF+Ek1UonOzFnKZp6k5mgLBqSkuuAGXS4whJb5xz/xs
1990wXCHjiVerAk5eh9Kfz1wqOldtVv9dkbscfjgjKeTA8XPrtaNauX5rInOxaHuOReNtpFjo1/OxdFG
19915eY9hJ3L3jqcPJbATggXAemDLZX0MNZRYjSDH7C1wMHQh73DyYfTu8a0F9v+6D8W6XNnF1GEIXW/
1992JrSKPOtnW1YFat9mrLJkzLbyIlTvYzV0RGXcaTBfVLx7jF2PJ2wyuBsydpm7VSVa4C4Zb6pFO2TR
1993huypCEPwuQjNftUrNl6GsYZzuFrrLdC9iJjQ3omAPBbcI2lsU77tUD43kw1NPZhTrnZWzuQKLomx
1994Rd4OXM1ByExVVkmoTwfBJ7Lt10Iq1Kgo23Bmd8Ib1KrGbsbO4Pp2yO4fpnf3s6MnZiwuiJuls1/L
1995Pu4yUCvhpA+vZaJvWWDTr0yFYYyVnHMqCEq+QniuYX225xmnzRENjbXACF3wkCYNVZ1mBwxoR9Iw
1996WAo3/36oSOTfgjwEEQKt15e9Xpqm52+oaXxszmnE9GLl65RH2OMmS6+u5acKxDmlPgj2eT5/gQOX
1997LLK0j1y0Uwbmn438VZkVpqlfNKa/YET/53j+99G8H8tUhr9ZSXs2
1998""")
1999
2000##file activate.fish
2001ACTIVATE_FISH = convert("""
2002eJydVm1v4jgQ/s6vmA1wBxUE7X2stJVYlVWR2lK13d6d9laRk0yIr8HmbIe0++tvnIQQB9pbXT5A
2003Ys/LM55nZtyHx5RrSHiGsMm1gRAh1xhDwU0Kng8hFzMWGb5jBv2E69SDs0TJDdj3MxilxmzPZzP7
2004pVPMMl+q9bjXh1eZQ8SEkAZULoAbiLnCyGSvvV6SC7IoBcS4Nw0wjcFbvJDcjiuTswzFDpiIQaHJ
2005lQAjQUi1YRmUboC2uZJig8J4PaCnT5IaDcgsbm/CjinOwgx1KcUTMEhhTgV4g2B1fRk8Le8fv86v
2006g7v545UHpZB9rKnp+gXsMhxLunIIpwVQxP/l9c/Hq9Xt1epm4R27bva6AJqN92G4YhbMG2i+LB+u
2007grv71c3dY7B6WtzfLy9bePbp0taDTXSwJQJszUnnp0y57mvpPcrF7ZODyhswtd59+/jdgw+fwBNS
2008xLSscksUPIDqwwNmCez3PpxGeyBYg6HE0YdcWBxcKczYzuVJi5Wu915vn5oWePCCoPUZBN5B7IgV
2009MCi54ZDLG7TUZ0HweXkb3M5vFmSpFm/gthhBx0UrveoPpv9AJ9unIbQYdUoe21bKg2q48sPFGVwu
2010H+afrxd1qvclaNlRFyh1EQ2sSccEuNAGWQwysfVpz1tPajUqbqJUnEcIJkWo6OXDaodK8ZiLdbmM
2011L1wb+9H0D+pcyPSrX5u5kgWSygRYXCnJUi/KKcuU4cqsAyTKZBiissLc7NFwizvjxtieKBVCIdWz
2012fzilzPaYyljZN0cGN1v7NnaIPNCGmVy3GKuJaQ6iVjE1Qfm+36hglErwmnAD8hu0dDy4uICBA8ZV
2013pQr/q/+O0KFW2kjelu9Dgb9SDBsWV4F4x5CswgS0zBVlk5tDMP5bVtUGpslbm81Lu2sdKq7uNMGh
2014MVQ4fy9xhogC1lS5guhISa0DlBWv0O8odT6/LP+4WZzDV6FzIkEqC0uolGZSZoMnlpxplmD2euaT
2015O4hkTpPnbztDccey0bhjDaBIqaWQa0uwEtQEwtyU56i4fq54F9IE3ORR6mKriODM4XOYZwaVYLYz
20167SPbKkz4i7VkB6/Ot1upDE3znNqYKpM8raa0Bx8vfvntJ32UENsM4aI6gJL+jJwhxhh3jVIDOcpi
2017m0r2hmEtS8XXXNBk71QCDXTBNhhPiHX2LtHkrVIlhoEshH/EZgdq53Eirqs5iFKMnkOmqZTtr3Xq
2018djvPTWZT4S3NT5aVLgurMPUWI07BRVYqkQrmtCKohNY8qu9EdACoT6ki0a66XxVF4f9AQ3W38yO5
2019mWmZmIIpnDFrbXakvKWeZhLwhvrbUH8fahhqD0YUcBDJjEBMQwiznE4y5QbHrbhHBOnUAYzb2tVN
2020jJa65e+eE2Ya30E2GurxUP8ssA6e/wOnvo3V78d3vTcvMB3n7l3iX1JXWqk=
2021""")
2022
2023##file activate.csh
2024ACTIVATE_CSH = convert("""
2025eJx9U11vmzAUffevOCVRu+UB9pws29Kl0iq1aVWllaZlcgxciiViItsQdb9+xiQp+dh4QOB7Pu49
2026XHqY59IgkwVhVRmLmFAZSrGRNkdgykonhFiqSCRW1sJSmJg8wCDT5QrucRCyHn6WFRKhVGmhKwVp
2027kUpNiS3emup3TY6XIn7DVNQyJUwlrgthJD6n/iCNv72uhCzCpFx9CRkThRQGKe08cWXJ9db/yh/u
2028pvzl9mn+PLnjj5P5D1yM8QmXlzBkSdXwZ0H/BBc0mEo5FE5qI2jKhclHOOvy9HD/OO/6YO1mX9vx
2029sY0H/tPIV0dtqel0V7iZvWyNg8XFcBA0ToEqVeqOdNUEQFvN41SumAv32VtJrakQNSmLWmgp4oJM
2030yDoBHgoydtoEAs47r5wHHnUal5vbJ8oOI+9wI86vb2d8Nrm/4Xy4RZ8R85E4uTZPB5EZPnTaaAGu
2031E59J8BE2J8XgrkbLeXMlVoQxznEYFYY8uFFdxsKQRx90Giwx9vSueHP1YNaUSFG4vTaErNSYuBOF
2032lXiVyXa9Sy3JdClEyK1dD6Nos9mEf8iKlOpmqSNTZnYjNEWiUYn2pKNB3ttcLJ3HmYYXy6Un76f7
2033r8rRsC1TpTJj7f19m5sUf/V3Ir+x/yjtLu8KjLX/CmN/AcVGUUo=
2034""")
2035
2036##file activate.bat
2037ACTIVATE_BAT = convert("""
2038eJyFUkEKgzAQvAfyhz0YaL9QEWpRqlSjWGspFPZQTevFHOr/adQaU1GaUzI7Mzu7ZF89XhKkEJS8
2039qxaKMMsvboQ+LxxE44VICSW1gEa2UFaibqoS0iyJ0xw2lIA6nX5AHCu1jpRsv5KRjknkac9VLVug
2040sX9mtzxIeJDE/mg4OGp47qoLo3NHX2jsMB3AiDht5hryAUOEifoTdCXbSh7V0My2NMq/Xbh5MEjU
2041ZT63gpgNT9lKOJ/CtHsvT99re3pX303kydn4HeyOeAg5cjf2EW1D6HOPkg9NGKhu
2042""")
2043
2044##file deactivate.bat
2045DEACTIVATE_BAT = convert("""
2046eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q
2047FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL
2048i2dASrm4rFz9XLgAwJNbyQ==
2049""")
2050
2051##file distutils-init.py
2052DISTUTILS_INIT = convert("""
2053eJytV92L4zYQf/dfMU0ottuse7RvC6FQrg8Lxz2Ugz4si9HacqKuIxlJ2ST313dG8odkO9d7aGBB
2054luZLv/nNjFacOqUtKJMIvzK3cXlhWgp5MDBsqK5SNYftsBAGpLLA4F1oe2Ytl+9wUvW55TswCi4c
2055KibhbFDSglXQCFmDPXIwtm7FawLRbwtPzg2T9gf4gupKv4GS0N262w7V0NvpbCy8cvTo3eAus6C5
2056ETU3ICQZX1hFTw/dzR6V/AW1RCN4/XAtbsVXqIXmlVX6liS4lOzEYY9QFB2zx6LfoSNjz1a0pqT9
2057QOIfJWQ2E888NEVZNqLlZZnvIB0NpHkimlFdKn2iRRY7yGG/CCJb6Iz280d34SFXBS2yEYPNF0Q7
2058yM7oCjpWvbEDQmnhRwOs6zjThpKE8HogwRAgraqYFZgGZvzmzVh+mgz9vskT3hruwyjdFcqyENJw
2059bbMPO5jdzonxK68QKT7B57CMRRG5shRSWDTX3dI8LzRndZbnSWL1zfvriUmK4TcGWSnZiEPCrxXv
2060bM+sP7VW2is2WgWXCO3sAu3Rzysz3FiNCA8WPyM4gb1JAAmCiyTZbhFjWx3h9SzauuRXC9MFoVbc
2061yNTCm1QXOOIfIn/g1kGMhDUBN72hI5XCBQtIXQw8UEEdma6Jaz4vJIJ51Orc15hzzmu6TdFp3ogr
2062Aof0c98tsw1SiaiWotHffk3XYCkqdToxWRfTFXqgpg2khcLluOHMVC0zZhLKIomesfSreUNNgbXi
2063Ky9VRzwzkBneNoGQyyvGjbsFQqOZvpWIjqH281lJ/jireFgR3cPzSyTGWzQpDNIU+03Fs4XKLkhp
2064/n0uFnuF6VphB44b3uWRneSbBoMSioqE8oeF0JY+qTvYfEK+bPLYdoR4McfYQ7wMZj39q0kfP8q+
2065FfsymO0GzNlPh644Jje06ulqHpOEQqdJUfoidI2O4CWx4qOglLye6RrFQirpCRXvhoRqXH3sYdVJ
2066AItvc+VUsLO2v2hVAWrNIfVGtkG351cUMNncbh/WdowtSPtCdkzYFv6mwYc9o2Jt68ud6wectBr8
2067hYAulPSlgzH44YbV3ikjrulEaNJxt+/H3wZ7bXSXje/YY4tfVVrVmUstaDwwOBLMg6iduDB0lMVC
2068UyzYx7Ab4kjCqdViEJmDcdk/SKbgsjYXgfMznUWcrtS4z4fmJ/XOM1LPk/iIpqass5XwNbdnLb1Y
20698h3ERXSWZI6rZJxKs1LBqVH65w0Oy4ra0CBYxEeuOMbDmV5GI6E0Ha/wgVTtkX0+OXvqsD02CKLf
2070XHbeft85D7tTCMYy2Njp4DJP7gWJr6paVWXZ1+/6YXLv/iE0M90FktiI7yFJD9e7SOLhEkkaMTUO
2071azq9i2woBNR0/0eoF1HFMf0H8ChxH/jgcB34GZIz3Qn4/vid+VEamQrOVqAPTrOfmD4MPdVh09tb
20728dLLjvh/61lEP4yW5vJaH4vHcevG8agXvzPGoOhhXNncpTr99PTHx6e/UvffFLaxUSjuSeP286Dw
2073gtEMcW1xKr/he4/6IQ6FUXP+0gkioHY5iwC9Eyx3HKO7af0zPPe+XyLn7fAY78k4aiR387bCr5XT
20745C4rFgwLGfMvJuAMew==
2075""")
2076
2077##file distutils.cfg
2078DISTUTILS_CFG = convert("""
2079eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
2080xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
20819FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
2082""")
2083
2084##file activate_this.py
2085ACTIVATE_THIS = convert("""
2086eJyNUlGL2zAMfvevEBlHEujSsXsL9GGDvW1jD3sZpQQ3Ua7aJXawnbT595Ocpe0dO5ghseVP+vRJ
2087VpIkn2cYPZknwAvWLXWYhRP5Sk4baKgOWRWNqtpdgTyH2Y5wpq5Tug406YAgKEzkwqg7NBPwR86a
2088Hk0olPopaK0NHJHzYQPnE5rI0o8+yBUwiBfyQcT8mMPJGiAT0A0O+b8BY4MKJ7zPcSSzHaKrSpJE
2089qeDmUgGvVbPCS41DgO+6xy/OWbfAThMn/OQ9ukDWRCSLiKzk1yrLjWapq6NnvHUoHXQ4bYPdrsVX
20904lQMc/q6ZW975nmSK+oH6wL42a9H65U6aha342Mh0UVDzrD87C1bH73s16R5zsStkBZDp0NrXQ+7
2091HaRnMo8f06UBnljKoOtn/YT+LtdvSyaT/BtIv9KR60nF9f3qmuYKO4//T9ItJMsjPfgUHqKwCZ3n
2092xu/Lx8M/UvCLTxW7VULHxB1PRRbrYfvWNY5S8it008jOjcleaMqVBDnUXcWULV2YK9JEQ92OfC96
20931Tv4ZicZZZ7GpuEpZbbeQ7DxquVx5hdqoyFSSmXwfC90f1Dc7hjFs/tK99I0fpkI8zSLy4tSy+sI
20943vMWehjQNJmE5VePlZbL61nzX3S93ZcfDqznnkb9AZ3GWJU=
2095""")
2096
2097if __name__ == '__main__':
2098    main()
2099
2100## TODO:
2101## Copy python.exe.manifest
2102## Monkeypatch distutils.sysconfig
2103