diff --git a/src/milla/controller.py b/src/milla/controller.py new file mode 100644 index 0000000..fba6368 --- /dev/null +++ b/src/milla/controller.py @@ -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 diff --git a/src/milla/routing.py b/src/milla/routing.py new file mode 100644 index 0000000..77daa9f --- /dev/null +++ b/src/milla/routing.py @@ -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