[Checkins] SVN: grokcore.component/trunk/ Add support for registering global adapters at module level via a global_adapter() directive

Martin Aspeli optilude at gmx.net
Thu Apr 9 11:16:37 EDT 2009


Log message for revision 99034:
  Add support for registering global adapters at module level via a global_adapter() directive

Changed:
  U   grokcore.component/trunk/CHANGES.txt
  U   grokcore.component/trunk/src/grokcore/component/__init__.py
  U   grokcore.component/trunk/src/grokcore/component/directive.py
  U   grokcore.component/trunk/src/grokcore/component/meta.py
  A   grokcore.component/trunk/src/grokcore/component/tests/adapter/globaladapter.py

-=-
Modified: grokcore.component/trunk/CHANGES.txt
===================================================================
--- grokcore.component/trunk/CHANGES.txt	2009-04-09 15:14:35 UTC (rev 99033)
+++ grokcore.component/trunk/CHANGES.txt	2009-04-09 15:16:37 UTC (rev 99034)
@@ -4,10 +4,19 @@
 1.6 (unreleased)
 ----------------
 
+* Add support for registering global adapters at module level::
+
+    grok.global_adapter(factory, (IAdapted1, IAdapted2,), IProvided, name=u"name")
+    
+  Only 'factory' is required. If only a single interface is adapted, the
+  second argument may be a single interface instead of a tuple. If the
+  component has declared adapted/provided interfaces, the second and third
+  arguments may be omitted.
+
 * Add support for an @provider decorator to let a function directly provide
   an interface::
   
-    @provider(IFoo, IBar)
+    @grok.provider(IFoo, IBar)
     def some_function():
         ...
         
@@ -15,7 +24,7 @@
 
 * Add support for named adapters with the @adapter decorator::
 
-    @adapter(IAdaptedOne, IAdaptedTwo, name=u"foo")
+    @grok.adapter(IAdaptedOne, IAdaptedTwo, name=u"foo")
     def some_function(one, two):
         ...
 

Modified: grokcore.component/trunk/src/grokcore/component/__init__.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/__init__.py	2009-04-09 15:14:35 UTC (rev 99033)
+++ grokcore.component/trunk/src/grokcore/component/__init__.py	2009-04-09 15:16:37 UTC (rev 99034)
@@ -22,7 +22,7 @@
 
 from martian import baseclass
 from grokcore.component.directive import (
-    context, name, title, description, provides, global_utility, direct)
+    context, name, title, description, provides, global_utility, global_adapter, direct)
 from grokcore.component.decorators import subscribe, adapter, implementer, provider
 from martian.error import GrokError, GrokImportError
 

Modified: grokcore.component/trunk/src/grokcore/component/directive.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/directive.py	2009-04-09 15:14:35 UTC (rev 99033)
+++ grokcore.component/trunk/src/grokcore/component/directive.py	2009-04-09 15:16:37 UTC (rev 99034)
@@ -36,6 +36,33 @@
             name = grokcore.component.name.bind().get(factory)
         return (factory, provides, name, direct)
 
+class global_adapter(martian.MultipleTimesDirective):
+    scope = martian.MODULE
+
+    def factory(self, factory, adapts=None, provides=None, name=u''):
+        if provides is not None and not IInterface.providedBy(provides):
+            raise GrokImportError(
+                "You can only pass an interface to the "
+                "provides argument of %s." % self.name)
+
+        if provides is None:
+            provides = grokcore.component.provides.bind().get(factory)
+        
+        if adapts is None:
+            adapts = getattr(factory, '__component_adapts__', None)
+            if adapts is None:
+                adapts = grokcore.component.context.bind().get(factory)
+        
+        if not isinstance(adapts, (list, tuple,)):
+            adapts = (adapts,)
+        elif isinstance(adapts, list):
+            adapts = tuple(adapts)
+        
+        if not name:
+            name = grokcore.component.name.bind().get(factory)
+        
+        return (factory, adapts, provides, name)
+
 class name(martian.Directive):
     scope = martian.CLASS
     store = martian.ONCE
@@ -61,4 +88,4 @@
 class provides(martian.Directive):
     scope = martian.CLASS
     store = martian.ONCE
-    validate = martian.validateInterface
+    validate = martian.validateInterface
\ No newline at end of file

Modified: grokcore.component/trunk/src/grokcore/component/meta.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/meta.py	2009-04-09 15:14:35 UTC (rev 99033)
+++ grokcore.component/trunk/src/grokcore/component/meta.py	2009-04-09 15:16:37 UTC (rev 99034)
@@ -156,7 +156,20 @@
 
         return True
 
+class GlobalAdapterDirectiveGrokker(martian.GlobalGrokker):
 
+    def grok(self, name, module, module_info, config, **kw):
+        infos = grokcore.component.global_adapter.bind().get(module=module)
+
+        for factory, adapts, provides, name in infos:
+            config.action(
+                discriminator=('adapter', adapts, provides, name),
+                callable=component.provideAdapter,
+                args=(factory, adapts, provides, name),
+                )
+
+        return True
+
 class SubscriberGrokker(martian.GlobalGrokker):
 
     def grok(self, name, module, module_info, config, **kw):

Added: grokcore.component/trunk/src/grokcore/component/tests/adapter/globaladapter.py
===================================================================
--- grokcore.component/trunk/src/grokcore/component/tests/adapter/globaladapter.py	                        (rev 0)
+++ grokcore.component/trunk/src/grokcore/component/tests/adapter/globaladapter.py	2009-04-09 15:16:37 UTC (rev 99034)
@@ -0,0 +1,89 @@
+"""
+  >>> grok.testing.grok(__name__)
+  >>> from zope.component import getAdapter, getMultiAdapter
+  
+  >>> cave = Cave()
+  >>> fireplace = Fireplace()
+  
+  >>> home = IHome(cave)
+  >>> home.id
+  u'one'
+  
+  >>> home = getAdapter(cave, IHome, name=u"two")
+  >>> home.id
+  u'two'
+  
+  >>> home = getAdapter(cave, IHome, name=u"three")
+  >>> home.id
+  u'three'
+  
+  >>> home = getAdapter(cave, IHome, name=u"four")
+  >>> home.id
+  u'four'
+  
+  >>> home = getAdapter(fireplace, IHome, name=u"five")
+  >>> home.id
+  u'five'
+  
+  >>> home = getMultiAdapter((cave, fireplace), IHome)
+  >>> home.id
+  u'six'
+  
+"""
+
+import grokcore.component as grok
+from zope import interface
+
+class Cave(grok.Context):
+    pass
+
+class Fireplace(object):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class Home(object):
+    grok.implements(IHome)
+    
+    def __init__(self, id):
+        self.id = id
+
+class CaveHomeFactory(object):
+    grok.implements(IHome)
+    
+    def __init__(self, id):
+        self.id = id
+    
+    def __call__(self, context):
+        return Home(self.id)
+
+class CaveFireplaceHomeFactory(object):
+    def __init__(self, id):
+        self.id = id
+    
+    def __call__(self, cave, fireplace):
+        return Home(self.id)
+
+factory1 = CaveHomeFactory(u"one")
+factory2 = CaveHomeFactory(u"two")
+factory3 = CaveHomeFactory(u"three")
+factory4 = CaveHomeFactory(u"four")
+factory5 = CaveHomeFactory(u"five")
+factory6 = CaveFireplaceHomeFactory(u"six")
+
+# make some direct assertions
+
+grok.implementer(IHome)(factory3)
+grok.implementer(IHome)(factory4)
+grok.implementer(IHome)(factory5)
+grok.implementer(IHome)(factory6)
+
+grok.adapter(Fireplace)(factory5)
+
+grok.global_adapter(factory1, Cave, IHome)                  # should accept single value for adapts
+grok.global_adapter(factory2, (Cave,), IHome, name="two")   # should accept tuple for adapts
+grok.global_adapter(factory3, Cave, name="three")           # should look at the provided interface
+grok.global_adapter(factory4, name=u"four")                 # should pick the canonical context
+grok.global_adapter(factory5, name="five")                  # should use __component_adapts__
+grok.global_adapter(factory6, (Cave, Fireplace,))           # should work as multi-adapter



More information about the Checkins mailing list