Basic URL dispatch and controller functionality

master
Dustin C. Hatch 2011-03-13 16:49:54 -05:00
parent 655f3a8a5d
commit 7d355f3de5
2 changed files with 96 additions and 0 deletions

25
src/milla/controller.py Normal file
View File

@ -0,0 +1,25 @@
'''Module milla.controller
Please give me a docstring!
:Created: Mar 13, 2011
:Author: dustin
:Updated: $Date$
:Updater: $Author$
'''
import webob
import webob.exc
class Controller(object):
def __call__(self, environ, start_response):
request = webob.Request(environ)
try:
response = getattr(self, request.method)(request, **request.urlvars)
except AttributeError:
return webob.exc.HTTPMethodNotAllowed()(environ, start_response)
except webob.exc.WSGIHTTPException as e:
return e(environ, start_response)
start_response(response.status, response.headerlist)
return response.app_iter

71
src/milla/routing.py Normal file
View File

@ -0,0 +1,71 @@
'''URL router
TODO: Document me!
:Created: Mar 13, 2011
:Author: dustin
:Updated: $Date$
:Updater: $Author$
'''
import re
import sys
import urllib
import webob
class Router(object):
template_re = re.compile(r'\{(\w+)(?::([^}]+))?\}')
def __init__(self):
self.routes = []
def __call__(self, environ, start_response):
request = webob.Request(environ)
for regex, controller, vars in self.routes:
match = regex.match(request.path_info)
if match:
request.urlvars = match.groupdict()
request.urlvars.update(vars)
return controller(environ, start_response)
return webob.exc.HTTPNotFound()(environ, start_response)
def _compile_template(self, template):
regex = ''
last_pos = 0
for match in self.template_re.finditer(template):
regex += re.escape(template[last_pos:match.start()])
var_name = match.group(1)
expr = match.group(2) or '[^/]+'
expr = '(?P<%s>%s)' % (var_name, expr)
regex += expr
last_pos = match.end()
regex += re.escape(template[last_pos:])
regex = '^%s$' % regex
return re.compile(regex)
def _import_controller(self, name):
module_name, func_name = name.split(':', 1)
__import__(module_name)
module = sys.modules[module_name]
func = getattr(module, func_name)
return func
def add_route(self, template, controller, **vars):
if isinstance(controller, basestring):
controller = self._import_controller(controller)
self.routes.append((self._compile_template(template),
controller, vars))
class Generator(object):
def __init__(self, request):
self.request = request
def generate(self, *segments, **vars):
base_url = self.request.application_url
path = '/'.join(str(s) for s in segments)
if not path.startswith('/'):
path = '/' + path
if vars:
path += '?' + urllib.urlencode(vars)
return base_url + path