werkzeug

Werkzeug is a collection
of WSGI utility modules.
The werkzeug web site
presents (on welcome page click on nutshell to see the code)
a very simple demo application, that is described as:

A tiny WSGI application (about 50 lines of code) that
just uses werkzeug’s routing system and uses template names as
endpoints. These templates are then loaded with Mako,
rendered and returned as responses
.

It is really trivial to make an equivalent application that uses
Evoque instead. The changes to the two concerned files
werkzeug_nutshell.py and
say_hello.html, shown further below,
are superficial:

  • Initialize an Evoque domain, thus implicitly also defining
    the default template collection.
  • Evoque’ing the template is identical, except for a different method name.
  • In the sample say_hello.html template, remove the unnecessary
    h filter (Evoque automatically quotes all incoming unquoted data).
  • Make the sample say_hello.html template a valid HTML document 😉

werkzeug_nutshell.py

!/usr/bin/env python
# -*- coding: utf-8 -*-
from os import path
from werkzeug import BaseRequest, BaseResponse, \
        SharedDataMiddleware, responder
from werkzeug.routing import Map, Rule
from werkzeug.exceptions import HTTPException
from evoque.domain import Domain

# path for this file's folder 
# used as root for default template collection
root_path = path.abspath(path.dirname(__file__))

# create an evoque template domain (and default collection) 
domain = Domain(root_path)

# create the URL map. The endpoints are template names without the 
# .html extension, to be rendered by the `dispatch_request` function.
url_map = Map([
    Rule('/', endpoint='index'),
    Rule('/hello/', defaults={'name': 'World'}, endpoint='say_hello'),
    Rule('/hello/<name>', endpoint='say_hello'),
    Rule('/shared/<file>', endpoint='shared', build_only=True)
])


def dispatch_request(environ, start_response):
    """
    A simple dispatch function that (if decorated with responder) 
    is the complete WSGI application that does the template  
    rendering and error handling.
    """
    # first we bind the url map to the current request
    adapter = url_map.bind_to_environ(environ)
    # then we wrap all the calls in a try/except for HTTP exceptions
    try:
        # get the endpoint and the values (variable or parts)
        # of the adapter.  If the match fails it raises a NotFound
        # exception which is a HTTPException which we catch
        endpoint, values = adapter.match()
        
        # create a new request object for the incoming WSGI environ
        request = BaseRequest(environ)
        
        # create an empty response object with the correct mimetype.
        response = BaseResponse(mimetype='text/html')
        
        # get the template and render it. Pass some useful stuff to 
        # the template (request and response objects, the current  
        # url endpoint, the url values and a url_for function which 
        # can be used to generate urls
        template = domain.get_template(endpoint + '.html')
        response.write(template.evoque(
            request=request,
            response=response,
            endpoint=endpoint,
            url_for=lambda e, **v: adapter.build(e, v),
            url_values=values
        ))
        
        # return the response
        return response
    
    except HTTPException, e:
        # if an http exception is caught we can return it as  
        # response because those exceptions render standard error 
        # messages under wsgi
        return e


# finish the wsgi application by wrapping it in a middleware that 
# serves static files in the shared folder and wrap the dispatch 
# function in a responder so that the return value is called as 
# wsgi application.
application = SharedDataMiddleware(responder(dispatch_request), {
    '/shared':  path.join(root_path, 'shared')
})


# if the script is called from the command line start the 
# application with the development server on localhost:4000
if __name__ == '__main__':
    from werkzeug import run_simple
    run_simple('localhost', 4000, application)

say_hello.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<title>Hello World Fun!</title>
</head><body>
<h1>Hello ${url_values['name']}!</h1>
<p><a href="${url_for('index')}">back to the index</a></p>
</body></html>