Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
Make predicate mismatches not hide valid views #786
This is mostly an issue with views that use request_method predicates. See Issue #409
Here's a motivating example:
Currently the override_post view registration hides the get and delete views in the context of MyResource -- leading to a predicate mismatch error when trying to use GET or DELETE methods. With my patch the views are found and no predicate mismatch is raised.
Hey Amos! Long time no see.
Yeah, for better or worse, as you've found, "context" binds more tightly than any other predicate, so you can tend to think of the set of views that mention a particular context as the subset of views that will be searched when the context of the request matches. It's more equal than all the other predicates.
This is actually mostly an optimization so that we don't need to match every request against every view configuration; only those that match the most specific view registrations made against the request's context. In your example, the most specific registration is for context=MyResource, so it will only grub through the set of views registered for MyResource (and, as you've found, not through the set of views registered for IResource, because, although it matches, it's less specific).
I'm a bit loath to change this, as it really is meant to be an optimization, even if it only meant falling back to sort of looking up the iro as your patch does. That said, I'm willing to hear arguments to the contrary.
Hope you're good!
Would love to catch up with you sometime soon. Lot's to tell.
I hear what you're saying about context binding, but in practice registering views for an interface and then overriding one or more view for a specific class that implements that interface works well.
This works fine, and seems like a nice style to me. So it's not just the context that's important, but the view name too.
The issue that my patch tries to address is that this style of view configuration doesn't work when you have multiple views registered for the same name and only want to override one of them, e.g. REST views. The fact that this doesn't work was surprising and frustrating to me, especially since everything works so nicely in other cases.
I'm curious about the optimization issue. Does this patch slow existing sites down? The only thing I think that it would slow down would be returning predicate mismatch errors, since it would do some more checking before giving up. It's true that views that took advantage of the new behavior could be a little slower to serve since they might require multiple adapter look ups. I guess that I should do some performance testing rather than speculation.
I've been thinking about this a bit more.
I believe that pyramid basically deals with predicates by using a multiview to collect all the various views that differ only by predicate, then it tries various views when a request comes in, catches PredicateMismatches and returning the first view whose predicates are OK.
The issue that I'm trying to address is that when you register views by context interface the multiviews don't get created. Instead view registrations can hide other ones since the contexts aren't the same.
An alternate solution would be to create multiviews by walking the iro at configuration time rather than view lookup time. So for example, if I register a view with a context of MyResource (using the example above) then we could look up the interfaces that MyResource implements and create a multiview with any existing views registered for any of the interfaces it implements that have the same view name. Unfortunately this solution wouldn't address the use case presented in issue #409 since there would be no way to know that IReader and IWriter views belong in a MultiView together. I'm not wild about this solution, but If you like it I'd be happy to create a pull request for it.
Thinking about the performance issue I believe that it makes sense to continue to use context and name as the primary predicates in order to limit the search space for views. However, I don't see the performance issue of walking the iro looking for valid views if you can't find one at first. The alternative is to fail. So basically the change I'm proposing would slow down the speed at which users would receive PredicateMismatch errors. My understanding is that these errors aren't normally supposed to occur. They aren't the sort of thing that an application should regularly return. So I believe that slowing them down a bit shouldn't be a big deal.
Another way of thinking about the performance issue is to say that the change would encourage people to adopt a less efficient method of creating their application. I can understand this argument. However I think that suggesting people use the contextpred solution from issue #409 is even worse from the point of view of encouraging inefficient usage.
In the end I would like to see this change adopted, but if it's not acceptable, that's OK. I can work around the issue.
I had a design for a simple CMS where there is a frontend and admin view for a resource collection. The frontend view is type-specific, as it has a custom mako template. The admin view is not - it simply sends all the data to be rendered on browser side with dgrid. This optimisation however doesn't allow me to define a superclass views with
For what purpose is
Anyway, @latteier 's comment about this only being used in the error path is a good one and performance issues shouldn't be such a worry when it's making view lookup more sane.