summaryrefslogtreecommitdiff
path: root/repoze/bfg/urldispatch.py
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-06-11 03:15:15 +0000
committerChris McDonough <chrism@agendaless.com>2009-06-11 03:15:15 +0000
commitdfc2b65c1b6d2f938f68b7868a14d8f9a4faab9e (patch)
treef3241401b7175a401e00286b11e3efe3c21f5093 /repoze/bfg/urldispatch.py
parentf8b0065b6ede54424d7a7b49f9f113e87634b5ab (diff)
downloadpyramid-dfc2b65c1b6d2f938f68b7868a14d8f9a4faab9e.tar.gz
pyramid-dfc2b65c1b6d2f938f68b7868a14d8f9a4faab9e.tar.bz2
pyramid-dfc2b65c1b6d2f938f68b7868a14d8f9a4faab9e.zip
Merge unifyroutesandtraversal branch into trunk
Diffstat (limited to 'repoze/bfg/urldispatch.py')
-rw-r--r--repoze/bfg/urldispatch.py136
1 files changed, 11 insertions, 125 deletions
diff --git a/repoze/bfg/urldispatch.py b/repoze/bfg/urldispatch.py
index 612843cfa..bfeae3333 100644
--- a/repoze/bfg/urldispatch.py
+++ b/repoze/bfg/urldispatch.py
@@ -1,72 +1,25 @@
-import re
-
-from zope.component import queryUtility
-
-from zope.interface import implements
-from zope.interface import alsoProvides
-from zope.interface import classProvides
-
from routes import Mapper
from routes import request_config
-from routes import url_for
-
-from repoze.bfg.interfaces import IContextNotFound
-from repoze.bfg.interfaces import IContextURL
-from repoze.bfg.interfaces import IRoutesContext
-from repoze.bfg.interfaces import IRoutesContextFactory
-from repoze.bfg.interfaces import ITraverser
-from repoze.bfg.interfaces import ITraverserFactory
-_marker = ()
-
-class DefaultRoutesContext(object):
- implements(IRoutesContext)
- def __init__(self, **kw):
- self.__dict__.update(kw)
-
-class RoutesContextNotFound(object):
- implements(IContextNotFound)
- def __init__(self, msg):
- self.msg = msg
-
-_notfound = RoutesContextNotFound(
- 'Routes context cannot be found and no fallback "get_root"')
+_marker = object()
class RoutesRootFactory(Mapper):
- """ The ``RoutesRootFactory`` is a wrapper for the root factory
- callable passed in to the repoze.bfg ``Router`` at initialization
- time. When it is instantiated, it wraps the root factory of an
- application in such a way that the `Routes
- <http://routes.groovie.org/index.html>`_ 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 route ``name`` name for the match. It
- will be passed a context object that has attributes that are
- present as Routes match arguments dictionary keys. If no Routes
- route matches the current request, the 'fallback' get_root is
- called."""
- decorate_context = True
- def __init__(self, get_root=None, **kw):
- self.get_root = get_root
+ def __init__(self, default_root_factory, **kw):
+ 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.default_context_factory = DefaultRoutesContext
def has_routes(self):
return bool(self.matchlist)
def connect(self, *arg, **kw):
- # we need to deal with our custom attributes specially :-(
- factory = None
- if '_factory' in kw:
- factory = kw.pop('_factory')
result = Mapper.connect(self, *arg, **kw)
- self.matchlist[-1]._factory = factory
+ route = self.matchlist[-1]
+ route._factory = None # overridden by ZCML
return result
def __call__(self, environ):
@@ -89,78 +42,11 @@ class RoutesRootFactory(Mapper):
config.host = environ.get('HTTP_HOST', environ['SERVER_NAME'])
config.protocol = environ['wsgi.url_scheme']
config.redirect = None
- kw = {}
- for k, v in args.items():
- # Routes "helpfully" converts default parameter names
- # into Unicode; these can't be used as attr names
- if k.__class__ is unicode:
- k = k.encode('utf-8')
- kw[k] = v
- factory = route._factory
- if factory is None:
- context = self.default_context_factory(**kw)
- if self.decorate_context:
- alsoProvides(context, IRoutesContext)
- else:
- context = factory(**kw)
- alsoProvides(context, IRoutesContext)
- environ['wsgiorg.routing_args'] = ((), kw)
- environ['bfg.route'] = route
- return context
-
- if self.get_root is None:
- return _notfound
-
- return self.get_root(environ)
-
-class RoutesModelTraverser(object):
- classProvides(ITraverserFactory)
- implements(ITraverser)
- def __init__(self, context):
- self.context = context
-
- def __call__(self, environ):
- route = environ['bfg.route']
- match = environ['wsgiorg.routing_args'][1]
-
- subpath = match.get('subpath', [])
- if subpath:
- subpath = filter(None, subpath.split('/'))
-
- if 'path_info' in match:
- # this is stolen from routes.middleware; if the route map
- # has a *path_info capture, use it to influence the path
- # info and script_name of the generated environment
- oldpath = environ['PATH_INFO']
- newpath = match['path_info'] or ''
- environ['PATH_INFO'] = newpath
- if not environ['PATH_INFO'].startswith('/'):
- environ['PATH_INFO'] = '/' + environ['PATH_INFO']
- pattern = r'^(.*?)/' + re.escape(newpath) + '$'
- environ['SCRIPT_NAME'] += re.sub(pattern, r'\1', oldpath)
- if environ['SCRIPT_NAME'].endswith('/'):
- environ['SCRIPT_NAME'] = environ['SCRIPT_NAME'][:-1]
-
- return dict(context=self.context, view_name=route.name,
- subpath=subpath, traversed=None, virtual_root=self.context,
- virtual_root_path=None, root=self.context)
-
-class RoutesContextURL(object):
- """ The IContextURL adapter used to generate URLs for a context
- object obtained via Routes URL dispatch. This implementation
- juses the ``url_for`` Routes API to generate a URL based on
- ``environ['wsgiorg.routing_args']``. Routes context objects,
- unlike traversal-based context objects, cannot have a virtual root
- that differs from its physical root; furthermore, the physical
- root of a Routes context is always itself, so the ``virtual_root``
- function returns the context of this adapter unconditionally."""
- implements(IContextURL)
- def __init__(self, context, request):
- self.context = context
- self.request = request
+ environ['wsgiorg.routing_args'] = ((), args)
+ environ['bfg.routes.route'] = route
+ environ['bfg.routes.matchdict'] = args
+ factory = route._factory or self.default_root_factory
+ return factory(environ)
- def virtual_root(self):
- return self.context
+ return self.default_root_factory(environ)
- def __call__(self):
- return url_for(**self.request.environ['wsgiorg.routing_args'][1])