1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/python/virtualenv/virtualenv.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2342 @@ 1.4 +#!/usr/bin/env python 1.5 +"""Create a "virtual" Python installation 1.6 +""" 1.7 + 1.8 +__version__ = "1.11.4" 1.9 +virtualenv_version = __version__ # legacy 1.10 + 1.11 +import base64 1.12 +import sys 1.13 +import os 1.14 +import codecs 1.15 +import optparse 1.16 +import re 1.17 +import shutil 1.18 +import logging 1.19 +import tempfile 1.20 +import zlib 1.21 +import errno 1.22 +import glob 1.23 +import distutils.sysconfig 1.24 +from distutils.util import strtobool 1.25 +import struct 1.26 +import subprocess 1.27 +import tarfile 1.28 + 1.29 +if sys.version_info < (2, 6): 1.30 + print('ERROR: %s' % sys.exc_info()[1]) 1.31 + print('ERROR: this script requires Python 2.6 or greater.') 1.32 + sys.exit(101) 1.33 + 1.34 +try: 1.35 + set 1.36 +except NameError: 1.37 + from sets import Set as set 1.38 +try: 1.39 + basestring 1.40 +except NameError: 1.41 + basestring = str 1.42 + 1.43 +try: 1.44 + import ConfigParser 1.45 +except ImportError: 1.46 + import configparser as ConfigParser 1.47 + 1.48 +join = os.path.join 1.49 +py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1]) 1.50 + 1.51 +is_jython = sys.platform.startswith('java') 1.52 +is_pypy = hasattr(sys, 'pypy_version_info') 1.53 +is_win = (sys.platform == 'win32') 1.54 +is_cygwin = (sys.platform == 'cygwin') 1.55 +is_darwin = (sys.platform == 'darwin') 1.56 +abiflags = getattr(sys, 'abiflags', '') 1.57 + 1.58 +user_dir = os.path.expanduser('~') 1.59 +if is_win: 1.60 + default_storage_dir = os.path.join(user_dir, 'virtualenv') 1.61 +else: 1.62 + default_storage_dir = os.path.join(user_dir, '.virtualenv') 1.63 +default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini') 1.64 + 1.65 +if is_pypy: 1.66 + expected_exe = 'pypy' 1.67 +elif is_jython: 1.68 + expected_exe = 'jython' 1.69 +else: 1.70 + expected_exe = 'python' 1.71 + 1.72 +# Return a mapping of version -> Python executable 1.73 +# Only provided for Windows, where the information in the registry is used 1.74 +if not is_win: 1.75 + def get_installed_pythons(): 1.76 + return {} 1.77 +else: 1.78 + try: 1.79 + import winreg 1.80 + except ImportError: 1.81 + import _winreg as winreg 1.82 + 1.83 + def get_installed_pythons(): 1.84 + python_core = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, 1.85 + "Software\\Python\\PythonCore") 1.86 + i = 0 1.87 + versions = [] 1.88 + while True: 1.89 + try: 1.90 + versions.append(winreg.EnumKey(python_core, i)) 1.91 + i = i + 1 1.92 + except WindowsError: 1.93 + break 1.94 + exes = dict() 1.95 + for ver in versions: 1.96 + path = winreg.QueryValue(python_core, "%s\\InstallPath" % ver) 1.97 + exes[ver] = join(path, "python.exe") 1.98 + 1.99 + winreg.CloseKey(python_core) 1.100 + 1.101 + # Add the major versions 1.102 + # Sort the keys, then repeatedly update the major version entry 1.103 + # Last executable (i.e., highest version) wins with this approach 1.104 + for ver in sorted(exes): 1.105 + exes[ver[0]] = exes[ver] 1.106 + 1.107 + return exes 1.108 + 1.109 +REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath', 1.110 + 'fnmatch', 'locale', 'encodings', 'codecs', 1.111 + 'stat', 'UserDict', 'readline', 'copy_reg', 'types', 1.112 + 're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile', 1.113 + 'zlib'] 1.114 + 1.115 +REQUIRED_FILES = ['lib-dynload', 'config'] 1.116 + 1.117 +majver, minver = sys.version_info[:2] 1.118 +if majver == 2: 1.119 + if minver >= 6: 1.120 + REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc']) 1.121 + if minver >= 7: 1.122 + REQUIRED_MODULES.extend(['_weakrefset']) 1.123 + if minver <= 3: 1.124 + REQUIRED_MODULES.extend(['sets', '__future__']) 1.125 +elif majver == 3: 1.126 + # Some extra modules are needed for Python 3, but different ones 1.127 + # for different versions. 1.128 + REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io', 1.129 + '_weakrefset', 'copyreg', 'tempfile', 'random', 1.130 + '__future__', 'collections', 'keyword', 'tarfile', 1.131 + 'shutil', 'struct', 'copy', 'tokenize', 'token', 1.132 + 'functools', 'heapq', 'bisect', 'weakref', 1.133 + 'reprlib']) 1.134 + if minver >= 2: 1.135 + REQUIRED_FILES[-1] = 'config-%s' % majver 1.136 + if minver >= 3: 1.137 + import sysconfig 1.138 + platdir = sysconfig.get_config_var('PLATDIR') 1.139 + REQUIRED_FILES.append(platdir) 1.140 + # The whole list of 3.3 modules is reproduced below - the current 1.141 + # uncommented ones are required for 3.3 as of now, but more may be 1.142 + # added as 3.3 development continues. 1.143 + REQUIRED_MODULES.extend([ 1.144 + #"aifc", 1.145 + #"antigravity", 1.146 + #"argparse", 1.147 + #"ast", 1.148 + #"asynchat", 1.149 + #"asyncore", 1.150 + "base64", 1.151 + #"bdb", 1.152 + #"binhex", 1.153 + #"bisect", 1.154 + #"calendar", 1.155 + #"cgi", 1.156 + #"cgitb", 1.157 + #"chunk", 1.158 + #"cmd", 1.159 + #"codeop", 1.160 + #"code", 1.161 + #"colorsys", 1.162 + #"_compat_pickle", 1.163 + #"compileall", 1.164 + #"concurrent", 1.165 + #"configparser", 1.166 + #"contextlib", 1.167 + #"cProfile", 1.168 + #"crypt", 1.169 + #"csv", 1.170 + #"ctypes", 1.171 + #"curses", 1.172 + #"datetime", 1.173 + #"dbm", 1.174 + #"decimal", 1.175 + #"difflib", 1.176 + #"dis", 1.177 + #"doctest", 1.178 + #"dummy_threading", 1.179 + "_dummy_thread", 1.180 + #"email", 1.181 + #"filecmp", 1.182 + #"fileinput", 1.183 + #"formatter", 1.184 + #"fractions", 1.185 + #"ftplib", 1.186 + #"functools", 1.187 + #"getopt", 1.188 + #"getpass", 1.189 + #"gettext", 1.190 + #"glob", 1.191 + #"gzip", 1.192 + "hashlib", 1.193 + #"heapq", 1.194 + "hmac", 1.195 + #"html", 1.196 + #"http", 1.197 + #"idlelib", 1.198 + #"imaplib", 1.199 + #"imghdr", 1.200 + "imp", 1.201 + "importlib", 1.202 + #"inspect", 1.203 + #"json", 1.204 + #"lib2to3", 1.205 + #"logging", 1.206 + #"macpath", 1.207 + #"macurl2path", 1.208 + #"mailbox", 1.209 + #"mailcap", 1.210 + #"_markupbase", 1.211 + #"mimetypes", 1.212 + #"modulefinder", 1.213 + #"multiprocessing", 1.214 + #"netrc", 1.215 + #"nntplib", 1.216 + #"nturl2path", 1.217 + #"numbers", 1.218 + #"opcode", 1.219 + #"optparse", 1.220 + #"os2emxpath", 1.221 + #"pdb", 1.222 + #"pickle", 1.223 + #"pickletools", 1.224 + #"pipes", 1.225 + #"pkgutil", 1.226 + #"platform", 1.227 + #"plat-linux2", 1.228 + #"plistlib", 1.229 + #"poplib", 1.230 + #"pprint", 1.231 + #"profile", 1.232 + #"pstats", 1.233 + #"pty", 1.234 + #"pyclbr", 1.235 + #"py_compile", 1.236 + #"pydoc_data", 1.237 + #"pydoc", 1.238 + #"_pyio", 1.239 + #"queue", 1.240 + #"quopri", 1.241 + #"reprlib", 1.242 + "rlcompleter", 1.243 + #"runpy", 1.244 + #"sched", 1.245 + #"shelve", 1.246 + #"shlex", 1.247 + #"smtpd", 1.248 + #"smtplib", 1.249 + #"sndhdr", 1.250 + #"socket", 1.251 + #"socketserver", 1.252 + #"sqlite3", 1.253 + #"ssl", 1.254 + #"stringprep", 1.255 + #"string", 1.256 + #"_strptime", 1.257 + #"subprocess", 1.258 + #"sunau", 1.259 + #"symbol", 1.260 + #"symtable", 1.261 + #"sysconfig", 1.262 + #"tabnanny", 1.263 + #"telnetlib", 1.264 + #"test", 1.265 + #"textwrap", 1.266 + #"this", 1.267 + #"_threading_local", 1.268 + #"threading", 1.269 + #"timeit", 1.270 + #"tkinter", 1.271 + #"tokenize", 1.272 + #"token", 1.273 + #"traceback", 1.274 + #"trace", 1.275 + #"tty", 1.276 + #"turtledemo", 1.277 + #"turtle", 1.278 + #"unittest", 1.279 + #"urllib", 1.280 + #"uuid", 1.281 + #"uu", 1.282 + #"wave", 1.283 + #"weakref", 1.284 + #"webbrowser", 1.285 + #"wsgiref", 1.286 + #"xdrlib", 1.287 + #"xml", 1.288 + #"xmlrpc", 1.289 + #"zipfile", 1.290 + ]) 1.291 + if minver >= 4: 1.292 + REQUIRED_MODULES.extend([ 1.293 + 'operator', 1.294 + '_collections_abc', 1.295 + '_bootlocale', 1.296 + ]) 1.297 + 1.298 +if is_pypy: 1.299 + # these are needed to correctly display the exceptions that may happen 1.300 + # during the bootstrap 1.301 + REQUIRED_MODULES.extend(['traceback', 'linecache']) 1.302 + 1.303 +class Logger(object): 1.304 + 1.305 + """ 1.306 + Logging object for use in command-line script. Allows ranges of 1.307 + levels, to avoid some redundancy of displayed information. 1.308 + """ 1.309 + 1.310 + DEBUG = logging.DEBUG 1.311 + INFO = logging.INFO 1.312 + NOTIFY = (logging.INFO+logging.WARN)/2 1.313 + WARN = WARNING = logging.WARN 1.314 + ERROR = logging.ERROR 1.315 + FATAL = logging.FATAL 1.316 + 1.317 + LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] 1.318 + 1.319 + def __init__(self, consumers): 1.320 + self.consumers = consumers 1.321 + self.indent = 0 1.322 + self.in_progress = None 1.323 + self.in_progress_hanging = False 1.324 + 1.325 + def debug(self, msg, *args, **kw): 1.326 + self.log(self.DEBUG, msg, *args, **kw) 1.327 + def info(self, msg, *args, **kw): 1.328 + self.log(self.INFO, msg, *args, **kw) 1.329 + def notify(self, msg, *args, **kw): 1.330 + self.log(self.NOTIFY, msg, *args, **kw) 1.331 + def warn(self, msg, *args, **kw): 1.332 + self.log(self.WARN, msg, *args, **kw) 1.333 + def error(self, msg, *args, **kw): 1.334 + self.log(self.ERROR, msg, *args, **kw) 1.335 + def fatal(self, msg, *args, **kw): 1.336 + self.log(self.FATAL, msg, *args, **kw) 1.337 + def log(self, level, msg, *args, **kw): 1.338 + if args: 1.339 + if kw: 1.340 + raise TypeError( 1.341 + "You may give positional or keyword arguments, not both") 1.342 + args = args or kw 1.343 + rendered = None 1.344 + for consumer_level, consumer in self.consumers: 1.345 + if self.level_matches(level, consumer_level): 1.346 + if (self.in_progress_hanging 1.347 + and consumer in (sys.stdout, sys.stderr)): 1.348 + self.in_progress_hanging = False 1.349 + sys.stdout.write('\n') 1.350 + sys.stdout.flush() 1.351 + if rendered is None: 1.352 + if args: 1.353 + rendered = msg % args 1.354 + else: 1.355 + rendered = msg 1.356 + rendered = ' '*self.indent + rendered 1.357 + if hasattr(consumer, 'write'): 1.358 + consumer.write(rendered+'\n') 1.359 + else: 1.360 + consumer(rendered) 1.361 + 1.362 + def start_progress(self, msg): 1.363 + assert not self.in_progress, ( 1.364 + "Tried to start_progress(%r) while in_progress %r" 1.365 + % (msg, self.in_progress)) 1.366 + if self.level_matches(self.NOTIFY, self._stdout_level()): 1.367 + sys.stdout.write(msg) 1.368 + sys.stdout.flush() 1.369 + self.in_progress_hanging = True 1.370 + else: 1.371 + self.in_progress_hanging = False 1.372 + self.in_progress = msg 1.373 + 1.374 + def end_progress(self, msg='done.'): 1.375 + assert self.in_progress, ( 1.376 + "Tried to end_progress without start_progress") 1.377 + if self.stdout_level_matches(self.NOTIFY): 1.378 + if not self.in_progress_hanging: 1.379 + # Some message has been printed out since start_progress 1.380 + sys.stdout.write('...' + self.in_progress + msg + '\n') 1.381 + sys.stdout.flush() 1.382 + else: 1.383 + sys.stdout.write(msg + '\n') 1.384 + sys.stdout.flush() 1.385 + self.in_progress = None 1.386 + self.in_progress_hanging = False 1.387 + 1.388 + def show_progress(self): 1.389 + """If we are in a progress scope, and no log messages have been 1.390 + shown, write out another '.'""" 1.391 + if self.in_progress_hanging: 1.392 + sys.stdout.write('.') 1.393 + sys.stdout.flush() 1.394 + 1.395 + def stdout_level_matches(self, level): 1.396 + """Returns true if a message at this level will go to stdout""" 1.397 + return self.level_matches(level, self._stdout_level()) 1.398 + 1.399 + def _stdout_level(self): 1.400 + """Returns the level that stdout runs at""" 1.401 + for level, consumer in self.consumers: 1.402 + if consumer is sys.stdout: 1.403 + return level 1.404 + return self.FATAL 1.405 + 1.406 + def level_matches(self, level, consumer_level): 1.407 + """ 1.408 + >>> l = Logger([]) 1.409 + >>> l.level_matches(3, 4) 1.410 + False 1.411 + >>> l.level_matches(3, 2) 1.412 + True 1.413 + >>> l.level_matches(slice(None, 3), 3) 1.414 + False 1.415 + >>> l.level_matches(slice(None, 3), 2) 1.416 + True 1.417 + >>> l.level_matches(slice(1, 3), 1) 1.418 + True 1.419 + >>> l.level_matches(slice(2, 3), 1) 1.420 + False 1.421 + """ 1.422 + if isinstance(level, slice): 1.423 + start, stop = level.start, level.stop 1.424 + if start is not None and start > consumer_level: 1.425 + return False 1.426 + if stop is not None and stop <= consumer_level: 1.427 + return False 1.428 + return True 1.429 + else: 1.430 + return level >= consumer_level 1.431 + 1.432 + #@classmethod 1.433 + def level_for_integer(cls, level): 1.434 + levels = cls.LEVELS 1.435 + if level < 0: 1.436 + return levels[0] 1.437 + if level >= len(levels): 1.438 + return levels[-1] 1.439 + return levels[level] 1.440 + 1.441 + level_for_integer = classmethod(level_for_integer) 1.442 + 1.443 +# create a silent logger just to prevent this from being undefined 1.444 +# will be overridden with requested verbosity main() is called. 1.445 +logger = Logger([(Logger.LEVELS[-1], sys.stdout)]) 1.446 + 1.447 +def mkdir(path): 1.448 + if not os.path.exists(path): 1.449 + logger.info('Creating %s', path) 1.450 + os.makedirs(path) 1.451 + else: 1.452 + logger.info('Directory %s already exists', path) 1.453 + 1.454 +def copyfileordir(src, dest, symlink=True): 1.455 + if os.path.isdir(src): 1.456 + shutil.copytree(src, dest, symlink) 1.457 + else: 1.458 + shutil.copy2(src, dest) 1.459 + 1.460 +def copyfile(src, dest, symlink=True): 1.461 + if not os.path.exists(src): 1.462 + # Some bad symlink in the src 1.463 + logger.warn('Cannot find file %s (bad symlink)', src) 1.464 + return 1.465 + if os.path.exists(dest): 1.466 + logger.debug('File %s already exists', dest) 1.467 + return 1.468 + if not os.path.exists(os.path.dirname(dest)): 1.469 + logger.info('Creating parent directories for %s', os.path.dirname(dest)) 1.470 + os.makedirs(os.path.dirname(dest)) 1.471 + if not os.path.islink(src): 1.472 + srcpath = os.path.abspath(src) 1.473 + else: 1.474 + srcpath = os.readlink(src) 1.475 + if symlink and hasattr(os, 'symlink') and not is_win: 1.476 + logger.info('Symlinking %s', dest) 1.477 + try: 1.478 + os.symlink(srcpath, dest) 1.479 + except (OSError, NotImplementedError): 1.480 + logger.info('Symlinking failed, copying to %s', dest) 1.481 + copyfileordir(src, dest, symlink) 1.482 + else: 1.483 + logger.info('Copying to %s', dest) 1.484 + copyfileordir(src, dest, symlink) 1.485 + 1.486 +def writefile(dest, content, overwrite=True): 1.487 + if not os.path.exists(dest): 1.488 + logger.info('Writing %s', dest) 1.489 + f = open(dest, 'wb') 1.490 + f.write(content.encode('utf-8')) 1.491 + f.close() 1.492 + return 1.493 + else: 1.494 + f = open(dest, 'rb') 1.495 + c = f.read() 1.496 + f.close() 1.497 + if c != content.encode("utf-8"): 1.498 + if not overwrite: 1.499 + logger.notify('File %s exists with different content; not overwriting', dest) 1.500 + return 1.501 + logger.notify('Overwriting %s with new content', dest) 1.502 + f = open(dest, 'wb') 1.503 + f.write(content.encode('utf-8')) 1.504 + f.close() 1.505 + else: 1.506 + logger.info('Content %s already in place', dest) 1.507 + 1.508 +def rmtree(dir): 1.509 + if os.path.exists(dir): 1.510 + logger.notify('Deleting tree %s', dir) 1.511 + shutil.rmtree(dir) 1.512 + else: 1.513 + logger.info('Do not need to delete %s; already gone', dir) 1.514 + 1.515 +def make_exe(fn): 1.516 + if hasattr(os, 'chmod'): 1.517 + oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777 1.518 + newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777 1.519 + os.chmod(fn, newmode) 1.520 + logger.info('Changed mode of %s to %s', fn, oct(newmode)) 1.521 + 1.522 +def _find_file(filename, dirs): 1.523 + for dir in reversed(dirs): 1.524 + files = glob.glob(os.path.join(dir, filename)) 1.525 + if files and os.path.isfile(files[0]): 1.526 + return True, files[0] 1.527 + return False, filename 1.528 + 1.529 +def file_search_dirs(): 1.530 + here = os.path.dirname(os.path.abspath(__file__)) 1.531 + dirs = ['.', here, 1.532 + join(here, 'virtualenv_support')] 1.533 + if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv': 1.534 + # Probably some boot script; just in case virtualenv is installed... 1.535 + try: 1.536 + import virtualenv 1.537 + except ImportError: 1.538 + pass 1.539 + else: 1.540 + dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support')) 1.541 + return [d for d in dirs if os.path.isdir(d)] 1.542 + 1.543 + 1.544 +class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter): 1.545 + """ 1.546 + Custom help formatter for use in ConfigOptionParser that updates 1.547 + the defaults before expanding them, allowing them to show up correctly 1.548 + in the help listing 1.549 + """ 1.550 + def expand_default(self, option): 1.551 + if self.parser is not None: 1.552 + self.parser.update_defaults(self.parser.defaults) 1.553 + return optparse.IndentedHelpFormatter.expand_default(self, option) 1.554 + 1.555 + 1.556 +class ConfigOptionParser(optparse.OptionParser): 1.557 + """ 1.558 + Custom option parser which updates its defaults by checking the 1.559 + configuration files and environmental variables 1.560 + """ 1.561 + def __init__(self, *args, **kwargs): 1.562 + self.config = ConfigParser.RawConfigParser() 1.563 + self.files = self.get_config_files() 1.564 + self.config.read(self.files) 1.565 + optparse.OptionParser.__init__(self, *args, **kwargs) 1.566 + 1.567 + def get_config_files(self): 1.568 + config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False) 1.569 + if config_file and os.path.exists(config_file): 1.570 + return [config_file] 1.571 + return [default_config_file] 1.572 + 1.573 + def update_defaults(self, defaults): 1.574 + """ 1.575 + Updates the given defaults with values from the config files and 1.576 + the environ. Does a little special handling for certain types of 1.577 + options (lists). 1.578 + """ 1.579 + # Then go and look for the other sources of configuration: 1.580 + config = {} 1.581 + # 1. config files 1.582 + config.update(dict(self.get_config_section('virtualenv'))) 1.583 + # 2. environmental variables 1.584 + config.update(dict(self.get_environ_vars())) 1.585 + # Then set the options with those values 1.586 + for key, val in config.items(): 1.587 + key = key.replace('_', '-') 1.588 + if not key.startswith('--'): 1.589 + key = '--%s' % key # only prefer long opts 1.590 + option = self.get_option(key) 1.591 + if option is not None: 1.592 + # ignore empty values 1.593 + if not val: 1.594 + continue 1.595 + # handle multiline configs 1.596 + if option.action == 'append': 1.597 + val = val.split() 1.598 + else: 1.599 + option.nargs = 1 1.600 + if option.action == 'store_false': 1.601 + val = not strtobool(val) 1.602 + elif option.action in ('store_true', 'count'): 1.603 + val = strtobool(val) 1.604 + try: 1.605 + val = option.convert_value(key, val) 1.606 + except optparse.OptionValueError: 1.607 + e = sys.exc_info()[1] 1.608 + print("An error occured during configuration: %s" % e) 1.609 + sys.exit(3) 1.610 + defaults[option.dest] = val 1.611 + return defaults 1.612 + 1.613 + def get_config_section(self, name): 1.614 + """ 1.615 + Get a section of a configuration 1.616 + """ 1.617 + if self.config.has_section(name): 1.618 + return self.config.items(name) 1.619 + return [] 1.620 + 1.621 + def get_environ_vars(self, prefix='VIRTUALENV_'): 1.622 + """ 1.623 + Returns a generator with all environmental vars with prefix VIRTUALENV 1.624 + """ 1.625 + for key, val in os.environ.items(): 1.626 + if key.startswith(prefix): 1.627 + yield (key.replace(prefix, '').lower(), val) 1.628 + 1.629 + def get_default_values(self): 1.630 + """ 1.631 + Overridding to make updating the defaults after instantiation of 1.632 + the option parser possible, update_defaults() does the dirty work. 1.633 + """ 1.634 + if not self.process_default_values: 1.635 + # Old, pre-Optik 1.5 behaviour. 1.636 + return optparse.Values(self.defaults) 1.637 + 1.638 + defaults = self.update_defaults(self.defaults.copy()) # ours 1.639 + for option in self._get_all_options(): 1.640 + default = defaults.get(option.dest) 1.641 + if isinstance(default, basestring): 1.642 + opt_str = option.get_opt_string() 1.643 + defaults[option.dest] = option.check_value(opt_str, default) 1.644 + return optparse.Values(defaults) 1.645 + 1.646 + 1.647 +def main(): 1.648 + parser = ConfigOptionParser( 1.649 + version=virtualenv_version, 1.650 + usage="%prog [OPTIONS] DEST_DIR", 1.651 + formatter=UpdatingDefaultsHelpFormatter()) 1.652 + 1.653 + parser.add_option( 1.654 + '-v', '--verbose', 1.655 + action='count', 1.656 + dest='verbose', 1.657 + default=0, 1.658 + help="Increase verbosity.") 1.659 + 1.660 + parser.add_option( 1.661 + '-q', '--quiet', 1.662 + action='count', 1.663 + dest='quiet', 1.664 + default=0, 1.665 + help='Decrease verbosity.') 1.666 + 1.667 + parser.add_option( 1.668 + '-p', '--python', 1.669 + dest='python', 1.670 + metavar='PYTHON_EXE', 1.671 + help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 ' 1.672 + 'interpreter to create the new environment. The default is the interpreter that ' 1.673 + 'virtualenv was installed with (%s)' % sys.executable) 1.674 + 1.675 + parser.add_option( 1.676 + '--clear', 1.677 + dest='clear', 1.678 + action='store_true', 1.679 + help="Clear out the non-root install and start from scratch.") 1.680 + 1.681 + parser.set_defaults(system_site_packages=False) 1.682 + parser.add_option( 1.683 + '--no-site-packages', 1.684 + dest='system_site_packages', 1.685 + action='store_false', 1.686 + help="DEPRECATED. Retained only for backward compatibility. " 1.687 + "Not having access to global site-packages is now the default behavior.") 1.688 + 1.689 + parser.add_option( 1.690 + '--system-site-packages', 1.691 + dest='system_site_packages', 1.692 + action='store_true', 1.693 + help="Give the virtual environment access to the global site-packages.") 1.694 + 1.695 + parser.add_option( 1.696 + '--always-copy', 1.697 + dest='symlink', 1.698 + action='store_false', 1.699 + default=True, 1.700 + help="Always copy files rather than symlinking.") 1.701 + 1.702 + parser.add_option( 1.703 + '--unzip-setuptools', 1.704 + dest='unzip_setuptools', 1.705 + action='store_true', 1.706 + help="Unzip Setuptools when installing it.") 1.707 + 1.708 + parser.add_option( 1.709 + '--relocatable', 1.710 + dest='relocatable', 1.711 + action='store_true', 1.712 + help='Make an EXISTING virtualenv environment relocatable. ' 1.713 + 'This fixes up scripts and makes all .pth files relative.') 1.714 + 1.715 + parser.add_option( 1.716 + '--no-setuptools', 1.717 + dest='no_setuptools', 1.718 + action='store_true', 1.719 + help='Do not install setuptools (or pip) in the new virtualenv.') 1.720 + 1.721 + parser.add_option( 1.722 + '--no-pip', 1.723 + dest='no_pip', 1.724 + action='store_true', 1.725 + help='Do not install pip in the new virtualenv.') 1.726 + 1.727 + default_search_dirs = file_search_dirs() 1.728 + parser.add_option( 1.729 + '--extra-search-dir', 1.730 + dest="search_dirs", 1.731 + action="append", 1.732 + metavar='DIR', 1.733 + default=default_search_dirs, 1.734 + help="Directory to look for setuptools/pip distributions in. " 1.735 + "This option can be used multiple times.") 1.736 + 1.737 + parser.add_option( 1.738 + '--never-download', 1.739 + dest="never_download", 1.740 + action="store_true", 1.741 + default=True, 1.742 + help="DEPRECATED. Retained only for backward compatibility. This option has no effect. " 1.743 + "Virtualenv never downloads pip or setuptools.") 1.744 + 1.745 + parser.add_option( 1.746 + '--prompt', 1.747 + dest='prompt', 1.748 + help='Provides an alternative prompt prefix for this environment.') 1.749 + 1.750 + parser.add_option( 1.751 + '--setuptools', 1.752 + dest='setuptools', 1.753 + action='store_true', 1.754 + help="DEPRECATED. Retained only for backward compatibility. This option has no effect.") 1.755 + 1.756 + parser.add_option( 1.757 + '--distribute', 1.758 + dest='distribute', 1.759 + action='store_true', 1.760 + help="DEPRECATED. Retained only for backward compatibility. This option has no effect.") 1.761 + 1.762 + if 'extend_parser' in globals(): 1.763 + extend_parser(parser) 1.764 + 1.765 + options, args = parser.parse_args() 1.766 + 1.767 + global logger 1.768 + 1.769 + if 'adjust_options' in globals(): 1.770 + adjust_options(options, args) 1.771 + 1.772 + verbosity = options.verbose - options.quiet 1.773 + logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)]) 1.774 + 1.775 + if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): 1.776 + env = os.environ.copy() 1.777 + interpreter = resolve_interpreter(options.python) 1.778 + if interpreter == sys.executable: 1.779 + logger.warn('Already using interpreter %s' % interpreter) 1.780 + else: 1.781 + logger.notify('Running virtualenv with interpreter %s' % interpreter) 1.782 + env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true' 1.783 + file = __file__ 1.784 + if file.endswith('.pyc'): 1.785 + file = file[:-1] 1.786 + popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env) 1.787 + raise SystemExit(popen.wait()) 1.788 + 1.789 + if not args: 1.790 + print('You must provide a DEST_DIR') 1.791 + parser.print_help() 1.792 + sys.exit(2) 1.793 + if len(args) > 1: 1.794 + print('There must be only one argument: DEST_DIR (you gave %s)' % ( 1.795 + ' '.join(args))) 1.796 + parser.print_help() 1.797 + sys.exit(2) 1.798 + 1.799 + home_dir = args[0] 1.800 + 1.801 + if os.environ.get('WORKING_ENV'): 1.802 + logger.fatal('ERROR: you cannot run virtualenv while in a workingenv') 1.803 + logger.fatal('Please deactivate your workingenv, then re-run this script') 1.804 + sys.exit(3) 1.805 + 1.806 + if 'PYTHONHOME' in os.environ: 1.807 + logger.warn('PYTHONHOME is set. You *must* activate the virtualenv before using it') 1.808 + del os.environ['PYTHONHOME'] 1.809 + 1.810 + if options.relocatable: 1.811 + make_environment_relocatable(home_dir) 1.812 + return 1.813 + 1.814 + if not options.never_download: 1.815 + logger.warn('The --never-download option is for backward compatibility only.') 1.816 + logger.warn('Setting it to false is no longer supported, and will be ignored.') 1.817 + 1.818 + create_environment(home_dir, 1.819 + site_packages=options.system_site_packages, 1.820 + clear=options.clear, 1.821 + unzip_setuptools=options.unzip_setuptools, 1.822 + prompt=options.prompt, 1.823 + search_dirs=options.search_dirs, 1.824 + never_download=True, 1.825 + no_setuptools=options.no_setuptools, 1.826 + no_pip=options.no_pip, 1.827 + symlink=options.symlink) 1.828 + if 'after_install' in globals(): 1.829 + after_install(options, home_dir) 1.830 + 1.831 +def call_subprocess(cmd, show_stdout=True, 1.832 + filter_stdout=None, cwd=None, 1.833 + raise_on_returncode=True, extra_env=None, 1.834 + remove_from_env=None): 1.835 + cmd_parts = [] 1.836 + for part in cmd: 1.837 + if len(part) > 45: 1.838 + part = part[:20]+"..."+part[-20:] 1.839 + if ' ' in part or '\n' in part or '"' in part or "'" in part: 1.840 + part = '"%s"' % part.replace('"', '\\"') 1.841 + if hasattr(part, 'decode'): 1.842 + try: 1.843 + part = part.decode(sys.getdefaultencoding()) 1.844 + except UnicodeDecodeError: 1.845 + part = part.decode(sys.getfilesystemencoding()) 1.846 + cmd_parts.append(part) 1.847 + cmd_desc = ' '.join(cmd_parts) 1.848 + if show_stdout: 1.849 + stdout = None 1.850 + else: 1.851 + stdout = subprocess.PIPE 1.852 + logger.debug("Running command %s" % cmd_desc) 1.853 + if extra_env or remove_from_env: 1.854 + env = os.environ.copy() 1.855 + if extra_env: 1.856 + env.update(extra_env) 1.857 + if remove_from_env: 1.858 + for varname in remove_from_env: 1.859 + env.pop(varname, None) 1.860 + else: 1.861 + env = None 1.862 + try: 1.863 + proc = subprocess.Popen( 1.864 + cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout, 1.865 + cwd=cwd, env=env) 1.866 + except Exception: 1.867 + e = sys.exc_info()[1] 1.868 + logger.fatal( 1.869 + "Error %s while executing command %s" % (e, cmd_desc)) 1.870 + raise 1.871 + all_output = [] 1.872 + if stdout is not None: 1.873 + stdout = proc.stdout 1.874 + encoding = sys.getdefaultencoding() 1.875 + fs_encoding = sys.getfilesystemencoding() 1.876 + while 1: 1.877 + line = stdout.readline() 1.878 + try: 1.879 + line = line.decode(encoding) 1.880 + except UnicodeDecodeError: 1.881 + line = line.decode(fs_encoding) 1.882 + if not line: 1.883 + break 1.884 + line = line.rstrip() 1.885 + all_output.append(line) 1.886 + if filter_stdout: 1.887 + level = filter_stdout(line) 1.888 + if isinstance(level, tuple): 1.889 + level, line = level 1.890 + logger.log(level, line) 1.891 + if not logger.stdout_level_matches(level): 1.892 + logger.show_progress() 1.893 + else: 1.894 + logger.info(line) 1.895 + else: 1.896 + proc.communicate() 1.897 + proc.wait() 1.898 + if proc.returncode: 1.899 + if raise_on_returncode: 1.900 + if all_output: 1.901 + logger.notify('Complete output from command %s:' % cmd_desc) 1.902 + logger.notify('\n'.join(all_output) + '\n----------------------------------------') 1.903 + raise OSError( 1.904 + "Command %s failed with error code %s" 1.905 + % (cmd_desc, proc.returncode)) 1.906 + else: 1.907 + logger.warn( 1.908 + "Command %s had error code %s" 1.909 + % (cmd_desc, proc.returncode)) 1.910 + 1.911 +def filter_install_output(line): 1.912 + if line.strip().startswith('running'): 1.913 + return Logger.INFO 1.914 + return Logger.DEBUG 1.915 + 1.916 +def find_wheels(projects, search_dirs): 1.917 + """Find wheels from which we can import PROJECTS. 1.918 + 1.919 + Scan through SEARCH_DIRS for a wheel for each PROJECT in turn. Return 1.920 + a list of the first wheel found for each PROJECT 1.921 + """ 1.922 + 1.923 + wheels = [] 1.924 + 1.925 + # Look through SEARCH_DIRS for the first suitable wheel. Don't bother 1.926 + # about version checking here, as this is simply to get something we can 1.927 + # then use to install the correct version. 1.928 + for project in projects: 1.929 + for dirname in search_dirs: 1.930 + # This relies on only having "universal" wheels available. 1.931 + # The pattern could be tightened to require -py2.py3-none-any.whl. 1.932 + files = glob.glob(os.path.join(dirname, project + '-*.whl')) 1.933 + if files: 1.934 + wheels.append(os.path.abspath(files[0])) 1.935 + break 1.936 + else: 1.937 + # We're out of luck, so quit with a suitable error 1.938 + logger.fatal('Cannot find a wheel for %s' % (project,)) 1.939 + 1.940 + return wheels 1.941 + 1.942 +def install_wheel(project_names, py_executable, search_dirs=None): 1.943 + if search_dirs is None: 1.944 + search_dirs = file_search_dirs() 1.945 + 1.946 + wheels = find_wheels(['setuptools', 'pip'], search_dirs) 1.947 + pythonpath = os.pathsep.join(wheels) 1.948 + findlinks = ' '.join(search_dirs) 1.949 + 1.950 + cmd = [ 1.951 + py_executable, '-c', 1.952 + 'import sys, pip; sys.exit(pip.main(["install", "--ignore-installed"] + sys.argv[1:]))', 1.953 + ] + project_names 1.954 + logger.start_progress('Installing %s...' % (', '.join(project_names))) 1.955 + logger.indent += 2 1.956 + try: 1.957 + call_subprocess(cmd, show_stdout=False, 1.958 + extra_env = { 1.959 + 'PYTHONPATH': pythonpath, 1.960 + 'PIP_FIND_LINKS': findlinks, 1.961 + 'PIP_USE_WHEEL': '1', 1.962 + 'PIP_PRE': '1', 1.963 + 'PIP_NO_INDEX': '1' 1.964 + } 1.965 + ) 1.966 + finally: 1.967 + logger.indent -= 2 1.968 + logger.end_progress() 1.969 + 1.970 +def create_environment(home_dir, site_packages=False, clear=False, 1.971 + unzip_setuptools=False, 1.972 + prompt=None, search_dirs=None, never_download=False, 1.973 + no_setuptools=False, no_pip=False, symlink=True): 1.974 + """ 1.975 + Creates a new environment in ``home_dir``. 1.976 + 1.977 + If ``site_packages`` is true, then the global ``site-packages/`` 1.978 + directory will be on the path. 1.979 + 1.980 + If ``clear`` is true (default False) then the environment will 1.981 + first be cleared. 1.982 + """ 1.983 + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) 1.984 + 1.985 + py_executable = os.path.abspath(install_python( 1.986 + home_dir, lib_dir, inc_dir, bin_dir, 1.987 + site_packages=site_packages, clear=clear, symlink=symlink)) 1.988 + 1.989 + install_distutils(home_dir) 1.990 + 1.991 + if not no_setuptools: 1.992 + to_install = ['setuptools'] 1.993 + if not no_pip: 1.994 + to_install.append('pip') 1.995 + install_wheel(to_install, py_executable, search_dirs) 1.996 + 1.997 + install_activate(home_dir, bin_dir, prompt) 1.998 + 1.999 +def is_executable_file(fpath): 1.1000 + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 1.1001 + 1.1002 +def path_locations(home_dir): 1.1003 + """Return the path locations for the environment (where libraries are, 1.1004 + where scripts go, etc)""" 1.1005 + # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its 1.1006 + # prefix arg is broken: http://bugs.python.org/issue3386 1.1007 + if is_win: 1.1008 + # Windows has lots of problems with executables with spaces in 1.1009 + # the name; this function will remove them (using the ~1 1.1010 + # format): 1.1011 + mkdir(home_dir) 1.1012 + if ' ' in home_dir: 1.1013 + import ctypes 1.1014 + GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW 1.1015 + size = max(len(home_dir)+1, 256) 1.1016 + buf = ctypes.create_unicode_buffer(size) 1.1017 + try: 1.1018 + u = unicode 1.1019 + except NameError: 1.1020 + u = str 1.1021 + ret = GetShortPathName(u(home_dir), buf, size) 1.1022 + if not ret: 1.1023 + print('Error: the path "%s" has a space in it' % home_dir) 1.1024 + print('We could not determine the short pathname for it.') 1.1025 + print('Exiting.') 1.1026 + sys.exit(3) 1.1027 + home_dir = str(buf.value) 1.1028 + lib_dir = join(home_dir, 'Lib') 1.1029 + inc_dir = join(home_dir, 'Include') 1.1030 + bin_dir = join(home_dir, 'Scripts') 1.1031 + if is_jython: 1.1032 + lib_dir = join(home_dir, 'Lib') 1.1033 + inc_dir = join(home_dir, 'Include') 1.1034 + bin_dir = join(home_dir, 'bin') 1.1035 + elif is_pypy: 1.1036 + lib_dir = home_dir 1.1037 + inc_dir = join(home_dir, 'include') 1.1038 + bin_dir = join(home_dir, 'bin') 1.1039 + elif not is_win: 1.1040 + lib_dir = join(home_dir, 'lib', py_version) 1.1041 + multiarch_exec = '/usr/bin/multiarch-platform' 1.1042 + if is_executable_file(multiarch_exec): 1.1043 + # In Mageia (2) and Mandriva distros the include dir must be like: 1.1044 + # virtualenv/include/multiarch-x86_64-linux/python2.7 1.1045 + # instead of being virtualenv/include/python2.7 1.1046 + p = subprocess.Popen(multiarch_exec, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 1.1047 + stdout, stderr = p.communicate() 1.1048 + # stdout.strip is needed to remove newline character 1.1049 + inc_dir = join(home_dir, 'include', stdout.strip(), py_version + abiflags) 1.1050 + else: 1.1051 + inc_dir = join(home_dir, 'include', py_version + abiflags) 1.1052 + bin_dir = join(home_dir, 'bin') 1.1053 + return home_dir, lib_dir, inc_dir, bin_dir 1.1054 + 1.1055 + 1.1056 +def change_prefix(filename, dst_prefix): 1.1057 + prefixes = [sys.prefix] 1.1058 + 1.1059 + if is_darwin: 1.1060 + prefixes.extend(( 1.1061 + os.path.join("/Library/Python", sys.version[:3], "site-packages"), 1.1062 + os.path.join(sys.prefix, "Extras", "lib", "python"), 1.1063 + os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"), 1.1064 + # Python 2.6 no-frameworks 1.1065 + os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"), 1.1066 + # System Python 2.7 on OSX Mountain Lion 1.1067 + os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages"))) 1.1068 + 1.1069 + if hasattr(sys, 'real_prefix'): 1.1070 + prefixes.append(sys.real_prefix) 1.1071 + if hasattr(sys, 'base_prefix'): 1.1072 + prefixes.append(sys.base_prefix) 1.1073 + prefixes = list(map(os.path.expanduser, prefixes)) 1.1074 + prefixes = list(map(os.path.abspath, prefixes)) 1.1075 + # Check longer prefixes first so we don't split in the middle of a filename 1.1076 + prefixes = sorted(prefixes, key=len, reverse=True) 1.1077 + filename = os.path.abspath(filename) 1.1078 + for src_prefix in prefixes: 1.1079 + if filename.startswith(src_prefix): 1.1080 + _, relpath = filename.split(src_prefix, 1) 1.1081 + if src_prefix != os.sep: # sys.prefix == "/" 1.1082 + assert relpath[0] == os.sep 1.1083 + relpath = relpath[1:] 1.1084 + return join(dst_prefix, relpath) 1.1085 + assert False, "Filename %s does not start with any of these prefixes: %s" % \ 1.1086 + (filename, prefixes) 1.1087 + 1.1088 +def copy_required_modules(dst_prefix, symlink): 1.1089 + import imp 1.1090 + # If we are running under -p, we need to remove the current 1.1091 + # directory from sys.path temporarily here, so that we 1.1092 + # definitely get the modules from the site directory of 1.1093 + # the interpreter we are running under, not the one 1.1094 + # virtualenv.py is installed under (which might lead to py2/py3 1.1095 + # incompatibility issues) 1.1096 + _prev_sys_path = sys.path 1.1097 + if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): 1.1098 + sys.path = sys.path[1:] 1.1099 + try: 1.1100 + for modname in REQUIRED_MODULES: 1.1101 + if modname in sys.builtin_module_names: 1.1102 + logger.info("Ignoring built-in bootstrap module: %s" % modname) 1.1103 + continue 1.1104 + try: 1.1105 + f, filename, _ = imp.find_module(modname) 1.1106 + except ImportError: 1.1107 + logger.info("Cannot import bootstrap module: %s" % modname) 1.1108 + else: 1.1109 + if f is not None: 1.1110 + f.close() 1.1111 + # special-case custom readline.so on OS X, but not for pypy: 1.1112 + if modname == 'readline' and sys.platform == 'darwin' and not ( 1.1113 + is_pypy or filename.endswith(join('lib-dynload', 'readline.so'))): 1.1114 + dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so') 1.1115 + elif modname == 'readline' and sys.platform == 'win32': 1.1116 + # special-case for Windows, where readline is not a 1.1117 + # standard module, though it may have been installed in 1.1118 + # site-packages by a third-party package 1.1119 + pass 1.1120 + else: 1.1121 + dst_filename = change_prefix(filename, dst_prefix) 1.1122 + copyfile(filename, dst_filename, symlink) 1.1123 + if filename.endswith('.pyc'): 1.1124 + pyfile = filename[:-1] 1.1125 + if os.path.exists(pyfile): 1.1126 + copyfile(pyfile, dst_filename[:-1], symlink) 1.1127 + finally: 1.1128 + sys.path = _prev_sys_path 1.1129 + 1.1130 + 1.1131 +def subst_path(prefix_path, prefix, home_dir): 1.1132 + prefix_path = os.path.normpath(prefix_path) 1.1133 + prefix = os.path.normpath(prefix) 1.1134 + home_dir = os.path.normpath(home_dir) 1.1135 + if not prefix_path.startswith(prefix): 1.1136 + logger.warn('Path not in prefix %r %r', prefix_path, prefix) 1.1137 + return 1.1138 + return prefix_path.replace(prefix, home_dir, 1) 1.1139 + 1.1140 + 1.1141 +def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, symlink=True): 1.1142 + """Install just the base environment, no distutils patches etc""" 1.1143 + if sys.executable.startswith(bin_dir): 1.1144 + print('Please use the *system* python to run this script') 1.1145 + return 1.1146 + 1.1147 + if clear: 1.1148 + rmtree(lib_dir) 1.1149 + ## FIXME: why not delete it? 1.1150 + ## Maybe it should delete everything with #!/path/to/venv/python in it 1.1151 + logger.notify('Not deleting %s', bin_dir) 1.1152 + 1.1153 + if hasattr(sys, 'real_prefix'): 1.1154 + logger.notify('Using real prefix %r' % sys.real_prefix) 1.1155 + prefix = sys.real_prefix 1.1156 + elif hasattr(sys, 'base_prefix'): 1.1157 + logger.notify('Using base prefix %r' % sys.base_prefix) 1.1158 + prefix = sys.base_prefix 1.1159 + else: 1.1160 + prefix = sys.prefix 1.1161 + mkdir(lib_dir) 1.1162 + fix_lib64(lib_dir, symlink) 1.1163 + stdlib_dirs = [os.path.dirname(os.__file__)] 1.1164 + if is_win: 1.1165 + stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs')) 1.1166 + elif is_darwin: 1.1167 + stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages')) 1.1168 + if hasattr(os, 'symlink'): 1.1169 + logger.info('Symlinking Python bootstrap modules') 1.1170 + else: 1.1171 + logger.info('Copying Python bootstrap modules') 1.1172 + logger.indent += 2 1.1173 + try: 1.1174 + # copy required files... 1.1175 + for stdlib_dir in stdlib_dirs: 1.1176 + if not os.path.isdir(stdlib_dir): 1.1177 + continue 1.1178 + for fn in os.listdir(stdlib_dir): 1.1179 + bn = os.path.splitext(fn)[0] 1.1180 + if fn != 'site-packages' and bn in REQUIRED_FILES: 1.1181 + copyfile(join(stdlib_dir, fn), join(lib_dir, fn), symlink) 1.1182 + # ...and modules 1.1183 + copy_required_modules(home_dir, symlink) 1.1184 + finally: 1.1185 + logger.indent -= 2 1.1186 + mkdir(join(lib_dir, 'site-packages')) 1.1187 + import site 1.1188 + site_filename = site.__file__ 1.1189 + if site_filename.endswith('.pyc'): 1.1190 + site_filename = site_filename[:-1] 1.1191 + elif site_filename.endswith('$py.class'): 1.1192 + site_filename = site_filename.replace('$py.class', '.py') 1.1193 + site_filename_dst = change_prefix(site_filename, home_dir) 1.1194 + site_dir = os.path.dirname(site_filename_dst) 1.1195 + writefile(site_filename_dst, SITE_PY) 1.1196 + writefile(join(site_dir, 'orig-prefix.txt'), prefix) 1.1197 + site_packages_filename = join(site_dir, 'no-global-site-packages.txt') 1.1198 + if not site_packages: 1.1199 + writefile(site_packages_filename, '') 1.1200 + 1.1201 + if is_pypy or is_win: 1.1202 + stdinc_dir = join(prefix, 'include') 1.1203 + else: 1.1204 + stdinc_dir = join(prefix, 'include', py_version + abiflags) 1.1205 + if os.path.exists(stdinc_dir): 1.1206 + copyfile(stdinc_dir, inc_dir, symlink) 1.1207 + else: 1.1208 + logger.debug('No include dir %s' % stdinc_dir) 1.1209 + 1.1210 + platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1) 1.1211 + if platinc_dir != stdinc_dir: 1.1212 + platinc_dest = distutils.sysconfig.get_python_inc( 1.1213 + plat_specific=1, prefix=home_dir) 1.1214 + if platinc_dir == platinc_dest: 1.1215 + # Do platinc_dest manually due to a CPython bug; 1.1216 + # not http://bugs.python.org/issue3386 but a close cousin 1.1217 + platinc_dest = subst_path(platinc_dir, prefix, home_dir) 1.1218 + if platinc_dest: 1.1219 + # PyPy's stdinc_dir and prefix are relative to the original binary 1.1220 + # (traversing virtualenvs), whereas the platinc_dir is relative to 1.1221 + # the inner virtualenv and ignores the prefix argument. 1.1222 + # This seems more evolved than designed. 1.1223 + copyfile(platinc_dir, platinc_dest, symlink) 1.1224 + 1.1225 + # pypy never uses exec_prefix, just ignore it 1.1226 + if sys.exec_prefix != prefix and not is_pypy: 1.1227 + if is_win: 1.1228 + exec_dir = join(sys.exec_prefix, 'lib') 1.1229 + elif is_jython: 1.1230 + exec_dir = join(sys.exec_prefix, 'Lib') 1.1231 + else: 1.1232 + exec_dir = join(sys.exec_prefix, 'lib', py_version) 1.1233 + for fn in os.listdir(exec_dir): 1.1234 + copyfile(join(exec_dir, fn), join(lib_dir, fn), symlink) 1.1235 + 1.1236 + if is_jython: 1.1237 + # Jython has either jython-dev.jar and javalib/ dir, or just 1.1238 + # jython.jar 1.1239 + for name in 'jython-dev.jar', 'javalib', 'jython.jar': 1.1240 + src = join(prefix, name) 1.1241 + if os.path.exists(src): 1.1242 + copyfile(src, join(home_dir, name), symlink) 1.1243 + # XXX: registry should always exist after Jython 2.5rc1 1.1244 + src = join(prefix, 'registry') 1.1245 + if os.path.exists(src): 1.1246 + copyfile(src, join(home_dir, 'registry'), symlink=False) 1.1247 + copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'), 1.1248 + symlink=False) 1.1249 + 1.1250 + mkdir(bin_dir) 1.1251 + py_executable = join(bin_dir, os.path.basename(sys.executable)) 1.1252 + if 'Python.framework' in prefix: 1.1253 + # OS X framework builds cause validation to break 1.1254 + # https://github.com/pypa/virtualenv/issues/322 1.1255 + if os.environ.get('__PYVENV_LAUNCHER__'): 1.1256 + del os.environ["__PYVENV_LAUNCHER__"] 1.1257 + if re.search(r'/Python(?:-32|-64)*$', py_executable): 1.1258 + # The name of the python executable is not quite what 1.1259 + # we want, rename it. 1.1260 + py_executable = os.path.join( 1.1261 + os.path.dirname(py_executable), 'python') 1.1262 + 1.1263 + logger.notify('New %s executable in %s', expected_exe, py_executable) 1.1264 + pcbuild_dir = os.path.dirname(sys.executable) 1.1265 + pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth') 1.1266 + if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')): 1.1267 + logger.notify('Detected python running from build directory %s', pcbuild_dir) 1.1268 + logger.notify('Writing .pth file linking to build directory for *.pyd files') 1.1269 + writefile(pyd_pth, pcbuild_dir) 1.1270 + else: 1.1271 + pcbuild_dir = None 1.1272 + if os.path.exists(pyd_pth): 1.1273 + logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth) 1.1274 + os.unlink(pyd_pth) 1.1275 + 1.1276 + if sys.executable != py_executable: 1.1277 + ## FIXME: could I just hard link? 1.1278 + executable = sys.executable 1.1279 + shutil.copyfile(executable, py_executable) 1.1280 + make_exe(py_executable) 1.1281 + if is_win or is_cygwin: 1.1282 + pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe') 1.1283 + if os.path.exists(pythonw): 1.1284 + logger.info('Also created pythonw.exe') 1.1285 + shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe')) 1.1286 + python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe') 1.1287 + python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe') 1.1288 + if os.path.exists(python_d): 1.1289 + logger.info('Also created python_d.exe') 1.1290 + shutil.copyfile(python_d, python_d_dest) 1.1291 + elif os.path.exists(python_d_dest): 1.1292 + logger.info('Removed python_d.exe as it is no longer at the source') 1.1293 + os.unlink(python_d_dest) 1.1294 + # we need to copy the DLL to enforce that windows will load the correct one. 1.1295 + # may not exist if we are cygwin. 1.1296 + py_executable_dll = 'python%s%s.dll' % ( 1.1297 + sys.version_info[0], sys.version_info[1]) 1.1298 + py_executable_dll_d = 'python%s%s_d.dll' % ( 1.1299 + sys.version_info[0], sys.version_info[1]) 1.1300 + pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll) 1.1301 + pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d) 1.1302 + pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d) 1.1303 + if os.path.exists(pythondll): 1.1304 + logger.info('Also created %s' % py_executable_dll) 1.1305 + shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll)) 1.1306 + if os.path.exists(pythondll_d): 1.1307 + logger.info('Also created %s' % py_executable_dll_d) 1.1308 + shutil.copyfile(pythondll_d, pythondll_d_dest) 1.1309 + elif os.path.exists(pythondll_d_dest): 1.1310 + logger.info('Removed %s as the source does not exist' % pythondll_d_dest) 1.1311 + os.unlink(pythondll_d_dest) 1.1312 + if is_pypy: 1.1313 + # make a symlink python --> pypy-c 1.1314 + python_executable = os.path.join(os.path.dirname(py_executable), 'python') 1.1315 + if sys.platform in ('win32', 'cygwin'): 1.1316 + python_executable += '.exe' 1.1317 + logger.info('Also created executable %s' % python_executable) 1.1318 + copyfile(py_executable, python_executable, symlink) 1.1319 + 1.1320 + if is_win: 1.1321 + for name in 'libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', 'libeay32.dll', 'ssleay32.dll', 'sqlite.dll': 1.1322 + src = join(prefix, name) 1.1323 + if os.path.exists(src): 1.1324 + copyfile(src, join(bin_dir, name), symlink) 1.1325 + 1.1326 + if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe: 1.1327 + secondary_exe = os.path.join(os.path.dirname(py_executable), 1.1328 + expected_exe) 1.1329 + py_executable_ext = os.path.splitext(py_executable)[1] 1.1330 + if py_executable_ext.lower() == '.exe': 1.1331 + # python2.4 gives an extension of '.4' :P 1.1332 + secondary_exe += py_executable_ext 1.1333 + if os.path.exists(secondary_exe): 1.1334 + logger.warn('Not overwriting existing %s script %s (you must use %s)' 1.1335 + % (expected_exe, secondary_exe, py_executable)) 1.1336 + else: 1.1337 + logger.notify('Also creating executable in %s' % secondary_exe) 1.1338 + shutil.copyfile(sys.executable, secondary_exe) 1.1339 + make_exe(secondary_exe) 1.1340 + 1.1341 + if '.framework' in prefix: 1.1342 + if 'Python.framework' in prefix: 1.1343 + logger.debug('MacOSX Python framework detected') 1.1344 + # Make sure we use the the embedded interpreter inside 1.1345 + # the framework, even if sys.executable points to 1.1346 + # the stub executable in ${sys.prefix}/bin 1.1347 + # See http://groups.google.com/group/python-virtualenv/ 1.1348 + # browse_thread/thread/17cab2f85da75951 1.1349 + original_python = os.path.join( 1.1350 + prefix, 'Resources/Python.app/Contents/MacOS/Python') 1.1351 + if 'EPD' in prefix: 1.1352 + logger.debug('EPD framework detected') 1.1353 + original_python = os.path.join(prefix, 'bin/python') 1.1354 + shutil.copy(original_python, py_executable) 1.1355 + 1.1356 + # Copy the framework's dylib into the virtual 1.1357 + # environment 1.1358 + virtual_lib = os.path.join(home_dir, '.Python') 1.1359 + 1.1360 + if os.path.exists(virtual_lib): 1.1361 + os.unlink(virtual_lib) 1.1362 + copyfile( 1.1363 + os.path.join(prefix, 'Python'), 1.1364 + virtual_lib, 1.1365 + symlink) 1.1366 + 1.1367 + # And then change the install_name of the copied python executable 1.1368 + try: 1.1369 + mach_o_change(py_executable, 1.1370 + os.path.join(prefix, 'Python'), 1.1371 + '@executable_path/../.Python') 1.1372 + except: 1.1373 + e = sys.exc_info()[1] 1.1374 + logger.warn("Could not call mach_o_change: %s. " 1.1375 + "Trying to call install_name_tool instead." % e) 1.1376 + try: 1.1377 + call_subprocess( 1.1378 + ["install_name_tool", "-change", 1.1379 + os.path.join(prefix, 'Python'), 1.1380 + '@executable_path/../.Python', 1.1381 + py_executable]) 1.1382 + except: 1.1383 + logger.fatal("Could not call install_name_tool -- you must " 1.1384 + "have Apple's development tools installed") 1.1385 + raise 1.1386 + 1.1387 + if not is_win: 1.1388 + # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist 1.1389 + py_exe_version_major = 'python%s' % sys.version_info[0] 1.1390 + py_exe_version_major_minor = 'python%s.%s' % ( 1.1391 + sys.version_info[0], sys.version_info[1]) 1.1392 + py_exe_no_version = 'python' 1.1393 + required_symlinks = [ py_exe_no_version, py_exe_version_major, 1.1394 + py_exe_version_major_minor ] 1.1395 + 1.1396 + py_executable_base = os.path.basename(py_executable) 1.1397 + 1.1398 + if py_executable_base in required_symlinks: 1.1399 + # Don't try to symlink to yourself. 1.1400 + required_symlinks.remove(py_executable_base) 1.1401 + 1.1402 + for pth in required_symlinks: 1.1403 + full_pth = join(bin_dir, pth) 1.1404 + if os.path.exists(full_pth): 1.1405 + os.unlink(full_pth) 1.1406 + if symlink: 1.1407 + os.symlink(py_executable_base, full_pth) 1.1408 + else: 1.1409 + copyfile(py_executable, full_pth, symlink) 1.1410 + 1.1411 + if is_win and ' ' in py_executable: 1.1412 + # There's a bug with subprocess on Windows when using a first 1.1413 + # argument that has a space in it. Instead we have to quote 1.1414 + # the value: 1.1415 + py_executable = '"%s"' % py_executable 1.1416 + # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks 1.1417 + cmd = [py_executable, '-c', 'import sys;out=sys.stdout;' 1.1418 + 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))'] 1.1419 + logger.info('Testing executable with %s %s "%s"' % tuple(cmd)) 1.1420 + try: 1.1421 + proc = subprocess.Popen(cmd, 1.1422 + stdout=subprocess.PIPE) 1.1423 + proc_stdout, proc_stderr = proc.communicate() 1.1424 + except OSError: 1.1425 + e = sys.exc_info()[1] 1.1426 + if e.errno == errno.EACCES: 1.1427 + logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e)) 1.1428 + sys.exit(100) 1.1429 + else: 1.1430 + raise e 1.1431 + 1.1432 + proc_stdout = proc_stdout.strip().decode("utf-8") 1.1433 + proc_stdout = os.path.normcase(os.path.abspath(proc_stdout)) 1.1434 + norm_home_dir = os.path.normcase(os.path.abspath(home_dir)) 1.1435 + if hasattr(norm_home_dir, 'decode'): 1.1436 + norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding()) 1.1437 + if proc_stdout != norm_home_dir: 1.1438 + logger.fatal( 1.1439 + 'ERROR: The executable %s is not functioning' % py_executable) 1.1440 + logger.fatal( 1.1441 + 'ERROR: It thinks sys.prefix is %r (should be %r)' 1.1442 + % (proc_stdout, norm_home_dir)) 1.1443 + logger.fatal( 1.1444 + 'ERROR: virtualenv is not compatible with this system or executable') 1.1445 + if is_win: 1.1446 + logger.fatal( 1.1447 + 'Note: some Windows users have reported this error when they ' 1.1448 + 'installed Python for "Only this user" or have multiple ' 1.1449 + 'versions of Python installed. Copying the appropriate ' 1.1450 + 'PythonXX.dll to the virtualenv Scripts/ directory may fix ' 1.1451 + 'this problem.') 1.1452 + sys.exit(100) 1.1453 + else: 1.1454 + logger.info('Got sys.prefix result: %r' % proc_stdout) 1.1455 + 1.1456 + pydistutils = os.path.expanduser('~/.pydistutils.cfg') 1.1457 + if os.path.exists(pydistutils): 1.1458 + logger.notify('Please make sure you remove any previous custom paths from ' 1.1459 + 'your %s file.' % pydistutils) 1.1460 + ## FIXME: really this should be calculated earlier 1.1461 + 1.1462 + fix_local_scheme(home_dir, symlink) 1.1463 + 1.1464 + if site_packages: 1.1465 + if os.path.exists(site_packages_filename): 1.1466 + logger.info('Deleting %s' % site_packages_filename) 1.1467 + os.unlink(site_packages_filename) 1.1468 + 1.1469 + return py_executable 1.1470 + 1.1471 + 1.1472 +def install_activate(home_dir, bin_dir, prompt=None): 1.1473 + home_dir = os.path.abspath(home_dir) 1.1474 + if is_win or is_jython and os._name == 'nt': 1.1475 + files = { 1.1476 + 'activate.bat': ACTIVATE_BAT, 1.1477 + 'deactivate.bat': DEACTIVATE_BAT, 1.1478 + 'activate.ps1': ACTIVATE_PS, 1.1479 + } 1.1480 + 1.1481 + # MSYS needs paths of the form /c/path/to/file 1.1482 + drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/')) 1.1483 + home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail) 1.1484 + 1.1485 + # Run-time conditional enables (basic) Cygwin compatibility 1.1486 + home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" % 1.1487 + (home_dir, home_dir_msys)) 1.1488 + files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh) 1.1489 + 1.1490 + else: 1.1491 + files = {'activate': ACTIVATE_SH} 1.1492 + 1.1493 + # suppling activate.fish in addition to, not instead of, the 1.1494 + # bash script support. 1.1495 + files['activate.fish'] = ACTIVATE_FISH 1.1496 + 1.1497 + # same for csh/tcsh support... 1.1498 + files['activate.csh'] = ACTIVATE_CSH 1.1499 + 1.1500 + files['activate_this.py'] = ACTIVATE_THIS 1.1501 + if hasattr(home_dir, 'decode'): 1.1502 + home_dir = home_dir.decode(sys.getfilesystemencoding()) 1.1503 + vname = os.path.basename(home_dir) 1.1504 + for name, content in files.items(): 1.1505 + content = content.replace('__VIRTUAL_PROMPT__', prompt or '') 1.1506 + content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname) 1.1507 + content = content.replace('__VIRTUAL_ENV__', home_dir) 1.1508 + content = content.replace('__VIRTUAL_NAME__', vname) 1.1509 + content = content.replace('__BIN_NAME__', os.path.basename(bin_dir)) 1.1510 + writefile(os.path.join(bin_dir, name), content) 1.1511 + 1.1512 +def install_distutils(home_dir): 1.1513 + distutils_path = change_prefix(distutils.__path__[0], home_dir) 1.1514 + mkdir(distutils_path) 1.1515 + ## FIXME: maybe this prefix setting should only be put in place if 1.1516 + ## there's a local distutils.cfg with a prefix setting? 1.1517 + home_dir = os.path.abspath(home_dir) 1.1518 + ## FIXME: this is breaking things, removing for now: 1.1519 + #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir 1.1520 + writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT) 1.1521 + writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False) 1.1522 + 1.1523 +def fix_local_scheme(home_dir, symlink=True): 1.1524 + """ 1.1525 + Platforms that use the "posix_local" install scheme (like Ubuntu with 1.1526 + Python 2.7) need to be given an additional "local" location, sigh. 1.1527 + """ 1.1528 + try: 1.1529 + import sysconfig 1.1530 + except ImportError: 1.1531 + pass 1.1532 + else: 1.1533 + if sysconfig._get_default_scheme() == 'posix_local': 1.1534 + local_path = os.path.join(home_dir, 'local') 1.1535 + if not os.path.exists(local_path): 1.1536 + os.mkdir(local_path) 1.1537 + for subdir_name in os.listdir(home_dir): 1.1538 + if subdir_name == 'local': 1.1539 + continue 1.1540 + copyfile(os.path.abspath(os.path.join(home_dir, subdir_name)), \ 1.1541 + os.path.join(local_path, subdir_name), symlink) 1.1542 + 1.1543 +def fix_lib64(lib_dir, symlink=True): 1.1544 + """ 1.1545 + Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y 1.1546 + instead of lib/pythonX.Y. If this is such a platform we'll just create a 1.1547 + symlink so lib64 points to lib 1.1548 + """ 1.1549 + if [p for p in distutils.sysconfig.get_config_vars().values() 1.1550 + if isinstance(p, basestring) and 'lib64' in p]: 1.1551 + # PyPy's library path scheme is not affected by this. 1.1552 + # Return early or we will die on the following assert. 1.1553 + if is_pypy: 1.1554 + logger.debug('PyPy detected, skipping lib64 symlinking') 1.1555 + return 1.1556 + 1.1557 + logger.debug('This system uses lib64; symlinking lib64 to lib') 1.1558 + 1.1559 + assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], ( 1.1560 + "Unexpected python lib dir: %r" % lib_dir) 1.1561 + lib_parent = os.path.dirname(lib_dir) 1.1562 + top_level = os.path.dirname(lib_parent) 1.1563 + lib_dir = os.path.join(top_level, 'lib') 1.1564 + lib64_link = os.path.join(top_level, 'lib64') 1.1565 + assert os.path.basename(lib_parent) == 'lib', ( 1.1566 + "Unexpected parent dir: %r" % lib_parent) 1.1567 + if os.path.lexists(lib64_link): 1.1568 + return 1.1569 + cp_or_ln = (os.symlink if symlink else copyfile) 1.1570 + cp_or_ln('lib', lib64_link) 1.1571 + 1.1572 +def resolve_interpreter(exe): 1.1573 + """ 1.1574 + If the executable given isn't an absolute path, search $PATH for the interpreter 1.1575 + """ 1.1576 + # If the "executable" is a version number, get the installed executable for 1.1577 + # that version 1.1578 + python_versions = get_installed_pythons() 1.1579 + if exe in python_versions: 1.1580 + exe = python_versions[exe] 1.1581 + 1.1582 + if os.path.abspath(exe) != exe: 1.1583 + paths = os.environ.get('PATH', '').split(os.pathsep) 1.1584 + for path in paths: 1.1585 + if os.path.exists(os.path.join(path, exe)): 1.1586 + exe = os.path.join(path, exe) 1.1587 + break 1.1588 + if not os.path.exists(exe): 1.1589 + logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe)) 1.1590 + raise SystemExit(3) 1.1591 + if not is_executable(exe): 1.1592 + logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe)) 1.1593 + raise SystemExit(3) 1.1594 + return exe 1.1595 + 1.1596 +def is_executable(exe): 1.1597 + """Checks a file is executable""" 1.1598 + return os.access(exe, os.X_OK) 1.1599 + 1.1600 +############################################################ 1.1601 +## Relocating the environment: 1.1602 + 1.1603 +def make_environment_relocatable(home_dir): 1.1604 + """ 1.1605 + Makes the already-existing environment use relative paths, and takes out 1.1606 + the #!-based environment selection in scripts. 1.1607 + """ 1.1608 + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) 1.1609 + activate_this = os.path.join(bin_dir, 'activate_this.py') 1.1610 + if not os.path.exists(activate_this): 1.1611 + logger.fatal( 1.1612 + 'The environment doesn\'t have a file %s -- please re-run virtualenv ' 1.1613 + 'on this environment to update it' % activate_this) 1.1614 + fixup_scripts(home_dir, bin_dir) 1.1615 + fixup_pth_and_egg_link(home_dir) 1.1616 + ## FIXME: need to fix up distutils.cfg 1.1617 + 1.1618 +OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3], 1.1619 + 'activate', 'activate.bat', 'activate_this.py', 1.1620 + 'activate.fish', 'activate.csh'] 1.1621 + 1.1622 +def fixup_scripts(home_dir, bin_dir): 1.1623 + if is_win: 1.1624 + new_shebang_args = ( 1.1625 + '%s /c' % os.path.normcase(os.environ.get('COMSPEC', 'cmd.exe')), 1.1626 + '', '.exe') 1.1627 + else: 1.1628 + new_shebang_args = ('/usr/bin/env', sys.version[:3], '') 1.1629 + 1.1630 + # This is what we expect at the top of scripts: 1.1631 + shebang = '#!%s' % os.path.normcase(os.path.join( 1.1632 + os.path.abspath(bin_dir), 'python%s' % new_shebang_args[2])) 1.1633 + # This is what we'll put: 1.1634 + new_shebang = '#!%s python%s%s' % new_shebang_args 1.1635 + 1.1636 + for filename in os.listdir(bin_dir): 1.1637 + filename = os.path.join(bin_dir, filename) 1.1638 + if not os.path.isfile(filename): 1.1639 + # ignore subdirs, e.g. .svn ones. 1.1640 + continue 1.1641 + f = open(filename, 'rb') 1.1642 + try: 1.1643 + try: 1.1644 + lines = f.read().decode('utf-8').splitlines() 1.1645 + except UnicodeDecodeError: 1.1646 + # This is probably a binary program instead 1.1647 + # of a script, so just ignore it. 1.1648 + continue 1.1649 + finally: 1.1650 + f.close() 1.1651 + if not lines: 1.1652 + logger.warn('Script %s is an empty file' % filename) 1.1653 + continue 1.1654 + 1.1655 + old_shebang = lines[0].strip() 1.1656 + old_shebang = old_shebang[0:2] + os.path.normcase(old_shebang[2:]) 1.1657 + 1.1658 + if not old_shebang.startswith(shebang): 1.1659 + if os.path.basename(filename) in OK_ABS_SCRIPTS: 1.1660 + logger.debug('Cannot make script %s relative' % filename) 1.1661 + elif lines[0].strip() == new_shebang: 1.1662 + logger.info('Script %s has already been made relative' % filename) 1.1663 + else: 1.1664 + logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)' 1.1665 + % (filename, shebang)) 1.1666 + continue 1.1667 + logger.notify('Making script %s relative' % filename) 1.1668 + script = relative_script([new_shebang] + lines[1:]) 1.1669 + f = open(filename, 'wb') 1.1670 + f.write('\n'.join(script).encode('utf-8')) 1.1671 + f.close() 1.1672 + 1.1673 +def relative_script(lines): 1.1674 + "Return a script that'll work in a relocatable environment." 1.1675 + 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" 1.1676 + # Find the last future statement in the script. If we insert the activation 1.1677 + # line before a future statement, Python will raise a SyntaxError. 1.1678 + activate_at = None 1.1679 + for idx, line in reversed(list(enumerate(lines))): 1.1680 + if line.split()[:3] == ['from', '__future__', 'import']: 1.1681 + activate_at = idx + 1 1.1682 + break 1.1683 + if activate_at is None: 1.1684 + # Activate after the shebang. 1.1685 + activate_at = 1 1.1686 + return lines[:activate_at] + ['', activate, ''] + lines[activate_at:] 1.1687 + 1.1688 +def fixup_pth_and_egg_link(home_dir, sys_path=None): 1.1689 + """Makes .pth and .egg-link files use relative paths""" 1.1690 + home_dir = os.path.normcase(os.path.abspath(home_dir)) 1.1691 + if sys_path is None: 1.1692 + sys_path = sys.path 1.1693 + for path in sys_path: 1.1694 + if not path: 1.1695 + path = '.' 1.1696 + if not os.path.isdir(path): 1.1697 + continue 1.1698 + path = os.path.normcase(os.path.abspath(path)) 1.1699 + if not path.startswith(home_dir): 1.1700 + logger.debug('Skipping system (non-environment) directory %s' % path) 1.1701 + continue 1.1702 + for filename in os.listdir(path): 1.1703 + filename = os.path.join(path, filename) 1.1704 + if filename.endswith('.pth'): 1.1705 + if not os.access(filename, os.W_OK): 1.1706 + logger.warn('Cannot write .pth file %s, skipping' % filename) 1.1707 + else: 1.1708 + fixup_pth_file(filename) 1.1709 + if filename.endswith('.egg-link'): 1.1710 + if not os.access(filename, os.W_OK): 1.1711 + logger.warn('Cannot write .egg-link file %s, skipping' % filename) 1.1712 + else: 1.1713 + fixup_egg_link(filename) 1.1714 + 1.1715 +def fixup_pth_file(filename): 1.1716 + lines = [] 1.1717 + prev_lines = [] 1.1718 + f = open(filename) 1.1719 + prev_lines = f.readlines() 1.1720 + f.close() 1.1721 + for line in prev_lines: 1.1722 + line = line.strip() 1.1723 + if (not line or line.startswith('#') or line.startswith('import ') 1.1724 + or os.path.abspath(line) != line): 1.1725 + lines.append(line) 1.1726 + else: 1.1727 + new_value = make_relative_path(filename, line) 1.1728 + if line != new_value: 1.1729 + logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename)) 1.1730 + lines.append(new_value) 1.1731 + if lines == prev_lines: 1.1732 + logger.info('No changes to .pth file %s' % filename) 1.1733 + return 1.1734 + logger.notify('Making paths in .pth file %s relative' % filename) 1.1735 + f = open(filename, 'w') 1.1736 + f.write('\n'.join(lines) + '\n') 1.1737 + f.close() 1.1738 + 1.1739 +def fixup_egg_link(filename): 1.1740 + f = open(filename) 1.1741 + link = f.readline().strip() 1.1742 + f.close() 1.1743 + if os.path.abspath(link) != link: 1.1744 + logger.debug('Link in %s already relative' % filename) 1.1745 + return 1.1746 + new_link = make_relative_path(filename, link) 1.1747 + logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link)) 1.1748 + f = open(filename, 'w') 1.1749 + f.write(new_link) 1.1750 + f.close() 1.1751 + 1.1752 +def make_relative_path(source, dest, dest_is_directory=True): 1.1753 + """ 1.1754 + Make a filename relative, where the filename is dest, and it is 1.1755 + being referred to from the filename source. 1.1756 + 1.1757 + >>> make_relative_path('/usr/share/something/a-file.pth', 1.1758 + ... '/usr/share/another-place/src/Directory') 1.1759 + '../another-place/src/Directory' 1.1760 + >>> make_relative_path('/usr/share/something/a-file.pth', 1.1761 + ... '/home/user/src/Directory') 1.1762 + '../../../home/user/src/Directory' 1.1763 + >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/') 1.1764 + './' 1.1765 + """ 1.1766 + source = os.path.dirname(source) 1.1767 + if not dest_is_directory: 1.1768 + dest_filename = os.path.basename(dest) 1.1769 + dest = os.path.dirname(dest) 1.1770 + dest = os.path.normpath(os.path.abspath(dest)) 1.1771 + source = os.path.normpath(os.path.abspath(source)) 1.1772 + dest_parts = dest.strip(os.path.sep).split(os.path.sep) 1.1773 + source_parts = source.strip(os.path.sep).split(os.path.sep) 1.1774 + while dest_parts and source_parts and dest_parts[0] == source_parts[0]: 1.1775 + dest_parts.pop(0) 1.1776 + source_parts.pop(0) 1.1777 + full_parts = ['..']*len(source_parts) + dest_parts 1.1778 + if not dest_is_directory: 1.1779 + full_parts.append(dest_filename) 1.1780 + if not full_parts: 1.1781 + # Special case for the current directory (otherwise it'd be '') 1.1782 + return './' 1.1783 + return os.path.sep.join(full_parts) 1.1784 + 1.1785 + 1.1786 + 1.1787 +############################################################ 1.1788 +## Bootstrap script creation: 1.1789 + 1.1790 +def create_bootstrap_script(extra_text, python_version=''): 1.1791 + """ 1.1792 + Creates a bootstrap script, which is like this script but with 1.1793 + extend_parser, adjust_options, and after_install hooks. 1.1794 + 1.1795 + This returns a string that (written to disk of course) can be used 1.1796 + as a bootstrap script with your own customizations. The script 1.1797 + will be the standard virtualenv.py script, with your extra text 1.1798 + added (your extra text should be Python code). 1.1799 + 1.1800 + If you include these functions, they will be called: 1.1801 + 1.1802 + ``extend_parser(optparse_parser)``: 1.1803 + You can add or remove options from the parser here. 1.1804 + 1.1805 + ``adjust_options(options, args)``: 1.1806 + You can change options here, or change the args (if you accept 1.1807 + different kinds of arguments, be sure you modify ``args`` so it is 1.1808 + only ``[DEST_DIR]``). 1.1809 + 1.1810 + ``after_install(options, home_dir)``: 1.1811 + 1.1812 + After everything is installed, this function is called. This 1.1813 + is probably the function you are most likely to use. An 1.1814 + example would be:: 1.1815 + 1.1816 + def after_install(options, home_dir): 1.1817 + subprocess.call([join(home_dir, 'bin', 'easy_install'), 1.1818 + 'MyPackage']) 1.1819 + subprocess.call([join(home_dir, 'bin', 'my-package-script'), 1.1820 + 'setup', home_dir]) 1.1821 + 1.1822 + This example immediately installs a package, and runs a setup 1.1823 + script from that package. 1.1824 + 1.1825 + If you provide something like ``python_version='2.5'`` then the 1.1826 + script will start with ``#!/usr/bin/env python2.5`` instead of 1.1827 + ``#!/usr/bin/env python``. You can use this when the script must 1.1828 + be run with a particular Python version. 1.1829 + """ 1.1830 + filename = __file__ 1.1831 + if filename.endswith('.pyc'): 1.1832 + filename = filename[:-1] 1.1833 + f = codecs.open(filename, 'r', encoding='utf-8') 1.1834 + content = f.read() 1.1835 + f.close() 1.1836 + py_exe = 'python%s' % python_version 1.1837 + content = (('#!/usr/bin/env %s\n' % py_exe) 1.1838 + + '## WARNING: This file is generated\n' 1.1839 + + content) 1.1840 + return content.replace('##EXT' 'END##', extra_text) 1.1841 + 1.1842 +##EXTEND## 1.1843 + 1.1844 +def convert(s): 1.1845 + b = base64.b64decode(s.encode('ascii')) 1.1846 + return zlib.decompress(b).decode('utf-8') 1.1847 + 1.1848 +##file site.py 1.1849 +SITE_PY = convert(""" 1.1850 +eJzFPf1z2zaWv/OvwMqToZTIdOJ0e3tOnRsncVrvuYm3SWdz63q0lARZrCmSJUjL2pu7v/3eBwAC 1.1851 +JCXbm+6cphNLJPDw8PC+8PAeOhgMTopCZnOxyud1KoWScTlbiiKulkos8lJUy6Sc7xdxWW3g6ewm 1.1852 +vpZKVLlQGxVhqygInn7lJ3gqPi8TZVCAb3Fd5au4SmZxmm5EsiryspJzMa/LJLsWSZZUSZwm/4AW 1.1853 +eRaJp1+PQXCWCZh5mshS3MpSAVwl8oW42FTLPBPDusA5v4j+GL8cjYWalUlRQYNS4wwUWcZVkEk5 1.1854 +BzShZa2AlEkl91UhZ8kimdmG67xO56JI45kUf/87T42ahmGg8pVcL2UpRQbIAEwJsArEA74mpZjl 1.1855 +cxkJ8UbOYhyAnzfEChjaGNdMIRmzXKR5dg1zyuRMKhWXGzGc1hUBIpTFPAecEsCgStI0WOfljRrB 1.1856 +ktJ6rOGRiJk9/Mkwe8A8cfwu5wCOH7Pg5yy5GzNs4B4EVy2ZbUq5SO5EjGDhp7yTs4l+NkwWYp4s 1.1857 +FkCDrBphk4ARUCJNpgcFLcd3eoVeHxBWlitjGEMiytyYX1KPKDirRJwqYNu6QBopwvydnCZxBtTI 1.1858 +bmE4gAgkDfrGmSeqsuPQ7EQOAEpcxwqkZKXEcBUnGTDrj/GM0P5rks3ztRoRBWC1lPi1VpU7/2EP 1.1859 +AaC1Q4BxgItlVrPO0uRGppsRIPAZsC+lqtMKBWKelHJW5WUiFQEA1DZC3gHSYxGXUpOQOdPI7Zjo 1.1860 +TzRJMlxYFDAUeHyJJFkk13VJEiYWCXAucMX7jz+Jd6dvzk4+aB4zwFhmr1eAM0ChhXZwggHEQa3K 1.1861 +gzQHgY6Cc/wj4vkchewaxwe8mgYH9650MIS5F1G7j7PgQHa9uHoYmGMFyoTGCqjff0OXsVoCff7n 1.1862 +nvUOgpNtVKGJ87f1MgeZzOKVFMuY+Qs5I/hOw3kdFdXyFXCDQjgVkErh4iCCCcIDkrg0G+aZFAWw 1.1863 +WJpkchQAhabU1l9FYIUPebZPa93iBIBQBhm8dJ6NaMRMwkS7sF6hvjCNNzQz3SSw67zKS1IcwP/Z 1.1864 +jHRRGmc3hKMihuJvU3mdZBkihLwQhHshDaxuEuDEeSTOqRXpBdNIhKy9uCWKRA28hEwHPCnv4lWR 1.1865 +yjGLL+rW3WqEBpOVMGudMsdBy4rUK61aM9Ve3juMvrS4jtCslqUE4PXUE7pFno/FFHQ2YVPEKxav 1.1866 +ap0T5wQ98kSdkCeoJfTF70DRE6XqlbQvkVdAsxBDBYs8TfM1kOwoCITYw0bGKPvMCW/hHfwLcPHf 1.1867 +VFazZRA4I1nAGhQivw0UAgGTIDPN1RoJj9s0K7eVTJKxpsjLuSxpqIcR+4ARf2BjnGvwIa+0UePp 1.1868 +4irnq6RClTTVJjNhi5eFFevHVzxvmAZYbkU0M00bOq1wemmxjKfSuCRTuUBJ0Iv0yi47jBn0jEm2 1.1869 +uBIrtjLwDsgiE7Yg/YoFlc6ikuQEAAwWvjhLijqlRgoZTMQw0Kog+KsYTXqunSVgbzbLASokNt8z 1.1870 +sD+A2z9AjNbLBOgzAwigYVBLwfJNk6pEB6HRR4Fv9E1/Hh849WyhbRMPuYiTVFv5OAvO6OFpWZL4 1.1871 +zmSBvcaaGApmmFXo2l1nQEcU88FgEATGHdoo8zVXQVVujoAVhBlnMpnWCRq+yQRNvf6hAh5FOAN7 1.1872 +3Ww7Cw80hOn0AajkdFmU+Qpf27l9AmUCY2GPYE9ckJaR7CB7nPgKyeeq9MI0RdvtsLNAPRRc/HT6 1.1873 +/uzL6SdxLC4blTZu67MrGPM0i4GtySIAU7WGbXQZtETFl6DuE+/BvBNTgD2j3iS+Mq5q4F1A/XNZ 1.1874 +02uYxsx7GZx+OHlzfjr5+dPpT5NPZ59PAUGwMzLYoymjeazBYVQRCAdw5VxF2r4GnR704M3JJ/sg 1.1875 +mCRq8u03wG7wZHgtK2DicggzHotwFd8pYNBwTE1HiGOnAVjwcDQSr8Xh06cvDwlasSk2AAzMrtMU 1.1876 +H060RZ8k2SIPR9T4V3bpj1lJaf/t8uibK3F8LMJf49s4DMCHapoyS/xI4vR5U0joWsGfYa5GQTCX 1.1877 +CxC9G4kCOnxKfvGIO8CSQMtc2+lf8yQz75kr3SFIfwypB+AwmczSWClsPJmEQATq0POBDhE71yh1 1.1878 +Q+hYbNyuI40KfkoJC5thlzH+04NiPKV+iAaj6HYxjUBcV7NYSW5F04d+kwnqrMlkqAcEYSaJAYeL 1.1879 +1VAoTBPUWWUCfi1xHuqwqcpT/InwUQuQAOLWCrUkLpLeOkW3cVpLNXQmBUQcDltkREWbKOJHcFGG 1.1880 +YImbpRuN2tQ0PAPNgHxpDlq0bFEOP3vg74C6Mps43Ojx3otphpj+mXcahAO4nCGqe6VaUFg7iovT 1.1881 +C/Hy+eE+ujOw55xb6njN0UInWS3twwWslpEHRph7GXlx6bJAPYtPj3bDXEV2ZbqssNBLXMpVfivn 1.1882 +gC0ysLPK4id6AztzmMcshlUEvU7+AKtQ4zfGuA/l2YO0oO8A1FsRFLP+Zun3OBggMwWKiDfWRGq9 1.1883 +62dTWJT5bYLOxnSjX4KtBGWJFtM4NoGzcB6ToUkEDQFecIaUWssQ1GFZs8NKeCNItBfzRrFGBO4c 1.1884 +NfUVfb3J8nU24Z3wMSrd4ciyLgqWZl5s0CzBnngPVgiQzGFj1xCNoYDLL1C29gF5mD5MFyhLewsA 1.1885 +BIZe0XbNgWW2ejRF3jXisAhj9EqQ8JYS/YVbMwRttQwxHEj0NrIPjJZASDA5q+CsatBMhrJmmsHA 1.1886 +Dkl8rjuPeAvqA2hRMQKzOdTQuJGh3+URKGdx7iolpx9a5C9fvjDbqCXFVxCxKU4aXYgFGcuo2IBh 1.1887 +TUAnGI+MozXEBmtwbgFMrTRriv1PIi/YG4P1vNCyDX4A7O6qqjg6OFiv15GOLuTl9YFaHPzxT99+ 1.1888 ++6fnrBPnc+IfmI4jLTrUFh3QO/Roo++MBXptVq7Fj0nmcyPBGkryysgVRfy+r5N5Lo72R1Z/Ihc3 1.1889 +Zhr/Na4MKJCJGZSpDLQdNBg9UftPopdqIJ6QdbZthyP2S7RJtVbMt7rQo8rBEwC/ZZbXaKobTlDi 1.1890 +GVg32KHP5bS+Du3gno00P2CqKKdDywP7L64QA58zDF8ZUzxBLUFsgRbfIf1PzDYxeUdaQyB50UR1 1.1891 +ds+bfi1miDt/uLxbX9MRGjPDRCF3oET4TR4sgLZxV3Lwo11btHuOa2s+niEwlj4wzKsdyyEKDuGC 1.1892 +azF2pc7havR4QZrWrJpBwbiqERQ0OIlTprYGRzYyRJDo3ZjNPi+sbgF0akUOTXzArAK0cMfpWLs2 1.1893 +KzieEPLAsXhBTyS4yEedd895aes0pYBOi0c9qjBgb6HRTufAl0MDYCwG5c8Dbmm2KR9bi8Jr0AMs 1.1894 +5xgQMtiiw0z4xvUBB3uDHnbqWP1tvZnGfSBwkYYci3oQdEL5mEcoFUhTMfR7bmNxS9zuYDstDjGV 1.1895 +WSYSabVFuNrKo1eodhqmRZKh7nUWKZqlOXjFVisSIzXvfWeB9kH4uM+YaQnUZGjI4TQ6Jm/PE8BQ 1.1896 +t8Pw2XWNgQY3DoMYrRJF1g3JtIR/wK2g+AYFo4CWBM2CeaiU+RP7HWTOzld/2cIeltDIEG7TbW5I 1.1897 +x2JoOOb9nkAy6mgMSEEGJOwKI7mOrA5S4DBngTzhhtdyq3QTjEiBnDkWhNQM4E4vvQ0OPonwBIQk 1.1898 +FCHfVUoW4pkYwPK1RfVhuvt35VIThBg6DchV0NGLYzey4UQ1jltRDp+h/fgGnZUUOXDwFFweN9Dv 1.1899 +srlhWht0AWfdV9wWKdDIFIcZjFxUrwxh3GDyH46dFg2xzCCGobyBvCMdM9IosMutQcOCGzDemrfH 1.1900 +0o/diAX2HYa5OpSrO9j/hWWiZrkKKWbSjl24H80VXdpYbM+T6QD+eAswGF15kGSq4xcYZfknBgk9 1.1901 +6GEfdG+yGBaZx+U6yUJSYJp+x/7SdPCwpPSM3MEn2k4dwEQx4nnwvgQBoaPPAxAn1ASwK5eh0m5/ 1.1902 +F+zOKQ4sXO4+8Nzmy6OXV13ijrdFeOynf6lO76oyVrhaKS8aCwWuVteAo9KFycXZRh9e6sNt3CaU 1.1903 +uYJdpPj46YtAQnBcdx1vHjf1huERm3vn5H0M6qDX7iVXa3bELoAIakVklIPw8Rz5cGQfO7kdE3sE 1.1904 +kEcxzI5FMZA0n/wzcHYtFIyxP99kGEdrqwz8wOtvv5n0REZdJL/9ZnDPKC1i9In9sOUJ2pE5qWDX 1.1905 +bEsZp+RqOH0oqJg1rGPbFCPW57T90zx21eNzarRs7Lu/BX4MFAypS/ARno8bsnWnih/fndoKT9up 1.1906 +HcA6u1Xz2aNFgL19Pv0VdshKB9Vu4ySlcwWY/P4+Klezued4Rb/28CDtVDAOCfr2X+ryOXBDyNGE 1.1907 +UXc62hk7MQHnnl2w+RSx6qKyp3MImiMwLy/APf7sQtUWzDDucz5eOOxRTd6M+5yJr1Gr+PldNJAF 1.1908 +5tFg0Ef2rez4/zHL5/+aST5wKubk+ne0ho8E9HvNhI0HQ9PGw4fVv+yu3TXAHmCetridO9zC7tB8 1.1909 +Vrkwzh2rJCWeou56KtaUrkCxVTwpAihz9vt64OAy6kPvt3VZ8tE1qcBClvt4HDsWmKllPL9eE7Mn 1.1910 +Dj7ICjGxzWYUq3byevI+NRLq6LOdSdjsG/rlbJmbmJXMbpMS+oLCHYY/fPzxNOw3IRjHhU4PtyIP 1.1911 +9xsQ7iOYNtTECR/Thyn0mC7/vFS1ty4+QU1GgIkIa7L12gc/EGziCP1rcE9EyDuw5WN23KHPlnJ2 1.1912 +M5GUOoBsil2doPhbfI2Y2IwCP/9LxQtKYoOZzNIaacWON2YfLupsRucjlQT/SqcKY+oQJQRw+G+R 1.1913 +xtdiSJ3nGHrS3EjRqdu41N5nUeaYnCrqZH5wncyF/K2OU9zWy8UCcMHDK/0q4uEpAiXecU4DJy0q 1.1914 +OavLpNoACWKV67M/Sn9wGk43PNGhhyQf8zABMSHiSHzCaeN7JtzckMsEB/wTD5wk7ruxg5OsENFz 1.1915 +eJ/lExx1Qjm+Y0aqey5Pj4P2CDkAGABQmP9gpCN3/htJr9wDRlpzl6ioJT1SupGGnJwxhDIcYaSD 1.1916 +f9NPnxFd3tqC5fV2LK93Y3ndxvK6F8trH8vr3Vi6IoELa4NWRhL6AlftY43efBs35sTDnMazJbfD 1.1917 +3E/M8QSIojAbbCNTnALtRbb4fI+AkNp2DpzpYZM/k3BSaZlzCFyDRO7HQyy9mTfJ605nysbRnXkq 1.1918 +xp3dlkPk9z2IIkoVm1J3lrd5XMWRJxfXaT4FsbXojhsAY9FOJ+JYaXY7mXJ0t2WpBhf/9fmHjx+w 1.1919 +OYIamPQG6oaLiIYFpzJ8GpfXqitNzeavAHakln4iDnXTAPceGFnjUfb4n3eU4YGMI9aUoZCLAjwA 1.1920 +yuqyzdzcpzBsPddJUvo5MzkfNh2LQVYNmkltIdLJxcW7k88nAwr5Df534AqMoa0vHS4+poVt0PXf 1.1921 +3OaW4tgHhFrHthrj587Jo3XDEffbWAO248O3Hhw+xGD3hgn8Wf5LKQVLAoSKdPD3MYR68B7oq7YJ 1.1922 +HfoYRuwk/7kna+ys2HeO7DkuiiP6fccO7QH8w07cY0yAANqFGpqdQbOZail9a153UNQB+kBf76u3 1.1923 +YO2tV3sn41PUTqLHAXQoa5ttd/+8cxo2ekpWb06/P/twfvbm4uTzD44LiK7cx08Hh+L0xy+C8kPQ 1.1924 +gLFPFGNqRIWZSGBY3EInMc/hvxojP/O64iAx9Hp3fq5PalZY6oK5z2hzInjOaUwWGgfNOAptH+r8 1.1925 +I8Qo1Rskp6aI0nWo5gj3SyuuZ1G5zo+mUqUpOqu13nrpWjFTU0bn2hFIHzR2ScEgOMUMXlEWe2V2 1.1926 +hSWfAOo6qx6ktI22iSEpBQU76QLO+Zc5XfECpdQZnjSdtaK/DF1cw6tIFWkCO7lXoZUl3Q3TYxrG 1.1927 +0Q/tATfj1acBne4wsm7Is96KBVqtVyHPTfcfNYz2Ww0YNgz2DuadSUoPoQxsTG4TITbik5xQ3sFX 1.1928 +u/R6DRQsGB70VbiIhukSmH0Mm2uxTGADATy5BOuL+wSA0FoJ/0DgyIkOyByzM8K3q/n+X0JNEL/1 1.1929 +L7/0NK/KdP9vooBdkOBUorCHmG7jd7DxiWQkTj++H4WMHKXmir/UWB4ADgkFQB1pp/wlPkGfDJVM 1.1930 +Fzq/xNcH+EL7CfS61b2URam797vGIUrAEzUkr+GJMvQLMd3Lwh7jVEYt0Fj5YDHDCkI3DcF89sSn 1.1931 +pUxTne9+9u78FHxHLMZACeJzt1MYjuMleISuk++4wrEFCg/Y4XWJbFyiC0tJFvPIa9YbtEaRo95e 1.1932 +XoZdJwoMd3t1osBlnCgX7SFOm2GZcoIIWRnWwiwrs3arDVLYbUMUR5lhlphclJTA6vME8DI9jXlL 1.1933 +BHslLPUwEXg+RU6yymQspskM9CioXFCoYxASJC7WMxLn5RnHwPNSmTIoeFhsyuR6WeHpBnSOqAQD 1.1934 +m/948uX87AOVJRy+bLzuHuYc005gzEkkx5giiNEO+OKm/SFXTSZ9PKtfIQzUPvCn/YqzU455gE4/ 1.1935 +Dizin/YrrkM7dnaCPANQUHXRFg/cADjd+uSmkQXG1e6D8eOmADaY+WAoFollLzrRw51flxNty5Yp 1.1936 +obiPefmIA5xFYVPSdGc3Ja390XNcFHjONR/2N4K3fbJlPlPoetN5sy35zf10pBBLYgGjbmt/DJMd 1.1937 +1mmqp+Mw2zZuoW2ttrG/ZE6s1Gk3y1CUgYhDt/PIZbJ+JaybMwd6adQdYOI7ja6RxF5VPvglG2gP 1.1938 +w8PEEruzTzEdqYyFjABGMqSu/anBh0KLAAqEsn+HjuSOR08PvTk61uD+OWrdBbbxB1CEOheXajzy 1.1939 +EjgRvvzGjiO/IrRQjx6J0PFUMpnlNk8MP+slepUv/Dn2ygAFMVHsyji7lkOGNTYwn/nE3hKCJW3r 1.1940 +kfoyueozLOIMnNO7LRzelYv+gxODWosROu1u5KatjnzyYIPeUpCdBPPBl/EadH9RV0NeyS3n0L21 1.1941 +dNuh3g8Rsw+hqT59H4YYjvkt3LI+DeBeamhY6OH9tuUUltfGOLLWPraqmkL7QnuwsxK2ZpWiYxmn 1.1942 +ONH4otYLaAzucWPyB/apThSyv3vqxJyYkAXKg7sgvbkNdINWOGHA5UpcOZpQOnxTTaPfzeWtTMFo 1.1943 +gJEdYrXDr7baYRTZcEpvHthXY3exudj040ZvGsyOTDkGIkCFGL2Bnl0INTjgCv+idyJxdkPO8du/ 1.1944 +no3F2w8/wb9v5EewoFjzOBZ/g9HF27yEbSUX7dJtCljAUfF+Ma8VFkYSNDqh4Isn0Fu78MiLpyG6 1.1945 +ssQvKbEKUmAybbni204ARZ4gFbI37oGpl4DfpqCr5YQaB7FvLQb6JdJge40L1oUc6JbRslqlaCac 1.1946 +4EiziJeD87O3px8+nUbVHTK2+Tlwgid+HhZORx8Nl3gMNhb2yazGJ1eOv/yDTIsed1nvNU29DO41 1.1947 +RQjbkcLuL/kmjdjuKeISAwai2MzzWYQtgdO5RK9ag/88craV99p3z7girOFIH541Tjw+BmqIX9r6 1.1948 +ZwANqY+eE/UkhOIp1orx42jQb4HHgiLa8OfpzXruBsR10Q9NsI1pM+uh392qwCXTWcOznER4Hdtl 1.1949 +MHWgaRKr1XTm1gd+zIS+CAWUGx1vyEVcp5WQGWylaG9PN1KAgndL+lhCmFXYilGdG0Vn0nW8UU7u 1.1950 +UazEAEcdUFE9nsNQoBC23j/GN2wGsNZQ1FwCDdAJUdo25U5XVc+WLMG8EyLq9eQbrJPspZvGoynM 1.1951 +g/LGeNb4rzBP9BYZo2tZ6fnzg+Ho8kWT4EDB6JlX0DsrwNi5bLIHGrN4+vTpQPzH/U4PoxKleX4D 1.1952 +3hjA7nVWzun1FoOtJ2dXq+vQmzcR8ONsKS/hwRUFze3zOqOI5I6utCDS/jUwQlyb0DKjad8yxxyr 1.1953 +K/l8mVvwOZU2GD9nCV13hBElicpW3xqF0SYjTcSSoBjCWM2SJOToBKzHJq+xFg+ji5pf5B1wfIJg 1.1954 +xvgWD8Z4h71Ex5LyZi33WHSOxYAADyiljEejYmaqRgM8JxcbjebkLEuqpozkuXtmqq8AqOwtRpqv 1.1955 +RLxGyTDzaBHDKev0WLVxrPOdLOptVPLZpRtnbM2SX9+HO7A2SFq+WBhM4aFZpFkuy5kxp7hiySyp 1.1956 +HDCmHcLhznR5E1mfKOhBaQDqnazC3Eq0ffsHuy4uph/p+HjfjKSzhip7IRbHhOKslVcYRc34FH2y 1.1957 +hLR8a76MYJQPFM3WnoA3lviDjqViDYF3b4dbzlhn+j4OTttoLukAOHQHlFWQlh09HeFcPGbhM9Nu 1.1958 +uUUDP7QzJ9xuk7Kq43Sir32YoJ82sefpGk9bBrezwNN6K+Db5+D47uuMfXAcTHIN0hMzbk1FxrFY 1.1959 +6MhE5FaW+UVYRY5e3iH7SuBTIGXmE1MPbWJHl5ZdbaGpTtV0VDyCemaKl7Y45KZqplNw4mI+pvQm 1.1960 +U+6wxXn2M0fp6grxWgxfjsVha+czKzZ4kxMg+2Qe+q4YdYOpOMEAM8f2vRji9bEYvhiLP+6AHm0Z 1.1961 +4OjQHaG9j21B2Ark5dWjyZgmUyJb2JfCfn9fncMImp5xHF21yd8l03dEpX9vUYkrBHWi8ot2onJr 1.1962 +7K371s7HRzJcgeJYJHK+/0QhCTXSjW7ezuCEHxbQ79kcLV073lTUUOHcFDYj60YPOhrRuM12EFOU 1.1963 +rtUX1++irmHDae8cMGkyrVRFe8scpjFq9FpEBQCTvqM0/IZ3u8B7TQrXP9t6xKqLACzYngiCrvTk 1.1964 +A7OmYSOo9zqCj9IA9zCKCPEwtVEUrmQ9QkRCugeHmOhZ6xDb4fjfnXm4xGDbUWgHy2+/2YWnK5i9 1.1965 +RR09C7q70sITWVte0Sy3+fQH5jxG6ev6VQLjQGlEB5xVc1UluZlHmL3Md9DkNot5hZdB0sk0msRU 1.1966 +um4Tb6X51i/0Yyh2QMlksBbgSdULPEi+pbstTxQlveEVNd8cvhibymAGpCfwMnr5TF8BSd3M5Qe+ 1.1967 +jz3Wezd4qfsdRv/mAEsqv7d91dnN0LSOW3dB+YOFFD0bRRNLh8Yw3V8H0qxZLPDOxIaY7FvbC0De 1.1968 +g7czBT/HXH6ag8MGG9KoD11XYzTSu021bRHg+03GNsl5UNdGkSLSu4Rtm/LcpTgfLQq6V78FwRAC 1.1969 +cv4y5jfoCtbFkQ2xGZuCJ59DN5sTP9VNb90Z2xM0ttVNuGv63H/X3HWLwM7cJDN05u7Xl7o00H23 1.1970 +W9E+GnB4QxPiQSUSjcbvNyauHRjrHJr+CL3+IPndTjjTLWblPjAmYwfj/cSeGntj9lfxzP2OCWH7 1.1971 +fCGzW07c62y0pt2xGW2Of4inwMkv+NzeMEAZTXPNgbxfohv2JpwjO5HX12oS4+2OE9pkUz5XZ/dk 1.1972 +tm3v6XI+GauN2W3hpUUAwnCTzrx1k+uBMUBX8i3TnA7l3E4jaGhKGnaykFUyZ5Ogt3YALuKIKfU3 1.1973 +gXhOIx6kEgPdqi6LEnbDA30XMefp9KU2N0BNAG8VqxuDuukx1lfTkmKl5DBTgsxx2laSDxCBjXjH 1.1974 +NEwm9h3wyvPmmoVkbJlBZvVKlnHVXDHkZwQksOlqRqCic1xcJzzXSGWLS1zEEssbDlIYILPfn8HG 1.1975 +0ttU77hXYWS13cPZiXrokO9jrmxwjJHh4uTOXi/oXms1p6utXe/QNmu4zl6pBMtg7sojHaljZfxW 1.1976 +39/Fd8xyJB/9S4d/QN7dyks/C92qM/ZuLRrOM1chdC9swhsDyDj33cPY4YDujYutDbAd39cXllE6 1.1977 +HuaWxpaK2ifvVTjNaKMmgoQJo/dEkPyigEdGkDz4D4wg6VszwdBofLQe6C0TuCfUxOrBvYKyYQTo 1.1978 +MwEi4QF26wJDYyqHbtJ9kavkbmAvlGZd6VTyGfOAHNm9m4xA8FWTys1Q9q6C2xVB8qWLHn9//vHN 1.1979 +yTnRYnJx8vY/T76npCw8LmnZqgeH2LJ8n6m976V/u+E2nUjTN3iDbc8NsVzDpCF03ndyEHog9Ner 1.1980 +9S1oW5G5r7d16NT9dDsB4run3YK6TWX3Qu74ZbrGxE2faeVpB/opJ9WaX05mgnlkTupYHJqTOPO+ 1.1981 +OTzRMtqJLW9bOCe9tatOtL+qbwHdEvce2SRrWgE8M0H+skcmpmLGBubZQWn/bz4oMxyrDc0NOiCF 1.1982 +M+nc5EiXODKoyv//iZSg7GLc27GjOLZ3c1M7Ph5S9tJ5PPudycgQxCv3G3Tn5wr7XKZbqBAErPD0 1.1983 +PYWMiNF/+kDVph88UeJynwqL91HZXNlfuGbauf1rgkkGlb3vS3GCEh+zQuNFnbqJA7ZPpwM5fXQa 1.1984 +lS+cShbQfAdA50Y8FbA3+kusEKcbEcLGUbtkmBxLdNSX9TnIo910sDe0ei72t5WdumWXQrzY3nDe 1.1985 +quzUPQ65h7qnh6pNcZ9jgTFLc1s9qXhNkPk4U9AFX57zgWfoetsPX28vXxzZwwXkd3ztKBLKJhs4 1.1986 +hv3Sycbceamk052YpRxTuh7u1ZyQsG5x5UBln2Db3qZTkrJl/2PyHBjSwHvfHzIzPbyr9wdtTC3r 1.1987 +HcGUxPCJGtG0nCIejbt9MupOt1FbXSBckPQAIB0VCLAQTEc3OgmiG87yHj7Xu8FpTdfxuidMoSMV 1.1988 +lCzmcwT3ML5fg1+7OxUSP6g7o2j6c4M2B+olB+Fm34FbjbxQyHaT0J56wwdbXACuye7v/+IB/btp 1.1989 +jLb74S6/2rZ62VsHyL4sZr5iZlCLROZxBEYG9OaQtDWWSxhBx2toGjq6DNXMDfkCHT/KpsXLtmmD 1.1990 +Qc7sRHsA1igE/wfVIOdx 1.1991 +""") 1.1992 + 1.1993 +##file activate.sh 1.1994 +ACTIVATE_SH = convert(""" 1.1995 +eJytVVFvokAQfudXTLEPtTlLeo9tvMSmJpq02hSvl7u2wRUG2QR2DSxSe7n/frOACEVNLlceRHa+ 1.1996 +nfl25pvZDswCnoDPQ4QoTRQsENIEPci4CsBMZBq7CAsuLOYqvmYKTTj3YxnBgiXBudGBjUzBZUJI 1.1997 +BXEqgCvweIyuCjeG4eF2F5x14bcB9KQiQQWrjSddI1/oQIx6SYYeoFjzWIoIhYI1izlbhJjkKO7D 1.1998 +M/QEmKfO9O7WeRo/zr4P7pyHwWxkwitcgwpQ5Ej96OX+PmiFwLeVjFUOrNYKaq1Nud3nR2n8nI2m 1.1999 +k9H0friPTGVsUdptaxGrTEfpNVFEskxpXtUkkCkl1UNF9cgLBkx48J4EXyALuBtAwNYIjF5kcmUU 1.2000 +abMKmMq1ULoiRbgsDEkTSsKSGFCJ6Z8vY/2xYiSacmtyAfCDdCNTVZoVF8vSTQOoEwSnOrngBkws 1.2001 +MYGMBMg8/bMBLSYKS7pYEXP0PqT+ZmBT0Xuy+Pplj5yn4aM9nk72JD8/Wi+Gr98sD9eWSMOwkapD 1.2002 +BbUv91XSvmyVkICt2tmXR4tWmrcUCsjWOpw87YidEC8i0gdTSOFhouJUNxR+4NYBG0MftoCTD9F7 1.2003 +2rTtxG3oPwY1b2HncYwhrlmj6Wq924xtGDWqfdNxap+OYxplEurnMVo9RWks+rH8qKEtx7kZT5zJ 1.2004 +4H7oOFclrN6uFe+d+nW2aIUsSgs/42EIPuOhXq+jEo3S6tX6w2ilNkDnIpHCWdEQhFgwj9pkk7FN 1.2005 +l/y5eQvRSIQ5+TrL05lewxWpt/Lbhes5cJF3mLET1MGhcKCF+40tNWnUulxrpojwDo2sObdje3Bz 1.2006 +N3QeHqf3D7OjEXMVV8LN3ZlvuzoWHqiUcNKHtwNd0IbvPGKYYM31nPKCgkUILw3KL+Y8l7aO1ArS 1.2007 +Ad37nIU0fCj5NE5gQCuC5sOSu+UdI2NeXg/lFkQIlFpdWVaWZRfvqGiirC9o6liJ9FXGYrSY9mI1 1.2008 +D/Ncozgn13vJvsznr7DnkJWXsyMH7e42ljdJ+aqNDF1bFnKWFLdj31xtaJYK6EXFgqmV/ymD/ROG 1.2009 ++n8O9H8f5vsGOWXsL1+1k3g= 1.2010 +""") 1.2011 + 1.2012 +##file activate.fish 1.2013 +ACTIVATE_FISH = convert(""" 1.2014 +eJydVW2P2jgQ/s6vmAZQoVpA9/WkqqJaTou0u6x2uZVOVWWZZEKsS+yc7UDpr+84bziQbauLxEvs 1.2015 +eXnsZ56ZIWwTYSAWKUJWGAs7hMJgBEdhEwiMKnSIsBNywUMrDtziPBYmCeBDrFUG7v8HmCTW5n8u 1.2016 +Fu7NJJim81Bl08EQTqqAkEupLOhCgrAQCY2hTU+DQVxIiqgkRNiEBphFEKy+kd1BaFvwFOUBuIxA 1.2017 +oy20BKtAKp3xFMo0QNtCK5mhtMEA6BmSpUELKo38TThwLfguRVNaiRgs0llnEoIR29zfstf18/bv 1.2018 +5T17Wm7vAiiN3ONCzfbfwC3DtWXXDqHfAGX0q6z/bO82j3ebh1VwnbrduwTQbvwcRtesAfMGor/W 1.2019 +L3fs6Xnz8LRlm9fV8/P61sM0LDNwCZjl9gSpCokJRzpryGQ5t8kNGFUt51QjOZGu0Mj35FlYlXEr 1.2020 +yC09EVOp4lEXfF84Lz1qbhBsgl59vDedXI3rTV03xipduSgt9kLytI3XmBp3aV6MPoMQGNUU62T6 1.2021 +uQdeefTy1Hfj10zVHg2pq8fXDoHBiOv94csfXwN49xECqWREy7pwukKfvxdMY2j23vXDPuuxxeE+ 1.2022 +JOdCOhxCE3N44B1ZeSLuZh8Mmkr2wEPAmPfKWHA2uxIRjEopdbQYjDz3BWOf14/scfmwoki1eQvX 1.2023 +ExBdF60Mqh+Y/QcX4uiH4Amwzx79KOVFtbL63sXJbtcvy8/3q5rupmO5CnE91wBviQAhjUUegYpL 1.2024 +vVEbpLt2/W+PklRgq5Ku6mp+rpMhhCo/lXthQTxJ2ysO4Ka0ad97S7VT/n6YXus6fzk3fLnBZW5C 1.2025 +KDC6gSO62QDqgFqLCCtPmjegjnLeAdArtSE8VYGbAJ/aLb+vnQutFhk768E9uRbSxhCMzdgEveYw 1.2026 +IZ5ZqFKl6+kz7UR4U+buqQZXu9SIujrAfD7f0FXpozB4Q0gwp31H9mVTZGGC4b871/wm7lvyDLu1 1.2027 +FUyvTj/yvD66k3UPTs08x1AQQaGziOl0S1qRkPG9COtBTSTWM9NzQ4R64B+Px/l3tDzCgxv5C6Ni 1.2028 +e+QaF9xFWrxx0V/G5uvYQOdiZzvYpQUVQSIsTr1TTghI33GnPbTA7/GCqcE3oE3GZurq4HeQXQD6 1.2029 +32XS1ITj/qLjN72ob0hc5C9bzw8MhfmL 1.2030 +""") 1.2031 + 1.2032 +##file activate.csh 1.2033 +ACTIVATE_CSH = convert(""" 1.2034 +eJx9VG1P2zAQ/u5fcYQKNgTNPtN1WxlIQ4KCUEGaxuQ6yYVYSuzKdhqVX7+zk3bpy5YPUXL3PPfc 1.2035 +ne98DLNCWshliVDV1kGCUFvMoJGugMjq2qQIiVSxSJ1cCofD1BYRnOVGV0CfZ0N2DD91DalQSjsw 1.2036 +tQLpIJMGU1euvPe7QeJlkKzgWixlhnAt4aoUVsLnLBiy5NtbJWQ5THX1ZciYKKWwkOFaE04dUm6D 1.2037 +r/zh7pq/3D7Nnid3/HEy+wFHY/gEJydg0aFaQrBFgz1c5DG1IhTs+UZgsBC2GMFBlaeH+8dZXwcW 1.2038 +VPvCjXdlAvCfQsE7al0+07XjZvrSCUevR5dnkVeKlFYZmUztG4BdzL2u9KyLVabTU0bdfg7a0hgs 1.2039 +cSmUg6UwUiQl2iHrcbcVGNvPCiLOe7+cRwG13z9qRGgx2z6DHjfm/Op2yqeT+xvOLzs0PTKHDz2V 1.2040 +tkckFHoQfQRXoGJAj9el0FyJCmEMhzgMS4sB7KPOE2ExoLcSieYwDvR+cP8cg11gKkVJc2wRcm1g 1.2041 +QhYFlXiTaTfO2ki0fQoiFM4tLuO4aZrhOzqR4dIPcWx17hphMBY+Srwh7RTyN83XOWkcSPh1Pg/k 1.2042 +TXX/jbJTbMtUmcxZ+/bbqOsy82suFQg/BhdSOTRhMNBHlUarCpU7JzBhmkKmRejKOQzayQe6MWoa 1.2043 +n1wqWmuh6LZAaHxcdeqIlVLhIBJdO9/kbl0It2oEXQj+eGjJOuvOIR/YGRqvFhttUB2XTvLXYN2H 1.2044 +37CBdbW2W7j2r2+VsCn0doVWcFG1/4y1VwBjfwAyoZhD 1.2045 +""") 1.2046 + 1.2047 +##file activate.bat 1.2048 +ACTIVATE_BAT = convert(""" 1.2049 +eJx9UdEKgjAUfW6wfxjiIH+hEDKUFHSKLCMI7kNOEkIf9P9pTJ3OLJ/03HPPPed4Es9XS9qqwqgT 1.2050 +PbGKKOdXL4aAFS7A4gvAwgijuiKlqOpGlATS2NeMLE+TjJM9RkQ+SmqAXLrBo1LLIeLdiWlD6jZt 1.2051 +r7VNubWkndkXaxg5GO3UaOOKS6drO3luDDiO5my3iA0YAKGzPRV1ack8cOdhysI0CYzIPzjSiH5X 1.2052 +0QcvC8Lfaj0emsVKYF2rhL5L3fCkVjV76kShi59NHwDniAHzkgDgqBcwOgTMx+gDQQqXCw== 1.2053 +""") 1.2054 + 1.2055 +##file deactivate.bat 1.2056 +DEACTIVATE_BAT = convert(""" 1.2057 +eJxzSE3OyFfIT0vj4ipOLVEI8wwKCXX0iXf1C7Pl4spMU0hJTcvMS01RiPf3cYmHyQYE+fsGhCho 1.2058 +cCkAAUibEkTEVhWLMlUlLk6QGixStlyaeCyJDPHw9/Pw93VFsQguim4ZXAJoIUw5DhX47XUM8UCx 1.2059 +EchHtwsohN1bILUgw61c/Vy4AJYPYm4= 1.2060 +""") 1.2061 + 1.2062 +##file activate.ps1 1.2063 +ACTIVATE_PS = convert(""" 1.2064 +eJylWdmS40Z2fVeE/oHT6rCloNUEAXDThB6wAyQAEjsB29GBjdgXYiWgmC/zgz/Jv+AEWNVd3S2N 1.2065 +xuOKYEUxM+/Jmzfvcm7W//zXf/+wUMOoXtyi1F9kbd0sHH/hFc2iLtrK9b3FrSqyxaVQwr8uhqJd 1.2066 +uHaeg9mqzRdR8/13Pyy8qPLdJh0+LMhi0QCoXxYfFh9WtttEnd34H8p6/f1300KauwrULws39e18 1.2067 +0ZaLNm9rgN/ZVf3h++/e124Vlc0vKsspHy+Yyi5+XbzPhijvCtduoiL/kA1ukWV27n0o7Sb8LIFj 1.2068 +CvWR5GQgUJdp1Pw8TS9+rPy6SDv/+e3d+0+4qw8f3v20+PliV37efEYBAB9FTKC+RHn/Cfxn3rdv 1.2069 +00Fube5O+iyCtHDs9BfPfz3q4sfFv9d91Ljhfy7ei0VO+nVTtdOkv/jpt0l2AX6iG1jXgKnnDuD4 1.2070 +ke2k/i8fzzz5UedkVcP4pwF+Wvz2FJl+3vt598urXf5Y6LNA5WcFOP7r0sW7b9a+W/xcu0Xpv5zk 1.2071 +Kfq3P9Dz9di/fCxS72MXVU1rpx9L4Bxl85Wmn5a+zP76Zuh3pL9ROWr87PN+//GHIl+oOtvn9XSU 1.2072 +qH+p0gQBFnx1uV+JLH5O5zv+PXW+WepXVVHZT0+oQezkIATcIm+ivPV/z5J/+cYj3ir4w0Lx09vC 1.2073 +e5n/y5/Y5LPPfdrqb88ga/PabxZRVfmp39l588m/6u+/e+OpP+dF7n1WZpJ9//Z4v372fDDz9eHB 1.2074 +7Juvs/BLMHzrxL9+9twXpJfhd1/DrpQ5Euu/vlss3wp9HXC/54C/Ld69m6zwdx3tC0d8daSv0V8B 1.2075 +n4b9YYF53sJelJV/ix6LZspw/sJtqyl5LJ5r/23htA1Imfm/gt9R7dqVB1LjhydAX4Gb+zksQF59 1.2076 +9+P7H//U+376afFuvh2/T6P85Xr/5c8C6OXyFY4BGuN+EE0+GeR201b+wkkLN5mmBY5TfMw8ngqL 1.2077 +CztXxCSXKMCYrRIElWkEJlEPYsSOeKBVZCAQTKBhApMwRFQzmCThE0YQu2CdEhgjbgmk9GluHpfR 1.2078 +/hhwJCZhGI5jt5FsAkOrObVyE6g2y1snyhMGFlDY1x+BoHpCMulTj5JYWNAYJmnKpvLxXgmQ8az1 1.2079 +4fUGxxcitMbbhDFcsiAItg04E+OSBIHTUYD1HI4FHH4kMREPknuYRMyhh3AARWMkfhCketqD1CWJ 1.2080 +mTCo/nhUScoQcInB1hpFhIKoIXLo5jLpwFCgsnLCx1QlEMlz/iFEGqzH3vWYcpRcThgWnEKm0QcS 1.2081 +rA8ek2a2IYYeowUanOZOlrbWSJUC4c7y2EMI3uJPMnMF/SSXdk6E495VLhzkWHps0rOhKwqk+xBI 1.2082 +DhJirhdUCTamMfXz2Hy303hM4DFJ8QL21BcPBULR+gcdYxoeiDqOFSqpi5B5PUISfGg46gFZBPo4 1.2083 +jdh8lueaWuVSMTURfbAUnLINr/QYuuYoMQV6l1aWxuZVTjlaLC14UzqZ+ziTGDzJzhiYoPLrt3uI 1.2084 +tXkVR47kAo09lo5BD76CH51cTt1snVpMOttLhY93yxChCQPI4OBecS7++h4p4Bdn4H97bJongtPk 1.2085 +s9gQnXku1vzsjjmX4/o4YUDkXkjHwDg5FXozU0fW4y5kyeYW0uJWlh536BKr0kMGjtzTkng6Ep62 1.2086 +uTWnQtiIqKnEsx7e1hLtzlXs7Upw9TwEnp0t9yzCGgUJIZConx9OHJArLkRYW0dW42G9OeR5Nzwk 1.2087 +yk1mX7du5RGHT7dka7N3AznmSif7y6tuKe2N1Al/1TUPRqH6E2GLVc27h9IptMLkCKQYRqPQJgzV 1.2088 +2m6WLsSipS3v3b1/WmXEYY1meLEVIU/arOGVkyie7ZsH05ZKpjFW4cpY0YkjySpSExNG2TS8nnJx 1.2089 +nrQmWh2WY3cP1eISP9wbaVK35ZXc60yC3VN/j9n7UFoK6zvjSTE2+Pvz6Mx322rnftfP8Y0XKIdv 1.2090 +Qd7AfK0nexBTMqRiErvCMa3Hegpfjdh58glW2oNMsKeAX8x6YJLZs9K8/ozjJkWL+JmECMvhQ54x 1.2091 +9rsTHwcoGrDi6Y4I+H7yY4/rJVPAbYymUH7C2D3uiUS3KQ1nrCAUkE1dJMneDQIJMQQx5SONxoEO 1.2092 +OEn1/Ig1eBBUeEDRuOT2WGGGE4bNypBLFh2PeIg3bEbg44PHiqNDbGIQm50LW6MJU62JHCGBrmc9 1.2093 +2F7WBJrrj1ssnTAK4sxwRgh5LLblhwNAclv3Gd+jC/etCfyfR8TMhcWQz8TBIbG8IIyAQ81w2n/C 1.2094 +mHWAwRzxd3WoBY7BZnsqGOWrOCKwGkMMNfO0Kci/joZgEocLjNnzgcmdehPHJY0FudXgsr+v44TB 1.2095 +I3jnMGnsK5veAhgi9iXGifkHMOC09Rh9cAw9sQ0asl6wKMk8mpzFYaaDSgG4F0wisQDDBRpjCINg 1.2096 +FIxhlhQ31xdSkkk6odXZFpTYOQpOOgw9ugM2cDQ+2MYa7JsEirGBrOuxsQy5nPMRdYjsTJ/j1iNw 1.2097 +FeSt1jY2+dd5yx1/pzZMOQXUIDcXeAzR7QlDRM8AMkUldXOmGmvYXPABjxqkYKO7VAY6JRU7kpXr 1.2098 ++Epu2BU3qFFXClFi27784LrDZsJwbNlDw0JzhZ6M0SMXE4iBHehCpHVkrQhpTFn2dsvsZYkiPEEB 1.2099 +GSEAwdiur9LS1U6P2U9JhGp4hnFpJo4FfkdJHcwV6Q5dV1Q9uNeeu7rV8PAjwdFg9RLtroifOr0k 1.2100 +uOiRTo/obNPhQIf42Fr4mtThWoSjitEdAmFW66UCe8WFjPk1YVNpL9srFbond7jrLg8tqAasIMpy 1.2101 +zkH0SY/6zVAwJrEc14zt14YRXdY+fcJ4qOd2XKB0/Kghw1ovd11t2o+zjt+txndo1ZDZ2T+uMVHT 1.2102 +VSXhedBAHoJIID9xm6wPQI3cXY+HR7vxtrJuCKh6kbXaW5KkVeJsdsjqsYsOwYSh0w5sMbu7LF8J 1.2103 +5T7U6LJdiTx+ca7RKlulGgS5Z1JSU2Llt32cHFipkaurtBrvNX5UtvNZjkufZ/r1/XyLl6yOpytL 1.2104 +Km8Fn+y4wkhlqZP5db0rooqy7xdL4wxzFVTX+6HaxuQJK5E5B1neSSovZ9ALB8091dDbbjVxhWNY 1.2105 +Ve5hn1VnI9OF0wpvaRm7SZuC1IRczwC7GnkhPt3muHV1YxUJfo+uh1sYnJy+vI0ZwuPV2uqWJYUH 1.2106 +bmBsi1zmFSxHrqwA+WIzLrHkwW4r+bad7xbOzJCnKIa3S3YvrzEBK1Dc0emzJW+SqysQfdEDorQG 1.2107 +9ZJlbQzEHQV8naPaF440YXzJk/7vHGK2xwuP+Gc5xITxyiP+WQ4x18oXHjFzCBy9kir1EFTAm0Zq 1.2108 +LYwS8MpiGhtfxiBRDXpxDWxk9g9Q2fzPPAhS6VFDAc/aiNGatUkPtZIStZFQ1qD0IlJa/5ZPAi5J 1.2109 +ySp1ETDomZMnvgiysZSBfMikrSDte/K5lqV6iwC5q7YN9I1dBZXUytDJNqU74MJsUyNNLAPopWK3 1.2110 +tzmLkCiDyl7WQnj9sm7Kd5kzgpoccdNeMw/6zPVB3pUwMgi4C7hj4AMFAf4G27oXH8NNT9zll/sK 1.2111 +S6wVlQwazjxWKWy20ZzXb9ne8ngGalPBWSUSj9xkc1drsXkZ8oOyvYT3e0rnYsGwx85xZB9wKeKg 1.2112 +cJKZnamYwiaMymZvzk6wtDUkxmdUg0mPad0YHtvzpjEfp2iMxvORhnx0kCVLf5Qa43WJsVoyfEyI 1.2113 +pzmf8ruM6xBr7dnBgzyxpqXuUPYaKahOaz1LrxNkS/Q3Ae5AC+xl6NbxAqXXlzghZBZHmOrM6Y6Y 1.2114 +ctAkltwlF7SKEsShjVh7QHuxMU0a08/eiu3x3M+07OijMcKFFltByXrpk8w+JNnZpnp3CfgjV1Ax 1.2115 +gUYCnWwYow42I5wHCcTzLXK0hMZN2DrPM/zCSqe9jRSlJnr70BPE4+zrwbk/xVIDHy2FAQyHoomT 1.2116 +Tt5jiM68nBQut35Y0qLclLiQrutxt/c0OlSqXAC8VrxW97lGoRWzhOnifE2zbF05W4xuyhg7JTUL 1.2117 +aqJ7SWDywhjlal0b+NLTpERBgnPW0+Nw99X2Ws72gOL27iER9jgzj7Uu09JaZ3n+hmCjjvZpjNst 1.2118 +vOWWTbuLrg+/1ltX8WpPauEDEvcunIgTxuMEHweWKCx2KQ9DU/UKdO/3za4Szm2iHYL+ss9AAttm 1.2119 +gZHq2pkUXFbV+FiJCKrpBms18zH75vax5jSo7FNunrVWY3Chvd8KKnHdaTt/6ealwaA1x17yTlft 1.2120 +8VBle3nAE+7R0MScC3MJofNCCkA9PGKBgGMYEwfB2QO5j8zUqa8F/EkWKCzGQJ5EZ05HTly1B01E 1.2121 +z813G5BY++RZ2sxbQS8ZveGPJNabp5kXAeoign6Tlt5+L8i5ZquY9+S+KEUHkmYMRFBxRrHnbl2X 1.2122 +rVemKnG+oB1yd9+zT+4c43jQ0wWmQRR6mTCkY1q3VG05Y120ZzKOMBe6Vy7I5Vz4ygPB3yY4G0FP 1.2123 +8RxiMx985YJPXsgRU58EuHj75gygTzejP+W/zKGe78UQN3yOJ1aMQV9hFH+GAfLRsza84WlPLAI/ 1.2124 +9G/5JdcHftEfH+Y3/fHUG7/o8bv98dzzy3e8S+XCvgqB+VUf7sH0yDHpONdbRE8tAg9NWOzcTJ7q 1.2125 +TuAxe/AJ07c1Rs9okJvl1/0G60qvbdDzz5zO0FuPFQIHNp9y9Bd1CufYVx7dB26mAxwa8GMNrN/U 1.2126 +oGbNZ3EQ7inLzHy5tRg9AXJrN8cB59cCUBeCiVO7zKM0jU0MamhnRThkg/NMmBOGb6StNeD9tDfA 1.2127 +7czsAWopDdnGoXUHtA+s/k0vNPkBcxEI13jVd/axp85va3LpwGggXXWw12Gwr/JGAH0b8CPboiZd 1.2128 +QO1l0mk/UHukud4C+w5uRoNzpCmoW6GbgbMyaQNkga2pQINB18lOXOCJzSWPFOhZcwzdgrsQnne7 1.2129 +nvjBi+7cP2BbtBeDOW5uOLGf3z94FasKIguOqJl+8ss/6Kumns4cuWbqq5592TN/RNIbn5Qo6qbi 1.2130 +O4F0P9txxPAwagqPlftztO8cWBzdN/jz3b7GD6JHYP/Zp4ToAMaA74M+EGSft3hEGMuf8EwjnTk/ 1.2131 +nz/P7SLipB/ogQ6xNX0fDqNncMCfHqGLCMM0ZzFa+6lPJYQ5p81vW4HkCvidYf6kb+P/oB965g8K 1.2132 +C6uR0rdjX1DNKc5pOSTquI8uQ6KXxYaKBn+30/09tK4kMpJPgUIQkbENEPbuezNPPje2Um83SgyX 1.2133 +GTCJb6MnGVIpgncdQg1qz2bvPfxYD9fewCXDomx9S+HQJuX6W3VAL+v5WZMudRQZk9ZdOk6GIUtC 1.2134 +PqEb/uwSIrtR7/edzqgEdtpEwq7p2J5OQV+RLrmtTvFwFpf03M/VrRyTZ73qVod7v7Jh2Dwe5J25 1.2135 +JqFOU2qEu1sP+CRotklediycKfLjeIZzjJQsvKmiGSNQhxuJpKa+hoWUizaE1PuIRGzJqropwgVB 1.2136 +oo1hr870MZLgnXF5ZIpr6mF0L8aSy2gVnTAuoB4WEd4d5NPVC9TMotYXERKlTcwQ2KiB/C48AEfH 1.2137 +Qbyq4CN8xTFnTvf/ebOc3isnjD95s0QF0nx9s+y+zMmz782xL0SgEmRpA3x1w1Ff9/74xcxKEPdS 1.2138 +IEFTz6GgU0+BK/UZ5Gwbl4gZwycxEw+Kqa5QmMkh4OzgzEVPnDAiAOGBFaBW4wkDmj1G4RyElKgj 1.2139 +NlLCq8zsp085MNh/+R4t1Q8yxoSv8PUpTt7izZwf2BTHZZ3pIZpUIpuLkL1nNL6sYcHqcKm237wp 1.2140 +T2+RCjgXweXd2Zp7ZM8W6dG5bZsqo0nrJBTx8EC0+CQQdzEGnabTnkzofu1pYkWl4E7XSniECdxy 1.2141 +vLYavPMcL9LW5SToJFNnos+uqweOHriUZ1ntIYZUonc7ltEQ6oTRtwOHNwez2sVREskHN+bqG3ua 1.2142 +eaEbJ8XpyO8CeD9QJc8nbLP2C2R3A437ISUNyt5Yd0TbDNcl11/DSsOzdbi/VhCC0KE6v1vqVNkq 1.2143 +45ZnG6fiV2NwzInxCNth3BwL0+8814jE6+1W1EeWtpWbSZJOJNYXmWRXa7vLnAljE692eHjZ4y5u 1.2144 +y1u63De0IzKca7As48Z3XshVF+3XiLNz0JIMh/JOpbiNLlMi672uO0wYzOCZjRxcxj3D+gVenGIE 1.2145 +MvFUGGXuRps2RzMcgWIRolHXpGUP6sMsQt1hspUBnVKUn/WQj2u6j3SXd9Xz0QtEzoM7qTu5y7gR 1.2146 +q9gNNsrlEMLdikBt9bFvBnfbUIh6voTw7eDsyTmPKUvF0bHqWLbHe3VRHyRZnNeSGKsB73q66Vsk 1.2147 +taxWYmwz1tYVFG/vOQhlM0gUkyvIab3nv2caJ1udU1F3pDMty7stubTE4OJqm0i0ECfrJIkLtraC 1.2148 +HwRWKzlqpfhEIqYH09eT9WrOhQyt8YEoyBlnXtAT37WHIQ03TIuEHbnRxZDdLun0iok9PUC79prU 1.2149 +m5beZzfQUelEXnhzb/pIROKx3F7qCttYIFGh5dXNzFzID7u8vKykA8Uejf7XXz//S4nKvW//ofS/ 1.2150 +QastYw== 1.2151 +""") 1.2152 + 1.2153 +##file distutils-init.py 1.2154 +DISTUTILS_INIT = convert(""" 1.2155 +eJytV1uL4zYUfvevOE0ottuMW9q3gVDa3aUMXXbLMlDKMBiNrSTqOJKRlMxkf33PkXyRbGe7Dw2E 1.2156 +UXTu37lpxLFV2oIyifAncxmOL0xLIfcG+gv80x9VW6maw7o/CANSWWBwFtqeWMPlGY6qPjV8A0bB 1.2157 +C4eKSTgZ5LRgFeyErMEeOBhbN+Ipgeizhjtnhkn7DdyjuNLPoCS0l/ayQTG0djwZC08cLXozeMss 1.2158 +aG5EzQ0IScpnWtHSTXuxByV/QCmxE7y+eS0uxWeoheaVVfqSJHiU7Mhhi6gULbOHorshkrEnKxpT 1.2159 +0n3A8Y8SMpuwZx6aoix3ouFlmW8gHRSkeSJ2g7hU+kiHLDaQw3bmRDaTGfTnty7gPm0FHbIBg9U9 1.2160 +oh1kZzAFLaue2R6htPCtAda2nGlDSUJ4PZBgCJBGVcwKTAMz/vJiLD+Oin5Z5QlvDPdulC6EsiyE 1.2161 +NFzb7McNTKJzbJqzphx92VKRFY1idenzmq3K0emRcbWBD0ryqc4NZGmKOOOX9Pz5x+/l27tP797c 1.2162 +f/z0d+4NruGNai8uAM0bfsYaw8itFk8ny41jsfpyO+BWlpqfhcG4yxLdi/0tQqoT4a8Vby382mt8 1.2163 +p7XSo7aWGdPBc+b6utaBmCQ7rQKQoWtAuthQCiold2KfJIPTT8xwg9blPumc+YDZC/wYGdAyHpJk 1.2164 +vUbHbHWAp5No6pK/WhhLEWrFjUwtPEv1Agf8YmnsuXUQYkeZoHm8ogP16gt2uHoxcEMdf2C6pmbw 1.2165 +hUMsWGhanboh4IzzmsIpWs134jVPqD/c74bZHdY69UKKSn/+KfVhxLgUlToemayLMYQOqfEC61bh 1.2166 +cbhwaqoGUzIyZRFHPmau5juaWqwRn3mpWmoEA5nhzS5gog/5jbcFQqOZvmBasZtwYlG93k5GEiyw 1.2167 +buHhMWLjDarEGpMGB2LFs5nIJkhp/nUmZneFaRth++lieJtHepIvKgx6PJqIlD9X2j6pG1i9x3pZ 1.2168 +5bHuCPFiirGHeO7McvoXkz786GaKVzC9DSpnOxJdc4xm6NSVq7lNEnKdVlnpu9BNYoKX2Iq3wvgh 1.2169 +gGEUM66kK6j4NiyoneuPLSwaCWDxczgaolEWpiMyDVDb7dNuLAbriL8ig8mmeju31oNvQdpnvEPC 1.2170 +1vAXbWacGRVrGt/uXN/gU0CDDwgooKRrHfTBb1/s9lYZ8ZqOBU0yLvpuP6+K9hLFsvIjeNhBi0KL 1.2171 +MlOuWRn3FRwx5oHXjl0YImUx0+gLzjGchrgzca026ETmYJzPD+IpuKzNi8AFn048Thd63OdD86M6 1.2172 +84zE8yQm0VqXdbbgvub2pKVnS76icBGdeTHHXTKspUmr4NYo/furFLKiMdQzFjHJNcdAnMhltBJK 1.2173 +0/IKX3DVFqvPJ2dLE7bDBkH0l/PJ29074+F0CsGYOxsb7U3myTUncYfXqnLLfa6sJybX4g+hmcjO 1.2174 +kMRBfA1JellfRRKJcyRpxdS4rIl6FdmQCWjo/o9Qz7yKffoP4JHjOvABcRn4CZIT2RH4jnxmfpVG 1.2175 +qgLaAvQBNfuO6X0/Ux02nb4FKx3vgP+XnkX0QW9pLy/NsXgdN24dD3LxO2Nwil7Zlc1dqtP3d7/h 1.2176 +kzp1/+7hGBuY4pk0XD/0Ao/oTe/XGrfyM773aB7iUhgkpy+dwAMalxMP0DrBcsVw/6p25+/hobP9 1.2177 +GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ= 1.2178 +""") 1.2179 + 1.2180 +##file distutils.cfg 1.2181 +DISTUTILS_CFG = convert(""" 1.2182 +eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH 1.2183 +xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg 1.2184 +9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q= 1.2185 +""") 1.2186 + 1.2187 +##file activate_this.py 1.2188 +ACTIVATE_THIS = convert(""" 1.2189 +eJyNU01v2zAMvetXEB4K21jmDOstQA4dMGCHbeihlyEIDMWmG62yJEiKE//7kXKdpN2KzYBt8euR 1.2190 +fKSyLPs8wiEo8wh4wqZTGou4V6Hm0wJa1cSiTkJdr8+GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe 1.2191 +5a3p0cRKiAe2NtLADikftnDco0ko/SFEVgEZ8aRC5GLux7i3BpSJ6J1H+i7A2CjiHq9z7JRZuuQq 1.2192 +siwTIvpxJYCeuWaBpwZdhB+yxy/eWz+ZvVSU8C4E9FFZkyxFsvCT/ZzL8gcz9aXVE14Yyp2M+2W0 1.2193 +y7n5mp0qN+avKXvbsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCZN9UzlJr+/e/iab8WfqsmPI6pWeUPd 1.2194 +FrMsd4H/55poeO9n54COhUs+sZNEzNtg/wanpjpuqHJaxs76HtZryI/K3H7KJ/KDIhqcbJ7kI4ar 1.2195 +XL+sMgXnX0D+Te2Iy5xdP8yueSlQB/x/ED2BTAtyE3K4SYUN6AMNfbO63f4lBW3bUJPbTL+mjSxS 1.2196 +PyRfJkZRgj+VbFv+EzHFi5pKwUEepa4JslMnwkowSRCXI+m5XvEOvtuBrxHdhLalG0JofYBok6qj 1.2197 +YdN2dEngUlbC4PG60M1WEN0piu7Nq7on0mgyyUw3iV1etLo6r/81biWdQ9MWHFaePWZYaq+nmp+t 1.2198 +s3az+sj7eA0jfgPfeoN1 1.2199 +""") 1.2200 + 1.2201 +MH_MAGIC = 0xfeedface 1.2202 +MH_CIGAM = 0xcefaedfe 1.2203 +MH_MAGIC_64 = 0xfeedfacf 1.2204 +MH_CIGAM_64 = 0xcffaedfe 1.2205 +FAT_MAGIC = 0xcafebabe 1.2206 +BIG_ENDIAN = '>' 1.2207 +LITTLE_ENDIAN = '<' 1.2208 +LC_LOAD_DYLIB = 0xc 1.2209 +maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint') 1.2210 + 1.2211 + 1.2212 +class fileview(object): 1.2213 + """ 1.2214 + A proxy for file-like objects that exposes a given view of a file. 1.2215 + Modified from macholib. 1.2216 + """ 1.2217 + 1.2218 + def __init__(self, fileobj, start=0, size=maxint): 1.2219 + if isinstance(fileobj, fileview): 1.2220 + self._fileobj = fileobj._fileobj 1.2221 + else: 1.2222 + self._fileobj = fileobj 1.2223 + self._start = start 1.2224 + self._end = start + size 1.2225 + self._pos = 0 1.2226 + 1.2227 + def __repr__(self): 1.2228 + return '<fileview [%d, %d] %r>' % ( 1.2229 + self._start, self._end, self._fileobj) 1.2230 + 1.2231 + def tell(self): 1.2232 + return self._pos 1.2233 + 1.2234 + def _checkwindow(self, seekto, op): 1.2235 + if not (self._start <= seekto <= self._end): 1.2236 + raise IOError("%s to offset %d is outside window [%d, %d]" % ( 1.2237 + op, seekto, self._start, self._end)) 1.2238 + 1.2239 + def seek(self, offset, whence=0): 1.2240 + seekto = offset 1.2241 + if whence == os.SEEK_SET: 1.2242 + seekto += self._start 1.2243 + elif whence == os.SEEK_CUR: 1.2244 + seekto += self._start + self._pos 1.2245 + elif whence == os.SEEK_END: 1.2246 + seekto += self._end 1.2247 + else: 1.2248 + raise IOError("Invalid whence argument to seek: %r" % (whence,)) 1.2249 + self._checkwindow(seekto, 'seek') 1.2250 + self._fileobj.seek(seekto) 1.2251 + self._pos = seekto - self._start 1.2252 + 1.2253 + def write(self, bytes): 1.2254 + here = self._start + self._pos 1.2255 + self._checkwindow(here, 'write') 1.2256 + self._checkwindow(here + len(bytes), 'write') 1.2257 + self._fileobj.seek(here, os.SEEK_SET) 1.2258 + self._fileobj.write(bytes) 1.2259 + self._pos += len(bytes) 1.2260 + 1.2261 + def read(self, size=maxint): 1.2262 + assert size >= 0 1.2263 + here = self._start + self._pos 1.2264 + self._checkwindow(here, 'read') 1.2265 + size = min(size, self._end - here) 1.2266 + self._fileobj.seek(here, os.SEEK_SET) 1.2267 + bytes = self._fileobj.read(size) 1.2268 + self._pos += len(bytes) 1.2269 + return bytes 1.2270 + 1.2271 + 1.2272 +def read_data(file, endian, num=1): 1.2273 + """ 1.2274 + Read a given number of 32-bits unsigned integers from the given file 1.2275 + with the given endianness. 1.2276 + """ 1.2277 + res = struct.unpack(endian + 'L' * num, file.read(num * 4)) 1.2278 + if len(res) == 1: 1.2279 + return res[0] 1.2280 + return res 1.2281 + 1.2282 + 1.2283 +def mach_o_change(path, what, value): 1.2284 + """ 1.2285 + Replace a given name (what) in any LC_LOAD_DYLIB command found in 1.2286 + the given binary with a new name (value), provided it's shorter. 1.2287 + """ 1.2288 + 1.2289 + def do_macho(file, bits, endian): 1.2290 + # Read Mach-O header (the magic number is assumed read by the caller) 1.2291 + cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6) 1.2292 + # 64-bits header has one more field. 1.2293 + if bits == 64: 1.2294 + read_data(file, endian) 1.2295 + # The header is followed by ncmds commands 1.2296 + for n in range(ncmds): 1.2297 + where = file.tell() 1.2298 + # Read command header 1.2299 + cmd, cmdsize = read_data(file, endian, 2) 1.2300 + if cmd == LC_LOAD_DYLIB: 1.2301 + # The first data field in LC_LOAD_DYLIB commands is the 1.2302 + # offset of the name, starting from the beginning of the 1.2303 + # command. 1.2304 + name_offset = read_data(file, endian) 1.2305 + file.seek(where + name_offset, os.SEEK_SET) 1.2306 + # Read the NUL terminated string 1.2307 + load = file.read(cmdsize - name_offset).decode() 1.2308 + load = load[:load.index('\0')] 1.2309 + # If the string is what is being replaced, overwrite it. 1.2310 + if load == what: 1.2311 + file.seek(where + name_offset, os.SEEK_SET) 1.2312 + file.write(value.encode() + '\0'.encode()) 1.2313 + # Seek to the next command 1.2314 + file.seek(where + cmdsize, os.SEEK_SET) 1.2315 + 1.2316 + def do_file(file, offset=0, size=maxint): 1.2317 + file = fileview(file, offset, size) 1.2318 + # Read magic number 1.2319 + magic = read_data(file, BIG_ENDIAN) 1.2320 + if magic == FAT_MAGIC: 1.2321 + # Fat binaries contain nfat_arch Mach-O binaries 1.2322 + nfat_arch = read_data(file, BIG_ENDIAN) 1.2323 + for n in range(nfat_arch): 1.2324 + # Read arch header 1.2325 + cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5) 1.2326 + do_file(file, offset, size) 1.2327 + elif magic == MH_MAGIC: 1.2328 + do_macho(file, 32, BIG_ENDIAN) 1.2329 + elif magic == MH_CIGAM: 1.2330 + do_macho(file, 32, LITTLE_ENDIAN) 1.2331 + elif magic == MH_MAGIC_64: 1.2332 + do_macho(file, 64, BIG_ENDIAN) 1.2333 + elif magic == MH_CIGAM_64: 1.2334 + do_macho(file, 64, LITTLE_ENDIAN) 1.2335 + 1.2336 + assert(len(what) >= len(value)) 1.2337 + do_file(open(path, 'r+b')) 1.2338 + 1.2339 + 1.2340 +if __name__ == '__main__': 1.2341 + main() 1.2342 + 1.2343 +## TODO: 1.2344 +## Copy python.exe.manifest 1.2345 +## Monkeypatch distutils.sysconfig