From 29e01279ff0b13623a6b1b769351632f12bafb35 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 16 May 2009 18:48:02 +0000 Subject: - The ``RoutesMapper`` class in ``repoze.bfg.urldispatch`` has been removed, as well as its documentation. It had been deprecated since 0.6.3. Code in ``repoze.bfg.urldispatch.RoutesModelTraverser`` which catered to it has also been removed. - The semantics of the ``route`` ZCML directive have been simplified. Previously, it was assumed that to use a route, you wanted to map a route to an externally registered view. The new ``route`` directive instead has a ``view`` attribute which is required, specifying the dotted path to a view callable. When a route directive is processed, a view is *registered* using the name attribute of the route directive as its name and the callable as its value. The ``view_name`` and ``provides`` attributes of the ``route`` directive are therefore no longer used. Effectively, if you were previously using the ``route`` directive, it means you must change a pair of ZCML directives that look like this:: To a ZCML directive that looks like this:: In other words, to make old code work, remove the ``view`` directives that were only there to serve the purpose of backing ``route`` directives, and move their ``view=`` attribute into the ``route`` directive itself. This change also necessitated that the ``name`` attribute of the ``route`` directive is now required. If you were previously using ``route`` directives without a ``name`` attribute, you'll need to add one (the name is arbitrary, but must be unique among all ``route`` and ``view`` statements). The ``provides`` attribute of the ``route`` directive has also been removed. This directive specified a sequence of interface types that the generated context would be decorated with. Since route views are always generated now for a single interface (``repoze.bfg.IRoutesContext``) as opposed to being looked up arbitrarily, there is no need to decorate any context to ensure a view is found. - The Routes ``Route`` object used to resolve the match is now put into the environment as ``bfg.route`` when URL dispatch is used. --- repoze/bfg/urldispatch.py | 114 ++++------------------------------------------ 1 file changed, 8 insertions(+), 106 deletions(-) (limited to 'repoze/bfg/urldispatch.py') diff --git a/repoze/bfg/urldispatch.py b/repoze/bfg/urldispatch.py index ead8876de..2b6717891 100644 --- a/repoze/bfg/urldispatch.py +++ b/repoze/bfg/urldispatch.py @@ -31,85 +31,6 @@ deprecated('RoutesContext', "DefaultRoutesContext')", ) -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 - `_ engine has the 'first - crack' at resolving the current request URL to a repoze.bfg view. - Any view that claims it is 'for' the 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. - - .. warning:: This class is deprecated. As of :mod:`repoze.bfg` - 0.6.3, you should use the ```` ZCML directive instead - of manually creating a RoutesMapper. See :ref:`urldispatch_chapter` - for more information. - """ - def __init__(self, get_root): - self.get_root = get_root - self.mapper = Mapper(controller_scan=None, directory=None, - explicit=True, always_scan=False) - self.mapper.explicit = True - self._regs_created = False - - def __call__(self, environ): - if not self._regs_created: - self.mapper.create_regs([]) - self._regs_created = True - path = environ.get('PATH_INFO', '/') - self.mapper.environ = environ - args = self.mapper.match(path) - if isinstance(args, dict): # might be an empty dict - context_factory = args.get('context_factory', _marker) - if context_factory is _marker: - context_factory = DefaultRoutesContext - 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 - 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. One differences 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 ``DefaultRoutesContext`` 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) - -deprecated('RoutesMapper', - 'Usage of the ``RoutesMapper`` class is deprecated. As of ' - 'repoze.bfg 0.6.3, you should use the ```` ZCML ' - 'directive instead of manually creating a RoutesMapper.', - ) - class RoutesContextNotFound(object): implements(IContextNotFound) def __init__(self, msg): @@ -172,7 +93,7 @@ class RoutesRootFactory(Mapper): args = args.copy() routepath = route.routepath factory = route._factory - if not factory: + if factory is None: factory = DefaultRoutesContext config = request_config() config.mapper = self @@ -189,9 +110,7 @@ class RoutesRootFactory(Mapper): kw[k] = v context = factory(**kw) environ['wsgiorg.routing_args'] = ((), kw) - provides = route._provides - for iface in provides: - alsoProvides(context, iface) + environ['bfg.route'] = route alsoProvides(context, IRoutesContext) return context @@ -207,29 +126,12 @@ class RoutesModelTraverser(object): self.context = context def __call__(self, environ): - # the traverser *wants* to get routing args from the environ - # as of 0.6.5; the rest of this stuff is for backwards - # compatibility - try: - # 0.6.5 + - match = environ['wsgiorg.routing_args'][1] - except KeyError: - # <= 0.6.4 - match = self.context.__dict__ - try: - view_name = match['view_name'] - except KeyError: - # b/w compat < 0.6.3 - try: - view_name = match['controller'] - except KeyError: - view_name = '' - try: - subpath = match['subpath'] + route = environ['bfg.route'] + match = environ['wsgiorg.routing_args'][1] + + subpath = match.get('subpath', []) + if subpath: subpath = filter(None, subpath.split('/')) - except KeyError: - # b/w compat < 0.6.5 - subpath = [] if 'path_info' in match: # this is stolen from routes.middleware; if the route map @@ -245,7 +147,7 @@ class RoutesModelTraverser(object): if environ['SCRIPT_NAME'].endswith('/'): environ['SCRIPT_NAME'] = environ['SCRIPT_NAME'][:-1] - return self.context, view_name, subpath, None, self.context, None + return self.context, route.name, subpath, None, self.context, None class RoutesContextURL(object): """ The IContextURL adapter used to generate URLs for a context -- cgit v1.2.3