[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