summaryrefslogtreecommitdiff
path: root/repoze/bfg/urldispatch.py
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-06-24 19:23:43 +0000
committerChris McDonough <chrism@agendaless.com>2009-06-24 19:23:43 +0000
commit05c02322f5a09c14f49c529d6fd885153e52c66f (patch)
treec09c43dc7b82d6cc475648c33313d1c1e495311e /repoze/bfg/urldispatch.py
parentaedb399ccb4da1d055163708894f690bb96685c0 (diff)
downloadpyramid-05c02322f5a09c14f49c529d6fd885153e52c66f.tar.gz
pyramid-05c02322f5a09c14f49c529d6fd885153e52c66f.tar.bz2
pyramid-05c02322f5a09c14f49c529d6fd885153e52c66f.zip
Merge noroutes branch to trunk.
Diffstat (limited to 'repoze/bfg/urldispatch.py')
-rw-r--r--repoze/bfg/urldispatch.py129
1 files changed, 89 insertions, 40 deletions
diff --git a/repoze/bfg/urldispatch.py b/repoze/bfg/urldispatch.py
index 0281b52b3..497d3980e 100644
--- a/repoze/bfg/urldispatch.py
+++ b/repoze/bfg/urldispatch.py
@@ -1,53 +1,102 @@
-from routes import Mapper
-from routes import request_config
+import re
_marker = object()
-class RoutesRootFactory(Mapper):
- def __init__(self, default_root_factory, **kw):
+class Route(object):
+ def __init__(self, name, matcher, generator, factory):
+ self.name = name
+ self.matcher = matcher
+ self.generator = generator
+ self.factory = factory
+
+ def match(self, path):
+ return self.matcher(path)
+
+ def generate(self, kw):
+ return self.generator(kw)
+
+class RoutesRootFactory(object):
+ def __init__(self, default_root_factory):
self.default_root_factory = default_root_factory
- kw['controller_scan'] = None
- kw['always_scan'] = False
- kw['directory'] = None
- kw['explicit'] = True
- Mapper.__init__(self, **kw)
- self._regs_created = False
+ self.routelist = []
+ self.routes = {}
def has_routes(self):
- return bool(self.matchlist)
+ return bool(self.routelist)
- def connect(self, *arg, **kw):
- result = Mapper.connect(self, *arg, **kw)
- route = self.matchlist[-1]
- route._factory = None # overridden by ZCML
- return result
+ def connect(self, name, path, factory=None):
+ matcher, generator = _compile_route(path)
+ route = Route(name, matcher, generator, factory)
+ self.routelist.append(route)
+ self.routes[name] = route
+ return route
+
+ def generate(self, name, kw):
+ return self.routes[name].generate(kw)
def __call__(self, environ):
- if not self._regs_created:
- self.create_regs([])
- self._regs_created = True
path = environ.get('PATH_INFO', '/')
- self.environ = environ # sets the thread local
- match = self.routematch(path)
- if match:
- args, route = match
- else:
- args = None
- if isinstance(args, dict): # might be an empty dict
- args = args.copy()
- config = request_config()
- config.mapper = self
- config.mapper_dict = args
- config.host = environ.get('HTTP_HOST', environ['SERVER_NAME'])
- config.protocol = environ['wsgi.url_scheme']
- config.redirect = None
- environ['wsgiorg.routing_args'] = ((), args)
- environ['bfg.routes.route'] = route
- environ['bfg.routes.matchdict'] = args
- adhoc_attrs = environ.setdefault('webob.adhoc_attrs', {})
- adhoc_attrs['matchdict'] = args
- factory = route._factory or self.default_root_factory
- return factory(environ)
+ for route in self.routelist:
+ match = route.match(path)
+ if match is not None:
+ environ['wsgiorg.routing_args'] = ((), match)
+ environ['bfg.routes.route'] = route
+ environ['bfg.routes.matchdict'] = match
+ adhoc_attrs = environ.setdefault('webob.adhoc_attrs', {})
+ adhoc_attrs['matchdict'] = match
+ factory = route.factory or self.default_root_factory
+ return factory(environ)
return self.default_root_factory(environ)
+# stolen from bobo and modified
+route_re = re.compile(r'(/:[a-zA-Z]\w*)')
+def _compile_route(route):
+ if not route.startswith('/'):
+ route = '/' + route
+ star = None
+ if '*' in route:
+ route, star = route.rsplit('*', 1)
+ pat = route_re.split(route)
+ pat.reverse()
+ rpat = []
+ gen = []
+ prefix = pat.pop()
+ if prefix:
+ rpat.append(re.escape(prefix))
+ gen.append(prefix)
+ while pat:
+ name = pat.pop()
+ name = name[2:]
+ gen.append('/%%(%s)s' % name)
+ name = '/(?P<%s>[^/]*)' % name
+ rpat.append(name)
+ s = pat.pop()
+ if s:
+ rpat.append(re.escape(s))
+ gen.append(s)
+
+ if star:
+ rpat.append('(?P<%s>.*?)' % star)
+ gen.append('%%(%s)s' % star)
+
+ pattern = ''.join(rpat) + '$'
+
+ match = re.compile(pattern).match
+ def matcher(path):
+ m = match(path)
+ if m is None:
+ return m
+ return dict(item for item in m.groupdict().iteritems()
+ if item[1] is not None)
+
+ gen = ''.join(gen)
+ def generator(dict):
+ newdict = {}
+ for k, v in dict.items():
+ if isinstance(v, unicode):
+ v = v.encode('utf-8')
+ newdict[k] = v
+ return gen % newdict
+
+ return matcher, generator