From 39fccbbfbceacaf1b3d5fb6f03a07fbe4d861969 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 6 Aug 2008 03:30:40 +0000 Subject: - Small url dispatch overhaul: the ``connect`` method of the ``urldispatch.RoutesMapper`` object now accepts a keyword parameter named ``context_factory``. If this parameter is supplied, it must be a callable which returns an instance. This instance is used as the context for the request when a route is matched. - The registration of a RoutesModelTraverser no longer needs to be performed by the application; it's in the bfg ZCML now. --- repoze/bfg/urldispatch.py | 58 +++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 19 deletions(-) (limited to 'repoze/bfg/urldispatch.py') diff --git a/repoze/bfg/urldispatch.py b/repoze/bfg/urldispatch.py index 9bdb1e5fa..434a2aa57 100644 --- a/repoze/bfg/urldispatch.py +++ b/repoze/bfg/urldispatch.py @@ -1,33 +1,34 @@ from zope.interface import implements from zope.interface import classProvides +from zope.interface import alsoProvides from routes import Mapper from routes import request_config -from repoze.bfg.interfaces import IURLDispatchModel +from repoze.bfg.interfaces import IRoutesContext from repoze.bfg.interfaces import ITraverserFactory from repoze.bfg.interfaces import ITraverser -class RoutesModel(object): - implements(IURLDispatchModel) +_marker = () + +class RoutesContext(object): def __init__(self, **kw): self.__dict__.update(kw) class RoutesMapper(object): - """ The RoutesMapper is a wrapper for the ``get_root`` callable - passed in to the repoze.bfg Router at initialization time. When - it is instantiated, it wraps the get_root of an application in - such a way that the `Routes + """ The ``RoutesMapper`` is a wrapper for the ``get_root`` + callable passed in to the repoze.bfg ``Router`` at initialization + time. When it is instantiated, it wraps the get_root of an + application in such a way that the `Routes `_ engine has the 'first crack' at resolving the current request URL to a repoze.bfg view. If the ``RoutesModelTraverser`` is configured in your application's configure.zcml, any view that claims it is 'for' the - interface ``repoze.bfg.interfaces.IURLDispatchModel`` will be - called if its *name* matches the Routes 'controller' name for the - match. It will be passed a context object that has attributes - that match the Routes match arguments dictionary keys. If no - Routes route matches the current request, the 'fallback' get_root - is called.""" + interface ``repoze.bfg.interfaces.IRoutesContext`` will be called + if its *name* matches the Routes 'controller' name for the match. + It will be passed a context object that has attributes that match + the Routes match arguments dictionary keys. If no Routes route + matches the current request, the 'fallback' get_root is called.""" def __init__(self, get_root): self.get_root = get_root self.mapper = Mapper(controller_scan=None, directory=None, @@ -42,32 +43,51 @@ class RoutesMapper(object): path = environ.get('PATH_INFO', '/') args = self.mapper.match(path) if args: + context_factory = args.get('context_factory', _marker) + if context_factory is _marker: + context_factory = RoutesContext + else: + args = args.copy() + del args['context_factory'] config = request_config() config.mapper = self.mapper config.mapper_dict = args config.host = environ.get('HTTP_HOST', environ['SERVER_NAME']) config.protocol = environ['wsgi.url_scheme'] config.redirect = None - model = RoutesModel(**args) - return model + context = context_factory(**args) + alsoProvides(context, IRoutesContext) + return context + # fall back to original get_root return self.get_root(environ) def connect(self, *arg, **kw): """ Add a route to the Routes mapper associated with this request. This method accepts the same arguments as a Routes - *Mapper* object""" + *Mapper* object. One difference exists: if the + ``context_factory`` is passed in with a value as a keyword + argument, this callable will be called when a model object + representing the ``context``` for the request needs to be + constructed. It will be called with the (all-keyword) + arguments supplied by the Routes mapper's ``match`` method for + this route, and should return an instance of a class. If + ``context_factory`` is not supplied in this way for a route, a + default context factory (the ``RoutesContext`` class) will be + used. The interface ``repoze.bfg.interfaces.IRoutesContext`` + will always be tacked on to the context instance in addition + to whatever interfaces the context instance already supplies.""" self.mapper.connect(*arg, **kw) class RoutesModelTraverser(object): classProvides(ITraverserFactory) implements(ITraverser) - def __init__(self, model, request): - self.model = model + def __init__(self, context, request): + self.context = context self.request = request def __call__(self, environ): - return self.model, self.model.controller, '' + return self.context, self.context.controller, '' -- cgit v1.2.3