I made a mistake by adding the current generation of "URL-dispatch" behavior to repoze.bfg.
Currently, repoze.bfg allows you to use Routes to invoke a bfg view with a manufactured context based on a route match. To do so, you configure a "repoze.bfg.urldispatch.RoutesMapper" as the bfg "get_root" callable (aka IRootFactory, lately, at least), and pass it in to bfg's "make_app" at application construction time. Before you pass it in, you are expected to call the RoutesMapper's "connect" method with the same arguments you might pass to a "real" Routes mapper object (see http://routes.groovie.org/manual.html#setting-up-routes). The BFG RoutesMapper also treats one argument to "connect" specially: a "context_factory". This argument, if it exists, allows you to tell BFG what kind of class to create for the manufactured context. If it doesn't exist, BFG creates a generic RoutesContext object. In either case, the object is decorated with a single interface: IRoutesContext. Whether it's a custom context manufactured by a "context_factory" or a default RoutesContext object, the object obtains only that single interface. The attributes of an instance of the class are the keys and values in the routes match_dict. You are expected to make BFG view declarations *against IRoutesContext* with names that match the "controller" name in the routes match_dict. Some of this is wrong. Instead of working this way, URL dispatch should replace traversal to find the context, the view_name, and the subpath based on elements in a route path, and it should *allow the user to specify the context interface types* instead of expecting a user to register views against IRoutesContext. Here's how such a scheme might work: in the case that a context is found by a route, the context will be manufactured instead of being returned as a result of traversal through the root graph. Next-gen urldispatch will just find a context and possibly inform BFG about the "view name" and the "subpath" based on elements present the Route path (just like the normal ModelGraphTraverser does). Each route should allow a "context_factory" to be specified as well as a sequence of "context_interfaces". When a route is matched, a context will be created using the context factory; its attributes will be all the attributes in the routes match_dict. It will also be decorated (via alsoProvides) with the interfaces mentioned as "context_interfaces". Users will make "normal" BFG view declarations against such interfaces. This will allow you to mix and match traversal and graph traversal using the same interfaces. Additionally, instead of requiring a RoutesMapper as an IRootFactory, a next-gen BFG that allows a context to be found as a result of a Routes route match will just allow ZCML "route" declarations to be placed in an application's "configure.zcml". If any of these declarations exist, URL dispatch will be given "first crack" at resolving a URL; in applications that *only* use URL dispatch, the get_root callable passed to make_app at app startup can be a do-nothing. For convenience, if a Routes match_dict contains a ":view_name" key, it will be passed back to BFG as the BFG view name. Likewise, if it contains a "*subpath" wildcard match, this will be passed back to BFG as the subpath. These will be attached by BFG to the request as "subpath" and "view_name". They'll also be available on the manufactured context, too; this is only a way to make contexts found through traversal or url dispatch more similar. Here's an example of some ZCML that would create a Routes route: <route name="blog_entry" path="/blog/:id/:view_name" context_factory=".blog.BlogEntry" context_interfaces=".interfaces.IBlogEntry .interfaces.IContent" </route> For PATH_INFO '/blog/1/edit' The urldispatch "traverser" will pass back a BlogEntry with the interfaces IBlogEntry and IContent attached to it (another marker interface IRoutesContext will also be attached, but it's only for framework consumption). The "view_name" will be passed back as "edit". The subpath will be empty. Here's another example: <route name="blog_entry" path="/blog/:id/:view_name/*subpath" context_factory=".blog.BlogEntry" context_interfaces=".interfaces.IBlogEntry .interfaces.IContent" </route> Here we'll get the same context and view_name for PATH_INFO '/blog/1/edit', but we'll have a non-empty subpath. Of course, users will be able to specify a "view_name" and "subpath" argument as defaults in the route declaration as well, e.g.: <route name="blog_entry" path="/blog/:id" view_name="edit" subpath="/foo/bar" context_factory=".blog.BlogEntry" context_interfaces=".interfaces.IBlogEntry .interfaces.IContent" </route> The "repoze.bfg.model_url" API will be changed to inspect if the context is an IRoutesContext; if so, the Routes url_for API will be used to construct a URL for Routes-generated contexts. I'm not sure how this will work out. If I find time to do this, I won't unceremoniously rip out the existing urldispatch stuff; it will just get deprecated. In any case, comments welcome. - C _______________________________________________ Repoze-dev mailing list Repoze-dev@lists.repoze.org http://lists.repoze.org/listinfo/repoze-dev