From 5c2a12d9128f9012a14081ef188cac86bd5160bd Mon Sep 17 00:00:00 2001 From: blackbird Date: Fri, 22 Jun 2007 01:38:49 +0200 Subject: [PATCH] [svn] added missing module --- lodgeit/_magic.py | 198 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 lodgeit/_magic.py diff --git a/lodgeit/_magic.py b/lodgeit/_magic.py new file mode 100644 index 0000000..25a24be --- /dev/null +++ b/lodgeit/_magic.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +""" + lodgeit._magic + ~~~~~~~~~~~~~~ + + Psssst. (actually this module exists because lodgeit was designed with + the old werkzeug routing system and i was to lazy to update this) + + :copyright: 2007 by Armin Ronacher. + :license: BSD +""" +import urlparse +import re + + +__all__ = ['Map', 'root', 'Var', 'Int', 'Bool'] + + +class Partial(object): + + def __init__(self, builder, trace): + self.trace = trace + self.builder = builder + + def __div__(self, other): + self.trace += ['/', other] + return Partial(self.builder, self.trace) + + def __add__(self, other): + self.trace.append(other) + return Partial(self.builder, self.trace) + + def __sub__(self, other): + self.trace += ['-', other] + return Partial(self.builder, self.trace, other) + + def __gt__(self, controller): + return Route(self.builder, self.trace, controller) + + +class Var(object): + + def __init__(self, name): + self.name = name + + def get_regex(self): + return '[^/]+' + + def to_python(self, value): + return value + + def to_unicode(self, value): + return unicode(value) + + +class Int(Var): + + def get_regex(self): + return '\d+' + + def to_python(self, value): + return int(value) + + def to_unicode(self, value): + return unicode(value) + + +class Bool(Var): + + def get_regex(self): + return 'yes|no' + + def to_python(self, value): + return value == 'yes' + + def to_unicode(self, value): + return value and 'yes' or 'no' + + +class Builder(object): + + def __gt__(self, controller): + return Route(self, [], controller) + + def __div__(self, other): + return Partial(self, [other]) + + def finish(self, rule): + pass + + +class AssignmentBuilder(Builder): + + def __init__(self, map): + self.map = map + + def finish(self, route): + self.map.add_route(route) + + +class Route(object): + + def __init__(self, builder, trace, controller): + self.builder = builder + self.controller = controller + self.converters = {} + self.arguments = set() + self._bits = [] + + tmp = [] + for item in trace: + if isinstance(item, Var): + tmp.append('(?P<%s>%s)' % ( + item.name, + item.get_regex() + )) + self.converters[item.name] = item + self._bits.append((True, item.name)) + self.arguments.add(item.name) + else: + item = unicode(item) + tmp.append(re.escape(item)) + self._bits.append((False, item)) + + self.regex = re.compile('^%s/?$(?u)' % u''.join(tmp)) + self.builder.finish(self) + + def test(self, path): + m = self.regex.search(path) + if m is not None: + result = {} + for name, value in m.groupdict().iteritems(): + result[str(name)] = self.converters[name].to_python(value) + return result + + def build(self, values): + tmp = [] + for is_dynamic, data in self._bits: + if is_dynamic: + tmp.append(self.converters[data].to_unicode(values[data])) + else: + tmp.append(data) + return u''.join(tmp) + + +class Map(object): + """ + URL Mapping. + """ + + def __init__(self, *routes): + self.routes = [] + for route in routes: + self.add_route(route) + + def add_route(self, route): + if isinstance(route, Route): + self.routes.append(route) + elif isinstance(route, Partial): + self.routes.append(route > None) + else: + raise TypeError('invalid route %r' % route.__class__.__name__) + + def test(self, path): + path = path.lstrip('/') + for route in self.routes: + rv = route.test(path) + if rv is not None: + return route.controller, rv + + def build(self, environ, controller, values): + valueset = set(values.keys()) + for route in self.routes: + if route.controller == controller and \ + route.arguments.issubset(valueset): + relative_url = route.build(values) + script_name = environ.get('SCRIPT_NAME') or '/' + if not script_name.endswith('/'): + script_name += '/' + return unicode(urlparse.urljoin(script_name, relative_url)) + raise TypeError('no matching url found') + + +root = Builder() + + +def automap(f): + """ + Decorator for fany url maps. + """ + builder = AssignmentBuilder(Map()) + (type(f)(f.func_code, { + 'root': builder, + 'int': Int, + 'str': Var, + 'bool': Bool + }))() + return builder.map