Bumping gaia.json for 2 gaia-central revision(s) a=gaia-bump
[gecko.git] / python / virtualenv / virtualenv.py
blobba357fd5ea05a799770295d3a980d286322a3c4f
1 #!/usr/bin/env python
2 """Create a "virtual" Python installation
3 """
5 __version__ = "1.10.1"
6 virtualenv_version = __version__ # legacy
8 import base64
9 import sys
10 import os
11 import codecs
12 import optparse
13 import re
14 import shutil
15 import logging
16 import tempfile
17 import zlib
18 import errno
19 import glob
20 import distutils.sysconfig
21 from distutils.util import strtobool
22 import struct
23 import subprocess
24 import tarfile
26 if sys.version_info < (2, 6):
27 print('ERROR: %s' % sys.exc_info()[1])
28 print('ERROR: this script requires Python 2.6 or greater.')
29 sys.exit(101)
31 try:
32 set
33 except NameError:
34 from sets import Set as set
35 try:
36 basestring
37 except NameError:
38 basestring = str
40 try:
41 import ConfigParser
42 except ImportError:
43 import configparser as ConfigParser
45 join = os.path.join
46 py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
48 is_jython = sys.platform.startswith('java')
49 is_pypy = hasattr(sys, 'pypy_version_info')
50 is_win = (sys.platform == 'win32')
51 is_cygwin = (sys.platform == 'cygwin')
52 is_darwin = (sys.platform == 'darwin')
53 abiflags = getattr(sys, 'abiflags', '')
55 user_dir = os.path.expanduser('~')
56 if is_win:
57 default_storage_dir = os.path.join(user_dir, 'virtualenv')
58 else:
59 default_storage_dir = os.path.join(user_dir, '.virtualenv')
60 default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini')
62 if is_pypy:
63 expected_exe = 'pypy'
64 elif is_jython:
65 expected_exe = 'jython'
66 else:
67 expected_exe = 'python'
69 # Return a mapping of version -> Python executable
70 # Only provided for Windows, where the information in the registry is used
71 if not is_win:
72 def get_installed_pythons():
73 return {}
74 else:
75 try:
76 import winreg
77 except ImportError:
78 import _winreg as winreg
80 def get_installed_pythons():
81 python_core = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE,
82 "Software\\Python\\PythonCore")
83 i = 0
84 versions = []
85 while True:
86 try:
87 versions.append(winreg.EnumKey(python_core, i))
88 i = i + 1
89 except WindowsError:
90 break
91 exes = dict()
92 for ver in versions:
93 path = winreg.QueryValue(python_core, "%s\\InstallPath" % ver)
94 exes[ver] = join(path, "python.exe")
96 winreg.CloseKey(python_core)
98 # Add the major versions
99 # Sort the keys, then repeatedly update the major version entry
100 # Last executable (i.e., highest version) wins with this approach
101 for ver in sorted(exes):
102 exes[ver[0]] = exes[ver]
104 return exes
106 REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
107 'fnmatch', 'locale', 'encodings', 'codecs',
108 'stat', 'UserDict', 'readline', 'copy_reg', 'types',
109 're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
110 'zlib']
112 REQUIRED_FILES = ['lib-dynload', 'config']
114 majver, minver = sys.version_info[:2]
115 if majver == 2:
116 if minver >= 6:
117 REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc'])
118 if minver >= 7:
119 REQUIRED_MODULES.extend(['_weakrefset'])
120 if minver <= 3:
121 REQUIRED_MODULES.extend(['sets', '__future__'])
122 elif majver == 3:
123 # Some extra modules are needed for Python 3, but different ones
124 # for different versions.
125 REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
126 '_weakrefset', 'copyreg', 'tempfile', 'random',
127 '__future__', 'collections', 'keyword', 'tarfile',
128 'shutil', 'struct', 'copy', 'tokenize', 'token',
129 'functools', 'heapq', 'bisect', 'weakref',
130 'reprlib'])
131 if minver >= 2:
132 REQUIRED_FILES[-1] = 'config-%s' % majver
133 if minver == 3:
134 import sysconfig
135 platdir = sysconfig.get_config_var('PLATDIR')
136 REQUIRED_FILES.append(platdir)
137 # The whole list of 3.3 modules is reproduced below - the current
138 # uncommented ones are required for 3.3 as of now, but more may be
139 # added as 3.3 development continues.
140 REQUIRED_MODULES.extend([
141 #"aifc",
142 #"antigravity",
143 #"argparse",
144 #"ast",
145 #"asynchat",
146 #"asyncore",
147 "base64",
148 #"bdb",
149 #"binhex",
150 #"bisect",
151 #"calendar",
152 #"cgi",
153 #"cgitb",
154 #"chunk",
155 #"cmd",
156 #"codeop",
157 #"code",
158 #"colorsys",
159 #"_compat_pickle",
160 #"compileall",
161 #"concurrent",
162 #"configparser",
163 #"contextlib",
164 #"cProfile",
165 #"crypt",
166 #"csv",
167 #"ctypes",
168 #"curses",
169 #"datetime",
170 #"dbm",
171 #"decimal",
172 #"difflib",
173 #"dis",
174 #"doctest",
175 #"dummy_threading",
176 "_dummy_thread",
177 #"email",
178 #"filecmp",
179 #"fileinput",
180 #"formatter",
181 #"fractions",
182 #"ftplib",
183 #"functools",
184 #"getopt",
185 #"getpass",
186 #"gettext",
187 #"glob",
188 #"gzip",
189 "hashlib",
190 #"heapq",
191 "hmac",
192 #"html",
193 #"http",
194 #"idlelib",
195 #"imaplib",
196 #"imghdr",
197 "imp",
198 "importlib",
199 #"inspect",
200 #"json",
201 #"lib2to3",
202 #"logging",
203 #"macpath",
204 #"macurl2path",
205 #"mailbox",
206 #"mailcap",
207 #"_markupbase",
208 #"mimetypes",
209 #"modulefinder",
210 #"multiprocessing",
211 #"netrc",
212 #"nntplib",
213 #"nturl2path",
214 #"numbers",
215 #"opcode",
216 #"optparse",
217 #"os2emxpath",
218 #"pdb",
219 #"pickle",
220 #"pickletools",
221 #"pipes",
222 #"pkgutil",
223 #"platform",
224 #"plat-linux2",
225 #"plistlib",
226 #"poplib",
227 #"pprint",
228 #"profile",
229 #"pstats",
230 #"pty",
231 #"pyclbr",
232 #"py_compile",
233 #"pydoc_data",
234 #"pydoc",
235 #"_pyio",
236 #"queue",
237 #"quopri",
238 #"reprlib",
239 "rlcompleter",
240 #"runpy",
241 #"sched",
242 #"shelve",
243 #"shlex",
244 #"smtpd",
245 #"smtplib",
246 #"sndhdr",
247 #"socket",
248 #"socketserver",
249 #"sqlite3",
250 #"ssl",
251 #"stringprep",
252 #"string",
253 #"_strptime",
254 #"subprocess",
255 #"sunau",
256 #"symbol",
257 #"symtable",
258 #"sysconfig",
259 #"tabnanny",
260 #"telnetlib",
261 #"test",
262 #"textwrap",
263 #"this",
264 #"_threading_local",
265 #"threading",
266 #"timeit",
267 #"tkinter",
268 #"tokenize",
269 #"token",
270 #"traceback",
271 #"trace",
272 #"tty",
273 #"turtledemo",
274 #"turtle",
275 #"unittest",
276 #"urllib",
277 #"uuid",
278 #"uu",
279 #"wave",
280 #"weakref",
281 #"webbrowser",
282 #"wsgiref",
283 #"xdrlib",
284 #"xml",
285 #"xmlrpc",
286 #"zipfile",
289 if is_pypy:
290 # these are needed to correctly display the exceptions that may happen
291 # during the bootstrap
292 REQUIRED_MODULES.extend(['traceback', 'linecache'])
294 class Logger(object):
297 Logging object for use in command-line script. Allows ranges of
298 levels, to avoid some redundancy of displayed information.
301 DEBUG = logging.DEBUG
302 INFO = logging.INFO
303 NOTIFY = (logging.INFO+logging.WARN)/2
304 WARN = WARNING = logging.WARN
305 ERROR = logging.ERROR
306 FATAL = logging.FATAL
308 LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
310 def __init__(self, consumers):
311 self.consumers = consumers
312 self.indent = 0
313 self.in_progress = None
314 self.in_progress_hanging = False
316 def debug(self, msg, *args, **kw):
317 self.log(self.DEBUG, msg, *args, **kw)
318 def info(self, msg, *args, **kw):
319 self.log(self.INFO, msg, *args, **kw)
320 def notify(self, msg, *args, **kw):
321 self.log(self.NOTIFY, msg, *args, **kw)
322 def warn(self, msg, *args, **kw):
323 self.log(self.WARN, msg, *args, **kw)
324 def error(self, msg, *args, **kw):
325 self.log(self.ERROR, msg, *args, **kw)
326 def fatal(self, msg, *args, **kw):
327 self.log(self.FATAL, msg, *args, **kw)
328 def log(self, level, msg, *args, **kw):
329 if args:
330 if kw:
331 raise TypeError(
332 "You may give positional or keyword arguments, not both")
333 args = args or kw
334 rendered = None
335 for consumer_level, consumer in self.consumers:
336 if self.level_matches(level, consumer_level):
337 if (self.in_progress_hanging
338 and consumer in (sys.stdout, sys.stderr)):
339 self.in_progress_hanging = False
340 sys.stdout.write('\n')
341 sys.stdout.flush()
342 if rendered is None:
343 if args:
344 rendered = msg % args
345 else:
346 rendered = msg
347 rendered = ' '*self.indent + rendered
348 if hasattr(consumer, 'write'):
349 consumer.write(rendered+'\n')
350 else:
351 consumer(rendered)
353 def start_progress(self, msg):
354 assert not self.in_progress, (
355 "Tried to start_progress(%r) while in_progress %r"
356 % (msg, self.in_progress))
357 if self.level_matches(self.NOTIFY, self._stdout_level()):
358 sys.stdout.write(msg)
359 sys.stdout.flush()
360 self.in_progress_hanging = True
361 else:
362 self.in_progress_hanging = False
363 self.in_progress = msg
365 def end_progress(self, msg='done.'):
366 assert self.in_progress, (
367 "Tried to end_progress without start_progress")
368 if self.stdout_level_matches(self.NOTIFY):
369 if not self.in_progress_hanging:
370 # Some message has been printed out since start_progress
371 sys.stdout.write('...' + self.in_progress + msg + '\n')
372 sys.stdout.flush()
373 else:
374 sys.stdout.write(msg + '\n')
375 sys.stdout.flush()
376 self.in_progress = None
377 self.in_progress_hanging = False
379 def show_progress(self):
380 """If we are in a progress scope, and no log messages have been
381 shown, write out another '.'"""
382 if self.in_progress_hanging:
383 sys.stdout.write('.')
384 sys.stdout.flush()
386 def stdout_level_matches(self, level):
387 """Returns true if a message at this level will go to stdout"""
388 return self.level_matches(level, self._stdout_level())
390 def _stdout_level(self):
391 """Returns the level that stdout runs at"""
392 for level, consumer in self.consumers:
393 if consumer is sys.stdout:
394 return level
395 return self.FATAL
397 def level_matches(self, level, consumer_level):
399 >>> l = Logger([])
400 >>> l.level_matches(3, 4)
401 False
402 >>> l.level_matches(3, 2)
403 True
404 >>> l.level_matches(slice(None, 3), 3)
405 False
406 >>> l.level_matches(slice(None, 3), 2)
407 True
408 >>> l.level_matches(slice(1, 3), 1)
409 True
410 >>> l.level_matches(slice(2, 3), 1)
411 False
413 if isinstance(level, slice):
414 start, stop = level.start, level.stop
415 if start is not None and start > consumer_level:
416 return False
417 if stop is not None and stop <= consumer_level:
418 return False
419 return True
420 else:
421 return level >= consumer_level
423 #@classmethod
424 def level_for_integer(cls, level):
425 levels = cls.LEVELS
426 if level < 0:
427 return levels[0]
428 if level >= len(levels):
429 return levels[-1]
430 return levels[level]
432 level_for_integer = classmethod(level_for_integer)
434 # create a silent logger just to prevent this from being undefined
435 # will be overridden with requested verbosity main() is called.
436 logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
438 def mkdir(path):
439 if not os.path.exists(path):
440 logger.info('Creating %s', path)
441 os.makedirs(path)
442 else:
443 logger.info('Directory %s already exists', path)
445 def copyfileordir(src, dest, symlink=True):
446 if os.path.isdir(src):
447 shutil.copytree(src, dest, symlink)
448 else:
449 shutil.copy2(src, dest)
451 def copyfile(src, dest, symlink=True):
452 if not os.path.exists(src):
453 # Some bad symlink in the src
454 logger.warn('Cannot find file %s (bad symlink)', src)
455 return
456 if os.path.exists(dest):
457 logger.debug('File %s already exists', dest)
458 return
459 if not os.path.exists(os.path.dirname(dest)):
460 logger.info('Creating parent directories for %s', os.path.dirname(dest))
461 os.makedirs(os.path.dirname(dest))
462 if not os.path.islink(src):
463 srcpath = os.path.abspath(src)
464 else:
465 srcpath = os.readlink(src)
466 if symlink and hasattr(os, 'symlink') and not is_win:
467 logger.info('Symlinking %s', dest)
468 try:
469 os.symlink(srcpath, dest)
470 except (OSError, NotImplementedError):
471 logger.info('Symlinking failed, copying to %s', dest)
472 copyfileordir(src, dest, symlink)
473 else:
474 logger.info('Copying to %s', dest)
475 copyfileordir(src, dest, symlink)
477 def writefile(dest, content, overwrite=True):
478 if not os.path.exists(dest):
479 logger.info('Writing %s', dest)
480 f = open(dest, 'wb')
481 f.write(content.encode('utf-8'))
482 f.close()
483 return
484 else:
485 f = open(dest, 'rb')
486 c = f.read()
487 f.close()
488 if c != content.encode("utf-8"):
489 if not overwrite:
490 logger.notify('File %s exists with different content; not overwriting', dest)
491 return
492 logger.notify('Overwriting %s with new content', dest)
493 f = open(dest, 'wb')
494 f.write(content.encode('utf-8'))
495 f.close()
496 else:
497 logger.info('Content %s already in place', dest)
499 def rmtree(dir):
500 if os.path.exists(dir):
501 logger.notify('Deleting tree %s', dir)
502 shutil.rmtree(dir)
503 else:
504 logger.info('Do not need to delete %s; already gone', dir)
506 def make_exe(fn):
507 if hasattr(os, 'chmod'):
508 oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777
509 newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777
510 os.chmod(fn, newmode)
511 logger.info('Changed mode of %s to %s', fn, oct(newmode))
513 def _find_file(filename, dirs):
514 for dir in reversed(dirs):
515 files = glob.glob(os.path.join(dir, filename))
516 if files and os.path.isfile(files[0]):
517 return True, files[0]
518 return False, filename
520 def file_search_dirs():
521 here = os.path.dirname(os.path.abspath(__file__))
522 dirs = ['.', here,
523 join(here, 'virtualenv_support')]
524 if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
525 # Probably some boot script; just in case virtualenv is installed...
526 try:
527 import virtualenv
528 except ImportError:
529 pass
530 else:
531 dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
532 return [d for d in dirs if os.path.isdir(d)]
535 class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
537 Custom help formatter for use in ConfigOptionParser that updates
538 the defaults before expanding them, allowing them to show up correctly
539 in the help listing
541 def expand_default(self, option):
542 if self.parser is not None:
543 self.parser.update_defaults(self.parser.defaults)
544 return optparse.IndentedHelpFormatter.expand_default(self, option)
547 class ConfigOptionParser(optparse.OptionParser):
549 Custom option parser which updates its defaults by checking the
550 configuration files and environmental variables
552 def __init__(self, *args, **kwargs):
553 self.config = ConfigParser.RawConfigParser()
554 self.files = self.get_config_files()
555 self.config.read(self.files)
556 optparse.OptionParser.__init__(self, *args, **kwargs)
558 def get_config_files(self):
559 config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False)
560 if config_file and os.path.exists(config_file):
561 return [config_file]
562 return [default_config_file]
564 def update_defaults(self, defaults):
566 Updates the given defaults with values from the config files and
567 the environ. Does a little special handling for certain types of
568 options (lists).
570 # Then go and look for the other sources of configuration:
571 config = {}
572 # 1. config files
573 config.update(dict(self.get_config_section('virtualenv')))
574 # 2. environmental variables
575 config.update(dict(self.get_environ_vars()))
576 # Then set the options with those values
577 for key, val in config.items():
578 key = key.replace('_', '-')
579 if not key.startswith('--'):
580 key = '--%s' % key # only prefer long opts
581 option = self.get_option(key)
582 if option is not None:
583 # ignore empty values
584 if not val:
585 continue
586 # handle multiline configs
587 if option.action == 'append':
588 val = val.split()
589 else:
590 option.nargs = 1
591 if option.action == 'store_false':
592 val = not strtobool(val)
593 elif option.action in ('store_true', 'count'):
594 val = strtobool(val)
595 try:
596 val = option.convert_value(key, val)
597 except optparse.OptionValueError:
598 e = sys.exc_info()[1]
599 print("An error occured during configuration: %s" % e)
600 sys.exit(3)
601 defaults[option.dest] = val
602 return defaults
604 def get_config_section(self, name):
606 Get a section of a configuration
608 if self.config.has_section(name):
609 return self.config.items(name)
610 return []
612 def get_environ_vars(self, prefix='VIRTUALENV_'):
614 Returns a generator with all environmental vars with prefix VIRTUALENV
616 for key, val in os.environ.items():
617 if key.startswith(prefix):
618 yield (key.replace(prefix, '').lower(), val)
620 def get_default_values(self):
622 Overridding to make updating the defaults after instantiation of
623 the option parser possible, update_defaults() does the dirty work.
625 if not self.process_default_values:
626 # Old, pre-Optik 1.5 behaviour.
627 return optparse.Values(self.defaults)
629 defaults = self.update_defaults(self.defaults.copy()) # ours
630 for option in self._get_all_options():
631 default = defaults.get(option.dest)
632 if isinstance(default, basestring):
633 opt_str = option.get_opt_string()
634 defaults[option.dest] = option.check_value(opt_str, default)
635 return optparse.Values(defaults)
638 def main():
639 parser = ConfigOptionParser(
640 version=virtualenv_version,
641 usage="%prog [OPTIONS] DEST_DIR",
642 formatter=UpdatingDefaultsHelpFormatter())
644 parser.add_option(
645 '-v', '--verbose',
646 action='count',
647 dest='verbose',
648 default=0,
649 help="Increase verbosity")
651 parser.add_option(
652 '-q', '--quiet',
653 action='count',
654 dest='quiet',
655 default=0,
656 help='Decrease verbosity')
658 parser.add_option(
659 '-p', '--python',
660 dest='python',
661 metavar='PYTHON_EXE',
662 help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
663 'interpreter to create the new environment. The default is the interpreter that '
664 'virtualenv was installed with (%s)' % sys.executable)
666 parser.add_option(
667 '--clear',
668 dest='clear',
669 action='store_true',
670 help="Clear out the non-root install and start from scratch")
672 parser.set_defaults(system_site_packages=False)
673 parser.add_option(
674 '--no-site-packages',
675 dest='system_site_packages',
676 action='store_false',
677 help="Don't give access to the global site-packages dir to the "
678 "virtual environment (default)")
680 parser.add_option(
681 '--system-site-packages',
682 dest='system_site_packages',
683 action='store_true',
684 help="Give access to the global site-packages dir to the "
685 "virtual environment")
687 parser.add_option(
688 '--always-copy',
689 dest='symlink',
690 action='store_false',
691 default=True,
692 help="Always copy files rather than symlinking")
694 parser.add_option(
695 '--unzip-setuptools',
696 dest='unzip_setuptools',
697 action='store_true',
698 help="Unzip Setuptools when installing it")
700 parser.add_option(
701 '--relocatable',
702 dest='relocatable',
703 action='store_true',
704 help='Make an EXISTING virtualenv environment relocatable. '
705 'This fixes up scripts and makes all .pth files relative')
707 parser.add_option(
708 '--no-setuptools',
709 dest='no_setuptools',
710 action='store_true',
711 help='Do not install setuptools (or pip) '
712 'in the new virtualenv.')
714 parser.add_option(
715 '--no-pip',
716 dest='no_pip',
717 action='store_true',
718 help='Do not install pip in the new virtualenv.')
720 default_search_dirs = file_search_dirs()
721 parser.add_option(
722 '--extra-search-dir',
723 dest="search_dirs",
724 action="append",
725 default=default_search_dirs,
726 help="Directory to look for setuptools/pip distributions in. "
727 "You can add any number of additional --extra-search-dir paths.")
729 parser.add_option(
730 '--never-download',
731 dest="never_download",
732 action="store_true",
733 default=True,
734 help="Never download anything from the network. This is now always "
735 "the case. The option is only retained for backward compatibility, "
736 "and does nothing. Virtualenv will fail if local distributions "
737 "of setuptools/pip are not present.")
739 parser.add_option(
740 '--prompt',
741 dest='prompt',
742 help='Provides an alternative prompt prefix for this environment')
744 parser.add_option(
745 '--setuptools',
746 dest='setuptools',
747 action='store_true',
748 help="Backward compatibility. Does nothing.")
750 parser.add_option(
751 '--distribute',
752 dest='distribute',
753 action='store_true',
754 help="Backward compatibility. Does nothing.")
756 if 'extend_parser' in globals():
757 extend_parser(parser)
759 options, args = parser.parse_args()
761 global logger
763 if 'adjust_options' in globals():
764 adjust_options(options, args)
766 verbosity = options.verbose - options.quiet
767 logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)])
769 if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
770 env = os.environ.copy()
771 interpreter = resolve_interpreter(options.python)
772 if interpreter == sys.executable:
773 logger.warn('Already using interpreter %s' % interpreter)
774 else:
775 logger.notify('Running virtualenv with interpreter %s' % interpreter)
776 env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
777 file = __file__
778 if file.endswith('.pyc'):
779 file = file[:-1]
780 popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
781 raise SystemExit(popen.wait())
783 if not args:
784 print('You must provide a DEST_DIR')
785 parser.print_help()
786 sys.exit(2)
787 if len(args) > 1:
788 print('There must be only one argument: DEST_DIR (you gave %s)' % (
789 ' '.join(args)))
790 parser.print_help()
791 sys.exit(2)
793 home_dir = args[0]
795 if os.environ.get('WORKING_ENV'):
796 logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
797 logger.fatal('Please deactivate your workingenv, then re-run this script')
798 sys.exit(3)
800 if 'PYTHONHOME' in os.environ:
801 logger.warn('PYTHONHOME is set. You *must* activate the virtualenv before using it')
802 del os.environ['PYTHONHOME']
804 if options.relocatable:
805 make_environment_relocatable(home_dir)
806 return
808 if not options.never_download:
809 logger.warn('The --never-download option is for backward compatibility only.')
810 logger.warn('Setting it to false is no longer supported, and will be ignored.')
812 create_environment(home_dir,
813 site_packages=options.system_site_packages,
814 clear=options.clear,
815 unzip_setuptools=options.unzip_setuptools,
816 prompt=options.prompt,
817 search_dirs=options.search_dirs,
818 never_download=True,
819 no_setuptools=options.no_setuptools,
820 no_pip=options.no_pip,
821 symlink=options.symlink)
822 if 'after_install' in globals():
823 after_install(options, home_dir)
825 def call_subprocess(cmd, show_stdout=True,
826 filter_stdout=None, cwd=None,
827 raise_on_returncode=True, extra_env=None,
828 remove_from_env=None):
829 cmd_parts = []
830 for part in cmd:
831 if len(part) > 45:
832 part = part[:20]+"..."+part[-20:]
833 if ' ' in part or '\n' in part or '"' in part or "'" in part:
834 part = '"%s"' % part.replace('"', '\\"')
835 if hasattr(part, 'decode'):
836 try:
837 part = part.decode(sys.getdefaultencoding())
838 except UnicodeDecodeError:
839 part = part.decode(sys.getfilesystemencoding())
840 cmd_parts.append(part)
841 cmd_desc = ' '.join(cmd_parts)
842 if show_stdout:
843 stdout = None
844 else:
845 stdout = subprocess.PIPE
846 logger.debug("Running command %s" % cmd_desc)
847 if extra_env or remove_from_env:
848 env = os.environ.copy()
849 if extra_env:
850 env.update(extra_env)
851 if remove_from_env:
852 for varname in remove_from_env:
853 env.pop(varname, None)
854 else:
855 env = None
856 try:
857 proc = subprocess.Popen(
858 cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
859 cwd=cwd, env=env)
860 except Exception:
861 e = sys.exc_info()[1]
862 logger.fatal(
863 "Error %s while executing command %s" % (e, cmd_desc))
864 raise
865 all_output = []
866 if stdout is not None:
867 stdout = proc.stdout
868 encoding = sys.getdefaultencoding()
869 fs_encoding = sys.getfilesystemencoding()
870 while 1:
871 line = stdout.readline()
872 try:
873 line = line.decode(encoding)
874 except UnicodeDecodeError:
875 line = line.decode(fs_encoding)
876 if not line:
877 break
878 line = line.rstrip()
879 all_output.append(line)
880 if filter_stdout:
881 level = filter_stdout(line)
882 if isinstance(level, tuple):
883 level, line = level
884 logger.log(level, line)
885 if not logger.stdout_level_matches(level):
886 logger.show_progress()
887 else:
888 logger.info(line)
889 else:
890 proc.communicate()
891 proc.wait()
892 if proc.returncode:
893 if raise_on_returncode:
894 if all_output:
895 logger.notify('Complete output from command %s:' % cmd_desc)
896 logger.notify('\n'.join(all_output) + '\n----------------------------------------')
897 raise OSError(
898 "Command %s failed with error code %s"
899 % (cmd_desc, proc.returncode))
900 else:
901 logger.warn(
902 "Command %s had error code %s"
903 % (cmd_desc, proc.returncode))
905 def filter_install_output(line):
906 if line.strip().startswith('running'):
907 return Logger.INFO
908 return Logger.DEBUG
910 def install_sdist(project_name, sdist, py_executable, search_dirs=None):
912 if search_dirs is None:
913 search_dirs = file_search_dirs()
914 found, sdist_path = _find_file(sdist, search_dirs)
915 if not found:
916 logger.fatal("Cannot find sdist %s" % (sdist,))
917 return
919 tmpdir = tempfile.mkdtemp()
920 try:
921 tar = tarfile.open(sdist_path)
922 tar.extractall(tmpdir)
923 tar.close()
924 srcdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
925 cmd = [py_executable, 'setup.py', 'install',
926 '--single-version-externally-managed',
927 '--record', 'record']
928 logger.start_progress('Installing %s...' % project_name)
929 logger.indent += 2
930 try:
931 call_subprocess(cmd, show_stdout=False, cwd=srcdir,
932 filter_stdout=filter_install_output)
933 finally:
934 logger.indent -= 2
935 logger.end_progress()
936 finally:
937 shutil.rmtree(tmpdir)
939 def create_environment(home_dir, site_packages=False, clear=False,
940 unzip_setuptools=False,
941 prompt=None, search_dirs=None, never_download=False,
942 no_setuptools=False, no_pip=False, symlink=True):
944 Creates a new environment in ``home_dir``.
946 If ``site_packages`` is true, then the global ``site-packages/``
947 directory will be on the path.
949 If ``clear`` is true (default False) then the environment will
950 first be cleared.
952 home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
954 py_executable = os.path.abspath(install_python(
955 home_dir, lib_dir, inc_dir, bin_dir,
956 site_packages=site_packages, clear=clear, symlink=symlink))
958 install_distutils(home_dir)
960 if not no_setuptools:
961 install_sdist('Setuptools', 'setuptools-*.tar.gz', py_executable, search_dirs)
962 if not no_pip:
963 install_sdist('Pip', 'pip-*.tar.gz', py_executable, search_dirs)
965 install_activate(home_dir, bin_dir, prompt)
967 def is_executable_file(fpath):
968 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
970 def path_locations(home_dir):
971 """Return the path locations for the environment (where libraries are,
972 where scripts go, etc)"""
973 # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
974 # prefix arg is broken: http://bugs.python.org/issue3386
975 if is_win:
976 # Windows has lots of problems with executables with spaces in
977 # the name; this function will remove them (using the ~1
978 # format):
979 mkdir(home_dir)
980 if ' ' in home_dir:
981 import ctypes
982 GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW
983 size = max(len(home_dir)+1, 256)
984 buf = ctypes.create_unicode_buffer(size)
985 try:
986 u = unicode
987 except NameError:
988 u = str
989 ret = GetShortPathName(u(home_dir), buf, size)
990 if not ret:
991 print('Error: the path "%s" has a space in it' % home_dir)
992 print('We could not determine the short pathname for it.')
993 print('Exiting.')
994 sys.exit(3)
995 home_dir = str(buf.value)
996 lib_dir = join(home_dir, 'Lib')
997 inc_dir = join(home_dir, 'Include')
998 bin_dir = join(home_dir, 'Scripts')
999 if is_jython:
1000 lib_dir = join(home_dir, 'Lib')
1001 inc_dir = join(home_dir, 'Include')
1002 bin_dir = join(home_dir, 'bin')
1003 elif is_pypy:
1004 lib_dir = home_dir
1005 inc_dir = join(home_dir, 'include')
1006 bin_dir = join(home_dir, 'bin')
1007 elif not is_win:
1008 lib_dir = join(home_dir, 'lib', py_version)
1009 multiarch_exec = '/usr/bin/multiarch-platform'
1010 if is_executable_file(multiarch_exec):
1011 # In Mageia (2) and Mandriva distros the include dir must be like:
1012 # virtualenv/include/multiarch-x86_64-linux/python2.7
1013 # instead of being virtualenv/include/python2.7
1014 p = subprocess.Popen(multiarch_exec, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
1015 stdout, stderr = p.communicate()
1016 # stdout.strip is needed to remove newline character
1017 inc_dir = join(home_dir, 'include', stdout.strip(), py_version + abiflags)
1018 else:
1019 inc_dir = join(home_dir, 'include', py_version + abiflags)
1020 bin_dir = join(home_dir, 'bin')
1021 return home_dir, lib_dir, inc_dir, bin_dir
1024 def change_prefix(filename, dst_prefix):
1025 prefixes = [sys.prefix]
1027 if is_darwin:
1028 prefixes.extend((
1029 os.path.join("/Library/Python", sys.version[:3], "site-packages"),
1030 os.path.join(sys.prefix, "Extras", "lib", "python"),
1031 os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"),
1032 # Python 2.6 no-frameworks
1033 os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"),
1034 # System Python 2.7 on OSX Mountain Lion
1035 os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages")))
1037 if hasattr(sys, 'real_prefix'):
1038 prefixes.append(sys.real_prefix)
1039 if hasattr(sys, 'base_prefix'):
1040 prefixes.append(sys.base_prefix)
1041 prefixes = list(map(os.path.expanduser, prefixes))
1042 prefixes = list(map(os.path.abspath, prefixes))
1043 # Check longer prefixes first so we don't split in the middle of a filename
1044 prefixes = sorted(prefixes, key=len, reverse=True)
1045 filename = os.path.abspath(filename)
1046 for src_prefix in prefixes:
1047 if filename.startswith(src_prefix):
1048 _, relpath = filename.split(src_prefix, 1)
1049 if src_prefix != os.sep: # sys.prefix == "/"
1050 assert relpath[0] == os.sep
1051 relpath = relpath[1:]
1052 return join(dst_prefix, relpath)
1053 assert False, "Filename %s does not start with any of these prefixes: %s" % \
1054 (filename, prefixes)
1056 def copy_required_modules(dst_prefix, symlink):
1057 import imp
1058 # If we are running under -p, we need to remove the current
1059 # directory from sys.path temporarily here, so that we
1060 # definitely get the modules from the site directory of
1061 # the interpreter we are running under, not the one
1062 # virtualenv.py is installed under (which might lead to py2/py3
1063 # incompatibility issues)
1064 _prev_sys_path = sys.path
1065 if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
1066 sys.path = sys.path[1:]
1067 try:
1068 for modname in REQUIRED_MODULES:
1069 if modname in sys.builtin_module_names:
1070 logger.info("Ignoring built-in bootstrap module: %s" % modname)
1071 continue
1072 try:
1073 f, filename, _ = imp.find_module(modname)
1074 except ImportError:
1075 logger.info("Cannot import bootstrap module: %s" % modname)
1076 else:
1077 if f is not None:
1078 f.close()
1079 # special-case custom readline.so on OS X, but not for pypy:
1080 if modname == 'readline' and sys.platform == 'darwin' and not (
1081 is_pypy or filename.endswith(join('lib-dynload', 'readline.so'))):
1082 dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so')
1083 elif modname == 'readline' and sys.platform == 'win32':
1084 # special-case for Windows, where readline is not a
1085 # standard module, though it may have been installed in
1086 # site-packages by a third-party package
1087 pass
1088 else:
1089 dst_filename = change_prefix(filename, dst_prefix)
1090 copyfile(filename, dst_filename, symlink)
1091 if filename.endswith('.pyc'):
1092 pyfile = filename[:-1]
1093 if os.path.exists(pyfile):
1094 copyfile(pyfile, dst_filename[:-1], symlink)
1095 finally:
1096 sys.path = _prev_sys_path
1099 def subst_path(prefix_path, prefix, home_dir):
1100 prefix_path = os.path.normpath(prefix_path)
1101 prefix = os.path.normpath(prefix)
1102 home_dir = os.path.normpath(home_dir)
1103 if not prefix_path.startswith(prefix):
1104 logger.warn('Path not in prefix %r %r', prefix_path, prefix)
1105 return
1106 return prefix_path.replace(prefix, home_dir, 1)
1109 def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, symlink=True):
1110 """Install just the base environment, no distutils patches etc"""
1111 if sys.executable.startswith(bin_dir):
1112 print('Please use the *system* python to run this script')
1113 return
1115 if clear:
1116 rmtree(lib_dir)
1117 ## FIXME: why not delete it?
1118 ## Maybe it should delete everything with #!/path/to/venv/python in it
1119 logger.notify('Not deleting %s', bin_dir)
1121 if hasattr(sys, 'real_prefix'):
1122 logger.notify('Using real prefix %r' % sys.real_prefix)
1123 prefix = sys.real_prefix
1124 elif hasattr(sys, 'base_prefix'):
1125 logger.notify('Using base prefix %r' % sys.base_prefix)
1126 prefix = sys.base_prefix
1127 else:
1128 prefix = sys.prefix
1129 mkdir(lib_dir)
1130 fix_lib64(lib_dir, symlink)
1131 stdlib_dirs = [os.path.dirname(os.__file__)]
1132 if is_win:
1133 stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
1134 elif is_darwin:
1135 stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
1136 if hasattr(os, 'symlink'):
1137 logger.info('Symlinking Python bootstrap modules')
1138 else:
1139 logger.info('Copying Python bootstrap modules')
1140 logger.indent += 2
1141 try:
1142 # copy required files...
1143 for stdlib_dir in stdlib_dirs:
1144 if not os.path.isdir(stdlib_dir):
1145 continue
1146 for fn in os.listdir(stdlib_dir):
1147 bn = os.path.splitext(fn)[0]
1148 if fn != 'site-packages' and bn in REQUIRED_FILES:
1149 copyfile(join(stdlib_dir, fn), join(lib_dir, fn), symlink)
1150 # ...and modules
1151 copy_required_modules(home_dir, symlink)
1152 finally:
1153 logger.indent -= 2
1154 mkdir(join(lib_dir, 'site-packages'))
1155 import site
1156 site_filename = site.__file__
1157 if site_filename.endswith('.pyc'):
1158 site_filename = site_filename[:-1]
1159 elif site_filename.endswith('$py.class'):
1160 site_filename = site_filename.replace('$py.class', '.py')
1161 site_filename_dst = change_prefix(site_filename, home_dir)
1162 site_dir = os.path.dirname(site_filename_dst)
1163 writefile(site_filename_dst, SITE_PY)
1164 writefile(join(site_dir, 'orig-prefix.txt'), prefix)
1165 site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
1166 if not site_packages:
1167 writefile(site_packages_filename, '')
1169 if is_pypy or is_win:
1170 stdinc_dir = join(prefix, 'include')
1171 else:
1172 stdinc_dir = join(prefix, 'include', py_version + abiflags)
1173 if os.path.exists(stdinc_dir):
1174 copyfile(stdinc_dir, inc_dir, symlink)
1175 else:
1176 logger.debug('No include dir %s' % stdinc_dir)
1178 platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1)
1179 if platinc_dir != stdinc_dir:
1180 platinc_dest = distutils.sysconfig.get_python_inc(
1181 plat_specific=1, prefix=home_dir)
1182 if platinc_dir == platinc_dest:
1183 # Do platinc_dest manually due to a CPython bug;
1184 # not http://bugs.python.org/issue3386 but a close cousin
1185 platinc_dest = subst_path(platinc_dir, prefix, home_dir)
1186 if platinc_dest:
1187 # PyPy's stdinc_dir and prefix are relative to the original binary
1188 # (traversing virtualenvs), whereas the platinc_dir is relative to
1189 # the inner virtualenv and ignores the prefix argument.
1190 # This seems more evolved than designed.
1191 copyfile(platinc_dir, platinc_dest, symlink)
1193 # pypy never uses exec_prefix, just ignore it
1194 if sys.exec_prefix != prefix and not is_pypy:
1195 if is_win:
1196 exec_dir = join(sys.exec_prefix, 'lib')
1197 elif is_jython:
1198 exec_dir = join(sys.exec_prefix, 'Lib')
1199 else:
1200 exec_dir = join(sys.exec_prefix, 'lib', py_version)
1201 for fn in os.listdir(exec_dir):
1202 copyfile(join(exec_dir, fn), join(lib_dir, fn), symlink)
1204 if is_jython:
1205 # Jython has either jython-dev.jar and javalib/ dir, or just
1206 # jython.jar
1207 for name in 'jython-dev.jar', 'javalib', 'jython.jar':
1208 src = join(prefix, name)
1209 if os.path.exists(src):
1210 copyfile(src, join(home_dir, name), symlink)
1211 # XXX: registry should always exist after Jython 2.5rc1
1212 src = join(prefix, 'registry')
1213 if os.path.exists(src):
1214 copyfile(src, join(home_dir, 'registry'), symlink=False)
1215 copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
1216 symlink=False)
1218 mkdir(bin_dir)
1219 py_executable = join(bin_dir, os.path.basename(sys.executable))
1220 if 'Python.framework' in prefix:
1221 # OS X framework builds cause validation to break
1222 # https://github.com/pypa/virtualenv/issues/322
1223 if os.environ.get('__PYVENV_LAUNCHER__'):
1224 os.unsetenv('__PYVENV_LAUNCHER__')
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')
1231 logger.notify('New %s executable in %s', expected_exe, py_executable)
1232 pcbuild_dir = os.path.dirname(sys.executable)
1233 pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth')
1234 if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')):
1235 logger.notify('Detected python running from build directory %s', pcbuild_dir)
1236 logger.notify('Writing .pth file linking to build directory for *.pyd files')
1237 writefile(pyd_pth, pcbuild_dir)
1238 else:
1239 pcbuild_dir = None
1240 if os.path.exists(pyd_pth):
1241 logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth)
1242 os.unlink(pyd_pth)
1244 if sys.executable != py_executable:
1245 ## FIXME: could I just hard link?
1246 executable = sys.executable
1247 shutil.copyfile(executable, py_executable)
1248 make_exe(py_executable)
1249 if is_win or is_cygwin:
1250 pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
1251 if os.path.exists(pythonw):
1252 logger.info('Also created pythonw.exe')
1253 shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
1254 python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe')
1255 python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe')
1256 if os.path.exists(python_d):
1257 logger.info('Also created python_d.exe')
1258 shutil.copyfile(python_d, python_d_dest)
1259 elif os.path.exists(python_d_dest):
1260 logger.info('Removed python_d.exe as it is no longer at the source')
1261 os.unlink(python_d_dest)
1262 # we need to copy the DLL to enforce that windows will load the correct one.
1263 # may not exist if we are cygwin.
1264 py_executable_dll = 'python%s%s.dll' % (
1265 sys.version_info[0], sys.version_info[1])
1266 py_executable_dll_d = 'python%s%s_d.dll' % (
1267 sys.version_info[0], sys.version_info[1])
1268 pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll)
1269 pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d)
1270 pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d)
1271 if os.path.exists(pythondll):
1272 logger.info('Also created %s' % py_executable_dll)
1273 shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll))
1274 if os.path.exists(pythondll_d):
1275 logger.info('Also created %s' % py_executable_dll_d)
1276 shutil.copyfile(pythondll_d, pythondll_d_dest)
1277 elif os.path.exists(pythondll_d_dest):
1278 logger.info('Removed %s as the source does not exist' % pythondll_d_dest)
1279 os.unlink(pythondll_d_dest)
1280 if is_pypy:
1281 # make a symlink python --> pypy-c
1282 python_executable = os.path.join(os.path.dirname(py_executable), 'python')
1283 if sys.platform in ('win32', 'cygwin'):
1284 python_executable += '.exe'
1285 logger.info('Also created executable %s' % python_executable)
1286 copyfile(py_executable, python_executable, symlink)
1288 if is_win:
1289 for name in 'libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', 'libeay32.dll', 'ssleay32.dll', 'sqlite.dll':
1290 src = join(prefix, name)
1291 if os.path.exists(src):
1292 copyfile(src, join(bin_dir, name), symlink)
1294 if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
1295 secondary_exe = os.path.join(os.path.dirname(py_executable),
1296 expected_exe)
1297 py_executable_ext = os.path.splitext(py_executable)[1]
1298 if py_executable_ext.lower() == '.exe':
1299 # python2.4 gives an extension of '.4' :P
1300 secondary_exe += py_executable_ext
1301 if os.path.exists(secondary_exe):
1302 logger.warn('Not overwriting existing %s script %s (you must use %s)'
1303 % (expected_exe, secondary_exe, py_executable))
1304 else:
1305 logger.notify('Also creating executable in %s' % secondary_exe)
1306 shutil.copyfile(sys.executable, secondary_exe)
1307 make_exe(secondary_exe)
1309 if '.framework' in prefix:
1310 if 'Python.framework' in prefix:
1311 logger.debug('MacOSX Python framework detected')
1312 # Make sure we use the the embedded interpreter inside
1313 # the framework, even if sys.executable points to
1314 # the stub executable in ${sys.prefix}/bin
1315 # See http://groups.google.com/group/python-virtualenv/
1316 # browse_thread/thread/17cab2f85da75951
1317 original_python = os.path.join(
1318 prefix, 'Resources/Python.app/Contents/MacOS/Python')
1319 if 'EPD' in prefix:
1320 logger.debug('EPD framework detected')
1321 original_python = os.path.join(prefix, 'bin/python')
1322 shutil.copy(original_python, py_executable)
1324 # Copy the framework's dylib into the virtual
1325 # environment
1326 virtual_lib = os.path.join(home_dir, '.Python')
1328 if os.path.exists(virtual_lib):
1329 os.unlink(virtual_lib)
1330 copyfile(
1331 os.path.join(prefix, 'Python'),
1332 virtual_lib,
1333 symlink)
1335 # And then change the install_name of the copied python executable
1336 try:
1337 mach_o_change(py_executable,
1338 os.path.join(prefix, 'Python'),
1339 '@executable_path/../.Python')
1340 except:
1341 e = sys.exc_info()[1]
1342 logger.warn("Could not call mach_o_change: %s. "
1343 "Trying to call install_name_tool instead." % e)
1344 try:
1345 call_subprocess(
1346 ["install_name_tool", "-change",
1347 os.path.join(prefix, 'Python'),
1348 '@executable_path/../.Python',
1349 py_executable])
1350 except:
1351 logger.fatal("Could not call install_name_tool -- you must "
1352 "have Apple's development tools installed")
1353 raise
1355 if not is_win:
1356 # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist
1357 py_exe_version_major = 'python%s' % sys.version_info[0]
1358 py_exe_version_major_minor = 'python%s.%s' % (
1359 sys.version_info[0], sys.version_info[1])
1360 py_exe_no_version = 'python'
1361 required_symlinks = [ py_exe_no_version, py_exe_version_major,
1362 py_exe_version_major_minor ]
1364 py_executable_base = os.path.basename(py_executable)
1366 if py_executable_base in required_symlinks:
1367 # Don't try to symlink to yourself.
1368 required_symlinks.remove(py_executable_base)
1370 for pth in required_symlinks:
1371 full_pth = join(bin_dir, pth)
1372 if os.path.exists(full_pth):
1373 os.unlink(full_pth)
1374 if symlink:
1375 os.symlink(py_executable_base, full_pth)
1376 else:
1377 shutil.copyfile(py_executable_base, full_pth)
1379 if is_win and ' ' in py_executable:
1380 # There's a bug with subprocess on Windows when using a first
1381 # argument that has a space in it. Instead we have to quote
1382 # the value:
1383 py_executable = '"%s"' % py_executable
1384 # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks
1385 cmd = [py_executable, '-c', 'import sys;out=sys.stdout;'
1386 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))']
1387 logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
1388 try:
1389 proc = subprocess.Popen(cmd,
1390 stdout=subprocess.PIPE)
1391 proc_stdout, proc_stderr = proc.communicate()
1392 except OSError:
1393 e = sys.exc_info()[1]
1394 if e.errno == errno.EACCES:
1395 logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e))
1396 sys.exit(100)
1397 else:
1398 raise e
1400 proc_stdout = proc_stdout.strip().decode("utf-8")
1401 proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
1402 norm_home_dir = os.path.normcase(os.path.abspath(home_dir))
1403 if hasattr(norm_home_dir, 'decode'):
1404 norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding())
1405 if proc_stdout != norm_home_dir:
1406 logger.fatal(
1407 'ERROR: The executable %s is not functioning' % py_executable)
1408 logger.fatal(
1409 'ERROR: It thinks sys.prefix is %r (should be %r)'
1410 % (proc_stdout, norm_home_dir))
1411 logger.fatal(
1412 'ERROR: virtualenv is not compatible with this system or executable')
1413 if is_win:
1414 logger.fatal(
1415 'Note: some Windows users have reported this error when they '
1416 'installed Python for "Only this user" or have multiple '
1417 'versions of Python installed. Copying the appropriate '
1418 'PythonXX.dll to the virtualenv Scripts/ directory may fix '
1419 'this problem.')
1420 sys.exit(100)
1421 else:
1422 logger.info('Got sys.prefix result: %r' % proc_stdout)
1424 pydistutils = os.path.expanduser('~/.pydistutils.cfg')
1425 if os.path.exists(pydistutils):
1426 logger.notify('Please make sure you remove any previous custom paths from '
1427 'your %s file.' % pydistutils)
1428 ## FIXME: really this should be calculated earlier
1430 fix_local_scheme(home_dir, symlink)
1432 if site_packages:
1433 if os.path.exists(site_packages_filename):
1434 logger.info('Deleting %s' % site_packages_filename)
1435 os.unlink(site_packages_filename)
1437 return py_executable
1440 def install_activate(home_dir, bin_dir, prompt=None):
1441 home_dir = os.path.abspath(home_dir)
1442 if is_win or is_jython and os._name == 'nt':
1443 files = {
1444 'activate.bat': ACTIVATE_BAT,
1445 'deactivate.bat': DEACTIVATE_BAT,
1446 'activate.ps1': ACTIVATE_PS,
1449 # MSYS needs paths of the form /c/path/to/file
1450 drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/'))
1451 home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail)
1453 # Run-time conditional enables (basic) Cygwin compatibility
1454 home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" %
1455 (home_dir, home_dir_msys))
1456 files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh)
1458 else:
1459 files = {'activate': ACTIVATE_SH}
1461 # suppling activate.fish in addition to, not instead of, the
1462 # bash script support.
1463 files['activate.fish'] = ACTIVATE_FISH
1465 # same for csh/tcsh support...
1466 files['activate.csh'] = ACTIVATE_CSH
1468 files['activate_this.py'] = ACTIVATE_THIS
1469 if hasattr(home_dir, 'decode'):
1470 home_dir = home_dir.decode(sys.getfilesystemencoding())
1471 vname = os.path.basename(home_dir)
1472 for name, content in files.items():
1473 content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
1474 content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname)
1475 content = content.replace('__VIRTUAL_ENV__', home_dir)
1476 content = content.replace('__VIRTUAL_NAME__', vname)
1477 content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
1478 writefile(os.path.join(bin_dir, name), content)
1480 def install_distutils(home_dir):
1481 distutils_path = change_prefix(distutils.__path__[0], home_dir)
1482 mkdir(distutils_path)
1483 ## FIXME: maybe this prefix setting should only be put in place if
1484 ## there's a local distutils.cfg with a prefix setting?
1485 home_dir = os.path.abspath(home_dir)
1486 ## FIXME: this is breaking things, removing for now:
1487 #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
1488 writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
1489 writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
1491 def fix_local_scheme(home_dir, symlink=True):
1493 Platforms that use the "posix_local" install scheme (like Ubuntu with
1494 Python 2.7) need to be given an additional "local" location, sigh.
1496 try:
1497 import sysconfig
1498 except ImportError:
1499 pass
1500 else:
1501 if sysconfig._get_default_scheme() == 'posix_local':
1502 local_path = os.path.join(home_dir, 'local')
1503 if not os.path.exists(local_path):
1504 os.mkdir(local_path)
1505 for subdir_name in os.listdir(home_dir):
1506 if subdir_name == 'local':
1507 continue
1508 cp_or_ln = (os.symlink if symlink else copyfile)
1509 cp_or_ln(os.path.abspath(os.path.join(home_dir, subdir_name)), \
1510 os.path.join(local_path, subdir_name))
1512 def fix_lib64(lib_dir, symlink=True):
1514 Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
1515 instead of lib/pythonX.Y. If this is such a platform we'll just create a
1516 symlink so lib64 points to lib
1518 if [p for p in distutils.sysconfig.get_config_vars().values()
1519 if isinstance(p, basestring) and 'lib64' in p]:
1520 # PyPy's library path scheme is not affected by this.
1521 # Return early or we will die on the following assert.
1522 if is_pypy:
1523 logger.debug('PyPy detected, skipping lib64 symlinking')
1524 return
1526 logger.debug('This system uses lib64; symlinking lib64 to lib')
1528 assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
1529 "Unexpected python lib dir: %r" % lib_dir)
1530 lib_parent = os.path.dirname(lib_dir)
1531 top_level = os.path.dirname(lib_parent)
1532 lib_dir = os.path.join(top_level, 'lib')
1533 lib64_link = os.path.join(top_level, 'lib64')
1534 assert os.path.basename(lib_parent) == 'lib', (
1535 "Unexpected parent dir: %r" % lib_parent)
1536 if os.path.lexists(lib64_link):
1537 return
1538 cp_or_ln = (os.symlink if symlink else copyfile)
1539 cp_or_ln('lib', lib64_link)
1541 def resolve_interpreter(exe):
1543 If the executable given isn't an absolute path, search $PATH for the interpreter
1545 # If the "executable" is a version number, get the installed executable for
1546 # that version
1547 python_versions = get_installed_pythons()
1548 if exe in python_versions:
1549 exe = python_versions[exe]
1551 if os.path.abspath(exe) != exe:
1552 paths = os.environ.get('PATH', '').split(os.pathsep)
1553 for path in paths:
1554 if os.path.exists(os.path.join(path, exe)):
1555 exe = os.path.join(path, exe)
1556 break
1557 if not os.path.exists(exe):
1558 logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
1559 raise SystemExit(3)
1560 if not is_executable(exe):
1561 logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
1562 raise SystemExit(3)
1563 return exe
1565 def is_executable(exe):
1566 """Checks a file is executable"""
1567 return os.access(exe, os.X_OK)
1569 ############################################################
1570 ## Relocating the environment:
1572 def make_environment_relocatable(home_dir):
1574 Makes the already-existing environment use relative paths, and takes out
1575 the #!-based environment selection in scripts.
1577 home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
1578 activate_this = os.path.join(bin_dir, 'activate_this.py')
1579 if not os.path.exists(activate_this):
1580 logger.fatal(
1581 'The environment doesn\'t have a file %s -- please re-run virtualenv '
1582 'on this environment to update it' % activate_this)
1583 fixup_scripts(home_dir, bin_dir)
1584 fixup_pth_and_egg_link(home_dir)
1585 ## FIXME: need to fix up distutils.cfg
1587 OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
1588 'activate', 'activate.bat', 'activate_this.py']
1590 def fixup_scripts(home_dir, bin_dir):
1591 if is_win:
1592 new_shebang_args = (
1593 '%s /c' % os.path.normcase(os.environ.get('COMSPEC', 'cmd.exe')),
1594 '', '.exe')
1595 else:
1596 new_shebang_args = ('/usr/bin/env', sys.version[:3], '')
1598 # This is what we expect at the top of scripts:
1599 shebang = '#!%s' % os.path.normcase(os.path.join(
1600 os.path.abspath(bin_dir), 'python%s' % new_shebang_args[2]))
1601 # This is what we'll put:
1602 new_shebang = '#!%s python%s%s' % new_shebang_args
1604 for filename in os.listdir(bin_dir):
1605 filename = os.path.join(bin_dir, filename)
1606 if not os.path.isfile(filename):
1607 # ignore subdirs, e.g. .svn ones.
1608 continue
1609 f = open(filename, 'rb')
1610 try:
1611 try:
1612 lines = f.read().decode('utf-8').splitlines()
1613 except UnicodeDecodeError:
1614 # This is probably a binary program instead
1615 # of a script, so just ignore it.
1616 continue
1617 finally:
1618 f.close()
1619 if not lines:
1620 logger.warn('Script %s is an empty file' % filename)
1621 continue
1623 old_shebang = lines[0].strip()
1624 old_shebang = old_shebang[0:2] + os.path.normcase(old_shebang[2:])
1626 if not old_shebang.startswith(shebang):
1627 if os.path.basename(filename) in OK_ABS_SCRIPTS:
1628 logger.debug('Cannot make script %s relative' % filename)
1629 elif lines[0].strip() == new_shebang:
1630 logger.info('Script %s has already been made relative' % filename)
1631 else:
1632 logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
1633 % (filename, shebang))
1634 continue
1635 logger.notify('Making script %s relative' % filename)
1636 script = relative_script([new_shebang] + lines[1:])
1637 f = open(filename, 'wb')
1638 f.write('\n'.join(script).encode('utf-8'))
1639 f.close()
1641 def relative_script(lines):
1642 "Return a script that'll work in a relocatable environment."
1643 activate = "import os; activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); exec(compile(open(activate_this).read(), activate_this, 'exec'), dict(__file__=activate_this)); del os, activate_this"
1644 # Find the last future statement in the script. If we insert the activation
1645 # line before a future statement, Python will raise a SyntaxError.
1646 activate_at = None
1647 for idx, line in reversed(list(enumerate(lines))):
1648 if line.split()[:3] == ['from', '__future__', 'import']:
1649 activate_at = idx + 1
1650 break
1651 if activate_at is None:
1652 # Activate after the shebang.
1653 activate_at = 1
1654 return lines[:activate_at] + ['', activate, ''] + lines[activate_at:]
1656 def fixup_pth_and_egg_link(home_dir, sys_path=None):
1657 """Makes .pth and .egg-link files use relative paths"""
1658 home_dir = os.path.normcase(os.path.abspath(home_dir))
1659 if sys_path is None:
1660 sys_path = sys.path
1661 for path in sys_path:
1662 if not path:
1663 path = '.'
1664 if not os.path.isdir(path):
1665 continue
1666 path = os.path.normcase(os.path.abspath(path))
1667 if not path.startswith(home_dir):
1668 logger.debug('Skipping system (non-environment) directory %s' % path)
1669 continue
1670 for filename in os.listdir(path):
1671 filename = os.path.join(path, filename)
1672 if filename.endswith('.pth'):
1673 if not os.access(filename, os.W_OK):
1674 logger.warn('Cannot write .pth file %s, skipping' % filename)
1675 else:
1676 fixup_pth_file(filename)
1677 if filename.endswith('.egg-link'):
1678 if not os.access(filename, os.W_OK):
1679 logger.warn('Cannot write .egg-link file %s, skipping' % filename)
1680 else:
1681 fixup_egg_link(filename)
1683 def fixup_pth_file(filename):
1684 lines = []
1685 prev_lines = []
1686 f = open(filename)
1687 prev_lines = f.readlines()
1688 f.close()
1689 for line in prev_lines:
1690 line = line.strip()
1691 if (not line or line.startswith('#') or line.startswith('import ')
1692 or os.path.abspath(line) != line):
1693 lines.append(line)
1694 else:
1695 new_value = make_relative_path(filename, line)
1696 if line != new_value:
1697 logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
1698 lines.append(new_value)
1699 if lines == prev_lines:
1700 logger.info('No changes to .pth file %s' % filename)
1701 return
1702 logger.notify('Making paths in .pth file %s relative' % filename)
1703 f = open(filename, 'w')
1704 f.write('\n'.join(lines) + '\n')
1705 f.close()
1707 def fixup_egg_link(filename):
1708 f = open(filename)
1709 link = f.readline().strip()
1710 f.close()
1711 if os.path.abspath(link) != link:
1712 logger.debug('Link in %s already relative' % filename)
1713 return
1714 new_link = make_relative_path(filename, link)
1715 logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
1716 f = open(filename, 'w')
1717 f.write(new_link)
1718 f.close()
1720 def make_relative_path(source, dest, dest_is_directory=True):
1722 Make a filename relative, where the filename is dest, and it is
1723 being referred to from the filename source.
1725 >>> make_relative_path('/usr/share/something/a-file.pth',
1726 ... '/usr/share/another-place/src/Directory')
1727 '../another-place/src/Directory'
1728 >>> make_relative_path('/usr/share/something/a-file.pth',
1729 ... '/home/user/src/Directory')
1730 '../../../home/user/src/Directory'
1731 >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
1732 './'
1734 source = os.path.dirname(source)
1735 if not dest_is_directory:
1736 dest_filename = os.path.basename(dest)
1737 dest = os.path.dirname(dest)
1738 dest = os.path.normpath(os.path.abspath(dest))
1739 source = os.path.normpath(os.path.abspath(source))
1740 dest_parts = dest.strip(os.path.sep).split(os.path.sep)
1741 source_parts = source.strip(os.path.sep).split(os.path.sep)
1742 while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
1743 dest_parts.pop(0)
1744 source_parts.pop(0)
1745 full_parts = ['..']*len(source_parts) + dest_parts
1746 if not dest_is_directory:
1747 full_parts.append(dest_filename)
1748 if not full_parts:
1749 # Special case for the current directory (otherwise it'd be '')
1750 return './'
1751 return os.path.sep.join(full_parts)
1755 ############################################################
1756 ## Bootstrap script creation:
1758 def create_bootstrap_script(extra_text, python_version=''):
1760 Creates a bootstrap script, which is like this script but with
1761 extend_parser, adjust_options, and after_install hooks.
1763 This returns a string that (written to disk of course) can be used
1764 as a bootstrap script with your own customizations. The script
1765 will be the standard virtualenv.py script, with your extra text
1766 added (your extra text should be Python code).
1768 If you include these functions, they will be called:
1770 ``extend_parser(optparse_parser)``:
1771 You can add or remove options from the parser here.
1773 ``adjust_options(options, args)``:
1774 You can change options here, or change the args (if you accept
1775 different kinds of arguments, be sure you modify ``args`` so it is
1776 only ``[DEST_DIR]``).
1778 ``after_install(options, home_dir)``:
1780 After everything is installed, this function is called. This
1781 is probably the function you are most likely to use. An
1782 example would be::
1784 def after_install(options, home_dir):
1785 subprocess.call([join(home_dir, 'bin', 'easy_install'),
1786 'MyPackage'])
1787 subprocess.call([join(home_dir, 'bin', 'my-package-script'),
1788 'setup', home_dir])
1790 This example immediately installs a package, and runs a setup
1791 script from that package.
1793 If you provide something like ``python_version='2.5'`` then the
1794 script will start with ``#!/usr/bin/env python2.5`` instead of
1795 ``#!/usr/bin/env python``. You can use this when the script must
1796 be run with a particular Python version.
1798 filename = __file__
1799 if filename.endswith('.pyc'):
1800 filename = filename[:-1]
1801 f = codecs.open(filename, 'r', encoding='utf-8')
1802 content = f.read()
1803 f.close()
1804 py_exe = 'python%s' % python_version
1805 content = (('#!/usr/bin/env %s\n' % py_exe)
1806 + '## WARNING: This file is generated\n'
1807 + content)
1808 return content.replace('##EXT' 'END##', extra_text)
1810 ##EXTEND##
1812 def convert(s):
1813 b = base64.b64decode(s.encode('ascii'))
1814 return zlib.decompress(b).decode('utf-8')
1816 ##file site.py
1817 SITE_PY = convert("""
1818 eJzFPf1z2zaWv/OvwMqToZTIdOJ0e3tOnRsncVrvuYm3SWdz63q0lARZrCmSJUjL2pu7v/3eBwAC
1819 JCXbm+6cphNLJPDw8PC+8PAeOhgMTopCZnOxyud1KoWScTlbiiKulkos8lJUy6Sc7xdxWW3g6ewm
1820 vpZKVLlQGxVhqygInn7lJ3gqPi8TZVCAb3Fd5au4SmZxmm5EsiryspJzMa/LJLsWSZZUSZwm/4AW
1821 eRaJp1+PQXCWCZh5mshS3MpSAVwl8oW42FTLPBPDusA5v4j+GL8cjYWalUlRQYNS4wwUWcZVkEk5
1822 BzShZa2AlEkl91UhZ8kimdmG67xO56JI45kUf/87T42ahmGg8pVcL2UpRQbIAEwJsArEA74mpZjl
1823 cxkJ8UbOYhyAnzfEChjaGNdMIRmzXKR5dg1zyuRMKhWXGzGc1hUBIpTFPAecEsCgStI0WOfljRrB
1824 ktJ6rOGRiJk9/Mkwe8A8cfwu5wCOH7Pg5yy5GzNs4B4EVy2ZbUq5SO5EjGDhp7yTs4l+NkwWYp4s
1825 FkCDrBphk4ARUCJNpgcFLcd3eoVeHxBWlitjGEMiytyYX1KPKDirRJwqYNu6QBopwvydnCZxBtTI
1826 bmE4gAgkDfrGmSeqsuPQ7EQOAEpcxwqkZKXEcBUnGTDrj/GM0P5rks3ztRoRBWC1lPi1VpU7/2EP
1827 AaC1Q4BxgItlVrPO0uRGppsRIPAZsC+lqtMKBWKelHJW5WUiFQEA1DZC3gHSYxGXUpOQOdPI7Zjo
1828 TzRJMlxYFDAUeHyJJFkk13VJEiYWCXAucMX7jz+Jd6dvzk4+aB4zwFhmr1eAM0ChhXZwggHEQa3K
1829 gzQHgY6Cc/wj4vkchewaxwe8mgYH9650MIS5F1G7j7PgQHa9uHoYmGMFyoTGCqjff0OXsVoCff7n
1830 nvUOgpNtVKGJ87f1MgeZzOKVFMuY+Qs5I/hOw3kdFdXyFXCDQjgVkErh4iCCCcIDkrg0G+aZFAWw
1831 WJpkchQAhabU1l9FYIUPebZPa93iBIBQBhm8dJ6NaMRMwkS7sF6hvjCNNzQz3SSw67zKS1IcwP/Z
1832 jHRRGmc3hKMihuJvU3mdZBkihLwQhHshDaxuEuDEeSTOqRXpBdNIhKy9uCWKRA28hEwHPCnv4lWR
1833 yjGLL+rW3WqEBpOVMGudMsdBy4rUK61aM9Ve3juMvrS4jtCslqUE4PXUE7pFno/FFHQ2YVPEKxav
1834 ap0T5wQ98kSdkCeoJfTF70DRE6XqlbQvkVdAsxBDBYs8TfM1kOwoCITYw0bGKPvMCW/hHfwLcPHf
1835 VFazZRA4I1nAGhQivw0UAgGTIDPN1RoJj9s0K7eVTJKxpsjLuSxpqIcR+4ARf2BjnGvwIa+0UePp
1836 4irnq6RClTTVJjNhi5eFFevHVzxvmAZYbkU0M00bOq1wemmxjKfSuCRTuUBJ0Iv0yi47jBn0jEm2
1837 uBIrtjLwDsgiE7Yg/YoFlc6ikuQEAAwWvjhLijqlRgoZTMQw0Kog+KsYTXqunSVgbzbLASokNt8z
1838 sD+A2z9AjNbLBOgzAwigYVBLwfJNk6pEB6HRR4Fv9E1/Hh849WyhbRMPuYiTVFv5OAvO6OFpWZL4
1839 zmSBvcaaGApmmFXo2l1nQEcU88FgEATGHdoo8zVXQVVujoAVhBlnMpnWCRq+yQRNvf6hAh5FOAN7
1840 3Ww7Cw80hOn0AajkdFmU+Qpf27l9AmUCY2GPYE9ckJaR7CB7nPgKyeeq9MI0RdvtsLNAPRRc/HT6
1841 /uzL6SdxLC4blTZu67MrGPM0i4GtySIAU7WGbXQZtETFl6DuE+/BvBNTgD2j3iS+Mq5q4F1A/XNZ
1842 02uYxsx7GZx+OHlzfjr5+dPpT5NPZ59PAUGwMzLYoymjeazBYVQRCAdw5VxF2r4GnR704M3JJ/sg
1843 mCRq8u03wG7wZHgtK2DicggzHotwFd8pYNBwTE1HiGOnAVjwcDQSr8Xh06cvDwlasSk2AAzMrtMU
1844 H060RZ8k2SIPR9T4V3bpj1lJaf/t8uibK3F8LMJf49s4DMCHapoyS/xI4vR5U0joWsGfYa5GQTCX
1845 CxC9G4kCOnxKfvGIO8CSQMtc2+lf8yQz75kr3SFIfwypB+AwmczSWClsPJmEQATq0POBDhE71yh1
1846 Q+hYbNyuI40KfkoJC5thlzH+04NiPKV+iAaj6HYxjUBcV7NYSW5F04d+kwnqrMlkqAcEYSaJAYeL
1847 1VAoTBPUWWUCfi1xHuqwqcpT/InwUQuQAOLWCrUkLpLeOkW3cVpLNXQmBUQcDltkREWbKOJHcFGG
1848 YImbpRuN2tQ0PAPNgHxpDlq0bFEOP3vg74C6Mps43Ojx3otphpj+mXcahAO4nCGqe6VaUFg7iovT
1849 C/Hy+eE+ujOw55xb6njN0UInWS3twwWslpEHRph7GXlx6bJAPYtPj3bDXEV2ZbqssNBLXMpVfivn
1850 gC0ysLPK4id6AztzmMcshlUEvU7+AKtQ4zfGuA/l2YO0oO8A1FsRFLP+Zun3OBggMwWKiDfWRGq9
1851 62dTWJT5bYLOxnSjX4KtBGWJFtM4NoGzcB6ToUkEDQFecIaUWssQ1GFZs8NKeCNItBfzRrFGBO4c
1852 NfUVfb3J8nU24Z3wMSrd4ciyLgqWZl5s0CzBnngPVgiQzGFj1xCNoYDLL1C29gF5mD5MFyhLewsA
1853 BIZe0XbNgWW2ejRF3jXisAhj9EqQ8JYS/YVbMwRttQwxHEj0NrIPjJZASDA5q+CsatBMhrJmmsHA
1854 Dkl8rjuPeAvqA2hRMQKzOdTQuJGh3+URKGdx7iolpx9a5C9fvjDbqCXFVxCxKU4aXYgFGcuo2IBh
1855 TUAnGI+MozXEBmtwbgFMrTRriv1PIi/YG4P1vNCyDX4A7O6qqjg6OFiv15GOLuTl9YFaHPzxT99+
1856 +6fnrBPnc+IfmI4jLTrUFh3QO/Roo++MBXptVq7Fj0nmcyPBGkryysgVRfy+r5N5Lo72R1Z/Ihc3
1857 Zhr/Na4MKJCJGZSpDLQdNBg9UftPopdqIJ6QdbZthyP2S7RJtVbMt7rQo8rBEwC/ZZbXaKobTlDi
1858 GVg32KHP5bS+Du3gno00P2CqKKdDywP7L64QA58zDF8ZUzxBLUFsgRbfIf1PzDYxeUdaQyB50UR1
1859 ds+bfi1miDt/uLxbX9MRGjPDRCF3oET4TR4sgLZxV3Lwo11btHuOa2s+niEwlj4wzKsdyyEKDuGC
1860 azF2pc7havR4QZrWrJpBwbiqERQ0OIlTprYGRzYyRJDo3ZjNPi+sbgF0akUOTXzArAK0cMfpWLs2
1861 KzieEPLAsXhBTyS4yEedd895aes0pYBOi0c9qjBgb6HRTufAl0MDYCwG5c8Dbmm2KR9bi8Jr0AMs
1862 5xgQMtiiw0z4xvUBB3uDHnbqWP1tvZnGfSBwkYYci3oQdEL5mEcoFUhTMfR7bmNxS9zuYDstDjGV
1863 WSYSabVFuNrKo1eodhqmRZKh7nUWKZqlOXjFVisSIzXvfWeB9kH4uM+YaQnUZGjI4TQ6Jm/PE8BQ
1864 t8Pw2XWNgQY3DoMYrRJF1g3JtIR/wK2g+AYFo4CWBM2CeaiU+RP7HWTOzld/2cIeltDIEG7TbW5I
1865 x2JoOOb9nkAy6mgMSEEGJOwKI7mOrA5S4DBngTzhhtdyq3QTjEiBnDkWhNQM4E4vvQ0OPonwBIQk
1866 FCHfVUoW4pkYwPK1RfVhuvt35VIThBg6DchV0NGLYzey4UQ1jltRDp+h/fgGnZUUOXDwFFweN9Dv
1867 srlhWht0AWfdV9wWKdDIFIcZjFxUrwxh3GDyH46dFg2xzCCGobyBvCMdM9IosMutQcOCGzDemrfH
1868 0o/diAX2HYa5OpSrO9j/hWWiZrkKKWbSjl24H80VXdpYbM+T6QD+eAswGF15kGSq4xcYZfknBgk9
1869 6GEfdG+yGBaZx+U6yUJSYJp+x/7SdPCwpPSM3MEn2k4dwEQx4nnwvgQBoaPPAxAn1ASwK5eh0m5/
1870 F+zOKQ4sXO4+8Nzmy6OXV13ijrdFeOynf6lO76oyVrhaKS8aCwWuVteAo9KFycXZRh9e6sNt3CaU
1871 uYJdpPj46YtAQnBcdx1vHjf1huERm3vn5H0M6qDX7iVXa3bELoAIakVklIPw8Rz5cGQfO7kdE3sE
1872 kEcxzI5FMZA0n/wzcHYtFIyxP99kGEdrqwz8wOtvv5n0REZdJL/9ZnDPKC1i9In9sOUJ2pE5qWDX
1873 bEsZp+RqOH0oqJg1rGPbFCPW57T90zx21eNzarRs7Lu/BX4MFAypS/ARno8bsnWnih/fndoKT9up
1874 HcA6u1Xz2aNFgL19Pv0VdshKB9Vu4ySlcwWY/P4+Klezued4Rb/28CDtVDAOCfr2X+ryOXBDyNGE
1875 UXc62hk7MQHnnl2w+RSx6qKyp3MImiMwLy/APf7sQtUWzDDucz5eOOxRTd6M+5yJr1Gr+PldNJAF
1876 5tFg0Ef2rez4/zHL5/+aST5wKubk+ne0ho8E9HvNhI0HQ9PGw4fVv+yu3TXAHmCetridO9zC7tB8
1877 Vrkwzh2rJCWeou56KtaUrkCxVTwpAihz9vt64OAy6kPvt3VZ8tE1qcBClvt4HDsWmKllPL9eE7Mn
1878 Dj7ICjGxzWYUq3byevI+NRLq6LOdSdjsG/rlbJmbmJXMbpMS+oLCHYY/fPzxNOw3IRjHhU4PtyIP
1879 9xsQ7iOYNtTECR/Thyn0mC7/vFS1ty4+QU1GgIkIa7L12gc/EGziCP1rcE9EyDuw5WN23KHPlnJ2
1880 M5GUOoBsil2doPhbfI2Y2IwCP/9LxQtKYoOZzNIaacWON2YfLupsRucjlQT/SqcKY+oQJQRw+G+R
1881 xtdiSJ3nGHrS3EjRqdu41N5nUeaYnCrqZH5wncyF/K2OU9zWy8UCcMHDK/0q4uEpAiXecU4DJy0q
1882 OavLpNoACWKV67M/Sn9wGk43PNGhhyQf8zABMSHiSHzCaeN7JtzckMsEB/wTD5wk7ruxg5OsENFz
1883 eJ/lExx1Qjm+Y0aqey5Pj4P2CDkAGABQmP9gpCN3/htJr9wDRlpzl6ioJT1SupGGnJwxhDIcYaSD
1884 f9NPnxFd3tqC5fV2LK93Y3ndxvK6F8trH8vr3Vi6IoELa4NWRhL6AlftY43efBs35sTDnMazJbfD
1885 3E/M8QSIojAbbCNTnALtRbb4fI+AkNp2DpzpYZM/k3BSaZlzCFyDRO7HQyy9mTfJ605nysbRnXkq
1886 xp3dlkPk9z2IIkoVm1J3lrd5XMWRJxfXaT4FsbXojhsAY9FOJ+JYaXY7mXJ0t2WpBhf/9fmHjx+w
1887 OYIamPQG6oaLiIYFpzJ8GpfXqitNzeavAHakln4iDnXTAPceGFnjUfb4n3eU4YGMI9aUoZCLAjwA
1888 yuqyzdzcpzBsPddJUvo5MzkfNh2LQVYNmkltIdLJxcW7k88nAwr5Df534AqMoa0vHS4+poVt0PXf
1889 3OaW4tgHhFrHthrj587Jo3XDEffbWAO248O3Hhw+xGD3hgn8Wf5LKQVLAoSKdPD3MYR68B7oq7YJ
1890 HfoYRuwk/7kna+ys2HeO7DkuiiP6fccO7QH8w07cY0yAANqFGpqdQbOZail9a153UNQB+kBf76u3
1891 YO2tV3sn41PUTqLHAXQoa5ttd/+8cxo2ekpWb06/P/twfvbm4uTzD44LiK7cx08Hh+L0xy+C8kPQ
1892 gLFPFGNqRIWZSGBY3EInMc/hvxojP/O64iAx9Hp3fq5PalZY6oK5z2hzInjOaUwWGgfNOAptH+r8
1893 I8Qo1Rskp6aI0nWo5gj3SyuuZ1G5zo+mUqUpOqu13nrpWjFTU0bn2hFIHzR2ScEgOMUMXlEWe2V2
1894 hSWfAOo6qx6ktI22iSEpBQU76QLO+Zc5XfECpdQZnjSdtaK/DF1cw6tIFWkCO7lXoZUl3Q3TYxrG
1895 0Q/tATfj1acBne4wsm7Is96KBVqtVyHPTfcfNYz2Ww0YNgz2DuadSUoPoQxsTG4TITbik5xQ3sFX
1896 u/R6DRQsGB70VbiIhukSmH0Mm2uxTGADATy5BOuL+wSA0FoJ/0DgyIkOyByzM8K3q/n+X0JNEL/1
1897 L7/0NK/KdP9vooBdkOBUorCHmG7jd7DxiWQkTj++H4WMHKXmir/UWB4ADgkFQB1pp/wlPkGfDJVM
1898 Fzq/xNcH+EL7CfS61b2URam797vGIUrAEzUkr+GJMvQLMd3Lwh7jVEYt0Fj5YDHDCkI3DcF89sSn
1899 pUxTne9+9u78FHxHLMZACeJzt1MYjuMleISuk++4wrEFCg/Y4XWJbFyiC0tJFvPIa9YbtEaRo95e
1900 XoZdJwoMd3t1osBlnCgX7SFOm2GZcoIIWRnWwiwrs3arDVLYbUMUR5lhlphclJTA6vME8DI9jXlL
1901 BHslLPUwEXg+RU6yymQspskM9CioXFCoYxASJC7WMxLn5RnHwPNSmTIoeFhsyuR6WeHpBnSOqAQD
1902 m/948uX87AOVJRy+bLzuHuYc005gzEkkx5giiNEO+OKm/SFXTSZ9PKtfIQzUPvCn/YqzU455gE4/
1903 Dizin/YrrkM7dnaCPANQUHXRFg/cADjd+uSmkQXG1e6D8eOmADaY+WAoFollLzrRw51flxNty5Yp
1904 obiPefmIA5xFYVPSdGc3Ja390XNcFHjONR/2N4K3fbJlPlPoetN5sy35zf10pBBLYgGjbmt/DJMd
1905 1mmqp+Mw2zZuoW2ttrG/ZE6s1Gk3y1CUgYhDt/PIZbJ+JaybMwd6adQdYOI7ja6RxF5VPvglG2gP
1906 w8PEEruzTzEdqYyFjABGMqSu/anBh0KLAAqEsn+HjuSOR08PvTk61uD+OWrdBbbxB1CEOheXajzy
1907 EjgRvvzGjiO/IrRQjx6J0PFUMpnlNk8MP+slepUv/Dn2ygAFMVHsyji7lkOGNTYwn/nE3hKCJW3r
1908 kfoyueozLOIMnNO7LRzelYv+gxODWosROu1u5KatjnzyYIPeUpCdBPPBl/EadH9RV0NeyS3n0L21
1909 dNuh3g8Rsw+hqT59H4YYjvkt3LI+DeBeamhY6OH9tuUUltfGOLLWPraqmkL7QnuwsxK2ZpWiYxmn
1910 ONH4otYLaAzucWPyB/apThSyv3vqxJyYkAXKg7sgvbkNdINWOGHA5UpcOZpQOnxTTaPfzeWtTMFo
1911 gJEdYrXDr7baYRTZcEpvHthXY3exudj040ZvGsyOTDkGemaqgPWLMlkdIDq9EZ9dmDXI4FL/orck
1912 cXZDXvLbv56NxdsPP8G/b+RHMKVY/DgWfwM0xNu8hP0lV+/StQpYyVHxxjGvFVZIEjQ6quAbKNBt
1913 u/DojMciusTEry2xmlJgVm254mtPAEWeIFW0N36CKZyA36ayq+WNGk+xb1EG+iXSYHuxCxaIHOiW
1914 0bJapWgvnChJs5qXg/Ozt6cfPp1G1R1yuPk5cKIofkIWTkefEZd4HjYW9smsxidXjuP8g0yLHr9Z
1915 bzpN4QxuOkUI+5LCbjT5So3Ybi7iEiMHotjM81mELYHluVavWoMjPXL2l/caes/KIqzhSJ+iNd48
1916 PgZqiF/aimgADamPnhP1JITiKRaN8eNo0G+Kx4JC2/Dn6c167kbGdfUPTbCNaTProd/d6sIl01nD
1917 s5xEeB3bZTAFoWkSq9V05hYKfsyEvhEFtBydc8hFXKeVkBlILm3y6WoK0PRubR9LCLMKmzMqeKMw
1918 TbqON8pJQoqVGOCoA6quxwMZihjCHvzH+IbtARYdipproQE6IUr7p9zpqurZkiWYt0REvZ7Eg3WS
1919 vXTzeTSFeVDeIc8aRxbmiW4jY3QtKz1/fjAcXb5oMh0oKj3zKntnBVg9l032QHUWT58+HYj/uN/7
1920 YVSiNM9vwC0D2L1eyzm93mK59eTsanU9e/MmAn6cLeUlPLii6Ll9XmcUmtzRlRZE2r8GRohrE1pm
1921 NO1bdpmDdiUfNHMLPrDSluPnLKF7jzC0JFHZ6uujMOxkpIlYEhRDGKtZkoQcpoD12OQ1FuVhmFHz
1922 i7wDjk8QzBjf4gkZb7WX6GFSAq3lHovOsRgQ4AHllvFoVNVMZWmA5+Rio9GcnGVJ1dSTPHcPT/Vd
1923 AJW9zkjzlYjXKBlmHi1iOPWdHqs2Hna+k0W9HUs+u3QDjq1Z8uv7cAfWBknLFwuDKTw0izTLZTkz
1924 5hRXLJkllQPGtEM43JlucSLrEwU9KA1AvZNVmFuJtm//YNfFxfQjnSPvm5F0+lBlb8bi4FCctRIM
1925 o6gZn8JQlpCWb82XEYzygcLa2hPwxhJ/0EFVLCbwLvBw6xrrTF/MwfkbzW0dAIcug7IK0rKjpyOc
1926 G8gsfGbaLddp4Ie26ITbbVJWdZxO9P0PE3TYJvZgXeNp6+F2VnpabwWc/Bw84H2dug+Og8myQXpi
1927 6q0pzTgWCx2iiNwSM78aq8jRyztkXwl8CqTMfGIKo00Q6dKyq6041TmbjopHUM9MFdMWz9yUz3Qq
1928 T1zMx5TnZOoetnjRfgop3WEhXovhy7E4bG2BZsUGr3QCZJ/MQ98Vo24wFScqYObYviBDvD4Wwxdj
1929 8ccd0KMtAxwduiO0N7QtCFuBvLx6NBnTZEpkC/ty2e/vq5MZQdMzjqOrNvm7ZPqOqPTvLSpxqaDO
1930 WH7Rzlhujb11A9v5+EiGK1Aci0TO958oJKFGutHN2xmc8MNK+j2brKWLyJvSGqqgm8JmZN3oQUcj
1931 GrfZDmKq07X64kJe1DVsOO3lAyZfppWzaK+bw3xGjV6LqABg0nemht/wkhd4r0nh+mdbz1p1NYAF
1932 2xNK0CWffHLWNGwE9V5H8FEa4B5GESGeqjaKwpWsR4hISBfiEBM9a51mOxz/uzMP1xpsOxPtYPnt
1933 N7vwdAWzt7qjZ0F3l1x4ImvrLJrlNp/+CJ3HKH1dv0pgHCiN6ICzau6sJDfzCNOY+TKa3KYzr/BW
1934 SDqiRpOYStdt4q00X/+FfgzFDiirDNYCPKl6gSfKt3TJ5Ymi7De8q+abwxdjUyLMgPQEXkYvn+m7
1935 IKmbuQXB97HHeu8GL3W/w+jfHGBJ5fe2rzq7GZrWcetSKH+wkMJoo2hi6dAYpvsLQpo1iwVentgQ
1936 k31rexPIe/B2puDnmFtQc3DYYEMa9aHraoxGerepti0CfL/J2CY5D+raKFJEepewbVOeuxTno0VB
1937 9+q3IBhCQM5fxvwGXcG6OLIhNmNT8Ah06KZ14qe66S1AY3uCxra6CXdNn/vvmrtuEdiZm6yGztz9
1938 QlOXBrrvdivaRwMOb2hCPKhWotH4/cbEtQNjnUzTH6rXHyS/2wlnusWs3AfGpO5g4J/YU2NvzP4q
1939 nrnfMTNsn29mduuKe52N1rQ7NqPN8Q/xFDgLBp/bqwYotWmuOZD3S3TV3oSTZSfy+lpNYrzmcUKb
1940 bErs6uyezLbtPd3SJ2O1MbstvL0IQBhu0im4bpY9MAboSr5umvOinGtqBA1N2cNOOrJK5mwS9NYO
1941 wEUcMaX+JiLP+cSDVGKgW9VlUcJueKAvJeaEnb4c5waoCeCtYnVjUDc9xvqOWlKslCVmapE5TtvK
1942 9gEisBHvmIbJxL4DXnne3LeQjC0zyKxeyTKumruG/NSABDZdzQhUfY6L64TnGqlscYmLWGJ5w0EK
1943 A2T2+zPYWHqb6h0XLIystns4O1EPHfJ9zN0NjjEyXJzc2XsG3fut5nTHtesd2mYN19m7lWAZzKV5
1944 pCN1rIzf6ou8+LJZjuSjf+nwD8i7W4Lpp6NbdcberUXDeeYqhO7NTXh1ABnnvgsZOxzQvXqxtQG2
1945 4/v6wjJKx8Pc0thSUfvkvQqnGW3URJAwc/SeCJJfHfDICJIH/4ERJH19JhgajY/WA731AveEmlg9
1946 uHdRNowAfSZAJDzJbt1kaEzl0M2+L3KV3A3szdKsK52SPmMekCO7l5QRCL5zUrmpyt6dcLsiSL50
1947 0ePvzz++OTknWkwuTt7+58n3lJ2FxyUtW/XgEFuW7zO19708cDfcpjNq+gZvsO25KpaLmTSEzvtO
1948 MkIPhP7Ctb4FbSsy9/W2Dp0CoG4nQHz3tFtQt6nsXsgdv0wXm7h5NK2E7UA/5exa88tJUTCPzEkd
1949 i0NzEmfeN4cnWkY7seVtC+fkuXbVifZX9XWgW+LeI5ttTSuAZybIX/bIxJTO2MA8Oyjt/98HpYhj
1950 2aG5SgekcCadKx3pNkcGVfn/Y5ESlF2Mezt2FMf2km5qx8dDyt4+j2e/MxkZgnh1f4Pu/Fxhn8t0
1951 CxWCgBWevrCQETH6Tx+o2vSDJ0pc7lOF8T4qmyv7C9dMO7d/TTDJoLIXfynOVOJjVmi8qFM3ccD2
1952 6XQgp49Oo/KFU9ICmu8A6NyIpwL2Rn+JFeJ0I0LYOGqXDLNkiY761j4HebSbDvaGVs/F/rb6U7f+
1953 UogX2xvOWyWeusch91D39FC1qfJzLDCma24rLBWvCTIfZwq66ctzPvAMXW/74evt5Ysje7iA/I6v
1954 HUVCaWUDx7BfOmmZO2+XdLoTs5RjytvDvZoTEtYtrhyo7BNs29t0alO27H9MngNDGnjv+0Nmpod3
1955 B/+gjallvSOYkhg+USOallPNo3G3T0bd6TZqqwuEK5MeAKSjAgEWgunoRidTdMPp3sPnejc4rele
1956 XveEKXSkgrLGfI7gHsb3a/Brd6eK4gd1ZxRNf27Q5kC95CDc7Dtwq5EXCtluEtpTb/hgiwvAxdn9
1957 /V88oH83n9F2P9zlV9tWL3sLAtmXxRRYzAxqkcg8jsDIgN4ckrbGugkj6HgfTUNHl6GauSFfoONH
1958 abV46zZtMMiZnWgPwBqF4P8ACHXrHw==
1959 """)
1961 ##file activate.sh
1962 ACTIVATE_SH = convert("""
1963 eJytVVFvokAQfudXTLEPtTlLeo9tvMSmJpq02hSvl7u2wRUG2QR2DSxSe7n/frOACEVNLlceRHa+
1964 nfl25pvZDswCnoDPQ4QoTRQsENIEPci4CsBMZBq7CAsuLOYqvmYKTTj3YxnBgiXBudGBjUzBZUJI
1965 BXEqgCvweIyuCjeG4eF2F5x14bcB9KQiQQWrjSddI1/oQIx6SYYeoFjzWIoIhYI1izlbhJjkKO7D
1966 M/QEmKfO9O7WeRo/zr4P7pyHwWxkwitcgwpQ5Ej96OX+PmiFwLeVjFUOrNYKaq1Nud3nR2n8nI2m
1967 k9H0friPTGVsUdptaxGrTEfpNVFEskxpXtUkkCkl1UNF9cgLBkx48J4EXyALuBtAwNYIjF5kcmUU
1968 abMKmMq1ULoiRbgsDEkTSsKSGFCJ6Z8vY/2xYiSacmtyAfCDdCNTVZoVF8vSTQOoEwSnOrngBkws
1969 MYGMBMg8/bMBLSYKS7pYEXP0PqT+ZmBT0Xuy+Pplj5yn4aM9nk72JD8/Wi+Gr98sD9eWSMOwkapD
1970 BbUv91XSvmyVkICt2tmXR4tWmrcUCsjWOpw87YidEC8i0gdTSOFhouJUNxR+4NYBG0MftoCTD9F7
1971 2rTtxG3oPwY1b2HncYwhrlmj6Wq924xtGDWqfdNxap+OYxplEurnMVo9RWks+rH8qKEtx7kZT5zJ
1972 4H7oOFclrN6uFe+d+nW2aIUsSgs/42EIPuOhXq+jEo3S6tX6w2ilNkDnIpHCWdEQhFgwj9pkk7FN
1973 l/y5eQvRSIQ5+TrL05lewxWpt/Lbhes5cJF3mLET1MGhcKCF+40tNWnUulxrpojwDo2sObdje3Bz
1974 N3QeHqf3D7OjEXMVV8LN3ZlvuzoWHqiUcNKHtwNd0IbvPGKYYM31nPKCgkUILw3KL+Y8l7aO1ArS
1975 Ad37nIU0fCj5NE5gQCuC5sOSu+UdI2NeXg/lFkQIlFpdWVaWZRfvqGiirC9o6liJ9FXGYrSY9mI1
1976 D/Ncozgn13vJvsznr7DnkJWXsyMH7e42ljdJ+aqNDF1bFnKWFLdj31xtaJYK6EXFgqmV/ymD/ROG
1977 +n8O9H8f5vsGOWXsL1+1k3g=
1978 """)
1980 ##file activate.fish
1981 ACTIVATE_FISH = convert("""
1982 eJyVVWFv2jAQ/c6vuBoqQVWC9nVSNVGVCaS2VC2rNLWVZZILWAs2s52wVvvxsyEJDrjbmgpK7PP5
1983 3bt3d22YLbmGlGcIq1wbmCPkGhPYcLMEEsGciwGLDS+YwSjlekngLFVyBe73GXSXxqw/DwbuTS8x
1984 yyKpFr1WG15lDjETQhpQuQBuIOEKY5O9tlppLqxHKSDByjVAPwEy+mXtCq5MzjIUBTCRgEKTKwFG
1985 gpBqxTLYXgN2myspVigMaYF92tZSowGZJf4mFExxNs9Qb614CgZtmH0BpEOn11f0cXI/+za8pnfD
1986 2ZjA1sg9zlV/8QvcMhxbNu0QwgYokn/d+n02nt6Opzcjcnx1vXcIoN74O4ymWQXmHURfJw9jenc/
1987 vbmb0enj6P5+cuVhqlKm3S0u2XRtRbA2QQAhV7VhBF0rsgUX9Ur1rBUXJgVSy8O751k8mzY5OrKH
1988 RW3eaQhYGTr8hrXO59ALhxQ83mCsDLAid3T72CCSdJhaFE+fXgicXAARUiR2WeVO37gH3oYHzFKo
1989 9k7CaPZ1UeNwH1tWuXA4uFKYYcEa8vaKqXl7q1UpygMPhFLvlVKyNzsSM3S2km7UBOl4xweUXk5u
1990 6e3wZmQ9leY1XE/Ili670tr9g/5POBBpGIJXCCF79L1siarl/dbESa8mD8PL61GpzqpzuMS7tqeB
1991 1YkALrRBloBMbR9yLcVx7frQAgUqR7NZIuzkEu110gbNit1enNs82Rx5utq7Z3prU78HFRgulqNC
1992 OTwbqJa9vkJFclQgZSjbKeBgSsUtCtt9D8OwAbIVJuewQdfvQRaoFE9wd1TmCuRG7OgJ1bVXGHc7
1993 z5WDL/WW36v2oi37CyVBak61+yPBA9C1qqGxzKQqZ0oPuocU9hpud0PIp8sDHkXR1HKkNlzjuUWA
1994 a0enFUyzOWZA4yXGP+ZMI3Tdt2OuqU/SO4q64526cPE0A7ZyW2PMbWZiZ5HamIZ2RcCKLXhcDl2b
1995 vXL+eccQoRzem80mekPDEiyiWK4GWqZmwxQOmPM0eIfgp1P9cqrBsewR2p/DPMtt+pfcYM+Ls2uh
1996 hALufTAdmGl8B1H3VPd2af8fQAc4PgqjlIBL9cGQqNpXaAwe3LrtVn8AkZTUxg==
1997 """)
1999 ##file activate.csh
2000 ACTIVATE_CSH = convert("""
2001 eJx9VG1P2zAQ/u5fcYQKNgTNPtN1WxlIQ4KCUEGaxuQ6yYVYSuzKdhqVX7+zk3bpy5YPUXL3PPfc
2002 ne98DLNCWshliVDV1kGCUFvMoJGugMjq2qQIiVSxSJ1cCofD1BYRnOVGV0CfZ0N2DD91DalQSjsw
2003 tQLpIJMGU1euvPe7QeJlkKzgWixlhnAt4aoUVsLnLBiy5NtbJWQ5THX1ZciYKKWwkOFaE04dUm6D
2004 r/zh7pq/3D7Nnid3/HEy+wFHY/gEJydg0aFaQrBFgz1c5DG1IhTs+UZgsBC2GMFBlaeH+8dZXwcW
2005 VPvCjXdlAvCfQsE7al0+07XjZvrSCUevR5dnkVeKlFYZmUztG4BdzL2u9KyLVabTU0bdfg7a0hgs
2006 cSmUg6UwUiQl2iHrcbcVGNvPCiLOe7+cRwG13z9qRGgx2z6DHjfm/Op2yqeT+xvOLzs0PTKHDz2V
2007 tkckFHoQfQRXoGJAj9el0FyJCmEMhzgMS4sB7KPOE2ExoLcSieYwDvR+cP8cg11gKkVJc2wRcm1g
2008 QhYFlXiTaTfO2ki0fQoiFM4tLuO4aZrhOzqR4dIPcWx17hphMBY+Srwh7RTyN83XOWkcSPh1Pg/k
2009 TXX/jbJTbMtUmcxZ+/bbqOsy82suFQg/BhdSOTRhMNBHlUarCpU7JzBhmkKmRejKOQzayQe6MWoa
2010 n1wqWmuh6LZAaHxcdeqIlVLhIBJdO9/kbl0It2oEXQj+eGjJOuvOIR/YGRqvFhttUB2XTvLXYN2H
2011 37CBdbW2W7j2r2+VsCn0doVWcFG1/4y1VwBjfwAyoZhD
2012 """)
2014 ##file activate.bat
2015 ACTIVATE_BAT = convert("""
2016 eJx9UdEKgjAUfW6wfxjiIH+hEDKUFHSKLCMI7kNOEkIf9P9pTJ3OLJ/03HPPPed4Es9XS9qqwqgT
2017 PbGKKOdXL4aAFS7A4gvAwgijuiKlqOpGlATS2NeMLE+TjJM9RkQ+SmqAXLrBo1LLIeLdiWlD6jZt
2018 r7VNubWkndkXaxg5GO3UaOOKS6drO3luDDiO5my3iA0YAKGzPRV1ack8cOdhysI0CYzIPzjSiH5X
2019 0QcvC8Lfaj0emsVKYF2rhL5L3fCkVjV76kShi59NHwDniAHzkgDgqBcwOgTMx+gDQQqXCw==
2020 """)
2022 ##file deactivate.bat
2023 DEACTIVATE_BAT = convert("""
2024 eJxzSE3OyFfIT0vj4ipOLVEI8wwKCXX0iXf1C7Pl4spMU0hJTcvMS01RiPf3cYmHyQYE+fsGhCho
2025 cCkAAUibEkTEVhWLMlUlLk6QGixStlyaeCyJDPHw9/Pw93VFsQguim4ZXAJoIUw5DhX47XUM8UCx
2026 EchHtwsohN1bILUgw61c/Vy4AJYPYm4=
2027 """)
2029 ##file activate.ps1
2030 ACTIVATE_PS = convert("""
2031 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
2117 QastYw==
2118 """)
2120 ##file distutils-init.py
2121 DISTUTILS_INIT = convert("""
2122 eJytV1uL4zYUfvevOE0ottuMW9q3gVDa3aUMXXbLMlDKMBiNrSTqOJKRlMxkf33PkXyRbGe7Dw2E
2123 UXTu37lpxLFV2oIyifAncxmOL0xLIfcG+gv80x9VW6maw7o/CANSWWBwFtqeWMPlGY6qPjV8A0bB
2124 C4eKSTgZ5LRgFeyErMEeOBhbN+Ipgeizhjtnhkn7DdyjuNLPoCS0l/ayQTG0djwZC08cLXozeMss
2125 aG5EzQ0IScpnWtHSTXuxByV/QCmxE7y+eS0uxWeoheaVVfqSJHiU7Mhhi6gULbOHorshkrEnKxpT
2126 0n3A8Y8SMpuwZx6aoix3ouFlmW8gHRSkeSJ2g7hU+kiHLDaQw3bmRDaTGfTnty7gPm0FHbIBg9U9
2127 oh1kZzAFLaue2R6htPCtAda2nGlDSUJ4PZBgCJBGVcwKTAMz/vJiLD+Oin5Z5QlvDPdulC6EsiyE
2128 NFzb7McNTKJzbJqzphx92VKRFY1idenzmq3K0emRcbWBD0ryqc4NZGmKOOOX9Pz5x+/l27tP797c
2129 f/z0d+4NruGNai8uAM0bfsYaw8itFk8ny41jsfpyO+BWlpqfhcG4yxLdi/0tQqoT4a8Vby382mt8
2130 p7XSo7aWGdPBc+b6utaBmCQ7rQKQoWtAuthQCiold2KfJIPTT8xwg9blPumc+YDZC/wYGdAyHpJk
2131 vUbHbHWAp5No6pK/WhhLEWrFjUwtPEv1Agf8YmnsuXUQYkeZoHm8ogP16gt2uHoxcEMdf2C6pmbw
2132 hUMsWGhanboh4IzzmsIpWs134jVPqD/c74bZHdY69UKKSn/+KfVhxLgUlToemayLMYQOqfEC61bh
2133 cbhwaqoGUzIyZRFHPmau5juaWqwRn3mpWmoEA5nhzS5gog/5jbcFQqOZvmBasZtwYlG93k5GEiyw
2134 buHhMWLjDarEGpMGB2LFs5nIJkhp/nUmZneFaRth++lieJtHepIvKgx6PJqIlD9X2j6pG1i9x3pZ
2135 5bHuCPFiirGHeO7McvoXkz786GaKVzC9DSpnOxJdc4xm6NSVq7lNEnKdVlnpu9BNYoKX2Iq3wvgh
2136 gGEUM66kK6j4NiyoneuPLSwaCWDxczgaolEWpiMyDVDb7dNuLAbriL8ig8mmeju31oNvQdpnvEPC
2137 1vAXbWacGRVrGt/uXN/gU0CDDwgooKRrHfTBb1/s9lYZ8ZqOBU0yLvpuP6+K9hLFsvIjeNhBi0KL
2138 MlOuWRn3FRwx5oHXjl0YImUx0+gLzjGchrgzca026ETmYJzPD+IpuKzNi8AFn048Thd63OdD86M6
2139 84zE8yQm0VqXdbbgvub2pKVnS76icBGdeTHHXTKspUmr4NYo/furFLKiMdQzFjHJNcdAnMhltBJK
2140 0/IKX3DVFqvPJ2dLE7bDBkH0l/PJ29074+F0CsGYOxsb7U3myTUncYfXqnLLfa6sJybX4g+hmcjO
2141 kMRBfA1JellfRRKJcyRpxdS4rIl6FdmQCWjo/o9Qz7yKffoP4JHjOvABcRn4CZIT2RH4jnxmfpVG
2142 qgLaAvQBNfuO6X0/Ux02nb4FKx3vgP+XnkX0QW9pLy/NsXgdN24dD3LxO2Nwil7Zlc1dqtP3d7/h
2143 kzp1/+7hGBuY4pk0XD/0Ao/oTe/XGrfyM773aB7iUhgkpy+dwAMalxMP0DrBcsVw/6p25+/hobP9
2144 GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ=
2145 """)
2147 ##file distutils.cfg
2148 DISTUTILS_CFG = convert("""
2149 eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
2150 xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
2151 9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
2152 """)
2154 ##file activate_this.py
2155 ACTIVATE_THIS = convert("""
2156 eJyNU01v2zAMvetXEB4K21jmDOstQA4dMGCHbeihlyEIDMWmG62yJEiKE//7kXKdpN2KzYBt8euR
2157 fKSyLPs8wiEo8wh4wqZTGou4V6Hm0wJa1cSiTkJdr8+GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe
2158 5a3p0cRKiAe2NtLADikftnDco0ko/SFEVgEZ8aRC5GLux7i3BpSJ6J1H+i7A2CjiHq9z7JRZuuQq
2159 siwTIvpxJYCeuWaBpwZdhB+yxy/eWz+ZvVSU8C4E9FFZkyxFsvCT/ZzL8gcz9aXVE14Yyp2M+2W0
2160 y7n5mp0qN+avKXvbsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCZN9UzlJr+/e/iab8WfqsmPI6pWeUPd
2161 FrMsd4H/55poeO9n54COhUs+sZNEzNtg/wanpjpuqHJaxs76HtZryI/K3H7KJ/KDIhqcbJ7kI4ar
2162 XL+sMgXnX0D+Te2Iy5xdP8yueSlQB/x/ED2BTAtyE3K4SYUN6AMNfbO63f4lBW3bUJPbTL+mjSxS
2163 PyRfJkZRgj+VbFv+EzHFi5pKwUEepa4JslMnwkowSRCXI+m5XvEOvtuBrxHdhLalG0JofYBok6qj
2164 YdN2dEngUlbC4PG60M1WEN0piu7Nq7on0mgyyUw3iV1etLo6r/81biWdQ9MWHFaePWZYaq+nmp+t
2165 s3az+sj7eA0jfgPfeoN1
2166 """)
2168 MH_MAGIC = 0xfeedface
2169 MH_CIGAM = 0xcefaedfe
2170 MH_MAGIC_64 = 0xfeedfacf
2171 MH_CIGAM_64 = 0xcffaedfe
2172 FAT_MAGIC = 0xcafebabe
2173 BIG_ENDIAN = '>'
2174 LITTLE_ENDIAN = '<'
2175 LC_LOAD_DYLIB = 0xc
2176 maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint')
2179 class fileview(object):
2181 A proxy for file-like objects that exposes a given view of a file.
2182 Modified from macholib.
2185 def __init__(self, fileobj, start=0, size=maxint):
2186 if isinstance(fileobj, fileview):
2187 self._fileobj = fileobj._fileobj
2188 else:
2189 self._fileobj = fileobj
2190 self._start = start
2191 self._end = start + size
2192 self._pos = 0
2194 def __repr__(self):
2195 return '<fileview [%d, %d] %r>' % (
2196 self._start, self._end, self._fileobj)
2198 def tell(self):
2199 return self._pos
2201 def _checkwindow(self, seekto, op):
2202 if not (self._start <= seekto <= self._end):
2203 raise IOError("%s to offset %d is outside window [%d, %d]" % (
2204 op, seekto, self._start, self._end))
2206 def seek(self, offset, whence=0):
2207 seekto = offset
2208 if whence == os.SEEK_SET:
2209 seekto += self._start
2210 elif whence == os.SEEK_CUR:
2211 seekto += self._start + self._pos
2212 elif whence == os.SEEK_END:
2213 seekto += self._end
2214 else:
2215 raise IOError("Invalid whence argument to seek: %r" % (whence,))
2216 self._checkwindow(seekto, 'seek')
2217 self._fileobj.seek(seekto)
2218 self._pos = seekto - self._start
2220 def write(self, bytes):
2221 here = self._start + self._pos
2222 self._checkwindow(here, 'write')
2223 self._checkwindow(here + len(bytes), 'write')
2224 self._fileobj.seek(here, os.SEEK_SET)
2225 self._fileobj.write(bytes)
2226 self._pos += len(bytes)
2228 def read(self, size=maxint):
2229 assert size >= 0
2230 here = self._start + self._pos
2231 self._checkwindow(here, 'read')
2232 size = min(size, self._end - here)
2233 self._fileobj.seek(here, os.SEEK_SET)
2234 bytes = self._fileobj.read(size)
2235 self._pos += len(bytes)
2236 return bytes
2239 def read_data(file, endian, num=1):
2241 Read a given number of 32-bits unsigned integers from the given file
2242 with the given endianness.
2244 res = struct.unpack(endian + 'L' * num, file.read(num * 4))
2245 if len(res) == 1:
2246 return res[0]
2247 return res
2250 def mach_o_change(path, what, value):
2252 Replace a given name (what) in any LC_LOAD_DYLIB command found in
2253 the given binary with a new name (value), provided it's shorter.
2256 def do_macho(file, bits, endian):
2257 # Read Mach-O header (the magic number is assumed read by the caller)
2258 cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6)
2259 # 64-bits header has one more field.
2260 if bits == 64:
2261 read_data(file, endian)
2262 # The header is followed by ncmds commands
2263 for n in range(ncmds):
2264 where = file.tell()
2265 # Read command header
2266 cmd, cmdsize = read_data(file, endian, 2)
2267 if cmd == LC_LOAD_DYLIB:
2268 # The first data field in LC_LOAD_DYLIB commands is the
2269 # offset of the name, starting from the beginning of the
2270 # command.
2271 name_offset = read_data(file, endian)
2272 file.seek(where + name_offset, os.SEEK_SET)
2273 # Read the NUL terminated string
2274 load = file.read(cmdsize - name_offset).decode()
2275 load = load[:load.index('\0')]
2276 # If the string is what is being replaced, overwrite it.
2277 if load == what:
2278 file.seek(where + name_offset, os.SEEK_SET)
2279 file.write(value.encode() + '\0'.encode())
2280 # Seek to the next command
2281 file.seek(where + cmdsize, os.SEEK_SET)
2283 def do_file(file, offset=0, size=maxint):
2284 file = fileview(file, offset, size)
2285 # Read magic number
2286 magic = read_data(file, BIG_ENDIAN)
2287 if magic == FAT_MAGIC:
2288 # Fat binaries contain nfat_arch Mach-O binaries
2289 nfat_arch = read_data(file, BIG_ENDIAN)
2290 for n in range(nfat_arch):
2291 # Read arch header
2292 cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5)
2293 do_file(file, offset, size)
2294 elif magic == MH_MAGIC:
2295 do_macho(file, 32, BIG_ENDIAN)
2296 elif magic == MH_CIGAM:
2297 do_macho(file, 32, LITTLE_ENDIAN)
2298 elif magic == MH_MAGIC_64:
2299 do_macho(file, 64, BIG_ENDIAN)
2300 elif magic == MH_CIGAM_64:
2301 do_macho(file, 64, LITTLE_ENDIAN)
2303 assert(len(what) >= len(value))
2304 do_file(open(path, 'r+b'))
2307 if __name__ == '__main__':
2308 main()
2310 ## TODO:
2311 ## Copy python.exe.manifest
2312 ## Monkeypatch distutils.sysconfig