[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