[Checkins] SVN: martian/trunk/src/martian/ Introduce priorities.

Martijn Faassen faassen at infrae.com
Tue Jun 19 14:50:13 EDT 2007


Log message for revision 76804:
  Introduce priorities.
  

Changed:
  U   martian/trunk/src/martian/README.txt
  U   martian/trunk/src/martian/components.py
  U   martian/trunk/src/martian/core.py
  U   martian/trunk/src/martian/interfaces.py

-=-
Modified: martian/trunk/src/martian/README.txt
===================================================================
--- martian/trunk/src/martian/README.txt	2007-06-19 18:34:39 UTC (rev 76803)
+++ martian/trunk/src/martian/README.txt	2007-06-19 18:50:13 UTC (rev 76804)
@@ -936,7 +936,87 @@
   >>> multi_grokker.grok('ColorGrokker', ColorGrokker)
   True
 
+Priority
+--------
 
+When grokking a module using a ``ModuleGrokker``, grokker execution
+can be determined by their priority. By default, grokkers have a
+priority of ``0``. Let's define two base classes, ``A`` and ``B``, 
+which can be grokked::
 
+  >>> class A(object):
+  ...   pass
 
+  >>> class B(object):
+  ...   pass
 
+Let's define a special kind of class grokker that records the order in
+which names get grokked::
+
+  >>> order = []
+  >>> class OrderGrokker(ClassGrokker):
+  ...   def grok(self, name, obj):
+  ...     order.append(name)
+  ...     return True
+
+Now we define two grokkers for subclasses of ``A`` and ``B``, where
+the ``BGrokker`` has a higher priority::
+
+  >>> class AGrokker(OrderGrokker):
+  ...   component_class = A
+  >>> class BGrokker(OrderGrokker):
+  ...   component_class = B
+  ...   priority = 10
+
+Let's register these grokkers::
+
+  >>> multi_grokker = MetaMultiGrokker()
+  >>> multi_grokker.grok('AGrokker', AGrokker)
+  True
+  >>> multi_grokker.grok('BGrokker', BGrokker)
+  True
+
+Let's create a module containing ``A`` and ``B`` subclasses::
+
+  >>> class mymodule(FakeModule):
+  ...   class ASub(A):
+  ...     pass
+  ...   class BSub(B):
+  ...     pass
+  >>> mymodule = fake_import(mymodule)
+
+We'll grok it::
+
+  >>> module_grokker = ModuleGrokker(multi_grokker)
+  >>> module_grokker.grok('mymodule', mymodule)
+  True
+
+Since the ``BGrokker`` has a higher priority, we expect the following
+order of grokking::
+
+  >>> order 
+  ['BSub', 'ASub']
+
+This also works for GlobalGrokkers. We will define a GlobalGrokker
+that has a higher priority than the default, but lower than B::
+
+  >>> class MyGlobalGrokker(GlobalGrokker):
+  ...   priority = 5
+  ...   def grok(self, name, obj):
+  ...     order.append(name)
+  ...     return True
+  >>> multi_grokker.grok('MyGlobalGrokker', MyGlobalGrokker)
+  True
+
+We will grok the module again::
+  
+  >>> order = []
+  >>> module_grokker.grok('mymodule', mymodule)
+  True
+
+This time, the global grokker should appear after 'BSub' but before 'ASub'::
+
+  >>> order
+  ['BSub', 'mymodule', 'ASub']
+
+

Modified: martian/trunk/src/martian/components.py
===================================================================
--- martian/trunk/src/martian/components.py	2007-06-19 18:34:39 UTC (rev 76803)
+++ martian/trunk/src/martian/components.py	2007-06-19 18:50:13 UTC (rev 76804)
@@ -22,6 +22,8 @@
 class GrokkerBase(object):
     implements(IGrokker)
 
+    priority = 0
+    
     def grok(self, name, obj, **kw):
         raise NotImplementedError
 

Modified: martian/trunk/src/martian/core.py
===================================================================
--- martian/trunk/src/martian/core.py	2007-06-19 18:34:39 UTC (rev 76803)
+++ martian/trunk/src/martian/core.py	2007-06-19 18:50:13 UTC (rev 76804)
@@ -35,8 +35,7 @@
         raise NotImplementedError
 
 class ModuleGrokker(MultiGrokkerBase):
-    implements(IMultiGrokker)
-
+  
     def __init__(self, grokker=None, prepare=None, finalize=None):
         if grokker is None:
             grokker = MultiGrokker()
@@ -51,17 +50,31 @@
         self._grokker.clear()
     
     def grok(self, name, module, **kw):
+        grokked_status = False
+
         # prepare module grok - this can also influence the kw dictionary
         if self.prepare is not None:
             self.prepare(name, module, kw)
 
-        # do the actual grokking
-        grokked_status = super(ModuleGrokker, self).grok(name, module, **kw)
-
+        # sort grokkers by priority
+        grokkers = sorted(self.grokkers(name, module),
+                          key=lambda (grokker, name, obj): grokker.priority)
+        # reverse so highest priority happens first
+        grokkers.reverse()
+        
+        for g, name, obj in grokkers:
+            grokked = g.grok(name, obj, **kw)
+            if grokked not in (True, False):
+                raise GrokError(
+                    "%r returns %r instead of True or False." %
+                    (g, grokked), None)
+            if grokked:
+                grokked_status = True
+                
         # finalize module grok
         if self.finalize is not None:
             self.finalize(name, module, kw)
-        
+
         return grokked_status
 
     def grokkers(self, name, module):
@@ -83,7 +96,6 @@
                 yield t
 
 class MultiInstanceOrClassGrokkerBase(MultiGrokkerBase):
-    implements(IMultiGrokker)
 
     def __init__(self):
         self.clear()
@@ -119,7 +131,6 @@
         return inspect.getmro(obj)
 
 class MultiGlobalGrokker(MultiGrokkerBase):
-    implements(IMultiGrokker)
 
     def __init__(self):
         self.clear()
@@ -135,7 +146,6 @@
             yield grokker, name, module
     
 class MultiGrokker(MultiGrokkerBase):
-    implements(IMultiGrokker)
     
     def __init__(self):
         self.clear()

Modified: martian/trunk/src/martian/interfaces.py
===================================================================
--- martian/trunk/src/martian/interfaces.py	2007-06-19 18:34:39 UTC (rev 76803)
+++ martian/trunk/src/martian/interfaces.py	2007-06-19 18:50:13 UTC (rev 76804)
@@ -15,6 +15,8 @@
 from zope.interface import Interface, Attribute
 
 class IGrokker(Interface):
+    priority = Attribute('Priority during module grokking.')
+
     def grok(name, obj, **kw):
         """Grok obj.
 
@@ -27,7 +29,7 @@
         Returns True if grok is attempted, False if object is filtered
         out by this grokker.
         """
-
+    
 class IComponentGrokker(IGrokker):
     """A grokker that groks components in a module.
 



More information about the Checkins mailing list