[Checkins] SVN: martian/trunk/src/martian/ Add section on meta grokkers. Get rid of single global grokker.

Martijn Faassen faassen at infrae.com
Tue Jun 19 12:12:32 EDT 2007


Log message for revision 76794:
  Add section on meta grokkers. Get rid of single global grokker.
  

Changed:
  U   martian/trunk/src/martian/README.txt
  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 15:22:02 UTC (rev 76793)
+++ martian/trunk/src/martian/README.txt	2007-06-19 16:12:32 UTC (rev 76794)
@@ -856,3 +856,87 @@
   Traceback (most recent call last):
     ...
   GrokError: <MyGrokker object at ...> returns 'Foo' instead of True or False.
+
+Meta Grokkers
+-------------
+
+Meta grokkers are grokkers that grok grokkers. This mechanism can be
+used to extend Martian. Let's register a ``ClassMetaGrokker`` that
+looks for subclasses of ``ClassGrokker``::
+
+  >>> from martian.core import MetaGrokker
+  >>> class ClassMetaGrokker(MetaGrokker):
+  ...   component_class = ClassGrokker
+  >>> multi_grokker = MultiGrokker()
+  >>> multi_grokker.register(ClassMetaGrokker(multi_grokker))
+
+``multi_grokker`` should now grok subclasses of ``ClassGrokker``, such
+as ``AnimalGrokker``::
+
+  >>> all_animals = {} # clean out animal registry
+  >>> multi_grokker.grok('AnimalGrokker', AnimalGrokker)
+  True
+
+Our multi_grokker should now also be able to grok animals::
+
+  >>> class Woodpecker(animal.Animal):
+  ...   pass
+  >>> multi_grokker.grok('Woodpecker', Woodpecker)
+  True
+
+A ``MetaMultiGrokker`` is a ``MultiGrokker`` that comes preconfigured with
+grokkers for ``ClassGrokker``, ``InstanceGrokker`` and ``GlobalGrokker``::
+
+  >>> from martian.core import MetaMultiGrokker
+  >>> multi_grokker = MetaMultiGrokker()
+
+It works for ``ClassGrokker``::
+  
+  >>> all_animals = {}
+  >>> multi_grokker.grok('AnimalGrokker', AnimalGrokker)
+  True
+  >>> multi_grokker.grok('Woodpecker', Woodpecker)
+  True
+  >>> all_animals
+  {'Woodpecker': <class 'Woodpecker'>}
+
+and for ``InstanceGrokker``::
+
+  >>> color.all_colors = {}
+  >>> multi_grokker.grok('ColorGrokker', ColorGrokker)
+  True
+  >>> multi_grokker.grok('color', Color(255, 0, 0))
+  True
+  >>> color.all_colors
+  {'color': <Color 255 0 0>}
+
+and for ``GlobalGrokker``::
+
+  >>> read_amount = {}
+  >>> multi_grokker.grok('AmountGrokker', AmountGrokker)
+  True
+  >>> grokker.grok('g', g)
+  True
+  >>> read_amount[None]
+  50
+
+We can clear the meta multi grokker::
+
+  >>> multi_grokker.clear()
+
+It won't grok particular classes or instances anymore::
+
+  >>> multi_grokker.grok('Woodpecker', Woodpecker)
+  False 
+  >>> multi_grokker.grok('color', Color(255, 0, 0))
+  False
+
+It can still grok grokkers::
+
+  >>> multi_grokker.grok('ColorGrokker', ColorGrokker)
+  True
+
+
+
+
+

Modified: martian/trunk/src/martian/core.py
===================================================================
--- martian/trunk/src/martian/core.py	2007-06-19 15:22:02 UTC (rev 76793)
+++ martian/trunk/src/martian/core.py	2007-06-19 16:12:32 UTC (rev 76794)
@@ -20,7 +20,10 @@
         
     def register(self, grokker):
         self._grokker.register(grokker)
-        
+
+    def clear(self):
+        self._grokker.clear()
+    
     def grok(self, name, module, **kw):
         grokked_status = False
         grokker = self._grokker
@@ -57,14 +60,17 @@
     implements(IMultiGrokker)
 
     def __init__(self):
-        self._grokkers = {}
+        self.clear()
         
     def register(self, grokker):
         key = grokker.component_class
         grokkers = self._grokkers.setdefault(key, [])
         if grokker not in grokkers:
             grokkers.append(grokker)
-    
+
+    def clear(self):
+        self._grokkers = {}
+        
     def grok(self, name, obj, **kw):
         used_grokkers = set()
         grokked_status = False
@@ -98,11 +104,14 @@
     implements(IMultiGrokker)
 
     def __init__(self):
-        self._grokkers = []
+        self.clear()
 
     def register(self, grokker):
         self._grokkers.append(grokker)
 
+    def clear(self):
+        self._grokkers = []
+        
     def grok(self, name, module, **kw):
         grokked_status = False
         for grokker in self._grokkers:
@@ -119,9 +128,7 @@
     implements(IMultiGrokker)
     
     def __init__(self):
-        self._multi_instance_grokker = MultiInstanceGrokker()
-        self._multi_class_grokker = MultiClassGrokker()
-        self._multi_global_grokker = MultiGlobalGrokker()
+        self.clear()
         
     def register(self, grokker):
         if isinstance(grokker, InstanceGrokker):
@@ -133,6 +140,11 @@
         else:
             assert 0, "Unknown type of grokker: %r" % grokker
 
+    def clear(self):
+        self._multi_instance_grokker = MultiInstanceGrokker()
+        self._multi_class_grokker = MultiClassGrokker()
+        self._multi_global_grokker = MultiGlobalGrokker()
+
     def grok(self, name, obj, **kw):
         obj_type = type(obj)
         if obj_type in (type, types.ClassType):
@@ -142,28 +154,40 @@
         else:
             return self._multi_instance_grokker.grok(name, obj, **kw)
 
+class MetaMultiGrokker(MultiGrokker):
+    """Multi grokker which comes pre-registered with meta-grokkers.
+    """
+    def clear(self):
+        super(MetaMultiGrokker, self).clear()
+        # bootstrap the meta-grokkers
+        self.register(ClassMetaGrokker(self))
+        self.register(InstanceMetaGrokker(self))
+        self.register(GlobalMetaGrokker(self))
+
 def grok_dotted_name(dotted_name, grokker=None, **kw):
     module_info = scan.module_info_from_dotted_name(dotted_name)
     grok_package(module_info, grokker, **kw)
     
-def grok_package(module_info, grokker=None, **kw):
-    if grokker is None:
-        grokker = the_module_grokker
+def grok_package(module_info, grokker, **kw):
     grok_module(module_info, grokker, **kw)
     for sub_module_info in module_info.getSubModuleInfos():
         grok_package(sub_module_info, grokker, **kw)
 
-def grok_module(module_info, grokker=None, **kw):
-    if grokker is None:
-        grokker = the_module_grokker
+def grok_module(module_info, grokker, **kw):
     grokker.grok(module_info.dotted_name, module_info.getModule(), **kw)
     
 # deep meta mode here - we define grokkers that can pick up the
 # three kinds of grokker: ClassGrokker, InstanceGrokker and ModuleGrokker
 class MetaGrokker(ClassGrokker):
+    def __init__(self, multi_grokker):
+        """multi_grokker - the grokker to register grokkers with.
+        """
+        self.multi_grokker = multi_grokker
+        
     def grok(self, name, obj, **kw):
-        the_grokker.register(obj())
-
+        self.multi_grokker.register(obj())
+        return True
+    
 class ClassMetaGrokker(MetaGrokker):
     component_class = ClassGrokker
 
@@ -172,13 +196,3 @@
 
 class GlobalMetaGrokker(MetaGrokker):
     component_class = GlobalGrokker
-
-# the global single grokker to bootstrap everything
-the_grokker = MultiGrokker()
-# bootstrap the meta-grokkers
-the_grokker.register(ClassMetaGrokker())
-the_grokker.register(InstanceMetaGrokker())
-the_grokker.register(GlobalMetaGrokker())
-
-# a global module grokker
-the_module_grokker = ModuleGrokker(the_grokker)

Modified: martian/trunk/src/martian/interfaces.py
===================================================================
--- martian/trunk/src/martian/interfaces.py	2007-06-19 15:22:02 UTC (rev 76793)
+++ martian/trunk/src/martian/interfaces.py	2007-06-19 16:12:32 UTC (rev 76794)
@@ -42,6 +42,10 @@
         """Register a martian.
         """
 
+    def clear():
+        """Clear all martians and go back to initial state.
+        """
+
 class IModuleInfo(Interface):
     def getModule():
         """Get the module object this module info is representing.



More information about the Checkins mailing list