Hello,
I am developing an application where it is desirable to reuse an existing resource class, but route some of the child resources to a different resource class.
My code is currently organized similar to this example:
class Foo(Resource):
@child("bar")
def bar(self, request, segments):
return Bar()
class Foo2(foo):
@child("bar")
def baz(self, request, segments):
return Baz()
Then, for example, URLs beginning with "/foo" are routed through the Foo resource and URLs beginning with "/foo2" are routed through the Foo2 resource. I am expecting a GET for "/foo/bar" to show the Bar resource, and a GET for "/foo2/bar" to show the Baz resource. Unfortunately, I am seeing the Bar resource shown in both cases.
Looking through the code, the problem appears to be in _gather_child_factories (resource.py). Specifically, the child_factories list of "the" base class (the first class in the MRO with a child_factories attribute) is copied, the list of @child-decorated methods attached to the sub-class (a la _find_annotated_funcs) is appended, then the entire list is sorted based on the method's "score". The problem is that the score does not take into account the method's location in the class hierarchy. Thus, the ultimate order of the list in this case ends up being decided by the implementation of sorted. (There is also the issue that only one parent resource class can be supported, but that is irrelevant in this particular case.)
I'm thinking it would best to build the child_factories list from scratch for each class, and take into account the MRO of the class each method is attached to. (This would have to be built from scratch for each class, because the same baseclass could end up in different places in the MRO for different subclasses.) Basically, just add an element to the tuple returned by the scoring function that is "high" for subclasses and "low" for baseclasses.
I'm just wondering:
(1) Is my analysis of the situation correct?
(2) Are there any plans to fix this?
(2.a) If yes, what are they, and how can I help?
(2.b) If not, does my proposed solution above sound reasonable?
(3) What is the preferred way to submit patches?
(4) What codebase should I submit a patch against? I'm using v0.12.1 in production. Ideally, I'd like to work against that. But in GitHub, the last tagged release was 0.9.
Thank you,
Nathan Davis