KanonConductor
changeset 12:427a87821423 centos5-support
refactoring for CentOS5.x support.
author | chris |
---|---|
date | Wed, 09 Mar 2011 18:15:30 +0900 |
parents | 6524a9f7a133 |
children | d48ffe357575 |
files | kanon-setup pkglist.rhel pkglist.rhel6 resource/virtualenv.py |
diffstat | 4 files changed, 1722 insertions(+), 54 deletions(-) [+] |
line diff
1.1 --- a/kanon-setup Mon Mar 07 23:58:42 2011 +0900 1.2 +++ b/kanon-setup Wed Mar 09 18:15:30 2011 +0900 1.3 @@ -9,8 +9,14 @@ 1.4 APACHE_USER=www-data 1.5 elif [ -f /etc/redhat-release ] 1.6 then 1.7 - OS='rhel' 1.8 APACHE_USER=apache 1.9 + CHK=`egrep "CentOS release 5|Red Hat Enterprise Linux .* 5" /etc/redhat-release` 1.10 + if [ "$CHK" != '' ] 1.11 + then 1.12 + OS='rhel5' 1.13 + else 1.14 + OS='rhel6' 1.15 + fi 1.16 else 1.17 echo "サポートされていないOSです。" 1.18 echo "現在サポートされいているOSは、" 1.19 @@ -49,14 +55,19 @@ 1.20 fi 1.21 1.22 ### install ubuntu package 1.23 -if [ "$OS" = 'debian' ] 1.24 -then 1.25 - apt-get update 1.26 - apt-get -y install `cat pkglist.debian` 1.27 -elif [ "$OS" = 'rhel' ] 1.28 -then 1.29 - yum -y install `cat pkglist.rhel` 1.30 -fi 1.31 +case $OS in 1.32 + debian) 1.33 + apt-get update 1.34 + apt-get -y install `cat pkglist.debian` 1.35 + ;; 1.36 + rhel6) 1.37 + yum -y install `cat pkglist.rhel6` 1.38 + ;; 1.39 + rhel5) 1.40 + ;; 1.41 + *) 1.42 + ;; 1.43 +esac 1.44 1.45 ### install files 1.46 cp -fr opt/* /opt 1.47 @@ -64,8 +75,8 @@ 1.48 1.49 1.50 ### setup configuration 1.51 -export PYTHONPATH=/opt/kanon/lib/python2.6:/opt/kanon/lib/python2.6/site-packages 1.52 -cp resource/dot.pydistutils.cfg ~/.pydistutils.cfg 1.53 +python resource/virtualenv.py /opt/kanon 1.54 +source /opt/kanon/bin/activate 1.55 1.56 ## setup sitecustomize for python 1.57 if [ -f /etc/python2.6/sitecustomize.py ] 1.58 @@ -78,18 +89,18 @@ 1.59 fi 1.60 1.61 ### install python components 1.62 -easy_install --prefix $KANON_OPT http://svn.edgewall.org/repos/genshi/tags/0.6.0/ 1.63 -easy_install --prefix $KANON_OPT http://ftp.edgewall.com/pub/babel/Babel-0.9.5.zip 1.64 -easy_install --prefix $KANON_OPT http://www.i-act.co.jp/project/products/downloads/Trac-0.12.2.ja1.zip 1.65 -easy_install --prefix $KANON_OPT xlrd 1.66 -easy_install --prefix $KANON_OPT https://github.com/hvr/trac-git-plugin/zipball/v0.12.0.5 1.67 +easy_install http://svn.edgewall.org/repos/genshi/tags/0.6.0/ 1.68 +easy_install http://ftp.edgewall.com/pub/babel/Babel-0.9.5.zip 1.69 +easy_install http://www.i-act.co.jp/project/products/downloads/Trac-0.12.2.ja1.zip 1.70 +easy_install xlrd 1.71 +easy_install https://github.com/hvr/trac-git-plugin/zipball/v0.12.0.5 1.72 # bzr co lp:trac-bzr /tmp/trac-bzr-install 1.73 #easy_install --prefix /opt/kanon /tmp/trac-bzr-install 1.74 #rm -fr /tmp/trac-bzr-install 1.75 1.76 1.77 ### install trac plugins 1.78 -easy_install --prefix $KANON_OPT http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin 1.79 +easy_install http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin 1.80 1.81 #resource/pluginsディレクトリのプラグインをインストール 1.82 pushd . 1.83 @@ -117,32 +128,38 @@ 1.84 1.85 1.86 ### setup apache and restart 1.87 -if [ "$OS" = 'debian' ] 1.88 -then 1.89 - cp resource/trac_hook.py /usr/lib/python2.6/dist-packages/bzrlib/plugins 1.90 - if [ ! -f /etc/apache2/sites-available/kanon ] 1.91 - then 1.92 - cp resource/httpd.conf /etc/apache2/sites-available/kanon 1.93 - fi 1.94 - a2enmod expires 1.95 - a2enmod auth_digest 1.96 - a2enmod dav_fs 1.97 - a2ensite kanon 1.98 - service apache2 stop 1.99 - service apache2 start 1.100 -elif [ "$OS" = 'rhel' ] 1.101 -then 1.102 - mkdir -p /usr/lib/python2.6/site-packages/bzrlib/plugin 1.103 - cp resource/trac_hook.py /usr/lib/python2.6/site-packages/bzrlib/plugin 1.104 - if [ ! -f /etc/httpd/conf.d/kanon.conf ] 1.105 - then 1.106 - cp resource/httpd.conf /etc/httpd/conf.d/kanon.conf 1.107 - fi 1.108 - echo 0 > /selinux/enforce 1.109 - echo "SELinuxが無効化されました" 1.110 - service httpd stop 1.111 - service httpd start 1.112 -fi 1.113 +case $OS in 1.114 + debian) 1.115 + cp resource/trac_hook.py /usr/lib/python2.6/dist-packages/bzrlib/plugins 1.116 + if [ ! -f /etc/apache2/sites-available/kanon ] 1.117 + then 1.118 + cp resource/httpd.conf /etc/apache2/sites-available/kanon 1.119 + fi 1.120 + a2enmod expires 1.121 + a2enmod auth_digest 1.122 + a2enmod dav_fs 1.123 + a2ensite kanon 1.124 + service apache2 stop 1.125 + service apache2 start 1.126 + ;; 1.127 + rhel6) 1.128 + mkdir -p /usr/lib/python2.6/site-packages/bzrlib/plugin 1.129 + cp resource/trac_hook.py /usr/lib/python2.6/site-packages/bzrlib/plugin 1.130 + if [ ! -f /etc/httpd/conf.d/kanon.conf ] 1.131 + then 1.132 + cp resource/httpd.conf /etc/httpd/conf.d/kanon.conf 1.133 + fi 1.134 + echo 0 > /selinux/enforce 1.135 + echo "SELinuxが無効化されました" 1.136 + service httpd stop 1.137 + service httpd start 1.138 + ;; 1.139 + rhel5) 1.140 + ;; 1.141 + *) 1.142 + ;; 1.143 +esac 1.144 + 1.145 1.146 # データディレクトリが存在しない場合作成 1.147 if [ ! -d "$KANON_VAR/trac" ]
2.1 --- a/pkglist.rhel Mon Mar 07 23:58:42 2011 +0900 2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 2.3 @@ -1,11 +0,0 @@ 2.4 -httpd 2.5 -python-setuptools 2.6 -python-pygments 2.7 -sqlite 2.8 -mod_dav_svn 2.9 -mod_wsgi 2.10 -subversion 2.11 -mercurial 2.12 -bzr 2.13 -gcc 2.14 -git
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/pkglist.rhel6 Wed Mar 09 18:15:30 2011 +0900 3.3 @@ -0,0 +1,11 @@ 3.4 +httpd 3.5 +python-setuptools 3.6 +python-pygments 3.7 +sqlite 3.8 +mod_dav_svn 3.9 +mod_wsgi 3.10 +subversion 3.11 +mercurial 3.12 +bzr 3.13 +gcc 3.14 +git
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/resource/virtualenv.py Wed Mar 09 18:15:30 2011 +0900 4.3 @@ -0,0 +1,1651 @@ 4.4 +#!/usr/bin/env python 4.5 +"""Create a "virtual" Python installation 4.6 +""" 4.7 + 4.8 +virtualenv_version = "1.5.1" 4.9 + 4.10 +import sys 4.11 +import os 4.12 +import optparse 4.13 +import re 4.14 +import shutil 4.15 +import logging 4.16 +import tempfile 4.17 +import distutils.sysconfig 4.18 +try: 4.19 + import subprocess 4.20 +except ImportError, e: 4.21 + if sys.version_info <= (2, 3): 4.22 + print 'ERROR: %s' % e 4.23 + print 'ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.' 4.24 + print 'If you copy subprocess.py from a newer version of Python this script will probably work' 4.25 + sys.exit(101) 4.26 + else: 4.27 + raise 4.28 +try: 4.29 + set 4.30 +except NameError: 4.31 + from sets import Set as set 4.32 + 4.33 +join = os.path.join 4.34 +py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1]) 4.35 + 4.36 +is_jython = sys.platform.startswith('java') 4.37 +is_pypy = hasattr(sys, 'pypy_version_info') 4.38 + 4.39 +if is_pypy: 4.40 + expected_exe = 'pypy-c' 4.41 +elif is_jython: 4.42 + expected_exe = 'jython' 4.43 +else: 4.44 + expected_exe = 'python' 4.45 + 4.46 + 4.47 +REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath', 4.48 + 'fnmatch', 'locale', 'encodings', 'codecs', 4.49 + 'stat', 'UserDict', 'readline', 'copy_reg', 'types', 4.50 + 're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile', 4.51 + 'zlib'] 4.52 + 4.53 +REQUIRED_FILES = ['lib-dynload', 'config'] 4.54 + 4.55 +if sys.version_info[:2] >= (2, 6): 4.56 + REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc']) 4.57 +if sys.version_info[:2] >= (2, 7): 4.58 + REQUIRED_MODULES.extend(['_weakrefset']) 4.59 +if sys.version_info[:2] <= (2, 3): 4.60 + REQUIRED_MODULES.extend(['sets', '__future__']) 4.61 +if is_pypy: 4.62 + # these are needed to correctly display the exceptions that may happen 4.63 + # during the bootstrap 4.64 + REQUIRED_MODULES.extend(['traceback', 'linecache']) 4.65 + 4.66 +class Logger(object): 4.67 + 4.68 + """ 4.69 + Logging object for use in command-line script. Allows ranges of 4.70 + levels, to avoid some redundancy of displayed information. 4.71 + """ 4.72 + 4.73 + DEBUG = logging.DEBUG 4.74 + INFO = logging.INFO 4.75 + NOTIFY = (logging.INFO+logging.WARN)/2 4.76 + WARN = WARNING = logging.WARN 4.77 + ERROR = logging.ERROR 4.78 + FATAL = logging.FATAL 4.79 + 4.80 + LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] 4.81 + 4.82 + def __init__(self, consumers): 4.83 + self.consumers = consumers 4.84 + self.indent = 0 4.85 + self.in_progress = None 4.86 + self.in_progress_hanging = False 4.87 + 4.88 + def debug(self, msg, *args, **kw): 4.89 + self.log(self.DEBUG, msg, *args, **kw) 4.90 + def info(self, msg, *args, **kw): 4.91 + self.log(self.INFO, msg, *args, **kw) 4.92 + def notify(self, msg, *args, **kw): 4.93 + self.log(self.NOTIFY, msg, *args, **kw) 4.94 + def warn(self, msg, *args, **kw): 4.95 + self.log(self.WARN, msg, *args, **kw) 4.96 + def error(self, msg, *args, **kw): 4.97 + self.log(self.WARN, msg, *args, **kw) 4.98 + def fatal(self, msg, *args, **kw): 4.99 + self.log(self.FATAL, msg, *args, **kw) 4.100 + def log(self, level, msg, *args, **kw): 4.101 + if args: 4.102 + if kw: 4.103 + raise TypeError( 4.104 + "You may give positional or keyword arguments, not both") 4.105 + args = args or kw 4.106 + rendered = None 4.107 + for consumer_level, consumer in self.consumers: 4.108 + if self.level_matches(level, consumer_level): 4.109 + if (self.in_progress_hanging 4.110 + and consumer in (sys.stdout, sys.stderr)): 4.111 + self.in_progress_hanging = False 4.112 + sys.stdout.write('\n') 4.113 + sys.stdout.flush() 4.114 + if rendered is None: 4.115 + if args: 4.116 + rendered = msg % args 4.117 + else: 4.118 + rendered = msg 4.119 + rendered = ' '*self.indent + rendered 4.120 + if hasattr(consumer, 'write'): 4.121 + consumer.write(rendered+'\n') 4.122 + else: 4.123 + consumer(rendered) 4.124 + 4.125 + def start_progress(self, msg): 4.126 + assert not self.in_progress, ( 4.127 + "Tried to start_progress(%r) while in_progress %r" 4.128 + % (msg, self.in_progress)) 4.129 + if self.level_matches(self.NOTIFY, self._stdout_level()): 4.130 + sys.stdout.write(msg) 4.131 + sys.stdout.flush() 4.132 + self.in_progress_hanging = True 4.133 + else: 4.134 + self.in_progress_hanging = False 4.135 + self.in_progress = msg 4.136 + 4.137 + def end_progress(self, msg='done.'): 4.138 + assert self.in_progress, ( 4.139 + "Tried to end_progress without start_progress") 4.140 + if self.stdout_level_matches(self.NOTIFY): 4.141 + if not self.in_progress_hanging: 4.142 + # Some message has been printed out since start_progress 4.143 + sys.stdout.write('...' + self.in_progress + msg + '\n') 4.144 + sys.stdout.flush() 4.145 + else: 4.146 + sys.stdout.write(msg + '\n') 4.147 + sys.stdout.flush() 4.148 + self.in_progress = None 4.149 + self.in_progress_hanging = False 4.150 + 4.151 + def show_progress(self): 4.152 + """If we are in a progress scope, and no log messages have been 4.153 + shown, write out another '.'""" 4.154 + if self.in_progress_hanging: 4.155 + sys.stdout.write('.') 4.156 + sys.stdout.flush() 4.157 + 4.158 + def stdout_level_matches(self, level): 4.159 + """Returns true if a message at this level will go to stdout""" 4.160 + return self.level_matches(level, self._stdout_level()) 4.161 + 4.162 + def _stdout_level(self): 4.163 + """Returns the level that stdout runs at""" 4.164 + for level, consumer in self.consumers: 4.165 + if consumer is sys.stdout: 4.166 + return level 4.167 + return self.FATAL 4.168 + 4.169 + def level_matches(self, level, consumer_level): 4.170 + """ 4.171 + >>> l = Logger() 4.172 + >>> l.level_matches(3, 4) 4.173 + False 4.174 + >>> l.level_matches(3, 2) 4.175 + True 4.176 + >>> l.level_matches(slice(None, 3), 3) 4.177 + False 4.178 + >>> l.level_matches(slice(None, 3), 2) 4.179 + True 4.180 + >>> l.level_matches(slice(1, 3), 1) 4.181 + True 4.182 + >>> l.level_matches(slice(2, 3), 1) 4.183 + False 4.184 + """ 4.185 + if isinstance(level, slice): 4.186 + start, stop = level.start, level.stop 4.187 + if start is not None and start > consumer_level: 4.188 + return False 4.189 + if stop is not None or stop <= consumer_level: 4.190 + return False 4.191 + return True 4.192 + else: 4.193 + return level >= consumer_level 4.194 + 4.195 + #@classmethod 4.196 + def level_for_integer(cls, level): 4.197 + levels = cls.LEVELS 4.198 + if level < 0: 4.199 + return levels[0] 4.200 + if level >= len(levels): 4.201 + return levels[-1] 4.202 + return levels[level] 4.203 + 4.204 + level_for_integer = classmethod(level_for_integer) 4.205 + 4.206 +def mkdir(path): 4.207 + if not os.path.exists(path): 4.208 + logger.info('Creating %s', path) 4.209 + os.makedirs(path) 4.210 + else: 4.211 + logger.info('Directory %s already exists', path) 4.212 + 4.213 +def copyfile(src, dest, symlink=True): 4.214 + if not os.path.exists(src): 4.215 + # Some bad symlink in the src 4.216 + logger.warn('Cannot find file %s (bad symlink)', src) 4.217 + return 4.218 + if os.path.exists(dest): 4.219 + logger.debug('File %s already exists', dest) 4.220 + return 4.221 + if not os.path.exists(os.path.dirname(dest)): 4.222 + logger.info('Creating parent directories for %s' % os.path.dirname(dest)) 4.223 + os.makedirs(os.path.dirname(dest)) 4.224 + if symlink and hasattr(os, 'symlink'): 4.225 + logger.info('Symlinking %s', dest) 4.226 + os.symlink(os.path.abspath(src), dest) 4.227 + else: 4.228 + logger.info('Copying to %s', dest) 4.229 + if os.path.isdir(src): 4.230 + shutil.copytree(src, dest, True) 4.231 + else: 4.232 + shutil.copy2(src, dest) 4.233 + 4.234 +def writefile(dest, content, overwrite=True): 4.235 + if not os.path.exists(dest): 4.236 + logger.info('Writing %s', dest) 4.237 + f = open(dest, 'wb') 4.238 + f.write(content) 4.239 + f.close() 4.240 + return 4.241 + else: 4.242 + f = open(dest, 'rb') 4.243 + c = f.read() 4.244 + f.close() 4.245 + if c != content: 4.246 + if not overwrite: 4.247 + logger.notify('File %s exists with different content; not overwriting', dest) 4.248 + return 4.249 + logger.notify('Overwriting %s with new content', dest) 4.250 + f = open(dest, 'wb') 4.251 + f.write(content) 4.252 + f.close() 4.253 + else: 4.254 + logger.info('Content %s already in place', dest) 4.255 + 4.256 +def rmtree(dir): 4.257 + if os.path.exists(dir): 4.258 + logger.notify('Deleting tree %s', dir) 4.259 + shutil.rmtree(dir) 4.260 + else: 4.261 + logger.info('Do not need to delete %s; already gone', dir) 4.262 + 4.263 +def make_exe(fn): 4.264 + if hasattr(os, 'chmod'): 4.265 + oldmode = os.stat(fn).st_mode & 07777 4.266 + newmode = (oldmode | 0555) & 07777 4.267 + os.chmod(fn, newmode) 4.268 + logger.info('Changed mode of %s to %s', fn, oct(newmode)) 4.269 + 4.270 +def _find_file(filename, dirs): 4.271 + for dir in dirs: 4.272 + if os.path.exists(join(dir, filename)): 4.273 + return join(dir, filename) 4.274 + return filename 4.275 + 4.276 +def _install_req(py_executable, unzip=False, distribute=False): 4.277 + if not distribute: 4.278 + setup_fn = 'setuptools-0.6c11-py%s.egg' % sys.version[:3] 4.279 + project_name = 'setuptools' 4.280 + bootstrap_script = EZ_SETUP_PY 4.281 + source = None 4.282 + else: 4.283 + setup_fn = None 4.284 + source = 'distribute-0.6.14.tar.gz' 4.285 + project_name = 'distribute' 4.286 + bootstrap_script = DISTRIBUTE_SETUP_PY 4.287 + try: 4.288 + # check if the global Python has distribute installed or plain 4.289 + # setuptools 4.290 + import pkg_resources 4.291 + if not hasattr(pkg_resources, '_distribute'): 4.292 + location = os.path.dirname(pkg_resources.__file__) 4.293 + logger.notify("A globally installed setuptools was found (in %s)" % location) 4.294 + logger.notify("Use the --no-site-packages option to use distribute in " 4.295 + "the virtualenv.") 4.296 + except ImportError: 4.297 + pass 4.298 + 4.299 + search_dirs = file_search_dirs() 4.300 + 4.301 + if setup_fn is not None: 4.302 + setup_fn = _find_file(setup_fn, search_dirs) 4.303 + 4.304 + if source is not None: 4.305 + source = _find_file(source, search_dirs) 4.306 + 4.307 + if is_jython and os._name == 'nt': 4.308 + # Jython's .bat sys.executable can't handle a command line 4.309 + # argument with newlines 4.310 + fd, ez_setup = tempfile.mkstemp('.py') 4.311 + os.write(fd, bootstrap_script) 4.312 + os.close(fd) 4.313 + cmd = [py_executable, ez_setup] 4.314 + else: 4.315 + cmd = [py_executable, '-c', bootstrap_script] 4.316 + if unzip: 4.317 + cmd.append('--always-unzip') 4.318 + env = {} 4.319 + remove_from_env = [] 4.320 + if logger.stdout_level_matches(logger.DEBUG): 4.321 + cmd.append('-v') 4.322 + 4.323 + old_chdir = os.getcwd() 4.324 + if setup_fn is not None and os.path.exists(setup_fn): 4.325 + logger.info('Using existing %s egg: %s' % (project_name, setup_fn)) 4.326 + cmd.append(setup_fn) 4.327 + if os.environ.get('PYTHONPATH'): 4.328 + env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH'] 4.329 + else: 4.330 + env['PYTHONPATH'] = setup_fn 4.331 + else: 4.332 + # the source is found, let's chdir 4.333 + if source is not None and os.path.exists(source): 4.334 + os.chdir(os.path.dirname(source)) 4.335 + # in this case, we want to be sure that PYTHONPATH is unset (not 4.336 + # just empty, really unset), else CPython tries to import the 4.337 + # site.py that it's in virtualenv_support 4.338 + remove_from_env.append('PYTHONPATH') 4.339 + else: 4.340 + logger.info('No %s egg found; downloading' % project_name) 4.341 + cmd.extend(['--always-copy', '-U', project_name]) 4.342 + logger.start_progress('Installing %s...' % project_name) 4.343 + logger.indent += 2 4.344 + cwd = None 4.345 + if project_name == 'distribute': 4.346 + env['DONT_PATCH_SETUPTOOLS'] = 'true' 4.347 + 4.348 + def _filter_ez_setup(line): 4.349 + return filter_ez_setup(line, project_name) 4.350 + 4.351 + if not os.access(os.getcwd(), os.W_OK): 4.352 + cwd = tempfile.mkdtemp() 4.353 + if source is not None and os.path.exists(source): 4.354 + # the current working dir is hostile, let's copy the 4.355 + # tarball to a temp dir 4.356 + target = os.path.join(cwd, os.path.split(source)[-1]) 4.357 + shutil.copy(source, target) 4.358 + try: 4.359 + call_subprocess(cmd, show_stdout=False, 4.360 + filter_stdout=_filter_ez_setup, 4.361 + extra_env=env, 4.362 + remove_from_env=remove_from_env, 4.363 + cwd=cwd) 4.364 + finally: 4.365 + logger.indent -= 2 4.366 + logger.end_progress() 4.367 + if os.getcwd() != old_chdir: 4.368 + os.chdir(old_chdir) 4.369 + if is_jython and os._name == 'nt': 4.370 + os.remove(ez_setup) 4.371 + 4.372 +def file_search_dirs(): 4.373 + here = os.path.dirname(os.path.abspath(__file__)) 4.374 + dirs = ['.', here, 4.375 + join(here, 'virtualenv_support')] 4.376 + if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv': 4.377 + # Probably some boot script; just in case virtualenv is installed... 4.378 + try: 4.379 + import virtualenv 4.380 + except ImportError: 4.381 + pass 4.382 + else: 4.383 + dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support')) 4.384 + return [d for d in dirs if os.path.isdir(d)] 4.385 + 4.386 +def install_setuptools(py_executable, unzip=False): 4.387 + _install_req(py_executable, unzip) 4.388 + 4.389 +def install_distribute(py_executable, unzip=False): 4.390 + _install_req(py_executable, unzip, distribute=True) 4.391 + 4.392 +_pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I) 4.393 +def install_pip(py_executable): 4.394 + filenames = [] 4.395 + for dir in file_search_dirs(): 4.396 + filenames.extend([join(dir, fn) for fn in os.listdir(dir) 4.397 + if _pip_re.search(fn)]) 4.398 + filenames = [(os.path.basename(filename).lower(), i, filename) for i, filename in enumerate(filenames)] 4.399 + filenames.sort() 4.400 + filenames = [filename for basename, i, filename in filenames] 4.401 + if not filenames: 4.402 + filename = 'pip' 4.403 + else: 4.404 + filename = filenames[-1] 4.405 + easy_install_script = 'easy_install' 4.406 + if sys.platform == 'win32': 4.407 + easy_install_script = 'easy_install-script.py' 4.408 + cmd = [py_executable, join(os.path.dirname(py_executable), easy_install_script), filename] 4.409 + if filename == 'pip': 4.410 + logger.info('Installing pip from network...') 4.411 + else: 4.412 + logger.info('Installing %s' % os.path.basename(filename)) 4.413 + logger.indent += 2 4.414 + def _filter_setup(line): 4.415 + return filter_ez_setup(line, 'pip') 4.416 + try: 4.417 + call_subprocess(cmd, show_stdout=False, 4.418 + filter_stdout=_filter_setup) 4.419 + finally: 4.420 + logger.indent -= 2 4.421 + 4.422 +def filter_ez_setup(line, project_name='setuptools'): 4.423 + if not line.strip(): 4.424 + return Logger.DEBUG 4.425 + if project_name == 'distribute': 4.426 + for prefix in ('Extracting', 'Now working', 'Installing', 'Before', 4.427 + 'Scanning', 'Setuptools', 'Egg', 'Already', 4.428 + 'running', 'writing', 'reading', 'installing', 4.429 + 'creating', 'copying', 'byte-compiling', 'removing', 4.430 + 'Processing'): 4.431 + if line.startswith(prefix): 4.432 + return Logger.DEBUG 4.433 + return Logger.DEBUG 4.434 + for prefix in ['Reading ', 'Best match', 'Processing setuptools', 4.435 + 'Copying setuptools', 'Adding setuptools', 4.436 + 'Installing ', 'Installed ']: 4.437 + if line.startswith(prefix): 4.438 + return Logger.DEBUG 4.439 + return Logger.INFO 4.440 + 4.441 +def main(): 4.442 + parser = optparse.OptionParser( 4.443 + version=virtualenv_version, 4.444 + usage="%prog [OPTIONS] DEST_DIR") 4.445 + 4.446 + parser.add_option( 4.447 + '-v', '--verbose', 4.448 + action='count', 4.449 + dest='verbose', 4.450 + default=0, 4.451 + help="Increase verbosity") 4.452 + 4.453 + parser.add_option( 4.454 + '-q', '--quiet', 4.455 + action='count', 4.456 + dest='quiet', 4.457 + default=0, 4.458 + help='Decrease verbosity') 4.459 + 4.460 + parser.add_option( 4.461 + '-p', '--python', 4.462 + dest='python', 4.463 + metavar='PYTHON_EXE', 4.464 + help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 ' 4.465 + 'interpreter to create the new environment. The default is the interpreter that ' 4.466 + 'virtualenv was installed with (%s)' % sys.executable) 4.467 + 4.468 + parser.add_option( 4.469 + '--clear', 4.470 + dest='clear', 4.471 + action='store_true', 4.472 + help="Clear out the non-root install and start from scratch") 4.473 + 4.474 + parser.add_option( 4.475 + '--no-site-packages', 4.476 + dest='no_site_packages', 4.477 + action='store_true', 4.478 + help="Don't give access to the global site-packages dir to the " 4.479 + "virtual environment") 4.480 + 4.481 + parser.add_option( 4.482 + '--unzip-setuptools', 4.483 + dest='unzip_setuptools', 4.484 + action='store_true', 4.485 + help="Unzip Setuptools or Distribute when installing it") 4.486 + 4.487 + parser.add_option( 4.488 + '--relocatable', 4.489 + dest='relocatable', 4.490 + action='store_true', 4.491 + help='Make an EXISTING virtualenv environment relocatable. ' 4.492 + 'This fixes up scripts and makes all .pth files relative') 4.493 + 4.494 + parser.add_option( 4.495 + '--distribute', 4.496 + dest='use_distribute', 4.497 + action='store_true', 4.498 + help='Use Distribute instead of Setuptools. Set environ variable ' 4.499 + 'VIRTUALENV_USE_DISTRIBUTE to make it the default ') 4.500 + 4.501 + parser.add_option( 4.502 + '--prompt=', 4.503 + dest='prompt', 4.504 + help='Provides an alternative prompt prefix for this environment') 4.505 + 4.506 + if 'extend_parser' in globals(): 4.507 + extend_parser(parser) 4.508 + 4.509 + options, args = parser.parse_args() 4.510 + 4.511 + global logger 4.512 + 4.513 + if 'adjust_options' in globals(): 4.514 + adjust_options(options, args) 4.515 + 4.516 + verbosity = options.verbose - options.quiet 4.517 + logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)]) 4.518 + 4.519 + if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): 4.520 + env = os.environ.copy() 4.521 + interpreter = resolve_interpreter(options.python) 4.522 + if interpreter == sys.executable: 4.523 + logger.warn('Already using interpreter %s' % interpreter) 4.524 + else: 4.525 + logger.notify('Running virtualenv with interpreter %s' % interpreter) 4.526 + env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true' 4.527 + file = __file__ 4.528 + if file.endswith('.pyc'): 4.529 + file = file[:-1] 4.530 + popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env) 4.531 + raise SystemExit(popen.wait()) 4.532 + 4.533 + if not args: 4.534 + print 'You must provide a DEST_DIR' 4.535 + parser.print_help() 4.536 + sys.exit(2) 4.537 + if len(args) > 1: 4.538 + print 'There must be only one argument: DEST_DIR (you gave %s)' % ( 4.539 + ' '.join(args)) 4.540 + parser.print_help() 4.541 + sys.exit(2) 4.542 + 4.543 + home_dir = args[0] 4.544 + 4.545 + if os.environ.get('WORKING_ENV'): 4.546 + logger.fatal('ERROR: you cannot run virtualenv while in a workingenv') 4.547 + logger.fatal('Please deactivate your workingenv, then re-run this script') 4.548 + sys.exit(3) 4.549 + 4.550 + if 'PYTHONHOME' in os.environ: 4.551 + logger.warn('PYTHONHOME is set. You *must* activate the virtualenv before using it') 4.552 + del os.environ['PYTHONHOME'] 4.553 + 4.554 + if options.relocatable: 4.555 + make_environment_relocatable(home_dir) 4.556 + return 4.557 + 4.558 + create_environment(home_dir, site_packages=not options.no_site_packages, clear=options.clear, 4.559 + unzip_setuptools=options.unzip_setuptools, 4.560 + use_distribute=options.use_distribute, 4.561 + prompt=options.prompt) 4.562 + if 'after_install' in globals(): 4.563 + after_install(options, home_dir) 4.564 + 4.565 +def call_subprocess(cmd, show_stdout=True, 4.566 + filter_stdout=None, cwd=None, 4.567 + raise_on_returncode=True, extra_env=None, 4.568 + remove_from_env=None): 4.569 + cmd_parts = [] 4.570 + for part in cmd: 4.571 + if len(part) > 40: 4.572 + part = part[:30]+"..."+part[-5:] 4.573 + if ' ' in part or '\n' in part or '"' in part or "'" in part: 4.574 + part = '"%s"' % part.replace('"', '\\"') 4.575 + cmd_parts.append(part) 4.576 + cmd_desc = ' '.join(cmd_parts) 4.577 + if show_stdout: 4.578 + stdout = None 4.579 + else: 4.580 + stdout = subprocess.PIPE 4.581 + logger.debug("Running command %s" % cmd_desc) 4.582 + if extra_env or remove_from_env: 4.583 + env = os.environ.copy() 4.584 + if extra_env: 4.585 + env.update(extra_env) 4.586 + if remove_from_env: 4.587 + for varname in remove_from_env: 4.588 + env.pop(varname, None) 4.589 + else: 4.590 + env = None 4.591 + try: 4.592 + proc = subprocess.Popen( 4.593 + cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout, 4.594 + cwd=cwd, env=env) 4.595 + except Exception, e: 4.596 + logger.fatal( 4.597 + "Error %s while executing command %s" % (e, cmd_desc)) 4.598 + raise 4.599 + all_output = [] 4.600 + if stdout is not None: 4.601 + stdout = proc.stdout 4.602 + while 1: 4.603 + line = stdout.readline() 4.604 + if not line: 4.605 + break 4.606 + line = line.rstrip() 4.607 + all_output.append(line) 4.608 + if filter_stdout: 4.609 + level = filter_stdout(line) 4.610 + if isinstance(level, tuple): 4.611 + level, line = level 4.612 + logger.log(level, line) 4.613 + if not logger.stdout_level_matches(level): 4.614 + logger.show_progress() 4.615 + else: 4.616 + logger.info(line) 4.617 + else: 4.618 + proc.communicate() 4.619 + proc.wait() 4.620 + if proc.returncode: 4.621 + if raise_on_returncode: 4.622 + if all_output: 4.623 + logger.notify('Complete output from command %s:' % cmd_desc) 4.624 + logger.notify('\n'.join(all_output) + '\n----------------------------------------') 4.625 + raise OSError( 4.626 + "Command %s failed with error code %s" 4.627 + % (cmd_desc, proc.returncode)) 4.628 + else: 4.629 + logger.warn( 4.630 + "Command %s had error code %s" 4.631 + % (cmd_desc, proc.returncode)) 4.632 + 4.633 + 4.634 +def create_environment(home_dir, site_packages=True, clear=False, 4.635 + unzip_setuptools=False, use_distribute=False, 4.636 + prompt=None): 4.637 + """ 4.638 + Creates a new environment in ``home_dir``. 4.639 + 4.640 + If ``site_packages`` is true (the default) then the global 4.641 + ``site-packages/`` directory will be on the path. 4.642 + 4.643 + If ``clear`` is true (default False) then the environment will 4.644 + first be cleared. 4.645 + """ 4.646 + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) 4.647 + 4.648 + py_executable = os.path.abspath(install_python( 4.649 + home_dir, lib_dir, inc_dir, bin_dir, 4.650 + site_packages=site_packages, clear=clear)) 4.651 + 4.652 + install_distutils(home_dir) 4.653 + 4.654 + if use_distribute or os.environ.get('VIRTUALENV_USE_DISTRIBUTE'): 4.655 + install_distribute(py_executable, unzip=unzip_setuptools) 4.656 + else: 4.657 + install_setuptools(py_executable, unzip=unzip_setuptools) 4.658 + 4.659 + install_pip(py_executable) 4.660 + 4.661 + install_activate(home_dir, bin_dir, prompt) 4.662 + 4.663 +def path_locations(home_dir): 4.664 + """Return the path locations for the environment (where libraries are, 4.665 + where scripts go, etc)""" 4.666 + # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its 4.667 + # prefix arg is broken: http://bugs.python.org/issue3386 4.668 + if sys.platform == 'win32': 4.669 + # Windows has lots of problems with executables with spaces in 4.670 + # the name; this function will remove them (using the ~1 4.671 + # format): 4.672 + mkdir(home_dir) 4.673 + if ' ' in home_dir: 4.674 + try: 4.675 + import win32api 4.676 + except ImportError: 4.677 + print 'Error: the path "%s" has a space in it' % home_dir 4.678 + print 'To handle these kinds of paths, the win32api module must be installed:' 4.679 + print ' http://sourceforge.net/projects/pywin32/' 4.680 + sys.exit(3) 4.681 + home_dir = win32api.GetShortPathName(home_dir) 4.682 + lib_dir = join(home_dir, 'Lib') 4.683 + inc_dir = join(home_dir, 'Include') 4.684 + bin_dir = join(home_dir, 'Scripts') 4.685 + elif is_jython: 4.686 + lib_dir = join(home_dir, 'Lib') 4.687 + inc_dir = join(home_dir, 'Include') 4.688 + bin_dir = join(home_dir, 'bin') 4.689 + elif is_pypy: 4.690 + lib_dir = home_dir 4.691 + inc_dir = join(home_dir, 'include') 4.692 + bin_dir = join(home_dir, 'bin') 4.693 + else: 4.694 + lib_dir = join(home_dir, 'lib', py_version) 4.695 + inc_dir = join(home_dir, 'include', py_version) 4.696 + bin_dir = join(home_dir, 'bin') 4.697 + return home_dir, lib_dir, inc_dir, bin_dir 4.698 + 4.699 + 4.700 +def change_prefix(filename, dst_prefix): 4.701 + prefixes = [sys.prefix] 4.702 + if hasattr(sys, 'real_prefix'): 4.703 + prefixes.append(sys.real_prefix) 4.704 + prefixes = map(os.path.abspath, prefixes) 4.705 + filename = os.path.abspath(filename) 4.706 + for src_prefix in prefixes: 4.707 + if filename.startswith(src_prefix): 4.708 + _, relpath = filename.split(src_prefix, 1) 4.709 + assert relpath[0] == os.sep 4.710 + relpath = relpath[1:] 4.711 + return join(dst_prefix, relpath) 4.712 + assert False, "Filename %s does not start with any of these prefixes: %s" % \ 4.713 + (filename, prefixes) 4.714 + 4.715 +def copy_required_modules(dst_prefix): 4.716 + import imp 4.717 + for modname in REQUIRED_MODULES: 4.718 + if modname in sys.builtin_module_names: 4.719 + logger.info("Ignoring built-in bootstrap module: %s" % modname) 4.720 + continue 4.721 + try: 4.722 + f, filename, _ = imp.find_module(modname) 4.723 + except ImportError: 4.724 + logger.info("Cannot import bootstrap module: %s" % modname) 4.725 + else: 4.726 + if f is not None: 4.727 + f.close() 4.728 + dst_filename = change_prefix(filename, dst_prefix) 4.729 + copyfile(filename, dst_filename) 4.730 + if filename.endswith('.pyc'): 4.731 + pyfile = filename[:-1] 4.732 + if os.path.exists(pyfile): 4.733 + copyfile(pyfile, dst_filename[:-1]) 4.734 + 4.735 + 4.736 +def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear): 4.737 + """Install just the base environment, no distutils patches etc""" 4.738 + if sys.executable.startswith(bin_dir): 4.739 + print 'Please use the *system* python to run this script' 4.740 + return 4.741 + 4.742 + if clear: 4.743 + rmtree(lib_dir) 4.744 + ## FIXME: why not delete it? 4.745 + ## Maybe it should delete everything with #!/path/to/venv/python in it 4.746 + logger.notify('Not deleting %s', bin_dir) 4.747 + 4.748 + if hasattr(sys, 'real_prefix'): 4.749 + logger.notify('Using real prefix %r' % sys.real_prefix) 4.750 + prefix = sys.real_prefix 4.751 + else: 4.752 + prefix = sys.prefix 4.753 + mkdir(lib_dir) 4.754 + fix_lib64(lib_dir) 4.755 + stdlib_dirs = [os.path.dirname(os.__file__)] 4.756 + if sys.platform == 'win32': 4.757 + stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs')) 4.758 + elif sys.platform == 'darwin': 4.759 + stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages')) 4.760 + if hasattr(os, 'symlink'): 4.761 + logger.info('Symlinking Python bootstrap modules') 4.762 + else: 4.763 + logger.info('Copying Python bootstrap modules') 4.764 + logger.indent += 2 4.765 + try: 4.766 + # copy required files... 4.767 + for stdlib_dir in stdlib_dirs: 4.768 + if not os.path.isdir(stdlib_dir): 4.769 + continue 4.770 + for fn in os.listdir(stdlib_dir): 4.771 + if fn != 'site-packages' and os.path.splitext(fn)[0] in REQUIRED_FILES: 4.772 + copyfile(join(stdlib_dir, fn), join(lib_dir, fn)) 4.773 + # ...and modules 4.774 + copy_required_modules(home_dir) 4.775 + finally: 4.776 + logger.indent -= 2 4.777 + mkdir(join(lib_dir, 'site-packages')) 4.778 + import site 4.779 + site_filename = site.__file__ 4.780 + if site_filename.endswith('.pyc'): 4.781 + site_filename = site_filename[:-1] 4.782 + elif site_filename.endswith('$py.class'): 4.783 + site_filename = site_filename.replace('$py.class', '.py') 4.784 + site_filename_dst = change_prefix(site_filename, home_dir) 4.785 + site_dir = os.path.dirname(site_filename_dst) 4.786 + writefile(site_filename_dst, SITE_PY) 4.787 + writefile(join(site_dir, 'orig-prefix.txt'), prefix) 4.788 + site_packages_filename = join(site_dir, 'no-global-site-packages.txt') 4.789 + if not site_packages: 4.790 + writefile(site_packages_filename, '') 4.791 + else: 4.792 + if os.path.exists(site_packages_filename): 4.793 + logger.info('Deleting %s' % site_packages_filename) 4.794 + os.unlink(site_packages_filename) 4.795 + 4.796 + if is_pypy: 4.797 + stdinc_dir = join(prefix, 'include') 4.798 + else: 4.799 + stdinc_dir = join(prefix, 'include', py_version) 4.800 + if os.path.exists(stdinc_dir): 4.801 + copyfile(stdinc_dir, inc_dir) 4.802 + else: 4.803 + logger.debug('No include dir %s' % stdinc_dir) 4.804 + 4.805 + if sys.exec_prefix != prefix: 4.806 + if sys.platform == 'win32': 4.807 + exec_dir = join(sys.exec_prefix, 'lib') 4.808 + elif is_jython: 4.809 + exec_dir = join(sys.exec_prefix, 'Lib') 4.810 + else: 4.811 + exec_dir = join(sys.exec_prefix, 'lib', py_version) 4.812 + for fn in os.listdir(exec_dir): 4.813 + copyfile(join(exec_dir, fn), join(lib_dir, fn)) 4.814 + 4.815 + if is_jython: 4.816 + # Jython has either jython-dev.jar and javalib/ dir, or just 4.817 + # jython.jar 4.818 + for name in 'jython-dev.jar', 'javalib', 'jython.jar': 4.819 + src = join(prefix, name) 4.820 + if os.path.exists(src): 4.821 + copyfile(src, join(home_dir, name)) 4.822 + # XXX: registry should always exist after Jython 2.5rc1 4.823 + src = join(prefix, 'registry') 4.824 + if os.path.exists(src): 4.825 + copyfile(src, join(home_dir, 'registry'), symlink=False) 4.826 + copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'), 4.827 + symlink=False) 4.828 + 4.829 + mkdir(bin_dir) 4.830 + py_executable = join(bin_dir, os.path.basename(sys.executable)) 4.831 + if 'Python.framework' in prefix: 4.832 + if re.search(r'/Python(?:-32|-64)*$', py_executable): 4.833 + # The name of the python executable is not quite what 4.834 + # we want, rename it. 4.835 + py_executable = os.path.join( 4.836 + os.path.dirname(py_executable), 'python') 4.837 + 4.838 + logger.notify('New %s executable in %s', expected_exe, py_executable) 4.839 + if sys.executable != py_executable: 4.840 + ## FIXME: could I just hard link? 4.841 + executable = sys.executable 4.842 + if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'): 4.843 + # Cygwin misreports sys.executable sometimes 4.844 + executable += '.exe' 4.845 + py_executable += '.exe' 4.846 + logger.info('Executable actually exists in %s' % executable) 4.847 + shutil.copyfile(executable, py_executable) 4.848 + make_exe(py_executable) 4.849 + if sys.platform == 'win32' or sys.platform == 'cygwin': 4.850 + pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe') 4.851 + if os.path.exists(pythonw): 4.852 + logger.info('Also created pythonw.exe') 4.853 + shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe')) 4.854 + if is_pypy: 4.855 + # make a symlink python --> pypy-c 4.856 + python_executable = os.path.join(os.path.dirname(py_executable), 'python') 4.857 + logger.info('Also created executable %s' % python_executable) 4.858 + copyfile(py_executable, python_executable) 4.859 + 4.860 + if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe: 4.861 + secondary_exe = os.path.join(os.path.dirname(py_executable), 4.862 + expected_exe) 4.863 + py_executable_ext = os.path.splitext(py_executable)[1] 4.864 + if py_executable_ext == '.exe': 4.865 + # python2.4 gives an extension of '.4' :P 4.866 + secondary_exe += py_executable_ext 4.867 + if os.path.exists(secondary_exe): 4.868 + logger.warn('Not overwriting existing %s script %s (you must use %s)' 4.869 + % (expected_exe, secondary_exe, py_executable)) 4.870 + else: 4.871 + logger.notify('Also creating executable in %s' % secondary_exe) 4.872 + shutil.copyfile(sys.executable, secondary_exe) 4.873 + make_exe(secondary_exe) 4.874 + 4.875 + if 'Python.framework' in prefix: 4.876 + logger.debug('MacOSX Python framework detected') 4.877 + 4.878 + # Make sure we use the the embedded interpreter inside 4.879 + # the framework, even if sys.executable points to 4.880 + # the stub executable in ${sys.prefix}/bin 4.881 + # See http://groups.google.com/group/python-virtualenv/ 4.882 + # browse_thread/thread/17cab2f85da75951 4.883 + original_python = os.path.join( 4.884 + prefix, 'Resources/Python.app/Contents/MacOS/Python') 4.885 + shutil.copy(original_python, py_executable) 4.886 + 4.887 + # Copy the framework's dylib into the virtual 4.888 + # environment 4.889 + virtual_lib = os.path.join(home_dir, '.Python') 4.890 + 4.891 + if os.path.exists(virtual_lib): 4.892 + os.unlink(virtual_lib) 4.893 + copyfile( 4.894 + os.path.join(prefix, 'Python'), 4.895 + virtual_lib) 4.896 + 4.897 + # And then change the install_name of the copied python executable 4.898 + try: 4.899 + call_subprocess( 4.900 + ["install_name_tool", "-change", 4.901 + os.path.join(prefix, 'Python'), 4.902 + '@executable_path/../.Python', 4.903 + py_executable]) 4.904 + except: 4.905 + logger.fatal( 4.906 + "Could not call install_name_tool -- you must have Apple's development tools installed") 4.907 + raise 4.908 + 4.909 + # Some tools depend on pythonX.Y being present 4.910 + py_executable_version = '%s.%s' % ( 4.911 + sys.version_info[0], sys.version_info[1]) 4.912 + if not py_executable.endswith(py_executable_version): 4.913 + # symlinking pythonX.Y > python 4.914 + pth = py_executable + '%s.%s' % ( 4.915 + sys.version_info[0], sys.version_info[1]) 4.916 + if os.path.exists(pth): 4.917 + os.unlink(pth) 4.918 + os.symlink('python', pth) 4.919 + else: 4.920 + # reverse symlinking python -> pythonX.Y (with --python) 4.921 + pth = join(bin_dir, 'python') 4.922 + if os.path.exists(pth): 4.923 + os.unlink(pth) 4.924 + os.symlink(os.path.basename(py_executable), pth) 4.925 + 4.926 + if sys.platform == 'win32' and ' ' in py_executable: 4.927 + # There's a bug with subprocess on Windows when using a first 4.928 + # argument that has a space in it. Instead we have to quote 4.929 + # the value: 4.930 + py_executable = '"%s"' % py_executable 4.931 + cmd = [py_executable, '-c', 'import sys; print sys.prefix'] 4.932 + logger.info('Testing executable with %s %s "%s"' % tuple(cmd)) 4.933 + proc = subprocess.Popen(cmd, 4.934 + stdout=subprocess.PIPE) 4.935 + proc_stdout, proc_stderr = proc.communicate() 4.936 + proc_stdout = os.path.normcase(os.path.abspath(proc_stdout.strip())) 4.937 + if proc_stdout != os.path.normcase(os.path.abspath(home_dir)): 4.938 + logger.fatal( 4.939 + 'ERROR: The executable %s is not functioning' % py_executable) 4.940 + logger.fatal( 4.941 + 'ERROR: It thinks sys.prefix is %r (should be %r)' 4.942 + % (proc_stdout, os.path.normcase(os.path.abspath(home_dir)))) 4.943 + logger.fatal( 4.944 + 'ERROR: virtualenv is not compatible with this system or executable') 4.945 + if sys.platform == 'win32': 4.946 + logger.fatal( 4.947 + 'Note: some Windows users have reported this error when they installed Python for "Only this user". The problem may be resolvable if you install Python "For all users". (See https://bugs.launchpad.net/virtualenv/+bug/352844)') 4.948 + sys.exit(100) 4.949 + else: 4.950 + logger.info('Got sys.prefix result: %r' % proc_stdout) 4.951 + 4.952 + pydistutils = os.path.expanduser('~/.pydistutils.cfg') 4.953 + if os.path.exists(pydistutils): 4.954 + logger.notify('Please make sure you remove any previous custom paths from ' 4.955 + 'your %s file.' % pydistutils) 4.956 + ## FIXME: really this should be calculated earlier 4.957 + return py_executable 4.958 + 4.959 +def install_activate(home_dir, bin_dir, prompt=None): 4.960 + if sys.platform == 'win32' or is_jython and os._name == 'nt': 4.961 + files = {'activate.bat': ACTIVATE_BAT, 4.962 + 'deactivate.bat': DEACTIVATE_BAT} 4.963 + if os.environ.get('OS') == 'Windows_NT' and os.environ.get('OSTYPE') == 'cygwin': 4.964 + files['activate'] = ACTIVATE_SH 4.965 + else: 4.966 + files = {'activate': ACTIVATE_SH} 4.967 + 4.968 + # suppling activate.fish in addition to, not instead of, the 4.969 + # bash script support. 4.970 + files['activate.fish'] = ACTIVATE_FISH 4.971 + 4.972 + # same for csh/tcsh support... 4.973 + files['activate.csh'] = ACTIVATE_CSH 4.974 + 4.975 + 4.976 + 4.977 + files['activate_this.py'] = ACTIVATE_THIS 4.978 + vname = os.path.basename(os.path.abspath(home_dir)) 4.979 + for name, content in files.items(): 4.980 + content = content.replace('__VIRTUAL_PROMPT__', prompt or '') 4.981 + content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname) 4.982 + content = content.replace('__VIRTUAL_ENV__', os.path.abspath(home_dir)) 4.983 + content = content.replace('__VIRTUAL_NAME__', vname) 4.984 + content = content.replace('__BIN_NAME__', os.path.basename(bin_dir)) 4.985 + writefile(os.path.join(bin_dir, name), content) 4.986 + 4.987 +def install_distutils(home_dir): 4.988 + distutils_path = change_prefix(distutils.__path__[0], home_dir) 4.989 + mkdir(distutils_path) 4.990 + ## FIXME: maybe this prefix setting should only be put in place if 4.991 + ## there's a local distutils.cfg with a prefix setting? 4.992 + home_dir = os.path.abspath(home_dir) 4.993 + ## FIXME: this is breaking things, removing for now: 4.994 + #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir 4.995 + writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT) 4.996 + writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False) 4.997 + 4.998 +def fix_lib64(lib_dir): 4.999 + """ 4.1000 + Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y 4.1001 + instead of lib/pythonX.Y. If this is such a platform we'll just create a 4.1002 + symlink so lib64 points to lib 4.1003 + """ 4.1004 + if [p for p in distutils.sysconfig.get_config_vars().values() 4.1005 + if isinstance(p, basestring) and 'lib64' in p]: 4.1006 + logger.debug('This system uses lib64; symlinking lib64 to lib') 4.1007 + assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], ( 4.1008 + "Unexpected python lib dir: %r" % lib_dir) 4.1009 + lib_parent = os.path.dirname(lib_dir) 4.1010 + assert os.path.basename(lib_parent) == 'lib', ( 4.1011 + "Unexpected parent dir: %r" % lib_parent) 4.1012 + copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64')) 4.1013 + 4.1014 +def resolve_interpreter(exe): 4.1015 + """ 4.1016 + If the executable given isn't an absolute path, search $PATH for the interpreter 4.1017 + """ 4.1018 + if os.path.abspath(exe) != exe: 4.1019 + paths = os.environ.get('PATH', '').split(os.pathsep) 4.1020 + for path in paths: 4.1021 + if os.path.exists(os.path.join(path, exe)): 4.1022 + exe = os.path.join(path, exe) 4.1023 + break 4.1024 + if not os.path.exists(exe): 4.1025 + logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe)) 4.1026 + sys.exit(3) 4.1027 + return exe 4.1028 + 4.1029 +############################################################ 4.1030 +## Relocating the environment: 4.1031 + 4.1032 +def make_environment_relocatable(home_dir): 4.1033 + """ 4.1034 + Makes the already-existing environment use relative paths, and takes out 4.1035 + the #!-based environment selection in scripts. 4.1036 + """ 4.1037 + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) 4.1038 + activate_this = os.path.join(bin_dir, 'activate_this.py') 4.1039 + if not os.path.exists(activate_this): 4.1040 + logger.fatal( 4.1041 + 'The environment doesn\'t have a file %s -- please re-run virtualenv ' 4.1042 + 'on this environment to update it' % activate_this) 4.1043 + fixup_scripts(home_dir) 4.1044 + fixup_pth_and_egg_link(home_dir) 4.1045 + ## FIXME: need to fix up distutils.cfg 4.1046 + 4.1047 +OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3], 4.1048 + 'activate', 'activate.bat', 'activate_this.py'] 4.1049 + 4.1050 +def fixup_scripts(home_dir): 4.1051 + # This is what we expect at the top of scripts: 4.1052 + shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir)) 4.1053 + # This is what we'll put: 4.1054 + new_shebang = '#!/usr/bin/env python%s' % sys.version[:3] 4.1055 + activate = "import os; activate_this=os.path.join(os.path.dirname(__file__), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this" 4.1056 + if sys.platform == 'win32': 4.1057 + bin_suffix = 'Scripts' 4.1058 + else: 4.1059 + bin_suffix = 'bin' 4.1060 + bin_dir = os.path.join(home_dir, bin_suffix) 4.1061 + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) 4.1062 + for filename in os.listdir(bin_dir): 4.1063 + filename = os.path.join(bin_dir, filename) 4.1064 + if not os.path.isfile(filename): 4.1065 + # ignore subdirs, e.g. .svn ones. 4.1066 + continue 4.1067 + f = open(filename, 'rb') 4.1068 + lines = f.readlines() 4.1069 + f.close() 4.1070 + if not lines: 4.1071 + logger.warn('Script %s is an empty file' % filename) 4.1072 + continue 4.1073 + if not lines[0].strip().startswith(shebang): 4.1074 + if os.path.basename(filename) in OK_ABS_SCRIPTS: 4.1075 + logger.debug('Cannot make script %s relative' % filename) 4.1076 + elif lines[0].strip() == new_shebang: 4.1077 + logger.info('Script %s has already been made relative' % filename) 4.1078 + else: 4.1079 + logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)' 4.1080 + % (filename, shebang)) 4.1081 + continue 4.1082 + logger.notify('Making script %s relative' % filename) 4.1083 + lines = [new_shebang+'\n', activate+'\n'] + lines[1:] 4.1084 + f = open(filename, 'wb') 4.1085 + f.writelines(lines) 4.1086 + f.close() 4.1087 + 4.1088 +def fixup_pth_and_egg_link(home_dir, sys_path=None): 4.1089 + """Makes .pth and .egg-link files use relative paths""" 4.1090 + home_dir = os.path.normcase(os.path.abspath(home_dir)) 4.1091 + if sys_path is None: 4.1092 + sys_path = sys.path 4.1093 + for path in sys_path: 4.1094 + if not path: 4.1095 + path = '.' 4.1096 + if not os.path.isdir(path): 4.1097 + continue 4.1098 + path = os.path.normcase(os.path.abspath(path)) 4.1099 + if not path.startswith(home_dir): 4.1100 + logger.debug('Skipping system (non-environment) directory %s' % path) 4.1101 + continue 4.1102 + for filename in os.listdir(path): 4.1103 + filename = os.path.join(path, filename) 4.1104 + if filename.endswith('.pth'): 4.1105 + if not os.access(filename, os.W_OK): 4.1106 + logger.warn('Cannot write .pth file %s, skipping' % filename) 4.1107 + else: 4.1108 + fixup_pth_file(filename) 4.1109 + if filename.endswith('.egg-link'): 4.1110 + if not os.access(filename, os.W_OK): 4.1111 + logger.warn('Cannot write .egg-link file %s, skipping' % filename) 4.1112 + else: 4.1113 + fixup_egg_link(filename) 4.1114 + 4.1115 +def fixup_pth_file(filename): 4.1116 + lines = [] 4.1117 + prev_lines = [] 4.1118 + f = open(filename) 4.1119 + prev_lines = f.readlines() 4.1120 + f.close() 4.1121 + for line in prev_lines: 4.1122 + line = line.strip() 4.1123 + if (not line or line.startswith('#') or line.startswith('import ') 4.1124 + or os.path.abspath(line) != line): 4.1125 + lines.append(line) 4.1126 + else: 4.1127 + new_value = make_relative_path(filename, line) 4.1128 + if line != new_value: 4.1129 + logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename)) 4.1130 + lines.append(new_value) 4.1131 + if lines == prev_lines: 4.1132 + logger.info('No changes to .pth file %s' % filename) 4.1133 + return 4.1134 + logger.notify('Making paths in .pth file %s relative' % filename) 4.1135 + f = open(filename, 'w') 4.1136 + f.write('\n'.join(lines) + '\n') 4.1137 + f.close() 4.1138 + 4.1139 +def fixup_egg_link(filename): 4.1140 + f = open(filename) 4.1141 + link = f.read().strip() 4.1142 + f.close() 4.1143 + if os.path.abspath(link) != link: 4.1144 + logger.debug('Link in %s already relative' % filename) 4.1145 + return 4.1146 + new_link = make_relative_path(filename, link) 4.1147 + logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link)) 4.1148 + f = open(filename, 'w') 4.1149 + f.write(new_link) 4.1150 + f.close() 4.1151 + 4.1152 +def make_relative_path(source, dest, dest_is_directory=True): 4.1153 + """ 4.1154 + Make a filename relative, where the filename is dest, and it is 4.1155 + being referred to from the filename source. 4.1156 + 4.1157 + >>> make_relative_path('/usr/share/something/a-file.pth', 4.1158 + ... '/usr/share/another-place/src/Directory') 4.1159 + '../another-place/src/Directory' 4.1160 + >>> make_relative_path('/usr/share/something/a-file.pth', 4.1161 + ... '/home/user/src/Directory') 4.1162 + '../../../home/user/src/Directory' 4.1163 + >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/') 4.1164 + './' 4.1165 + """ 4.1166 + source = os.path.dirname(source) 4.1167 + if not dest_is_directory: 4.1168 + dest_filename = os.path.basename(dest) 4.1169 + dest = os.path.dirname(dest) 4.1170 + dest = os.path.normpath(os.path.abspath(dest)) 4.1171 + source = os.path.normpath(os.path.abspath(source)) 4.1172 + dest_parts = dest.strip(os.path.sep).split(os.path.sep) 4.1173 + source_parts = source.strip(os.path.sep).split(os.path.sep) 4.1174 + while dest_parts and source_parts and dest_parts[0] == source_parts[0]: 4.1175 + dest_parts.pop(0) 4.1176 + source_parts.pop(0) 4.1177 + full_parts = ['..']*len(source_parts) + dest_parts 4.1178 + if not dest_is_directory: 4.1179 + full_parts.append(dest_filename) 4.1180 + if not full_parts: 4.1181 + # Special case for the current directory (otherwise it'd be '') 4.1182 + return './' 4.1183 + return os.path.sep.join(full_parts) 4.1184 + 4.1185 + 4.1186 + 4.1187 +############################################################ 4.1188 +## Bootstrap script creation: 4.1189 + 4.1190 +def create_bootstrap_script(extra_text, python_version=''): 4.1191 + """ 4.1192 + Creates a bootstrap script, which is like this script but with 4.1193 + extend_parser, adjust_options, and after_install hooks. 4.1194 + 4.1195 + This returns a string that (written to disk of course) can be used 4.1196 + as a bootstrap script with your own customizations. The script 4.1197 + will be the standard virtualenv.py script, with your extra text 4.1198 + added (your extra text should be Python code). 4.1199 + 4.1200 + If you include these functions, they will be called: 4.1201 + 4.1202 + ``extend_parser(optparse_parser)``: 4.1203 + You can add or remove options from the parser here. 4.1204 + 4.1205 + ``adjust_options(options, args)``: 4.1206 + You can change options here, or change the args (if you accept 4.1207 + different kinds of arguments, be sure you modify ``args`` so it is 4.1208 + only ``[DEST_DIR]``). 4.1209 + 4.1210 + ``after_install(options, home_dir)``: 4.1211 + 4.1212 + After everything is installed, this function is called. This 4.1213 + is probably the function you are most likely to use. An 4.1214 + example would be:: 4.1215 + 4.1216 + def after_install(options, home_dir): 4.1217 + subprocess.call([join(home_dir, 'bin', 'easy_install'), 4.1218 + 'MyPackage']) 4.1219 + subprocess.call([join(home_dir, 'bin', 'my-package-script'), 4.1220 + 'setup', home_dir]) 4.1221 + 4.1222 + This example immediately installs a package, and runs a setup 4.1223 + script from that package. 4.1224 + 4.1225 + If you provide something like ``python_version='2.4'`` then the 4.1226 + script will start with ``#!/usr/bin/env python2.4`` instead of 4.1227 + ``#!/usr/bin/env python``. You can use this when the script must 4.1228 + be run with a particular Python version. 4.1229 + """ 4.1230 + filename = __file__ 4.1231 + if filename.endswith('.pyc'): 4.1232 + filename = filename[:-1] 4.1233 + f = open(filename, 'rb') 4.1234 + content = f.read() 4.1235 + f.close() 4.1236 + py_exe = 'python%s' % python_version 4.1237 + content = (('#!/usr/bin/env %s\n' % py_exe) 4.1238 + + '## WARNING: This file is generated\n' 4.1239 + + content) 4.1240 + return content.replace('##EXT' 'END##', extra_text) 4.1241 + 4.1242 +##EXTEND## 4.1243 + 4.1244 +##file site.py 4.1245 +SITE_PY = """ 4.1246 +eJzVPP1z2zaWv/OvQOXJUEplOh/dzo5T98ZJnNZ7buJt0mluXY+WkiCJNUWyBGlZe3P3t9/7AECA 4.1247 +pGS77f5wmkwskcDDw8P7xgMGg8FpUchsLtb5vE6lUDIuZytRxNVKiUVeimqVlPPDIi6rLTyd3cRL 4.1248 +qUSVC7VVEbaKguDpH/wET8WnVaIMCvAtrqt8HVfJLE7TrUjWRV5Wci7mdZlkS5FkSZXEafIvaJFn 4.1249 +kXj6xzEIzjMBM08TWYpbWSqAq0S+EJfbapVnYlgXOOfn0V/il6OxULMyKSpoUGqcgSKruAoyKeeA 4.1250 +JrSsFZAyqeShKuQsWSQz23CT1+lcFGk8k+Kf/+SpUdMwDFS+lpuVLKXIABmAKQFWgXjA16QUs3wu 4.1251 +IyFey1mMA/DzhlgBQxvjmikkY5aLNM+WMKdMzqRScbkVw2ldESBCWcxzwCkBDKokTYNNXt6oESwp 4.1252 +rccGHomY2cOfDLMHzBPH73IO4PghC37KkrsxwwbuQXDVitmmlIvkTsQIFn7KOzmb6GfDZCHmyWIB 4.1253 +NMiqETYJGAEl0mR6VNByfKNX6NsjwspyZQxjSESZG/NL6hEF55WIUwVsWxdII0WYv5XTJM6AGtkt 4.1254 +DAcQgaRB3zjzRFV2HJqdyAFAietYgZSslRiu4yQDZv0hnhHaPyfZPN+oEVEAVkuJX2tVufMf9hAA 4.1255 +WjsEGAe4WGY16yxNbmS6HQECnwD7Uqo6rVAg5kkpZ1VeJlIRAEBtK+QdID0WcSk1CZkzjdyOif5E 4.1256 +kyTDhUUBQ4HHl0iSRbKsS5IwsUiAc4Er3n34Ubw9e31++l7zmAHGMrtcA84AhRbawQkGEEe1Ko/S 4.1257 +HAQ6Ci7wj4jncxSyJY4PeDUNju5d6WAIcy+idh9nwYHsenH1MDDHCpQJjRVQv/+GLmO1Avr8zz3r 4.1258 +HQSnu6hCE+dvm1UOMpnFaylWMfMXckbwjYbzbVRUq1fADQrhVEAqhYuDCCYID0ji0myYZ1IUwGJp 4.1259 +kslRABSaUlt/FYEV3ufZIa11ixMAQhlk8NJ5NqIRMwkT7cJ6hfrCNN7SzHSTwK7zOi9JcQD/ZzPS 4.1260 +RWmc3RCOihiKv03lMskyRAh5IQgPQhpY3STAifNIXFAr0gumkQhZe3FLFIkaeAmZDnhS3sXrIpVj 4.1261 +Fl/UrfvVCA0mK2HWOmWOg5YVqVdatWaqvbz3Ivrc4jpCs1qVEoDXU0/oFnk+FlPQ2YRNEa9ZvKpN 4.1262 +TpwT9MgTdUKeoJbQF78DRU+VqtfSvkReAc1CDBUs8jTNN0Cy4yAQ4gAbGaPsMye8hXfwP8DF/1NZ 4.1263 +zVZB4IxkAWtQiPwuUAgETILMNFdrJDxu06zcVjJJxpoiL+eypKEeRuwjRvyBjXGuwfu80kaNp4ur 4.1264 +nK+TClXSVJvMhC1eFlasH1/xvGEaYLkV0cw0bei0xumlxSqeSuOSTOUCJUEv0iu77DBm0DMm2eJK 4.1265 +rNnKwDsgi0zYgvQrFlQ6i0qSEwAwWPjiLCnqlBopZDARw0DrguCvYzTpuXaWgL3ZLAeokNh8z8D+ 4.1266 +AG7/AjHarBKgzwwggIZBLQXLN02qEh2ERh8FvtE3/Xl84NTzhbZNPOQiTlJt5eMsOKeHZ2VJ4juT 4.1267 +BfYaa2IomGFWoWu3zICOKOaDwSAIjDu0VeZrbr9NJtM6QXs3mQRVuT0G7hAo5AFDF+9hojQcv1mU 4.1268 ++RpfW/Q+gj4AvYw9ggNxSYpCso/rMdMrpICrlQvTFM2vw5ECVUlw+ePZu/PPZx/FibhqtNK4rZKu 4.1269 +YcyzLAbOJKUOfNEatlFH0BJ1V4LqS7wDC03rCiaJepMEyriqgf0A9U9lTa9hGjPvZXD2/vT1xdnk 4.1270 +p49nP04+nn86AwTBVMjggKaMFq4Gn09FwN/AWHMVaRMZdHrQg9enH+2DYJKoSbEttvAAbB1wYTmE 4.1271 ++Y5FiA8n2oxOkmyRhyNq/Cv70SesGbTTdHX81bU4ORHhr/FtHAbguDRNeRF/IB7+tC0kdK3gzzBX 4.1272 +oyCYywXw+41EqRg+JWd0xB2AiNAy18bx1zzJzHt67Q1BQjukHoDDZDJLY6Ww8WQSAmmpQ88HOkTs 4.1273 +0SKrD6FjsXW7jjQq+CklLEWGXcb4Xw+K8ZT6IRqMotvFNAIZWc9iJbkVTR/6TSaoKCaToR4QJIh4 4.1274 +HLwclv1QmCaoKMoEnEniFVQcU5Wn+BPho+iRyGA8g6oJF0nHK9FtnNZSDZ1JARGHwxYZUbslijgI 4.1275 +/IIhmL9m6UajNjUNz0AzIF+ag+oqW5TDzwE4GaAjTOSE0RUHPEwzxPRv7N4TDuDnhahjlWpBYZUk 4.1276 +Ls8uxctnLw7Rh4BAb26p4zVHs5hktbQPF7BaS1k5CHOvcEzCMHLpskDlhk+P98NcR3Zluqyw0Etc 4.1277 +ynV+K+eALTKws8riR3oD4TDMYxbDKoIyJSPMSs84azEGfzx7kBY02EC9NUEx62+W/oAjcJkpUB0c 4.1278 +zRKpdajN9qco89sELfx0q1+CgQL1hmbKeBOBs3Aek6EdAg0BrmeGlNrIEBRYWbOXSHgjSFTx80YV 4.1279 +RgTuAnXrNX29yfJNNuHw8wTV5HBkWRcFSzMvNmiW4EC8A8MBSOYQTTVEYyjgZwuUrUNAHqYP0wXK 4.1280 +kkMPgMC6KoqRHFgmvqIpcqiGwyKM0StBwltKNNK3ZgiKbwwxHEj0NrIPjJZASDA5q+CsatBMhrJm 4.1281 +msHADkl8rruIOO7zAbSoGIGhG2po3MjQ7+oYlLO4cJWS0w9t6OfPn5lt1IqSGojYFCeNdntB5i0q 4.1282 +tmAKE9AJxg3iFAmxwQY8SgBTK82a4vCjyAt2gWA9L7Vsg+WGkKqqiuOjo81mE+mQPi+XR2px9Je/ 4.1283 +fv31X5+xTpzPiX9gOo606PxWdETv0I2MvjEW6Fuzci1+TDKfGwnWUJIrRP4f4vddncxzcXw4svoT 4.1284 +ubgxrPi/cT5AgUzMoExloO2gweiJOnwSvVQD8UQM3bbDEXsS2qRaK+ZbXehR5WC7wdOY5XVWhY4i 4.1285 +VeJLsG4QFs/ltF6GdnDPRpofMFWU06HlgcPn14iBzxmGr4wpnqCWILZAi++Q/kdmm5j8Ga0hkLxo 4.1286 +ojoh67Zfixnizh8u79Y7dITGzDBRyB0oEX6TBwugbdyVHPxoZxTtnuOMmo9nCIylDwzzaldwiIJD 4.1287 +uOBajF2pc7gafVSQpg2rZlAwrmoEBQ1u3ZSprcGRjQwRJHo3JsLmhdUtgE6tdJ0Jys0qQAt3nI61 4.1288 +a7OC4wkhD5yI5/REglN73Hn3jJe2TlPKorR41KMKA/YWGu10Dnw5NADGYlD+NOCWelnOP7QWhdeg 4.1289 +B1jOiRdksEWHmfCN6wMODgY97NSx+rt6M437QOAiUfuHASeMT3iAUoEwFUOfcXdxuKUtJ5taCO82 4.1290 +OMRTZpVIotUO2Wrrjl6Z2muXFkmGqtdZo2iW5uAUW6VIfNS8930FClzwcZ8t0wKoydCQw2l0Qs6e 4.1291 +J3+hbocpq2WNwb2b+0CM1oki44ZkWsF/4FVQToESQEBLgmbBPFTI/In9CSJn56u/7GAPS2hkCLfp 4.1292 +Li+kYzA0HPP+QCAZdQYEhCADEnZlkTxH1gYpcJizQJ5sw2u5U7gJRqRAzBwDQloGcKeXXnyDTyLc 4.1293 +dSABRch3lZKF+FIMYPnakvow1f2ncqnJGgydBuQp6HTDiZuKcNIQJ620hM/QfkKC9ieKHDh4Ch6P 4.1294 +m1x32dwwrc2SgK/u622LFChkSpwMRi6q14YwbgL3ixOnRUMsM4hhKG8gbxvFjDQK7HJr0LDgBoy3 4.1295 +5u2x9GM3YYF9h2GuXsj1HYR/YZmoWa5CjG87qQv3o7miSxuL7UUyHcAfbwEGo2sPkkx1+gKTLL9j 4.1296 +kNCDHvZB9yaLWZF5XG6SLCQFpul34i9NBw9LSs/GHX2kaOoIJopZxqN3JQgIbTcegTihJoCgXIZK 4.1297 +e/1dsHunOLBwufvA85qvjl9ed4k73pXgsZ/+pTq7q8pY4WqlvGgsFLhaXfuNShcmF2dbvWGoN5Qx 4.1298 +SihzBUGk+PDxs0BCcC51E28fN/WG4RGbe+fkfQzqoNfuJVdrdsQugAhqRWSUo/DxHPlwZB87uT0T 4.1299 +ewSQRzHMnkUxkDSf/B44+xYKxjicbzNMo7VVBn7g9ddfTXoSoy6SX381uGeUFjH6xH7Y8gTtyLSR 4.1300 +L3qnbbqUMk7J13A6UVIxa3jHtilGrNAp/NNMdt3jdOLHvDcmo4Hfad6JG83ngOgBUXY+/RViVaXT 4.1301 +W7dxklJOHtA4PEQ9Z8Jszhz04+NB2o8ypqTAY3k27o2E1NUzWJiQ4/pRdzraLzo1qd+eeNR8ilh1 4.1302 +UTnQW+jNDpC3Le7u/u2W/V5L/W/SWY8E5M1m0EPAB87B7E7+/58JKyuGppXVqKX1ldyv5w2wB6jD 4.1303 +HW7OHjekOzRvZi2MM8Fyp8RTFNCnYkNb0pTKw40JgDJnP6MHDi6j3th8U5clb0+SnBeyPMT9urHA 4.1304 +ahzjaVCRTxfM0XtZISa22YxSo07tRt6nOkOd7LQzCRs/tV9kV7lJkcjsNimhL2iVYfj9hx/Owi4D 4.1305 +6GGwUz84dx0NlzzcTiHcRzBtqIkTPqYPU+gxXX6/VLVdZZ+gZsvYJCA12bqE7eQdTdzavwb3ZCC8 4.1306 +/UHeh8WIcLaSs5uJpL1lZFPs6uRg3+BrxMRuOfs1PipeUKESzGSW1kgrdvSwwmxRZzNKx1cS7Lku 4.1307 +B8XyENox5nTTIo2XYkid55jq0NxI2ZDbuNTeTlHmWIAo6mR+tEzmQv5WxymGkXKxAFxwr0S/inh4 4.1308 +yniIt7zpzYVpSs7qMqm2QIJY5XqrifbHnYbTLU906CHJuwpMQNwxPxYfcdr4ngk3N+QywaifYMdJ 4.1309 +YpyHHcxeIHIXPYf3WT7BUSdUxzlmpLrbwPQ4aI+QA4ABAIX5D0Y6U+S/kfTK3c+iNXeJilrSI6Ub 4.1310 +2ebkcSCU4Qgja/5NP31GdHlrB5bL3Vgu92O5bGO57MVy6WO53I+lKxK4sDZJYiShL1HSzqL3FmS4 4.1311 +OQ4e5iyerbgd1vdhHR9AFIUJ6IxMcZmrl0nh7SQCQmrb2d+kh02BRcKFg2XOKVcNErkf90x08GgK 4.1312 +lJ3OVK6hO/NUjM+2q8jE73sURVQONKXuLG/zuIojTy6WaT4FsbXojhsAY9GuN+HcXHY7mXI2sWWp 4.1313 +Bpf/9en7D++xOYIamN106oaLiIYFpzJ8GpdL1ZWmJtgogB2ppV/3Qd00wIMHZnJ4lAP+7y0VFCDj 4.1314 +iA1tiOeiAA+Ayn5sM7c4Jgxbz3UVjX7OTM57GydikFWDZlI7iHR6efn29NPpgFJMg/8duAJjaOtL 4.1315 +h4uPaWEbdP03t7mlOPYBoda5lMb4uXPyaN1wxP021oBtub3PrlsPXjzEYPeGpf4s/62UgiUBQkU6 4.1316 +2fgYQj04+PlDYUKHPoYRO9Vh7k4OOyv2nSN7joviiH5fmrs9gL+3hjHGBAigXaihiQyaYKql9K15 4.1317 +3UNRB+gDfb0/HIK1Q692JONT1E6ixwF0KGub7Xb/vH0BNnpKVq/Pvjt/f3H++vL00/eOC4iu3IeP 4.1318 +Ry/E2Q+fBZUjoAFjnyjGnfgKC1/AsLiHWcQ8h381pjfmdcVJSej19uJC7wys8TgD1reizYngOVfN 4.1319 +WGico+Gsp32oy10Qo1QHSM65EaoOoXMlGC+t+cyCynUNLB1HmaKzWuvQS58HMueGaBs1AumDxi4p 4.1320 +GARXNMErqlSuTFRY8o6TPkvTg5S20bYOIaUcVGd32tlvMdl8LzFHneFJ01kr+qvQxTW8jlSRJhDJ 4.1321 +vQqtLOluWI3RMI5+aDdUGa8+Deh0h5F1Q571TizQar0KeW66/6hhtN9qwLBhsLcw70xSNQLV6GIt 4.1322 +lQixEe8chPIOvtql12ugYMFwY6nCRTRMl8DsYwiuxSqBAAJ4cgXWF+MEgNBaCT8BfexkB2SOxQDh 4.1323 +m/X88O+hJojf+pdfeppXZXr4D1FAFCS4ciXsIabb+C0EPpGMxNmHd6OQkaNKUPH3GkvAwSGhLJ8j 4.1324 +7VQuwzu2k6GS6UKXM/j6AF9oP4Fet7qXsih1937XOEQJeKKG5DU8UYZ+IVYXWdhjnMqoBRqr2y1m 4.1325 +eErM3fY2nwPxcSXTVBdEn7+9OAPfEQvuUYJ4n+cMhuN8CW7Z6lovPsXWAoUbuvC6RDYu0YWlTf15 4.1326 +5DXrzcyiyFFvrw7ArhNlP7u9OqnOMk6Ui/YQp82wnJLzCLkZlsOsLHN3txnS2W1GdEfJYcaYXJZU 4.1327 +NelzBnA0PY05MIKICYv6TbKZ9y6TrDJlcmkyA20KihfU6hhEBUmMJ9eI//KM0715qcyBF3hYbMtk 4.1328 +uaowpQ6dIyq2x+Y/nH6+OH9P1esvXja+dw+LjikeGHPpwgnWpWHOA764tWbIW5NJH+fqVwgDdRD8 4.1329 +ab/imogTHqDTj9OL+Kf9ik8cnTjxIM8A1FRdtIUEwwCnW5/0NBLBuNpoGD9u3VmDmQ+GMpJ4wEGX 4.1330 +F7jz6/KjbdkyKJT9MS8fsVexKDQNh6azWwfV/ug5LgrcXJkP+xvB2z4JM58pdL3pvNlVceV+OrKI 4.1331 +hx8Bo25rfwxTk9RpqqfjMNsubqHgVlvaXzInY+q0m2UoykDEodt55DJZvyrWzZkDvdrdDjDxjUbX 4.1332 +SGKvQh/8kg20n+FhYondiVZMRzo7QaYA8xlSHxGpwZNCuwAKhEpOh47kjkdPX3hzdGzC/XPUugss 4.1333 +5PegCHUBKB0syEvgRPjyG7uP/IrQQlV6LELHX8lkltvqJPxsVuhbPvfn2CsDlMpEsSvjbCmHDGts 4.1334 +YH7pE3tHIpa0rccxV0mrWkJzN3iodzsYvCsW/bsnBrMWH3Ta3chtWxv51MEGvccPfAhlvAHtXtTV 4.1335 +kNdq52YBNtdbsMMQkyS/hTvodQ96Ghb6Xb/17OHgh4ll3Etrr1pHW0L7QvuVsxICpkrRZoljhY2H 4.1336 +6BrmxgaeNFZ4YJ/qihH7u+e8kFPl6sJlFFyo3gwHukEr1B/wyRU+uZdQZXRzsEK/m8tbmebgFkHE 4.1337 +hYXvv9rC91FkUx29NUF/BoKX28ttP3r0pkHu2BTno+OkCljIKJPVEWLUm5C5B7kGH1z2X3TQEGc3 4.1338 +5Me++fl8LN68/xH+fy0/QOSD59fG4h+AiXiTlxAB8hlKOtyOpf0Vh3Z5rfCQG0GjzQS+BwBdqkuP 4.1339 +2rhxoc8c+IcNrBYTWGdZrvnyCUCR50jnihsbbirp4bc56tN1Fo0j17c0A/0SybD7AAQeGjjSLaNV 4.1340 +tU5RnTupjGZNrwYX52/O3n88i6o75Hbzc+CkOvwqHZyR3sgtcdNqLOyTWY1Prh2/9nuZFj1urY4M 4.1341 +zWEKjAxFCMFDYaNBvtsgthFAXGJ4L4rtPJ9F2BJ4n89vVRvwc0dOEHivHfaMIMIajvRWV+Ns42Og 4.1342 +hvilrZcG0JD66DlRT0IonuJBIn4cDfot5VhQ/hn+PL3ZzN30tT4RQhNsY9rMeuh3t6pxxXTW8Fxm 4.1343 +ItRO7EqYc4JpEqv1dOaeH/uQCX07BSg92o+Qi7hOKyEzEGEKxumaAND97pEvlhPmFrY4dA6K0inp 4.1344 +Jt4qpyImVmKAow7opDNunFBmD2LlH+IbthB4Fk3UfKgVoBOiFOHkTldVz1Ysxxy0EAF7CgQ2Sfby 4.1345 +RdghMg/KkeyscTVhnujYMUZLWen584Ph6Op5Y+wpezzzDnzOCrCDLqccgA4tnj59OhD/cb9/wqhE 4.1346 +aZ7fgOMEsPvCVnFBr3d4FnpydrW6vrd5EwFLzlbyCh5cU5bbPq8zSiHu6UoLIu1fAyPEtQktP5r2 4.1347 +LUvNybWSN4S5BW8saRPyU5bQHTSYApKocvVVPpgeMgJFLAm6IYzVLElCTifAemzzGs9qYTpQ84u8 4.1348 +A45PEMwY3+JOFgfDK/QBqbDSco9F50QMCPCACp14NDrsSqeVAM/J5VajOTnPkqo5Z/DM3eTUh7or 4.1349 +e7WM5isRb1AyzDxaxHCO/Xms2vjA+V4W9WKKfHblJgZbs+TX9+EOrA2Sli8WBlN4aBZplstyZowq 4.1350 +rlgySyoHjGmHcLgz3ahDBigKelAagIYnwzC3Em3ffmHXxcX0A+33HpqRdJlPZW8p4iROnLWq3aKo 4.1351 +GZ/SRZaQlm/NlxGM8p7Sz9of8MYSX+jkJxaZe5cpuMfd6kxfksB1Fs3NCQCHLuaxCtKyo6cjnNug 4.1352 +LHxmWh1uNHcqODXxGEQTbrdJWdVxOtEH+SfouU3sBrjG0x6T2nsA0Pos4Pbn4BAf6pJu8B1MNQzS 4.1353 +EysyTcn+iVjoJELkHj3yT+kUOfp6Lzw9jqnpZ3wRgKPBseWX5vDKQ1S+OULROX3gYjmm2qNw1K6o 4.1354 +7LTCfQ5TIm+d7HYc8KghW7B8h31WbPFOHpjWk3lE/0LfkaPLFHBj6tGDp8mUBgv7Co/v76srATH+ 4.1355 +W4OgLBI5P3yiEDvG+Y9C1VAMddxA4REzDOnuCQL5ZWsnzykv5NrfXds3HaBff7UPrKuCewufac/E 4.1356 +V8v6aJtbidxs2uDnwHrEK3C6UW/MzWFkrZb43CbqEDaI9qy5qVdpH5mB1w+f8p4JP2BHNMTBNHe4 4.1357 +8rqPVha/faRqGgW/i0q6Vz+t0AnGUtFVzG9QmdXFsQ0V+TBfRmn2oVtAhJ/qpre0Psa7j4jRq5tw 4.1358 +3/S5/7656xaBnbnZP+vM3T9C49JA993NL300YAddE+JBVbkWo8mfI7pjvbXbn6LSn4W9hZEzVcSD 4.1359 +GrWxZsl1PHO/Y4HBIV/i6B6HClyQZtVbc+qcD2uzc5eTu9zMm6n43J6QpB3yuWYvNud0pc+Ea64m 4.1360 +crlUkxhvhJqQD0j1AR3jbryKd3QbkIzV1jgDeOcCgDCsoiu53GJNWHXwM/lmSt5edw7XCxqaitCc 4.1361 +qjaVzDm2154HgIs4pqf+JnPEZWmDVGI2RtVlUYKzNtD3F/K+b1+pXAPUxJfrWN0Y1E2Psb7ODofg 4.1362 +YgNzhIozCewAetQBQvDJCudmF67znEzsO+CXZ81R0WRsGUJm9VqWcdXckuDvLyXiW2cEOjiHC+xE 4.1363 +kI3YtTjFRSyx/OEghTGc/f6ldo4832/P+dCRVWkPZyvqoZMTjzl66ki54ebkzt6S5N7OMadrMSle 4.1364 +5Ns1hG3WcJ+9GQKWwlz5Q4pQh3T8Vl9DwvfTcc4Jq+ocPgK5d4+t+NWNVmexw2DRcJ65iqF77wSe 4.1365 +fCRD23edVIcLuhdH+czQjO/rDcssnd2EHY0tFU+4Ra/iaUYbNYEOFiLdE+j4xaaPDHQ8+A8MdPTl 4.1366 +X2BNND5aH/SWn94TEbGacG/SahgB+kyASLhh0rqHydjDoVvMCeFKcjewl1GyznROiBgzgRzZvWKF 4.1367 +QPCNWcqtfPNutDHj9kUivnTR4+8uPrw+vSBaTC5P3/zn6Xe0zY9ZvZbNenAkmOWHTO1Dr6zQjQr1 4.1368 +1mzf4A22PVfTcW28htB539nW6oHQfw6ib0Hbisx9vatDp5682wkQ3z/tFtRdKrsXcsf50rXL7oZs 4.1369 +q/4v0E+5WMv8cvbWzCOTU2ZxaBLG5n2T49My2kmB7Fo4p2yqq060U6ovM9uRnhnZ4j1aAUztIX/Z 4.1370 +zJ6pxLb5I3ZU2leEU8UhnmIxNwGAFM6kcyEV3UXFoCr/LvISlF2MOxTsMI7tvZ7UjrOYyl5Yi7sU 4.1371 +MxkZgnjHSAbd+bnCPpfpDioEASs8fd0SI2L0n877272yJ0pcHdKBtUNUNtf2F66ZdnJ/TnBHrLL3 4.1372 +liiz5Y27AdB4UafuLpft0+lAzh8lTfOFUyENmu8I6NyIpwL2Rp+JFeJ0K0KIEvVWDhZdER31nUMO 4.1373 +8mg3HewNrZ6Jw13HmdzjPEI8391w3joxpHu84B7qnh6qNodGHAuMdT+7zimJbwkyZ90FXVTiOR+4 4.1374 +26Ovx4Svt1fPj23KFvkdX7vXYCDtB45hv2pOBuy9GsvpTbxSjqn+A4uNRm3w1wOHNRdid4DTqXPe 4.1375 +EQSZ7TiGNPDe99dGmB7enb2DNqKW745hQmL4RI1oUk5luMbdPhl1JtuorC4MLnK/H0ZH+wEohNLv 4.1376 +m+CHb2MB9fxMx4PTmu4TtA4nHg115IEKHXxe4B7G62uwa3eno2kP6k4l//agADdo855ebxBr9hq4 4.1377 +lZfo2G0L2jNveGCH7edDfv39nz+gf7ckxnZ/sc+htq1e9h4sYScWi6hw87pFIfM4AusCCnNIahrr 4.1378 +b42E4+H9howONzVTQ65Ah4/qsvCuUAosyImdaMtvjUHwf71Zz9M= 4.1379 +""".decode("base64").decode("zlib") 4.1380 + 4.1381 +##file ez_setup.py 4.1382 +EZ_SETUP_PY = """ 4.1383 +eJzNWmuP28YV/a5fwShYSIJlLt8PGXKRJi5gIEiDPAoU9lY7zxVrilRJyhu1yH/vmeFDJLVU2iIf 4.1384 +ysDZXXJ45z7PuXekL784nqt9ns3m8/kf87wqq4IcjVJUp2OV52lpJFlZkTQlVYJFs/fSOOcn45lk 4.1385 +lVHlxqkUw7XqaWEcCftEnsSirB+ax/Pa+PuprLCApScujGqflDOZpEK9Uu0hhByEwZNCsCovzsZz 4.1386 +Uu2NpFobJOMG4Vy/oDZUa6v8aOSy3qmVv9nMZgYuWeQHQ/xzp+8byeGYF5XScnfRUq8b3lquriwr 4.1387 +xD9OUMcgRnkULJEJMz6LooQT1N6XV9fqd6zi+XOW5oTPDklR5MXayAvtHZIZJK1EkZFKdIsulq71 4.1388 +pgyreG6UuUHPRnk6HtNzkj3NlLHkeCzyY5Go1/OjCoL2w+Pj2ILHR3M2+0m5SfuV6Y2VRGEUJ/xe 4.1389 +KlNYkRy1eU1UtZbHp4LwfhxNlQyzxnnluZx98+5PX/387U+7v7z74cf3f/7O2BpzywyYbc+7Rz// 4.1390 +8K3yq3q0r6rj5v7+eD4mZp1cZl483TdJUd7flff4r9vtfm7cqV3Mxr8fNu7DbHbg/o6TikDgv3TE 4.1391 +Fpc3XmNzar8+nh3TNcXT02JjLKLIcRiRsWU7vsUjL6JxHNBQOj4LRMDIYn1DitdKoWFMIuJZrvB8 4.1392 +y5GURr4QrrRjzw5dn9EJKc5QFz/ww9CPeUQCHknmeVZokZhboRM6PI5vS+l08WAAibgdxNyhIghs 4.1393 +SVyHBMJ3hCcjZ8oid6gLpa7NLMlCN45J4PphHIc+IzyWPrECO7oppdPFjUjEcJcHgnHHcbxQ2mEs 4.1394 +Q06CIJaETUjxhroEjuX5xPEE94QtKAtDKSw3JsQTgQyFf1PKxS+MOsSOfOgRccKkpA63oY/lUpfa 4.1395 +zHtZChvlC3WlQ33fjXmAuIYy9AgPY9uBIBJb0YRFbJwvsIcLDk8GIXe4I6WwPcuK3cCTDvEmIs1s 4.1396 +a6gMgzscQn3uEsvxA88PEB9mu5FlkdCKrdtiOm38kONFxCimkRWGDvNj4rsk8lyX+JxPeqYW47di 4.1397 +uPACwiL4Mg5ZFPt+6AhfRD7SUdCIhbfFBJ02kUAlESGtAA5ymAg824M0B0bC4RPRBqgMfeNQIghq 4.1398 +2HY53kcZOZEIKfGpT6ARF7fFXCLFAzeWMbUgzGOe48Wh5XpcMEcwizmTkbKHvgk8FnvSpTIkIbLQ 4.1399 +FSxyhUUdhDv0YurcFtP5hkoSO7ZlUY4wcdQEJAnOXQQ+8KwomBAzwhlpWYFHZUCIQ0NuQS141kNi 4.1400 +W5EdMmcqUCOcCezAjh0hmOtLLxSImh0wHhDbgVQnnJIywhlpRwAogC+XSBXi+DGLIUXaPKRhJCfQ 4.1401 +io1wRliCh14QOSyOIyppCE9HFrLXQsxDeyrY7jBIhAppB5JzGOb7vu1Fns1C4BePozjwp6SM0Ipa 4.1402 +NLZdmzBCXceCM4BzofQ85gMoQlvelNJZhCSR2DPgnqTSRUVRGXsBs+AqoJ6YShhvaFGk0BrA7zqM 4.1403 +05iFDmXSA3w5gXQiIqfQyh9aJEQseWRBHRQkMla6ApjuhwAMHtnBVKT9oUVEAqu4BKvYoWULAeeG 4.1404 +ICefMhAeCaZQxh/FKOKuDAAIHmOERKHtIXG4G1LGuMt9PiElGFqEgonA8pFtB2CiKPJCByLAmL4X 4.1405 +o7SngDMYsRvzAyL9kMK/6B5QDYEFQzzPRYH5ZAobgqFF1JERCX0HZA/YpS5I2kKoufAlWgnfnZAS 4.1406 +juDOQoxkTDhzSWD7wrdtH2WIliICBE7mSzhiAhLJ2PfAAhxYbkkahEza0kEY8MiZqoBwaJEHjiXA 4.1407 +W4mWAQXouZ5t25KLyLXxL5zSJRp1Q5bqhZwYHok5+EOlIAA8ci3VWFm3pXQWMUrcCNiAnsOLXGap 4.1408 +nEW2wdkMzDJJA9HQIjt07BAgh0DHnNm+5ccW8SPqCtR57E9FOh5aBN2ZZ6GZsZWHqRcHwmOSCiuC 4.1409 +rcyainQ8QgYkGRo7cKsbRTwAOhEhrADgxQLXm+rvGimdRVIgtK7wiR1S22EIE/M9m4bgXjC/mGKS 4.1410 +eMhHjKBsbKlQkziCA5js2AWzhdSPHfQ4kPLrrDcRYLwpZ1Vx3tQD156U+zSh7byF3n0mfmECo8Z7 4.1411 +feedGomatXjYXzfjQhq7zyRN0O2LHW4todMuwzy4NtQAsNpoAxJptPfVzNiOB/VDdfEEs0WFcUGJ 4.1412 +0C+ae/FLfRfzXbsMcpqVX2w7KR9a0Q8XeerC3IVp8O1bNZ2UFRcF5rrlYIW65sqkxoJmPrzDFEYw 4.1413 +hvEvDGP5fV6WCU174x9GOvx9+MNqfiXsrjNz8Gg1+EvpI35JqqVT3y8Q3CLT7qodOhoO9aJmvNqO 4.1414 +hrl1p9aOklJsewPdGpPiDqPqNi9NdirwW51M3QtcpOS8tf1ZEySMjV+dqvwAPzBMl2eMohm/78zu 4.1415 +nRSouf5APiGWGJ4/w1VEOQjOU6YdSbWvx/nHRulHo9znp5SraZbUvu5Layfz7HSgojCqPakMDMKd 4.1416 +YC1LTcCZ8q4hMfV2Sp0yrl8RxuPAEY+GGmmXz/uE7dvdBbRWRxO1PGNxv1iZULL20qPaUsnpHWPs 4.1417 +RTE4IHlOMHPTSyYIvkZG1gmuVc5y+CMtBOHni/rY473sqafdrrdrzia0mKrRUkujQqvSOESfWLA8 4.1418 +42Xtm1aNI0GiKKfCI6qskipB6LKn3nlGHfHG/jwT+jyhPhvhtV5wap4qH754PqK0bA4bRCNMn+UU 4.1419 ++Qk7iVqVus6IcRBlSZ5EfcBxKbrHR50vBUlKYfx4LitxePeL8ldWByIzSIV79ckGoQpalPEqBZUx 4.1420 +9amH2Wao/vlMyl2NQrB/ayyOn552hSjzU8FEuVAIo7Y/5PyUilKdkvQAdPy4rglUHUceNG5bri5I 4.1421 +olJueymaXl02HhuVYFt261GhXTCgLRITnhVFtbTWapMeyDVA3e30pn+6Q9tjvl0TmJ0G5q2SUQcI 4.1422 +wD6WNXCQfvgCwncvtYDUd0jz6HqHgWizSa7l/KLx2+38VeOq1ZtGdl+FoYC/1Cu/zjOZJqyCazZ9 4.1423 +9O9H/r9F+/lP+0v2T+T78u32rlx1tdzWsD7K/JgNAX/OSLaoVEl1JQLMUMd3ukaa4zpVLacsQyqb 4.1424 +xvepQIa0y6/kqRpSpQwAErCl1VAmRQlHnEpVDgtIOLehN17/3FN+YY7kfcw+ZsuvT0UBaYDzWsBd 4.1425 +MeKtFVjrksvCJMVT+cF6uM1ZOn5pKYYxQKIPw7nuV9qHUZ0+qFe+hLUayfNPA1Ev5eB01nyToCQS 4.1426 +elIM/l1e/SkHL9zO55ppXyrr35tuVfGjPAc8+80LpKrLmFxIwUhzVrckGj5rG5KqPiHWLcb/KcnW 4.1427 +EK0+A2hJ9rc4Vt1Tu14TbI37jxfOnODFvGbDlgwVqbDqRNKLEQ3JDImk/YihANdQB9m6RwqldZ61 4.1428 +/erW6IHZ67sSvfddqVrveb9wRkfgda5Cbp87lM+MV8MWsSSfBbTfoiWvSeHveZItWwppl9biyoIp 4.1429 +cbpP/g5s3rbWCqra11GkZVUua7GrjSqwrz7niUqgoyCKL1t1yq4+BniuLp2KHIKUN8rWS2n+NFil 4.1430 +mnEVl+G76sJK85kU2VL5+fXvd9WfkDTA2iB5+VKW3+mUUJ+cLMVnkak/YM4Rys72Ij2qvu99nW29 4.1431 +3qNLFTQnKv/VZztL5YoZKGFtAF1m6tYB5ZwJOBKvoA5V5wuEFs8KjwnG2bLUb/c5QCO4OWu2BHQ3 4.1432 +Pc5lR6jM22w2Z7MlQExslIe1mANhe9Vu8VzUxLRHeKFE9ZwXn5pN18axZpecVqT5XE4hhUaJu3I2 4.1433 +UygCDzDdtesFkHypxKZyCtGwVd8Ac/V7RhFJsb5KmR7oXjVUOsvWqpquXkNHoZO1StRk2TROqRDH 4.1434 +N/WP5aj3GmZnC8OaF8u53mLEe7rkGnww8TM/imx5texL4wc0/ffPRVIBfBBj+Fe328DwT2v10eCz 4.1435 +ip5qF1ihyhDQyPKiOOnkSMVImI57Pz1UF14Jvb7FxPZqPmabGsJhgKkGkuVqqHGNItqaGivW82c6 4.1436 +hzvxwNR21GN49xKGQTUUbsYQgA02eheW5qVYrq4goqw2Wmj/ecNmLWhBwVT90sLW7D+5FH8fkOlL 4.1437 +NCyf11OMfeHc97c+NNUc+w6tVbOqJYiXmunRh9G3Oul6eOiw+kriZc3tAUNP6tZ1SzYcIwZThI6Z 4.1438 +Ko3e7MDywwGGmoMesj3OIc1A1l5NjLSLU3CB9vPqlTpteVjpNH0Wi0KntTAUjf9mqihLlZ9HXKXU 4.1439 +vuYQLDplmAA/LTuzhg1n0m/czd2u8dZuZ2wxElqmZdqL/3pE+CsAXoOrmotpmacCtToxGrdNP8ik 4.1440 +buyvGvpCHPLPGm91JOrvPOgJGMxRAXrT38DdUac+2ZI3RfWPYbPSm7z63c71MPgfDHT4eaP/Hk1t 4.1441 +m+ls/59T8laZdYJ/U8pVNr9Ud225PQxndu1sa4XEh1WK/RE4pjNFPXk5Q9Uuv5MDOvW15jemsDrN 4.1442 +5z9etUXzdYsoc4DgkyaiQh3/IgnRJF0Sev6CvMXyB7RT8/bbOebxPJw+5/X3bq6/mmKuFs2x5rHj 4.1443 +p3aEKS/w/LN+aqgSoackrV7X58QQ+aSGu7NC5H4WF838o3qt9ly5E3txiO65L921+lOtWF66ai2k 4.1444 +5UJNmouCLi7PumNm9e5Dc0QtW1J98ZhadmRXj4A1RX+Yqz/uig3+rYEVGB+aTrNuyNqNTJDvoVyu 4.1445 +HrqXzRIWd9R5VEPFfF5PCjVJ9x2DCGCErNqJQX+faNveNZ9EVRetur/sT+c73THsdk3Wdy5pZKwN 4.1446 +7ZY3TUvUOuDN2NgDqTANbqGnWQpSsP1y/jHrfx/oY7b88LdfH16tfp3r9mTVH2P02z0segGxQeT6 4.1447 +G1mpIRQKfDG/LtIWEWtV8f8PGy3Y1K330l49YAzTjnyln9YPMbri0ebhZfMXz01OyKY96lTvOWAG 4.1448 +M1o/breL3U4V7G636D4FSZVEqKlr+K2j6bD9+4P9gHdev4az6lLp0VevdrrlzubhJV7UGHGRqRbV 4.1449 +178BYnMUkw== 4.1450 +""".decode("base64").decode("zlib") 4.1451 + 4.1452 +##file distribute_setup.py 4.1453 +DISTRIBUTE_SETUP_PY = """ 4.1454 +eJztG2tz2zbyu34FTh4PqYSi7TT3GM+pM2nj9DzNJZnYaT8kHhoiIYk1X+XDsvrrb3cBkCAJyc61 4.1455 +dzM3c7qrIxGLxWLfuwCP/lTs6k2eTabT6Xd5Xld1yQsWxfBvvGxqweKsqnmS8DoGoMnliu3yhm15 4.1456 +VrM6Z00lWCXqpqjzPKkAFkdLVvDwjq+FU8lBv9h57JemqgEgTJpIsHoTV5NVnCB6+AFIeCpg1VKE 4.1457 +dV7u2DauNyyuPcaziPEoogm4IMLWecHylVxJ4z8/n0wYfFZlnhrUBzTO4rTIyxqpDTpqCb7/yJ2N 4.1458 +dliKXxsgi3FWFSKMV3HI7kVZATOQhm6qh98BKsq3WZLzaJLGZZmXHstL4hLPGE9qUWYceKqBuh17 4.1459 +tGgIUFHOqpwtd6xqiiLZxdl6gpvmRVHmRRnj9LxAYRA/bm+HO7i99SeTa2QX8TekhRGjYGUD3yvc 4.1460 +SljGBW1PSZeoLNYlj0x5+qgUE8W8vNLfql37tY5Tob+vspTX4aYdEmmBFLS/eUk/Wwk1dYwqI0eT 4.1461 +fD2Z1OXuvJNiFaP2yeFPVxcfg6vL64uJeAgFkH5Jzy+QxXJKC8EW7F2eCQObJrtZAgtDUVVSVSKx 4.1462 +YoFU/iBMI/cZL9fVTE7BD/4EZC5s1xcPImxqvkyEN2PPaaiFK4FfZWag90PgqEvY2GLBTid7iT4C 4.1463 +RQfmg2hAihFbgRQkQeyF/80fSuQR+7XJa1AmfNykIquB9StYPgNd7MDgEWIqwNyBmBTJdwDmmxdO 4.1464 +t6QmCxEK3OasP6bwOPA/MG4YHw8bbHOmx9XUYccIOIJTMMMhtenPHQXEOviiVqxuhtLJK78qOFid 4.1465 +C98+BD+/urz22IBp7Jkps9cXb159ensd/HTx8ery/TtYb3rq/8U/ezlthz59fIuPN3VdnJ+cFLsi 4.1466 +9qWo/LxcnygnWJ1U4KhCcRKddH7pZDq5urj+9OH6/fu3V8GbVz9evB4sFJ6dTScm0Icffwgu3715 4.1467 +j+PT6ZfJP0XNI17z+U/SHZ2zM/908g786LlhwpN29LiaXDVpysEq2AN8Jv/IUzEvgEL6PXnVAOWl 4.1468 ++X0uUh4n8snbOBRZpUBfC+lACC8+AIJAgvt2NJlMSI2Vr3HBEyzh35m2AfEAMSck5ST3LodpsE4L 4.1469 +cJGwZe1N/PQuwu/gqXEc3Ia/5WXmOhcdEtCB48rx1GQJmCdRsI0AEYh/LepwGykMrZcgKLDdDcxx 4.1470 +zakExYkI6cL8vBBZu4sWJlD7UFvsTfbDJK8EhpfOINe5IhY33QaCFgD8idw6EFXweuP/AvCKMA8f 4.1471 +JqBNBq2fT29m441ILN1Ax7B3+ZZt8/LO5JiGNqhUQsMwNMZx2Q6y161uOzPTnWR53XNgjo7YsJyj 4.1472 +kDsDD9ItcAU6CqEf8G/BZbFtmcPXqCm1rpjJiW8sPMAiBEEL9LwsBRcNWs/4Mr8XetIqzgCPTRWk 4.1473 +5sy0Ei+bGB6I9dqF/zytrPAlD5B1/9fp/wGdJhlSLMwYSNGC6LsWwlBshO0EIeXdcWqfjs9/xb9L 4.1474 +9P2oNvRojr/gT2kgeqIayh3IqKa1qxRVk9R95YGlJLCyQc1x8QBLVzTcrVLyGFLUy/eUmrjO93mT 4.1475 +RDSLOCVtZ71GW1FWEAHRKod1VTrstVltsOSV0BszHkci4Tu1KrJyqAYK3unC5Py4mhe748iH/yPv 4.1476 +rIkEfI5ZRwUGdfUDIs4qBx2yPDy7mT2dPcosgOB2L0bGvWf/+2gdfPZwqdOrRxwOAVLOhuSDPxRl 4.1477 +7Z56rJO/yn77dY+R5C911acDdEDp94JMQ8p7UGOoHS8GKdKAAwsjTbJyQ+5ggSrelBYmLM7+7IFw 4.1478 +ghW/E4vrshGtd005mXjVQGG2peSZdJQvqzxBQ0VeTLolDE0DEPzXNbm35VUguSTQmzrF3ToAk6Ks 4.1479 +raIkFvmb5lGTiAorpS/tbpyOK0PAsSfu/TBE01uvDyCVc8MrXtel2wMEQwkiI+hak3CcrThoz8Jp 4.1480 +qF8BD0GUc+hqlxZiX1nTzpS59+/xFvuZ12OGr8p0d9qx5NvF9LlabWYha7iLPj6VNn+fZ6skDuv+ 4.1481 +0gK0RNYOIXkTdwb+ZCg4U6vGvMfpEOogI/G3JRS67ghiek2enbYVmT0Hozfjfrs4hoIFan0UNL+H 4.1482 +dJ0qmS/ZdIwPWykhz5wa601l6oB5u8E2AfVXVFsAvpVNhtHFZx8SAeKx4tOtA87SvERSQ0zRNKGr 4.1483 +uKxqD0wT0FinO4B4p10Om38y9uX4Fvgv2ZfM/b4pS1gl2UnE7LicAfKe/xc+VnGYOYxVWQotrt0X 4.1484 +/TGRVBb7AA1kA5Mz7PvzwE/c4BSMzNTYye/2FbNfYw1PiiH7LMaq1202A6u+y+s3eZNFv9toHyXT 4.1485 +RuIo1TnkroKwFLwWQ28V4ObIAtssCsPVgSj9e2MWfSyBS8Ur5YWhHn7dtfhac6W42jYSwfaSPKTS 4.1486 +hdqcivFxLTt3GVTyMim8VbTfsmpDmdkS25H3PIl72LXlZU26FCVYNCdTbr0C4cL2HyW91DFp+5Cg 4.1487 +BTRFsNseP24Z9jhc8BHhRq8uskiGTezRcuacODOf3Uqe3OKKvdwf/IsohU4h236XXkVEvtwjcbCd 4.1488 +rvZAHdYwzyLqdRYcA/1SrNDdYFszrBuedB1X2l+NlVTtazH8RxKGXiwioTYlVMFLikIC29yq31wm 4.1489 +WFZNDGu0xkoDxQvb3Hr9W4DqgK2fXnLsYxm2/g0doJK+bGqXvVwVBcmet1hk/sfvBbB0TwquQVV2 4.1490 +WYaIDvalWquGtQ7yZol2do48f3Wfx6jVBVpu1JLTZTijkN4WL631kI+vph5uqe+yJVGKS+5o+Ih9 4.1491 +FDw6odjKMMBAcgaksyWY3J2HHfYtKiFGQ+laQJPDvCzBXZD1DZDBbkmrtb3EeNZRC4LXKqw/2JTD 4.1492 +BKEMQR94NMioJBuJaMksj023y+kISKUFiKwbG/lMJQlYy5JiAAG6RB/AA35LuINFTfiuc0oShr0k 4.1493 +ZAlKxqoSBHddgfda5g/uqslC9GbKCdKwOU7tVY89e3a3nR3IimXzv6tP1HRtGK+1Z7mSzw8lzENY 4.1494 +zJmhkLYly0jtfZzLVtKozW5+Cl5Vo4HhSj6uA4IeP28XeQKOFhYw7Z9X4LELlS5YJD0hsekmvOEA 4.1495 +8OR8fjhvvwyV7miN6In+UW1Wy4zpPswgqwisSZ0d0lR6U2+VohNVAfoGF83AA3cBHiCru5D/M8U2 4.1496 +Ht41BXmLlUysRSZ3BJFdByTyluDbAoVDewREPDO9BnBjDLvQS3ccOgIfh9N2mnmWntarPoTZLlW7 4.1497 +7rShm/UBobEU8PUEyCYxNgTkDIhimc+ZmwBD2zq2YKncmuadPRNc2fwQ6fbEEAOsZ3oXY0T7JjxU 4.1498 +1myzCk27uCHvDR4rVKM9SwSZ2OrIjE8hyjr++7ev/eMKj7TwdNTHP6PO7kdEJ4MbBpJc9hQliRqn 4.1499 +avJibYs/Xduo2oB+2BKb5veQLINpBGaH3C0SHooNKLvQnepBGI8r7DWOwfrUf8ruIBD2mu+QeKk9 4.1500 +GHP369cK646e/8F0VF8IMBrBdlKAanXa7Kt/XZzrmf2YZ9gxnGNxMHT3evGRt1yC9O9Mtqz65VHH 4.1501 +ga5DSim8eWhurjtgwGSkBSAn1AKRCHkkmzc1Jr3oPbZ819mcrnOGCZvBHo9J1VfkDySq5huc6Jy5 4.1502 +shwgO+jBSlfViyCjSdIfqhkes5xXqs624ujIt3fcAFPgQxflsT41VmU6AsxblojaqRgqfut8h/xs 4.1503 +FU3xG3XNNVt43qD5p1r4eBMBvxrc0xgOyUPB9I7Dhn1mBTKodk1vM8Iyjuk2vQSnKhv3wFZNrOLE 4.1504 +nja6c9Vd5ImMNoEz2EnfH+/zNUPvvA9O+2q+gnS6PSLG9RVTjACGIO2NlbZt3dpIx3ssVwADnoqB 4.1505 +/09TICLIl7+43YGjr3vdBZSEUHfJyPZYl6Hn3CTdXzOl53JNckElLcXUY27YImzNHN1YGLsg4tTu 4.1506 +nngEJqcilfvkUxNZEXYbVZHYsCJ1aFN1fhAW+NLTOXffVQFP0vYVTm9Aysj/aV6OHaDV80jwA35n 4.1507 +6MO/R/nLSD6a1aVErYM8nBZZ3ScB7E+RJKvqNifazypDRj5McIZJyWAr9cbgaLcV9fixrfTIMDpl 4.1508 +Q3k9vr/HTGzoaR4Bn/Xy+TbodTndkQolEIHCO1SlGH/Z8uu9Cioz4IsffpijCDGEgDjl969Q0HiU 4.1509 +wh6Ms/tiwlPjquHbu9i6J9kH4tO7lm/9RwdZMXvEtB/l3H/FpgxW9MoOpS32ykMNav2Sfco2oo2i 4.1510 +2Xeyj7k3nFlO5hRmatYGRSlW8YOrPX0XXNogR6FBHUpC/X1vnPcbe8Pf6kKdBvysv0CUjMSDETaf 4.1511 +n53ftFkUDXr62p3ImlSUXF7IM3snCCpvrMp8az4vYa/yHoTcxDBBh00ADh/WLOsK28yoxAsMIxKP 4.1512 +pTFT54WSDM0skrh2HVxn4cw+zwencwYLNPvMxRSu4RGRpApLQ0mF9cA1Ac2Utwi/lfyx95B65Faf 4.1513 +CfK5hcqvpbSjEZjbVKJ06GihuxyrjgqxjWvt2NhWaWdbDENq5EhVh8p+FXI6UDTOHfX1SJvt7j0Y 4.1514 +P9ShOmJb4YBFhUCCJcgb2S0opHGrJ8qFZEolRIrnDObx6LhLQj+3aC79UkHdO0I2jDdkxCFMTGHy 4.1515 +tvIxa+uf6fsf5XkvJtvgFUtwRr3yxJ64D7SFYj5iWJAbVx5Xce56V4gR37BVaRwkvfpw+QcTPuuK 4.1516 +wCFCUMi+Mpq3ucx3C8ySRBbmdtEcsUjUQt2aw+CNJ/FtBERNjYY5bHsMtxiS5+uhoT6b7zwYRY9c 4.1517 +GrRbt0Msqyhe0KGC9IWokOQL4wcitijz+zgSkXz9IV4pePNFi8poPkTqwl3qdYcauuNoVhz9wGGj 4.1518 +zC4FhQ0Y6g0JBkTyLMR2D3SsrfJGONCygfpjf43SS8PAKqUcK/O6ntqSZRO+yCIVNOjO2J5NZXN5 4.1519 +m68TXo8OtO/9fTSrVPVkRRrgsHlYS1PFuPC5n6R9GZOFlMMJlCLR3Zd/os71uxFfkYPuTUIPNJ8H 4.1520 +vOnPG7efTd1oj+7QrOl8Wbo/Ous1/H0mhqLtZ/+/V54Deum0MxNGwzzhTRZuuhSuezKMlB/VSG/P 4.1521 +GNrYhmNrC99IkhBU8Os3WiRUERcs5eUdnuXnjNMBLO8mLJvWeNpU7/ybG0wXPjvz0LyRTdkZXrFJ 4.1522 +xFy1AObigd5fgpx5nvIMYnfk3BghTmM8vWn7Adg0MxPMz/03Lm7Y83baROOg+znWl2la7hmXkiuR 4.1523 +rGTjfDH1px5LBV4cqBYYU7qTGXWRmg6CFYQ8ZqRLACVwW7IWf4byipG+R6z3111oQJ+M73rl2wyr 4.1524 +6jSP8K0w6f+x2U8AhSjTuKroNa3uyE4jiUEJqeEFMo8qn93iBpz2Ygi+ogVIV4IIGV2jBkIVB+Ar 4.1525 +TFY7ctATy9SUJ0REiq/c0WUR4CeRTA1AjQd77EqLQWOXO7YWtcLlzvo3KFRCFubFzvwNhRhk/OpG 4.1526 +oGSovE6uARTju2uDJgdAH27avECLZZQP6AGMzclq0lYfsBL5Q4goCqRXOath1f8e+KUjTViPHnWh 4.1527 +peIrgVIVg2P9DtLnBVSgkavW6LsyTdeCuOXjn4OAeJ8M+zYvX/6NcpcwTkF8VDQBfad/PT01krFk 4.1528 +5SvRa5xS+duc4qNAaxWsQu6bJJuGb/b02N+Z+8JjLw0OoY3hfFG6gOHMQzwvZtZyIUwLgvGxSSAB 4.1529 +/e50asg2ROpKzHaAUlLv2o4eRojuxG6hFdDH435QX6TZQQKcmccUNnl1WDMIMje66AG4WgturRZV 4.1530 +l8SBqdyQeQOlM8Z7RNI5oLWtoQXeZ9Do7JykHG6AuE7GCu9sDNjQ+eITAMMN7OwAoCoQTIv9N269 4.1531 +ShXFyQlwP4Eq+GxcAdON4kF1bbunQMiCaLl2QQmnyrXgm2x44UnocJDymGrue4/tueTXBYLLQ6+7 4.1532 +kgpc8GqnoLTzO3z9X8X44cttQFxM918weQqoIg8CJDUI1LuURHcbNc/Ob2aTfwH3muVf 4.1533 +""".decode("base64").decode("zlib") 4.1534 + 4.1535 +##file activate.sh 4.1536 +ACTIVATE_SH = """ 4.1537 +eJytVU1v4jAQPW9+xTT0ANVS1GsrDlRFAqmFqmG72m0rY5IJsRRslDiktNr/vuMQ8tFQpNU2B4I9 4.1538 +H36eeW/SglkgYvBFiLBKYg0LhCRGD1KhA7BjlUQuwkLIHne12HCNNpz5kVrBgsfBmdWCrUrA5VIq 4.1539 +DVEiQWjwRISuDreW5eE+CtodeLeAnhZEGKMGFXqAciMiJVcoNWx4JPgixDjzEj48QVeCfcqmtzfs 4.1540 +cfww+zG4ZfeD2ciGF7gCHaDMPM1jtvuHXAsPfF2rSGeOxV4iDY5GUGb3xVEYv2aj6WQ0vRseAlMY 4.1541 +G5DKsAawwnQUXt2LQOYlzZoYByqhonqoqfxZf4BLD97i4DukgXADCPgGgdOLTK5arYxZB1xnrc9T 4.1542 +EQFcHoZEAa1gSQioo/TPV5FZrDlxJA+NzwF+Ek1UonOzFnKZp6k5mgLBqSkuuAGXS4whJb5xz/xs 4.1543 +wXCHjiVerAk5eh9Kfz1wqOldtVv9dkbscfjgjKeTA8XPrtaNauX5rInOxaHuOReNtpFjo1/OxdFG 4.1544 +5eY9hJ3L3jqcPJbATggXAemDLZX0MNZRYjSDH7C1wMHQh73DyYfTu8a0F9v+6D8W6XNnF1GEIXW/ 4.1545 +JrSKPOtnW1YFat9mrLJkzLbyIlTvYzV0RGXcaTBfVLx7jF2PJ2wyuBsydpm7VSVa4C4Zb6pFO2TR 4.1546 +huypCEPwuQjNftUrNl6GsYZzuFrrLdC9iJjQ3omAPBbcI2lsU77tUD43kw1NPZhTrnZWzuQKLomx 4.1547 +Rd4OXM1ByExVVkmoTwfBJ7Lt10Iq1Kgo23Bmd8Ib1KrGbsbO4Pp2yO4fpnf3s6MnZiwuiJuls1/L 4.1548 +Pu4yUCvhpA+vZaJvWWDTr0yFYYyVnHMqCEq+QniuYX225xmnzRENjbXACF3wkCYNVZ1mBwxoR9Iw 4.1549 +WAo3/36oSOTfgjwEEQKt15e9Xpqm52+oaXxszmnE9GLl65RH2OMmS6+u5acKxDmlPgj2eT5/gQOX 4.1550 +LLK0j1y0Uwbmn438VZkVpqlfNKa/YET/53j+99G8H8tUhr9ZSXs2 4.1551 +""".decode("base64").decode("zlib") 4.1552 + 4.1553 +##file activate.fish 4.1554 +ACTIVATE_FISH = """ 4.1555 +eJydVm1v4jgQ/s6vmA1wBxUE7X2stJVYlVWR2lK13d6d9laRk0yIr8HmbIe0++tvnIQQB9pbXT5A 4.1556 +Ys/LM55nZtyHx5RrSHiGsMm1gRAh1xhDwU0Kng8hFzMWGb5jBv2E69SDs0TJDdj3MxilxmzPZzP7 4.1557 +pVPMMl+q9bjXh1eZQ8SEkAZULoAbiLnCyGSvvV6SC7IoBcS4Nw0wjcFbvJDcjiuTswzFDpiIQaHJ 4.1558 +lQAjQUi1YRmUboC2uZJig8J4PaCnT5IaDcgsbm/CjinOwgx1KcUTMEhhTgV4g2B1fRk8Le8fv86v 4.1559 +g7v545UHpZB9rKnp+gXsMhxLunIIpwVQxP/l9c/Hq9Xt1epm4R27bva6AJqN92G4YhbMG2i+LB+u 4.1560 +grv71c3dY7B6WtzfLy9bePbp0taDTXSwJQJszUnnp0y57mvpPcrF7ZODyhswtd59+/jdgw+fwBNS 4.1561 +xLSscksUPIDqwwNmCez3PpxGeyBYg6HE0YdcWBxcKczYzuVJi5Wu915vn5oWePCCoPUZBN5B7IgV 4.1562 +MCi54ZDLG7TUZ0HweXkb3M5vFmSpFm/gthhBx0UrveoPpv9AJ9unIbQYdUoe21bKg2q48sPFGVwu 4.1563 +H+afrxd1qvclaNlRFyh1EQ2sSccEuNAGWQwysfVpz1tPajUqbqJUnEcIJkWo6OXDaodK8ZiLdbmM 4.1564 +L1wb+9H0D+pcyPSrX5u5kgWSygRYXCnJUi/KKcuU4cqsAyTKZBiissLc7NFwizvjxtieKBVCIdWz 4.1565 +fzilzPaYyljZN0cGN1v7NnaIPNCGmVy3GKuJaQ6iVjE1Qfm+36hglErwmnAD8hu0dDy4uICBA8ZV 4.1566 +pQr/q/+O0KFW2kjelu9Dgb9SDBsWV4F4x5CswgS0zBVlk5tDMP5bVtUGpslbm81Lu2sdKq7uNMGh 4.1567 +MVQ4fy9xhogC1lS5guhISa0DlBWv0O8odT6/LP+4WZzDV6FzIkEqC0uolGZSZoMnlpxplmD2euaT 4.1568 +O4hkTpPnbztDccey0bhjDaBIqaWQa0uwEtQEwtyU56i4fq54F9IE3ORR6mKriODM4XOYZwaVYLYz 4.1569 +7SPbKkz4i7VkB6/Ot1upDE3znNqYKpM8raa0Bx8vfvntJ32UENsM4aI6gJL+jJwhxhh3jVIDOcpi 4.1570 +m0r2hmEtS8XXXNBk71QCDXTBNhhPiHX2LtHkrVIlhoEshH/EZgdq53Eirqs5iFKMnkOmqZTtr3Xq 4.1571 +djvPTWZT4S3NT5aVLgurMPUWI07BRVYqkQrmtCKohNY8qu9EdACoT6ki0a66XxVF4f9AQ3W38yO5 4.1572 +mWmZmIIpnDFrbXakvKWeZhLwhvrbUH8fahhqD0YUcBDJjEBMQwiznE4y5QbHrbhHBOnUAYzb2tVN 4.1573 +jJa65e+eE2Ya30E2GurxUP8ssA6e/wOnvo3V78d3vTcvMB3n7l3iX1JXWqk= 4.1574 +""".decode("base64").decode("zlib") 4.1575 + 4.1576 +##file activate.csh 4.1577 +ACTIVATE_CSH = """ 4.1578 +eJx9U11vmzAUffevOCVRu+UB9pws29Kl0iq1aVWllaZlcgxciiViItsQdb9+xiQp+dh4QOB7Pu49 4.1579 +XHqY59IgkwVhVRmLmFAZSrGRNkdgykonhFiqSCRW1sJSmJg8wCDT5QrucRCyHn6WFRKhVGmhKwVp 4.1580 +kUpNiS3emup3TY6XIn7DVNQyJUwlrgthJD6n/iCNv72uhCzCpFx9CRkThRQGKe08cWXJ9db/yh/u 4.1581 +pvzl9mn+PLnjj5P5D1yM8QmXlzBkSdXwZ0H/BBc0mEo5FE5qI2jKhclHOOvy9HD/OO/6YO1mX9vx 4.1582 +sY0H/tPIV0dtqel0V7iZvWyNg8XFcBA0ToEqVeqOdNUEQFvN41SumAv32VtJrakQNSmLWmgp4oJM 4.1583 +yDoBHgoydtoEAs47r5wHHnUal5vbJ8oOI+9wI86vb2d8Nrm/4Xy4RZ8R85E4uTZPB5EZPnTaaAGu 4.1584 +E59J8BE2J8XgrkbLeXMlVoQxznEYFYY8uFFdxsKQRx90Giwx9vSueHP1YNaUSFG4vTaErNSYuBOF 4.1585 +lXiVyXa9Sy3JdClEyK1dD6Nos9mEf8iKlOpmqSNTZnYjNEWiUYn2pKNB3ttcLJ3HmYYXy6Un76f7 4.1586 +r8rRsC1TpTJj7f19m5sUf/V3Ir+x/yjtLu8KjLX/CmN/AcVGUUo= 4.1587 +""".decode("base64").decode("zlib") 4.1588 + 4.1589 +##file activate.bat 4.1590 +ACTIVATE_BAT = """ 4.1591 +eJyFUkEKgzAQvAfyhz0YaL9QEWpRqlSjWGspFPZQTevFHOr/adQaU1GaUzI7Mzu7ZF89XhKkEJS8 4.1592 +qxaKMMsvboQ+LxxE44VICSW1gEa2UFaibqoS0iyJ0xw2lIA6nX5AHCu1jpRsv5KRjknkac9VLVug 4.1593 +sX9mtzxIeJDE/mg4OGp47qoLo3NHX2jsMB3AiDht5hryAUOEifoTdCXbSh7V0My2NMq/Xbh5MEjU 4.1594 +ZT63gpgNT9lKOJ/CtHsvT99re3pX303kydn4HeyOeAg5cjf2EW1D6HOPkg9NGKhu 4.1595 +""".decode("base64").decode("zlib") 4.1596 + 4.1597 +##file deactivate.bat 4.1598 +DEACTIVATE_BAT = """ 4.1599 +eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q 4.1600 +FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL 4.1601 +i2dASrm4rFz9XLgAwJNbyQ== 4.1602 +""".decode("base64").decode("zlib") 4.1603 + 4.1604 +##file distutils-init.py 4.1605 +DISTUTILS_INIT = """ 4.1606 +eJytV92L4zYQf9dfMU0ottuse/TeFkKh3MvC0Ydy0IdlMVpbTtR1JCMpm+T++s5Y/pBs53oPZ1hQ 4.1607 +pPnSb34zo5WnVhsH2jLpV/Y2Li/cKKkOFoYN3Za6ErAdFtKC0g44vEvjzrwR6h1Oujo3YgdWw0VA 4.1608 +yRWcLUo6cBpqqSpwRwHWVY18ZRB9W3jq3HDlfoIvqK7NG2gF7a297VANvZ3O1sGrQI/eDe5yB0ZY 4.1609 +WQkLUpHxhVX09NDe3FGr31BL1lJUD9f8ln+FShpROm1ujOFS8ZOAPUKRt9wd836Hjqw7O9nYgvYD 4.1610 +iX+1VOlMPPXQ5EVRy0YURbaDZDSQZEzWo7rS5kSLNHaQwX4RRLrQGe1nj92Fh1zltEhHDDZfEO0g 4.1611 +O6MraHn5xg8IpYOfLfC2FdxYShLC64EES4A0uuROYhq49Zs368RpMvTHJmOiscKHUXRXKIpcKiuM 4.1612 +Sz/sYHa7TkxcRYkkEhN8HZaxKCJXFFJJh+baW5JluRG8SjM20JHEA9qWWtXywBjbbvF2rjzC61k2 4.1613 +VSGuDibTUGlhVeLgTekLHPEP73wQrrscUsUGrPCGjkTCC1JXXyw8EJWP3FSUZY8IiSCCRp97dnfO 4.1614 +RUUx5a0RtbxSzLX/3XBXYxIpyQka/fh74pGrjQ5QzUt9OnFV5dMV+otOG5gQjctxozNTNtzaSSiN 4.1615 +JHqu0FeJmsqRN/KrKHRLGbaQWtHUgRB9FDfu5giN4eZWIDqWCv8vrcTjrNZgRXQPzy+RmGjQpLRI 4.1616 +EKz0UqQLlR28ciusM8jn7PtcLPZy2zbSDeyyos0iO+ybBgPyRvSk/CEFm8IndQebz8iXTRbbjhDP 4.1617 +5xh7iJfBrKd/Nenjj6Jvgp2B+W7AnP102BXH5IZWPV3tI2MUOvXowpdS12IIXhLLP0lKyeuZrpEv 4.1618 +pFhPqHg3JFTd1cceVp0EsPgGU0wFO2u4iyYRoFYfEm9kG/RZcUUBm87t9mFtx9iCtC9kx4Rt4R8a 4.1619 +OdgzSt40vtyFecAZZ8BfCOhCrC8djMGPFaz2Vlt5TSZCk053+37wbLDLRXfZ+F45NtdVpVWdudSC 4.1620 +xgODI8EsiLoTl5aO0lhoigX7GHZDHAY4LxoMIu1gXPYPksmFquxF4uRKZhEnKzXu82HESb+LlNQz 4.1621 +Fh/RvFJVuhK+Ee5slBdj30FcRGdJ5rhKxtkyKxWcGoV/WOCYKqkNDYJ5fNQVx3g400tpJBS2FSU+ 4.1622 +Tco9ss8nZ08dtscGQfSby87b73fOw+4UgrEMNnY6uMzYvSDxPVPpsij6+l0/ZPfuH0Iz010giY34 4.1623 +HpL0ZLyLJB4ukaQRU+GwptO7yIZCQE33B0K9iCqO6X+AR4n7wAeH68DPkJzpTsD3x+/cj9LIVHC2 4.1624 +An1wmv7CzWHoqR02vb0VL73siP+3nkX0YbQ0l9f6WDyOm24cj3rxO2MMip6kpcu6VCefn/789PR3 4.1625 +0v0fg21sFIp70rj9PCi8YDRDXFucym/43qN+iENh1Jy/dIIIqF3OIkDvBMsdx+huWv8Kz73vl8g5 4.1626 +WQ3JOGqwu3lb4dfKKbvLigXDQsb8B/xt39Q= 4.1627 +""".decode("base64").decode("zlib") 4.1628 + 4.1629 +##file distutils.cfg 4.1630 +DISTUTILS_CFG = """ 4.1631 +eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH 4.1632 +xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg 4.1633 +9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q= 4.1634 +""".decode("base64").decode("zlib") 4.1635 + 4.1636 +##file activate_this.py 4.1637 +ACTIVATE_THIS = """ 4.1638 +eJyNUlGL2zAMfvevEBlHEujSsXsL9GGDvW1jD3sZpQQ3Ua7aJXawnbT595Ocpe0dO5ghseVP+vRJ 4.1639 +VpIkn2cYPZknwAvWLXWYhRP5Sk4baKgOWRWNqtpdgTyH2Y5wpq5Tug406YAgKEzkwqg7NBPwR86a 4.1640 +Hk0olPopaK0NHJHzYQPnE5rI0o8+yBUwiBfyQcT8mMPJGiAT0A0O+b8BY4MKJ7zPcSSzHaKrSpJE 4.1641 +qeDmUgGvVbPCS41DgO+6xy/OWbfAThMn/OQ9ukDWRCSLiKzk1yrLjWapq6NnvHUoHXQ4bYPdrsVX 4.1642 +4lQMc/q6ZW975nmSK+oH6wL42a9H65U6aha342Mh0UVDzrD87C1bH73s16R5zsStkBZDp0NrXQ+7 4.1643 +HaRnMo8f06UBnljKoOtn/YT+LtdvSyaT/BtIv9KR60nF9f3qmuYKO4//T9ItJMsjPfgUHqKwCZ3n 4.1644 +xu/Lx8M/UvCLTxW7VULHxB1PRRbrYfvWNY5S8it008jOjcleaMqVBDnUXcWULV2YK9JEQ92OfC96 4.1645 +1Tv4ZicZZZ7GpuEpZbbeQ7DxquVx5hdqoyFSSmXwfC90f1Dc7hjFs/tK99I0fpkI8zSLy4tSy+sI 4.1646 +3vMWehjQNJmE5VePlZbL61nzX3S93ZcfDqznnkb9AZ3GWJU= 4.1647 +""".decode("base64").decode("zlib") 4.1648 + 4.1649 +if __name__ == '__main__': 4.1650 + main() 4.1651 + 4.1652 +## TODO: 4.1653 +## Copy python.exe.manifest 4.1654 +## Monkeypatch distutils.sysconfig