KanonConductor

changeset 33:818a2d559b52 jenkins-support

improved jenkins support.
author chris
date Mon, 28 Mar 2011 06:25:28 +0900
parents 01409f885018 640e6a9509aa
children 2d80ab4aebc6
files kanon-setup pkglist.rhel resource/httpd.conf
diffstat 11 files changed, 1804 insertions(+), 73 deletions(-) [+]
line diff
     1.1 --- a/etc/opt/kanon/trac-template/agile/trac-init.sql	Tue Mar 22 19:03:40 2011 +0900
     1.2 +++ b/etc/opt/kanon/trac-template/agile/trac-init.sql	Mon Mar 28 06:25:28 2011 +0900
     1.3 @@ -120,7 +120,7 @@
     1.4        ELSE 
     1.5          (CASE tt.owner WHEN $USER THEN 'font-weight: bold' END)
     1.6      END) AS __style__,
     1.7 -  t.milestone AS __group__,
     1.8 +  tt.milestone AS __group__,
     1.9    t.id AS id,
    1.10    '' AS 'ストーリー',
    1.11    tt.id AS ticket,
    1.12 @@ -138,7 +138,7 @@
    1.13    LEFT JOIN ticket_custom th ON th.ticket = tt.id AND th.name = 'totalhours'
    1.14    LEFT JOIN ticket_custom peh ON peh.ticket = t.id AND peh.name = 'estimatedhours'
    1.15    LEFT JOIN ticket_custom pth ON pth.ticket = t.id AND pth.name = 'totalhours'
    1.16 -WHERE t.type='ストーリー' AND t.component=$TEAM AND st.child IS NOT NULL AND t.status <> 'closed'
    1.17 +WHERE t.component=$TEAM AND t.type='ストーリー'  AND st.child IS NOT NULL AND t.status <> 'closed' 
    1.18  
    1.19  UNION
    1.20  
    1.21 @@ -156,7 +156,7 @@
    1.22    '',
    1.23    '[/newticket?type=タスク&parents='||t.id||'&milestone='||t.milestone||' タスク作成]' AS  description
    1.24  FROM ticket t
    1.25 -WHERE t.type='ストーリー' AND t.component=$TEAM AND t.status<>'closed'
    1.26 +WHERE t.component=$TEAM AND t.type='ストーリー' AND t.status<>'closed'
    1.27  
    1.28  UNION
    1.29  
    1.30 @@ -169,7 +169,7 @@
    1.31      END) AS __style__,
    1.32    t.milestone AS __group__,
    1.33    '-' AS id,
    1.34 -  'その他' AS 'ストーリー',
    1.35 +  'その他:' ||t.type AS 'ストーリー',
    1.36    t.id AS ticket,
    1.37    t.summary as 'タスク',
    1.38    t.owner AS '担当者', 
    1.39 @@ -180,8 +180,9 @@
    1.40  FROM ticket as t
    1.41    LEFT JOIN ticket_custom eh ON eh.ticket = t.id AND eh.name = 'estimatedhours'
    1.42    LEFT JOIN ticket_custom th ON th.ticket = t.id AND th.name = 'totalhours'
    1.43 -WHERE t.type NOT IN ('ストーリー') AND t.component=$TEAM  AND
    1.44 -  (SELECT count(*)==0 from subtickets WHERE subtickets.child = t.id)
    1.45 +WHERE t.component=$TEAM AND NOT t.type IN ('ストーリー')  AND
    1.46 +  NOT EXISTS (SELECT * from subtickets WHERE subtickets.child = t.id)
    1.47 +
    1.48  ORDER BY __group__ DESC, id,ticket DESC","
    1.49   * チーム別のスプリントのストーリー(プロダクトバックログ)とタスク(スプリントバックログ)を確認することができます。
    1.50   * {{{[report:19?TEAM=チームA チームAのバックログ]}}}のように、レポートのリンク、もしくはURLの最後にTEAM変数でチーム名を指定して利用します。
     2.1 --- a/etc/opt/kanon/trac-template/agile/trac.ini	Tue Mar 22 19:03:40 2011 +0900
     2.2 +++ b/etc/opt/kanon/trac-template/agile/trac.ini	Mon Mar 28 06:25:28 2011 +0900
     2.3 @@ -58,3 +58,7 @@
     2.4  
     2.5  [subtickets]
     2.6  ストーリー=タスク
     2.7 +
     2.8 +[mainnav]
     2.9 +tickets.href = /report/18
    2.10 +
     3.1 --- a/etc/opt/kanon/trac-template/common/trac.ini	Tue Mar 22 19:03:40 2011 +0900
     3.2 +++ b/etc/opt/kanon/trac-template/common/trac.ini	Mon Mar 28 06:25:28 2011 +0900
     3.3 @@ -69,7 +69,7 @@
     3.4  changeset_long_messages = false
     3.5  changeset_show_files = 0
     3.6  default_daysback = 30
     3.7 -ticket_show_details = false
     3.8 +ticket_show_details = true
     3.9  
    3.10  [trac]
    3.11  authz_file = /etc/opt/kanon/svnauthz 
     4.1 --- a/kanon-setup	Tue Mar 22 19:03:40 2011 +0900
     4.2 +++ b/kanon-setup	Mon Mar 28 06:25:28 2011 +0900
     4.3 @@ -9,8 +9,14 @@
     4.4      APACHE_USER=www-data
     4.5  elif [ -f /etc/redhat-release ]
     4.6  then
     4.7 -    OS='rhel'
     4.8      APACHE_USER=apache
     4.9 +    CHK=`egrep "CentOS release 5|Red Hat Enterprise Linux .* 5" /etc/redhat-release`
    4.10 +    if [ "$CHK" != '' ]
    4.11 +    then
    4.12 +        OS='rhel5'
    4.13 +    else
    4.14 +        OS='rhel6'
    4.15 +    fi
    4.16  else
    4.17      echo "サポートされていないOSです。"
    4.18      echo "現在サポートされいているOSは、"
    4.19 @@ -19,6 +25,7 @@
    4.20      echo "  * Debian GNU/Linux, GNU/kFreeBSD 6.0"
    4.21      echo "  * RedHat Enterprise Linux 6.0"
    4.22      echo "  * Oracle Enterprise Linux 6.0"
    4.23 +    echo "  * CentOS 5.x (Experimental)"
    4.24      echo ""
    4.25      echo "です。"
    4.26      exit
    4.27 @@ -75,14 +82,29 @@
    4.28  
    4.29  
    4.30  ### install ubuntu package 
    4.31 -if [ "$OS" = 'debian' ]
    4.32 -then
    4.33 -    apt-get update
    4.34 -    apt-get -y install `cat pkglist.debian`
    4.35 -elif [ "$OS" = 'rhel' ]
    4.36 -then
    4.37 -    yum -y install `cat pkglist.rhel`
    4.38 -fi
    4.39 +case $OS in
    4.40 +    debian)
    4.41 +        apt-get update 
    4.42 +        apt-get -y install `cat pkglist.debian` 
    4.43 +        ;;
    4.44 +    rhel6)
    4.45 +        yum -y install `cat pkglist.rhel6`
    4.46 +        ;;
    4.47 +    rhel5)
    4.48 +        # Add EPEL Repository. For python26, python26-devel, python26-mod_wsgi.
    4.49 +        EPEL_RPM_URL="http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm"
    4.50 +        wget $EPEL_RPM_URL
    4.51 +        rpm -Uvh epel-release-5-4.noarch.rpm
    4.52 +        rm -f epel-release-5-4.noarch.rpm
    4.53 +        yum -y install `cat pkglist.rhel5`
    4.54 +
    4.55 +        # Add Kanon Repository. For Subversion 1.6 with Python26.
    4.56 +        cp -f resource/kanon.repo /etc/yum.repos.d/kanon.repo
    4.57 +        yum -y install subversion-1.6.15 mod_dav_svn-1.6.15
    4.58 +        ;;
    4.59 +    *)
    4.60 +        ;;
    4.61 +esac
    4.62  
    4.63  ### install jenkins
    4.64  if [ "$JENKINS" = 'y' ]
    4.65 @@ -142,12 +164,18 @@
    4.66  
    4.67  ### install files
    4.68  cp -fr opt/* /opt
    4.69 -cp -frn etc/* /etc
    4.70 +if [ "$OS" = "rhel5" ]
    4.71 +then
    4.72 +    # FIXME CentOS 5.x では n オプションがないため 強制上書きになってしまう.
    4.73 +    cp -fr etc/* /etc
    4.74 +else
    4.75 +    cp -frn etc/* /etc
    4.76 +fi
    4.77  
    4.78  
    4.79  ### setup configuration
    4.80 -export PYTHONPATH=/opt/kanon/lib/python2.6:/opt/kanon/lib/python2.6/site-packages
    4.81 -cp resource/dot.pydistutils.cfg ~/.pydistutils.cfg
    4.82 +python2.6 resource/virtualenv.py /opt/kanon
    4.83 +source /opt/kanon/bin/activate
    4.84  
    4.85  ## setup sitecustomize for python
    4.86  if [ -f /etc/python2.6/sitecustomize.py ]
    4.87 @@ -159,19 +187,27 @@
    4.88      fi
    4.89  fi
    4.90  
    4.91 -### install python components
    4.92 -easy_install --prefix $KANON_OPT http://svn.edgewall.org/repos/genshi/tags/0.6.0/
    4.93 -easy_install --prefix $KANON_OPT http://ftp.edgewall.com/pub/babel/Babel-0.9.5.zip
    4.94 -easy_install --prefix $KANON_OPT http://www.i-act.co.jp/project/products/downloads/Trac-0.12.2.ja1.zip
    4.95 -easy_install --prefix $KANON_OPT xlrd
    4.96 -easy_install --prefix $KANON_OPT https://github.com/hvr/trac-git-plugin/zipball/v0.12.0.5
    4.97 +
    4.98 +if [ "$OS" = "rhel5" ]
    4.99 +then
   4.100 +    # Install Extra Package for CentOS 5.X
   4.101 +    easy_install "mercurial==1.7.3"
   4.102 +    easy_install bzr
   4.103 +    easy_install pygments
   4.104 +fi
   4.105 +
   4.106 +easy_install http://svn.edgewall.org/repos/genshi/tags/0.6.0/
   4.107 +easy_install http://ftp.edgewall.com/pub/babel/Babel-0.9.5.zip
   4.108 +easy_install http://www.i-act.co.jp/project/products/downloads/Trac-0.12.2.ja1.zip
   4.109 +easy_install xlrd
   4.110 +easy_install https://github.com/hvr/trac-git-plugin/zipball/v0.12.0.5
   4.111  # bzr co lp:trac-bzr /tmp/trac-bzr-install
   4.112  #easy_install --prefix /opt/kanon /tmp/trac-bzr-install
   4.113  #rm -fr /tmp/trac-bzr-install
   4.114  
   4.115  
   4.116  ### install trac plugins
   4.117 -easy_install --prefix $KANON_OPT http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin 
   4.118 +easy_install http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin
   4.119  
   4.120  #resource/pluginsディレクトリのプラグインをインストール
   4.121  pushd .
   4.122 @@ -179,8 +215,8 @@
   4.123  cd resource/trac-plugins
   4.124  for i in `ls -1 .`
   4.125  do
   4.126 -    cd $i;python setup.py install --prefix=/opt/kanon
   4.127 -    cd ..   
   4.128 +    cd $i;python setup.py install
   4.129 +    cd ..
   4.130  done
   4.131  cd ../..
   4.132  
   4.133 @@ -191,7 +227,7 @@
   4.134      cd /tmp
   4.135      svn co $i kanon_build
   4.136      cd kanon_build
   4.137 -    python setup.py install --prefix=/opt/kanon
   4.138 +    python setup.py install
   4.139      cd ..
   4.140      rm -fr kanon_build
   4.141  done
   4.142 @@ -199,38 +235,63 @@
   4.143  
   4.144  
   4.145  ### setup apache and restart
   4.146 -if [ "$OS" = 'debian' ]
   4.147 -then
   4.148 -    cp resource/trac_hook.py /usr/lib/python2.6/dist-packages/bzrlib/plugins
   4.149 -    if [ ! -f /etc/apache2/sites-available/kanon ]
   4.150 -    then
   4.151 -        cp resource/httpd.conf /etc/apache2/sites-available/kanon
   4.152 -    fi
   4.153 -    a2enmod expires
   4.154 -    a2enmod auth_digest
   4.155 -    a2enmod dav_fs
   4.156 -    a2ensite kanon
   4.157 -    service apache2 stop
   4.158 -    service apache2 start
   4.159 -elif [ "$OS" = 'rhel' ]
   4.160 -then
   4.161 -    mkdir -p /usr/lib/python2.6/site-packages/bzrlib/plugin
   4.162 -    cp resource/trac_hook.py /usr/lib/python2.6/site-packages/bzrlib/plugin
   4.163 -    if [ ! -f /etc/httpd/conf.d/kanon.conf ]
   4.164 -    then
   4.165 -        cp resource/httpd.conf /etc/httpd/conf.d/kanon.conf
   4.166 -    fi
   4.167 -    echo 0 > /selinux/enforce
   4.168 -    CHK=`grep SELINUX=enforcing /etc/selinux/config` 
   4.169 -    if [ ! "$CHK" = '' ]   
   4.170 -    then
   4.171 -        cat /etc/selinux/config |sed 's/SELINUX=enforcing/SELINUX=disabled/' > /tmp/selinux_config
   4.172 -        mv -f /tmp/selinux_config /etc/selinux/config 
   4.173 -    fi
   4.174 -    echo "SELinuxが無効化されました"
   4.175 -    service httpd stop
   4.176 -    service httpd start
   4.177 -fi
   4.178 +case $OS in
   4.179 +    debian)
   4.180 +        cp resource/trac_hook.py /usr/lib/python2.6/dist-packages/bzrlib/plugins
   4.181 +        if [ ! -f /etc/apache2/sites-available/kanon ]
   4.182 +        then
   4.183 +            cp resource/httpd.conf /etc/apache2/sites-available/kanon
   4.184 +        fi
   4.185 +        a2enmod expires
   4.186 +        a2enmod auth_digest
   4.187 +        a2enmod dav_fs
   4.188 +        a2ensite kanon
   4.189 +        service apache2 stop
   4.190 +        service apache2 start
   4.191 +        ;;
   4.192 +    rhel6)
   4.193 +        mkdir -p /usr/lib/python2.6/site-packages/bzrlib/plugin
   4.194 +        cp resource/trac_hook.py /usr/lib/python2.6/site-packages/bzrlib/plugin
   4.195 +        if [ ! -f /etc/httpd/conf.d/kanon.conf ]
   4.196 +        then
   4.197 +            cp resource/httpd.conf /etc/httpd/conf.d/kanon.conf
   4.198 +        fi
   4.199 +        echo 0 > /selinux/enforce
   4.200 +        CHK=`grep SELINUX=enforcing /etc/selinux/config` 
   4.201 +        if [ ! "$CHK" = '' ]   
   4.202 +        then
   4.203 +            cat /etc/selinux/config |sed 's/SELINUX=enforcing/SELINUX=disabled/' > /tmp/selinux_config
   4.204 +            mv /tmp/selinux_config /etc/selinux/config 
   4.205 +        fi
   4.206 +        echo "SELinuxが無効化されました"
   4.207 +        service httpd stop
   4.208 +        service httpd start
   4.209 +        ;;
   4.210 +    rhel5)
   4.211 +        mkdir -p /var/opt/kanon/trac/.egg-cache
   4.212 +        chown $APACHE_USER:$APACHE_USER -R /var/opt/kanon/trac/.egg-cache/
   4.213 +        mkdir -p /usr/lib/python2.6/site-packages/bzrlib/plugin
   4.214 +        cp resource/trac_hook.py /usr/lib/python2.6/site-packages/bzrlib/plugin
   4.215 +        if [ ! -f /etc/httpd/conf.d/kanon.conf ]
   4.216 +        then
   4.217 +            cp resource/httpd.conf /etc/httpd/conf.d/kanon.conf
   4.218 +        fi
   4.219 +        echo 0 > /selinux/enforce
   4.220 +        CHK=`grep SELINUX=enforcing /etc/selinux/config` 
   4.221 +        if [ ! "$CHK" = '' ]   
   4.222 +        then
   4.223 +            cat /etc/selinux/config |sed 's/SELINUX=enforcing/SELINUX=disabled/' > /tmp/selinux_config
   4.224 +            mv /tmp/selinux_config /etc/selinux/config 
   4.225 +        fi
   4.226 +        echo "SELinuxが無効化されました"
   4.227 +        mv /etc/httpd/conf.d/python.conf /etc/httpd/conf.d/python.conf.disabled
   4.228 +        service httpd stop
   4.229 +        service httpd start
   4.230 +        ;;
   4.231 +    *)
   4.232 +        ;;
   4.233 +esac
   4.234 +
   4.235  
   4.236  # データディレクトリが存在しない場合作成
   4.237  if [ ! -d "$KANON_VAR/trac" ]
     5.1 --- a/opt/kanon/lib/cgi-bin/hgweb.wsgi	Tue Mar 22 19:03:40 2011 +0900
     5.2 +++ b/opt/kanon/lib/cgi-bin/hgweb.wsgi	Mon Mar 28 06:25:28 2011 +0900
     5.3 @@ -5,6 +5,9 @@
     5.4  config = "/etc/opt/kanon/hgweb.config"
     5.5  
     5.6  import os
     5.7 +import sys
     5.8 +reload(sys)
     5.9 +sys.setdefaultencoding("utf-8")
    5.10  os.environ["HGENCODING"] = "UTF-8"
    5.11  
    5.12  # Uncomment and adjust if Mercurial is not installed system-wide:
     6.1 --- a/pkglist.rhel	Tue Mar 22 19:03:40 2011 +0900
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,11 +0,0 @@
     6.4 -httpd
     6.5 -python-setuptools
     6.6 -python-pygments
     6.7 -sqlite
     6.8 -mod_dav_svn
     6.9 -mod_wsgi
    6.10 -subversion
    6.11 -mercurial
    6.12 -bzr
    6.13 -gcc
    6.14 -git
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/pkglist.rhel5	Mon Mar 28 06:25:28 2011 +0900
     7.3 @@ -0,0 +1,6 @@
     7.4 +python26
     7.5 +python26-devel
     7.6 +python26-mod_wsgi
     7.7 +httpd
     7.8 +sqlite
     7.9 +gcc
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/pkglist.rhel6	Mon Mar 28 06:25:28 2011 +0900
     8.3 @@ -0,0 +1,11 @@
     8.4 +httpd
     8.5 +python-setuptools
     8.6 +python-pygments
     8.7 +sqlite
     8.8 +mod_dav_svn
     8.9 +mod_wsgi
    8.10 +subversion
    8.11 +mercurial
    8.12 +bzr
    8.13 +gcc
    8.14 +git
     9.1 --- a/resource/httpd.conf	Tue Mar 22 19:03:40 2011 +0900
     9.2 +++ b/resource/httpd.conf	Mon Mar 28 06:25:28 2011 +0900
     9.3 @@ -24,7 +24,7 @@
     9.4  </Location>
     9.5  
     9.6  # Subversionの設定
     9.7 -<Location "/svn">
     9.8 +<Location "/svn/">
     9.9  	DAV svn
    9.10  	SVNParentPath /var/opt/kanon/svn
    9.11  	SVNListParentPath on
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/resource/kanon.repo	Mon Mar 28 06:25:28 2011 +0900
    10.3 @@ -0,0 +1,5 @@
    10.4 +[kanon]
    10.5 +name = RHEL $releasever - Kanon - chris
    10.6 +baseurl = http://kanon.ultimania.org/pkg/centos5/$basearch
    10.7 +enabled = 1
    10.8 +gpgcheck = 0
    10.9 \ No newline at end of file
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/resource/virtualenv.py	Mon Mar 28 06:25:28 2011 +0900
    11.3 @@ -0,0 +1,1651 @@
    11.4 +#!/usr/bin/env python
    11.5 +"""Create a "virtual" Python installation
    11.6 +"""
    11.7 +
    11.8 +virtualenv_version = "1.5.1"
    11.9 +
   11.10 +import sys
   11.11 +import os
   11.12 +import optparse
   11.13 +import re
   11.14 +import shutil
   11.15 +import logging
   11.16 +import tempfile
   11.17 +import distutils.sysconfig
   11.18 +try:
   11.19 +    import subprocess
   11.20 +except ImportError, e:
   11.21 +    if sys.version_info <= (2, 3):
   11.22 +        print 'ERROR: %s' % e
   11.23 +        print 'ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.'
   11.24 +        print 'If you copy subprocess.py from a newer version of Python this script will probably work'
   11.25 +        sys.exit(101)
   11.26 +    else:
   11.27 +        raise
   11.28 +try:
   11.29 +    set
   11.30 +except NameError:
   11.31 +    from sets import Set as set
   11.32 +
   11.33 +join = os.path.join
   11.34 +py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
   11.35 +
   11.36 +is_jython = sys.platform.startswith('java')
   11.37 +is_pypy = hasattr(sys, 'pypy_version_info')
   11.38 +
   11.39 +if is_pypy:
   11.40 +    expected_exe = 'pypy-c'
   11.41 +elif is_jython:
   11.42 +    expected_exe = 'jython'
   11.43 +else:
   11.44 +    expected_exe = 'python'
   11.45 +
   11.46 +
   11.47 +REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
   11.48 +                    'fnmatch', 'locale', 'encodings', 'codecs',
   11.49 +                    'stat', 'UserDict', 'readline', 'copy_reg', 'types',
   11.50 +                    're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
   11.51 +                    'zlib']
   11.52 +
   11.53 +REQUIRED_FILES = ['lib-dynload', 'config']
   11.54 +
   11.55 +if sys.version_info[:2] >= (2, 6):
   11.56 +    REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc'])
   11.57 +if sys.version_info[:2] >= (2, 7):
   11.58 +    REQUIRED_MODULES.extend(['_weakrefset'])
   11.59 +if sys.version_info[:2] <= (2, 3):
   11.60 +    REQUIRED_MODULES.extend(['sets', '__future__'])
   11.61 +if is_pypy:
   11.62 +    # these are needed to correctly display the exceptions that may happen
   11.63 +    # during the bootstrap
   11.64 +    REQUIRED_MODULES.extend(['traceback', 'linecache'])
   11.65 +
   11.66 +class Logger(object):
   11.67 +
   11.68 +    """
   11.69 +    Logging object for use in command-line script.  Allows ranges of
   11.70 +    levels, to avoid some redundancy of displayed information.
   11.71 +    """
   11.72 +
   11.73 +    DEBUG = logging.DEBUG
   11.74 +    INFO = logging.INFO
   11.75 +    NOTIFY = (logging.INFO+logging.WARN)/2
   11.76 +    WARN = WARNING = logging.WARN
   11.77 +    ERROR = logging.ERROR
   11.78 +    FATAL = logging.FATAL
   11.79 +
   11.80 +    LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
   11.81 +
   11.82 +    def __init__(self, consumers):
   11.83 +        self.consumers = consumers
   11.84 +        self.indent = 0
   11.85 +        self.in_progress = None
   11.86 +        self.in_progress_hanging = False
   11.87 +
   11.88 +    def debug(self, msg, *args, **kw):
   11.89 +        self.log(self.DEBUG, msg, *args, **kw)
   11.90 +    def info(self, msg, *args, **kw):
   11.91 +        self.log(self.INFO, msg, *args, **kw)
   11.92 +    def notify(self, msg, *args, **kw):
   11.93 +        self.log(self.NOTIFY, msg, *args, **kw)
   11.94 +    def warn(self, msg, *args, **kw):
   11.95 +        self.log(self.WARN, msg, *args, **kw)
   11.96 +    def error(self, msg, *args, **kw):
   11.97 +        self.log(self.WARN, msg, *args, **kw)
   11.98 +    def fatal(self, msg, *args, **kw):
   11.99 +        self.log(self.FATAL, msg, *args, **kw)
  11.100 +    def log(self, level, msg, *args, **kw):
  11.101 +        if args:
  11.102 +            if kw:
  11.103 +                raise TypeError(
  11.104 +                    "You may give positional or keyword arguments, not both")
  11.105 +        args = args or kw
  11.106 +        rendered = None
  11.107 +        for consumer_level, consumer in self.consumers:
  11.108 +            if self.level_matches(level, consumer_level):
  11.109 +                if (self.in_progress_hanging
  11.110 +                    and consumer in (sys.stdout, sys.stderr)):
  11.111 +                    self.in_progress_hanging = False
  11.112 +                    sys.stdout.write('\n')
  11.113 +                    sys.stdout.flush()
  11.114 +                if rendered is None:
  11.115 +                    if args:
  11.116 +                        rendered = msg % args
  11.117 +                    else:
  11.118 +                        rendered = msg
  11.119 +                    rendered = ' '*self.indent + rendered
  11.120 +                if hasattr(consumer, 'write'):
  11.121 +                    consumer.write(rendered+'\n')
  11.122 +                else:
  11.123 +                    consumer(rendered)
  11.124 +
  11.125 +    def start_progress(self, msg):
  11.126 +        assert not self.in_progress, (
  11.127 +            "Tried to start_progress(%r) while in_progress %r"
  11.128 +            % (msg, self.in_progress))
  11.129 +        if self.level_matches(self.NOTIFY, self._stdout_level()):
  11.130 +            sys.stdout.write(msg)
  11.131 +            sys.stdout.flush()
  11.132 +            self.in_progress_hanging = True
  11.133 +        else:
  11.134 +            self.in_progress_hanging = False
  11.135 +        self.in_progress = msg
  11.136 +
  11.137 +    def end_progress(self, msg='done.'):
  11.138 +        assert self.in_progress, (
  11.139 +            "Tried to end_progress without start_progress")
  11.140 +        if self.stdout_level_matches(self.NOTIFY):
  11.141 +            if not self.in_progress_hanging:
  11.142 +                # Some message has been printed out since start_progress
  11.143 +                sys.stdout.write('...' + self.in_progress + msg + '\n')
  11.144 +                sys.stdout.flush()
  11.145 +            else:
  11.146 +                sys.stdout.write(msg + '\n')
  11.147 +                sys.stdout.flush()
  11.148 +        self.in_progress = None
  11.149 +        self.in_progress_hanging = False
  11.150 +
  11.151 +    def show_progress(self):
  11.152 +        """If we are in a progress scope, and no log messages have been
  11.153 +        shown, write out another '.'"""
  11.154 +        if self.in_progress_hanging:
  11.155 +            sys.stdout.write('.')
  11.156 +            sys.stdout.flush()
  11.157 +
  11.158 +    def stdout_level_matches(self, level):
  11.159 +        """Returns true if a message at this level will go to stdout"""
  11.160 +        return self.level_matches(level, self._stdout_level())
  11.161 +
  11.162 +    def _stdout_level(self):
  11.163 +        """Returns the level that stdout runs at"""
  11.164 +        for level, consumer in self.consumers:
  11.165 +            if consumer is sys.stdout:
  11.166 +                return level
  11.167 +        return self.FATAL
  11.168 +
  11.169 +    def level_matches(self, level, consumer_level):
  11.170 +        """
  11.171 +        >>> l = Logger()
  11.172 +        >>> l.level_matches(3, 4)
  11.173 +        False
  11.174 +        >>> l.level_matches(3, 2)
  11.175 +        True
  11.176 +        >>> l.level_matches(slice(None, 3), 3)
  11.177 +        False
  11.178 +        >>> l.level_matches(slice(None, 3), 2)
  11.179 +        True
  11.180 +        >>> l.level_matches(slice(1, 3), 1)
  11.181 +        True
  11.182 +        >>> l.level_matches(slice(2, 3), 1)
  11.183 +        False
  11.184 +        """
  11.185 +        if isinstance(level, slice):
  11.186 +            start, stop = level.start, level.stop
  11.187 +            if start is not None and start > consumer_level:
  11.188 +                return False
  11.189 +            if stop is not None or stop <= consumer_level:
  11.190 +                return False
  11.191 +            return True
  11.192 +        else:
  11.193 +            return level >= consumer_level
  11.194 +
  11.195 +    #@classmethod
  11.196 +    def level_for_integer(cls, level):
  11.197 +        levels = cls.LEVELS
  11.198 +        if level < 0:
  11.199 +            return levels[0]
  11.200 +        if level >= len(levels):
  11.201 +            return levels[-1]
  11.202 +        return levels[level]
  11.203 +
  11.204 +    level_for_integer = classmethod(level_for_integer)
  11.205 +
  11.206 +def mkdir(path):
  11.207 +    if not os.path.exists(path):
  11.208 +        logger.info('Creating %s', path)
  11.209 +        os.makedirs(path)
  11.210 +    else:
  11.211 +        logger.info('Directory %s already exists', path)
  11.212 +
  11.213 +def copyfile(src, dest, symlink=True):
  11.214 +    if not os.path.exists(src):
  11.215 +        # Some bad symlink in the src
  11.216 +        logger.warn('Cannot find file %s (bad symlink)', src)
  11.217 +        return
  11.218 +    if os.path.exists(dest):
  11.219 +        logger.debug('File %s already exists', dest)
  11.220 +        return
  11.221 +    if not os.path.exists(os.path.dirname(dest)):
  11.222 +        logger.info('Creating parent directories for %s' % os.path.dirname(dest))
  11.223 +        os.makedirs(os.path.dirname(dest))
  11.224 +    if symlink and hasattr(os, 'symlink'):
  11.225 +        logger.info('Symlinking %s', dest)
  11.226 +        os.symlink(os.path.abspath(src), dest)
  11.227 +    else:
  11.228 +        logger.info('Copying to %s', dest)
  11.229 +        if os.path.isdir(src):
  11.230 +            shutil.copytree(src, dest, True)
  11.231 +        else:
  11.232 +            shutil.copy2(src, dest)
  11.233 +
  11.234 +def writefile(dest, content, overwrite=True):
  11.235 +    if not os.path.exists(dest):
  11.236 +        logger.info('Writing %s', dest)
  11.237 +        f = open(dest, 'wb')
  11.238 +        f.write(content)
  11.239 +        f.close()
  11.240 +        return
  11.241 +    else:
  11.242 +        f = open(dest, 'rb')
  11.243 +        c = f.read()
  11.244 +        f.close()
  11.245 +        if c != content:
  11.246 +            if not overwrite:
  11.247 +                logger.notify('File %s exists with different content; not overwriting', dest)
  11.248 +                return
  11.249 +            logger.notify('Overwriting %s with new content', dest)
  11.250 +            f = open(dest, 'wb')
  11.251 +            f.write(content)
  11.252 +            f.close()
  11.253 +        else:
  11.254 +            logger.info('Content %s already in place', dest)
  11.255 +
  11.256 +def rmtree(dir):
  11.257 +    if os.path.exists(dir):
  11.258 +        logger.notify('Deleting tree %s', dir)
  11.259 +        shutil.rmtree(dir)
  11.260 +    else:
  11.261 +        logger.info('Do not need to delete %s; already gone', dir)
  11.262 +
  11.263 +def make_exe(fn):
  11.264 +    if hasattr(os, 'chmod'):
  11.265 +        oldmode = os.stat(fn).st_mode & 07777
  11.266 +        newmode = (oldmode | 0555) & 07777
  11.267 +        os.chmod(fn, newmode)
  11.268 +        logger.info('Changed mode of %s to %s', fn, oct(newmode))
  11.269 +
  11.270 +def _find_file(filename, dirs):
  11.271 +    for dir in dirs:
  11.272 +        if os.path.exists(join(dir, filename)):
  11.273 +            return join(dir, filename)
  11.274 +    return filename
  11.275 +
  11.276 +def _install_req(py_executable, unzip=False, distribute=False):
  11.277 +    if not distribute:
  11.278 +        setup_fn = 'setuptools-0.6c11-py%s.egg' % sys.version[:3]
  11.279 +        project_name = 'setuptools'
  11.280 +        bootstrap_script = EZ_SETUP_PY
  11.281 +        source = None
  11.282 +    else:
  11.283 +        setup_fn = None
  11.284 +        source = 'distribute-0.6.14.tar.gz'
  11.285 +        project_name = 'distribute'
  11.286 +        bootstrap_script = DISTRIBUTE_SETUP_PY
  11.287 +        try:
  11.288 +            # check if the global Python has distribute installed or plain
  11.289 +            # setuptools
  11.290 +            import pkg_resources
  11.291 +            if not hasattr(pkg_resources, '_distribute'):
  11.292 +                location = os.path.dirname(pkg_resources.__file__)
  11.293 +                logger.notify("A globally installed setuptools was found (in %s)" % location)
  11.294 +                logger.notify("Use the --no-site-packages option to use distribute in "
  11.295 +                              "the virtualenv.")
  11.296 +        except ImportError:
  11.297 +            pass
  11.298 +
  11.299 +    search_dirs = file_search_dirs()
  11.300 +
  11.301 +    if setup_fn is not None:
  11.302 +        setup_fn = _find_file(setup_fn, search_dirs)
  11.303 +
  11.304 +    if source is not None:
  11.305 +        source = _find_file(source, search_dirs)
  11.306 +
  11.307 +    if is_jython and os._name == 'nt':
  11.308 +        # Jython's .bat sys.executable can't handle a command line
  11.309 +        # argument with newlines
  11.310 +        fd, ez_setup = tempfile.mkstemp('.py')
  11.311 +        os.write(fd, bootstrap_script)
  11.312 +        os.close(fd)
  11.313 +        cmd = [py_executable, ez_setup]
  11.314 +    else:
  11.315 +        cmd = [py_executable, '-c', bootstrap_script]
  11.316 +    if unzip:
  11.317 +        cmd.append('--always-unzip')
  11.318 +    env = {}
  11.319 +    remove_from_env = []
  11.320 +    if logger.stdout_level_matches(logger.DEBUG):
  11.321 +        cmd.append('-v')
  11.322 +
  11.323 +    old_chdir = os.getcwd()
  11.324 +    if setup_fn is not None and os.path.exists(setup_fn):
  11.325 +        logger.info('Using existing %s egg: %s' % (project_name, setup_fn))
  11.326 +        cmd.append(setup_fn)
  11.327 +        if os.environ.get('PYTHONPATH'):
  11.328 +            env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH']
  11.329 +        else:
  11.330 +            env['PYTHONPATH'] = setup_fn
  11.331 +    else:
  11.332 +        # the source is found, let's chdir
  11.333 +        if source is not None and os.path.exists(source):
  11.334 +            os.chdir(os.path.dirname(source))
  11.335 +            # in this case, we want to be sure that PYTHONPATH is unset (not
  11.336 +            # just empty, really unset), else CPython tries to import the
  11.337 +            # site.py that it's in virtualenv_support
  11.338 +            remove_from_env.append('PYTHONPATH')
  11.339 +        else:
  11.340 +            logger.info('No %s egg found; downloading' % project_name)
  11.341 +        cmd.extend(['--always-copy', '-U', project_name])
  11.342 +    logger.start_progress('Installing %s...' % project_name)
  11.343 +    logger.indent += 2
  11.344 +    cwd = None
  11.345 +    if project_name == 'distribute':
  11.346 +        env['DONT_PATCH_SETUPTOOLS'] = 'true'
  11.347 +
  11.348 +    def _filter_ez_setup(line):
  11.349 +        return filter_ez_setup(line, project_name)
  11.350 +
  11.351 +    if not os.access(os.getcwd(), os.W_OK):
  11.352 +        cwd = tempfile.mkdtemp()
  11.353 +        if source is not None and os.path.exists(source):
  11.354 +            # the current working dir is hostile, let's copy the
  11.355 +            # tarball to a temp dir
  11.356 +            target = os.path.join(cwd, os.path.split(source)[-1])
  11.357 +            shutil.copy(source, target)
  11.358 +    try:
  11.359 +        call_subprocess(cmd, show_stdout=False,
  11.360 +                        filter_stdout=_filter_ez_setup,
  11.361 +                        extra_env=env,
  11.362 +                        remove_from_env=remove_from_env,
  11.363 +                        cwd=cwd)
  11.364 +    finally:
  11.365 +        logger.indent -= 2
  11.366 +        logger.end_progress()
  11.367 +        if os.getcwd() != old_chdir:
  11.368 +            os.chdir(old_chdir)
  11.369 +        if is_jython and os._name == 'nt':
  11.370 +            os.remove(ez_setup)
  11.371 +
  11.372 +def file_search_dirs():
  11.373 +    here = os.path.dirname(os.path.abspath(__file__))
  11.374 +    dirs = ['.', here,
  11.375 +            join(here, 'virtualenv_support')]
  11.376 +    if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
  11.377 +        # Probably some boot script; just in case virtualenv is installed...
  11.378 +        try:
  11.379 +            import virtualenv
  11.380 +        except ImportError:
  11.381 +            pass
  11.382 +        else:
  11.383 +            dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
  11.384 +    return [d for d in dirs if os.path.isdir(d)]
  11.385 +
  11.386 +def install_setuptools(py_executable, unzip=False):
  11.387 +    _install_req(py_executable, unzip)
  11.388 +
  11.389 +def install_distribute(py_executable, unzip=False):
  11.390 +    _install_req(py_executable, unzip, distribute=True)
  11.391 +
  11.392 +_pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I)
  11.393 +def install_pip(py_executable):
  11.394 +    filenames = []
  11.395 +    for dir in file_search_dirs():
  11.396 +        filenames.extend([join(dir, fn) for fn in os.listdir(dir)
  11.397 +                          if _pip_re.search(fn)])
  11.398 +    filenames = [(os.path.basename(filename).lower(), i, filename) for i, filename in enumerate(filenames)]
  11.399 +    filenames.sort()
  11.400 +    filenames = [filename for basename, i, filename in filenames]
  11.401 +    if not filenames:
  11.402 +        filename = 'pip'
  11.403 +    else:
  11.404 +        filename = filenames[-1]
  11.405 +    easy_install_script = 'easy_install'
  11.406 +    if sys.platform == 'win32':
  11.407 +        easy_install_script = 'easy_install-script.py'
  11.408 +    cmd = [py_executable, join(os.path.dirname(py_executable), easy_install_script), filename]
  11.409 +    if filename == 'pip':
  11.410 +        logger.info('Installing pip from network...')
  11.411 +    else:
  11.412 +        logger.info('Installing %s' % os.path.basename(filename))
  11.413 +    logger.indent += 2
  11.414 +    def _filter_setup(line):
  11.415 +        return filter_ez_setup(line, 'pip')
  11.416 +    try:
  11.417 +        call_subprocess(cmd, show_stdout=False,
  11.418 +                        filter_stdout=_filter_setup)
  11.419 +    finally:
  11.420 +        logger.indent -= 2
  11.421 +
  11.422 +def filter_ez_setup(line, project_name='setuptools'):
  11.423 +    if not line.strip():
  11.424 +        return Logger.DEBUG
  11.425 +    if project_name == 'distribute':
  11.426 +        for prefix in ('Extracting', 'Now working', 'Installing', 'Before',
  11.427 +                       'Scanning', 'Setuptools', 'Egg', 'Already',
  11.428 +                       'running', 'writing', 'reading', 'installing',
  11.429 +                       'creating', 'copying', 'byte-compiling', 'removing',
  11.430 +                       'Processing'):
  11.431 +            if line.startswith(prefix):
  11.432 +                return Logger.DEBUG
  11.433 +        return Logger.DEBUG
  11.434 +    for prefix in ['Reading ', 'Best match', 'Processing setuptools',
  11.435 +                   'Copying setuptools', 'Adding setuptools',
  11.436 +                   'Installing ', 'Installed ']:
  11.437 +        if line.startswith(prefix):
  11.438 +            return Logger.DEBUG
  11.439 +    return Logger.INFO
  11.440 +
  11.441 +def main():
  11.442 +    parser = optparse.OptionParser(
  11.443 +        version=virtualenv_version,
  11.444 +        usage="%prog [OPTIONS] DEST_DIR")
  11.445 +
  11.446 +    parser.add_option(
  11.447 +        '-v', '--verbose',
  11.448 +        action='count',
  11.449 +        dest='verbose',
  11.450 +        default=0,
  11.451 +        help="Increase verbosity")
  11.452 +
  11.453 +    parser.add_option(
  11.454 +        '-q', '--quiet',
  11.455 +        action='count',
  11.456 +        dest='quiet',
  11.457 +        default=0,
  11.458 +        help='Decrease verbosity')
  11.459 +
  11.460 +    parser.add_option(
  11.461 +        '-p', '--python',
  11.462 +        dest='python',
  11.463 +        metavar='PYTHON_EXE',
  11.464 +        help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
  11.465 +        'interpreter to create the new environment.  The default is the interpreter that '
  11.466 +        'virtualenv was installed with (%s)' % sys.executable)
  11.467 +
  11.468 +    parser.add_option(
  11.469 +        '--clear',
  11.470 +        dest='clear',
  11.471 +        action='store_true',
  11.472 +        help="Clear out the non-root install and start from scratch")
  11.473 +
  11.474 +    parser.add_option(
  11.475 +        '--no-site-packages',
  11.476 +        dest='no_site_packages',
  11.477 +        action='store_true',
  11.478 +        help="Don't give access to the global site-packages dir to the "
  11.479 +             "virtual environment")
  11.480 +
  11.481 +    parser.add_option(
  11.482 +        '--unzip-setuptools',
  11.483 +        dest='unzip_setuptools',
  11.484 +        action='store_true',
  11.485 +        help="Unzip Setuptools or Distribute when installing it")
  11.486 +
  11.487 +    parser.add_option(
  11.488 +        '--relocatable',
  11.489 +        dest='relocatable',
  11.490 +        action='store_true',
  11.491 +        help='Make an EXISTING virtualenv environment relocatable.  '
  11.492 +        'This fixes up scripts and makes all .pth files relative')
  11.493 +
  11.494 +    parser.add_option(
  11.495 +        '--distribute',
  11.496 +        dest='use_distribute',
  11.497 +        action='store_true',
  11.498 +        help='Use Distribute instead of Setuptools. Set environ variable '
  11.499 +        'VIRTUALENV_USE_DISTRIBUTE to make it the default ')
  11.500 +
  11.501 +    parser.add_option(
  11.502 +        '--prompt=',
  11.503 +        dest='prompt',
  11.504 +        help='Provides an alternative prompt prefix for this environment')
  11.505 +
  11.506 +    if 'extend_parser' in globals():
  11.507 +        extend_parser(parser)
  11.508 +
  11.509 +    options, args = parser.parse_args()
  11.510 +
  11.511 +    global logger
  11.512 +
  11.513 +    if 'adjust_options' in globals():
  11.514 +        adjust_options(options, args)
  11.515 +
  11.516 +    verbosity = options.verbose - options.quiet
  11.517 +    logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)])
  11.518 +
  11.519 +    if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
  11.520 +        env = os.environ.copy()
  11.521 +        interpreter = resolve_interpreter(options.python)
  11.522 +        if interpreter == sys.executable:
  11.523 +            logger.warn('Already using interpreter %s' % interpreter)
  11.524 +        else:
  11.525 +            logger.notify('Running virtualenv with interpreter %s' % interpreter)
  11.526 +            env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
  11.527 +            file = __file__
  11.528 +            if file.endswith('.pyc'):
  11.529 +                file = file[:-1]
  11.530 +            popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
  11.531 +            raise SystemExit(popen.wait())
  11.532 +
  11.533 +    if not args:
  11.534 +        print 'You must provide a DEST_DIR'
  11.535 +        parser.print_help()
  11.536 +        sys.exit(2)
  11.537 +    if len(args) > 1:
  11.538 +        print 'There must be only one argument: DEST_DIR (you gave %s)' % (
  11.539 +            ' '.join(args))
  11.540 +        parser.print_help()
  11.541 +        sys.exit(2)
  11.542 +
  11.543 +    home_dir = args[0]
  11.544 +
  11.545 +    if os.environ.get('WORKING_ENV'):
  11.546 +        logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
  11.547 +        logger.fatal('Please deactivate your workingenv, then re-run this script')
  11.548 +        sys.exit(3)
  11.549 +
  11.550 +    if 'PYTHONHOME' in os.environ:
  11.551 +        logger.warn('PYTHONHOME is set.  You *must* activate the virtualenv before using it')
  11.552 +        del os.environ['PYTHONHOME']
  11.553 +
  11.554 +    if options.relocatable:
  11.555 +        make_environment_relocatable(home_dir)
  11.556 +        return
  11.557 +
  11.558 +    create_environment(home_dir, site_packages=not options.no_site_packages, clear=options.clear,
  11.559 +                       unzip_setuptools=options.unzip_setuptools,
  11.560 +                       use_distribute=options.use_distribute,
  11.561 +                       prompt=options.prompt)
  11.562 +    if 'after_install' in globals():
  11.563 +        after_install(options, home_dir)
  11.564 +
  11.565 +def call_subprocess(cmd, show_stdout=True,
  11.566 +                    filter_stdout=None, cwd=None,
  11.567 +                    raise_on_returncode=True, extra_env=None,
  11.568 +                    remove_from_env=None):
  11.569 +    cmd_parts = []
  11.570 +    for part in cmd:
  11.571 +        if len(part) > 40:
  11.572 +            part = part[:30]+"..."+part[-5:]
  11.573 +        if ' ' in part or '\n' in part or '"' in part or "'" in part:
  11.574 +            part = '"%s"' % part.replace('"', '\\"')
  11.575 +        cmd_parts.append(part)
  11.576 +    cmd_desc = ' '.join(cmd_parts)
  11.577 +    if show_stdout:
  11.578 +        stdout = None
  11.579 +    else:
  11.580 +        stdout = subprocess.PIPE
  11.581 +    logger.debug("Running command %s" % cmd_desc)
  11.582 +    if extra_env or remove_from_env:
  11.583 +        env = os.environ.copy()
  11.584 +        if extra_env:
  11.585 +            env.update(extra_env)
  11.586 +        if remove_from_env:
  11.587 +            for varname in remove_from_env:
  11.588 +                env.pop(varname, None)
  11.589 +    else:
  11.590 +        env = None
  11.591 +    try:
  11.592 +        proc = subprocess.Popen(
  11.593 +            cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
  11.594 +            cwd=cwd, env=env)
  11.595 +    except Exception, e:
  11.596 +        logger.fatal(
  11.597 +            "Error %s while executing command %s" % (e, cmd_desc))
  11.598 +        raise
  11.599 +    all_output = []
  11.600 +    if stdout is not None:
  11.601 +        stdout = proc.stdout
  11.602 +        while 1:
  11.603 +            line = stdout.readline()
  11.604 +            if not line:
  11.605 +                break
  11.606 +            line = line.rstrip()
  11.607 +            all_output.append(line)
  11.608 +            if filter_stdout:
  11.609 +                level = filter_stdout(line)
  11.610 +                if isinstance(level, tuple):
  11.611 +                    level, line = level
  11.612 +                logger.log(level, line)
  11.613 +                if not logger.stdout_level_matches(level):
  11.614 +                    logger.show_progress()
  11.615 +            else:
  11.616 +                logger.info(line)
  11.617 +    else:
  11.618 +        proc.communicate()
  11.619 +    proc.wait()
  11.620 +    if proc.returncode:
  11.621 +        if raise_on_returncode:
  11.622 +            if all_output:
  11.623 +                logger.notify('Complete output from command %s:' % cmd_desc)
  11.624 +                logger.notify('\n'.join(all_output) + '\n----------------------------------------')
  11.625 +            raise OSError(
  11.626 +                "Command %s failed with error code %s"
  11.627 +                % (cmd_desc, proc.returncode))
  11.628 +        else:
  11.629 +            logger.warn(
  11.630 +                "Command %s had error code %s"
  11.631 +                % (cmd_desc, proc.returncode))
  11.632 +
  11.633 +
  11.634 +def create_environment(home_dir, site_packages=True, clear=False,
  11.635 +                       unzip_setuptools=False, use_distribute=False,
  11.636 +                       prompt=None):
  11.637 +    """
  11.638 +    Creates a new environment in ``home_dir``.
  11.639 +
  11.640 +    If ``site_packages`` is true (the default) then the global
  11.641 +    ``site-packages/`` directory will be on the path.
  11.642 +
  11.643 +    If ``clear`` is true (default False) then the environment will
  11.644 +    first be cleared.
  11.645 +    """
  11.646 +    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
  11.647 +
  11.648 +    py_executable = os.path.abspath(install_python(
  11.649 +        home_dir, lib_dir, inc_dir, bin_dir,
  11.650 +        site_packages=site_packages, clear=clear))
  11.651 +
  11.652 +    install_distutils(home_dir)
  11.653 +
  11.654 +    if use_distribute or os.environ.get('VIRTUALENV_USE_DISTRIBUTE'):
  11.655 +        install_distribute(py_executable, unzip=unzip_setuptools)
  11.656 +    else:
  11.657 +        install_setuptools(py_executable, unzip=unzip_setuptools)
  11.658 +
  11.659 +    install_pip(py_executable)
  11.660 +
  11.661 +    install_activate(home_dir, bin_dir, prompt)
  11.662 +
  11.663 +def path_locations(home_dir):
  11.664 +    """Return the path locations for the environment (where libraries are,
  11.665 +    where scripts go, etc)"""
  11.666 +    # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
  11.667 +    # prefix arg is broken: http://bugs.python.org/issue3386
  11.668 +    if sys.platform == 'win32':
  11.669 +        # Windows has lots of problems with executables with spaces in
  11.670 +        # the name; this function will remove them (using the ~1
  11.671 +        # format):
  11.672 +        mkdir(home_dir)
  11.673 +        if ' ' in home_dir:
  11.674 +            try:
  11.675 +                import win32api
  11.676 +            except ImportError:
  11.677 +                print 'Error: the path "%s" has a space in it' % home_dir
  11.678 +                print 'To handle these kinds of paths, the win32api module must be installed:'
  11.679 +                print '  http://sourceforge.net/projects/pywin32/'
  11.680 +                sys.exit(3)
  11.681 +            home_dir = win32api.GetShortPathName(home_dir)
  11.682 +        lib_dir = join(home_dir, 'Lib')
  11.683 +        inc_dir = join(home_dir, 'Include')
  11.684 +        bin_dir = join(home_dir, 'Scripts')
  11.685 +    elif is_jython:
  11.686 +        lib_dir = join(home_dir, 'Lib')
  11.687 +        inc_dir = join(home_dir, 'Include')
  11.688 +        bin_dir = join(home_dir, 'bin')
  11.689 +    elif is_pypy:
  11.690 +        lib_dir = home_dir
  11.691 +        inc_dir = join(home_dir, 'include')
  11.692 +        bin_dir = join(home_dir, 'bin')
  11.693 +    else:
  11.694 +        lib_dir = join(home_dir, 'lib', py_version)
  11.695 +        inc_dir = join(home_dir, 'include', py_version)
  11.696 +        bin_dir = join(home_dir, 'bin')
  11.697 +    return home_dir, lib_dir, inc_dir, bin_dir
  11.698 +
  11.699 +
  11.700 +def change_prefix(filename, dst_prefix):
  11.701 +    prefixes = [sys.prefix]
  11.702 +    if hasattr(sys, 'real_prefix'):
  11.703 +        prefixes.append(sys.real_prefix)
  11.704 +    prefixes = map(os.path.abspath, prefixes)
  11.705 +    filename = os.path.abspath(filename)
  11.706 +    for src_prefix in prefixes:
  11.707 +        if filename.startswith(src_prefix):
  11.708 +            _, relpath = filename.split(src_prefix, 1)
  11.709 +            assert relpath[0] == os.sep
  11.710 +            relpath = relpath[1:]
  11.711 +            return join(dst_prefix, relpath)
  11.712 +    assert False, "Filename %s does not start with any of these prefixes: %s" % \
  11.713 +        (filename, prefixes)
  11.714 +
  11.715 +def copy_required_modules(dst_prefix):
  11.716 +    import imp
  11.717 +    for modname in REQUIRED_MODULES:
  11.718 +        if modname in sys.builtin_module_names:
  11.719 +            logger.info("Ignoring built-in bootstrap module: %s" % modname)
  11.720 +            continue
  11.721 +        try:
  11.722 +            f, filename, _ = imp.find_module(modname)
  11.723 +        except ImportError:
  11.724 +            logger.info("Cannot import bootstrap module: %s" % modname)
  11.725 +        else:
  11.726 +            if f is not None:
  11.727 +                f.close()
  11.728 +            dst_filename = change_prefix(filename, dst_prefix)
  11.729 +            copyfile(filename, dst_filename)
  11.730 +            if filename.endswith('.pyc'):
  11.731 +                pyfile = filename[:-1]
  11.732 +                if os.path.exists(pyfile):
  11.733 +                    copyfile(pyfile, dst_filename[:-1])
  11.734 +
  11.735 +
  11.736 +def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
  11.737 +    """Install just the base environment, no distutils patches etc"""
  11.738 +    if sys.executable.startswith(bin_dir):
  11.739 +        print 'Please use the *system* python to run this script'
  11.740 +        return
  11.741 +
  11.742 +    if clear:
  11.743 +        rmtree(lib_dir)
  11.744 +        ## FIXME: why not delete it?
  11.745 +        ## Maybe it should delete everything with #!/path/to/venv/python in it
  11.746 +        logger.notify('Not deleting %s', bin_dir)
  11.747 +
  11.748 +    if hasattr(sys, 'real_prefix'):
  11.749 +        logger.notify('Using real prefix %r' % sys.real_prefix)
  11.750 +        prefix = sys.real_prefix
  11.751 +    else:
  11.752 +        prefix = sys.prefix
  11.753 +    mkdir(lib_dir)
  11.754 +    fix_lib64(lib_dir)
  11.755 +    stdlib_dirs = [os.path.dirname(os.__file__)]
  11.756 +    if sys.platform == 'win32':
  11.757 +        stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
  11.758 +    elif sys.platform == 'darwin':
  11.759 +        stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
  11.760 +    if hasattr(os, 'symlink'):
  11.761 +        logger.info('Symlinking Python bootstrap modules')
  11.762 +    else:
  11.763 +        logger.info('Copying Python bootstrap modules')
  11.764 +    logger.indent += 2
  11.765 +    try:
  11.766 +        # copy required files...
  11.767 +        for stdlib_dir in stdlib_dirs:
  11.768 +            if not os.path.isdir(stdlib_dir):
  11.769 +                continue
  11.770 +            for fn in os.listdir(stdlib_dir):
  11.771 +                if fn != 'site-packages' and os.path.splitext(fn)[0] in REQUIRED_FILES:
  11.772 +                    copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
  11.773 +        # ...and modules
  11.774 +        copy_required_modules(home_dir)
  11.775 +    finally:
  11.776 +        logger.indent -= 2
  11.777 +    mkdir(join(lib_dir, 'site-packages'))
  11.778 +    import site
  11.779 +    site_filename = site.__file__
  11.780 +    if site_filename.endswith('.pyc'):
  11.781 +        site_filename = site_filename[:-1]
  11.782 +    elif site_filename.endswith('$py.class'):
  11.783 +        site_filename = site_filename.replace('$py.class', '.py')
  11.784 +    site_filename_dst = change_prefix(site_filename, home_dir)
  11.785 +    site_dir = os.path.dirname(site_filename_dst)
  11.786 +    writefile(site_filename_dst, SITE_PY)
  11.787 +    writefile(join(site_dir, 'orig-prefix.txt'), prefix)
  11.788 +    site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
  11.789 +    if not site_packages:
  11.790 +        writefile(site_packages_filename, '')
  11.791 +    else:
  11.792 +        if os.path.exists(site_packages_filename):
  11.793 +            logger.info('Deleting %s' % site_packages_filename)
  11.794 +            os.unlink(site_packages_filename)
  11.795 +
  11.796 +    if is_pypy:
  11.797 +        stdinc_dir = join(prefix, 'include')
  11.798 +    else:
  11.799 +        stdinc_dir = join(prefix, 'include', py_version)
  11.800 +    if os.path.exists(stdinc_dir):
  11.801 +        copyfile(stdinc_dir, inc_dir)
  11.802 +    else:
  11.803 +        logger.debug('No include dir %s' % stdinc_dir)
  11.804 +
  11.805 +    if sys.exec_prefix != prefix:
  11.806 +        if sys.platform == 'win32':
  11.807 +            exec_dir = join(sys.exec_prefix, 'lib')
  11.808 +        elif is_jython:
  11.809 +            exec_dir = join(sys.exec_prefix, 'Lib')
  11.810 +        else:
  11.811 +            exec_dir = join(sys.exec_prefix, 'lib', py_version)
  11.812 +        for fn in os.listdir(exec_dir):
  11.813 +            copyfile(join(exec_dir, fn), join(lib_dir, fn))
  11.814 +
  11.815 +    if is_jython:
  11.816 +        # Jython has either jython-dev.jar and javalib/ dir, or just
  11.817 +        # jython.jar
  11.818 +        for name in 'jython-dev.jar', 'javalib', 'jython.jar':
  11.819 +            src = join(prefix, name)
  11.820 +            if os.path.exists(src):
  11.821 +                copyfile(src, join(home_dir, name))
  11.822 +        # XXX: registry should always exist after Jython 2.5rc1
  11.823 +        src = join(prefix, 'registry')
  11.824 +        if os.path.exists(src):
  11.825 +            copyfile(src, join(home_dir, 'registry'), symlink=False)
  11.826 +        copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
  11.827 +                 symlink=False)
  11.828 +
  11.829 +    mkdir(bin_dir)
  11.830 +    py_executable = join(bin_dir, os.path.basename(sys.executable))
  11.831 +    if 'Python.framework' in prefix:
  11.832 +        if re.search(r'/Python(?:-32|-64)*$', py_executable):
  11.833 +            # The name of the python executable is not quite what
  11.834 +            # we want, rename it.
  11.835 +            py_executable = os.path.join(
  11.836 +                    os.path.dirname(py_executable), 'python')
  11.837 +
  11.838 +    logger.notify('New %s executable in %s', expected_exe, py_executable)
  11.839 +    if sys.executable != py_executable:
  11.840 +        ## FIXME: could I just hard link?
  11.841 +        executable = sys.executable
  11.842 +        if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'):
  11.843 +            # Cygwin misreports sys.executable sometimes
  11.844 +            executable += '.exe'
  11.845 +            py_executable += '.exe'
  11.846 +            logger.info('Executable actually exists in %s' % executable)
  11.847 +        shutil.copyfile(executable, py_executable)
  11.848 +        make_exe(py_executable)
  11.849 +        if sys.platform == 'win32' or sys.platform == 'cygwin':
  11.850 +            pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
  11.851 +            if os.path.exists(pythonw):
  11.852 +                logger.info('Also created pythonw.exe')
  11.853 +                shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
  11.854 +        if is_pypy:
  11.855 +            # make a symlink python --> pypy-c
  11.856 +            python_executable = os.path.join(os.path.dirname(py_executable), 'python')
  11.857 +            logger.info('Also created executable %s' % python_executable)
  11.858 +            copyfile(py_executable, python_executable)
  11.859 +
  11.860 +    if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
  11.861 +        secondary_exe = os.path.join(os.path.dirname(py_executable),
  11.862 +                                     expected_exe)
  11.863 +        py_executable_ext = os.path.splitext(py_executable)[1]
  11.864 +        if py_executable_ext == '.exe':
  11.865 +            # python2.4 gives an extension of '.4' :P
  11.866 +            secondary_exe += py_executable_ext
  11.867 +        if os.path.exists(secondary_exe):
  11.868 +            logger.warn('Not overwriting existing %s script %s (you must use %s)'
  11.869 +                        % (expected_exe, secondary_exe, py_executable))
  11.870 +        else:
  11.871 +            logger.notify('Also creating executable in %s' % secondary_exe)
  11.872 +            shutil.copyfile(sys.executable, secondary_exe)
  11.873 +            make_exe(secondary_exe)
  11.874 +
  11.875 +    if 'Python.framework' in prefix:
  11.876 +        logger.debug('MacOSX Python framework detected')
  11.877 +
  11.878 +        # Make sure we use the the embedded interpreter inside
  11.879 +        # the framework, even if sys.executable points to
  11.880 +        # the stub executable in ${sys.prefix}/bin
  11.881 +        # See http://groups.google.com/group/python-virtualenv/
  11.882 +        #                              browse_thread/thread/17cab2f85da75951
  11.883 +        original_python = os.path.join(
  11.884 +            prefix, 'Resources/Python.app/Contents/MacOS/Python')
  11.885 +        shutil.copy(original_python, py_executable)
  11.886 +
  11.887 +        # Copy the framework's dylib into the virtual
  11.888 +        # environment
  11.889 +        virtual_lib = os.path.join(home_dir, '.Python')
  11.890 +
  11.891 +        if os.path.exists(virtual_lib):
  11.892 +            os.unlink(virtual_lib)
  11.893 +        copyfile(
  11.894 +            os.path.join(prefix, 'Python'),
  11.895 +            virtual_lib)
  11.896 +
  11.897 +        # And then change the install_name of the copied python executable
  11.898 +        try:
  11.899 +            call_subprocess(
  11.900 +                ["install_name_tool", "-change",
  11.901 +                 os.path.join(prefix, 'Python'),
  11.902 +                 '@executable_path/../.Python',
  11.903 +                 py_executable])
  11.904 +        except:
  11.905 +            logger.fatal(
  11.906 +                "Could not call install_name_tool -- you must have Apple's development tools installed")
  11.907 +            raise
  11.908 +
  11.909 +        # Some tools depend on pythonX.Y being present
  11.910 +        py_executable_version = '%s.%s' % (
  11.911 +            sys.version_info[0], sys.version_info[1])
  11.912 +        if not py_executable.endswith(py_executable_version):
  11.913 +            # symlinking pythonX.Y > python
  11.914 +            pth = py_executable + '%s.%s' % (
  11.915 +                    sys.version_info[0], sys.version_info[1])
  11.916 +            if os.path.exists(pth):
  11.917 +                os.unlink(pth)
  11.918 +            os.symlink('python', pth)
  11.919 +        else:
  11.920 +            # reverse symlinking python -> pythonX.Y (with --python)
  11.921 +            pth = join(bin_dir, 'python')
  11.922 +            if os.path.exists(pth):
  11.923 +                os.unlink(pth)
  11.924 +            os.symlink(os.path.basename(py_executable), pth)
  11.925 +
  11.926 +    if sys.platform == 'win32' and ' ' in py_executable:
  11.927 +        # There's a bug with subprocess on Windows when using a first
  11.928 +        # argument that has a space in it.  Instead we have to quote
  11.929 +        # the value:
  11.930 +        py_executable = '"%s"' % py_executable
  11.931 +    cmd = [py_executable, '-c', 'import sys; print sys.prefix']
  11.932 +    logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
  11.933 +    proc = subprocess.Popen(cmd,
  11.934 +                            stdout=subprocess.PIPE)
  11.935 +    proc_stdout, proc_stderr = proc.communicate()
  11.936 +    proc_stdout = os.path.normcase(os.path.abspath(proc_stdout.strip()))
  11.937 +    if proc_stdout != os.path.normcase(os.path.abspath(home_dir)):
  11.938 +        logger.fatal(
  11.939 +            'ERROR: The executable %s is not functioning' % py_executable)
  11.940 +        logger.fatal(
  11.941 +            'ERROR: It thinks sys.prefix is %r (should be %r)'
  11.942 +            % (proc_stdout, os.path.normcase(os.path.abspath(home_dir))))
  11.943 +        logger.fatal(
  11.944 +            'ERROR: virtualenv is not compatible with this system or executable')
  11.945 +        if sys.platform == 'win32':
  11.946 +            logger.fatal(
  11.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)')
  11.948 +        sys.exit(100)
  11.949 +    else:
  11.950 +        logger.info('Got sys.prefix result: %r' % proc_stdout)
  11.951 +
  11.952 +    pydistutils = os.path.expanduser('~/.pydistutils.cfg')
  11.953 +    if os.path.exists(pydistutils):
  11.954 +        logger.notify('Please make sure you remove any previous custom paths from '
  11.955 +                      'your %s file.' % pydistutils)
  11.956 +    ## FIXME: really this should be calculated earlier
  11.957 +    return py_executable
  11.958 +
  11.959 +def install_activate(home_dir, bin_dir, prompt=None):
  11.960 +    if sys.platform == 'win32' or is_jython and os._name == 'nt':
  11.961 +        files = {'activate.bat': ACTIVATE_BAT,
  11.962 +                 'deactivate.bat': DEACTIVATE_BAT}
  11.963 +        if os.environ.get('OS') == 'Windows_NT' and os.environ.get('OSTYPE') == 'cygwin':
  11.964 +            files['activate'] = ACTIVATE_SH
  11.965 +    else:
  11.966 +        files = {'activate': ACTIVATE_SH}
  11.967 +
  11.968 +        # suppling activate.fish in addition to, not instead of, the
  11.969 +        # bash script support.
  11.970 +        files['activate.fish'] = ACTIVATE_FISH
  11.971 +
  11.972 +        # same for csh/tcsh support...
  11.973 +        files['activate.csh'] = ACTIVATE_CSH
  11.974 +
  11.975 +
  11.976 +
  11.977 +    files['activate_this.py'] = ACTIVATE_THIS
  11.978 +    vname = os.path.basename(os.path.abspath(home_dir))
  11.979 +    for name, content in files.items():
  11.980 +        content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
  11.981 +        content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname)
  11.982 +        content = content.replace('__VIRTUAL_ENV__', os.path.abspath(home_dir))
  11.983 +        content = content.replace('__VIRTUAL_NAME__', vname)
  11.984 +        content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
  11.985 +        writefile(os.path.join(bin_dir, name), content)
  11.986 +
  11.987 +def install_distutils(home_dir):
  11.988 +    distutils_path = change_prefix(distutils.__path__[0], home_dir)
  11.989 +    mkdir(distutils_path)
  11.990 +    ## FIXME: maybe this prefix setting should only be put in place if
  11.991 +    ## there's a local distutils.cfg with a prefix setting?
  11.992 +    home_dir = os.path.abspath(home_dir)
  11.993 +    ## FIXME: this is breaking things, removing for now:
  11.994 +    #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
  11.995 +    writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
  11.996 +    writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
  11.997 +
  11.998 +def fix_lib64(lib_dir):
  11.999 +    """
 11.1000 +    Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
 11.1001 +    instead of lib/pythonX.Y.  If this is such a platform we'll just create a
 11.1002 +    symlink so lib64 points to lib
 11.1003 +    """
 11.1004 +    if [p for p in distutils.sysconfig.get_config_vars().values()
 11.1005 +        if isinstance(p, basestring) and 'lib64' in p]:
 11.1006 +        logger.debug('This system uses lib64; symlinking lib64 to lib')
 11.1007 +        assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
 11.1008 +            "Unexpected python lib dir: %r" % lib_dir)
 11.1009 +        lib_parent = os.path.dirname(lib_dir)
 11.1010 +        assert os.path.basename(lib_parent) == 'lib', (
 11.1011 +            "Unexpected parent dir: %r" % lib_parent)
 11.1012 +        copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64'))
 11.1013 +
 11.1014 +def resolve_interpreter(exe):
 11.1015 +    """
 11.1016 +    If the executable given isn't an absolute path, search $PATH for the interpreter
 11.1017 +    """
 11.1018 +    if os.path.abspath(exe) != exe:
 11.1019 +        paths = os.environ.get('PATH', '').split(os.pathsep)
 11.1020 +        for path in paths:
 11.1021 +            if os.path.exists(os.path.join(path, exe)):
 11.1022 +                exe = os.path.join(path, exe)
 11.1023 +                break
 11.1024 +    if not os.path.exists(exe):
 11.1025 +        logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
 11.1026 +        sys.exit(3)
 11.1027 +    return exe
 11.1028 +
 11.1029 +############################################################
 11.1030 +## Relocating the environment:
 11.1031 +
 11.1032 +def make_environment_relocatable(home_dir):
 11.1033 +    """
 11.1034 +    Makes the already-existing environment use relative paths, and takes out
 11.1035 +    the #!-based environment selection in scripts.
 11.1036 +    """
 11.1037 +    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
 11.1038 +    activate_this = os.path.join(bin_dir, 'activate_this.py')
 11.1039 +    if not os.path.exists(activate_this):
 11.1040 +        logger.fatal(
 11.1041 +            'The environment doesn\'t have a file %s -- please re-run virtualenv '
 11.1042 +            'on this environment to update it' % activate_this)
 11.1043 +    fixup_scripts(home_dir)
 11.1044 +    fixup_pth_and_egg_link(home_dir)
 11.1045 +    ## FIXME: need to fix up distutils.cfg
 11.1046 +
 11.1047 +OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
 11.1048 +                  'activate', 'activate.bat', 'activate_this.py']
 11.1049 +
 11.1050 +def fixup_scripts(home_dir):
 11.1051 +    # This is what we expect at the top of scripts:
 11.1052 +    shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
 11.1053 +    # This is what we'll put:
 11.1054 +    new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
 11.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"
 11.1056 +    if sys.platform == 'win32':
 11.1057 +        bin_suffix = 'Scripts'
 11.1058 +    else:
 11.1059 +        bin_suffix = 'bin'
 11.1060 +    bin_dir = os.path.join(home_dir, bin_suffix)
 11.1061 +    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
 11.1062 +    for filename in os.listdir(bin_dir):
 11.1063 +        filename = os.path.join(bin_dir, filename)
 11.1064 +        if not os.path.isfile(filename):
 11.1065 +            # ignore subdirs, e.g. .svn ones.
 11.1066 +            continue
 11.1067 +        f = open(filename, 'rb')
 11.1068 +        lines = f.readlines()
 11.1069 +        f.close()
 11.1070 +        if not lines:
 11.1071 +            logger.warn('Script %s is an empty file' % filename)
 11.1072 +            continue
 11.1073 +        if not lines[0].strip().startswith(shebang):
 11.1074 +            if os.path.basename(filename) in OK_ABS_SCRIPTS:
 11.1075 +                logger.debug('Cannot make script %s relative' % filename)
 11.1076 +            elif lines[0].strip() == new_shebang:
 11.1077 +                logger.info('Script %s has already been made relative' % filename)
 11.1078 +            else:
 11.1079 +                logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
 11.1080 +                            % (filename, shebang))
 11.1081 +            continue
 11.1082 +        logger.notify('Making script %s relative' % filename)
 11.1083 +        lines = [new_shebang+'\n', activate+'\n'] + lines[1:]
 11.1084 +        f = open(filename, 'wb')
 11.1085 +        f.writelines(lines)
 11.1086 +        f.close()
 11.1087 +
 11.1088 +def fixup_pth_and_egg_link(home_dir, sys_path=None):
 11.1089 +    """Makes .pth and .egg-link files use relative paths"""
 11.1090 +    home_dir = os.path.normcase(os.path.abspath(home_dir))
 11.1091 +    if sys_path is None:
 11.1092 +        sys_path = sys.path
 11.1093 +    for path in sys_path:
 11.1094 +        if not path:
 11.1095 +            path = '.'
 11.1096 +        if not os.path.isdir(path):
 11.1097 +            continue
 11.1098 +        path = os.path.normcase(os.path.abspath(path))
 11.1099 +        if not path.startswith(home_dir):
 11.1100 +            logger.debug('Skipping system (non-environment) directory %s' % path)
 11.1101 +            continue
 11.1102 +        for filename in os.listdir(path):
 11.1103 +            filename = os.path.join(path, filename)
 11.1104 +            if filename.endswith('.pth'):
 11.1105 +                if not os.access(filename, os.W_OK):
 11.1106 +                    logger.warn('Cannot write .pth file %s, skipping' % filename)
 11.1107 +                else:
 11.1108 +                    fixup_pth_file(filename)
 11.1109 +            if filename.endswith('.egg-link'):
 11.1110 +                if not os.access(filename, os.W_OK):
 11.1111 +                    logger.warn('Cannot write .egg-link file %s, skipping' % filename)
 11.1112 +                else:
 11.1113 +                    fixup_egg_link(filename)
 11.1114 +
 11.1115 +def fixup_pth_file(filename):
 11.1116 +    lines = []
 11.1117 +    prev_lines = []
 11.1118 +    f = open(filename)
 11.1119 +    prev_lines = f.readlines()
 11.1120 +    f.close()
 11.1121 +    for line in prev_lines:
 11.1122 +        line = line.strip()
 11.1123 +        if (not line or line.startswith('#') or line.startswith('import ')
 11.1124 +            or os.path.abspath(line) != line):
 11.1125 +            lines.append(line)
 11.1126 +        else:
 11.1127 +            new_value = make_relative_path(filename, line)
 11.1128 +            if line != new_value:
 11.1129 +                logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
 11.1130 +            lines.append(new_value)
 11.1131 +    if lines == prev_lines:
 11.1132 +        logger.info('No changes to .pth file %s' % filename)
 11.1133 +        return
 11.1134 +    logger.notify('Making paths in .pth file %s relative' % filename)
 11.1135 +    f = open(filename, 'w')
 11.1136 +    f.write('\n'.join(lines) + '\n')
 11.1137 +    f.close()
 11.1138 +
 11.1139 +def fixup_egg_link(filename):
 11.1140 +    f = open(filename)
 11.1141 +    link = f.read().strip()
 11.1142 +    f.close()
 11.1143 +    if os.path.abspath(link) != link:
 11.1144 +        logger.debug('Link in %s already relative' % filename)
 11.1145 +        return
 11.1146 +    new_link = make_relative_path(filename, link)
 11.1147 +    logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
 11.1148 +    f = open(filename, 'w')
 11.1149 +    f.write(new_link)
 11.1150 +    f.close()
 11.1151 +
 11.1152 +def make_relative_path(source, dest, dest_is_directory=True):
 11.1153 +    """
 11.1154 +    Make a filename relative, where the filename is dest, and it is
 11.1155 +    being referred to from the filename source.
 11.1156 +
 11.1157 +        >>> make_relative_path('/usr/share/something/a-file.pth',
 11.1158 +        ...                    '/usr/share/another-place/src/Directory')
 11.1159 +        '../another-place/src/Directory'
 11.1160 +        >>> make_relative_path('/usr/share/something/a-file.pth',
 11.1161 +        ...                    '/home/user/src/Directory')
 11.1162 +        '../../../home/user/src/Directory'
 11.1163 +        >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
 11.1164 +        './'
 11.1165 +    """
 11.1166 +    source = os.path.dirname(source)
 11.1167 +    if not dest_is_directory:
 11.1168 +        dest_filename = os.path.basename(dest)
 11.1169 +        dest = os.path.dirname(dest)
 11.1170 +    dest = os.path.normpath(os.path.abspath(dest))
 11.1171 +    source = os.path.normpath(os.path.abspath(source))
 11.1172 +    dest_parts = dest.strip(os.path.sep).split(os.path.sep)
 11.1173 +    source_parts = source.strip(os.path.sep).split(os.path.sep)
 11.1174 +    while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
 11.1175 +        dest_parts.pop(0)
 11.1176 +        source_parts.pop(0)
 11.1177 +    full_parts = ['..']*len(source_parts) + dest_parts
 11.1178 +    if not dest_is_directory:
 11.1179 +        full_parts.append(dest_filename)
 11.1180 +    if not full_parts:
 11.1181 +        # Special case for the current directory (otherwise it'd be '')
 11.1182 +        return './'
 11.1183 +    return os.path.sep.join(full_parts)
 11.1184 +
 11.1185 +
 11.1186 +
 11.1187 +############################################################
 11.1188 +## Bootstrap script creation:
 11.1189 +
 11.1190 +def create_bootstrap_script(extra_text, python_version=''):
 11.1191 +    """
 11.1192 +    Creates a bootstrap script, which is like this script but with
 11.1193 +    extend_parser, adjust_options, and after_install hooks.
 11.1194 +
 11.1195 +    This returns a string that (written to disk of course) can be used
 11.1196 +    as a bootstrap script with your own customizations.  The script
 11.1197 +    will be the standard virtualenv.py script, with your extra text
 11.1198 +    added (your extra text should be Python code).
 11.1199 +
 11.1200 +    If you include these functions, they will be called:
 11.1201 +
 11.1202 +    ``extend_parser(optparse_parser)``:
 11.1203 +        You can add or remove options from the parser here.
 11.1204 +
 11.1205 +    ``adjust_options(options, args)``:
 11.1206 +        You can change options here, or change the args (if you accept
 11.1207 +        different kinds of arguments, be sure you modify ``args`` so it is
 11.1208 +        only ``[DEST_DIR]``).
 11.1209 +
 11.1210 +    ``after_install(options, home_dir)``:
 11.1211 +
 11.1212 +        After everything is installed, this function is called.  This
 11.1213 +        is probably the function you are most likely to use.  An
 11.1214 +        example would be::
 11.1215 +
 11.1216 +            def after_install(options, home_dir):
 11.1217 +                subprocess.call([join(home_dir, 'bin', 'easy_install'),
 11.1218 +                                 'MyPackage'])
 11.1219 +                subprocess.call([join(home_dir, 'bin', 'my-package-script'),
 11.1220 +                                 'setup', home_dir])
 11.1221 +
 11.1222 +        This example immediately installs a package, and runs a setup
 11.1223 +        script from that package.
 11.1224 +
 11.1225 +    If you provide something like ``python_version='2.4'`` then the
 11.1226 +    script will start with ``#!/usr/bin/env python2.4`` instead of
 11.1227 +    ``#!/usr/bin/env python``.  You can use this when the script must
 11.1228 +    be run with a particular Python version.
 11.1229 +    """
 11.1230 +    filename = __file__
 11.1231 +    if filename.endswith('.pyc'):
 11.1232 +        filename = filename[:-1]
 11.1233 +    f = open(filename, 'rb')
 11.1234 +    content = f.read()
 11.1235 +    f.close()
 11.1236 +    py_exe = 'python%s' % python_version
 11.1237 +    content = (('#!/usr/bin/env %s\n' % py_exe)
 11.1238 +               + '## WARNING: This file is generated\n'
 11.1239 +               + content)
 11.1240 +    return content.replace('##EXT' 'END##', extra_text)
 11.1241 +
 11.1242 +##EXTEND##
 11.1243 +
 11.1244 +##file site.py
 11.1245 +SITE_PY = """
 11.1246 +eJzVPP1z2zaWv/OvQOXJUEplOh/dzo5T98ZJnNZ7buJt0mluXY+WkiCJNUWyBGlZe3P3t9/7AECA
 11.1247 +pGS77f5wmkwskcDDw8P7xgMGg8FpUchsLtb5vE6lUDIuZytRxNVKiUVeimqVlPPDIi6rLTyd3cRL
 11.1248 +qUSVC7VVEbaKguDpH/wET8WnVaIMCvAtrqt8HVfJLE7TrUjWRV5Wci7mdZlkS5FkSZXEafIvaJFn
 11.1249 +kXj6xzEIzjMBM08TWYpbWSqAq0S+EJfbapVnYlgXOOfn0V/il6OxULMyKSpoUGqcgSKruAoyKeeA
 11.1250 +JrSsFZAyqeShKuQsWSQz23CT1+lcFGk8k+Kf/+SpUdMwDFS+lpuVLKXIABmAKQFWgXjA16QUs3wu
 11.1251 +IyFey1mMA/DzhlgBQxvjmikkY5aLNM+WMKdMzqRScbkVw2ldESBCWcxzwCkBDKokTYNNXt6oESwp
 11.1252 +rccGHomY2cOfDLMHzBPH73IO4PghC37KkrsxwwbuQXDVitmmlIvkTsQIFn7KOzmb6GfDZCHmyWIB
 11.1253 +NMiqETYJGAEl0mR6VNByfKNX6NsjwspyZQxjSESZG/NL6hEF55WIUwVsWxdII0WYv5XTJM6AGtkt
 11.1254 +DAcQgaRB3zjzRFV2HJqdyAFAietYgZSslRiu4yQDZv0hnhHaPyfZPN+oEVEAVkuJX2tVufMf9hAA
 11.1255 +WjsEGAe4WGY16yxNbmS6HQECnwD7Uqo6rVAg5kkpZ1VeJlIRAEBtK+QdID0WcSk1CZkzjdyOif5E
 11.1256 +kyTDhUUBQ4HHl0iSRbKsS5IwsUiAc4Er3n34Ubw9e31++l7zmAHGMrtcA84AhRbawQkGEEe1Ko/S
 11.1257 +HAQ6Ci7wj4jncxSyJY4PeDUNju5d6WAIcy+idh9nwYHsenH1MDDHCpQJjRVQv/+GLmO1Avr8zz3r
 11.1258 +HQSnu6hCE+dvm1UOMpnFaylWMfMXckbwjYbzbVRUq1fADQrhVEAqhYuDCCYID0ji0myYZ1IUwGJp
 11.1259 +kslRABSaUlt/FYEV3ufZIa11ixMAQhlk8NJ5NqIRMwkT7cJ6hfrCNN7SzHSTwK7zOi9JcQD/ZzPS
 11.1260 +RWmc3RCOihiKv03lMskyRAh5IQgPQhpY3STAifNIXFAr0gumkQhZe3FLFIkaeAmZDnhS3sXrIpVj
 11.1261 +Fl/UrfvVCA0mK2HWOmWOg5YVqVdatWaqvbz3Ivrc4jpCs1qVEoDXU0/oFnk+FlPQ2YRNEa9ZvKpN
 11.1262 +TpwT9MgTdUKeoJbQF78DRU+VqtfSvkReAc1CDBUs8jTNN0Cy4yAQ4gAbGaPsMye8hXfwP8DF/1NZ
 11.1263 +zVZB4IxkAWtQiPwuUAgETILMNFdrJDxu06zcVjJJxpoiL+eypKEeRuwjRvyBjXGuwfu80kaNp4ur
 11.1264 +nK+TClXSVJvMhC1eFlasH1/xvGEaYLkV0cw0bei0xumlxSqeSuOSTOUCJUEv0iu77DBm0DMm2eJK
 11.1265 +rNnKwDsgi0zYgvQrFlQ6i0qSEwAwWPjiLCnqlBopZDARw0DrguCvYzTpuXaWgL3ZLAeokNh8z8D+
 11.1266 +AG7/AjHarBKgzwwggIZBLQXLN02qEh2ERh8FvtE3/Xl84NTzhbZNPOQiTlJt5eMsOKeHZ2VJ4juT
 11.1267 +BfYaa2IomGFWoWu3zICOKOaDwSAIjDu0VeZrbr9NJtM6QXs3mQRVuT0G7hAo5AFDF+9hojQcv1mU
 11.1268 ++RpfW/Q+gj4AvYw9ggNxSYpCso/rMdMrpICrlQvTFM2vw5ECVUlw+ePZu/PPZx/FibhqtNK4rZKu
 11.1269 +YcyzLAbOJKUOfNEatlFH0BJ1V4LqS7wDC03rCiaJepMEyriqgf0A9U9lTa9hGjPvZXD2/vT1xdnk
 11.1270 +p49nP04+nn86AwTBVMjggKaMFq4Gn09FwN/AWHMVaRMZdHrQg9enH+2DYJKoSbEttvAAbB1wYTmE
 11.1271 ++Y5FiA8n2oxOkmyRhyNq/Cv70SesGbTTdHX81bU4ORHhr/FtHAbguDRNeRF/IB7+tC0kdK3gzzBX
 11.1272 +oyCYywXw+41EqRg+JWd0xB2AiNAy18bx1zzJzHt67Q1BQjukHoDDZDJLY6Ww8WQSAmmpQ88HOkTs
 11.1273 +0SKrD6FjsXW7jjQq+CklLEWGXcb4Xw+K8ZT6IRqMotvFNAIZWc9iJbkVTR/6TSaoKCaToR4QJIh4
 11.1274 +HLwclv1QmCaoKMoEnEniFVQcU5Wn+BPho+iRyGA8g6oJF0nHK9FtnNZSDZ1JARGHwxYZUbslijgI
 11.1275 +/IIhmL9m6UajNjUNz0AzIF+ag+oqW5TDzwE4GaAjTOSE0RUHPEwzxPRv7N4TDuDnhahjlWpBYZUk
 11.1276 +Ls8uxctnLw7Rh4BAb26p4zVHs5hktbQPF7BaS1k5CHOvcEzCMHLpskDlhk+P98NcR3Zluqyw0Etc
 11.1277 +ynV+K+eALTKws8riR3oD4TDMYxbDKoIyJSPMSs84azEGfzx7kBY02EC9NUEx62+W/oAjcJkpUB0c
 11.1278 +zRKpdajN9qco89sELfx0q1+CgQL1hmbKeBOBs3Aek6EdAg0BrmeGlNrIEBRYWbOXSHgjSFTx80YV
 11.1279 +RgTuAnXrNX29yfJNNuHw8wTV5HBkWRcFSzMvNmiW4EC8A8MBSOYQTTVEYyjgZwuUrUNAHqYP0wXK
 11.1280 +kkMPgMC6KoqRHFgmvqIpcqiGwyKM0StBwltKNNK3ZgiKbwwxHEj0NrIPjJZASDA5q+CsatBMhrJm
 11.1281 +msHADkl8rruIOO7zAbSoGIGhG2po3MjQ7+oYlLO4cJWS0w9t6OfPn5lt1IqSGojYFCeNdntB5i0q
 11.1282 +tmAKE9AJxg3iFAmxwQY8SgBTK82a4vCjyAt2gWA9L7Vsg+WGkKqqiuOjo81mE+mQPi+XR2px9Je/
 11.1283 +fv31X5+xTpzPiX9gOo606PxWdETv0I2MvjEW6Fuzci1+TDKfGwnWUJIrRP4f4vddncxzcXw4svoT
 11.1284 +ubgxrPi/cT5AgUzMoExloO2gweiJOnwSvVQD8UQM3bbDEXsS2qRaK+ZbXehR5WC7wdOY5XVWhY4i
 11.1285 +VeJLsG4QFs/ltF6GdnDPRpofMFWU06HlgcPn14iBzxmGr4wpnqCWILZAi++Q/kdmm5j8Ga0hkLxo
 11.1286 +ojoh67Zfixnizh8u79Y7dITGzDBRyB0oEX6TBwugbdyVHPxoZxTtnuOMmo9nCIylDwzzaldwiIJD
 11.1287 +uOBajF2pc7gafVSQpg2rZlAwrmoEBQ1u3ZSprcGRjQwRJHo3JsLmhdUtgE6tdJ0Jys0qQAt3nI61
 11.1288 +a7OC4wkhD5yI5/REglN73Hn3jJe2TlPKorR41KMKA/YWGu10Dnw5NADGYlD+NOCWelnOP7QWhdeg
 11.1289 +B1jOiRdksEWHmfCN6wMODgY97NSx+rt6M437QOAiUfuHASeMT3iAUoEwFUOfcXdxuKUtJ5taCO82
 11.1290 +OMRTZpVIotUO2Wrrjl6Z2muXFkmGqtdZo2iW5uAUW6VIfNS8930FClzwcZ8t0wKoydCQw2l0Qs6e
 11.1291 +J3+hbocpq2WNwb2b+0CM1oki44ZkWsF/4FVQToESQEBLgmbBPFTI/In9CSJn56u/7GAPS2hkCLfp
 11.1292 +Li+kYzA0HPP+QCAZdQYEhCADEnZlkTxH1gYpcJizQJ5sw2u5U7gJRqRAzBwDQloGcKeXXnyDTyLc
 11.1293 +dSABRch3lZKF+FIMYPnakvow1f2ncqnJGgydBuQp6HTDiZuKcNIQJ620hM/QfkKC9ieKHDh4Ch6P
 11.1294 +m1x32dwwrc2SgK/u622LFChkSpwMRi6q14YwbgL3ixOnRUMsM4hhKG8gbxvFjDQK7HJr0LDgBoy3
 11.1295 +5u2x9GM3YYF9h2GuXsj1HYR/YZmoWa5CjG87qQv3o7miSxuL7UUyHcAfbwEGo2sPkkx1+gKTLL9j
 11.1296 +kNCDHvZB9yaLWZF5XG6SLCQFpul34i9NBw9LSs/GHX2kaOoIJopZxqN3JQgIbTcegTihJoCgXIZK
 11.1297 +e/1dsHunOLBwufvA85qvjl9ed4k73pXgsZ/+pTq7q8pY4WqlvGgsFLhaXfuNShcmF2dbvWGoN5Qx
 11.1298 +SihzBUGk+PDxs0BCcC51E28fN/WG4RGbe+fkfQzqoNfuJVdrdsQugAhqRWSUo/DxHPlwZB87uT0T
 11.1299 +ewSQRzHMnkUxkDSf/B44+xYKxjicbzNMo7VVBn7g9ddfTXoSoy6SX381uGeUFjH6xH7Y8gTtyLSR
 11.1300 +L3qnbbqUMk7J13A6UVIxa3jHtilGrNAp/NNMdt3jdOLHvDcmo4Hfad6JG83ngOgBUXY+/RViVaXT
 11.1301 +W7dxklJOHtA4PEQ9Z8Jszhz04+NB2o8ypqTAY3k27o2E1NUzWJiQ4/pRdzraLzo1qd+eeNR8ilh1
 11.1302 +UTnQW+jNDpC3Le7u/u2W/V5L/W/SWY8E5M1m0EPAB87B7E7+/58JKyuGppXVqKX1ldyv5w2wB6jD
 11.1303 +HW7OHjekOzRvZi2MM8Fyp8RTFNCnYkNb0pTKw40JgDJnP6MHDi6j3th8U5clb0+SnBeyPMT9urHA
 11.1304 +ahzjaVCRTxfM0XtZISa22YxSo07tRt6nOkOd7LQzCRs/tV9kV7lJkcjsNimhL2iVYfj9hx/Owi4D
 11.1305 +6GGwUz84dx0NlzzcTiHcRzBtqIkTPqYPU+gxXX6/VLVdZZ+gZsvYJCA12bqE7eQdTdzavwb3ZCC8
 11.1306 +/UHeh8WIcLaSs5uJpL1lZFPs6uRg3+BrxMRuOfs1PipeUKESzGSW1kgrdvSwwmxRZzNKx1cS7Lku
 11.1307 +B8XyENox5nTTIo2XYkid55jq0NxI2ZDbuNTeTlHmWIAo6mR+tEzmQv5WxymGkXKxAFxwr0S/inh4
 11.1308 +yniIt7zpzYVpSs7qMqm2QIJY5XqrifbHnYbTLU906CHJuwpMQNwxPxYfcdr4ngk3N+QywaifYMdJ
 11.1309 +YpyHHcxeIHIXPYf3WT7BUSdUxzlmpLrbwPQ4aI+QA4ABAIX5D0Y6U+S/kfTK3c+iNXeJilrSI6Ub
 11.1310 +2ebkcSCU4Qgja/5NP31GdHlrB5bL3Vgu92O5bGO57MVy6WO53I+lKxK4sDZJYiShL1HSzqL3FmS4
 11.1311 +OQ4e5iyerbgd1vdhHR9AFIUJ6IxMcZmrl0nh7SQCQmrb2d+kh02BRcKFg2XOKVcNErkf90x08GgK
 11.1312 +lJ3OVK6hO/NUjM+2q8jE73sURVQONKXuLG/zuIojTy6WaT4FsbXojhsAY9GuN+HcXHY7mXI2sWWp
 11.1313 +Bpf/9en7D++xOYIamN106oaLiIYFpzJ8GpdL1ZWmJtgogB2ppV/3Qd00wIMHZnJ4lAP+7y0VFCDj
 11.1314 +iA1tiOeiAA+Ayn5sM7c4Jgxbz3UVjX7OTM57GydikFWDZlI7iHR6efn29NPpgFJMg/8duAJjaOtL
 11.1315 +h4uPaWEbdP03t7mlOPYBoda5lMb4uXPyaN1wxP021oBtub3PrlsPXjzEYPeGpf4s/62UgiUBQkU6
 11.1316 +2fgYQj04+PlDYUKHPoYRO9Vh7k4OOyv2nSN7joviiH5fmrs9gL+3hjHGBAigXaihiQyaYKql9K15
 11.1317 +3UNRB+gDfb0/HIK1Q692JONT1E6ixwF0KGub7Xb/vH0BNnpKVq/Pvjt/f3H++vL00/eOC4iu3IeP
 11.1318 +Ry/E2Q+fBZUjoAFjnyjGnfgKC1/AsLiHWcQ8h381pjfmdcVJSej19uJC7wys8TgD1reizYngOVfN
 11.1319 +WGico+Gsp32oy10Qo1QHSM65EaoOoXMlGC+t+cyCynUNLB1HmaKzWuvQS58HMueGaBs1AumDxi4p
 11.1320 +GARXNMErqlSuTFRY8o6TPkvTg5S20bYOIaUcVGd32tlvMdl8LzFHneFJ01kr+qvQxTW8jlSRJhDJ
 11.1321 +vQqtLOluWI3RMI5+aDdUGa8+Deh0h5F1Q571TizQar0KeW66/6hhtN9qwLBhsLcw70xSNQLV6GIt
 11.1322 +lQixEe8chPIOvtql12ugYMFwY6nCRTRMl8DsYwiuxSqBAAJ4cgXWF+MEgNBaCT8BfexkB2SOxQDh
 11.1323 +m/X88O+hJojf+pdfeppXZXr4D1FAFCS4ciXsIabb+C0EPpGMxNmHd6OQkaNKUPH3GkvAwSGhLJ8j
 11.1324 +7VQuwzu2k6GS6UKXM/j6AF9oP4Fet7qXsih1937XOEQJeKKG5DU8UYZ+IVYXWdhjnMqoBRqr2y1m
 11.1325 +eErM3fY2nwPxcSXTVBdEn7+9OAPfEQvuUYJ4n+cMhuN8CW7Z6lovPsXWAoUbuvC6RDYu0YWlTf15
 11.1326 +5DXrzcyiyFFvrw7ArhNlP7u9OqnOMk6Ui/YQp82wnJLzCLkZlsOsLHN3txnS2W1GdEfJYcaYXJZU
 11.1327 +NelzBnA0PY05MIKICYv6TbKZ9y6TrDJlcmkyA20KihfU6hhEBUmMJ9eI//KM0715qcyBF3hYbMtk
 11.1328 +uaowpQ6dIyq2x+Y/nH6+OH9P1esvXja+dw+LjikeGHPpwgnWpWHOA764tWbIW5NJH+fqVwgDdRD8
 11.1329 +ab/imogTHqDTj9OL+Kf9ik8cnTjxIM8A1FRdtIUEwwCnW5/0NBLBuNpoGD9u3VmDmQ+GMpJ4wEGX
 11.1330 +F7jz6/KjbdkyKJT9MS8fsVexKDQNh6azWwfV/ug5LgrcXJkP+xvB2z4JM58pdL3pvNlVceV+OrKI
 11.1331 +hx8Bo25rfwxTk9RpqqfjMNsubqHgVlvaXzInY+q0m2UoykDEodt55DJZvyrWzZkDvdrdDjDxjUbX
 11.1332 +SGKvQh/8kg20n+FhYondiVZMRzo7QaYA8xlSHxGpwZNCuwAKhEpOh47kjkdPX3hzdGzC/XPUugss
 11.1333 +5PegCHUBKB0syEvgRPjyG7uP/IrQQlV6LELHX8lkltvqJPxsVuhbPvfn2CsDlMpEsSvjbCmHDGts
 11.1334 +YH7pE3tHIpa0rccxV0mrWkJzN3iodzsYvCsW/bsnBrMWH3Ta3chtWxv51MEGvccPfAhlvAHtXtTV
 11.1335 +kNdq52YBNtdbsMMQkyS/hTvodQ96Ghb6Xb/17OHgh4ll3Etrr1pHW0L7QvuVsxICpkrRZoljhY2H
 11.1336 +6BrmxgaeNFZ4YJ/qihH7u+e8kFPl6sJlFFyo3gwHukEr1B/wyRU+uZdQZXRzsEK/m8tbmebgFkHE
 11.1337 +hYXvv9rC91FkUx29NUF/BoKX28ttP3r0pkHu2BTno+OkCljIKJPVEWLUm5C5B7kGH1z2X3TQEGc3
 11.1338 +5Me++fl8LN68/xH+fy0/QOSD59fG4h+AiXiTlxAB8hlKOtyOpf0Vh3Z5rfCQG0GjzQS+BwBdqkuP
 11.1339 +2rhxoc8c+IcNrBYTWGdZrvnyCUCR50jnihsbbirp4bc56tN1Fo0j17c0A/0SybD7AAQeGjjSLaNV
 11.1340 +tU5RnTupjGZNrwYX52/O3n88i6o75Hbzc+CkOvwqHZyR3sgtcdNqLOyTWY1Prh2/9nuZFj1urY4M
 11.1341 +zWEKjAxFCMFDYaNBvtsgthFAXGJ4L4rtPJ9F2BJ4n89vVRvwc0dOEHivHfaMIMIajvRWV+Ns42Og
 11.1342 +hvilrZcG0JD66DlRT0IonuJBIn4cDfot5VhQ/hn+PL3ZzN30tT4RQhNsY9rMeuh3t6pxxXTW8Fxm
 11.1343 +ItRO7EqYc4JpEqv1dOaeH/uQCX07BSg92o+Qi7hOKyEzEGEKxumaAND97pEvlhPmFrY4dA6K0inp
 11.1344 +Jt4qpyImVmKAow7opDNunFBmD2LlH+IbthB4Fk3UfKgVoBOiFOHkTldVz1Ysxxy0EAF7CgQ2Sfby
 11.1345 +RdghMg/KkeyscTVhnujYMUZLWen584Ph6Op5Y+wpezzzDnzOCrCDLqccgA4tnj59OhD/cb9/wqhE
 11.1346 +aZ7fgOMEsPvCVnFBr3d4FnpydrW6vrd5EwFLzlbyCh5cU5bbPq8zSiHu6UoLIu1fAyPEtQktP5r2
 11.1347 +LUvNybWSN4S5BW8saRPyU5bQHTSYApKocvVVPpgeMgJFLAm6IYzVLElCTifAemzzGs9qYTpQ84u8
 11.1348 +A45PEMwY3+JOFgfDK/QBqbDSco9F50QMCPCACp14NDrsSqeVAM/J5VajOTnPkqo5Z/DM3eTUh7or
 11.1349 +e7WM5isRb1AyzDxaxHCO/Xms2vjA+V4W9WKKfHblJgZbs+TX9+EOrA2Sli8WBlN4aBZplstyZowq
 11.1350 +rlgySyoHjGmHcLgz3ahDBigKelAagIYnwzC3Em3ffmHXxcX0A+33HpqRdJlPZW8p4iROnLWq3aKo
 11.1351 +GZ/SRZaQlm/NlxGM8p7Sz9of8MYSX+jkJxaZe5cpuMfd6kxfksB1Fs3NCQCHLuaxCtKyo6cjnNug
 11.1352 +LHxmWh1uNHcqODXxGEQTbrdJWdVxOtEH+SfouU3sBrjG0x6T2nsA0Pos4Pbn4BAf6pJu8B1MNQzS
 11.1353 +EysyTcn+iVjoJELkHj3yT+kUOfp6Lzw9jqnpZ3wRgKPBseWX5vDKQ1S+OULROX3gYjmm2qNw1K6o
 11.1354 +7LTCfQ5TIm+d7HYc8KghW7B8h31WbPFOHpjWk3lE/0LfkaPLFHBj6tGDp8mUBgv7Co/v76srATH+
 11.1355 +W4OgLBI5P3yiEDvG+Y9C1VAMddxA4REzDOnuCQL5ZWsnzykv5NrfXds3HaBff7UPrKuCewufac/E
 11.1356 +V8v6aJtbidxs2uDnwHrEK3C6UW/MzWFkrZb43CbqEDaI9qy5qVdpH5mB1w+f8p4JP2BHNMTBNHe4
 11.1357 +8rqPVha/faRqGgW/i0q6Vz+t0AnGUtFVzG9QmdXFsQ0V+TBfRmn2oVtAhJ/qpre0Psa7j4jRq5tw
 11.1358 +3/S5/7656xaBnbnZP+vM3T9C49JA993NL300YAddE+JBVbkWo8mfI7pjvbXbn6LSn4W9hZEzVcSD
 11.1359 +GrWxZsl1PHO/Y4HBIV/i6B6HClyQZtVbc+qcD2uzc5eTu9zMm6n43J6QpB3yuWYvNud0pc+Ea64m
 11.1360 +crlUkxhvhJqQD0j1AR3jbryKd3QbkIzV1jgDeOcCgDCsoiu53GJNWHXwM/lmSt5edw7XCxqaitCc
 11.1361 +qjaVzDm2154HgIs4pqf+JnPEZWmDVGI2RtVlUYKzNtD3F/K+b1+pXAPUxJfrWN0Y1E2Psb7ODofg
 11.1362 +YgNzhIozCewAetQBQvDJCudmF67znEzsO+CXZ81R0WRsGUJm9VqWcdXckuDvLyXiW2cEOjiHC+xE
 11.1363 +kI3YtTjFRSyx/OEghTGc/f6ldo4832/P+dCRVWkPZyvqoZMTjzl66ki54ebkzt6S5N7OMadrMSle
 11.1364 +5Ns1hG3WcJ+9GQKWwlz5Q4pQh3T8Vl9DwvfTcc4Jq+ocPgK5d4+t+NWNVmexw2DRcJ65iqF77wSe
 11.1365 +fCRD23edVIcLuhdH+czQjO/rDcssnd2EHY0tFU+4Ra/iaUYbNYEOFiLdE+j4xaaPDHQ8+A8MdPTl
 11.1366 +X2BNND5aH/SWn94TEbGacG/SahgB+kyASLhh0rqHydjDoVvMCeFKcjewl1GyznROiBgzgRzZvWKF
 11.1367 +QPCNWcqtfPNutDHj9kUivnTR4+8uPrw+vSBaTC5P3/zn6Xe0zY9ZvZbNenAkmOWHTO1Dr6zQjQr1
 11.1368 +1mzf4A22PVfTcW28htB539nW6oHQfw6ib0Hbisx9vatDp5682wkQ3z/tFtRdKrsXcsf50rXL7oZs
 11.1369 +q/4v0E+5WMv8cvbWzCOTU2ZxaBLG5n2T49My2kmB7Fo4p2yqq060U6ovM9uRnhnZ4j1aAUztIX/Z
 11.1370 +zJ6pxLb5I3ZU2leEU8UhnmIxNwGAFM6kcyEV3UXFoCr/LvISlF2MOxTsMI7tvZ7UjrOYyl5Yi7sU
 11.1371 +MxkZgnjHSAbd+bnCPpfpDioEASs8fd0SI2L0n877272yJ0pcHdKBtUNUNtf2F66ZdnJ/TnBHrLL3
 11.1372 +liiz5Y27AdB4UafuLpft0+lAzh8lTfOFUyENmu8I6NyIpwL2Rp+JFeJ0K0KIEvVWDhZdER31nUMO
 11.1373 +8mg3HewNrZ6Jw13HmdzjPEI8391w3joxpHu84B7qnh6qNodGHAuMdT+7zimJbwkyZ90FXVTiOR+4
 11.1374 +26Ovx4Svt1fPj23KFvkdX7vXYCDtB45hv2pOBuy9GsvpTbxSjqn+A4uNRm3w1wOHNRdid4DTqXPe
 11.1375 +EQSZ7TiGNPDe99dGmB7enb2DNqKW745hQmL4RI1oUk5luMbdPhl1JtuorC4MLnK/H0ZH+wEohNLv
 11.1376 +m+CHb2MB9fxMx4PTmu4TtA4nHg115IEKHXxe4B7G62uwa3eno2kP6k4l//agADdo855ebxBr9hq4
 11.1377 +lZfo2G0L2jNveGCH7edDfv39nz+gf7ckxnZ/sc+htq1e9h4sYScWi6hw87pFIfM4AusCCnNIahrr
 11.1378 +b42E4+H9howONzVTQ65Ah4/qsvCuUAosyImdaMtvjUHwf71Zz9M=
 11.1379 +""".decode("base64").decode("zlib")
 11.1380 +
 11.1381 +##file ez_setup.py
 11.1382 +EZ_SETUP_PY = """
 11.1383 +eJzNWmuP28YV/a5fwShYSIJlLt8PGXKRJi5gIEiDPAoU9lY7zxVrilRJyhu1yH/vmeFDJLVU2iIf
 11.1384 +ysDZXXJ45z7PuXekL784nqt9ns3m8/kf87wqq4IcjVJUp2OV52lpJFlZkTQlVYJFs/fSOOcn45lk
 11.1385 +lVHlxqkUw7XqaWEcCftEnsSirB+ax/Pa+PuprLCApScujGqflDOZpEK9Uu0hhByEwZNCsCovzsZz
 11.1386 +Uu2NpFobJOMG4Vy/oDZUa6v8aOSy3qmVv9nMZgYuWeQHQ/xzp+8byeGYF5XScnfRUq8b3lquriwr
 11.1387 +xD9OUMcgRnkULJEJMz6LooQT1N6XV9fqd6zi+XOW5oTPDklR5MXayAvtHZIZJK1EkZFKdIsulq71
 11.1388 +pgyreG6UuUHPRnk6HtNzkj3NlLHkeCzyY5Go1/OjCoL2w+Pj2ILHR3M2+0m5SfuV6Y2VRGEUJ/xe
 11.1389 +KlNYkRy1eU1UtZbHp4LwfhxNlQyzxnnluZx98+5PX/387U+7v7z74cf3f/7O2BpzywyYbc+7Rz//
 11.1390 +8K3yq3q0r6rj5v7+eD4mZp1cZl483TdJUd7flff4r9vtfm7cqV3Mxr8fNu7DbHbg/o6TikDgv3TE
 11.1391 +Fpc3XmNzar8+nh3TNcXT02JjLKLIcRiRsWU7vsUjL6JxHNBQOj4LRMDIYn1DitdKoWFMIuJZrvB8
 11.1392 +y5GURr4QrrRjzw5dn9EJKc5QFz/ww9CPeUQCHknmeVZokZhboRM6PI5vS+l08WAAibgdxNyhIghs
 11.1393 +SVyHBMJ3hCcjZ8oid6gLpa7NLMlCN45J4PphHIc+IzyWPrECO7oppdPFjUjEcJcHgnHHcbxQ2mEs
 11.1394 +Q06CIJaETUjxhroEjuX5xPEE94QtKAtDKSw3JsQTgQyFf1PKxS+MOsSOfOgRccKkpA63oY/lUpfa
 11.1395 +zHtZChvlC3WlQ33fjXmAuIYy9AgPY9uBIBJb0YRFbJwvsIcLDk8GIXe4I6WwPcuK3cCTDvEmIs1s
 11.1396 +a6gMgzscQn3uEsvxA88PEB9mu5FlkdCKrdtiOm38kONFxCimkRWGDvNj4rsk8lyX+JxPeqYW47di
 11.1397 +uPACwiL4Mg5ZFPt+6AhfRD7SUdCIhbfFBJ02kUAlESGtAA5ymAg824M0B0bC4RPRBqgMfeNQIghq
 11.1398 +2HY53kcZOZEIKfGpT6ARF7fFXCLFAzeWMbUgzGOe48Wh5XpcMEcwizmTkbKHvgk8FnvSpTIkIbLQ
 11.1399 +FSxyhUUdhDv0YurcFtP5hkoSO7ZlUY4wcdQEJAnOXQQ+8KwomBAzwhlpWYFHZUCIQ0NuQS141kNi
 11.1400 +W5EdMmcqUCOcCezAjh0hmOtLLxSImh0wHhDbgVQnnJIywhlpRwAogC+XSBXi+DGLIUXaPKRhJCfQ
 11.1401 +io1wRliCh14QOSyOIyppCE9HFrLXQsxDeyrY7jBIhAppB5JzGOb7vu1Fns1C4BePozjwp6SM0Ipa
 11.1402 +NLZdmzBCXceCM4BzofQ85gMoQlvelNJZhCSR2DPgnqTSRUVRGXsBs+AqoJ6YShhvaFGk0BrA7zqM
 11.1403 +05iFDmXSA3w5gXQiIqfQyh9aJEQseWRBHRQkMla6ApjuhwAMHtnBVKT9oUVEAqu4BKvYoWULAeeG
 11.1404 +ICefMhAeCaZQxh/FKOKuDAAIHmOERKHtIXG4G1LGuMt9PiElGFqEgonA8pFtB2CiKPJCByLAmL4X
 11.1405 +o7SngDMYsRvzAyL9kMK/6B5QDYEFQzzPRYH5ZAobgqFF1JERCX0HZA/YpS5I2kKoufAlWgnfnZAS
 11.1406 +juDOQoxkTDhzSWD7wrdtH2WIliICBE7mSzhiAhLJ2PfAAhxYbkkahEza0kEY8MiZqoBwaJEHjiXA
 11.1407 +W4mWAQXouZ5t25KLyLXxL5zSJRp1Q5bqhZwYHok5+EOlIAA8ci3VWFm3pXQWMUrcCNiAnsOLXGap
 11.1408 +nEW2wdkMzDJJA9HQIjt07BAgh0DHnNm+5ccW8SPqCtR57E9FOh5aBN2ZZ6GZsZWHqRcHwmOSCiuC
 11.1409 +rcyainQ8QgYkGRo7cKsbRTwAOhEhrADgxQLXm+rvGimdRVIgtK7wiR1S22EIE/M9m4bgXjC/mGKS
 11.1410 +eMhHjKBsbKlQkziCA5js2AWzhdSPHfQ4kPLrrDcRYLwpZ1Vx3tQD156U+zSh7byF3n0mfmECo8Z7
 11.1411 +feedGomatXjYXzfjQhq7zyRN0O2LHW4todMuwzy4NtQAsNpoAxJptPfVzNiOB/VDdfEEs0WFcUGJ
 11.1412 +0C+ae/FLfRfzXbsMcpqVX2w7KR9a0Q8XeerC3IVp8O1bNZ2UFRcF5rrlYIW65sqkxoJmPrzDFEYw
 11.1413 +hvEvDGP5fV6WCU174x9GOvx9+MNqfiXsrjNz8Gg1+EvpI35JqqVT3y8Q3CLT7qodOhoO9aJmvNqO
 11.1414 +hrl1p9aOklJsewPdGpPiDqPqNi9NdirwW51M3QtcpOS8tf1ZEySMjV+dqvwAPzBMl2eMohm/78zu
 11.1415 +nRSouf5APiGWGJ4/w1VEOQjOU6YdSbWvx/nHRulHo9znp5SraZbUvu5Layfz7HSgojCqPakMDMKd
 11.1416 +YC1LTcCZ8q4hMfV2Sp0yrl8RxuPAEY+GGmmXz/uE7dvdBbRWRxO1PGNxv1iZULL20qPaUsnpHWPs
 11.1417 +RTE4IHlOMHPTSyYIvkZG1gmuVc5y+CMtBOHni/rY473sqafdrrdrzia0mKrRUkujQqvSOESfWLA8
 11.1418 +42Xtm1aNI0GiKKfCI6qskipB6LKn3nlGHfHG/jwT+jyhPhvhtV5wap4qH754PqK0bA4bRCNMn+UU
 11.1419 ++Qk7iVqVus6IcRBlSZ5EfcBxKbrHR50vBUlKYfx4LitxePeL8ldWByIzSIV79ckGoQpalPEqBZUx
 11.1420 +9amH2Wao/vlMyl2NQrB/ayyOn552hSjzU8FEuVAIo7Y/5PyUilKdkvQAdPy4rglUHUceNG5bri5I
 11.1421 +olJueymaXl02HhuVYFt261GhXTCgLRITnhVFtbTWapMeyDVA3e30pn+6Q9tjvl0TmJ0G5q2SUQcI
 11.1422 +wD6WNXCQfvgCwncvtYDUd0jz6HqHgWizSa7l/KLx2+38VeOq1ZtGdl+FoYC/1Cu/zjOZJqyCazZ9
 11.1423 +9O9H/r9F+/lP+0v2T+T78u32rlx1tdzWsD7K/JgNAX/OSLaoVEl1JQLMUMd3ukaa4zpVLacsQyqb
 11.1424 +xvepQIa0y6/kqRpSpQwAErCl1VAmRQlHnEpVDgtIOLehN17/3FN+YY7kfcw+ZsuvT0UBaYDzWsBd
 11.1425 +MeKtFVjrksvCJMVT+cF6uM1ZOn5pKYYxQKIPw7nuV9qHUZ0+qFe+hLUayfNPA1Ev5eB01nyToCQS
 11.1426 +elIM/l1e/SkHL9zO55ppXyrr35tuVfGjPAc8+80LpKrLmFxIwUhzVrckGj5rG5KqPiHWLcb/KcnW
 11.1427 +EK0+A2hJ9rc4Vt1Tu14TbI37jxfOnODFvGbDlgwVqbDqRNKLEQ3JDImk/YihANdQB9m6RwqldZ61
 11.1428 +/erW6IHZ67sSvfddqVrveb9wRkfgda5Cbp87lM+MV8MWsSSfBbTfoiWvSeHveZItWwppl9biyoIp
 11.1429 +cbpP/g5s3rbWCqra11GkZVUua7GrjSqwrz7niUqgoyCKL1t1yq4+BniuLp2KHIKUN8rWS2n+NFil
 11.1430 +mnEVl+G76sJK85kU2VL5+fXvd9WfkDTA2iB5+VKW3+mUUJ+cLMVnkak/YM4Rys72Ij2qvu99nW29
 11.1431 +3qNLFTQnKv/VZztL5YoZKGFtAF1m6tYB5ZwJOBKvoA5V5wuEFs8KjwnG2bLUb/c5QCO4OWu2BHQ3
 11.1432 +Pc5lR6jM22w2Z7MlQExslIe1mANhe9Vu8VzUxLRHeKFE9ZwXn5pN18axZpecVqT5XE4hhUaJu3I2
 11.1433 +UygCDzDdtesFkHypxKZyCtGwVd8Ac/V7RhFJsb5KmR7oXjVUOsvWqpquXkNHoZO1StRk2TROqRDH
 11.1434 +N/WP5aj3GmZnC8OaF8u53mLEe7rkGnww8TM/imx5texL4wc0/ffPRVIBfBBj+Fe328DwT2v10eCz
 11.1435 +ip5qF1ihyhDQyPKiOOnkSMVImI57Pz1UF14Jvb7FxPZqPmabGsJhgKkGkuVqqHGNItqaGivW82c6
 11.1436 +hzvxwNR21GN49xKGQTUUbsYQgA02eheW5qVYrq4goqw2Wmj/ecNmLWhBwVT90sLW7D+5FH8fkOlL
 11.1437 +NCyf11OMfeHc97c+NNUc+w6tVbOqJYiXmunRh9G3Oul6eOiw+kriZc3tAUNP6tZ1SzYcIwZThI6Z
 11.1438 +Ko3e7MDywwGGmoMesj3OIc1A1l5NjLSLU3CB9vPqlTpteVjpNH0Wi0KntTAUjf9mqihLlZ9HXKXU
 11.1439 +vuYQLDplmAA/LTuzhg1n0m/czd2u8dZuZ2wxElqmZdqL/3pE+CsAXoOrmotpmacCtToxGrdNP8ik
 11.1440 +buyvGvpCHPLPGm91JOrvPOgJGMxRAXrT38DdUac+2ZI3RfWPYbPSm7z63c71MPgfDHT4eaP/Hk1t
 11.1441 +m+ls/59T8laZdYJ/U8pVNr9Ud225PQxndu1sa4XEh1WK/RE4pjNFPXk5Q9Uuv5MDOvW15jemsDrN
 11.1442 +5z9etUXzdYsoc4DgkyaiQh3/IgnRJF0Sev6CvMXyB7RT8/bbOebxPJw+5/X3bq6/mmKuFs2x5rHj
 11.1443 +p3aEKS/w/LN+aqgSoackrV7X58QQ+aSGu7NC5H4WF838o3qt9ly5E3txiO65L921+lOtWF66ai2k
 11.1444 +5UJNmouCLi7PumNm9e5Dc0QtW1J98ZhadmRXj4A1RX+Yqz/uig3+rYEVGB+aTrNuyNqNTJDvoVyu
 11.1445 +HrqXzRIWd9R5VEPFfF5PCjVJ9x2DCGCErNqJQX+faNveNZ9EVRetur/sT+c73THsdk3Wdy5pZKwN
 11.1446 +7ZY3TUvUOuDN2NgDqTANbqGnWQpSsP1y/jHrfx/oY7b88LdfH16tfp3r9mTVH2P02z0segGxQeT6
 11.1447 +G1mpIRQKfDG/LtIWEWtV8f8PGy3Y1K330l49YAzTjnyln9YPMbri0ebhZfMXz01OyKY96lTvOWAG
 11.1448 +M1o/breL3U4V7G636D4FSZVEqKlr+K2j6bD9+4P9gHdev4az6lLp0VevdrrlzubhJV7UGHGRqRbV
 11.1449 +178BYnMUkw==
 11.1450 +""".decode("base64").decode("zlib")
 11.1451 +
 11.1452 +##file distribute_setup.py
 11.1453 +DISTRIBUTE_SETUP_PY = """
 11.1454 +eJztG2tz2zbyu34FTh4PqYSi7TT3GM+pM2nj9DzNJZnYaT8kHhoiIYk1X+XDsvrrb3cBkCAJyc61
 11.1455 +dzM3c7qrIxGLxWLfuwCP/lTs6k2eTabT6Xd5Xld1yQsWxfBvvGxqweKsqnmS8DoGoMnliu3yhm15
 11.1456 +VrM6Z00lWCXqpqjzPKkAFkdLVvDwjq+FU8lBv9h57JemqgEgTJpIsHoTV5NVnCB6+AFIeCpg1VKE
 11.1457 +dV7u2DauNyyuPcaziPEoogm4IMLWecHylVxJ4z8/n0wYfFZlnhrUBzTO4rTIyxqpDTpqCb7/yJ2N
 11.1458 +dliKXxsgi3FWFSKMV3HI7kVZATOQhm6qh98BKsq3WZLzaJLGZZmXHstL4hLPGE9qUWYceKqBuh17
 11.1459 +tGgIUFHOqpwtd6xqiiLZxdl6gpvmRVHmRRnj9LxAYRA/bm+HO7i99SeTa2QX8TekhRGjYGUD3yvc
 11.1460 +SljGBW1PSZeoLNYlj0x5+qgUE8W8vNLfql37tY5Tob+vspTX4aYdEmmBFLS/eUk/Wwk1dYwqI0eT
 11.1461 +fD2Z1OXuvJNiFaP2yeFPVxcfg6vL64uJeAgFkH5Jzy+QxXJKC8EW7F2eCQObJrtZAgtDUVVSVSKx
 11.1462 +YoFU/iBMI/cZL9fVTE7BD/4EZC5s1xcPImxqvkyEN2PPaaiFK4FfZWag90PgqEvY2GLBTid7iT4C
 11.1463 +RQfmg2hAihFbgRQkQeyF/80fSuQR+7XJa1AmfNykIquB9StYPgNd7MDgEWIqwNyBmBTJdwDmmxdO
 11.1464 +t6QmCxEK3OasP6bwOPA/MG4YHw8bbHOmx9XUYccIOIJTMMMhtenPHQXEOviiVqxuhtLJK78qOFid
 11.1465 +C98+BD+/urz22IBp7Jkps9cXb159ensd/HTx8ery/TtYb3rq/8U/ezlthz59fIuPN3VdnJ+cFLsi
 11.1466 +9qWo/LxcnygnWJ1U4KhCcRKddH7pZDq5urj+9OH6/fu3V8GbVz9evB4sFJ6dTScm0Icffwgu3715
 11.1467 +j+PT6ZfJP0XNI17z+U/SHZ2zM/908g786LlhwpN29LiaXDVpysEq2AN8Jv/IUzEvgEL6PXnVAOWl
 11.1468 ++X0uUh4n8snbOBRZpUBfC+lACC8+AIJAgvt2NJlMSI2Vr3HBEyzh35m2AfEAMSck5ST3LodpsE4L
 11.1469 +cJGwZe1N/PQuwu/gqXEc3Ia/5WXmOhcdEtCB48rx1GQJmCdRsI0AEYh/LepwGykMrZcgKLDdDcxx
 11.1470 +zakExYkI6cL8vBBZu4sWJlD7UFvsTfbDJK8EhpfOINe5IhY33QaCFgD8idw6EFXweuP/AvCKMA8f
 11.1471 +JqBNBq2fT29m441ILN1Ax7B3+ZZt8/LO5JiGNqhUQsMwNMZx2Q6y161uOzPTnWR53XNgjo7YsJyj
 11.1472 +kDsDD9ItcAU6CqEf8G/BZbFtmcPXqCm1rpjJiW8sPMAiBEEL9LwsBRcNWs/4Mr8XetIqzgCPTRWk
 11.1473 +5sy0Ei+bGB6I9dqF/zytrPAlD5B1/9fp/wGdJhlSLMwYSNGC6LsWwlBshO0EIeXdcWqfjs9/xb9L
 11.1474 +9P2oNvRojr/gT2kgeqIayh3IqKa1qxRVk9R95YGlJLCyQc1x8QBLVzTcrVLyGFLUy/eUmrjO93mT
 11.1475 +RDSLOCVtZ71GW1FWEAHRKod1VTrstVltsOSV0BszHkci4Tu1KrJyqAYK3unC5Py4mhe748iH/yPv
 11.1476 +rIkEfI5ZRwUGdfUDIs4qBx2yPDy7mT2dPcosgOB2L0bGvWf/+2gdfPZwqdOrRxwOAVLOhuSDPxRl
 11.1477 +7Z56rJO/yn77dY+R5C911acDdEDp94JMQ8p7UGOoHS8GKdKAAwsjTbJyQ+5ggSrelBYmLM7+7IFw
 11.1478 +ghW/E4vrshGtd005mXjVQGG2peSZdJQvqzxBQ0VeTLolDE0DEPzXNbm35VUguSTQmzrF3ToAk6Ks
 11.1479 +raIkFvmb5lGTiAorpS/tbpyOK0PAsSfu/TBE01uvDyCVc8MrXtel2wMEQwkiI+hak3CcrThoz8Jp
 11.1480 +qF8BD0GUc+hqlxZiX1nTzpS59+/xFvuZ12OGr8p0d9qx5NvF9LlabWYha7iLPj6VNn+fZ6skDuv+
 11.1481 +0gK0RNYOIXkTdwb+ZCg4U6vGvMfpEOogI/G3JRS67ghiek2enbYVmT0Hozfjfrs4hoIFan0UNL+H
 11.1482 +dJ0qmS/ZdIwPWykhz5wa601l6oB5u8E2AfVXVFsAvpVNhtHFZx8SAeKx4tOtA87SvERSQ0zRNKGr
 11.1483 +uKxqD0wT0FinO4B4p10Om38y9uX4Fvgv2ZfM/b4pS1gl2UnE7LicAfKe/xc+VnGYOYxVWQotrt0X
 11.1484 +/TGRVBb7AA1kA5Mz7PvzwE/c4BSMzNTYye/2FbNfYw1PiiH7LMaq1202A6u+y+s3eZNFv9toHyXT
 11.1485 +RuIo1TnkroKwFLwWQ28V4ObIAtssCsPVgSj9e2MWfSyBS8Ur5YWhHn7dtfhac6W42jYSwfaSPKTS
 11.1486 +hdqcivFxLTt3GVTyMim8VbTfsmpDmdkS25H3PIl72LXlZU26FCVYNCdTbr0C4cL2HyW91DFp+5Cg
 11.1487 +BTRFsNseP24Z9jhc8BHhRq8uskiGTezRcuacODOf3Uqe3OKKvdwf/IsohU4h236XXkVEvtwjcbCd
 11.1488 +rvZAHdYwzyLqdRYcA/1SrNDdYFszrBuedB1X2l+NlVTtazH8RxKGXiwioTYlVMFLikIC29yq31wm
 11.1489 +WFZNDGu0xkoDxQvb3Hr9W4DqgK2fXnLsYxm2/g0doJK+bGqXvVwVBcmet1hk/sfvBbB0TwquQVV2
 11.1490 +WYaIDvalWquGtQ7yZol2do48f3Wfx6jVBVpu1JLTZTijkN4WL631kI+vph5uqe+yJVGKS+5o+Ih9
 11.1491 +FDw6odjKMMBAcgaksyWY3J2HHfYtKiFGQ+laQJPDvCzBXZD1DZDBbkmrtb3EeNZRC4LXKqw/2JTD
 11.1492 +BKEMQR94NMioJBuJaMksj023y+kISKUFiKwbG/lMJQlYy5JiAAG6RB/AA35LuINFTfiuc0oShr0k
 11.1493 +ZAlKxqoSBHddgfda5g/uqslC9GbKCdKwOU7tVY89e3a3nR3IimXzv6tP1HRtGK+1Z7mSzw8lzENY
 11.1494 +zJmhkLYly0jtfZzLVtKozW5+Cl5Vo4HhSj6uA4IeP28XeQKOFhYw7Z9X4LELlS5YJD0hsekmvOEA
 11.1495 +8OR8fjhvvwyV7miN6In+UW1Wy4zpPswgqwisSZ0d0lR6U2+VohNVAfoGF83AA3cBHiCru5D/M8U2
 11.1496 +Ht41BXmLlUysRSZ3BJFdByTyluDbAoVDewREPDO9BnBjDLvQS3ccOgIfh9N2mnmWntarPoTZLlW7
 11.1497 +7rShm/UBobEU8PUEyCYxNgTkDIhimc+ZmwBD2zq2YKncmuadPRNc2fwQ6fbEEAOsZ3oXY0T7JjxU
 11.1498 +1myzCk27uCHvDR4rVKM9SwSZ2OrIjE8hyjr++7ev/eMKj7TwdNTHP6PO7kdEJ4MbBpJc9hQliRqn
 11.1499 +avJibYs/Xduo2oB+2BKb5veQLINpBGaH3C0SHooNKLvQnepBGI8r7DWOwfrUf8ruIBD2mu+QeKk9
 11.1500 +GHP369cK646e/8F0VF8IMBrBdlKAanXa7Kt/XZzrmf2YZ9gxnGNxMHT3evGRt1yC9O9Mtqz65VHH
 11.1501 +ga5DSim8eWhurjtgwGSkBSAn1AKRCHkkmzc1Jr3oPbZ819mcrnOGCZvBHo9J1VfkDySq5huc6Jy5
 11.1502 +shwgO+jBSlfViyCjSdIfqhkes5xXqs624ujIt3fcAFPgQxflsT41VmU6AsxblojaqRgqfut8h/xs
 11.1503 +FU3xG3XNNVt43qD5p1r4eBMBvxrc0xgOyUPB9I7Dhn1mBTKodk1vM8Iyjuk2vQSnKhv3wFZNrOLE
 11.1504 +nja6c9Vd5ImMNoEz2EnfH+/zNUPvvA9O+2q+gnS6PSLG9RVTjACGIO2NlbZt3dpIx3ssVwADnoqB
 11.1505 +/09TICLIl7+43YGjr3vdBZSEUHfJyPZYl6Hn3CTdXzOl53JNckElLcXUY27YImzNHN1YGLsg4tTu
 11.1506 +nngEJqcilfvkUxNZEXYbVZHYsCJ1aFN1fhAW+NLTOXffVQFP0vYVTm9Aysj/aV6OHaDV80jwA35n
 11.1507 +6MO/R/nLSD6a1aVErYM8nBZZ3ScB7E+RJKvqNifazypDRj5McIZJyWAr9cbgaLcV9fixrfTIMDpl
 11.1508 +Q3k9vr/HTGzoaR4Bn/Xy+TbodTndkQolEIHCO1SlGH/Z8uu9Cioz4IsffpijCDGEgDjl969Q0HiU
 11.1509 +wh6Ms/tiwlPjquHbu9i6J9kH4tO7lm/9RwdZMXvEtB/l3H/FpgxW9MoOpS32ykMNav2Sfco2oo2i
 11.1510 +2Xeyj7k3nFlO5hRmatYGRSlW8YOrPX0XXNogR6FBHUpC/X1vnPcbe8Pf6kKdBvysv0CUjMSDETaf
 11.1511 +n53ftFkUDXr62p3ImlSUXF7IM3snCCpvrMp8az4vYa/yHoTcxDBBh00ADh/WLOsK28yoxAsMIxKP
 11.1512 +pTFT54WSDM0skrh2HVxn4cw+zwencwYLNPvMxRSu4RGRpApLQ0mF9cA1Ac2Utwi/lfyx95B65Faf
 11.1513 +CfK5hcqvpbSjEZjbVKJ06GihuxyrjgqxjWvt2NhWaWdbDENq5EhVh8p+FXI6UDTOHfX1SJvt7j0Y
 11.1514 +P9ShOmJb4YBFhUCCJcgb2S0opHGrJ8qFZEolRIrnDObx6LhLQj+3aC79UkHdO0I2jDdkxCFMTGHy
 11.1515 +tvIxa+uf6fsf5XkvJtvgFUtwRr3yxJ64D7SFYj5iWJAbVx5Xce56V4gR37BVaRwkvfpw+QcTPuuK
 11.1516 +wCFCUMi+Mpq3ucx3C8ySRBbmdtEcsUjUQt2aw+CNJ/FtBERNjYY5bHsMtxiS5+uhoT6b7zwYRY9c
 11.1517 +GrRbt0Msqyhe0KGC9IWokOQL4wcitijz+zgSkXz9IV4pePNFi8poPkTqwl3qdYcauuNoVhz9wGGj
 11.1518 +zC4FhQ0Y6g0JBkTyLMR2D3SsrfJGONCygfpjf43SS8PAKqUcK/O6ntqSZRO+yCIVNOjO2J5NZXN5
 11.1519 +m68TXo8OtO/9fTSrVPVkRRrgsHlYS1PFuPC5n6R9GZOFlMMJlCLR3Zd/os71uxFfkYPuTUIPNJ8H
 11.1520 +vOnPG7efTd1oj+7QrOl8Wbo/Ous1/H0mhqLtZ/+/V54Deum0MxNGwzzhTRZuuhSuezKMlB/VSG/P
 11.1521 +GNrYhmNrC99IkhBU8Os3WiRUERcs5eUdnuXnjNMBLO8mLJvWeNpU7/ybG0wXPjvz0LyRTdkZXrFJ
 11.1522 +xFy1AObigd5fgpx5nvIMYnfk3BghTmM8vWn7Adg0MxPMz/03Lm7Y83baROOg+znWl2la7hmXkiuR
 11.1523 +rGTjfDH1px5LBV4cqBYYU7qTGXWRmg6CFYQ8ZqRLACVwW7IWf4byipG+R6z3111oQJ+M73rl2wyr
 11.1524 +6jSP8K0w6f+x2U8AhSjTuKroNa3uyE4jiUEJqeEFMo8qn93iBpz2Ygi+ogVIV4IIGV2jBkIVB+Ar
 11.1525 +TFY7ctATy9SUJ0REiq/c0WUR4CeRTA1AjQd77EqLQWOXO7YWtcLlzvo3KFRCFubFzvwNhRhk/OpG
 11.1526 +oGSovE6uARTju2uDJgdAH27avECLZZQP6AGMzclq0lYfsBL5Q4goCqRXOath1f8e+KUjTViPHnWh
 11.1527 +peIrgVIVg2P9DtLnBVSgkavW6LsyTdeCuOXjn4OAeJ8M+zYvX/6NcpcwTkF8VDQBfad/PT01krFk
 11.1528 +5SvRa5xS+duc4qNAaxWsQu6bJJuGb/b02N+Z+8JjLw0OoY3hfFG6gOHMQzwvZtZyIUwLgvGxSSAB
 11.1529 +/e50asg2ROpKzHaAUlLv2o4eRojuxG6hFdDH435QX6TZQQKcmccUNnl1WDMIMje66AG4WgturRZV
 11.1530 +l8SBqdyQeQOlM8Z7RNI5oLWtoQXeZ9Do7JykHG6AuE7GCu9sDNjQ+eITAMMN7OwAoCoQTIv9N269
 11.1531 +ShXFyQlwP4Eq+GxcAdON4kF1bbunQMiCaLl2QQmnyrXgm2x44UnocJDymGrue4/tueTXBYLLQ6+7
 11.1532 +kgpc8GqnoLTzO3z9X8X44cttQFxM918weQqoIg8CJDUI1LuURHcbNc/Ob2aTfwH3muVf
 11.1533 +""".decode("base64").decode("zlib")
 11.1534 +
 11.1535 +##file activate.sh
 11.1536 +ACTIVATE_SH = """
 11.1537 +eJytVU1v4jAQPW9+xTT0ANVS1GsrDlRFAqmFqmG72m0rY5IJsRRslDiktNr/vuMQ8tFQpNU2B4I9
 11.1538 +H36eeW/SglkgYvBFiLBKYg0LhCRGD1KhA7BjlUQuwkLIHne12HCNNpz5kVrBgsfBmdWCrUrA5VIq
 11.1539 +DVEiQWjwRISuDreW5eE+CtodeLeAnhZEGKMGFXqAciMiJVcoNWx4JPgixDjzEj48QVeCfcqmtzfs
 11.1540 +cfww+zG4ZfeD2ciGF7gCHaDMPM1jtvuHXAsPfF2rSGeOxV4iDY5GUGb3xVEYv2aj6WQ0vRseAlMY
 11.1541 +G5DKsAawwnQUXt2LQOYlzZoYByqhonqoqfxZf4BLD97i4DukgXADCPgGgdOLTK5arYxZB1xnrc9T
 11.1542 +EQFcHoZEAa1gSQioo/TPV5FZrDlxJA+NzwF+Ek1UonOzFnKZp6k5mgLBqSkuuAGXS4whJb5xz/xs
 11.1543 +wXCHjiVerAk5eh9Kfz1wqOldtVv9dkbscfjgjKeTA8XPrtaNauX5rInOxaHuOReNtpFjo1/OxdFG
 11.1544 +5eY9hJ3L3jqcPJbATggXAemDLZX0MNZRYjSDH7C1wMHQh73DyYfTu8a0F9v+6D8W6XNnF1GEIXW/
 11.1545 +JrSKPOtnW1YFat9mrLJkzLbyIlTvYzV0RGXcaTBfVLx7jF2PJ2wyuBsydpm7VSVa4C4Zb6pFO2TR
 11.1546 +huypCEPwuQjNftUrNl6GsYZzuFrrLdC9iJjQ3omAPBbcI2lsU77tUD43kw1NPZhTrnZWzuQKLomx
 11.1547 +Rd4OXM1ByExVVkmoTwfBJ7Lt10Iq1Kgo23Bmd8Ib1KrGbsbO4Pp2yO4fpnf3s6MnZiwuiJuls1/L
 11.1548 +Pu4yUCvhpA+vZaJvWWDTr0yFYYyVnHMqCEq+QniuYX225xmnzRENjbXACF3wkCYNVZ1mBwxoR9Iw
 11.1549 +WAo3/36oSOTfgjwEEQKt15e9Xpqm52+oaXxszmnE9GLl65RH2OMmS6+u5acKxDmlPgj2eT5/gQOX
 11.1550 +LLK0j1y0Uwbmn438VZkVpqlfNKa/YET/53j+99G8H8tUhr9ZSXs2
 11.1551 +""".decode("base64").decode("zlib")
 11.1552 +
 11.1553 +##file activate.fish
 11.1554 +ACTIVATE_FISH = """
 11.1555 +eJydVm1v4jgQ/s6vmA1wBxUE7X2stJVYlVWR2lK13d6d9laRk0yIr8HmbIe0++tvnIQQB9pbXT5A
 11.1556 +Ys/LM55nZtyHx5RrSHiGsMm1gRAh1xhDwU0Kng8hFzMWGb5jBv2E69SDs0TJDdj3MxilxmzPZzP7
 11.1557 +pVPMMl+q9bjXh1eZQ8SEkAZULoAbiLnCyGSvvV6SC7IoBcS4Nw0wjcFbvJDcjiuTswzFDpiIQaHJ
 11.1558 +lQAjQUi1YRmUboC2uZJig8J4PaCnT5IaDcgsbm/CjinOwgx1KcUTMEhhTgV4g2B1fRk8Le8fv86v
 11.1559 +g7v545UHpZB9rKnp+gXsMhxLunIIpwVQxP/l9c/Hq9Xt1epm4R27bva6AJqN92G4YhbMG2i+LB+u
 11.1560 +grv71c3dY7B6WtzfLy9bePbp0taDTXSwJQJszUnnp0y57mvpPcrF7ZODyhswtd59+/jdgw+fwBNS
 11.1561 +xLSscksUPIDqwwNmCez3PpxGeyBYg6HE0YdcWBxcKczYzuVJi5Wu915vn5oWePCCoPUZBN5B7IgV
 11.1562 +MCi54ZDLG7TUZ0HweXkb3M5vFmSpFm/gthhBx0UrveoPpv9AJ9unIbQYdUoe21bKg2q48sPFGVwu
 11.1563 +H+afrxd1qvclaNlRFyh1EQ2sSccEuNAGWQwysfVpz1tPajUqbqJUnEcIJkWo6OXDaodK8ZiLdbmM
 11.1564 +L1wb+9H0D+pcyPSrX5u5kgWSygRYXCnJUi/KKcuU4cqsAyTKZBiissLc7NFwizvjxtieKBVCIdWz
 11.1565 +fzilzPaYyljZN0cGN1v7NnaIPNCGmVy3GKuJaQ6iVjE1Qfm+36hglErwmnAD8hu0dDy4uICBA8ZV
 11.1566 +pQr/q/+O0KFW2kjelu9Dgb9SDBsWV4F4x5CswgS0zBVlk5tDMP5bVtUGpslbm81Lu2sdKq7uNMGh
 11.1567 +MVQ4fy9xhogC1lS5guhISa0DlBWv0O8odT6/LP+4WZzDV6FzIkEqC0uolGZSZoMnlpxplmD2euaT
 11.1568 +O4hkTpPnbztDccey0bhjDaBIqaWQa0uwEtQEwtyU56i4fq54F9IE3ORR6mKriODM4XOYZwaVYLYz
 11.1569 +7SPbKkz4i7VkB6/Ot1upDE3znNqYKpM8raa0Bx8vfvntJ32UENsM4aI6gJL+jJwhxhh3jVIDOcpi
 11.1570 +m0r2hmEtS8XXXNBk71QCDXTBNhhPiHX2LtHkrVIlhoEshH/EZgdq53Eirqs5iFKMnkOmqZTtr3Xq
 11.1571 +djvPTWZT4S3NT5aVLgurMPUWI07BRVYqkQrmtCKohNY8qu9EdACoT6ki0a66XxVF4f9AQ3W38yO5
 11.1572 +mWmZmIIpnDFrbXakvKWeZhLwhvrbUH8fahhqD0YUcBDJjEBMQwiznE4y5QbHrbhHBOnUAYzb2tVN
 11.1573 +jJa65e+eE2Ya30E2GurxUP8ssA6e/wOnvo3V78d3vTcvMB3n7l3iX1JXWqk=
 11.1574 +""".decode("base64").decode("zlib")
 11.1575 +
 11.1576 +##file activate.csh
 11.1577 +ACTIVATE_CSH = """
 11.1578 +eJx9U11vmzAUffevOCVRu+UB9pws29Kl0iq1aVWllaZlcgxciiViItsQdb9+xiQp+dh4QOB7Pu49
 11.1579 +XHqY59IgkwVhVRmLmFAZSrGRNkdgykonhFiqSCRW1sJSmJg8wCDT5QrucRCyHn6WFRKhVGmhKwVp
 11.1580 +kUpNiS3emup3TY6XIn7DVNQyJUwlrgthJD6n/iCNv72uhCzCpFx9CRkThRQGKe08cWXJ9db/yh/u
 11.1581 +pvzl9mn+PLnjj5P5D1yM8QmXlzBkSdXwZ0H/BBc0mEo5FE5qI2jKhclHOOvy9HD/OO/6YO1mX9vx
 11.1582 +sY0H/tPIV0dtqel0V7iZvWyNg8XFcBA0ToEqVeqOdNUEQFvN41SumAv32VtJrakQNSmLWmgp4oJM
 11.1583 +yDoBHgoydtoEAs47r5wHHnUal5vbJ8oOI+9wI86vb2d8Nrm/4Xy4RZ8R85E4uTZPB5EZPnTaaAGu
 11.1584 +E59J8BE2J8XgrkbLeXMlVoQxznEYFYY8uFFdxsKQRx90Giwx9vSueHP1YNaUSFG4vTaErNSYuBOF
 11.1585 +lXiVyXa9Sy3JdClEyK1dD6Nos9mEf8iKlOpmqSNTZnYjNEWiUYn2pKNB3ttcLJ3HmYYXy6Un76f7
 11.1586 +r8rRsC1TpTJj7f19m5sUf/V3Ir+x/yjtLu8KjLX/CmN/AcVGUUo=
 11.1587 +""".decode("base64").decode("zlib")
 11.1588 +
 11.1589 +##file activate.bat
 11.1590 +ACTIVATE_BAT = """
 11.1591 +eJyFUkEKgzAQvAfyhz0YaL9QEWpRqlSjWGspFPZQTevFHOr/adQaU1GaUzI7Mzu7ZF89XhKkEJS8
 11.1592 +qxaKMMsvboQ+LxxE44VICSW1gEa2UFaibqoS0iyJ0xw2lIA6nX5AHCu1jpRsv5KRjknkac9VLVug
 11.1593 +sX9mtzxIeJDE/mg4OGp47qoLo3NHX2jsMB3AiDht5hryAUOEifoTdCXbSh7V0My2NMq/Xbh5MEjU
 11.1594 +ZT63gpgNT9lKOJ/CtHsvT99re3pX303kydn4HeyOeAg5cjf2EW1D6HOPkg9NGKhu
 11.1595 +""".decode("base64").decode("zlib")
 11.1596 +
 11.1597 +##file deactivate.bat
 11.1598 +DEACTIVATE_BAT = """
 11.1599 +eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q
 11.1600 +FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL
 11.1601 +i2dASrm4rFz9XLgAwJNbyQ==
 11.1602 +""".decode("base64").decode("zlib")
 11.1603 +
 11.1604 +##file distutils-init.py
 11.1605 +DISTUTILS_INIT = """
 11.1606 +eJytV92L4zYQf9dfMU0ottuse/TeFkKh3MvC0Ydy0IdlMVpbTtR1JCMpm+T++s5Y/pBs53oPZ1hQ
 11.1607 +pPnSb34zo5WnVhsH2jLpV/Y2Li/cKKkOFoYN3Za6ErAdFtKC0g44vEvjzrwR6h1Oujo3YgdWw0VA
 11.1608 +yRWcLUo6cBpqqSpwRwHWVY18ZRB9W3jq3HDlfoIvqK7NG2gF7a297VANvZ3O1sGrQI/eDe5yB0ZY
 11.1609 +WQkLUpHxhVX09NDe3FGr31BL1lJUD9f8ln+FShpROm1ujOFS8ZOAPUKRt9wd836Hjqw7O9nYgvYD
 11.1610 +iX+1VOlMPPXQ5EVRy0YURbaDZDSQZEzWo7rS5kSLNHaQwX4RRLrQGe1nj92Fh1zltEhHDDZfEO0g
 11.1611 +O6MraHn5xg8IpYOfLfC2FdxYShLC64EES4A0uuROYhq49Zs368RpMvTHJmOiscKHUXRXKIpcKiuM
 11.1612 +Sz/sYHa7TkxcRYkkEhN8HZaxKCJXFFJJh+baW5JluRG8SjM20JHEA9qWWtXywBjbbvF2rjzC61k2
 11.1613 +VSGuDibTUGlhVeLgTekLHPEP73wQrrscUsUGrPCGjkTCC1JXXyw8EJWP3FSUZY8IiSCCRp97dnfO
 11.1614 +RUUx5a0RtbxSzLX/3XBXYxIpyQka/fh74pGrjQ5QzUt9OnFV5dMV+otOG5gQjctxozNTNtzaSSiN
 11.1615 +JHqu0FeJmsqRN/KrKHRLGbaQWtHUgRB9FDfu5giN4eZWIDqWCv8vrcTjrNZgRXQPzy+RmGjQpLRI
 11.1616 +EKz0UqQLlR28ciusM8jn7PtcLPZy2zbSDeyyos0iO+ybBgPyRvSk/CEFm8IndQebz8iXTRbbjhDP
 11.1617 +5xh7iJfBrKd/Nenjj6Jvgp2B+W7AnP102BXH5IZWPV3tI2MUOvXowpdS12IIXhLLP0lKyeuZrpEv
 11.1618 +pFhPqHg3JFTd1cceVp0EsPgGU0wFO2u4iyYRoFYfEm9kG/RZcUUBm87t9mFtx9iCtC9kx4Rt4R8a
 11.1619 +OdgzSt40vtyFecAZZ8BfCOhCrC8djMGPFaz2Vlt5TSZCk053+37wbLDLRXfZ+F45NtdVpVWdudSC
 11.1620 +xgODI8EsiLoTl5aO0lhoigX7GHZDHAY4LxoMIu1gXPYPksmFquxF4uRKZhEnKzXu82HESb+LlNQz
 11.1621 +Fh/RvFJVuhK+Ee5slBdj30FcRGdJ5rhKxtkyKxWcGoV/WOCYKqkNDYJ5fNQVx3g400tpJBS2FSU+
 11.1622 +Tco9ss8nZ08dtscGQfSby87b73fOw+4UgrEMNnY6uMzYvSDxPVPpsij6+l0/ZPfuH0Iz010giY34
 11.1623 +HpL0ZLyLJB4ukaQRU+GwptO7yIZCQE33B0K9iCqO6X+AR4n7wAeH68DPkJzpTsD3x+/cj9LIVHC2
 11.1624 +An1wmv7CzWHoqR02vb0VL73siP+3nkX0YbQ0l9f6WDyOm24cj3rxO2MMip6kpcu6VCefn/789PR3
 11.1625 +0v0fg21sFIp70rj9PCi8YDRDXFucym/43qN+iENh1Jy/dIIIqF3OIkDvBMsdx+huWv8Kz73vl8g5
 11.1626 +WQ3JOGqwu3lb4dfKKbvLigXDQsb8B/xt39Q=
 11.1627 +""".decode("base64").decode("zlib")
 11.1628 +
 11.1629 +##file distutils.cfg
 11.1630 +DISTUTILS_CFG = """
 11.1631 +eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
 11.1632 +xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
 11.1633 +9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
 11.1634 +""".decode("base64").decode("zlib")
 11.1635 +
 11.1636 +##file activate_this.py
 11.1637 +ACTIVATE_THIS = """
 11.1638 +eJyNUlGL2zAMfvevEBlHEujSsXsL9GGDvW1jD3sZpQQ3Ua7aJXawnbT595Ocpe0dO5ghseVP+vRJ
 11.1639 +VpIkn2cYPZknwAvWLXWYhRP5Sk4baKgOWRWNqtpdgTyH2Y5wpq5Tug406YAgKEzkwqg7NBPwR86a
 11.1640 +Hk0olPopaK0NHJHzYQPnE5rI0o8+yBUwiBfyQcT8mMPJGiAT0A0O+b8BY4MKJ7zPcSSzHaKrSpJE
 11.1641 +qeDmUgGvVbPCS41DgO+6xy/OWbfAThMn/OQ9ukDWRCSLiKzk1yrLjWapq6NnvHUoHXQ4bYPdrsVX
 11.1642 +4lQMc/q6ZW975nmSK+oH6wL42a9H65U6aha342Mh0UVDzrD87C1bH73s16R5zsStkBZDp0NrXQ+7
 11.1643 +HaRnMo8f06UBnljKoOtn/YT+LtdvSyaT/BtIv9KR60nF9f3qmuYKO4//T9ItJMsjPfgUHqKwCZ3n
 11.1644 +xu/Lx8M/UvCLTxW7VULHxB1PRRbrYfvWNY5S8it008jOjcleaMqVBDnUXcWULV2YK9JEQ92OfC96
 11.1645 +1Tv4ZicZZZ7GpuEpZbbeQ7DxquVx5hdqoyFSSmXwfC90f1Dc7hjFs/tK99I0fpkI8zSLy4tSy+sI
 11.1646 +3vMWehjQNJmE5VePlZbL61nzX3S93ZcfDqznnkb9AZ3GWJU=
 11.1647 +""".decode("base64").decode("zlib")
 11.1648 +
 11.1649 +if __name__ == '__main__':
 11.1650 +    main()
 11.1651 +
 11.1652 +## TODO:
 11.1653 +## Copy python.exe.manifest
 11.1654 +## Monkeypatch distutils.sysconfig