[Grok-dev] solving the grok.template() bug - part A of the solution
janwijbrand at gmail.com
Sun Jan 11 15:34:59 EST 2009
With only slow progress I'm still working on the grok.template() issue.
Recently Martijn and I had a couple of hours to spend on this problem.
We found there to be several parts to a solution.
This is part A - solving the directive inheritance-over-modules.
We found that grok directives with a CLASS_OR_MODULE scope do not behave
as one would expect in the face of inheritance. grok.template is one of
these directives, but grok.context is such a directive too.
Summarizing the issue:
When subclassing a component, the information set by directives on the
baseclass can be expected to be inherited by the subclass, where this
information can be overriden when needed.
This indeed works as expected for CLASS scope directives and
CLASS_OR_MODULE directives, but not for CLASS_OR_MODULE scope directives
*whenever the baseclass and the sublcass are not defined in the same
The solution for this problem appears to be more or less simple:
whenever the get() method on the ClassOrModuleScope class finds the
default value for the directive on the component and on the module of
this component, it could try to look for a value stored on the module of
the baseclass of the component.
This would take a bit of magic: we need to loop though the mro of the
component and resolve the __module__ attribute on the bases to get to
the actual module objects. Still doable.
However, there're a couple of issues:
1) Martian's tests use the FakeModule extensively to make tests a bit
easier to read (one does not need to refer to the actual modules while
reading the test cases). My implementation of finding the module of a
baseclass breaks on the use of FakeModule.
I see two possible solutions: a) make FakeModule work with resolving
modules from module names (although I did not see an easy way) or b)
remove the FakeModule construct and define the test fixtures as normal
2) Even if we solve resolving modules in respect to FakeModule, what
other situations can happen where a class's module cannot be resolved
and which of these situations do we need to support?
3) While studying martian's directive code it occurred to me that
there's lots of methods that pass the module of a component around,
essentially just to support the CLASS_OR_MODULE scope use case.
If resolving the module from a component works reliably, this would not
be need anymore I guess, simplifying the directive code, but also
simplifying the meta-directives that help make implementing grokkers easier.
Additionally, the grok.context directive does things kinda different
again since it has its own special UnambiguousComponentScope
implementation. I think this a sign something somewhere needs to be
factored a little better.
Feedback is highly appreciated.
 It does not need to explicitely look on the baseclass itself, as the
information directly set on the baseclass would've been properly
inherited in the first place. So when we find the default, we only need
to continue looking for information set with the directive on the
modules of the baseclasses.
 I tried to understand what exactly is going on there, but the
seemingly simple code confuses the hell out of me. It seems to cover a
particular edge case, but I cannot say what that egde case actually is...
More information about the Grok-dev