[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