KanonConductor
changeset 31:ca083cbc2c09
merge centos5-supprot branch.
author | chris |
---|---|
date | Mon, 28 Mar 2011 03:22:46 +0900 |
parents | 3d1c15c7cefa c6335712741b |
children | 640e6a9509aa |
files | kanon-setup pkglist.rhel |
diffstat | 7 files changed, 1780 insertions(+), 34 deletions(-) [+] |
line diff
1.1 --- a/kanon-setup Fri Mar 25 00:30:38 2011 +0900 1.2 +++ b/kanon-setup Mon Mar 28 03:22:46 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 @@ -19,6 +25,7 @@ 1.20 echo " * Debian GNU/Linux, GNU/kFreeBSD 6.0" 1.21 echo " * RedHat Enterprise Linux 6.0" 1.22 echo " * Oracle Enterprise Linux 6.0" 1.23 + echo " * CentOS 5.x (Experimental)" 1.24 echo "" 1.25 echo "です。" 1.26 exit 1.27 @@ -49,23 +56,44 @@ 1.28 fi 1.29 1.30 ### install ubuntu package 1.31 -if [ "$OS" = 'debian' ] 1.32 -then 1.33 - apt-get update 1.34 - apt-get -y install `cat pkglist.debian` 1.35 -elif [ "$OS" = 'rhel' ] 1.36 -then 1.37 - yum -y install `cat pkglist.rhel` 1.38 -fi 1.39 +case $OS in 1.40 + debian) 1.41 + apt-get update 1.42 + apt-get -y install `cat pkglist.debian` 1.43 + ;; 1.44 + rhel6) 1.45 + yum -y install `cat pkglist.rhel6` 1.46 + ;; 1.47 + rhel5) 1.48 + # Add EPEL Repository. For python26, python26-devel, python26-mod_wsgi. 1.49 + EPEL_RPM_URL="http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm" 1.50 + wget $EPEL_RPM_URL 1.51 + rpm -Uvh epel-release-5-4.noarch.rpm 1.52 + rm -f epel-release-5-4.noarch.rpm 1.53 + yum -y install `cat pkglist.rhel5` 1.54 + 1.55 + # Add Kanon Repository. For Subversion 1.6 with Python26. 1.56 + cp -f resource/kanon.repo /etc/yum.repos.d/kanon.repo 1.57 + yum -y install subversion-1.6.15 mod_dav_svn-1.6.15 1.58 + ;; 1.59 + *) 1.60 + ;; 1.61 +esac 1.62 1.63 ### install files 1.64 cp -fr opt/* /opt 1.65 -cp -frn etc/* /etc 1.66 +if [ "$OS" = "rhel5" ] 1.67 +then 1.68 + # FIXME CentOS 5.x では n オプションがないため 強制上書きになってしまう. 1.69 + cp -fr etc/* /etc 1.70 +else 1.71 + cp -frn etc/* /etc 1.72 +fi 1.73 1.74 1.75 ### setup configuration 1.76 -export PYTHONPATH=/opt/kanon/lib/python2.6:/opt/kanon/lib/python2.6/site-packages 1.77 -cp resource/dot.pydistutils.cfg ~/.pydistutils.cfg 1.78 +python2.6 resource/virtualenv.py /opt/kanon 1.79 +source /opt/kanon/bin/activate 1.80 1.81 ## setup sitecustomize for python 1.82 if [ -f /etc/python2.6/sitecustomize.py ] 1.83 @@ -77,19 +105,27 @@ 1.84 fi 1.85 fi 1.86 1.87 -### install python components 1.88 -easy_install --prefix $KANON_OPT http://svn.edgewall.org/repos/genshi/tags/0.6.0/ 1.89 -easy_install --prefix $KANON_OPT http://ftp.edgewall.com/pub/babel/Babel-0.9.5.zip 1.90 -easy_install --prefix $KANON_OPT http://www.i-act.co.jp/project/products/downloads/Trac-0.12.2.ja1.zip 1.91 -easy_install --prefix $KANON_OPT xlrd 1.92 -easy_install --prefix $KANON_OPT https://github.com/hvr/trac-git-plugin/zipball/v0.12.0.5 1.93 + 1.94 +if [ "$OS" = "rhel5" ] 1.95 +then 1.96 + # Install Extra Package for CentOS 5.X 1.97 + easy_install "mercurial==1.7.3" 1.98 + easy_install bzr 1.99 + easy_install pygments 1.100 +fi 1.101 + 1.102 +easy_install http://svn.edgewall.org/repos/genshi/tags/0.6.0/ 1.103 +easy_install http://ftp.edgewall.com/pub/babel/Babel-0.9.5.zip 1.104 +easy_install http://www.i-act.co.jp/project/products/downloads/Trac-0.12.2.ja1.zip 1.105 +easy_install xlrd 1.106 +easy_install https://github.com/hvr/trac-git-plugin/zipball/v0.12.0.5 1.107 # bzr co lp:trac-bzr /tmp/trac-bzr-install 1.108 #easy_install --prefix /opt/kanon /tmp/trac-bzr-install 1.109 #rm -fr /tmp/trac-bzr-install 1.110 1.111 1.112 ### install trac plugins 1.113 -easy_install --prefix $KANON_OPT http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin 1.114 +easy_install http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin 1.115 1.116 #resource/pluginsディレクトリのプラグインをインストール 1.117 pushd . 1.118 @@ -97,8 +133,8 @@ 1.119 cd resource/trac-plugins 1.120 for i in `ls -1 .` 1.121 do 1.122 - cd $i;python setup.py install --prefix=/opt/kanon 1.123 - cd .. 1.124 + cd $i;python setup.py install 1.125 + cd .. 1.126 done 1.127 cd ../.. 1.128 1.129 @@ -109,7 +145,7 @@ 1.130 cd /tmp 1.131 svn co $i kanon_build 1.132 cd kanon_build 1.133 - python setup.py install --prefix=/opt/kanon 1.134 + python setup.py install 1.135 cd .. 1.136 rm -fr kanon_build 1.137 done 1.138 @@ -117,6 +153,7 @@ 1.139 1.140 1.141 ### setup apache and restart 1.142 +<<<<<<< local 1.143 if [ "$OS" = 'debian' ] 1.144 then 1.145 cp resource/trac_hook.py /usr/lib/python2.6/dist-packages/bzrlib/plugins 1.146 @@ -149,6 +186,53 @@ 1.147 service httpd stop 1.148 service httpd start 1.149 fi 1.150 +======= 1.151 +case $OS in 1.152 + debian) 1.153 + cp resource/trac_hook.py /usr/lib/python2.6/dist-packages/bzrlib/plugins 1.154 + if [ ! -f /etc/apache2/sites-available/kanon ] 1.155 + then 1.156 + cp resource/httpd.conf /etc/apache2/sites-available/kanon 1.157 + fi 1.158 + a2enmod expires 1.159 + a2enmod auth_digest 1.160 + a2enmod dav_fs 1.161 + a2ensite kanon 1.162 + service apache2 stop 1.163 + service apache2 start 1.164 + ;; 1.165 + rhel6) 1.166 + mkdir -p /usr/lib/python2.6/site-packages/bzrlib/plugin 1.167 + cp resource/trac_hook.py /usr/lib/python2.6/site-packages/bzrlib/plugin 1.168 + if [ ! -f /etc/httpd/conf.d/kanon.conf ] 1.169 + then 1.170 + cp resource/httpd.conf /etc/httpd/conf.d/kanon.conf 1.171 + fi 1.172 + echo 0 > /selinux/enforce 1.173 + echo "SELinuxが無効化されました" 1.174 + service httpd stop 1.175 + service httpd start 1.176 + ;; 1.177 + rhel5) 1.178 + mkdir -p /var/opt/kanon/trac/.egg-cache 1.179 + chown $APACHE_USER:$APACHE_USER -R /var/opt/kanon/trac/.egg-cache/ 1.180 + mkdir -p /usr/lib/python2.6/site-packages/bzrlib/plugin 1.181 + cp resource/trac_hook.py /usr/lib/python2.6/site-packages/bzrlib/plugin 1.182 + if [ ! -f /etc/httpd/conf.d/kanon.conf ] 1.183 + then 1.184 + cp resource/httpd.conf /etc/httpd/conf.d/kanon.conf 1.185 + fi 1.186 + echo 0 > /selinux/enforce 1.187 + echo "SELinuxが無効化されました" 1.188 + mv /etc/httpd/conf.d/python.conf /etc/httpd/conf.d/python.conf.disabled 1.189 + service httpd stop 1.190 + service httpd start 1.191 + ;; 1.192 + *) 1.193 + ;; 1.194 +esac 1.195 + 1.196 +>>>>>>> other 1.197 1.198 # データディレクトリが存在しない場合作成 1.199 if [ ! -d "$KANON_VAR/trac" ]
2.1 --- a/pkglist.rhel Fri Mar 25 00:30:38 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.rhel5 Mon Mar 28 03:22:46 2011 +0900 3.3 @@ -0,0 +1,6 @@ 3.4 +python26 3.5 +python26-devel 3.6 +python26-mod_wsgi 3.7 +httpd 3.8 +sqlite 3.9 +gcc
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/pkglist.rhel6 Mon Mar 28 03:22:46 2011 +0900 4.3 @@ -0,0 +1,11 @@ 4.4 +httpd 4.5 +python-setuptools 4.6 +python-pygments 4.7 +sqlite 4.8 +mod_dav_svn 4.9 +mod_wsgi 4.10 +subversion 4.11 +mercurial 4.12 +bzr 4.13 +gcc 4.14 +git
5.1 --- a/resource/httpd.conf Fri Mar 25 00:30:38 2011 +0900 5.2 +++ b/resource/httpd.conf Mon Mar 28 03:22:46 2011 +0900 5.3 @@ -24,7 +24,7 @@ 5.4 </Location> 5.5 5.6 # Subversionの設定 5.7 -<Location "/svn"> 5.8 +<Location "/svn/"> 5.9 DAV svn 5.10 SVNParentPath /var/opt/kanon/svn 5.11 SVNListParentPath on
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/resource/kanon.repo Mon Mar 28 03:22:46 2011 +0900 6.3 @@ -0,0 +1,5 @@ 6.4 +[kanon] 6.5 +name = RHEL $releasever - Kanon - chris 6.6 +baseurl = http://kanon.ultimania.org/pkg/centos5/$basearch 6.7 +enabled = 1 6.8 +gpgcheck = 0 6.9 \ No newline at end of file
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/resource/virtualenv.py Mon Mar 28 03:22:46 2011 +0900 7.3 @@ -0,0 +1,1651 @@ 7.4 +#!/usr/bin/env python 7.5 +"""Create a "virtual" Python installation 7.6 +""" 7.7 + 7.8 +virtualenv_version = "1.5.1" 7.9 + 7.10 +import sys 7.11 +import os 7.12 +import optparse 7.13 +import re 7.14 +import shutil 7.15 +import logging 7.16 +import tempfile 7.17 +import distutils.sysconfig 7.18 +try: 7.19 + import subprocess 7.20 +except ImportError, e: 7.21 + if sys.version_info <= (2, 3): 7.22 + print 'ERROR: %s' % e 7.23 + print 'ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.' 7.24 + print 'If you copy subprocess.py from a newer version of Python this script will probably work' 7.25 + sys.exit(101) 7.26 + else: 7.27 + raise 7.28 +try: 7.29 + set 7.30 +except NameError: 7.31 + from sets import Set as set 7.32 + 7.33 +join = os.path.join 7.34 +py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1]) 7.35 + 7.36 +is_jython = sys.platform.startswith('java') 7.37 +is_pypy = hasattr(sys, 'pypy_version_info') 7.38 + 7.39 +if is_pypy: 7.40 + expected_exe = 'pypy-c' 7.41 +elif is_jython: 7.42 + expected_exe = 'jython' 7.43 +else: 7.44 + expected_exe = 'python' 7.45 + 7.46 + 7.47 +REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath', 7.48 + 'fnmatch', 'locale', 'encodings', 'codecs', 7.49 + 'stat', 'UserDict', 'readline', 'copy_reg', 'types', 7.50 + 're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile', 7.51 + 'zlib'] 7.52 + 7.53 +REQUIRED_FILES = ['lib-dynload', 'config'] 7.54 + 7.55 +if sys.version_info[:2] >= (2, 6): 7.56 + REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc']) 7.57 +if sys.version_info[:2] >= (2, 7): 7.58 + REQUIRED_MODULES.extend(['_weakrefset']) 7.59 +if sys.version_info[:2] <= (2, 3): 7.60 + REQUIRED_MODULES.extend(['sets', '__future__']) 7.61 +if is_pypy: 7.62 + # these are needed to correctly display the exceptions that may happen 7.63 + # during the bootstrap 7.64 + REQUIRED_MODULES.extend(['traceback', 'linecache']) 7.65 + 7.66 +class Logger(object): 7.67 + 7.68 + """ 7.69 + Logging object for use in command-line script. Allows ranges of 7.70 + levels, to avoid some redundancy of displayed information. 7.71 + """ 7.72 + 7.73 + DEBUG = logging.DEBUG 7.74 + INFO = logging.INFO 7.75 + NOTIFY = (logging.INFO+logging.WARN)/2 7.76 + WARN = WARNING = logging.WARN 7.77 + ERROR = logging.ERROR 7.78 + FATAL = logging.FATAL 7.79 + 7.80 + LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] 7.81 + 7.82 + def __init__(self, consumers): 7.83 + self.consumers = consumers 7.84 + self.indent = 0 7.85 + self.in_progress = None 7.86 + self.in_progress_hanging = False 7.87 + 7.88 + def debug(self, msg, *args, **kw): 7.89 + self.log(self.DEBUG, msg, *args, **kw) 7.90 + def info(self, msg, *args, **kw): 7.91 + self.log(self.INFO, msg, *args, **kw) 7.92 + def notify(self, msg, *args, **kw): 7.93 + self.log(self.NOTIFY, msg, *args, **kw) 7.94 + def warn(self, msg, *args, **kw): 7.95 + self.log(self.WARN, msg, *args, **kw) 7.96 + def error(self, msg, *args, **kw): 7.97 + self.log(self.WARN, msg, *args, **kw) 7.98 + def fatal(self, msg, *args, **kw): 7.99 + self.log(self.FATAL, msg, *args, **kw) 7.100 + def log(self, level, msg, *args, **kw): 7.101 + if args: 7.102 + if kw: 7.103 + raise TypeError( 7.104 + "You may give positional or keyword arguments, not both") 7.105 + args = args or kw 7.106 + rendered = None 7.107 + for consumer_level, consumer in self.consumers: 7.108 + if self.level_matches(level, consumer_level): 7.109 + if (self.in_progress_hanging 7.110 + and consumer in (sys.stdout, sys.stderr)): 7.111 + self.in_progress_hanging = False 7.112 + sys.stdout.write('\n') 7.113 + sys.stdout.flush() 7.114 + if rendered is None: 7.115 + if args: 7.116 + rendered = msg % args 7.117 + else: 7.118 + rendered = msg 7.119 + rendered = ' '*self.indent + rendered 7.120 + if hasattr(consumer, 'write'): 7.121 + consumer.write(rendered+'\n') 7.122 + else: 7.123 + consumer(rendered) 7.124 + 7.125 + def start_progress(self, msg): 7.126 + assert not self.in_progress, ( 7.127 + "Tried to start_progress(%r) while in_progress %r" 7.128 + % (msg, self.in_progress)) 7.129 + if self.level_matches(self.NOTIFY, self._stdout_level()): 7.130 + sys.stdout.write(msg) 7.131 + sys.stdout.flush() 7.132 + self.in_progress_hanging = True 7.133 + else: 7.134 + self.in_progress_hanging = False 7.135 + self.in_progress = msg 7.136 + 7.137 + def end_progress(self, msg='done.'): 7.138 + assert self.in_progress, ( 7.139 + "Tried to end_progress without start_progress") 7.140 + if self.stdout_level_matches(self.NOTIFY): 7.141 + if not self.in_progress_hanging: 7.142 + # Some message has been printed out since start_progress 7.143 + sys.stdout.write('...' + self.in_progress + msg + '\n') 7.144 + sys.stdout.flush() 7.145 + else: 7.146 + sys.stdout.write(msg + '\n') 7.147 + sys.stdout.flush() 7.148 + self.in_progress = None 7.149 + self.in_progress_hanging = False 7.150 + 7.151 + def show_progress(self): 7.152 + """If we are in a progress scope, and no log messages have been 7.153 + shown, write out another '.'""" 7.154 + if self.in_progress_hanging: 7.155 + sys.stdout.write('.') 7.156 + sys.stdout.flush() 7.157 + 7.158 + def stdout_level_matches(self, level): 7.159 + """Returns true if a message at this level will go to stdout""" 7.160 + return self.level_matches(level, self._stdout_level()) 7.161 + 7.162 + def _stdout_level(self): 7.163 + """Returns the level that stdout runs at""" 7.164 + for level, consumer in self.consumers: 7.165 + if consumer is sys.stdout: 7.166 + return level 7.167 + return self.FATAL 7.168 + 7.169 + def level_matches(self, level, consumer_level): 7.170 + """ 7.171 + >>> l = Logger() 7.172 + >>> l.level_matches(3, 4) 7.173 + False 7.174 + >>> l.level_matches(3, 2) 7.175 + True 7.176 + >>> l.level_matches(slice(None, 3), 3) 7.177 + False 7.178 + >>> l.level_matches(slice(None, 3), 2) 7.179 + True 7.180 + >>> l.level_matches(slice(1, 3), 1) 7.181 + True 7.182 + >>> l.level_matches(slice(2, 3), 1) 7.183 + False 7.184 + """ 7.185 + if isinstance(level, slice): 7.186 + start, stop = level.start, level.stop 7.187 + if start is not None and start > consumer_level: 7.188 + return False 7.189 + if stop is not None or stop <= consumer_level: 7.190 + return False 7.191 + return True 7.192 + else: 7.193 + return level >= consumer_level 7.194 + 7.195 + #@classmethod 7.196 + def level_for_integer(cls, level): 7.197 + levels = cls.LEVELS 7.198 + if level < 0: 7.199 + return levels[0] 7.200 + if level >= len(levels): 7.201 + return levels[-1] 7.202 + return levels[level] 7.203 + 7.204 + level_for_integer = classmethod(level_for_integer) 7.205 + 7.206 +def mkdir(path): 7.207 + if not os.path.exists(path): 7.208 + logger.info('Creating %s', path) 7.209 + os.makedirs(path) 7.210 + else: 7.211 + logger.info('Directory %s already exists', path) 7.212 + 7.213 +def copyfile(src, dest, symlink=True): 7.214 + if not os.path.exists(src): 7.215 + # Some bad symlink in the src 7.216 + logger.warn('Cannot find file %s (bad symlink)', src) 7.217 + return 7.218 + if os.path.exists(dest): 7.219 + logger.debug('File %s already exists', dest) 7.220 + return 7.221 + if not os.path.exists(os.path.dirname(dest)): 7.222 + logger.info('Creating parent directories for %s' % os.path.dirname(dest)) 7.223 + os.makedirs(os.path.dirname(dest)) 7.224 + if symlink and hasattr(os, 'symlink'): 7.225 + logger.info('Symlinking %s', dest) 7.226 + os.symlink(os.path.abspath(src), dest) 7.227 + else: 7.228 + logger.info('Copying to %s', dest) 7.229 + if os.path.isdir(src): 7.230 + shutil.copytree(src, dest, True) 7.231 + else: 7.232 + shutil.copy2(src, dest) 7.233 + 7.234 +def writefile(dest, content, overwrite=True): 7.235 + if not os.path.exists(dest): 7.236 + logger.info('Writing %s', dest) 7.237 + f = open(dest, 'wb') 7.238 + f.write(content) 7.239 + f.close() 7.240 + return 7.241 + else: 7.242 + f = open(dest, 'rb') 7.243 + c = f.read() 7.244 + f.close() 7.245 + if c != content: 7.246 + if not overwrite: 7.247 + logger.notify('File %s exists with different content; not overwriting', dest) 7.248 + return 7.249 + logger.notify('Overwriting %s with new content', dest) 7.250 + f = open(dest, 'wb') 7.251 + f.write(content) 7.252 + f.close() 7.253 + else: 7.254 + logger.info('Content %s already in place', dest) 7.255 + 7.256 +def rmtree(dir): 7.257 + if os.path.exists(dir): 7.258 + logger.notify('Deleting tree %s', dir) 7.259 + shutil.rmtree(dir) 7.260 + else: 7.261 + logger.info('Do not need to delete %s; already gone', dir) 7.262 + 7.263 +def make_exe(fn): 7.264 + if hasattr(os, 'chmod'): 7.265 + oldmode = os.stat(fn).st_mode & 07777 7.266 + newmode = (oldmode | 0555) & 07777 7.267 + os.chmod(fn, newmode) 7.268 + logger.info('Changed mode of %s to %s', fn, oct(newmode)) 7.269 + 7.270 +def _find_file(filename, dirs): 7.271 + for dir in dirs: 7.272 + if os.path.exists(join(dir, filename)): 7.273 + return join(dir, filename) 7.274 + return filename 7.275 + 7.276 +def _install_req(py_executable, unzip=False, distribute=False): 7.277 + if not distribute: 7.278 + setup_fn = 'setuptools-0.6c11-py%s.egg' % sys.version[:3] 7.279 + project_name = 'setuptools' 7.280 + bootstrap_script = EZ_SETUP_PY 7.281 + source = None 7.282 + else: 7.283 + setup_fn = None 7.284 + source = 'distribute-0.6.14.tar.gz' 7.285 + project_name = 'distribute' 7.286 + bootstrap_script = DISTRIBUTE_SETUP_PY 7.287 + try: 7.288 + # check if the global Python has distribute installed or plain 7.289 + # setuptools 7.290 + import pkg_resources 7.291 + if not hasattr(pkg_resources, '_distribute'): 7.292 + location = os.path.dirname(pkg_resources.__file__) 7.293 + logger.notify("A globally installed setuptools was found (in %s)" % location) 7.294 + logger.notify("Use the --no-site-packages option to use distribute in " 7.295 + "the virtualenv.") 7.296 + except ImportError: 7.297 + pass 7.298 + 7.299 + search_dirs = file_search_dirs() 7.300 + 7.301 + if setup_fn is not None: 7.302 + setup_fn = _find_file(setup_fn, search_dirs) 7.303 + 7.304 + if source is not None: 7.305 + source = _find_file(source, search_dirs) 7.306 + 7.307 + if is_jython and os._name == 'nt': 7.308 + # Jython's .bat sys.executable can't handle a command line 7.309 + # argument with newlines 7.310 + fd, ez_setup = tempfile.mkstemp('.py') 7.311 + os.write(fd, bootstrap_script) 7.312 + os.close(fd) 7.313 + cmd = [py_executable, ez_setup] 7.314 + else: 7.315 + cmd = [py_executable, '-c', bootstrap_script] 7.316 + if unzip: 7.317 + cmd.append('--always-unzip') 7.318 + env = {} 7.319 + remove_from_env = [] 7.320 + if logger.stdout_level_matches(logger.DEBUG): 7.321 + cmd.append('-v') 7.322 + 7.323 + old_chdir = os.getcwd() 7.324 + if setup_fn is not None and os.path.exists(setup_fn): 7.325 + logger.info('Using existing %s egg: %s' % (project_name, setup_fn)) 7.326 + cmd.append(setup_fn) 7.327 + if os.environ.get('PYTHONPATH'): 7.328 + env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH'] 7.329 + else: 7.330 + env['PYTHONPATH'] = setup_fn 7.331 + else: 7.332 + # the source is found, let's chdir 7.333 + if source is not None and os.path.exists(source): 7.334 + os.chdir(os.path.dirname(source)) 7.335 + # in this case, we want to be sure that PYTHONPATH is unset (not 7.336 + # just empty, really unset), else CPython tries to import the 7.337 + # site.py that it's in virtualenv_support 7.338 + remove_from_env.append('PYTHONPATH') 7.339 + else: 7.340 + logger.info('No %s egg found; downloading' % project_name) 7.341 + cmd.extend(['--always-copy', '-U', project_name]) 7.342 + logger.start_progress('Installing %s...' % project_name) 7.343 + logger.indent += 2 7.344 + cwd = None 7.345 + if project_name == 'distribute': 7.346 + env['DONT_PATCH_SETUPTOOLS'] = 'true' 7.347 + 7.348 + def _filter_ez_setup(line): 7.349 + return filter_ez_setup(line, project_name) 7.350 + 7.351 + if not os.access(os.getcwd(), os.W_OK): 7.352 + cwd = tempfile.mkdtemp() 7.353 + if source is not None and os.path.exists(source): 7.354 + # the current working dir is hostile, let's copy the 7.355 + # tarball to a temp dir 7.356 + target = os.path.join(cwd, os.path.split(source)[-1]) 7.357 + shutil.copy(source, target) 7.358 + try: 7.359 + call_subprocess(cmd, show_stdout=False, 7.360 + filter_stdout=_filter_ez_setup, 7.361 + extra_env=env, 7.362 + remove_from_env=remove_from_env, 7.363 + cwd=cwd) 7.364 + finally: 7.365 + logger.indent -= 2 7.366 + logger.end_progress() 7.367 + if os.getcwd() != old_chdir: 7.368 + os.chdir(old_chdir) 7.369 + if is_jython and os._name == 'nt': 7.370 + os.remove(ez_setup) 7.371 + 7.372 +def file_search_dirs(): 7.373 + here = os.path.dirname(os.path.abspath(__file__)) 7.374 + dirs = ['.', here, 7.375 + join(here, 'virtualenv_support')] 7.376 + if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv': 7.377 + # Probably some boot script; just in case virtualenv is installed... 7.378 + try: 7.379 + import virtualenv 7.380 + except ImportError: 7.381 + pass 7.382 + else: 7.383 + dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support')) 7.384 + return [d for d in dirs if os.path.isdir(d)] 7.385 + 7.386 +def install_setuptools(py_executable, unzip=False): 7.387 + _install_req(py_executable, unzip) 7.388 + 7.389 +def install_distribute(py_executable, unzip=False): 7.390 + _install_req(py_executable, unzip, distribute=True) 7.391 + 7.392 +_pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I) 7.393 +def install_pip(py_executable): 7.394 + filenames = [] 7.395 + for dir in file_search_dirs(): 7.396 + filenames.extend([join(dir, fn) for fn in os.listdir(dir) 7.397 + if _pip_re.search(fn)]) 7.398 + filenames = [(os.path.basename(filename).lower(), i, filename) for i, filename in enumerate(filenames)] 7.399 + filenames.sort() 7.400 + filenames = [filename for basename, i, filename in filenames] 7.401 + if not filenames: 7.402 + filename = 'pip' 7.403 + else: 7.404 + filename = filenames[-1] 7.405 + easy_install_script = 'easy_install' 7.406 + if sys.platform == 'win32': 7.407 + easy_install_script = 'easy_install-script.py' 7.408 + cmd = [py_executable, join(os.path.dirname(py_executable), easy_install_script), filename] 7.409 + if filename == 'pip': 7.410 + logger.info('Installing pip from network...') 7.411 + else: 7.412 + logger.info('Installing %s' % os.path.basename(filename)) 7.413 + logger.indent += 2 7.414 + def _filter_setup(line): 7.415 + return filter_ez_setup(line, 'pip') 7.416 + try: 7.417 + call_subprocess(cmd, show_stdout=False, 7.418 + filter_stdout=_filter_setup) 7.419 + finally: 7.420 + logger.indent -= 2 7.421 + 7.422 +def filter_ez_setup(line, project_name='setuptools'): 7.423 + if not line.strip(): 7.424 + return Logger.DEBUG 7.425 + if project_name == 'distribute': 7.426 + for prefix in ('Extracting', 'Now working', 'Installing', 'Before', 7.427 + 'Scanning', 'Setuptools', 'Egg', 'Already', 7.428 + 'running', 'writing', 'reading', 'installing', 7.429 + 'creating', 'copying', 'byte-compiling', 'removing', 7.430 + 'Processing'): 7.431 + if line.startswith(prefix): 7.432 + return Logger.DEBUG 7.433 + return Logger.DEBUG 7.434 + for prefix in ['Reading ', 'Best match', 'Processing setuptools', 7.435 + 'Copying setuptools', 'Adding setuptools', 7.436 + 'Installing ', 'Installed ']: 7.437 + if line.startswith(prefix): 7.438 + return Logger.DEBUG 7.439 + return Logger.INFO 7.440 + 7.441 +def main(): 7.442 + parser = optparse.OptionParser( 7.443 + version=virtualenv_version, 7.444 + usage="%prog [OPTIONS] DEST_DIR") 7.445 + 7.446 + parser.add_option( 7.447 + '-v', '--verbose', 7.448 + action='count', 7.449 + dest='verbose', 7.450 + default=0, 7.451 + help="Increase verbosity") 7.452 + 7.453 + parser.add_option( 7.454 + '-q', '--quiet', 7.455 + action='count', 7.456 + dest='quiet', 7.457 + default=0, 7.458 + help='Decrease verbosity') 7.459 + 7.460 + parser.add_option( 7.461 + '-p', '--python', 7.462 + dest='python', 7.463 + metavar='PYTHON_EXE', 7.464 + help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 ' 7.465 + 'interpreter to create the new environment. The default is the interpreter that ' 7.466 + 'virtualenv was installed with (%s)' % sys.executable) 7.467 + 7.468 + parser.add_option( 7.469 + '--clear', 7.470 + dest='clear', 7.471 + action='store_true', 7.472 + help="Clear out the non-root install and start from scratch") 7.473 + 7.474 + parser.add_option( 7.475 + '--no-site-packages', 7.476 + dest='no_site_packages', 7.477 + action='store_true', 7.478 + help="Don't give access to the global site-packages dir to the " 7.479 + "virtual environment") 7.480 + 7.481 + parser.add_option( 7.482 + '--unzip-setuptools', 7.483 + dest='unzip_setuptools', 7.484 + action='store_true', 7.485 + help="Unzip Setuptools or Distribute when installing it") 7.486 + 7.487 + parser.add_option( 7.488 + '--relocatable', 7.489 + dest='relocatable', 7.490 + action='store_true', 7.491 + help='Make an EXISTING virtualenv environment relocatable. ' 7.492 + 'This fixes up scripts and makes all .pth files relative') 7.493 + 7.494 + parser.add_option( 7.495 + '--distribute', 7.496 + dest='use_distribute', 7.497 + action='store_true', 7.498 + help='Use Distribute instead of Setuptools. Set environ variable ' 7.499 + 'VIRTUALENV_USE_DISTRIBUTE to make it the default ') 7.500 + 7.501 + parser.add_option( 7.502 + '--prompt=', 7.503 + dest='prompt', 7.504 + help='Provides an alternative prompt prefix for this environment') 7.505 + 7.506 + if 'extend_parser' in globals(): 7.507 + extend_parser(parser) 7.508 + 7.509 + options, args = parser.parse_args() 7.510 + 7.511 + global logger 7.512 + 7.513 + if 'adjust_options' in globals(): 7.514 + adjust_options(options, args) 7.515 + 7.516 + verbosity = options.verbose - options.quiet 7.517 + logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)]) 7.518 + 7.519 + if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): 7.520 + env = os.environ.copy() 7.521 + interpreter = resolve_interpreter(options.python) 7.522 + if interpreter == sys.executable: 7.523 + logger.warn('Already using interpreter %s' % interpreter) 7.524 + else: 7.525 + logger.notify('Running virtualenv with interpreter %s' % interpreter) 7.526 + env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true' 7.527 + file = __file__ 7.528 + if file.endswith('.pyc'): 7.529 + file = file[:-1] 7.530 + popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env) 7.531 + raise SystemExit(popen.wait()) 7.532 + 7.533 + if not args: 7.534 + print 'You must provide a DEST_DIR' 7.535 + parser.print_help() 7.536 + sys.exit(2) 7.537 + if len(args) > 1: 7.538 + print 'There must be only one argument: DEST_DIR (you gave %s)' % ( 7.539 + ' '.join(args)) 7.540 + parser.print_help() 7.541 + sys.exit(2) 7.542 + 7.543 + home_dir = args[0] 7.544 + 7.545 + if os.environ.get('WORKING_ENV'): 7.546 + logger.fatal('ERROR: you cannot run virtualenv while in a workingenv') 7.547 + logger.fatal('Please deactivate your workingenv, then re-run this script') 7.548 + sys.exit(3) 7.549 + 7.550 + if 'PYTHONHOME' in os.environ: 7.551 + logger.warn('PYTHONHOME is set. You *must* activate the virtualenv before using it') 7.552 + del os.environ['PYTHONHOME'] 7.553 + 7.554 + if options.relocatable: 7.555 + make_environment_relocatable(home_dir) 7.556 + return 7.557 + 7.558 + create_environment(home_dir, site_packages=not options.no_site_packages, clear=options.clear, 7.559 + unzip_setuptools=options.unzip_setuptools, 7.560 + use_distribute=options.use_distribute, 7.561 + prompt=options.prompt) 7.562 + if 'after_install' in globals(): 7.563 + after_install(options, home_dir) 7.564 + 7.565 +def call_subprocess(cmd, show_stdout=True, 7.566 + filter_stdout=None, cwd=None, 7.567 + raise_on_returncode=True, extra_env=None, 7.568 + remove_from_env=None): 7.569 + cmd_parts = [] 7.570 + for part in cmd: 7.571 + if len(part) > 40: 7.572 + part = part[:30]+"..."+part[-5:] 7.573 + if ' ' in part or '\n' in part or '"' in part or "'" in part: 7.574 + part = '"%s"' % part.replace('"', '\\"') 7.575 + cmd_parts.append(part) 7.576 + cmd_desc = ' '.join(cmd_parts) 7.577 + if show_stdout: 7.578 + stdout = None 7.579 + else: 7.580 + stdout = subprocess.PIPE 7.581 + logger.debug("Running command %s" % cmd_desc) 7.582 + if extra_env or remove_from_env: 7.583 + env = os.environ.copy() 7.584 + if extra_env: 7.585 + env.update(extra_env) 7.586 + if remove_from_env: 7.587 + for varname in remove_from_env: 7.588 + env.pop(varname, None) 7.589 + else: 7.590 + env = None 7.591 + try: 7.592 + proc = subprocess.Popen( 7.593 + cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout, 7.594 + cwd=cwd, env=env) 7.595 + except Exception, e: 7.596 + logger.fatal( 7.597 + "Error %s while executing command %s" % (e, cmd_desc)) 7.598 + raise 7.599 + all_output = [] 7.600 + if stdout is not None: 7.601 + stdout = proc.stdout 7.602 + while 1: 7.603 + line = stdout.readline() 7.604 + if not line: 7.605 + break 7.606 + line = line.rstrip() 7.607 + all_output.append(line) 7.608 + if filter_stdout: 7.609 + level = filter_stdout(line) 7.610 + if isinstance(level, tuple): 7.611 + level, line = level 7.612 + logger.log(level, line) 7.613 + if not logger.stdout_level_matches(level): 7.614 + logger.show_progress() 7.615 + else: 7.616 + logger.info(line) 7.617 + else: 7.618 + proc.communicate() 7.619 + proc.wait() 7.620 + if proc.returncode: 7.621 + if raise_on_returncode: 7.622 + if all_output: 7.623 + logger.notify('Complete output from command %s:' % cmd_desc) 7.624 + logger.notify('\n'.join(all_output) + '\n----------------------------------------') 7.625 + raise OSError( 7.626 + "Command %s failed with error code %s" 7.627 + % (cmd_desc, proc.returncode)) 7.628 + else: 7.629 + logger.warn( 7.630 + "Command %s had error code %s" 7.631 + % (cmd_desc, proc.returncode)) 7.632 + 7.633 + 7.634 +def create_environment(home_dir, site_packages=True, clear=False, 7.635 + unzip_setuptools=False, use_distribute=False, 7.636 + prompt=None): 7.637 + """ 7.638 + Creates a new environment in ``home_dir``. 7.639 + 7.640 + If ``site_packages`` is true (the default) then the global 7.641 + ``site-packages/`` directory will be on the path. 7.642 + 7.643 + If ``clear`` is true (default False) then the environment will 7.644 + first be cleared. 7.645 + """ 7.646 + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) 7.647 + 7.648 + py_executable = os.path.abspath(install_python( 7.649 + home_dir, lib_dir, inc_dir, bin_dir, 7.650 + site_packages=site_packages, clear=clear)) 7.651 + 7.652 + install_distutils(home_dir) 7.653 + 7.654 + if use_distribute or os.environ.get('VIRTUALENV_USE_DISTRIBUTE'): 7.655 + install_distribute(py_executable, unzip=unzip_setuptools) 7.656 + else: 7.657 + install_setuptools(py_executable, unzip=unzip_setuptools) 7.658 + 7.659 + install_pip(py_executable) 7.660 + 7.661 + install_activate(home_dir, bin_dir, prompt) 7.662 + 7.663 +def path_locations(home_dir): 7.664 + """Return the path locations for the environment (where libraries are, 7.665 + where scripts go, etc)""" 7.666 + # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its 7.667 + # prefix arg is broken: http://bugs.python.org/issue3386 7.668 + if sys.platform == 'win32': 7.669 + # Windows has lots of problems with executables with spaces in 7.670 + # the name; this function will remove them (using the ~1 7.671 + # format): 7.672 + mkdir(home_dir) 7.673 + if ' ' in home_dir: 7.674 + try: 7.675 + import win32api 7.676 + except ImportError: 7.677 + print 'Error: the path "%s" has a space in it' % home_dir 7.678 + print 'To handle these kinds of paths, the win32api module must be installed:' 7.679 + print ' http://sourceforge.net/projects/pywin32/' 7.680 + sys.exit(3) 7.681 + home_dir = win32api.GetShortPathName(home_dir) 7.682 + lib_dir = join(home_dir, 'Lib') 7.683 + inc_dir = join(home_dir, 'Include') 7.684 + bin_dir = join(home_dir, 'Scripts') 7.685 + elif is_jython: 7.686 + lib_dir = join(home_dir, 'Lib') 7.687 + inc_dir = join(home_dir, 'Include') 7.688 + bin_dir = join(home_dir, 'bin') 7.689 + elif is_pypy: 7.690 + lib_dir = home_dir 7.691 + inc_dir = join(home_dir, 'include') 7.692 + bin_dir = join(home_dir, 'bin') 7.693 + else: 7.694 + lib_dir = join(home_dir, 'lib', py_version) 7.695 + inc_dir = join(home_dir, 'include', py_version) 7.696 + bin_dir = join(home_dir, 'bin') 7.697 + return home_dir, lib_dir, inc_dir, bin_dir 7.698 + 7.699 + 7.700 +def change_prefix(filename, dst_prefix): 7.701 + prefixes = [sys.prefix] 7.702 + if hasattr(sys, 'real_prefix'): 7.703 + prefixes.append(sys.real_prefix) 7.704 + prefixes = map(os.path.abspath, prefixes) 7.705 + filename = os.path.abspath(filename) 7.706 + for src_prefix in prefixes: 7.707 + if filename.startswith(src_prefix): 7.708 + _, relpath = filename.split(src_prefix, 1) 7.709 + assert relpath[0] == os.sep 7.710 + relpath = relpath[1:] 7.711 + return join(dst_prefix, relpath) 7.712 + assert False, "Filename %s does not start with any of these prefixes: %s" % \ 7.713 + (filename, prefixes) 7.714 + 7.715 +def copy_required_modules(dst_prefix): 7.716 + import imp 7.717 + for modname in REQUIRED_MODULES: 7.718 + if modname in sys.builtin_module_names: 7.719 + logger.info("Ignoring built-in bootstrap module: %s" % modname) 7.720 + continue 7.721 + try: 7.722 + f, filename, _ = imp.find_module(modname) 7.723 + except ImportError: 7.724 + logger.info("Cannot import bootstrap module: %s" % modname) 7.725 + else: 7.726 + if f is not None: 7.727 + f.close() 7.728 + dst_filename = change_prefix(filename, dst_prefix) 7.729 + copyfile(filename, dst_filename) 7.730 + if filename.endswith('.pyc'): 7.731 + pyfile = filename[:-1] 7.732 + if os.path.exists(pyfile): 7.733 + copyfile(pyfile, dst_filename[:-1]) 7.734 + 7.735 + 7.736 +def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear): 7.737 + """Install just the base environment, no distutils patches etc""" 7.738 + if sys.executable.startswith(bin_dir): 7.739 + print 'Please use the *system* python to run this script' 7.740 + return 7.741 + 7.742 + if clear: 7.743 + rmtree(lib_dir) 7.744 + ## FIXME: why not delete it? 7.745 + ## Maybe it should delete everything with #!/path/to/venv/python in it 7.746 + logger.notify('Not deleting %s', bin_dir) 7.747 + 7.748 + if hasattr(sys, 'real_prefix'): 7.749 + logger.notify('Using real prefix %r' % sys.real_prefix) 7.750 + prefix = sys.real_prefix 7.751 + else: 7.752 + prefix = sys.prefix 7.753 + mkdir(lib_dir) 7.754 + fix_lib64(lib_dir) 7.755 + stdlib_dirs = [os.path.dirname(os.__file__)] 7.756 + if sys.platform == 'win32': 7.757 + stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs')) 7.758 + elif sys.platform == 'darwin': 7.759 + stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages')) 7.760 + if hasattr(os, 'symlink'): 7.761 + logger.info('Symlinking Python bootstrap modules') 7.762 + else: 7.763 + logger.info('Copying Python bootstrap modules') 7.764 + logger.indent += 2 7.765 + try: 7.766 + # copy required files... 7.767 + for stdlib_dir in stdlib_dirs: 7.768 + if not os.path.isdir(stdlib_dir): 7.769 + continue 7.770 + for fn in os.listdir(stdlib_dir): 7.771 + if fn != 'site-packages' and os.path.splitext(fn)[0] in REQUIRED_FILES: 7.772 + copyfile(join(stdlib_dir, fn), join(lib_dir, fn)) 7.773 + # ...and modules 7.774 + copy_required_modules(home_dir) 7.775 + finally: 7.776 + logger.indent -= 2 7.777 + mkdir(join(lib_dir, 'site-packages')) 7.778 + import site 7.779 + site_filename = site.__file__ 7.780 + if site_filename.endswith('.pyc'): 7.781 + site_filename = site_filename[:-1] 7.782 + elif site_filename.endswith('$py.class'): 7.783 + site_filename = site_filename.replace('$py.class', '.py') 7.784 + site_filename_dst = change_prefix(site_filename, home_dir) 7.785 + site_dir = os.path.dirname(site_filename_dst) 7.786 + writefile(site_filename_dst, SITE_PY) 7.787 + writefile(join(site_dir, 'orig-prefix.txt'), prefix) 7.788 + site_packages_filename = join(site_dir, 'no-global-site-packages.txt') 7.789 + if not site_packages: 7.790 + writefile(site_packages_filename, '') 7.791 + else: 7.792 + if os.path.exists(site_packages_filename): 7.793 + logger.info('Deleting %s' % site_packages_filename) 7.794 + os.unlink(site_packages_filename) 7.795 + 7.796 + if is_pypy: 7.797 + stdinc_dir = join(prefix, 'include') 7.798 + else: 7.799 + stdinc_dir = join(prefix, 'include', py_version) 7.800 + if os.path.exists(stdinc_dir): 7.801 + copyfile(stdinc_dir, inc_dir) 7.802 + else: 7.803 + logger.debug('No include dir %s' % stdinc_dir) 7.804 + 7.805 + if sys.exec_prefix != prefix: 7.806 + if sys.platform == 'win32': 7.807 + exec_dir = join(sys.exec_prefix, 'lib') 7.808 + elif is_jython: 7.809 + exec_dir = join(sys.exec_prefix, 'Lib') 7.810 + else: 7.811 + exec_dir = join(sys.exec_prefix, 'lib', py_version) 7.812 + for fn in os.listdir(exec_dir): 7.813 + copyfile(join(exec_dir, fn), join(lib_dir, fn)) 7.814 + 7.815 + if is_jython: 7.816 + # Jython has either jython-dev.jar and javalib/ dir, or just 7.817 + # jython.jar 7.818 + for name in 'jython-dev.jar', 'javalib', 'jython.jar': 7.819 + src = join(prefix, name) 7.820 + if os.path.exists(src): 7.821 + copyfile(src, join(home_dir, name)) 7.822 + # XXX: registry should always exist after Jython 2.5rc1 7.823 + src = join(prefix, 'registry') 7.824 + if os.path.exists(src): 7.825 + copyfile(src, join(home_dir, 'registry'), symlink=False) 7.826 + copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'), 7.827 + symlink=False) 7.828 + 7.829 + mkdir(bin_dir) 7.830 + py_executable = join(bin_dir, os.path.basename(sys.executable)) 7.831 + if 'Python.framework' in prefix: 7.832 + if re.search(r'/Python(?:-32|-64)*$', py_executable): 7.833 + # The name of the python executable is not quite what 7.834 + # we want, rename it. 7.835 + py_executable = os.path.join( 7.836 + os.path.dirname(py_executable), 'python') 7.837 + 7.838 + logger.notify('New %s executable in %s', expected_exe, py_executable) 7.839 + if sys.executable != py_executable: 7.840 + ## FIXME: could I just hard link? 7.841 + executable = sys.executable 7.842 + if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'): 7.843 + # Cygwin misreports sys.executable sometimes 7.844 + executable += '.exe' 7.845 + py_executable += '.exe' 7.846 + logger.info('Executable actually exists in %s' % executable) 7.847 + shutil.copyfile(executable, py_executable) 7.848 + make_exe(py_executable) 7.849 + if sys.platform == 'win32' or sys.platform == 'cygwin': 7.850 + pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe') 7.851 + if os.path.exists(pythonw): 7.852 + logger.info('Also created pythonw.exe') 7.853 + shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe')) 7.854 + if is_pypy: 7.855 + # make a symlink python --> pypy-c 7.856 + python_executable = os.path.join(os.path.dirname(py_executable), 'python') 7.857 + logger.info('Also created executable %s' % python_executable) 7.858 + copyfile(py_executable, python_executable) 7.859 + 7.860 + if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe: 7.861 + secondary_exe = os.path.join(os.path.dirname(py_executable), 7.862 + expected_exe) 7.863 + py_executable_ext = os.path.splitext(py_executable)[1] 7.864 + if py_executable_ext == '.exe': 7.865 + # python2.4 gives an extension of '.4' :P 7.866 + secondary_exe += py_executable_ext 7.867 + if os.path.exists(secondary_exe): 7.868 + logger.warn('Not overwriting existing %s script %s (you must use %s)' 7.869 + % (expected_exe, secondary_exe, py_executable)) 7.870 + else: 7.871 + logger.notify('Also creating executable in %s' % secondary_exe) 7.872 + shutil.copyfile(sys.executable, secondary_exe) 7.873 + make_exe(secondary_exe) 7.874 + 7.875 + if 'Python.framework' in prefix: 7.876 + logger.debug('MacOSX Python framework detected') 7.877 + 7.878 + # Make sure we use the the embedded interpreter inside 7.879 + # the framework, even if sys.executable points to 7.880 + # the stub executable in ${sys.prefix}/bin 7.881 + # See http://groups.google.com/group/python-virtualenv/ 7.882 + # browse_thread/thread/17cab2f85da75951 7.883 + original_python = os.path.join( 7.884 + prefix, 'Resources/Python.app/Contents/MacOS/Python') 7.885 + shutil.copy(original_python, py_executable) 7.886 + 7.887 + # Copy the framework's dylib into the virtual 7.888 + # environment 7.889 + virtual_lib = os.path.join(home_dir, '.Python') 7.890 + 7.891 + if os.path.exists(virtual_lib): 7.892 + os.unlink(virtual_lib) 7.893 + copyfile( 7.894 + os.path.join(prefix, 'Python'), 7.895 + virtual_lib) 7.896 + 7.897 + # And then change the install_name of the copied python executable 7.898 + try: 7.899 + call_subprocess( 7.900 + ["install_name_tool", "-change", 7.901 + os.path.join(prefix, 'Python'), 7.902 + '@executable_path/../.Python', 7.903 + py_executable]) 7.904 + except: 7.905 + logger.fatal( 7.906 + "Could not call install_name_tool -- you must have Apple's development tools installed") 7.907 + raise 7.908 + 7.909 + # Some tools depend on pythonX.Y being present 7.910 + py_executable_version = '%s.%s' % ( 7.911 + sys.version_info[0], sys.version_info[1]) 7.912 + if not py_executable.endswith(py_executable_version): 7.913 + # symlinking pythonX.Y > python 7.914 + pth = py_executable + '%s.%s' % ( 7.915 + sys.version_info[0], sys.version_info[1]) 7.916 + if os.path.exists(pth): 7.917 + os.unlink(pth) 7.918 + os.symlink('python', pth) 7.919 + else: 7.920 + # reverse symlinking python -> pythonX.Y (with --python) 7.921 + pth = join(bin_dir, 'python') 7.922 + if os.path.exists(pth): 7.923 + os.unlink(pth) 7.924 + os.symlink(os.path.basename(py_executable), pth) 7.925 + 7.926 + if sys.platform == 'win32' and ' ' in py_executable: 7.927 + # There's a bug with subprocess on Windows when using a first 7.928 + # argument that has a space in it. Instead we have to quote 7.929 + # the value: 7.930 + py_executable = '"%s"' % py_executable 7.931 + cmd = [py_executable, '-c', 'import sys; print sys.prefix'] 7.932 + logger.info('Testing executable with %s %s "%s"' % tuple(cmd)) 7.933 + proc = subprocess.Popen(cmd, 7.934 + stdout=subprocess.PIPE) 7.935 + proc_stdout, proc_stderr = proc.communicate() 7.936 + proc_stdout = os.path.normcase(os.path.abspath(proc_stdout.strip())) 7.937 + if proc_stdout != os.path.normcase(os.path.abspath(home_dir)): 7.938 + logger.fatal( 7.939 + 'ERROR: The executable %s is not functioning' % py_executable) 7.940 + logger.fatal( 7.941 + 'ERROR: It thinks sys.prefix is %r (should be %r)' 7.942 + % (proc_stdout, os.path.normcase(os.path.abspath(home_dir)))) 7.943 + logger.fatal( 7.944 + 'ERROR: virtualenv is not compatible with this system or executable') 7.945 + if sys.platform == 'win32': 7.946 + logger.fatal( 7.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)') 7.948 + sys.exit(100) 7.949 + else: 7.950 + logger.info('Got sys.prefix result: %r' % proc_stdout) 7.951 + 7.952 + pydistutils = os.path.expanduser('~/.pydistutils.cfg') 7.953 + if os.path.exists(pydistutils): 7.954 + logger.notify('Please make sure you remove any previous custom paths from ' 7.955 + 'your %s file.' % pydistutils) 7.956 + ## FIXME: really this should be calculated earlier 7.957 + return py_executable 7.958 + 7.959 +def install_activate(home_dir, bin_dir, prompt=None): 7.960 + if sys.platform == 'win32' or is_jython and os._name == 'nt': 7.961 + files = {'activate.bat': ACTIVATE_BAT, 7.962 + 'deactivate.bat': DEACTIVATE_BAT} 7.963 + if os.environ.get('OS') == 'Windows_NT' and os.environ.get('OSTYPE') == 'cygwin': 7.964 + files['activate'] = ACTIVATE_SH 7.965 + else: 7.966 + files = {'activate': ACTIVATE_SH} 7.967 + 7.968 + # suppling activate.fish in addition to, not instead of, the 7.969 + # bash script support. 7.970 + files['activate.fish'] = ACTIVATE_FISH 7.971 + 7.972 + # same for csh/tcsh support... 7.973 + files['activate.csh'] = ACTIVATE_CSH 7.974 + 7.975 + 7.976 + 7.977 + files['activate_this.py'] = ACTIVATE_THIS 7.978 + vname = os.path.basename(os.path.abspath(home_dir)) 7.979 + for name, content in files.items(): 7.980 + content = content.replace('__VIRTUAL_PROMPT__', prompt or '') 7.981 + content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname) 7.982 + content = content.replace('__VIRTUAL_ENV__', os.path.abspath(home_dir)) 7.983 + content = content.replace('__VIRTUAL_NAME__', vname) 7.984 + content = content.replace('__BIN_NAME__', os.path.basename(bin_dir)) 7.985 + writefile(os.path.join(bin_dir, name), content) 7.986 + 7.987 +def install_distutils(home_dir): 7.988 + distutils_path = change_prefix(distutils.__path__[0], home_dir) 7.989 + mkdir(distutils_path) 7.990 + ## FIXME: maybe this prefix setting should only be put in place if 7.991 + ## there's a local distutils.cfg with a prefix setting? 7.992 + home_dir = os.path.abspath(home_dir) 7.993 + ## FIXME: this is breaking things, removing for now: 7.994 + #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir 7.995 + writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT) 7.996 + writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False) 7.997 + 7.998 +def fix_lib64(lib_dir): 7.999 + """ 7.1000 + Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y 7.1001 + instead of lib/pythonX.Y. If this is such a platform we'll just create a 7.1002 + symlink so lib64 points to lib 7.1003 + """ 7.1004 + if [p for p in distutils.sysconfig.get_config_vars().values() 7.1005 + if isinstance(p, basestring) and 'lib64' in p]: 7.1006 + logger.debug('This system uses lib64; symlinking lib64 to lib') 7.1007 + assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], ( 7.1008 + "Unexpected python lib dir: %r" % lib_dir) 7.1009 + lib_parent = os.path.dirname(lib_dir) 7.1010 + assert os.path.basename(lib_parent) == 'lib', ( 7.1011 + "Unexpected parent dir: %r" % lib_parent) 7.1012 + copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64')) 7.1013 + 7.1014 +def resolve_interpreter(exe): 7.1015 + """ 7.1016 + If the executable given isn't an absolute path, search $PATH for the interpreter 7.1017 + """ 7.1018 + if os.path.abspath(exe) != exe: 7.1019 + paths = os.environ.get('PATH', '').split(os.pathsep) 7.1020 + for path in paths: 7.1021 + if os.path.exists(os.path.join(path, exe)): 7.1022 + exe = os.path.join(path, exe) 7.1023 + break 7.1024 + if not os.path.exists(exe): 7.1025 + logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe)) 7.1026 + sys.exit(3) 7.1027 + return exe 7.1028 + 7.1029 +############################################################ 7.1030 +## Relocating the environment: 7.1031 + 7.1032 +def make_environment_relocatable(home_dir): 7.1033 + """ 7.1034 + Makes the already-existing environment use relative paths, and takes out 7.1035 + the #!-based environment selection in scripts. 7.1036 + """ 7.1037 + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) 7.1038 + activate_this = os.path.join(bin_dir, 'activate_this.py') 7.1039 + if not os.path.exists(activate_this): 7.1040 + logger.fatal( 7.1041 + 'The environment doesn\'t have a file %s -- please re-run virtualenv ' 7.1042 + 'on this environment to update it' % activate_this) 7.1043 + fixup_scripts(home_dir) 7.1044 + fixup_pth_and_egg_link(home_dir) 7.1045 + ## FIXME: need to fix up distutils.cfg 7.1046 + 7.1047 +OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3], 7.1048 + 'activate', 'activate.bat', 'activate_this.py'] 7.1049 + 7.1050 +def fixup_scripts(home_dir): 7.1051 + # This is what we expect at the top of scripts: 7.1052 + shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir)) 7.1053 + # This is what we'll put: 7.1054 + new_shebang = '#!/usr/bin/env python%s' % sys.version[:3] 7.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" 7.1056 + if sys.platform == 'win32': 7.1057 + bin_suffix = 'Scripts' 7.1058 + else: 7.1059 + bin_suffix = 'bin' 7.1060 + bin_dir = os.path.join(home_dir, bin_suffix) 7.1061 + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) 7.1062 + for filename in os.listdir(bin_dir): 7.1063 + filename = os.path.join(bin_dir, filename) 7.1064 + if not os.path.isfile(filename): 7.1065 + # ignore subdirs, e.g. .svn ones. 7.1066 + continue 7.1067 + f = open(filename, 'rb') 7.1068 + lines = f.readlines() 7.1069 + f.close() 7.1070 + if not lines: 7.1071 + logger.warn('Script %s is an empty file' % filename) 7.1072 + continue 7.1073 + if not lines[0].strip().startswith(shebang): 7.1074 + if os.path.basename(filename) in OK_ABS_SCRIPTS: 7.1075 + logger.debug('Cannot make script %s relative' % filename) 7.1076 + elif lines[0].strip() == new_shebang: 7.1077 + logger.info('Script %s has already been made relative' % filename) 7.1078 + else: 7.1079 + logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)' 7.1080 + % (filename, shebang)) 7.1081 + continue 7.1082 + logger.notify('Making script %s relative' % filename) 7.1083 + lines = [new_shebang+'\n', activate+'\n'] + lines[1:] 7.1084 + f = open(filename, 'wb') 7.1085 + f.writelines(lines) 7.1086 + f.close() 7.1087 + 7.1088 +def fixup_pth_and_egg_link(home_dir, sys_path=None): 7.1089 + """Makes .pth and .egg-link files use relative paths""" 7.1090 + home_dir = os.path.normcase(os.path.abspath(home_dir)) 7.1091 + if sys_path is None: 7.1092 + sys_path = sys.path 7.1093 + for path in sys_path: 7.1094 + if not path: 7.1095 + path = '.' 7.1096 + if not os.path.isdir(path): 7.1097 + continue 7.1098 + path = os.path.normcase(os.path.abspath(path)) 7.1099 + if not path.startswith(home_dir): 7.1100 + logger.debug('Skipping system (non-environment) directory %s' % path) 7.1101 + continue 7.1102 + for filename in os.listdir(path): 7.1103 + filename = os.path.join(path, filename) 7.1104 + if filename.endswith('.pth'): 7.1105 + if not os.access(filename, os.W_OK): 7.1106 + logger.warn('Cannot write .pth file %s, skipping' % filename) 7.1107 + else: 7.1108 + fixup_pth_file(filename) 7.1109 + if filename.endswith('.egg-link'): 7.1110 + if not os.access(filename, os.W_OK): 7.1111 + logger.warn('Cannot write .egg-link file %s, skipping' % filename) 7.1112 + else: 7.1113 + fixup_egg_link(filename) 7.1114 + 7.1115 +def fixup_pth_file(filename): 7.1116 + lines = [] 7.1117 + prev_lines = [] 7.1118 + f = open(filename) 7.1119 + prev_lines = f.readlines() 7.1120 + f.close() 7.1121 + for line in prev_lines: 7.1122 + line = line.strip() 7.1123 + if (not line or line.startswith('#') or line.startswith('import ') 7.1124 + or os.path.abspath(line) != line): 7.1125 + lines.append(line) 7.1126 + else: 7.1127 + new_value = make_relative_path(filename, line) 7.1128 + if line != new_value: 7.1129 + logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename)) 7.1130 + lines.append(new_value) 7.1131 + if lines == prev_lines: 7.1132 + logger.info('No changes to .pth file %s' % filename) 7.1133 + return 7.1134 + logger.notify('Making paths in .pth file %s relative' % filename) 7.1135 + f = open(filename, 'w') 7.1136 + f.write('\n'.join(lines) + '\n') 7.1137 + f.close() 7.1138 + 7.1139 +def fixup_egg_link(filename): 7.1140 + f = open(filename) 7.1141 + link = f.read().strip() 7.1142 + f.close() 7.1143 + if os.path.abspath(link) != link: 7.1144 + logger.debug('Link in %s already relative' % filename) 7.1145 + return 7.1146 + new_link = make_relative_path(filename, link) 7.1147 + logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link)) 7.1148 + f = open(filename, 'w') 7.1149 + f.write(new_link) 7.1150 + f.close() 7.1151 + 7.1152 +def make_relative_path(source, dest, dest_is_directory=True): 7.1153 + """ 7.1154 + Make a filename relative, where the filename is dest, and it is 7.1155 + being referred to from the filename source. 7.1156 + 7.1157 + >>> make_relative_path('/usr/share/something/a-file.pth', 7.1158 + ... '/usr/share/another-place/src/Directory') 7.1159 + '../another-place/src/Directory' 7.1160 + >>> make_relative_path('/usr/share/something/a-file.pth', 7.1161 + ... '/home/user/src/Directory') 7.1162 + '../../../home/user/src/Directory' 7.1163 + >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/') 7.1164 + './' 7.1165 + """ 7.1166 + source = os.path.dirname(source) 7.1167 + if not dest_is_directory: 7.1168 + dest_filename = os.path.basename(dest) 7.1169 + dest = os.path.dirname(dest) 7.1170 + dest = os.path.normpath(os.path.abspath(dest)) 7.1171 + source = os.path.normpath(os.path.abspath(source)) 7.1172 + dest_parts = dest.strip(os.path.sep).split(os.path.sep) 7.1173 + source_parts = source.strip(os.path.sep).split(os.path.sep) 7.1174 + while dest_parts and source_parts and dest_parts[0] == source_parts[0]: 7.1175 + dest_parts.pop(0) 7.1176 + source_parts.pop(0) 7.1177 + full_parts = ['..']*len(source_parts) + dest_parts 7.1178 + if not dest_is_directory: 7.1179 + full_parts.append(dest_filename) 7.1180 + if not full_parts: 7.1181 + # Special case for the current directory (otherwise it'd be '') 7.1182 + return './' 7.1183 + return os.path.sep.join(full_parts) 7.1184 + 7.1185 + 7.1186 + 7.1187 +############################################################ 7.1188 +## Bootstrap script creation: 7.1189 + 7.1190 +def create_bootstrap_script(extra_text, python_version=''): 7.1191 + """ 7.1192 + Creates a bootstrap script, which is like this script but with 7.1193 + extend_parser, adjust_options, and after_install hooks. 7.1194 + 7.1195 + This returns a string that (written to disk of course) can be used 7.1196 + as a bootstrap script with your own customizations. The script 7.1197 + will be the standard virtualenv.py script, with your extra text 7.1198 + added (your extra text should be Python code). 7.1199 + 7.1200 + If you include these functions, they will be called: 7.1201 + 7.1202 + ``extend_parser(optparse_parser)``: 7.1203 + You can add or remove options from the parser here. 7.1204 + 7.1205 + ``adjust_options(options, args)``: 7.1206 + You can change options here, or change the args (if you accept 7.1207 + different kinds of arguments, be sure you modify ``args`` so it is 7.1208 + only ``[DEST_DIR]``). 7.1209 + 7.1210 + ``after_install(options, home_dir)``: 7.1211 + 7.1212 + After everything is installed, this function is called. This 7.1213 + is probably the function you are most likely to use. An 7.1214 + example would be:: 7.1215 + 7.1216 + def after_install(options, home_dir): 7.1217 + subprocess.call([join(home_dir, 'bin', 'easy_install'), 7.1218 + 'MyPackage']) 7.1219 + subprocess.call([join(home_dir, 'bin', 'my-package-script'), 7.1220 + 'setup', home_dir]) 7.1221 + 7.1222 + This example immediately installs a package, and runs a setup 7.1223 + script from that package. 7.1224 + 7.1225 + If you provide something like ``python_version='2.4'`` then the 7.1226 + script will start with ``#!/usr/bin/env python2.4`` instead of 7.1227 + ``#!/usr/bin/env python``. You can use this when the script must 7.1228 + be run with a particular Python version. 7.1229 + """ 7.1230 + filename = __file__ 7.1231 + if filename.endswith('.pyc'): 7.1232 + filename = filename[:-1] 7.1233 + f = open(filename, 'rb') 7.1234 + content = f.read() 7.1235 + f.close() 7.1236 + py_exe = 'python%s' % python_version 7.1237 + content = (('#!/usr/bin/env %s\n' % py_exe) 7.1238 + + '## WARNING: This file is generated\n' 7.1239 + + content) 7.1240 + return content.replace('##EXT' 'END##', extra_text) 7.1241 + 7.1242 +##EXTEND## 7.1243 + 7.1244 +##file site.py 7.1245 +SITE_PY = """ 7.1246 +eJzVPP1z2zaWv/OvQOXJUEplOh/dzo5T98ZJnNZ7buJt0mluXY+WkiCJNUWyBGlZe3P3t9/7AECA 7.1247 +pGS77f5wmkwskcDDw8P7xgMGg8FpUchsLtb5vE6lUDIuZytRxNVKiUVeimqVlPPDIi6rLTyd3cRL 7.1248 +qUSVC7VVEbaKguDpH/wET8WnVaIMCvAtrqt8HVfJLE7TrUjWRV5Wci7mdZlkS5FkSZXEafIvaJFn 7.1249 +kXj6xzEIzjMBM08TWYpbWSqAq0S+EJfbapVnYlgXOOfn0V/il6OxULMyKSpoUGqcgSKruAoyKeeA 7.1250 +JrSsFZAyqeShKuQsWSQz23CT1+lcFGk8k+Kf/+SpUdMwDFS+lpuVLKXIABmAKQFWgXjA16QUs3wu 7.1251 +IyFey1mMA/DzhlgBQxvjmikkY5aLNM+WMKdMzqRScbkVw2ldESBCWcxzwCkBDKokTYNNXt6oESwp 7.1252 +rccGHomY2cOfDLMHzBPH73IO4PghC37KkrsxwwbuQXDVitmmlIvkTsQIFn7KOzmb6GfDZCHmyWIB 7.1253 +NMiqETYJGAEl0mR6VNByfKNX6NsjwspyZQxjSESZG/NL6hEF55WIUwVsWxdII0WYv5XTJM6AGtkt 7.1254 +DAcQgaRB3zjzRFV2HJqdyAFAietYgZSslRiu4yQDZv0hnhHaPyfZPN+oEVEAVkuJX2tVufMf9hAA 7.1255 +WjsEGAe4WGY16yxNbmS6HQECnwD7Uqo6rVAg5kkpZ1VeJlIRAEBtK+QdID0WcSk1CZkzjdyOif5E 7.1256 +kyTDhUUBQ4HHl0iSRbKsS5IwsUiAc4Er3n34Ubw9e31++l7zmAHGMrtcA84AhRbawQkGEEe1Ko/S 7.1257 +HAQ6Ci7wj4jncxSyJY4PeDUNju5d6WAIcy+idh9nwYHsenH1MDDHCpQJjRVQv/+GLmO1Avr8zz3r 7.1258 +HQSnu6hCE+dvm1UOMpnFaylWMfMXckbwjYbzbVRUq1fADQrhVEAqhYuDCCYID0ji0myYZ1IUwGJp 7.1259 +kslRABSaUlt/FYEV3ufZIa11ixMAQhlk8NJ5NqIRMwkT7cJ6hfrCNN7SzHSTwK7zOi9JcQD/ZzPS 7.1260 +RWmc3RCOihiKv03lMskyRAh5IQgPQhpY3STAifNIXFAr0gumkQhZe3FLFIkaeAmZDnhS3sXrIpVj 7.1261 +Fl/UrfvVCA0mK2HWOmWOg5YVqVdatWaqvbz3Ivrc4jpCs1qVEoDXU0/oFnk+FlPQ2YRNEa9ZvKpN 7.1262 +TpwT9MgTdUKeoJbQF78DRU+VqtfSvkReAc1CDBUs8jTNN0Cy4yAQ4gAbGaPsMye8hXfwP8DF/1NZ 7.1263 +zVZB4IxkAWtQiPwuUAgETILMNFdrJDxu06zcVjJJxpoiL+eypKEeRuwjRvyBjXGuwfu80kaNp4ur 7.1264 +nK+TClXSVJvMhC1eFlasH1/xvGEaYLkV0cw0bei0xumlxSqeSuOSTOUCJUEv0iu77DBm0DMm2eJK 7.1265 +rNnKwDsgi0zYgvQrFlQ6i0qSEwAwWPjiLCnqlBopZDARw0DrguCvYzTpuXaWgL3ZLAeokNh8z8D+ 7.1266 +AG7/AjHarBKgzwwggIZBLQXLN02qEh2ERh8FvtE3/Xl84NTzhbZNPOQiTlJt5eMsOKeHZ2VJ4juT 7.1267 +BfYaa2IomGFWoWu3zICOKOaDwSAIjDu0VeZrbr9NJtM6QXs3mQRVuT0G7hAo5AFDF+9hojQcv1mU 7.1268 ++RpfW/Q+gj4AvYw9ggNxSYpCso/rMdMrpICrlQvTFM2vw5ECVUlw+ePZu/PPZx/FibhqtNK4rZKu 7.1269 +YcyzLAbOJKUOfNEatlFH0BJ1V4LqS7wDC03rCiaJepMEyriqgf0A9U9lTa9hGjPvZXD2/vT1xdnk 7.1270 +p49nP04+nn86AwTBVMjggKaMFq4Gn09FwN/AWHMVaRMZdHrQg9enH+2DYJKoSbEttvAAbB1wYTmE 7.1271 ++Y5FiA8n2oxOkmyRhyNq/Cv70SesGbTTdHX81bU4ORHhr/FtHAbguDRNeRF/IB7+tC0kdK3gzzBX 7.1272 +oyCYywXw+41EqRg+JWd0xB2AiNAy18bx1zzJzHt67Q1BQjukHoDDZDJLY6Ww8WQSAmmpQ88HOkTs 7.1273 +0SKrD6FjsXW7jjQq+CklLEWGXcb4Xw+K8ZT6IRqMotvFNAIZWc9iJbkVTR/6TSaoKCaToR4QJIh4 7.1274 +HLwclv1QmCaoKMoEnEniFVQcU5Wn+BPho+iRyGA8g6oJF0nHK9FtnNZSDZ1JARGHwxYZUbslijgI 7.1275 +/IIhmL9m6UajNjUNz0AzIF+ag+oqW5TDzwE4GaAjTOSE0RUHPEwzxPRv7N4TDuDnhahjlWpBYZUk 7.1276 +Ls8uxctnLw7Rh4BAb26p4zVHs5hktbQPF7BaS1k5CHOvcEzCMHLpskDlhk+P98NcR3Zluqyw0Etc 7.1277 +ynV+K+eALTKws8riR3oD4TDMYxbDKoIyJSPMSs84azEGfzx7kBY02EC9NUEx62+W/oAjcJkpUB0c 7.1278 +zRKpdajN9qco89sELfx0q1+CgQL1hmbKeBOBs3Aek6EdAg0BrmeGlNrIEBRYWbOXSHgjSFTx80YV 7.1279 +RgTuAnXrNX29yfJNNuHw8wTV5HBkWRcFSzMvNmiW4EC8A8MBSOYQTTVEYyjgZwuUrUNAHqYP0wXK 7.1280 +kkMPgMC6KoqRHFgmvqIpcqiGwyKM0StBwltKNNK3ZgiKbwwxHEj0NrIPjJZASDA5q+CsatBMhrJm 7.1281 +msHADkl8rruIOO7zAbSoGIGhG2po3MjQ7+oYlLO4cJWS0w9t6OfPn5lt1IqSGojYFCeNdntB5i0q 7.1282 +tmAKE9AJxg3iFAmxwQY8SgBTK82a4vCjyAt2gWA9L7Vsg+WGkKqqiuOjo81mE+mQPi+XR2px9Je/ 7.1283 +fv31X5+xTpzPiX9gOo606PxWdETv0I2MvjEW6Fuzci1+TDKfGwnWUJIrRP4f4vddncxzcXw4svoT 7.1284 +ubgxrPi/cT5AgUzMoExloO2gweiJOnwSvVQD8UQM3bbDEXsS2qRaK+ZbXehR5WC7wdOY5XVWhY4i 7.1285 +VeJLsG4QFs/ltF6GdnDPRpofMFWU06HlgcPn14iBzxmGr4wpnqCWILZAi++Q/kdmm5j8Ga0hkLxo 7.1286 +ojoh67Zfixnizh8u79Y7dITGzDBRyB0oEX6TBwugbdyVHPxoZxTtnuOMmo9nCIylDwzzaldwiIJD 7.1287 +uOBajF2pc7gafVSQpg2rZlAwrmoEBQ1u3ZSprcGRjQwRJHo3JsLmhdUtgE6tdJ0Jys0qQAt3nI61 7.1288 +a7OC4wkhD5yI5/REglN73Hn3jJe2TlPKorR41KMKA/YWGu10Dnw5NADGYlD+NOCWelnOP7QWhdeg 7.1289 +B1jOiRdksEWHmfCN6wMODgY97NSx+rt6M437QOAiUfuHASeMT3iAUoEwFUOfcXdxuKUtJ5taCO82 7.1290 +OMRTZpVIotUO2Wrrjl6Z2muXFkmGqtdZo2iW5uAUW6VIfNS8930FClzwcZ8t0wKoydCQw2l0Qs6e 7.1291 +J3+hbocpq2WNwb2b+0CM1oki44ZkWsF/4FVQToESQEBLgmbBPFTI/In9CSJn56u/7GAPS2hkCLfp 7.1292 +Li+kYzA0HPP+QCAZdQYEhCADEnZlkTxH1gYpcJizQJ5sw2u5U7gJRqRAzBwDQloGcKeXXnyDTyLc 7.1293 +dSABRch3lZKF+FIMYPnakvow1f2ncqnJGgydBuQp6HTDiZuKcNIQJ620hM/QfkKC9ieKHDh4Ch6P 7.1294 +m1x32dwwrc2SgK/u622LFChkSpwMRi6q14YwbgL3ixOnRUMsM4hhKG8gbxvFjDQK7HJr0LDgBoy3 7.1295 +5u2x9GM3YYF9h2GuXsj1HYR/YZmoWa5CjG87qQv3o7miSxuL7UUyHcAfbwEGo2sPkkx1+gKTLL9j 7.1296 +kNCDHvZB9yaLWZF5XG6SLCQFpul34i9NBw9LSs/GHX2kaOoIJopZxqN3JQgIbTcegTihJoCgXIZK 7.1297 +e/1dsHunOLBwufvA85qvjl9ed4k73pXgsZ/+pTq7q8pY4WqlvGgsFLhaXfuNShcmF2dbvWGoN5Qx 7.1298 +SihzBUGk+PDxs0BCcC51E28fN/WG4RGbe+fkfQzqoNfuJVdrdsQugAhqRWSUo/DxHPlwZB87uT0T 7.1299 +ewSQRzHMnkUxkDSf/B44+xYKxjicbzNMo7VVBn7g9ddfTXoSoy6SX381uGeUFjH6xH7Y8gTtyLSR 7.1300 +L3qnbbqUMk7J13A6UVIxa3jHtilGrNAp/NNMdt3jdOLHvDcmo4Hfad6JG83ngOgBUXY+/RViVaXT 7.1301 +W7dxklJOHtA4PEQ9Z8Jszhz04+NB2o8ypqTAY3k27o2E1NUzWJiQ4/pRdzraLzo1qd+eeNR8ilh1 7.1302 +UTnQW+jNDpC3Le7u/u2W/V5L/W/SWY8E5M1m0EPAB87B7E7+/58JKyuGppXVqKX1ldyv5w2wB6jD 7.1303 +HW7OHjekOzRvZi2MM8Fyp8RTFNCnYkNb0pTKw40JgDJnP6MHDi6j3th8U5clb0+SnBeyPMT9urHA 7.1304 +ahzjaVCRTxfM0XtZISa22YxSo07tRt6nOkOd7LQzCRs/tV9kV7lJkcjsNimhL2iVYfj9hx/Owi4D 7.1305 +6GGwUz84dx0NlzzcTiHcRzBtqIkTPqYPU+gxXX6/VLVdZZ+gZsvYJCA12bqE7eQdTdzavwb3ZCC8 7.1306 +/UHeh8WIcLaSs5uJpL1lZFPs6uRg3+BrxMRuOfs1PipeUKESzGSW1kgrdvSwwmxRZzNKx1cS7Lku 7.1307 +B8XyENox5nTTIo2XYkid55jq0NxI2ZDbuNTeTlHmWIAo6mR+tEzmQv5WxymGkXKxAFxwr0S/inh4 7.1308 +yniIt7zpzYVpSs7qMqm2QIJY5XqrifbHnYbTLU906CHJuwpMQNwxPxYfcdr4ngk3N+QywaifYMdJ 7.1309 +YpyHHcxeIHIXPYf3WT7BUSdUxzlmpLrbwPQ4aI+QA4ABAIX5D0Y6U+S/kfTK3c+iNXeJilrSI6Ub 7.1310 +2ebkcSCU4Qgja/5NP31GdHlrB5bL3Vgu92O5bGO57MVy6WO53I+lKxK4sDZJYiShL1HSzqL3FmS4 7.1311 +OQ4e5iyerbgd1vdhHR9AFIUJ6IxMcZmrl0nh7SQCQmrb2d+kh02BRcKFg2XOKVcNErkf90x08GgK 7.1312 +lJ3OVK6hO/NUjM+2q8jE73sURVQONKXuLG/zuIojTy6WaT4FsbXojhsAY9GuN+HcXHY7mXI2sWWp 7.1313 +Bpf/9en7D++xOYIamN106oaLiIYFpzJ8GpdL1ZWmJtgogB2ppV/3Qd00wIMHZnJ4lAP+7y0VFCDj 7.1314 +iA1tiOeiAA+Ayn5sM7c4Jgxbz3UVjX7OTM57GydikFWDZlI7iHR6efn29NPpgFJMg/8duAJjaOtL 7.1315 +h4uPaWEbdP03t7mlOPYBoda5lMb4uXPyaN1wxP021oBtub3PrlsPXjzEYPeGpf4s/62UgiUBQkU6 7.1316 +2fgYQj04+PlDYUKHPoYRO9Vh7k4OOyv2nSN7joviiH5fmrs9gL+3hjHGBAigXaihiQyaYKql9K15 7.1317 +3UNRB+gDfb0/HIK1Q692JONT1E6ixwF0KGub7Xb/vH0BNnpKVq/Pvjt/f3H++vL00/eOC4iu3IeP 7.1318 +Ry/E2Q+fBZUjoAFjnyjGnfgKC1/AsLiHWcQ8h381pjfmdcVJSej19uJC7wys8TgD1reizYngOVfN 7.1319 +WGico+Gsp32oy10Qo1QHSM65EaoOoXMlGC+t+cyCynUNLB1HmaKzWuvQS58HMueGaBs1AumDxi4p 7.1320 +GARXNMErqlSuTFRY8o6TPkvTg5S20bYOIaUcVGd32tlvMdl8LzFHneFJ01kr+qvQxTW8jlSRJhDJ 7.1321 +vQqtLOluWI3RMI5+aDdUGa8+Deh0h5F1Q571TizQar0KeW66/6hhtN9qwLBhsLcw70xSNQLV6GIt 7.1322 +lQixEe8chPIOvtql12ugYMFwY6nCRTRMl8DsYwiuxSqBAAJ4cgXWF+MEgNBaCT8BfexkB2SOxQDh 7.1323 +m/X88O+hJojf+pdfeppXZXr4D1FAFCS4ciXsIabb+C0EPpGMxNmHd6OQkaNKUPH3GkvAwSGhLJ8j 7.1324 +7VQuwzu2k6GS6UKXM/j6AF9oP4Fet7qXsih1937XOEQJeKKG5DU8UYZ+IVYXWdhjnMqoBRqr2y1m 7.1325 +eErM3fY2nwPxcSXTVBdEn7+9OAPfEQvuUYJ4n+cMhuN8CW7Z6lovPsXWAoUbuvC6RDYu0YWlTf15 7.1326 +5DXrzcyiyFFvrw7ArhNlP7u9OqnOMk6Ui/YQp82wnJLzCLkZlsOsLHN3txnS2W1GdEfJYcaYXJZU 7.1327 +NelzBnA0PY05MIKICYv6TbKZ9y6TrDJlcmkyA20KihfU6hhEBUmMJ9eI//KM0715qcyBF3hYbMtk 7.1328 +uaowpQ6dIyq2x+Y/nH6+OH9P1esvXja+dw+LjikeGHPpwgnWpWHOA764tWbIW5NJH+fqVwgDdRD8 7.1329 +ab/imogTHqDTj9OL+Kf9ik8cnTjxIM8A1FRdtIUEwwCnW5/0NBLBuNpoGD9u3VmDmQ+GMpJ4wEGX 7.1330 +F7jz6/KjbdkyKJT9MS8fsVexKDQNh6azWwfV/ug5LgrcXJkP+xvB2z4JM58pdL3pvNlVceV+OrKI 7.1331 +hx8Bo25rfwxTk9RpqqfjMNsubqHgVlvaXzInY+q0m2UoykDEodt55DJZvyrWzZkDvdrdDjDxjUbX 7.1332 +SGKvQh/8kg20n+FhYondiVZMRzo7QaYA8xlSHxGpwZNCuwAKhEpOh47kjkdPX3hzdGzC/XPUugss 7.1333 +5PegCHUBKB0syEvgRPjyG7uP/IrQQlV6LELHX8lkltvqJPxsVuhbPvfn2CsDlMpEsSvjbCmHDGts 7.1334 +YH7pE3tHIpa0rccxV0mrWkJzN3iodzsYvCsW/bsnBrMWH3Ta3chtWxv51MEGvccPfAhlvAHtXtTV 7.1335 +kNdq52YBNtdbsMMQkyS/hTvodQ96Ghb6Xb/17OHgh4ll3Etrr1pHW0L7QvuVsxICpkrRZoljhY2H 7.1336 +6BrmxgaeNFZ4YJ/qihH7u+e8kFPl6sJlFFyo3gwHukEr1B/wyRU+uZdQZXRzsEK/m8tbmebgFkHE 7.1337 +hYXvv9rC91FkUx29NUF/BoKX28ttP3r0pkHu2BTno+OkCljIKJPVEWLUm5C5B7kGH1z2X3TQEGc3 7.1338 +5Me++fl8LN68/xH+fy0/QOSD59fG4h+AiXiTlxAB8hlKOtyOpf0Vh3Z5rfCQG0GjzQS+BwBdqkuP 7.1339 +2rhxoc8c+IcNrBYTWGdZrvnyCUCR50jnihsbbirp4bc56tN1Fo0j17c0A/0SybD7AAQeGjjSLaNV 7.1340 +tU5RnTupjGZNrwYX52/O3n88i6o75Hbzc+CkOvwqHZyR3sgtcdNqLOyTWY1Prh2/9nuZFj1urY4M 7.1341 +zWEKjAxFCMFDYaNBvtsgthFAXGJ4L4rtPJ9F2BJ4n89vVRvwc0dOEHivHfaMIMIajvRWV+Ns42Og 7.1342 +hvilrZcG0JD66DlRT0IonuJBIn4cDfot5VhQ/hn+PL3ZzN30tT4RQhNsY9rMeuh3t6pxxXTW8Fxm 7.1343 +ItRO7EqYc4JpEqv1dOaeH/uQCX07BSg92o+Qi7hOKyEzEGEKxumaAND97pEvlhPmFrY4dA6K0inp 7.1344 +Jt4qpyImVmKAow7opDNunFBmD2LlH+IbthB4Fk3UfKgVoBOiFOHkTldVz1Ysxxy0EAF7CgQ2Sfby 7.1345 +RdghMg/KkeyscTVhnujYMUZLWen584Ph6Op5Y+wpezzzDnzOCrCDLqccgA4tnj59OhD/cb9/wqhE 7.1346 +aZ7fgOMEsPvCVnFBr3d4FnpydrW6vrd5EwFLzlbyCh5cU5bbPq8zSiHu6UoLIu1fAyPEtQktP5r2 7.1347 +LUvNybWSN4S5BW8saRPyU5bQHTSYApKocvVVPpgeMgJFLAm6IYzVLElCTifAemzzGs9qYTpQ84u8 7.1348 +A45PEMwY3+JOFgfDK/QBqbDSco9F50QMCPCACp14NDrsSqeVAM/J5VajOTnPkqo5Z/DM3eTUh7or 7.1349 +e7WM5isRb1AyzDxaxHCO/Xms2vjA+V4W9WKKfHblJgZbs+TX9+EOrA2Sli8WBlN4aBZplstyZowq 7.1350 +rlgySyoHjGmHcLgz3ahDBigKelAagIYnwzC3Em3ffmHXxcX0A+33HpqRdJlPZW8p4iROnLWq3aKo 7.1351 +GZ/SRZaQlm/NlxGM8p7Sz9of8MYSX+jkJxaZe5cpuMfd6kxfksB1Fs3NCQCHLuaxCtKyo6cjnNug 7.1352 +LHxmWh1uNHcqODXxGEQTbrdJWdVxOtEH+SfouU3sBrjG0x6T2nsA0Pos4Pbn4BAf6pJu8B1MNQzS 7.1353 +EysyTcn+iVjoJELkHj3yT+kUOfp6Lzw9jqnpZ3wRgKPBseWX5vDKQ1S+OULROX3gYjmm2qNw1K6o 7.1354 +7LTCfQ5TIm+d7HYc8KghW7B8h31WbPFOHpjWk3lE/0LfkaPLFHBj6tGDp8mUBgv7Co/v76srATH+ 7.1355 +W4OgLBI5P3yiEDvG+Y9C1VAMddxA4REzDOnuCQL5ZWsnzykv5NrfXds3HaBff7UPrKuCewufac/E 7.1356 +V8v6aJtbidxs2uDnwHrEK3C6UW/MzWFkrZb43CbqEDaI9qy5qVdpH5mB1w+f8p4JP2BHNMTBNHe4 7.1357 +8rqPVha/faRqGgW/i0q6Vz+t0AnGUtFVzG9QmdXFsQ0V+TBfRmn2oVtAhJ/qpre0Psa7j4jRq5tw 7.1358 +3/S5/7656xaBnbnZP+vM3T9C49JA993NL300YAddE+JBVbkWo8mfI7pjvbXbn6LSn4W9hZEzVcSD 7.1359 +GrWxZsl1PHO/Y4HBIV/i6B6HClyQZtVbc+qcD2uzc5eTu9zMm6n43J6QpB3yuWYvNud0pc+Ea64m 7.1360 +crlUkxhvhJqQD0j1AR3jbryKd3QbkIzV1jgDeOcCgDCsoiu53GJNWHXwM/lmSt5edw7XCxqaitCc 7.1361 +qjaVzDm2154HgIs4pqf+JnPEZWmDVGI2RtVlUYKzNtD3F/K+b1+pXAPUxJfrWN0Y1E2Psb7ODofg 7.1362 +YgNzhIozCewAetQBQvDJCudmF67znEzsO+CXZ81R0WRsGUJm9VqWcdXckuDvLyXiW2cEOjiHC+xE 7.1363 +kI3YtTjFRSyx/OEghTGc/f6ldo4832/P+dCRVWkPZyvqoZMTjzl66ki54ebkzt6S5N7OMadrMSle 7.1364 +5Ns1hG3WcJ+9GQKWwlz5Q4pQh3T8Vl9DwvfTcc4Jq+ocPgK5d4+t+NWNVmexw2DRcJ65iqF77wSe 7.1365 +fCRD23edVIcLuhdH+czQjO/rDcssnd2EHY0tFU+4Ra/iaUYbNYEOFiLdE+j4xaaPDHQ8+A8MdPTl 7.1366 +X2BNND5aH/SWn94TEbGacG/SahgB+kyASLhh0rqHydjDoVvMCeFKcjewl1GyznROiBgzgRzZvWKF 7.1367 +QPCNWcqtfPNutDHj9kUivnTR4+8uPrw+vSBaTC5P3/zn6Xe0zY9ZvZbNenAkmOWHTO1Dr6zQjQr1 7.1368 +1mzf4A22PVfTcW28htB539nW6oHQfw6ib0Hbisx9vatDp5682wkQ3z/tFtRdKrsXcsf50rXL7oZs 7.1369 +q/4v0E+5WMv8cvbWzCOTU2ZxaBLG5n2T49My2kmB7Fo4p2yqq060U6ovM9uRnhnZ4j1aAUztIX/Z 7.1370 +zJ6pxLb5I3ZU2leEU8UhnmIxNwGAFM6kcyEV3UXFoCr/LvISlF2MOxTsMI7tvZ7UjrOYyl5Yi7sU 7.1371 +MxkZgnjHSAbd+bnCPpfpDioEASs8fd0SI2L0n877272yJ0pcHdKBtUNUNtf2F66ZdnJ/TnBHrLL3 7.1372 +liiz5Y27AdB4UafuLpft0+lAzh8lTfOFUyENmu8I6NyIpwL2Rp+JFeJ0K0KIEvVWDhZdER31nUMO 7.1373 +8mg3HewNrZ6Jw13HmdzjPEI8391w3joxpHu84B7qnh6qNodGHAuMdT+7zimJbwkyZ90FXVTiOR+4 7.1374 +26Ovx4Svt1fPj23KFvkdX7vXYCDtB45hv2pOBuy9GsvpTbxSjqn+A4uNRm3w1wOHNRdid4DTqXPe 7.1375 +EQSZ7TiGNPDe99dGmB7enb2DNqKW745hQmL4RI1oUk5luMbdPhl1JtuorC4MLnK/H0ZH+wEohNLv 7.1376 +m+CHb2MB9fxMx4PTmu4TtA4nHg115IEKHXxe4B7G62uwa3eno2kP6k4l//agADdo855ebxBr9hq4 7.1377 +lZfo2G0L2jNveGCH7edDfv39nz+gf7ckxnZ/sc+htq1e9h4sYScWi6hw87pFIfM4AusCCnNIahrr 7.1378 +b42E4+H9howONzVTQ65Ah4/qsvCuUAosyImdaMtvjUHwf71Zz9M= 7.1379 +""".decode("base64").decode("zlib") 7.1380 + 7.1381 +##file ez_setup.py 7.1382 +EZ_SETUP_PY = """ 7.1383 +eJzNWmuP28YV/a5fwShYSIJlLt8PGXKRJi5gIEiDPAoU9lY7zxVrilRJyhu1yH/vmeFDJLVU2iIf 7.1384 +ysDZXXJ45z7PuXekL784nqt9ns3m8/kf87wqq4IcjVJUp2OV52lpJFlZkTQlVYJFs/fSOOcn45lk 7.1385 +lVHlxqkUw7XqaWEcCftEnsSirB+ax/Pa+PuprLCApScujGqflDOZpEK9Uu0hhByEwZNCsCovzsZz 7.1386 +Uu2NpFobJOMG4Vy/oDZUa6v8aOSy3qmVv9nMZgYuWeQHQ/xzp+8byeGYF5XScnfRUq8b3lquriwr 7.1387 +xD9OUMcgRnkULJEJMz6LooQT1N6XV9fqd6zi+XOW5oTPDklR5MXayAvtHZIZJK1EkZFKdIsulq71 7.1388 +pgyreG6UuUHPRnk6HtNzkj3NlLHkeCzyY5Go1/OjCoL2w+Pj2ILHR3M2+0m5SfuV6Y2VRGEUJ/xe 7.1389 +KlNYkRy1eU1UtZbHp4LwfhxNlQyzxnnluZx98+5PX/387U+7v7z74cf3f/7O2BpzywyYbc+7Rz// 7.1390 +8K3yq3q0r6rj5v7+eD4mZp1cZl483TdJUd7flff4r9vtfm7cqV3Mxr8fNu7DbHbg/o6TikDgv3TE 7.1391 +Fpc3XmNzar8+nh3TNcXT02JjLKLIcRiRsWU7vsUjL6JxHNBQOj4LRMDIYn1DitdKoWFMIuJZrvB8 7.1392 +y5GURr4QrrRjzw5dn9EJKc5QFz/ww9CPeUQCHknmeVZokZhboRM6PI5vS+l08WAAibgdxNyhIghs 7.1393 +SVyHBMJ3hCcjZ8oid6gLpa7NLMlCN45J4PphHIc+IzyWPrECO7oppdPFjUjEcJcHgnHHcbxQ2mEs 7.1394 +Q06CIJaETUjxhroEjuX5xPEE94QtKAtDKSw3JsQTgQyFf1PKxS+MOsSOfOgRccKkpA63oY/lUpfa 7.1395 +zHtZChvlC3WlQ33fjXmAuIYy9AgPY9uBIBJb0YRFbJwvsIcLDk8GIXe4I6WwPcuK3cCTDvEmIs1s 7.1396 +a6gMgzscQn3uEsvxA88PEB9mu5FlkdCKrdtiOm38kONFxCimkRWGDvNj4rsk8lyX+JxPeqYW47di 7.1397 +uPACwiL4Mg5ZFPt+6AhfRD7SUdCIhbfFBJ02kUAlESGtAA5ymAg824M0B0bC4RPRBqgMfeNQIghq 7.1398 +2HY53kcZOZEIKfGpT6ARF7fFXCLFAzeWMbUgzGOe48Wh5XpcMEcwizmTkbKHvgk8FnvSpTIkIbLQ 7.1399 +FSxyhUUdhDv0YurcFtP5hkoSO7ZlUY4wcdQEJAnOXQQ+8KwomBAzwhlpWYFHZUCIQ0NuQS141kNi 7.1400 +W5EdMmcqUCOcCezAjh0hmOtLLxSImh0wHhDbgVQnnJIywhlpRwAogC+XSBXi+DGLIUXaPKRhJCfQ 7.1401 +io1wRliCh14QOSyOIyppCE9HFrLXQsxDeyrY7jBIhAppB5JzGOb7vu1Fns1C4BePozjwp6SM0Ipa 7.1402 +NLZdmzBCXceCM4BzofQ85gMoQlvelNJZhCSR2DPgnqTSRUVRGXsBs+AqoJ6YShhvaFGk0BrA7zqM 7.1403 +05iFDmXSA3w5gXQiIqfQyh9aJEQseWRBHRQkMla6ApjuhwAMHtnBVKT9oUVEAqu4BKvYoWULAeeG 7.1404 +ICefMhAeCaZQxh/FKOKuDAAIHmOERKHtIXG4G1LGuMt9PiElGFqEgonA8pFtB2CiKPJCByLAmL4X 7.1405 +o7SngDMYsRvzAyL9kMK/6B5QDYEFQzzPRYH5ZAobgqFF1JERCX0HZA/YpS5I2kKoufAlWgnfnZAS 7.1406 +juDOQoxkTDhzSWD7wrdtH2WIliICBE7mSzhiAhLJ2PfAAhxYbkkahEza0kEY8MiZqoBwaJEHjiXA 7.1407 +W4mWAQXouZ5t25KLyLXxL5zSJRp1Q5bqhZwYHok5+EOlIAA8ci3VWFm3pXQWMUrcCNiAnsOLXGap 7.1408 +nEW2wdkMzDJJA9HQIjt07BAgh0DHnNm+5ccW8SPqCtR57E9FOh5aBN2ZZ6GZsZWHqRcHwmOSCiuC 7.1409 +rcyainQ8QgYkGRo7cKsbRTwAOhEhrADgxQLXm+rvGimdRVIgtK7wiR1S22EIE/M9m4bgXjC/mGKS 7.1410 +eMhHjKBsbKlQkziCA5js2AWzhdSPHfQ4kPLrrDcRYLwpZ1Vx3tQD156U+zSh7byF3n0mfmECo8Z7 7.1411 +feedGomatXjYXzfjQhq7zyRN0O2LHW4todMuwzy4NtQAsNpoAxJptPfVzNiOB/VDdfEEs0WFcUGJ 7.1412 +0C+ae/FLfRfzXbsMcpqVX2w7KR9a0Q8XeerC3IVp8O1bNZ2UFRcF5rrlYIW65sqkxoJmPrzDFEYw 7.1413 +hvEvDGP5fV6WCU174x9GOvx9+MNqfiXsrjNz8Gg1+EvpI35JqqVT3y8Q3CLT7qodOhoO9aJmvNqO 7.1414 +hrl1p9aOklJsewPdGpPiDqPqNi9NdirwW51M3QtcpOS8tf1ZEySMjV+dqvwAPzBMl2eMohm/78zu 7.1415 +nRSouf5APiGWGJ4/w1VEOQjOU6YdSbWvx/nHRulHo9znp5SraZbUvu5Layfz7HSgojCqPakMDMKd 7.1416 +YC1LTcCZ8q4hMfV2Sp0yrl8RxuPAEY+GGmmXz/uE7dvdBbRWRxO1PGNxv1iZULL20qPaUsnpHWPs 7.1417 +RTE4IHlOMHPTSyYIvkZG1gmuVc5y+CMtBOHni/rY473sqafdrrdrzia0mKrRUkujQqvSOESfWLA8 7.1418 +42Xtm1aNI0GiKKfCI6qskipB6LKn3nlGHfHG/jwT+jyhPhvhtV5wap4qH754PqK0bA4bRCNMn+UU 7.1419 ++Qk7iVqVus6IcRBlSZ5EfcBxKbrHR50vBUlKYfx4LitxePeL8ldWByIzSIV79ckGoQpalPEqBZUx 7.1420 +9amH2Wao/vlMyl2NQrB/ayyOn552hSjzU8FEuVAIo7Y/5PyUilKdkvQAdPy4rglUHUceNG5bri5I 7.1421 +olJueymaXl02HhuVYFt261GhXTCgLRITnhVFtbTWapMeyDVA3e30pn+6Q9tjvl0TmJ0G5q2SUQcI 7.1422 +wD6WNXCQfvgCwncvtYDUd0jz6HqHgWizSa7l/KLx2+38VeOq1ZtGdl+FoYC/1Cu/zjOZJqyCazZ9 7.1423 +9O9H/r9F+/lP+0v2T+T78u32rlx1tdzWsD7K/JgNAX/OSLaoVEl1JQLMUMd3ukaa4zpVLacsQyqb 7.1424 +xvepQIa0y6/kqRpSpQwAErCl1VAmRQlHnEpVDgtIOLehN17/3FN+YY7kfcw+ZsuvT0UBaYDzWsBd 7.1425 +MeKtFVjrksvCJMVT+cF6uM1ZOn5pKYYxQKIPw7nuV9qHUZ0+qFe+hLUayfNPA1Ev5eB01nyToCQS 7.1426 +elIM/l1e/SkHL9zO55ppXyrr35tuVfGjPAc8+80LpKrLmFxIwUhzVrckGj5rG5KqPiHWLcb/KcnW 7.1427 +EK0+A2hJ9rc4Vt1Tu14TbI37jxfOnODFvGbDlgwVqbDqRNKLEQ3JDImk/YihANdQB9m6RwqldZ61 7.1428 +/erW6IHZ67sSvfddqVrveb9wRkfgda5Cbp87lM+MV8MWsSSfBbTfoiWvSeHveZItWwppl9biyoIp 7.1429 +cbpP/g5s3rbWCqra11GkZVUua7GrjSqwrz7niUqgoyCKL1t1yq4+BniuLp2KHIKUN8rWS2n+NFil 7.1430 +mnEVl+G76sJK85kU2VL5+fXvd9WfkDTA2iB5+VKW3+mUUJ+cLMVnkak/YM4Rys72Ij2qvu99nW29 7.1431 +3qNLFTQnKv/VZztL5YoZKGFtAF1m6tYB5ZwJOBKvoA5V5wuEFs8KjwnG2bLUb/c5QCO4OWu2BHQ3 7.1432 +Pc5lR6jM22w2Z7MlQExslIe1mANhe9Vu8VzUxLRHeKFE9ZwXn5pN18axZpecVqT5XE4hhUaJu3I2 7.1433 +UygCDzDdtesFkHypxKZyCtGwVd8Ac/V7RhFJsb5KmR7oXjVUOsvWqpquXkNHoZO1StRk2TROqRDH 7.1434 +N/WP5aj3GmZnC8OaF8u53mLEe7rkGnww8TM/imx5texL4wc0/ffPRVIBfBBj+Fe328DwT2v10eCz 7.1435 +ip5qF1ihyhDQyPKiOOnkSMVImI57Pz1UF14Jvb7FxPZqPmabGsJhgKkGkuVqqHGNItqaGivW82c6 7.1436 +hzvxwNR21GN49xKGQTUUbsYQgA02eheW5qVYrq4goqw2Wmj/ecNmLWhBwVT90sLW7D+5FH8fkOlL 7.1437 +NCyf11OMfeHc97c+NNUc+w6tVbOqJYiXmunRh9G3Oul6eOiw+kriZc3tAUNP6tZ1SzYcIwZThI6Z 7.1438 +Ko3e7MDywwGGmoMesj3OIc1A1l5NjLSLU3CB9vPqlTpteVjpNH0Wi0KntTAUjf9mqihLlZ9HXKXU 7.1439 +vuYQLDplmAA/LTuzhg1n0m/czd2u8dZuZ2wxElqmZdqL/3pE+CsAXoOrmotpmacCtToxGrdNP8ik 7.1440 +buyvGvpCHPLPGm91JOrvPOgJGMxRAXrT38DdUac+2ZI3RfWPYbPSm7z63c71MPgfDHT4eaP/Hk1t 7.1441 +m+ls/59T8laZdYJ/U8pVNr9Ud225PQxndu1sa4XEh1WK/RE4pjNFPXk5Q9Uuv5MDOvW15jemsDrN 7.1442 +5z9etUXzdYsoc4DgkyaiQh3/IgnRJF0Sev6CvMXyB7RT8/bbOebxPJw+5/X3bq6/mmKuFs2x5rHj 7.1443 +p3aEKS/w/LN+aqgSoackrV7X58QQ+aSGu7NC5H4WF838o3qt9ly5E3txiO65L921+lOtWF66ai2k 7.1444 +5UJNmouCLi7PumNm9e5Dc0QtW1J98ZhadmRXj4A1RX+Yqz/uig3+rYEVGB+aTrNuyNqNTJDvoVyu 7.1445 +HrqXzRIWd9R5VEPFfF5PCjVJ9x2DCGCErNqJQX+faNveNZ9EVRetur/sT+c73THsdk3Wdy5pZKwN 7.1446 +7ZY3TUvUOuDN2NgDqTANbqGnWQpSsP1y/jHrfx/oY7b88LdfH16tfp3r9mTVH2P02z0segGxQeT6 7.1447 +G1mpIRQKfDG/LtIWEWtV8f8PGy3Y1K330l49YAzTjnyln9YPMbri0ebhZfMXz01OyKY96lTvOWAG 7.1448 +M1o/breL3U4V7G636D4FSZVEqKlr+K2j6bD9+4P9gHdev4az6lLp0VevdrrlzubhJV7UGHGRqRbV 7.1449 +178BYnMUkw== 7.1450 +""".decode("base64").decode("zlib") 7.1451 + 7.1452 +##file distribute_setup.py 7.1453 +DISTRIBUTE_SETUP_PY = """ 7.1454 +eJztG2tz2zbyu34FTh4PqYSi7TT3GM+pM2nj9DzNJZnYaT8kHhoiIYk1X+XDsvrrb3cBkCAJyc61 7.1455 +dzM3c7qrIxGLxWLfuwCP/lTs6k2eTabT6Xd5Xld1yQsWxfBvvGxqweKsqnmS8DoGoMnliu3yhm15 7.1456 +VrM6Z00lWCXqpqjzPKkAFkdLVvDwjq+FU8lBv9h57JemqgEgTJpIsHoTV5NVnCB6+AFIeCpg1VKE 7.1457 +dV7u2DauNyyuPcaziPEoogm4IMLWecHylVxJ4z8/n0wYfFZlnhrUBzTO4rTIyxqpDTpqCb7/yJ2N 7.1458 +dliKXxsgi3FWFSKMV3HI7kVZATOQhm6qh98BKsq3WZLzaJLGZZmXHstL4hLPGE9qUWYceKqBuh17 7.1459 +tGgIUFHOqpwtd6xqiiLZxdl6gpvmRVHmRRnj9LxAYRA/bm+HO7i99SeTa2QX8TekhRGjYGUD3yvc 7.1460 +SljGBW1PSZeoLNYlj0x5+qgUE8W8vNLfql37tY5Tob+vspTX4aYdEmmBFLS/eUk/Wwk1dYwqI0eT 7.1461 +fD2Z1OXuvJNiFaP2yeFPVxcfg6vL64uJeAgFkH5Jzy+QxXJKC8EW7F2eCQObJrtZAgtDUVVSVSKx 7.1462 +YoFU/iBMI/cZL9fVTE7BD/4EZC5s1xcPImxqvkyEN2PPaaiFK4FfZWag90PgqEvY2GLBTid7iT4C 7.1463 +RQfmg2hAihFbgRQkQeyF/80fSuQR+7XJa1AmfNykIquB9StYPgNd7MDgEWIqwNyBmBTJdwDmmxdO 7.1464 +t6QmCxEK3OasP6bwOPA/MG4YHw8bbHOmx9XUYccIOIJTMMMhtenPHQXEOviiVqxuhtLJK78qOFid 7.1465 +C98+BD+/urz22IBp7Jkps9cXb159ensd/HTx8ery/TtYb3rq/8U/ezlthz59fIuPN3VdnJ+cFLsi 7.1466 +9qWo/LxcnygnWJ1U4KhCcRKddH7pZDq5urj+9OH6/fu3V8GbVz9evB4sFJ6dTScm0Icffwgu3715 7.1467 +j+PT6ZfJP0XNI17z+U/SHZ2zM/908g786LlhwpN29LiaXDVpysEq2AN8Jv/IUzEvgEL6PXnVAOWl 7.1468 ++X0uUh4n8snbOBRZpUBfC+lACC8+AIJAgvt2NJlMSI2Vr3HBEyzh35m2AfEAMSck5ST3LodpsE4L 7.1469 +cJGwZe1N/PQuwu/gqXEc3Ia/5WXmOhcdEtCB48rx1GQJmCdRsI0AEYh/LepwGykMrZcgKLDdDcxx 7.1470 +zakExYkI6cL8vBBZu4sWJlD7UFvsTfbDJK8EhpfOINe5IhY33QaCFgD8idw6EFXweuP/AvCKMA8f 7.1471 +JqBNBq2fT29m441ILN1Ax7B3+ZZt8/LO5JiGNqhUQsMwNMZx2Q6y161uOzPTnWR53XNgjo7YsJyj 7.1472 +kDsDD9ItcAU6CqEf8G/BZbFtmcPXqCm1rpjJiW8sPMAiBEEL9LwsBRcNWs/4Mr8XetIqzgCPTRWk 7.1473 +5sy0Ei+bGB6I9dqF/zytrPAlD5B1/9fp/wGdJhlSLMwYSNGC6LsWwlBshO0EIeXdcWqfjs9/xb9L 7.1474 +9P2oNvRojr/gT2kgeqIayh3IqKa1qxRVk9R95YGlJLCyQc1x8QBLVzTcrVLyGFLUy/eUmrjO93mT 7.1475 +RDSLOCVtZ71GW1FWEAHRKod1VTrstVltsOSV0BszHkci4Tu1KrJyqAYK3unC5Py4mhe748iH/yPv 7.1476 +rIkEfI5ZRwUGdfUDIs4qBx2yPDy7mT2dPcosgOB2L0bGvWf/+2gdfPZwqdOrRxwOAVLOhuSDPxRl 7.1477 +7Z56rJO/yn77dY+R5C911acDdEDp94JMQ8p7UGOoHS8GKdKAAwsjTbJyQ+5ggSrelBYmLM7+7IFw 7.1478 +ghW/E4vrshGtd005mXjVQGG2peSZdJQvqzxBQ0VeTLolDE0DEPzXNbm35VUguSTQmzrF3ToAk6Ks 7.1479 +raIkFvmb5lGTiAorpS/tbpyOK0PAsSfu/TBE01uvDyCVc8MrXtel2wMEQwkiI+hak3CcrThoz8Jp 7.1480 +qF8BD0GUc+hqlxZiX1nTzpS59+/xFvuZ12OGr8p0d9qx5NvF9LlabWYha7iLPj6VNn+fZ6skDuv+ 7.1481 +0gK0RNYOIXkTdwb+ZCg4U6vGvMfpEOogI/G3JRS67ghiek2enbYVmT0Hozfjfrs4hoIFan0UNL+H 7.1482 +dJ0qmS/ZdIwPWykhz5wa601l6oB5u8E2AfVXVFsAvpVNhtHFZx8SAeKx4tOtA87SvERSQ0zRNKGr 7.1483 +uKxqD0wT0FinO4B4p10Om38y9uX4Fvgv2ZfM/b4pS1gl2UnE7LicAfKe/xc+VnGYOYxVWQotrt0X 7.1484 +/TGRVBb7AA1kA5Mz7PvzwE/c4BSMzNTYye/2FbNfYw1PiiH7LMaq1202A6u+y+s3eZNFv9toHyXT 7.1485 +RuIo1TnkroKwFLwWQ28V4ObIAtssCsPVgSj9e2MWfSyBS8Ur5YWhHn7dtfhac6W42jYSwfaSPKTS 7.1486 +hdqcivFxLTt3GVTyMim8VbTfsmpDmdkS25H3PIl72LXlZU26FCVYNCdTbr0C4cL2HyW91DFp+5Cg 7.1487 +BTRFsNseP24Z9jhc8BHhRq8uskiGTezRcuacODOf3Uqe3OKKvdwf/IsohU4h236XXkVEvtwjcbCd 7.1488 +rvZAHdYwzyLqdRYcA/1SrNDdYFszrBuedB1X2l+NlVTtazH8RxKGXiwioTYlVMFLikIC29yq31wm 7.1489 +WFZNDGu0xkoDxQvb3Hr9W4DqgK2fXnLsYxm2/g0doJK+bGqXvVwVBcmet1hk/sfvBbB0TwquQVV2 7.1490 +WYaIDvalWquGtQ7yZol2do48f3Wfx6jVBVpu1JLTZTijkN4WL631kI+vph5uqe+yJVGKS+5o+Ih9 7.1491 +FDw6odjKMMBAcgaksyWY3J2HHfYtKiFGQ+laQJPDvCzBXZD1DZDBbkmrtb3EeNZRC4LXKqw/2JTD 7.1492 +BKEMQR94NMioJBuJaMksj023y+kISKUFiKwbG/lMJQlYy5JiAAG6RB/AA35LuINFTfiuc0oShr0k 7.1493 +ZAlKxqoSBHddgfda5g/uqslC9GbKCdKwOU7tVY89e3a3nR3IimXzv6tP1HRtGK+1Z7mSzw8lzENY 7.1494 +zJmhkLYly0jtfZzLVtKozW5+Cl5Vo4HhSj6uA4IeP28XeQKOFhYw7Z9X4LELlS5YJD0hsekmvOEA 7.1495 +8OR8fjhvvwyV7miN6In+UW1Wy4zpPswgqwisSZ0d0lR6U2+VohNVAfoGF83AA3cBHiCru5D/M8U2 7.1496 +Ht41BXmLlUysRSZ3BJFdByTyluDbAoVDewREPDO9BnBjDLvQS3ccOgIfh9N2mnmWntarPoTZLlW7 7.1497 +7rShm/UBobEU8PUEyCYxNgTkDIhimc+ZmwBD2zq2YKncmuadPRNc2fwQ6fbEEAOsZ3oXY0T7JjxU 7.1498 +1myzCk27uCHvDR4rVKM9SwSZ2OrIjE8hyjr++7ev/eMKj7TwdNTHP6PO7kdEJ4MbBpJc9hQliRqn 7.1499 +avJibYs/Xduo2oB+2BKb5veQLINpBGaH3C0SHooNKLvQnepBGI8r7DWOwfrUf8ruIBD2mu+QeKk9 7.1500 +GHP369cK646e/8F0VF8IMBrBdlKAanXa7Kt/XZzrmf2YZ9gxnGNxMHT3evGRt1yC9O9Mtqz65VHH 7.1501 +ga5DSim8eWhurjtgwGSkBSAn1AKRCHkkmzc1Jr3oPbZ819mcrnOGCZvBHo9J1VfkDySq5huc6Jy5 7.1502 +shwgO+jBSlfViyCjSdIfqhkes5xXqs624ujIt3fcAFPgQxflsT41VmU6AsxblojaqRgqfut8h/xs 7.1503 +FU3xG3XNNVt43qD5p1r4eBMBvxrc0xgOyUPB9I7Dhn1mBTKodk1vM8Iyjuk2vQSnKhv3wFZNrOLE 7.1504 +nja6c9Vd5ImMNoEz2EnfH+/zNUPvvA9O+2q+gnS6PSLG9RVTjACGIO2NlbZt3dpIx3ssVwADnoqB 7.1505 +/09TICLIl7+43YGjr3vdBZSEUHfJyPZYl6Hn3CTdXzOl53JNckElLcXUY27YImzNHN1YGLsg4tTu 7.1506 +nngEJqcilfvkUxNZEXYbVZHYsCJ1aFN1fhAW+NLTOXffVQFP0vYVTm9Aysj/aV6OHaDV80jwA35n 7.1507 +6MO/R/nLSD6a1aVErYM8nBZZ3ScB7E+RJKvqNifazypDRj5McIZJyWAr9cbgaLcV9fixrfTIMDpl 7.1508 +Q3k9vr/HTGzoaR4Bn/Xy+TbodTndkQolEIHCO1SlGH/Z8uu9Cioz4IsffpijCDGEgDjl969Q0HiU 7.1509 +wh6Ms/tiwlPjquHbu9i6J9kH4tO7lm/9RwdZMXvEtB/l3H/FpgxW9MoOpS32ykMNav2Sfco2oo2i 7.1510 +2Xeyj7k3nFlO5hRmatYGRSlW8YOrPX0XXNogR6FBHUpC/X1vnPcbe8Pf6kKdBvysv0CUjMSDETaf 7.1511 +n53ftFkUDXr62p3ImlSUXF7IM3snCCpvrMp8az4vYa/yHoTcxDBBh00ADh/WLOsK28yoxAsMIxKP 7.1512 +pTFT54WSDM0skrh2HVxn4cw+zwencwYLNPvMxRSu4RGRpApLQ0mF9cA1Ac2Utwi/lfyx95B65Faf 7.1513 +CfK5hcqvpbSjEZjbVKJ06GihuxyrjgqxjWvt2NhWaWdbDENq5EhVh8p+FXI6UDTOHfX1SJvt7j0Y 7.1514 +P9ShOmJb4YBFhUCCJcgb2S0opHGrJ8qFZEolRIrnDObx6LhLQj+3aC79UkHdO0I2jDdkxCFMTGHy 7.1515 +tvIxa+uf6fsf5XkvJtvgFUtwRr3yxJ64D7SFYj5iWJAbVx5Xce56V4gR37BVaRwkvfpw+QcTPuuK 7.1516 +wCFCUMi+Mpq3ucx3C8ySRBbmdtEcsUjUQt2aw+CNJ/FtBERNjYY5bHsMtxiS5+uhoT6b7zwYRY9c 7.1517 +GrRbt0Msqyhe0KGC9IWokOQL4wcitijz+zgSkXz9IV4pePNFi8poPkTqwl3qdYcauuNoVhz9wGGj 7.1518 +zC4FhQ0Y6g0JBkTyLMR2D3SsrfJGONCygfpjf43SS8PAKqUcK/O6ntqSZRO+yCIVNOjO2J5NZXN5 7.1519 +m68TXo8OtO/9fTSrVPVkRRrgsHlYS1PFuPC5n6R9GZOFlMMJlCLR3Zd/os71uxFfkYPuTUIPNJ8H 7.1520 +vOnPG7efTd1oj+7QrOl8Wbo/Ous1/H0mhqLtZ/+/V54Deum0MxNGwzzhTRZuuhSuezKMlB/VSG/P 7.1521 +GNrYhmNrC99IkhBU8Os3WiRUERcs5eUdnuXnjNMBLO8mLJvWeNpU7/ybG0wXPjvz0LyRTdkZXrFJ 7.1522 +xFy1AObigd5fgpx5nvIMYnfk3BghTmM8vWn7Adg0MxPMz/03Lm7Y83baROOg+znWl2la7hmXkiuR 7.1523 +rGTjfDH1px5LBV4cqBYYU7qTGXWRmg6CFYQ8ZqRLACVwW7IWf4byipG+R6z3111oQJ+M73rl2wyr 7.1524 +6jSP8K0w6f+x2U8AhSjTuKroNa3uyE4jiUEJqeEFMo8qn93iBpz2Ygi+ogVIV4IIGV2jBkIVB+Ar 7.1525 +TFY7ctATy9SUJ0REiq/c0WUR4CeRTA1AjQd77EqLQWOXO7YWtcLlzvo3KFRCFubFzvwNhRhk/OpG 7.1526 +oGSovE6uARTju2uDJgdAH27avECLZZQP6AGMzclq0lYfsBL5Q4goCqRXOath1f8e+KUjTViPHnWh 7.1527 +peIrgVIVg2P9DtLnBVSgkavW6LsyTdeCuOXjn4OAeJ8M+zYvX/6NcpcwTkF8VDQBfad/PT01krFk 7.1528 +5SvRa5xS+duc4qNAaxWsQu6bJJuGb/b02N+Z+8JjLw0OoY3hfFG6gOHMQzwvZtZyIUwLgvGxSSAB 7.1529 +/e50asg2ROpKzHaAUlLv2o4eRojuxG6hFdDH435QX6TZQQKcmccUNnl1WDMIMje66AG4WgturRZV 7.1530 +l8SBqdyQeQOlM8Z7RNI5oLWtoQXeZ9Do7JykHG6AuE7GCu9sDNjQ+eITAMMN7OwAoCoQTIv9N269 7.1531 +ShXFyQlwP4Eq+GxcAdON4kF1bbunQMiCaLl2QQmnyrXgm2x44UnocJDymGrue4/tueTXBYLLQ6+7 7.1532 +kgpc8GqnoLTzO3z9X8X44cttQFxM918weQqoIg8CJDUI1LuURHcbNc/Ob2aTfwH3muVf 7.1533 +""".decode("base64").decode("zlib") 7.1534 + 7.1535 +##file activate.sh 7.1536 +ACTIVATE_SH = """ 7.1537 +eJytVU1v4jAQPW9+xTT0ANVS1GsrDlRFAqmFqmG72m0rY5IJsRRslDiktNr/vuMQ8tFQpNU2B4I9 7.1538 +H36eeW/SglkgYvBFiLBKYg0LhCRGD1KhA7BjlUQuwkLIHne12HCNNpz5kVrBgsfBmdWCrUrA5VIq 7.1539 +DVEiQWjwRISuDreW5eE+CtodeLeAnhZEGKMGFXqAciMiJVcoNWx4JPgixDjzEj48QVeCfcqmtzfs 7.1540 +cfww+zG4ZfeD2ciGF7gCHaDMPM1jtvuHXAsPfF2rSGeOxV4iDY5GUGb3xVEYv2aj6WQ0vRseAlMY 7.1541 +G5DKsAawwnQUXt2LQOYlzZoYByqhonqoqfxZf4BLD97i4DukgXADCPgGgdOLTK5arYxZB1xnrc9T 7.1542 +EQFcHoZEAa1gSQioo/TPV5FZrDlxJA+NzwF+Ek1UonOzFnKZp6k5mgLBqSkuuAGXS4whJb5xz/xs 7.1543 +wXCHjiVerAk5eh9Kfz1wqOldtVv9dkbscfjgjKeTA8XPrtaNauX5rInOxaHuOReNtpFjo1/OxdFG 7.1544 +5eY9hJ3L3jqcPJbATggXAemDLZX0MNZRYjSDH7C1wMHQh73DyYfTu8a0F9v+6D8W6XNnF1GEIXW/ 7.1545 +JrSKPOtnW1YFat9mrLJkzLbyIlTvYzV0RGXcaTBfVLx7jF2PJ2wyuBsydpm7VSVa4C4Zb6pFO2TR 7.1546 +huypCEPwuQjNftUrNl6GsYZzuFrrLdC9iJjQ3omAPBbcI2lsU77tUD43kw1NPZhTrnZWzuQKLomx 7.1547 +Rd4OXM1ByExVVkmoTwfBJ7Lt10Iq1Kgo23Bmd8Ib1KrGbsbO4Pp2yO4fpnf3s6MnZiwuiJuls1/L 7.1548 +Pu4yUCvhpA+vZaJvWWDTr0yFYYyVnHMqCEq+QniuYX225xmnzRENjbXACF3wkCYNVZ1mBwxoR9Iw 7.1549 +WAo3/36oSOTfgjwEEQKt15e9Xpqm52+oaXxszmnE9GLl65RH2OMmS6+u5acKxDmlPgj2eT5/gQOX 7.1550 +LLK0j1y0Uwbmn438VZkVpqlfNKa/YET/53j+99G8H8tUhr9ZSXs2 7.1551 +""".decode("base64").decode("zlib") 7.1552 + 7.1553 +##file activate.fish 7.1554 +ACTIVATE_FISH = """ 7.1555 +eJydVm1v4jgQ/s6vmA1wBxUE7X2stJVYlVWR2lK13d6d9laRk0yIr8HmbIe0++tvnIQQB9pbXT5A 7.1556 +Ys/LM55nZtyHx5RrSHiGsMm1gRAh1xhDwU0Kng8hFzMWGb5jBv2E69SDs0TJDdj3MxilxmzPZzP7 7.1557 +pVPMMl+q9bjXh1eZQ8SEkAZULoAbiLnCyGSvvV6SC7IoBcS4Nw0wjcFbvJDcjiuTswzFDpiIQaHJ 7.1558 +lQAjQUi1YRmUboC2uZJig8J4PaCnT5IaDcgsbm/CjinOwgx1KcUTMEhhTgV4g2B1fRk8Le8fv86v 7.1559 +g7v545UHpZB9rKnp+gXsMhxLunIIpwVQxP/l9c/Hq9Xt1epm4R27bva6AJqN92G4YhbMG2i+LB+u 7.1560 +grv71c3dY7B6WtzfLy9bePbp0taDTXSwJQJszUnnp0y57mvpPcrF7ZODyhswtd59+/jdgw+fwBNS 7.1561 +xLSscksUPIDqwwNmCez3PpxGeyBYg6HE0YdcWBxcKczYzuVJi5Wu915vn5oWePCCoPUZBN5B7IgV 7.1562 +MCi54ZDLG7TUZ0HweXkb3M5vFmSpFm/gthhBx0UrveoPpv9AJ9unIbQYdUoe21bKg2q48sPFGVwu 7.1563 +H+afrxd1qvclaNlRFyh1EQ2sSccEuNAGWQwysfVpz1tPajUqbqJUnEcIJkWo6OXDaodK8ZiLdbmM 7.1564 +L1wb+9H0D+pcyPSrX5u5kgWSygRYXCnJUi/KKcuU4cqsAyTKZBiissLc7NFwizvjxtieKBVCIdWz 7.1565 +fzilzPaYyljZN0cGN1v7NnaIPNCGmVy3GKuJaQ6iVjE1Qfm+36hglErwmnAD8hu0dDy4uICBA8ZV 7.1566 +pQr/q/+O0KFW2kjelu9Dgb9SDBsWV4F4x5CswgS0zBVlk5tDMP5bVtUGpslbm81Lu2sdKq7uNMGh 7.1567 +MVQ4fy9xhogC1lS5guhISa0DlBWv0O8odT6/LP+4WZzDV6FzIkEqC0uolGZSZoMnlpxplmD2euaT 7.1568 +O4hkTpPnbztDccey0bhjDaBIqaWQa0uwEtQEwtyU56i4fq54F9IE3ORR6mKriODM4XOYZwaVYLYz 7.1569 +7SPbKkz4i7VkB6/Ot1upDE3znNqYKpM8raa0Bx8vfvntJ32UENsM4aI6gJL+jJwhxhh3jVIDOcpi 7.1570 +m0r2hmEtS8XXXNBk71QCDXTBNhhPiHX2LtHkrVIlhoEshH/EZgdq53Eirqs5iFKMnkOmqZTtr3Xq 7.1571 +djvPTWZT4S3NT5aVLgurMPUWI07BRVYqkQrmtCKohNY8qu9EdACoT6ki0a66XxVF4f9AQ3W38yO5 7.1572 +mWmZmIIpnDFrbXakvKWeZhLwhvrbUH8fahhqD0YUcBDJjEBMQwiznE4y5QbHrbhHBOnUAYzb2tVN 7.1573 +jJa65e+eE2Ya30E2GurxUP8ssA6e/wOnvo3V78d3vTcvMB3n7l3iX1JXWqk= 7.1574 +""".decode("base64").decode("zlib") 7.1575 + 7.1576 +##file activate.csh 7.1577 +ACTIVATE_CSH = """ 7.1578 +eJx9U11vmzAUffevOCVRu+UB9pws29Kl0iq1aVWllaZlcgxciiViItsQdb9+xiQp+dh4QOB7Pu49 7.1579 +XHqY59IgkwVhVRmLmFAZSrGRNkdgykonhFiqSCRW1sJSmJg8wCDT5QrucRCyHn6WFRKhVGmhKwVp 7.1580 +kUpNiS3emup3TY6XIn7DVNQyJUwlrgthJD6n/iCNv72uhCzCpFx9CRkThRQGKe08cWXJ9db/yh/u 7.1581 +pvzl9mn+PLnjj5P5D1yM8QmXlzBkSdXwZ0H/BBc0mEo5FE5qI2jKhclHOOvy9HD/OO/6YO1mX9vx 7.1582 +sY0H/tPIV0dtqel0V7iZvWyNg8XFcBA0ToEqVeqOdNUEQFvN41SumAv32VtJrakQNSmLWmgp4oJM 7.1583 +yDoBHgoydtoEAs47r5wHHnUal5vbJ8oOI+9wI86vb2d8Nrm/4Xy4RZ8R85E4uTZPB5EZPnTaaAGu 7.1584 +E59J8BE2J8XgrkbLeXMlVoQxznEYFYY8uFFdxsKQRx90Giwx9vSueHP1YNaUSFG4vTaErNSYuBOF 7.1585 +lXiVyXa9Sy3JdClEyK1dD6Nos9mEf8iKlOpmqSNTZnYjNEWiUYn2pKNB3ttcLJ3HmYYXy6Un76f7 7.1586 +r8rRsC1TpTJj7f19m5sUf/V3Ir+x/yjtLu8KjLX/CmN/AcVGUUo= 7.1587 +""".decode("base64").decode("zlib") 7.1588 + 7.1589 +##file activate.bat 7.1590 +ACTIVATE_BAT = """ 7.1591 +eJyFUkEKgzAQvAfyhz0YaL9QEWpRqlSjWGspFPZQTevFHOr/adQaU1GaUzI7Mzu7ZF89XhKkEJS8 7.1592 +qxaKMMsvboQ+LxxE44VICSW1gEa2UFaibqoS0iyJ0xw2lIA6nX5AHCu1jpRsv5KRjknkac9VLVug 7.1593 +sX9mtzxIeJDE/mg4OGp47qoLo3NHX2jsMB3AiDht5hryAUOEifoTdCXbSh7V0My2NMq/Xbh5MEjU 7.1594 +ZT63gpgNT9lKOJ/CtHsvT99re3pX303kydn4HeyOeAg5cjf2EW1D6HOPkg9NGKhu 7.1595 +""".decode("base64").decode("zlib") 7.1596 + 7.1597 +##file deactivate.bat 7.1598 +DEACTIVATE_BAT = """ 7.1599 +eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q 7.1600 +FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL 7.1601 +i2dASrm4rFz9XLgAwJNbyQ== 7.1602 +""".decode("base64").decode("zlib") 7.1603 + 7.1604 +##file distutils-init.py 7.1605 +DISTUTILS_INIT = """ 7.1606 +eJytV92L4zYQf9dfMU0ottuse/TeFkKh3MvC0Ydy0IdlMVpbTtR1JCMpm+T++s5Y/pBs53oPZ1hQ 7.1607 +pPnSb34zo5WnVhsH2jLpV/Y2Li/cKKkOFoYN3Za6ErAdFtKC0g44vEvjzrwR6h1Oujo3YgdWw0VA 7.1608 +yRWcLUo6cBpqqSpwRwHWVY18ZRB9W3jq3HDlfoIvqK7NG2gF7a297VANvZ3O1sGrQI/eDe5yB0ZY 7.1609 +WQkLUpHxhVX09NDe3FGr31BL1lJUD9f8ln+FShpROm1ujOFS8ZOAPUKRt9wd836Hjqw7O9nYgvYD 7.1610 +iX+1VOlMPPXQ5EVRy0YURbaDZDSQZEzWo7rS5kSLNHaQwX4RRLrQGe1nj92Fh1zltEhHDDZfEO0g 7.1611 +O6MraHn5xg8IpYOfLfC2FdxYShLC64EES4A0uuROYhq49Zs368RpMvTHJmOiscKHUXRXKIpcKiuM 7.1612 +Sz/sYHa7TkxcRYkkEhN8HZaxKCJXFFJJh+baW5JluRG8SjM20JHEA9qWWtXywBjbbvF2rjzC61k2 7.1613 +VSGuDibTUGlhVeLgTekLHPEP73wQrrscUsUGrPCGjkTCC1JXXyw8EJWP3FSUZY8IiSCCRp97dnfO 7.1614 +RUUx5a0RtbxSzLX/3XBXYxIpyQka/fh74pGrjQ5QzUt9OnFV5dMV+otOG5gQjctxozNTNtzaSSiN 7.1615 +JHqu0FeJmsqRN/KrKHRLGbaQWtHUgRB9FDfu5giN4eZWIDqWCv8vrcTjrNZgRXQPzy+RmGjQpLRI 7.1616 +EKz0UqQLlR28ciusM8jn7PtcLPZy2zbSDeyyos0iO+ybBgPyRvSk/CEFm8IndQebz8iXTRbbjhDP 7.1617 +5xh7iJfBrKd/Nenjj6Jvgp2B+W7AnP102BXH5IZWPV3tI2MUOvXowpdS12IIXhLLP0lKyeuZrpEv 7.1618 +pFhPqHg3JFTd1cceVp0EsPgGU0wFO2u4iyYRoFYfEm9kG/RZcUUBm87t9mFtx9iCtC9kx4Rt4R8a 7.1619 +OdgzSt40vtyFecAZZ8BfCOhCrC8djMGPFaz2Vlt5TSZCk053+37wbLDLRXfZ+F45NtdVpVWdudSC 7.1620 +xgODI8EsiLoTl5aO0lhoigX7GHZDHAY4LxoMIu1gXPYPksmFquxF4uRKZhEnKzXu82HESb+LlNQz 7.1621 +Fh/RvFJVuhK+Ee5slBdj30FcRGdJ5rhKxtkyKxWcGoV/WOCYKqkNDYJ5fNQVx3g400tpJBS2FSU+ 7.1622 +Tco9ss8nZ08dtscGQfSby87b73fOw+4UgrEMNnY6uMzYvSDxPVPpsij6+l0/ZPfuH0Iz010giY34 7.1623 +HpL0ZLyLJB4ukaQRU+GwptO7yIZCQE33B0K9iCqO6X+AR4n7wAeH68DPkJzpTsD3x+/cj9LIVHC2 7.1624 +An1wmv7CzWHoqR02vb0VL73siP+3nkX0YbQ0l9f6WDyOm24cj3rxO2MMip6kpcu6VCefn/789PR3 7.1625 +0v0fg21sFIp70rj9PCi8YDRDXFucym/43qN+iENh1Jy/dIIIqF3OIkDvBMsdx+huWv8Kz73vl8g5 7.1626 +WQ3JOGqwu3lb4dfKKbvLigXDQsb8B/xt39Q= 7.1627 +""".decode("base64").decode("zlib") 7.1628 + 7.1629 +##file distutils.cfg 7.1630 +DISTUTILS_CFG = """ 7.1631 +eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH 7.1632 +xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg 7.1633 +9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q= 7.1634 +""".decode("base64").decode("zlib") 7.1635 + 7.1636 +##file activate_this.py 7.1637 +ACTIVATE_THIS = """ 7.1638 +eJyNUlGL2zAMfvevEBlHEujSsXsL9GGDvW1jD3sZpQQ3Ua7aJXawnbT595Ocpe0dO5ghseVP+vRJ 7.1639 +VpIkn2cYPZknwAvWLXWYhRP5Sk4baKgOWRWNqtpdgTyH2Y5wpq5Tug406YAgKEzkwqg7NBPwR86a 7.1640 +Hk0olPopaK0NHJHzYQPnE5rI0o8+yBUwiBfyQcT8mMPJGiAT0A0O+b8BY4MKJ7zPcSSzHaKrSpJE 7.1641 +qeDmUgGvVbPCS41DgO+6xy/OWbfAThMn/OQ9ukDWRCSLiKzk1yrLjWapq6NnvHUoHXQ4bYPdrsVX 7.1642 +4lQMc/q6ZW975nmSK+oH6wL42a9H65U6aha342Mh0UVDzrD87C1bH73s16R5zsStkBZDp0NrXQ+7 7.1643 +HaRnMo8f06UBnljKoOtn/YT+LtdvSyaT/BtIv9KR60nF9f3qmuYKO4//T9ItJMsjPfgUHqKwCZ3n 7.1644 +xu/Lx8M/UvCLTxW7VULHxB1PRRbrYfvWNY5S8it008jOjcleaMqVBDnUXcWULV2YK9JEQ92OfC96 7.1645 +1Tv4ZicZZZ7GpuEpZbbeQ7DxquVx5hdqoyFSSmXwfC90f1Dc7hjFs/tK99I0fpkI8zSLy4tSy+sI 7.1646 +3vMWehjQNJmE5VePlZbL61nzX3S93ZcfDqznnkb9AZ3GWJU= 7.1647 +""".decode("base64").decode("zlib") 7.1648 + 7.1649 +if __name__ == '__main__': 7.1650 + main() 7.1651 + 7.1652 +## TODO: 7.1653 +## Copy python.exe.manifest 7.1654 +## Monkeypatch distutils.sysconfig