[Checkins] SVN: martian/trunk/src/martian/ The default rule ignores things declared baseclass(). base classes
Martijn Faassen
faassen at infrae.com
Thu Feb 26 08:58:13 EST 2009
Log message for revision 97300:
The default rule ignores things declared baseclass(). base classes
are inert and won't automatically associate with anything, just like
they aren't grokked. They're just there to make reuse more easy,
and if a base class wants directives set up for it, it should use
explicit directives.
Changed:
U martian/trunk/src/martian/core.py
U martian/trunk/src/martian/directive.py
U martian/trunk/src/martian/directive.txt
U martian/trunk/src/martian/util.py
-=-
Modified: martian/trunk/src/martian/core.py
===================================================================
--- martian/trunk/src/martian/core.py 2009-02-26 13:56:50 UTC (rev 97299)
+++ martian/trunk/src/martian/core.py 2009-02-26 13:58:13 UTC (rev 97300)
@@ -98,7 +98,7 @@
obj = getattr(module, name)
if not util.defined_locally(obj, module.__name__):
continue
- if util.is_baseclass(name, obj):
+ if util.is_baseclass(obj):
continue
for t in grokker.grokkers(name, obj):
yield t
Modified: martian/trunk/src/martian/directive.py
===================================================================
--- martian/trunk/src/martian/directive.py 2009-02-26 13:56:50 UTC (rev 97299)
+++ martian/trunk/src/martian/directive.py 2009-02-26 13:58:13 UTC (rev 97300)
@@ -134,6 +134,8 @@
for base in mro:
module_of_base = scan.resolve(base.__module__)
try:
+ if util.is_baseclass(base):
+ break
result = get_default(base, module_of_base)
except UnknownError, e:
# store error if this is the first UnknownError we ran into
Modified: martian/trunk/src/martian/directive.txt
===================================================================
--- martian/trunk/src/martian/directive.txt 2009-02-26 13:56:50 UTC (rev 97299)
+++ martian/trunk/src/martian/directive.txt 2009-02-26 13:58:13 UTC (rev 97300)
@@ -1093,3 +1093,76 @@
...
>>> martian.baseclass.bind().get(NoBase)
False
+
+Base classes influence computed directives: a directive computation
+will not happen on a base class (or in base classes of it).
+
+Let's define a directive with the computed rule that it will look for
+an object ``Context`` in the module it finds itself in and return its
+``value`` attribute::
+
+ >>> class info(Directive):
+ ... scope = CLASS
+ ... store = ONCE
+ >>> def get_default(component, module, **data):
+ ... context = getattr(module, 'Context', None)
+ ... if context is None:
+ ... return martian.UNKNOWN
+ ... return context.value
+
+Let use this rule with an example where no baseclass is declared
+first::
+
+ >>> class basemodule(FakeModule):
+ ... class Context(object):
+ ... value = 1
+ ... class A(object):
+ ... pass
+ >>> from martiantest.fake import basemodule
+ >>> class submodule(FakeModule):
+ ... class B(basemodule.A):
+ ... pass
+ >>> from martiantest.fake import submodule
+ >>> info.bind(get_default=get_default).get(submodule.B)
+ 1
+
+Now let's apply the rule where ``A`` is declared to be a
+baseclass. Since ``A`` is a base class, the computed default will not
+take effect::
+
+ >>> class basemodule2(FakeModule):
+ ... class Context(object):
+ ... value = 1
+ ... class A(object):
+ ... martian.baseclass()
+ >>> from martiantest.fake import basemodule2
+ >>> class submodule2(FakeModule):
+ ... class B(basemodule2.A):
+ ... pass
+ >>> from martiantest.fake import submodule2
+ >>> info.bind(get_default=get_default).get(submodule2.B) is martian.UNKNOWN
+ True
+
+If we change the default rule so we use ``UnknownError`` we see the same
+behavior, except an error message is raised::
+
+ >>> def get_default(component, module, **data):
+ ... context = getattr(module, 'Context', None)
+ ... if context is None:
+ ... raise UnknownError("No Context object found!", component)
+ ... return context.value
+
+It will work for the case where no baseclass is defined, as the rule
+can take effect then::
+
+ >>> info.bind(get_default=get_default).get(submodule.B)
+ 1
+
+But we will get a ``GrokError`` when a baseclass is in play::
+
+ >>> info.bind(get_default=get_default).get(submodule2.B)
+ Traceback (most recent call last):
+ ...
+ GrokError: No Context object found!
+
+
Modified: martian/trunk/src/martian/util.py
===================================================================
--- martian/trunk/src/martian/util.py 2009-02-26 13:56:50 UTC (rev 97299)
+++ martian/trunk/src/martian/util.py 2009-02-26 13:58:13 UTC (rev 97300)
@@ -48,8 +48,13 @@
def caller_module():
return sys._getframe(2).f_globals['__name__']
-def is_baseclass(name, component):
- return (isclass(component) and martian.baseclass.bind().get(component))
+def is_baseclass(component):
+ # this is a bit more low-level than we really want, but
+ # using martian.baseclass.bind().get(component) has the unfortunate
+ # site effect of causing infinite recursion when using this within
+ # the implementation of directives, which we now do...
+ return (isclass(component) and
+ 'martian.martiandirective.baseclass' in component.__dict__)
def defined_locally(obj, dotted_name):
obj_module = getattr(obj, '__grok_module__', None)
More information about the Checkins
mailing list