gump-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From leosim...@apache.org
Subject svn commit: r160420 - in gump/branches/Gump3: ./ webgump/ webgump/bin/ webgump/conf/ webgump/htdocs/ webgump/htdocs/app/ webgump/lib/ webgump/lib/python/ webgump/lib/python/webgump/ webgump/lib/python/webgump/controllers/ webgump/lib/python/webgump/util/ webgump/logs/ webgump/sql/ webgump/templates/
Date Thu, 07 Apr 2005 16:53:17 GMT
Author: leosimons
Date: Thu Apr  7 09:53:11 2005
New Revision: 160420

URL: http://svn.apache.org/viewcvs?view=rev&rev=160420
Log:
Commit a demo version of a new python-based web application setup primarily to show it can actually be pretty easy to do nicely. Whether to keep it around is a decision to make later :-D

Added:
    gump/branches/Gump3/webgump/
    gump/branches/Gump3/webgump/README.txt
    gump/branches/Gump3/webgump/bin/
    gump/branches/Gump3/webgump/bin/cleanup   (with props)
    gump/branches/Gump3/webgump/bin/debug   (with props)
    gump/branches/Gump3/webgump/bin/get-apache   (with props)
    gump/branches/Gump3/webgump/bin/get-mod-python   (with props)
    gump/branches/Gump3/webgump/bin/restart   (with props)
    gump/branches/Gump3/webgump/bin/settings
    gump/branches/Gump3/webgump/bin/start   (with props)
    gump/branches/Gump3/webgump/bin/stop   (with props)
    gump/branches/Gump3/webgump/conf/
    gump/branches/Gump3/webgump/conf/giraffe.conf
    gump/branches/Gump3/webgump/conf/httpd.conf
    gump/branches/Gump3/webgump/htdocs/
    gump/branches/Gump3/webgump/htdocs/app/   (with props)
    gump/branches/Gump3/webgump/htdocs/app/__init__.py
    gump/branches/Gump3/webgump/htdocs/app/handler.py
    gump/branches/Gump3/webgump/lib/   (with props)
    gump/branches/Gump3/webgump/lib/python/   (with props)
    gump/branches/Gump3/webgump/lib/python/ezt.py
    gump/branches/Gump3/webgump/lib/python/webgump/   (with props)
    gump/branches/Gump3/webgump/lib/python/webgump/__init__.py
    gump/branches/Gump3/webgump/lib/python/webgump/controllers/   (with props)
    gump/branches/Gump3/webgump/lib/python/webgump/controllers/__init__.py
    gump/branches/Gump3/webgump/lib/python/webgump/controllers/home.py
    gump/branches/Gump3/webgump/lib/python/webgump/util/   (with props)
    gump/branches/Gump3/webgump/lib/python/webgump/util/__init__.py
    gump/branches/Gump3/webgump/lib/python/webgump/util/log.py
    gump/branches/Gump3/webgump/lib/python/webgump/util/template.py
    gump/branches/Gump3/webgump/logs/   (with props)
    gump/branches/Gump3/webgump/sql/
    gump/branches/Gump3/webgump/sql/webgump.sql
    gump/branches/Gump3/webgump/templates/
    gump/branches/Gump3/webgump/templates/view.ezt
Modified:
    gump/branches/Gump3/gump

Modified: gump/branches/Gump3/gump
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/gump?view=diff&r1=160419&r2=160420
==============================================================================
--- gump/branches/Gump3/gump (original)
+++ gump/branches/Gump3/gump Thu Apr  7 09:53:11 2005
@@ -129,6 +129,20 @@
       If no action is specified, gump passes run as the action to
       execute."
       ;;
+    webgump)
+      echo "
+      Run Webgump.
+
+      Usage:
+        $0 webgump webgump-action [webgump-args ...]
+
+      The available actions are:
+"
+      ls -1 webgump/bin
+      echo "
+      If no action is specified, gump passes debug as the action to
+      execute."
+      ;;
     update-host)
       echo "
       Updates the gump installation on the specified host.
@@ -149,7 +163,7 @@
       ;;
     create-database)
       echo "
-      Create a new MySQL database with the gump database schema.
+      Create a new MySQL database with the dynagump database schema.
 
       Usage:
         $0 create-database [database-name] [mysql-args ...]
@@ -188,6 +202,7 @@
         debug           -- run pygump in debug mode
         test            -- run the pygump unit tests
         dynagump        -- run the dynagump web application server
+        webgump         -- run the webgump application server
         update-host     -- update the configuration of a gump host
         create-database -- create a new gump MySQL database
         pycompile       -- compile all pyump source files
@@ -707,6 +722,22 @@
   cd "$current"
 }
 
+# Run webgump
+function webgump
+{
+  # "debug" is the default command
+  local command="$1"
+  shift
+  if [[ -z "$command" ]]; then
+    command="debug"
+  fi
+  
+  local current=`pwd`
+  cd "$GUMP_HOME/webgump"
+  ./bin/$command $@
+  cd "$current"
+}
+
 # Create the gump database
 function create_database
 {
@@ -793,6 +824,9 @@
       ;;
     dynagump)
       dynagump $@
+      ;;
+    webgump)
+      webgump $@
       ;;
     create-database)
       create_database $@

Added: gump/branches/Gump3/webgump/README.txt
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/README.txt?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/README.txt (added)
+++ gump/branches/Gump3/webgump/README.txt Thu Apr  7 09:53:11 2005
@@ -0,0 +1,11 @@
+Welcome to WebGump!
+
+Webgump is a small experiment in building a python-based web application. It's mainly meant to contrast against dynagump (dynagump big, webgump 
+small), while both at the moment don't really do anything. It should serve as a discussion starter on the web side of things. Real options include
+
+  * dynagump-style  (dynamic)
+  * webgump-style   (dynamic)
+  * gump2-style     (generated)
+  * gump2-old-style (generated by forrest)
+  * using some other ready made python framework
+  * using some other ready made java framework

Added: gump/branches/Gump3/webgump/bin/cleanup
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/bin/cleanup?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/bin/cleanup (added)
+++ gump/branches/Gump3/webgump/bin/cleanup Thu Apr  7 09:53:11 2005
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Simple script to get rid of python object files in this webapp
+
+find $GUMP_HOME/webgump -name '*.pyc' -or -name '*.pyo' | xargs rm -f
+

Propchange: gump/branches/Gump3/webgump/bin/cleanup
------------------------------------------------------------------------------
    svn:executable = *

Added: gump/branches/Gump3/webgump/bin/debug
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/bin/debug?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/bin/debug (added)
+++ gump/branches/Gump3/webgump/bin/debug Thu Apr  7 09:53:11 2005
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# Simple script to start a single process apache
+
+# look for this file
+current=`pwd`
+thisscript="`pwd`/start"
+if [[ -f "$thisscript" ]]; then
+  # guess...
+  scriptdir="$current"
+else
+  # look for the path to this file
+  homedir=`dirname $0`
+  thisscript="$homedir/start"
+  if [[ -f "$thisscript" ]]; then
+    # guess...
+    scriptdir="$homedir"
+  fi
+fi
+
+# source settings
+. $scriptdir/settings
+
+$APACHECMD -f $APACHECONF -X

Propchange: gump/branches/Gump3/webgump/bin/debug
------------------------------------------------------------------------------
    svn:executable = *

Added: gump/branches/Gump3/webgump/bin/get-apache
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/bin/get-apache?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/bin/get-apache (added)
+++ gump/branches/Gump3/webgump/bin/get-apache Thu Apr  7 09:53:11 2005
@@ -0,0 +1,121 @@
+#!/bin/bash
+# simple script to setup apache
+
+# Where are we?
+if [[ -z "$GUMP_HOME" ]]; then
+  echo "ERROR: \$GUMP_HOME not set!"
+  exit 1
+fi
+
+###
+### Settings
+###
+APACHE_VERSION=2.0.53
+APACHE_INSTALL=$GUMP_HOME/webgump/lib/apache2-install
+
+###
+### Install apache
+###
+if [[ ! -d "$APACHE_INSTALL/current" ]]; then
+  mkdir $APACHE_INSTALL
+  cd $APACHE_INSTALL
+  if [[ ! -d "$APACHE_INSTALL/httpd-$APACHE_VERSION" ]]; then
+    wget http://apache.surfnet.nl/httpd/httpd-$APACHE_VERSION.tar.gz
+    tar zxf httpd-$APACHE_VERSION.tar.gz
+  fi
+  cd $APACHE_INSTALL/httpd-$APACHE_VERSION
+  ./configure --prefix=$APACHE_INSTALL/current --enable-mods-shared=most
+  make
+  make install
+else
+  echo "WARNING appears apache is already installed at"
+  echo "WARNING   $APACHE_INSTALL/current"
+  echo "WARNING We won't attempt re-install"
+fi
+
+###
+### Install mod_python
+###
+$GUMP_HOME/webgump/bin/get-mod-python
+
+###
+### Use our own config
+###
+if [[ -d "$APACHE_INSTALL/current/conf.dist" ]]; then
+  echo "WARNING appears our custom apache config is already installed at"
+  echo "WARNING   $APACHE_INSTALL/current/conf"
+  echo "WARNING We won't attempt re-install"
+else
+  echo "Installing config..."
+  cd $APACHE_INSTALL/current
+  mv conf conf.dist
+  ln -s $GUMP_HOME/webgump/conf
+  cd conf
+fi
+
+# Write the basic path-dependent config settings into a seperate file
+host=`hostname -s`
+if [[ -f "$GUMP_HOME/webgump/conf/$host.conf" ]]; then
+  echo "WARNING appears machine specific apache config is already installed at"
+  echo "WARNING   $GUMP_HOME/webgump/conf/$host.conf"
+  echo "WARNING We won't attempt re-install"
+else
+  echo "Installing machine-specific config"
+  cat > $GUMP_HOME/webgump/conf/$host.conf <<ENDECHO
+ServerName $host
+ServerRoot "$APACHE_INSTALL/current"
+# get most settings from the common config
+Include "conf/httpd.conf"
+
+ErrorLog "$GUMP_HOME/webgump/logs/error_log"
+
+DocumentRoot "$GUMP_HOME/webgump/htdocs"
+<Directory />
+    Options FollowSymLinks
+    AllowOverride None
+</Directory>
+
+<Directory "$GUMP_HOME/webgump/htdocs">
+    Options Indexes FollowSymLinks
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+</Directory>
+
+<Directory "$GUMP_HOME/webgump/htdocs/app">
+    AddHandler python-program .py
+    PythonHandler handler::Handler.handle
+    PythonPath "sys.path+['$GUMP_HOME/webgump/conf', '$GUMP_HOME/webgump/htdocs/app', '$GUMP_HOME/webgump/lib/python', '$GUMP_HOME/pygump/python']"
+    PythonDebug On
+
+    Order allow,deny
+    Allow from all
+
+    Options +Includes
+    SetOutputFilter INCLUDES
+    AcceptPathInfo On
+</Directory>
+ENDECHO
+
+fi
+
+###
+### Done. Report!
+###
+cat <<ENDMSG
+
+if All went well, apache2 is now installed inside
+
+  $APACHE_INSTALL/current
+
+ You may wish to customize the file
+
+ "$GUMP_HOME/webgump/conf/$host.conf"
+
+to further customize webgump's behaviour. After that,
+you should be able to run apache using
+
+ $GUMP_HOME/webgump/bin/start
+
+good luck!
+ENDMSG

Propchange: gump/branches/Gump3/webgump/bin/get-apache
------------------------------------------------------------------------------
    svn:executable = *

Added: gump/branches/Gump3/webgump/bin/get-mod-python
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/bin/get-mod-python?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/bin/get-mod-python (added)
+++ gump/branches/Gump3/webgump/bin/get-mod-python Thu Apr  7 09:53:11 2005
@@ -0,0 +1,35 @@
+#!/bin/bash
+#
+# Simple script to install mod_python
+
+# Where are we?
+if [[ -z "$GUMP_HOME" ]]; then
+  echo "ERROR: \$GUMP_HOME not set!"
+  exit 1
+fi
+
+###
+### Settings
+###
+MOD_PYTHON_VERSION=3.1.4
+APACHE_INSTALL=$GUMP_HOME/webgump/lib/apache2-install
+WEBGUMP=$GUMP_HOME/webgump
+
+###
+### Install mod_python
+###
+if [[ ! -d "$WEBGUMP/lib/python/mod_python" ]]; then
+  cd $APACHE_INSTALL
+  wget http://dist.apache.easynet.nl/httpd/modpython/mod_python-$MOD_PYTHON_VERSION.tgz
+  tar zxf mod_python-$MOD_PYTHON_VERSION.tgz
+  cd mod_python-$MOD_PYTHON_VERSION
+  ./configure --with-apxs=$APACHE_INSTALL/current/bin/apxs
+  make
+  make install_dso
+  cd dist
+  python setup.py install --install-lib=$WEBGUMP/lib/python
+else
+  echo "WARNING appears mod_python is already installed at"
+  echo "WARNING   $WEBGUMP/lib/python"
+  echo "WARNING We won't attempt re-install"
+fi

Propchange: gump/branches/Gump3/webgump/bin/get-mod-python
------------------------------------------------------------------------------
    svn:executable = *

Added: gump/branches/Gump3/webgump/bin/restart
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/bin/restart?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/bin/restart (added)
+++ gump/branches/Gump3/webgump/bin/restart Thu Apr  7 09:53:11 2005
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# Simple script to restart apache
+
+# look for this file
+current=`pwd`
+thisscript="`pwd`/start"
+if [[ -f "$thisscript" ]]; then
+  # guess...
+  scriptdir="$current"
+else
+  # look for the path to this file
+  homedir=`dirname $0`
+  thisscript="$homedir/start"
+  if [[ -f "$thisscript" ]]; then
+    # guess...
+    scriptdir="$homedir"
+  fi
+fi
+
+# source settings
+. $scriptdir/settings
+
+$APACHECTL -f $APACHECONF -k restart

Propchange: gump/branches/Gump3/webgump/bin/restart
------------------------------------------------------------------------------
    svn:executable = *

Added: gump/branches/Gump3/webgump/bin/settings
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/bin/settings?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/bin/settings (added)
+++ gump/branches/Gump3/webgump/bin/settings Thu Apr  7 09:53:11 2005
@@ -0,0 +1,7 @@
+if [[ -z "$GUMP_HOME" ]]; then
+  echo "ERROR: \$GUMP_HOME is not set!"
+  exit 1
+fi
+APACHECTL=$GUMP_HOME/webgump/lib/apache2-install/current/bin/apachectl
+APACHECMD=$GUMP_HOME/webgump/lib/apache2-install/current/bin/httpd
+APACHECONF=$GUMP_HOME/webgump/conf/`hostname -s`.conf

Added: gump/branches/Gump3/webgump/bin/start
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/bin/start?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/bin/start (added)
+++ gump/branches/Gump3/webgump/bin/start Thu Apr  7 09:53:11 2005
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# Simple script to start apache
+
+# look for this file
+current=`pwd`
+thisscript="`pwd`/start"
+if [[ -f "$thisscript" ]]; then
+  # guess...
+  scriptdir="$current"
+else
+  # look for the path to this file
+  homedir=`dirname $0`
+  thisscript="$homedir/start"
+  if [[ -f "$thisscript" ]]; then
+    # guess...
+    scriptdir="$homedir"
+  fi
+fi
+
+# source settings
+. $scriptdir/settings
+
+$APACHECTL -f $APACHECONF -k start

Propchange: gump/branches/Gump3/webgump/bin/start
------------------------------------------------------------------------------
    svn:executable = *

Added: gump/branches/Gump3/webgump/bin/stop
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/bin/stop?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/bin/stop (added)
+++ gump/branches/Gump3/webgump/bin/stop Thu Apr  7 09:53:11 2005
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# Simple script to stop apache
+
+# look for this file
+current=`pwd`
+thisscript="`pwd`/start"
+if [[ -f "$thisscript" ]]; then
+  # guess...
+  scriptdir="$current"
+else
+  # look for the path to this file
+  homedir=`dirname $0`
+  thisscript="$homedir/start"
+  if [[ -f "$thisscript" ]]; then
+    # guess...
+    scriptdir="$homedir"
+  fi
+fi
+
+# source settings
+. $scriptdir/settings
+
+$APACHECTL -f $APACHECONF -k stop

Propchange: gump/branches/Gump3/webgump/bin/stop
------------------------------------------------------------------------------
    svn:executable = *

Added: gump/branches/Gump3/webgump/conf/giraffe.conf
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/conf/giraffe.conf?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/conf/giraffe.conf (added)
+++ gump/branches/Gump3/webgump/conf/giraffe.conf Thu Apr  7 09:53:11 2005
@@ -0,0 +1,33 @@
+ServerName giraffe
+ServerRoot "/home/lsimons/svn/gump/branches/Gump3/webgump/lib/apache2-install/current"
+# get most settings from the common config
+Include "conf/httpd.conf"
+
+ErrorLog "/home/lsimons/svn/gump/branches/Gump3/webgump/logs/error_log"
+
+DocumentRoot "/home/lsimons/svn/gump/branches/Gump3/webgump/htdocs"
+<Directory />
+    Options FollowSymLinks
+    AllowOverride None
+</Directory>
+
+<Directory "/home/lsimons/svn/gump/branches/Gump3/webgump/htdocs">
+    Options Indexes FollowSymLinks
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+</Directory>
+
+<Directory "/home/lsimons/svn/gump/branches/Gump3/webgump/htdocs/app">
+    AddHandler python-program .py
+    PythonHandler handler::Handler.handle
+    PythonPath "sys.path+['/home/lsimons/svn/gump/branches/Gump3/webgump/conf', '/home/lsimons/svn/gump/branches/Gump3/webgump/htdocs/app', '/home/lsimons/svn/gump/branches/Gump3/webgump/lib/python', '/home/lsimons/svn/gump/branches/Gump3/pygump/python']"
+    PythonDebug On
+
+    Order allow,deny
+    Allow from all
+
+    Options +Includes
+    SetOutputFilter INCLUDES
+    AcceptPathInfo On
+</Directory>

Added: gump/branches/Gump3/webgump/conf/httpd.conf
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/conf/httpd.conf?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/conf/httpd.conf (added)
+++ gump/branches/Gump3/webgump/conf/httpd.conf Thu Apr  7 09:53:11 2005
@@ -0,0 +1,346 @@
+LoadModule access_module modules/mod_access.so
+LoadModule auth_module modules/mod_auth.so
+LoadModule ext_filter_module modules/mod_ext_filter.so
+LoadModule include_module modules/mod_include.so
+LoadModule log_config_module modules/mod_log_config.so
+LoadModule env_module modules/mod_env.so
+LoadModule expires_module modules/mod_expires.so
+LoadModule headers_module modules/mod_headers.so
+LoadModule setenvif_module modules/mod_setenvif.so
+LoadModule mime_module modules/mod_mime.so
+LoadModule status_module modules/mod_status.so
+LoadModule autoindex_module modules/mod_autoindex.so
+LoadModule asis_module modules/mod_asis.so
+LoadModule info_module modules/mod_info.so
+LoadModule cgi_module modules/mod_cgi.so
+LoadModule vhost_alias_module modules/mod_vhost_alias.so
+LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule dir_module modules/mod_dir.so
+LoadModule actions_module modules/mod_actions.so
+LoadModule speling_module modules/mod_speling.so
+LoadModule userdir_module modules/mod_userdir.so
+LoadModule alias_module modules/mod_alias.so
+LoadModule rewrite_module modules/mod_rewrite.so
+LoadModule python_module modules/mod_python.so
+
+Listen 8080
+ServerAdmin general@gump.apache.org
+Timeout 300
+KeepAlive On
+MaxKeepAliveRequests 100
+KeepAliveTimeout 15
+UseCanonicalName Off
+LogLevel debug
+
+<IfModule !mpm_netware.c>
+PidFile logs/httpd.pid
+</IfModule>
+
+<Directory />
+    Options FollowSymLinks
+    AllowOverride None
+</Directory>
+
+DirectoryIndex index.html index.html.var index.py
+AccessFileName .htaccess
+
+<Files ~ "^\.ht">
+    Order allow,deny
+    Deny from all
+</Files>
+
+TypesConfig conf.dist/mime.types
+
+DefaultType text/plain
+
+<IfModule mod_mime_magic.c>
+    MIMEMagicFile conf.dist/magic
+</IfModule>
+
+HostnameLookups Off
+#EnableMMAP off
+#EnableSendfile off
+
+ServerTokens Full
+ServerSignature On
+
+IndexOptions VersionSort
+ReadmeName README.html
+HeaderName HEADER.html
+IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
+
+AddLanguage ca .ca
+AddLanguage cs .cz .cs
+AddLanguage da .dk
+AddLanguage de .de
+AddLanguage el .el
+AddLanguage en .en
+AddLanguage eo .eo
+AddLanguage es .es
+AddLanguage et .et
+AddLanguage fr .fr
+AddLanguage he .he
+AddLanguage hr .hr
+AddLanguage it .it
+AddLanguage ja .ja
+AddLanguage ko .ko
+AddLanguage ltz .ltz
+AddLanguage nl .nl
+AddLanguage nn .nn
+AddLanguage no .no
+AddLanguage pl .po
+AddLanguage pt .pt
+AddLanguage pt-BR .pt-br
+AddLanguage ru .ru
+AddLanguage sv .sv
+AddLanguage zh-CN .zh-cn
+AddLanguage zh-TW .zh-tw
+
+LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW
+ForceLanguagePriority Prefer Fallback
+
+AddDefaultCharset ISO-8859-1
+AddCharset ISO-8859-1  .iso8859-1  .latin1
+AddCharset ISO-8859-2  .iso8859-2  .latin2 .cen
+AddCharset ISO-8859-3  .iso8859-3  .latin3
+AddCharset ISO-8859-4  .iso8859-4  .latin4
+AddCharset ISO-8859-5  .iso8859-5  .latin5 .cyr .iso-ru
+AddCharset ISO-8859-6  .iso8859-6  .latin6 .arb
+AddCharset ISO-8859-7  .iso8859-7  .latin7 .grk
+AddCharset ISO-8859-8  .iso8859-8  .latin8 .heb
+AddCharset ISO-8859-9  .iso8859-9  .latin9 .trk
+AddCharset ISO-2022-JP .iso2022-jp .jis
+AddCharset ISO-2022-KR .iso2022-kr .kis
+AddCharset ISO-2022-CN .iso2022-cn .cis
+AddCharset Big5        .Big5       .big5
+# For russian, more than one charset is used (depends on client, mostly):
+AddCharset WINDOWS-1251 .cp-1251   .win-1251
+AddCharset CP866       .cp866
+AddCharset KOI8-r      .koi8-r .koi8-ru
+AddCharset KOI8-ru     .koi8-uk .ua
+AddCharset ISO-10646-UCS-2 .ucs2
+AddCharset ISO-10646-UCS-4 .ucs4
+AddCharset UTF-8       .utf8
+AddCharset GB2312      .gb2312 .gb 
+AddCharset utf-7       .utf7
+AddCharset utf-8       .utf8
+AddCharset big5        .big5 .b5
+AddCharset EUC-TW      .euc-tw
+AddCharset EUC-JP      .euc-jp
+AddCharset EUC-KR      .euc-kr
+AddCharset shift_jis   .sjis
+
+BrowserMatch "Mozilla/2" nokeepalive
+BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
+BrowserMatch "RealPlayer 4\.0" force-response-1.0
+BrowserMatch "Java/1\.0" force-response-1.0
+BrowserMatch "JDK/1\.0" force-response-1.0
+BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
+BrowserMatch "^WebDrive" redirect-carefully
+BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully
+BrowserMatch "^gnome-vfs" redirect-carefully
+
+### .-------------------------------------------------------------.
+### |   FURSWA: Fancy URL Rewriting Scheme for Web Applications   |
+### .-------------------------------------------------------------.
+# The below combination of mod_rewrite directives allows any web application
+# that is built around a concept of controller+action pairs to have pretty
+# URLs on the outside, and easily parseable ones on the inside. All of the
+# rewrite rules combine to transform URLs that are requested like this:
+#
+# /controller/action/param1/value1/paramN/valueN/unparsed.stuff/index.html?otherparm=otherval#fragment
+#
+# into URLs like this as seen by your application:
+#
+# /myhandler?controller=controller&action=action&param1=value1&paramN=valueN&path=unparsed.stuff/index.html&otherparm=otherval#fragment
+#
+# which can then be processed further by your web application in any way you
+# choose.
+#
+# The reverse process is also applied. This means that URLs that are requested
+# like this:
+#
+# /myhandler?controller=controller&action=action&param1=value1&paramN=valueN&path=unparsed.stuff/index.html&otherparm=otherval#fragment
+#
+# are transformed into URLs like this:
+#
+# /controller/action/param1/value1/paramN/valueN/unparsed.stuff/index.html?otherparm=otherval#fragment
+#
+# which are sent back to the client with a 304 Moved Permanently redirect, so
+# that the client sees only the pretty url. This allows your web application to
+# output the ugly URLs and not worry about prettying those up.
+#
+# Note that none of the variables (controller, action, parameters, values)
+# that are parsed out can have a "/" or a "." in them. Also note that the order
+# of the controller, action and path parameters actually matters, not just when
+# transforming from ugly urls to pretty ones, but also when going back the other
+# way.
+#
+# Configuration
+# -------------
+#
+# Of course, you still need to configure the /myhandler location that will be
+# used to actually process the requests. Simply replace "/app/handler.py" with
+# the path to your webapplication in all the rules below.
+#
+# In addition, you will need to configure exactly what URLs are considered as
+# being part of the web application, and which are pointers to (for example)
+# regular files. You can do that by customizing RULE 02.
+#
+# Combining with other rules
+# --------------------------
+#
+# If you wish to use mod_rewrite rules in addition to the ones our "fancy
+# rewriting scheme" sets up, add them *after* all the rules below, i.e.,
+# define them as RULE 22 and later.
+
+###
+### Section I: Setup
+###
+RewriteEngine "On"
+# Enable the lines below for debugging
+#RewriteLog "logs/rewrite_log"
+#RewriteLogLevel 5
+
+###
+### Section II: Mode handling
+###
+### Step 01: Determine which mode we're in
+# Here, we configure a set of rules that puts us in one of three matching
+# modes:
+#
+# 1) prettyfication. We have an ugly query-string based url referencing part
+#    of our web application, which is rewritten to something fancy, then
+#    provided to the user with a 304 Moved Permanently redirect.
+# 2) redirection. We have a pretty webapp url which internally is rewritten
+#    into a query-string based url for easy processing by the CGI application
+# 3) other stuff. Neither of the above is the case, so we jump to another bit
+#    that does other kinds of redirection.
+#                                                                                       RULE 01
+RewriteCond "RULE1%{ENV:REWRITE_MODE}" =RULE1
+RewriteRule "^/app/handler.py$" - [env=REWRITE_MODE:prettyfy]
+
+#                                                                                       RULE 02
+RewriteCond "RULE2%{ENV:REWRITE_MODE}" =RULE2
+RewriteCond "%{REQUEST_FILENAME}" !-f
+# Specify what bits are webapplications here
+RewriteCond "%{REQUEST_URI}" "^/home"
+#RewriteCond "%{REQUEST_URI}" "^/webapp2" [OR]
+#RewriteCond "%{REQUEST_URI}" "^/webapp3" [OR]
+RewriteRule "^/([^/\.]+/[^/\.]+)(/.*)?$" - [env=REWRITE_MODE:redirection]
+
+#                                                                                       RULE 03
+RewriteCond "RULE3%{ENV:REWRITE_MODE}" =RULE3
+RewriteRule "." - [env=REWRITE_MODE:other]
+
+### Step 02: Jump to relevant section
+# Here, we configure a set of rules that skip forward a number of rules to the
+# section matching our REWRITE_MODE. This means it is important to keep track
+# of the number of rewrite rules in each section except the last one!
+
+#                                                                                       RULE 05
+# JUMP from RULE 05 to RULE 14: skip=(14-5-1=8)
+RewriteCond "RULE5%{ENV:REWRITE_MODE}" =RULE5redirection
+RewriteRule "." - [skip=8]
+
+#                                                                                       RULE 06
+# JUMP from RULE 06 to RULE 21: skip=(21-6-1=14)
+RewriteCond "RULE6%{ENV:REWRITE_MODE}" =RULE6other
+RewriteRule "." - [skip=14]
+
+###
+### Section III: Prettyfication
+###
+# Note that we never need to do qsappend here as we get "the rest" of
+# the query string all the time.
+
+### Step 01: /app/handler.py ->                                                         RULE 07
+###          prettyfy:/
+# basic paranoia :-D
+RewriteCond "RULE7%{ENV:REWRITE_MODE}" =RULE7prettyfy
+RewriteRule "^/app/handler.py$" "prettyfy:/"
+
+### Step 02: /?controller=controller&... ->                                             RULE 08
+###          /controller/...?...
+RewriteCond "RULE8%{QUERY_STRING}" "RULE8controller=([^/\.&]+)&?(.*)"
+RewriteRule "^prettyfy:/$" "prettyfy:/%1?%2"
+
+### Step 03: /controller?action=action&... ->                                           RULE 09
+###          /controller/action/...?...
+RewriteCond "RULE9%{QUERY_STRING}" "RULE9action=([^/\.&]+)&?(.*)"
+RewriteRule "^prettyfy:/([^/\.]+)$" "prettyfy:/$1/%1?%2"
+
+### Step 04: /...?path=unparsed.stuff/index.html&... ->                                 RULE 10
+###          /...?... && $PRETTYFY_PATH=unparsed.stuff/index.html
+RewriteCond "RULE10%{QUERY_STRING}" "RULE10path=([^&]+)&?(.*)"
+RewriteRule "^prettyfy:/(.*)$" "prettyfy:/$1?%2" [env=PRETTYFY_PATH=%1]
+
+### Step 05: /controller/action?param=value&... ->                                      RULE 11
+###          /controller/action/param/value/...?...
+# JUMP from RULE 11 to RULE 01
+RewriteCond "RULE11%{QUERY_STRING}" "RULE11([^/\.&]+)=([^/\.&]+)&?(.*)"
+RewriteRule "^prettyfy:/([^/\.]+)/([^/\.]+)$" "prettyfy:/$1/$2/%1/%2?%3" [next]
+
+### Step 06: /controller/action/param=value/paramN=valueN?... ->                        RULE 12
+###          /controller/action/param=value/paramN=valueN/unparsed.stuff/index.html?...
+RewriteCond "RULE12%{PRETTYFY_PATH}" !=RULE12
+RewriteCond "%{QUERY_STRING}" "(.*)"
+RewriteRule "^prettyfy:/(.*)$" "prettyfy:/$1/%{ENV:PRETTYFY_PATH}?%1"
+
+### Step 07: get rid of prefix                                                          RULE 13
+# STOP processing
+RewriteRule "^prettyfy:/(.*)$" "/$1" [last,redirect=permanent]
+
+
+###
+### Section IV: Redirection
+###
+
+### Step 01: /... -> webapp:/...                                                        RULE 14
+# basic paranoia :-D
+RewriteCond "RULE14%{ENV:REWRITE_MODE}" =RULE14redirection
+RewriteRule "^/(.*)$" "webapp:/$1"
+
+### Step 02: /$controller/... -> /..., saving $controller in ENV
+# this processing is run only once (deal with looping)                                  RULE 15
+RewriteCond "RULE15%{ENV:WEBAPP_CONTROLLER}" =RULE15
+RewriteRule "^webapp:/([^/\.]+)/(.*)$" "webapp:/$2" [env=WEBAPP_CONTROLLER:$1,chain]
+# make sure we have a default if no controller is specified
+# (for example, someone might request /myhandler directly)                              RULE 16
+RewriteCond "RULE16%{ENV:WEBAPP_CONTROLLER}" =RULE16
+RewriteRule "." - [env=WEBAPP_CONTROLLER:home]
+
+### Step 03: /$action/... -> /..., saving $action in ENV
+# this processing is run only once (deal with looping)                                  RULE 17
+RewriteCond "RULE17%{ENV:WEBAPP_ACTION}" =RULE17
+RewriteRule "^webapp:/([^/\.]+)/?(.*)$" "webapp:/$2" [env=WEBAPP_ACTION:$1,chain]
+# make sure we have a default if no controller is specified
+# (for example, someone might request /myhandler directly)                              RULE 18
+RewriteCond "RULE18%{ENV:WEBAPP_ACTION}" =RULE18
+RewriteRule "." - [env=WEBAPP_ACTION:view]
+
+### Step 04: /param/value/... -> /...?param=value
+# JUMP from RULE 19 to RULE 01                                                          RULE 19
+RewriteRule "^webapp:/([^/\.]+)/([^/\.]+)/?(.*)$" "webapp:/$3?$1=$2" [next,qsappend]
+
+### Step 05: /unparsed.stuff/index.html ->
+###          /app/handler.py?path=unparsed.stuff/index.html
+# save everything we did not process as "path", get rid of the
+# webapp: prefix, then call on the handler.
+# STOP processing                                                                       RULE 20
+RewriteRule "^webapp:(.*)$" "/app/handler.py?controller=%{ENV:WEBAPP_CONTROLLER}&action=%{ENV:WEBAPP_ACTION}&path=$1" [last,qsappend]
+
+###
+### Section V: Other
+###
+
+### Step 01: Basic paranoia :-D                                                         RULE 21
+RewriteCond "RULE21%{ENV:REWRITE_MODE}" !=RULE21other
+RewriteRule "." - [L]
+
+### Step 02: Whatever you want after this :-D
+# This is the place where you should do your own redirect rules, normally you will
+# want to make these external redirects, otherwise the above logic will not be
+# applied!
+RewriteRule "^/$" "/home/view" [redirect,last]
+RewriteRule "^/index.html?$" "/home/view?path=bla" [redirect,last]

Propchange: gump/branches/Gump3/webgump/htdocs/app/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Apr  7 09:53:11 2005
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo

Added: gump/branches/Gump3/webgump/htdocs/app/__init__.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/htdocs/app/__init__.py?view=auto&rev=160420
==============================================================================
    (empty)

Added: gump/branches/Gump3/webgump/htdocs/app/handler.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/htdocs/app/handler.py?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/htdocs/app/handler.py (added)
+++ gump/branches/Gump3/webgump/htdocs/app/handler.py Thu Apr  7 09:53:11 2005
@@ -0,0 +1,145 @@
+#!/usr/bin/env python
+import os
+import sys
+import imp
+
+from mod_python import apache
+from mod_python import util
+
+from webgump.util import log
+from webgump.util.log import Logger
+
+#DEBUG = True
+DEBUG = False
+
+class Handler:
+    def __init__(self, req):
+        """A new handler is created by mod_python on every request."""
+        self.status = None
+        self.req = req
+        
+        if DEBUG:
+            self.log = Logger(req, level=log.DEBUG, name="webgump.handler")
+        else:
+            self.log = Logger(req, level=log.INFO, name="webgump.handler")
+
+    def handle(self, req):
+        """This is the main delegation method that reads in config and then
+        fires up a controller."""
+        req.content_type = "text/html"
+        try:
+            self._settings()
+            action = self._get_action()
+            self.status = action(self.req, self.settings)
+        except IOError:
+            self.req = None
+            self.log.error("Client is gone.")
+            return apache.OK
+        except:
+            try:
+                # sufficiently advanced controllers should ideallly do their own
+                # exception handling and recovery. This is a minimal failsafe.
+                self.req.write("<p><strong>An unexpected problem has occurred!</strong></p>")
+                self.log.exception("Uncaught exception!")
+            except:
+                pass
+        #try:
+        #    if DEBUG:
+        #        self._debug_info()
+        #except:
+        #    pass
+    
+        if self.status:
+            return self.status
+        else:
+            return apache.OK
+    
+    def _settings(self):
+        """Set defaults, then load config file, then set some more settings based
+        on the mod_python provided environment."""
+        self.req.add_common_vars()
+        self.settings = {
+            'DEBUG': DEBUG,
+            'PAGE_TITLE': "Front Page",
+            'db_host': "localhost",
+            'db_user': "webgump",
+            'db_password': "webgump",
+            'db_name': "webgump"
+        }
+        for key,val in self.req.subprocess_env.items():
+            self.settings[key] = val
+
+        query_vars = util.parse_qs(self.req.subprocess_env["QUERY_STRING"])
+        self.settings['HTTP_GET_VARS'] = query_vars
+        for key,val in query_vars.items():
+            val.reverse()
+            self.settings[key] = val[0]
+            val.reverse()
+
+        self.settings['TEMPLATE_ROOT'] = \
+            os.path.abspath(os.path.join(self.settings['DOCUMENT_ROOT'], "../templates"))
+
+    
+    def _get_action(self):
+        """Determine the controller to fire up."""
+        controller = self.settings['controller'] or "home"
+        action = self.settings['action'] or "view"
+        self.log.debug("Executing %s::%s()" % (controller,action))
+        try:
+            module = _find_controller_module(controller)
+        except:
+            e = sys.exc_info()
+            raise e[0], "Unable to find controller '%s': %s" % (controller, e[1]), e[2]
+        
+        if module and hasattr(module, action):
+            method = getattr(module, action)
+            if callable(method):
+                return method
+            else:
+                raise "Action '%s' of controller '%s' not callable" % (action, controller)
+        else:
+            raise "No action '%s' available in controller '%s'" % (action, controller)   
+        
+    #def _debug_info(self):
+    #    """Write basic environment information to the web page."""
+    #    self.req.write("<hr/><p><strong>DEBUG INFO</strong></p>\n")
+    #    self.req.write("<p><em>Webapp Settings</em></p>\n<pre>")
+    #    for (key,val) in self.settings.items():
+    #        self.req.write("%s: %s\n" % (key,val))
+    #    self.req.write("</pre>")
+
+
+def _find_controller_module(controller):
+    """Finds and loads a module within lsdblog.controllers based on the provided
+    controller name."""
+    import webgump.controllers
+    
+    modulename = "webgump.controllers.%s" % controller
+    module = None
+    try:
+        module = sys.modules[modulename]
+    except KeyError:
+        n = "webgump"
+        (f1,p,d) = imp.find_module(n)
+        try:
+            m = imp.load_module(n,f1,p,d)
+            p = m.__path__
+            n = "controllers"
+            (f2,p,d) = imp.find_module(n,p)
+            try:
+                m = imp.load_module(n,f2,p,d)
+                p = m.__path__
+            
+                (f3,p,d) = imp.find_module(controller, p)
+                try:
+                    module = imp.load_module(controller, f3, p, d)
+                finally:
+                    if f3:
+                        f3.close()
+            finally:
+                if f2:
+                    f2.close()
+        finally:
+            if f1:
+                f1.close()
+    return module

Propchange: gump/branches/Gump3/webgump/lib/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Apr  7 09:53:11 2005
@@ -0,0 +1,2 @@
+apache2-install
+

Propchange: gump/branches/Gump3/webgump/lib/python/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Apr  7 09:53:11 2005
@@ -0,0 +1,4 @@
+*.pyc
+*.pyo
+mod_python
+

Added: gump/branches/Gump3/webgump/lib/python/ezt.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/lib/python/ezt.py?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/lib/python/ezt.py (added)
+++ gump/branches/Gump3/webgump/lib/python/ezt.py Thu Apr  7 09:53:11 2005
@@ -0,0 +1,585 @@
+#!/usr/bin/env python
+"""ezt.py -- easy templating
+
+ezt templates are very similar to standard HTML files.  But additionaly
+they contain directives sprinkled in between.  With these directives
+it possible to generate the dynamic content from the ezt templates.
+
+These directives are enclosed in square brackets.  If you are a 
+C-programmer, you might be familar with the #ifdef directives of the
+C preprocessor 'cpp'.  ezt provides a similar concept for HTML.  Additionally 
+EZT has a 'for' directive, which allows to iterate (repeat) certain 
+subsections of the template according to sequence of data items
+provided by the application.
+
+The HTML rendering is performed by the method generate() of the Template
+class.  Building template instances can either be done using external
+EZT files (convention: use the suffix .ezt for such files):
+
+    >>> template = Template("../templates/log.ezt")
+
+or by calling the parse() method of a template instance directly with 
+a EZT template string:
+
+    >>> template = Template()
+    >>> template.parse('''<html><head>
+    ... <title>[title_string]</title></head>
+    ... <body><h1>[title_string]</h1>
+    ...    [for a_sequence] <p>[a_sequence]</p>
+    ...    [end] <hr>
+    ...    The [person] is [if-any state]in[else]out[end].
+    ... </body>
+    ... </html>
+    ... ''')
+
+The application should build a dictionary 'data' and pass it together
+with the output fileobject to the templates generate method:
+
+    >>> data = {'title_string' : "A Dummy Page",
+    ...         'a_sequence' : ['list item 1', 'list item 2', 'another element'],
+    ...         'person': "doctor",
+    ...         'state' : None }
+    >>> import sys
+    >>> template.generate(sys.stdout, data)
+    <html><head>
+    <title>A Dummy Page</title></head>
+    <body><h1>A Dummy Page</h1>
+     <p>list item 1</p>
+     <p>list item 2</p>
+     <p>another element</p>
+     <hr>
+    The doctor is out.
+    </body>
+    </html>
+
+Template syntax error reporting should be improved.  Currently it is 
+very sparse (template line numbers would be nice):
+
+    >>> Template().parse("[if-any where] foo [else] bar [end unexpected args]")
+    Traceback (innermost last):
+      File "<stdin>", line 1, in ?
+      File "ezt.py", line 220, in parse
+        self.program = self._parse(text)
+      File "ezt.py", line 275, in _parse
+        raise ArgCountSyntaxError(str(args[1:]))
+    ArgCountSyntaxError: ['unexpected', 'args']
+    >>> Template().parse("[if unmatched_end]foo[end]")
+    Traceback (innermost last):
+      File "<stdin>", line 1, in ?
+      File "ezt.py", line 206, in parse
+        self.program = self._parse(text)
+      File "ezt.py", line 266, in _parse
+        raise UnmatchedEndError()
+    UnmatchedEndError
+
+
+Directives
+==========
+
+ Several directives allow the use of dotted qualified names refering to objects
+ or attributes of objects contained in the data dictionary given to the 
+ .generate() method.
+
+ Simple directives
+ -----------------
+
+   [QUAL_NAME]
+
+   This directive is simply replaced by the value of identifier from the data 
+   dictionary.  QUAL_NAME might be a dotted qualified name refering to some
+   instance attribute of objects contained in the dats dictionary.
+   Numbers are converted to string though.
+
+   [include "filename"]  or [include QUAL_NAME]
+
+   This directive is replaced by content of the named include file.
+
+ Block directives
+ ----------------
+
+   [for QUAL_NAME] ... [end]
+   
+   The text within the [for ...] directive and the corresponding [end]
+   is repeated for each element in the sequence referred to by the qualified
+   name in the for directive.  Within the for block this identifiers now 
+   refers to the actual item indexed by this loop iteration.
+
+   [if-any QUAL_NAME [QUAL_NAME2 ...]] ... [else] ... [end]
+
+   Test if any QUAL_NAME value is not None or an empty string or list.  
+   The [else] clause is optional.  CAUTION: Numeric values are converted to
+   string, so if QUAL_NAME refers to a numeric value 0, the then-clause is
+   substituted!
+
+   [if-index INDEX_FROM_FOR odd] ... [else] ... [end]
+   [if-index INDEX_FROM_FOR even] ... [else] ... [end]
+   [if-index INDEX_FROM_FOR first] ... [else] ... [end]
+   [if-index INDEX_FROM_FOR last] ... [else] ... [end]
+   [if-index INDEX_FROM_FOR NUMBER] ... [else] ... [end]
+
+   These five directives work similar to [if-any], but are only useful 
+   within a [for ...]-block (see above).  The odd/even directives are 
+   for example useful to choose different background colors for adjacent rows 
+   in a table.  Similar the first/last directives might be used to
+   remove certain parts (for example "Diff to previous" doesn't make sense,
+   if there is no previous).
+
+   [is QUAL_NAME STRING] ... [else] ... [end]
+   [is QUAL_NAME QUAL_NAME] ... [else] ... [end]
+
+   The [is ...] directive is similar to the other conditional directives
+   above.  But it allows to compare two value references or a value reference
+   with some constant string.
+ 
+"""
+#
+# Copyright (C) 2001-2002 Greg Stein. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without 
+# modification, are permitted provided that the following conditions are 
+# met:
+#
+# * Redistributions of source code must retain the above copyright 
+#   notice, this list of conditions and the following disclaimer. 
+#
+# * Redistributions in binary form must reproduce the above copyright 
+#   notice, this list of conditions and the following disclaimer in the 
+#   documentation and/or other materials provided with the distribution. 
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#
+# This software is maintained by Greg and is available at:
+#    http://viewcvs.sourceforge.net/
+# it is also used by the following projects:
+#    http://edna.sourceforge.net/
+#
+
+import string
+import re
+from types import StringType, IntType, FloatType
+import os
+
+#
+# This regular expression matches three alternatives:
+#   expr: DIRECTIVE | BRACKET | COMMENT
+#   DIRECTIVE: '[' ITEM (whitespace ITEM)* ']
+#   ITEM: STRING | NAME
+#   STRING: '"' (not-slash-or-dquote | '\' anychar)* '"'
+#   NAME: (alphanum | '_' | '-' | '.')+
+#   BRACKET: '[[]'
+#   COMMENT: '[#' not-rbracket* ']'
+#
+# When used with the split() method, the return value will be composed of
+# non-matching text and the two paren groups (DIRECTIVE and BRACKET). Since
+# the COMMENT matches are not placed into a group, they are considered a
+# "splitting" value and simply dropped.
+#
+_item = r'(?:"(?:[^\\"]|\\.)*"|[-\w.]+)'
+_re_parse = re.compile(r'\[(%s(?: +%s)*)\]|(\[\[\])|\[#[^\]]*\]' % (_item, _item))
+
+_re_args = re.compile(r'"(?:[^\\"]|\\.)*"|[-\w.]+')
+
+# block commands and their argument counts
+_block_cmd_specs = { 'if-index':2, 'for':1, 'is':2 }
+_block_cmds = _block_cmd_specs.keys()
+
+# two regular expresssions for compressing whitespace. the first is used to
+# compress any whitespace including a newline into a single newline. the
+# second regex is used to compress runs of whitespace into a single space.
+_re_newline = re.compile('[ \t\r\f\v]*\n\\s*')
+_re_whitespace = re.compile(r'\s\s+')
+
+# this regex is used to substitute arguments into a value. we split the value,
+# replace the relevant pieces, and then put it all back together. splitting
+# will produce a list of: TEXT ( splitter TEXT )*. splitter will be '%' or
+# an integer.
+_re_subst = re.compile('%(%|[0-9]+)')
+
+class Template:
+
+  def __init__(self, fname=None, compress_whitespace=1):
+    self.compress_whitespace = compress_whitespace
+    if fname:
+      self.parse_file(fname)
+
+  def parse_file(self, fname):
+    "fname -> a string object with pathname of file containg an EZT template."
+
+    self.program = self._parse(_FileReader(fname))
+
+  def parse(self, text_or_reader):
+    """Parse the template specified by text_or_reader.
+
+    The argument should be a string containing the template, or it should
+    specify a subclass of ezt.Reader which can read templates.
+    """
+    if not isinstance(text_or_reader, Reader):
+      # assume the argument is a plain text string
+      text_or_reader = _TextReader(text_or_reader)
+    self.program = self._parse(text_or_reader)
+
+  def generate(self, fp, data):
+    ctx = _context()
+    ctx.data = data
+    ctx.for_index = { }
+    self._execute(self.program, fp, ctx)
+
+  def _parse(self, reader, for_names=None, file_args=()):
+    """text -> string object containing the HTML template.
+
+    This is a private helper function doing the real work for method parse.
+    It returns the parsed template as a 'program'.  This program is a sequence
+    made out of strings or (function, argument) 2-tuples.
+
+    Note: comment directives [# ...] are automatically dropped by _re_parse.
+    """
+
+    # parse the template program into: (TEXT DIRECTIVE BRACKET)* TEXT
+    parts = _re_parse.split(reader.text)
+
+    program = [ ]
+    stack = [ ]
+    if not for_names:
+       for_names = [ ]
+
+    for i in range(len(parts)):
+      piece = parts[i]
+      which = i % 3  # discriminate between: TEXT DIRECTIVE BRACKET
+      if which == 0:
+        # TEXT. append if non-empty.
+        if piece:
+          if self.compress_whitespace:
+            piece = _re_whitespace.sub(' ', _re_newline.sub('\n', piece))
+          program.append(piece)
+      elif which == 2:
+        # BRACKET directive. append '[' if present.
+        if piece:
+          program.append('[')
+      elif piece:
+        # DIRECTIVE is present.
+        args = _re_args.findall(piece)
+        cmd = args[0]
+        if cmd == 'else':
+          if len(args) > 1:
+            raise ArgCountSyntaxError(str(args[1:]))
+          ### check: don't allow for 'for' cmd
+          idx = stack[-1][1]
+          true_section = program[idx:]
+          del program[idx:]
+          stack[-1][3] = true_section
+        elif cmd == 'end':
+          if len(args) > 1:
+            raise ArgCountSyntaxError(str(args[1:]))
+          # note: true-section may be None
+          try:
+            cmd, idx, args, true_section = stack.pop()
+          except IndexError:
+            raise UnmatchedEndError()
+          else_section = program[idx:]
+          func = getattr(self, '_cmd_' + re.sub('-', '_', cmd))
+          program[idx:] = [ (func, (args, true_section, else_section)) ]
+          if cmd == 'for':
+            for_names.pop()
+        elif cmd in _block_cmds:
+          if len(args) > _block_cmd_specs[cmd] + 1:
+            raise ArgCountSyntaxError(str(args[1:]))
+          ### this assumes arg1 is always a ref
+          args[1] = _prepare_ref(args[1], for_names, file_args)
+
+          # handle arg2 for the 'is' command
+          if cmd == 'is':
+            args[2] = _prepare_ref(args[2], for_names, file_args)
+          elif cmd == 'for':
+            for_names.append(args[1][0])
+
+          # remember the cmd, current pos, args, and a section placeholder
+          stack.append([cmd, len(program), args[1:], None])
+        elif cmd == 'include':
+          if args[1][0] == '"':
+            include_filename = args[1][1:-1]
+            f_args = [ ]
+            for arg in args[2:]:
+              f_args.append(_prepare_ref(arg, for_names, file_args))
+            program.extend(self._parse(reader.read_other(include_filename),
+                                       for_names,
+                                       f_args))
+          else:
+            if len(args) != 2:
+              raise ArgCountSyntaxError(str(args))
+            program.append((self._cmd_include,
+                            (_prepare_ref(args[1], for_names, file_args),
+                             reader)))
+        elif cmd == 'if-any':
+          f_args = [ ]
+          for arg in args[1:]:
+            f_args.append(_prepare_ref(arg, for_names, file_args))
+          stack.append(['if-any', len(program), f_args, None])
+        else:
+          # implied PRINT command
+          if len(args) > 1:
+            f_args = [ ]
+            for arg in args:
+              f_args.append(_prepare_ref(arg, for_names, file_args))
+            program.append((self._cmd_format, (f_args[0], f_args[1:])))
+          else:
+            program.append((self._cmd_print,
+                            _prepare_ref(args[0], for_names, file_args)))
+
+    if stack:
+      ### would be nice to say which blocks...
+      raise UnclosedBlocksError()
+    return program
+
+  def _execute(self, program, fp, ctx):
+    """This private helper function takes a 'program' sequence as created
+    by the method '_parse' and executes it step by step.  strings are written
+    to the file object 'fp' and functions are called.
+    """
+    for step in program:
+      if isinstance(step, StringType):
+        fp.write(step)
+      else:
+        step[0](step[1], fp, ctx)
+
+  def _cmd_print(self, valref, fp, ctx):
+    value = _get_value(valref, ctx)
+
+    # if the value has a 'read' attribute, then it is a stream: copy it
+    if hasattr(value, 'read'):
+      while 1:
+        chunk = value.read(16384)
+        if not chunk:
+          break
+        fp.write(chunk)
+    else:
+      fp.write(value)
+
+  def _cmd_format(self, (valref, args), fp, ctx):
+    fmt = _get_value(valref, ctx)
+    parts = _re_subst.split(fmt)
+    for i in range(len(parts)):
+      piece = parts[i]
+      if i%2 == 1 and piece != '%':
+        idx = int(piece)
+        if idx < len(args):
+          piece = _get_value(args[idx], ctx)
+        else:
+          piece = '<undef>'
+      fp.write(piece)
+
+  def _cmd_include(self, (valref, reader), fp, ctx):
+    fname = _get_value(valref, ctx)
+    ### note: we don't have the set of for_names to pass into this parse.
+    ### I don't think there is anything to do but document it.
+    self._execute(self._parse(reader.read_other(fname)), fp, ctx)
+
+  def _cmd_if_any(self, args, fp, ctx):
+    "If any value is a non-empty string or non-empty list, then T else F."
+    (valrefs, t_section, f_section) = args
+    value = 0
+    for valref in valrefs:
+      if _get_value(valref, ctx):
+        value = 1
+        break
+    self._do_if(value, t_section, f_section, fp, ctx)
+
+  def _cmd_if_index(self, args, fp, ctx):
+    ((valref, value), t_section, f_section) = args
+    list, idx = ctx.for_index[valref[0]]
+    if value == 'even':
+      value = idx % 2 == 0
+    elif value == 'odd':
+      value = idx % 2 == 1
+    elif value == 'first':
+      value = idx == 0
+    elif value == 'last':
+      value = idx == len(list)-1
+    else:
+      value = idx == int(value)
+    self._do_if(value, t_section, f_section, fp, ctx)
+
+  def _cmd_is(self, args, fp, ctx):
+    ((left_ref, right_ref), t_section, f_section) = args
+    value = _get_value(right_ref, ctx)
+    value = string.lower(_get_value(left_ref, ctx)) == string.lower(value)
+    self._do_if(value, t_section, f_section, fp, ctx)
+
+  def _do_if(self, value, t_section, f_section, fp, ctx):
+    if t_section is None:
+      t_section = f_section
+      f_section = None
+    if value:
+      section = t_section
+    else:
+      section = f_section
+    if section is not None:
+      self._execute(section, fp, ctx)
+
+  def _cmd_for(self, args, fp, ctx):
+    ((valref,), unused, section) = args
+    list = _get_value(valref, ctx)
+    if isinstance(list, StringType):
+      raise NeedSequenceError()
+    refname = valref[0]
+    ctx.for_index[refname] = idx = [ list, 0 ]
+    for item in list:
+      self._execute(section, fp, ctx)
+      idx[1] = idx[1] + 1
+    del ctx.for_index[refname]
+
+def boolean(value):
+  "Return a value suitable for [if-any bool_var] usage in a template."
+  if value:
+    return 'yes'
+  return None
+
+
+def _prepare_ref(refname, for_names, file_args):
+  """refname -> a string containing a dotted identifier. example:"foo.bar.bang"
+  for_names -> a list of active for sequences.
+
+  Returns a `value reference', a 3-Tupel made out of (refname, start, rest), 
+  for fast access later.
+  """
+  # is the reference a string constant?
+  if refname[0] == '"':
+    return None, refname[1:-1], None
+
+  # if this is an include-argument, then just return the prepared ref
+  if refname[:3] == 'arg':
+    try:
+      idx = int(refname[3:])
+    except ValueError:
+      pass
+    else:
+      if idx < len(file_args):
+        return file_args[idx]
+
+  parts = string.split(refname, '.')
+  start = parts[0]
+  rest = parts[1:]
+  while rest and (start in for_names):
+    # check if the next part is also a "for name"
+    name = start + '.' + rest[0]
+    if name in for_names:
+      start = name
+      del rest[0]
+    else:
+      break
+  return refname, start, rest
+
+def _get_value((refname, start, rest), ctx):
+  """(refname, start, rest) -> a prepared `value reference' (see above).
+  ctx -> an execution context instance.
+
+  Does a name space lookup within the template name space.  Active 
+  for blocks take precedence over data dictionary members with the 
+  same name.
+  """
+  if rest is None:
+    # it was a string constant
+    return start
+  if ctx.for_index.has_key(start):
+    list, idx = ctx.for_index[start]
+    ob = list[idx]
+  elif ctx.data.has_key(start):
+    ob = ctx.data[start]
+  else:
+    raise UnknownReference(refname)
+
+  # walk the rest of the dotted reference
+  for attr in rest:
+    try:
+      ob = getattr(ob, attr)
+    except AttributeError:
+      raise UnknownReference(refname)
+
+  # make sure we return a string instead of some various Python types
+  if isinstance(ob, IntType) or isinstance(ob, FloatType):
+    return str(ob)
+  if ob is None:
+    return ''
+
+  # string or a sequence
+  return ob
+
+
+class _context:
+  """A container for the execution context"""
+
+
+class Reader:
+  "Abstract class which allows EZT to detect Reader objects."
+
+class _FileReader(Reader):
+  """Reads templates from the filesystem."""
+  def __init__(self, fname):
+    self.text = open(fname, 'rb').read()
+    self._dir = os.path.dirname(fname)
+  def read_other(self, relative):
+    return _FileReader(os.path.join(self._dir, relative))
+
+class _TextReader(Reader):
+  """'Reads' a template from provided text."""
+  def __init__(self, text):
+    self.text = text
+  def read_other(self, relative):
+    raise BaseUnavailableError()
+
+
+class EZTException(Exception):
+  """Parent class of all EZT exceptions."""
+
+class ArgCountSyntaxError(EZTException):
+  """A bracket directive got the wrong number of arguments."""
+
+class UnknownReference(EZTException):
+  """The template references an object not contained in the data dictionary."""
+
+class NeedSequenceError(EZTException):
+  """The object dereferenced by the template is no sequence (tuple or list)."""
+
+class UnclosedBlocksError(EZTException):
+  """This error may be simply a missing [end]."""
+
+class UnmatchedEndError(EZTException):
+  """This error may be caused by a misspelled if directive."""
+
+class BaseUnavailableError(EZTException):
+  """Base location is unavailable, which disables includes."""
+
+
+# --- standard test environment ---
+def test_parse():
+  assert _re_parse.split('[a]') == ['', '[a]', None, '']
+  assert _re_parse.split('[a] [b]') == \
+         ['', '[a]', None, ' ', '[b]', None, '']
+  assert _re_parse.split('[a c] [b]') == \
+         ['', '[a c]', None, ' ', '[b]', None, '']
+  assert _re_parse.split('x [a] y [b] z') == \
+         ['x ', '[a]', None, ' y ', '[b]', None, ' z']
+  assert _re_parse.split('[a "b" c "d"]') == \
+         ['', '[a "b" c "d"]', None, '']
+  assert _re_parse.split(r'["a \"b[foo]" c.d f]') == \
+         ['', '["a \\"b[foo]" c.d f]', None, '']
+
+def _test(argv):
+  import doctest, ezt           
+  verbose = "-v" in argv
+  return doctest.testmod(ezt, verbose=verbose)
+
+if __name__ == "__main__":
+  # invoke unit test for this module:
+  import sys
+  sys.exit(_test(sys.argv)[0])

Propchange: gump/branches/Gump3/webgump/lib/python/webgump/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Apr  7 09:53:11 2005
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo

Added: gump/branches/Gump3/webgump/lib/python/webgump/__init__.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/lib/python/webgump/__init__.py?view=auto&rev=160420
==============================================================================
    (empty)

Propchange: gump/branches/Gump3/webgump/lib/python/webgump/controllers/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Apr  7 09:53:11 2005
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo

Added: gump/branches/Gump3/webgump/lib/python/webgump/controllers/__init__.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/lib/python/webgump/controllers/__init__.py?view=auto&rev=160420
==============================================================================
    (empty)

Added: gump/branches/Gump3/webgump/lib/python/webgump/controllers/home.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/lib/python/webgump/controllers/home.py?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/lib/python/webgump/controllers/home.py (added)
+++ gump/branches/Gump3/webgump/lib/python/webgump/controllers/home.py Thu Apr  7 09:53:11 2005
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+from webgump.util.template import TemplateEngine
+from gump.util.mysql import Database
+from webgump.util.log import Logger
+
+def view(req, settings):
+    req.content_type = "text/html"
+    
+    dblog = Logger(req, name="webgump.db")
+    db = Database(dblog,settings["db_host"], settings["db_user"],
+                  settings["db_password"],settings["db_name"])
+    
+    (affected, rows) = db.execute('SELECT * FROM test;')
+    content = []
+    for row in rows:
+        content.append(row["content"])
+    
+    settings["content"] = content
+    settings["log"] = Logger(req, name="webgump.ezt")
+    template = "view"
+    template_engine = TemplateEngine(settings['TEMPLATE_ROOT'])
+    try:
+        template_engine.render_template(template, req, settings)
+    except:
+        req.write("<p><strong>Error occurred rendering template '%s':</strong></p>\n" % template)
+        raise

Propchange: gump/branches/Gump3/webgump/lib/python/webgump/util/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Apr  7 09:53:11 2005
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo

Added: gump/branches/Gump3/webgump/lib/python/webgump/util/__init__.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/lib/python/webgump/util/__init__.py?view=auto&rev=160420
==============================================================================
    (empty)

Added: gump/branches/Gump3/webgump/lib/python/webgump/util/log.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/lib/python/webgump/util/log.py?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/lib/python/webgump/util/log.py (added)
+++ gump/branches/Gump3/webgump/lib/python/webgump/util/log.py Thu Apr  7 09:53:11 2005
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+import time
+import sys
+
+from mod_python import apache
+
+# log levels
+DEBUG = apache.APLOG_DEBUG      #7
+INFO = apache.APLOG_INFO        #6
+WARNING = apache.APLOG_WARNING  #4
+ERROR = apache.APLOG_ERR        #3
+CRITICAL = apache.APLOG_CRIT    #2
+NONE = -1000
+
+LOG_LEVEL_NAMES = {
+    DEBUG:'DEBUG',
+    INFO:'INFO',
+    WARNING:'WARNING',
+    ERROR:'ERROR',
+    CRITICAL:'CRITICAL'
+}
+
+class Logger:
+    """Simple logger similar to PEP 249 that logs to an apache error log."""
+    def __init__(self, req=None, level=DEBUG, printLevel=ERROR, name=None):
+        self.req = req
+        if req:
+            self.error_func = req.log_error
+        else:
+            self.error_func = apache.log_error
+        self.level = level
+        self.printLevel = printLevel
+        self.name = name
+
+
+    def log(self, level, msg):
+        try:
+            logToWebPage = self.req and level <= self.printLevel
+            if logToWebPage: self.req.write("<pre>\n")
+            
+            if self.name:
+                for line in msg.split("\n"):
+                    self.error_func("[%s] %s" % (self.name, line), level)
+                    if logToWebPage: self.req.write("[%s] %s: %s\n" % (self.name, LOG_LEVEL_NAMES[level], line))
+            else:
+                for line in msg.split("\n"):
+                    self.error_func(msg, level)
+                    if logToWebPage: self.req.write("%s: %s\n" % (LOG_LEVEL_NAMES[level], line))
+                    
+            if logToWebPage: self.req.write("</pre>\n")
+        except IOError:
+            # probably a client is "gone"
+            pass
+    
+    def debug(self, msg):
+        if self.level >= DEBUG:
+            self.log(DEBUG, msg);
+    
+    def info(self, msg):
+        if self.level >= INFO:
+            self.log(INFO, msg);
+    
+    def warning(self, msg):
+        if self.level >= WARNING:
+            self.log(WARNING, msg);
+    
+    def error(self, msg):
+        if self.level >= ERROR:
+            self.log(ERROR, msg);
+    
+    def exception(self, msg):
+        info = sys.exc_info()
+        import traceback
+        from StringIO import StringIO
+        buf = StringIO()
+        traceback.print_exception( info[0], info[1], info[2], file=buf)
+        self.error("%s\n%s" % (msg, buf.getvalue()))
+
+    def critical(self, msg):
+        if self.level >= CRITICAL:
+            self.log(CRITICAL, msg);
+

Added: gump/branches/Gump3/webgump/lib/python/webgump/util/template.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/lib/python/webgump/util/template.py?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/lib/python/webgump/util/template.py (added)
+++ gump/branches/Gump3/webgump/lib/python/webgump/util/template.py Thu Apr  7 09:53:11 2005
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+import os
+from ezt import Template
+
+class TemplateEngine:
+    def __init__(self, template_root):
+        self.template_root = template_root
+
+    def render_template(self, template, target, data):
+        if isinstance(template, Template):
+            template.generate(target, data)
+        else:
+            self.get_template(template).generate(target, data)
+
+    def get_template(self, name):
+        templatefile = os.path.abspath(os.path.join(self.template_root, "%s.ezt" % name))
+        template = Template(templatefile)
+        return template

Propchange: gump/branches/Gump3/webgump/logs/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Apr  7 09:53:11 2005
@@ -0,0 +1 @@
+*

Added: gump/branches/Gump3/webgump/sql/webgump.sql
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/sql/webgump.sql?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/sql/webgump.sql (added)
+++ gump/branches/Gump3/webgump/sql/webgump.sql Thu Apr  7 09:53:11 2005
@@ -0,0 +1,23 @@
+# CocoaMySQL dump
+# Version 0.5
+# http://cocoamysql.sourceforge.net
+#
+# Host: localhost (MySQL 4.0.23-standard)
+# Database: lsdblog
+# Generation Time: 2005-04-05 17:37:25 +0200
+# ************************************************************
+
+# Dump of table test
+# ------------------------------------------------------------
+
+DROP TABLE IF EXISTS `test`;
+
+CREATE TABLE `test` (
+  `id` int(11) NOT NULL auto_increment,
+  `content` text,
+  PRIMARY KEY  (`id`)
+) TYPE=MyISAM;
+
+INSERT INTO `test` (`id`,`content`) VALUES ("1","mwuhahahaha!");
+
+

Added: gump/branches/Gump3/webgump/templates/view.ezt
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/templates/view.ezt?view=auto&rev=160420
==============================================================================
--- gump/branches/Gump3/webgump/templates/view.ezt (added)
+++ gump/branches/Gump3/webgump/templates/view.ezt Thu Apr  7 09:53:11 2005
@@ -0,0 +1,14 @@
+<html>
+    <head>
+        <title>[PAGE_TITLE]</title>
+    </head>
+    <body>
+    
+    <h1>[PAGE_TITLE]</h1>
+    
+[for content]
+  <pre>Piece of content: [content]</pre>
+[end]
+
+    </body>
+</html>



Mime
View raw message