Open waweber opened 4 years ago
This is probably because zope.interface doesn't support implicit ABCs and I have no clue if that's on their roadmap. Personally I'm not a big fan of them so getting them supported is not high on my list but that is more than likely the issue here. Pyramid defers to the zope component registry to traverse the class SRO and then lookup instances by those interfaces.
It is related to getting the following chunk of code to work: https://github.com/Pylons/pyramid/blob/48a04855ad4f1f1ae6af934090f35a4ad035ed67/src/pyramid/view.py#L613-L622
Describe the bug View lookup using
context=
does not support abstract base classes in Pyramid 1.10.4 on Python 3.8.3.To Reproduce Experiment with the following code:
Now set up a Pyramid application with MyCoolClass in the resource tree. You will find that Pyramid will return 404 due to no view callable being found.
Now let's try with a less realistic use case:
Now set up a Pyramid application with a NotCoolClass resource in the tree. You will find that Pyramid matches
cool_view
even though NotCoolClass is NOT a CoolClass.Expected behavior When view lookup happens with a MyCoolClass as the context, cool_view should be selected. Instead, no appropriate view callable is found.
Additional context
The documentation for view configuration states:
I have confirmed that MyCoolClass is in fact an instance of CoolClass.
isinstance()
on an instance of MyCoolClass returns True, andissubclass()
of its type also returns True. As far as I can tell, the predicate forcontext=
should return True and select this view callable.Note that everything behaves correctly if MyCoolClass explicitly subclasses CoolClass. I am assuming Pyramid explicitly looks for CoolClass in its hierarchy instead of just using isinstance/issubclass.
All that said, I don't even know if this is a good thing to support or if its a good idea to select views this way, it's just confusing that Pyramid/isinstance disagree. On one hand, if a programmer declares
class MyCoolClass:
, they might find it surprising thatisinstance
returns True on something other than itself/object. On the other hand, ifisinstance
returns True on an object, they might find it surprising that a Pyramid view does not match it. Supporting this case, though, means that one could write some really advanced predicates using just thecontext=
argument.