Examples

We start with a simple helloworld example, than add a bit more modularity in the example server time. Before we proceed with examples below let’s setup a virtualenv environment:

$ virtualenv env
$ env/bin/easy_install wheezy.routing

Hello World

helloworld.py shows you how to use Wheezy Routing in a pretty simple WSGI application:

import sys

from wheezy.routing import PathRouter

if sys.version_info[0] >= 3:
    def ntob(n, encoding):
        return n.encode(encoding)
else:
    def ntob(n, encoding):
        return n


def hello_world(environ, start_response):
    start_response('200 OK', [
        ('Content-Type', 'text/html')
    ])
    yield ntob('Hello World!', 'utf-8')


def not_found(environ, start_response):
    start_response('404 Not Found', [
        ('Content-Type', 'text/html')
    ])
    yield ntob('', 'utf-8')


r = PathRouter()
r.add_routes([
    ('/', hello_world),
    ('/{any}', not_found)
])


def main(environ, start_response):
    handler, kwargs = r.match(environ['PATH_INFO'])
    return handler(environ, start_response)

if __name__ == '__main__':
    from wsgiref.simple_server import make_server
    try:
        print('Visit http://localhost:8080/')
        make_server('', 8080, main).serve_forever()
    except KeyboardInterrupt:
        pass
    print('\nThanks!')

Let’s have a look through each line in this application. First of all we import PathRouter that is actually just an exporting name for PathRouter:

from wheezy.routing import PathRouter

Next we create a pretty simple WSGI handler to provide a response.



def hello_world(environ, start_response):
    start_response('200 OK', [
        ('Content-Type', 'text/html')

In addition let’s add a handler for the ‘not found’ response.



def not_found(environ, start_response):
    start_response('404 Not Found', [
        ('Content-Type', 'text/html')

The declaration and mapping of patterns to handlers follows. We create an instance of PathRouter class and pass it a mapping, that in this particular case is a tuple of two values: pattern and handler.



r = PathRouter()
r.add_routes([
    ('/', hello_world),

The first pattern '/' will match only the root path of the request (it is finishing route in the match chain). The second pattern '/{any}' is a curly expression, that is translated to regular expression, that ultimately matches any path and is a finishing route as well.

main function serves as WSGI application entry point. The only thing we do here is to get a value of WSGI environment variable PATH_INFO (the remainder of the request URL’s path) and pass it to the router match() method. In return we get handler and kwargs (parameters discovered from matching rule, that we ignore for now).



def main(environ, start_response):

The rest in the helloworld application launches a simple wsgi server. Try it by running:

$ python helloworld.py

Visit http://localhost:8080/.

Server Time

The server time application consists of two screens. The first one has a link to the second that shows the time on the server. The second page will be mapped as a separate application with its own routing. The design used in this sample is modular. Let’s start with config module. The only thing we need here is an instance of PathRouter.

from wheezy.routing import PathRouter


router = PathRouter()

The view module is pretty straight: a welcome view with a link to server_time view. The server time page returns the server time. And finally a catch all not_found handler to display http 404 error, page not found.

from datetime import datetime

from config import router as r


def welcome(environ, start_response):
    start_response('200 OK', [
        ('Content-type', 'text/html')
    ])
    return ["Welcome!  <a href='%s'>Server Time</a>" %
            r.path_for('now')]


def server_time(environ, start_response):
    start_response('200 OK', [
        ('Content-type', 'text/plain')
    ])
    return ["The server time is: %s" % datetime.now()]


def not_found(environ, start_response):
    start_response("404 Not Found", [
        ('Content-Type', 'text/plain')
    ])
    return ["Not Found: " + environ['routing.kwargs']['url']]

So what is interesting in the welcome view is a way how we get a url for server_time view.

    return ["Welcome!  <a href='%s'>Server Time</a>" %
            r.path_for('now')]

The name now was used during url mapping as you can see below (module urls):

from wheezy.routing import url
from views import welcome, server_time, not_found

server_urls = [
    url('time', server_time, name='now')
]

all_urls = [
    ('', welcome),
    ('server/', server_urls)
]

all_urls += [
    url('{url:any}', not_found)
]

server_urls are then included under the parent path server/, so anything that starts with the path server/ will be directed to the server_urls url mapping. Lastly we add a curly expression that maps any url match to our not_found handler.

We combine that all together in app module.

from config import router
from urls import all_urls


router.add_routes(all_urls)


def main(environ, start_response):
    handler, kwargs = router.match(environ['PATH_INFO'].lstrip('/'))
    environ['routing.kwargs'] = kwargs
    return map(lambda chunk: chunk.encode('utf8'),
               handler(environ, start_response))

if __name__ == '__main__':
    from wsgiref.simple_server import make_server
    try:
        print('Visit http://localhost:8080/')
        make_server('', 8080, main).serve_forever()
    except KeyboardInterrupt:
        pass
    print('\nThanks!')

Try it by running:

$ python app.py

Visit http://localhost:8080/.