[Checkins] SVN: grok/branches/grok-martian/src/grok/ Port adapter decorator feature to martian branch.

Jan-Wijbrand Kolman jw at infrae.com
Wed Jun 27 05:05:58 EDT 2007


Log message for revision 77119:
  Port adapter decorator feature to martian branch.

Changed:
  U   grok/branches/grok-martian/src/grok/__init__.py
  U   grok/branches/grok-martian/src/grok/_grok.py
  U   grok/branches/grok-martian/src/grok/meta.py
  A   grok/branches/grok-martian/src/grok/tests/adapter/adapterdecorator.py
  A   grok/branches/grok-martian/src/grok/tests/adapter/functionasargument_fixture.py
  A   grok/branches/grok-martian/src/grok/tests/adapter/noarguments_fixture.py

-=-
Modified: grok/branches/grok-martian/src/grok/__init__.py
===================================================================
--- grok/branches/grok-martian/src/grok/__init__.py	2007-06-27 08:44:15 UTC (rev 77118)
+++ grok/branches/grok-martian/src/grok/__init__.py	2007-06-27 09:05:56 UTC (rev 77119)
@@ -41,6 +41,7 @@
 from grok._grok import do_grok as grok  # Avoid name clash within _grok
 from grok._grok import grok_component
 from grok._grok import SubscribeDecorator as subscribe
+from grok._grok import adapter, implementer
 from martian.error import GrokError, GrokImportError
 from grok.formlib import action, AutoFields, Fields
 from grok.util import url

Modified: grok/branches/grok-martian/src/grok/_grok.py
===================================================================
--- grok/branches/grok-martian/src/grok/_grok.py	2007-06-27 08:44:15 UTC (rev 77118)
+++ grok/branches/grok-martian/src/grok/_grok.py	2007-06-27 09:05:56 UTC (rev 77119)
@@ -15,6 +15,7 @@
 """
 import os
 import sys
+import types
 
 from zope import component
 from zope import interface
@@ -52,7 +53,7 @@
 
     # now grok the grokkers
     martian.grok_module(scan.module_info_from_module(meta), the_module_grokker)
-   
+
 def addSiteHandler(site, event):
     sitemanager = LocalSiteManager(site)
     # LocalSiteManager creates the 'default' folder in its __init__.
@@ -89,15 +90,15 @@
 
 def prepare_grok(name, module, kw):
     module_info = scan.module_info_from_module(module)
-    
+
     # XXX hardcoded in here which base classes are possible contexts
     # this should be made extensible
     possible_contexts = martian.scan_for_classes(module, [grok.Model,
                                                           grok.LocalUtility,
                                                           grok.Container])
     context = determine_module_context(module_info, possible_contexts)
-    
-    kw['context'] = context    
+
+    kw['context'] = context
     kw['module_info'] = module_info
     kw['templates'] = templatereg.TemplateRegistry()
 
@@ -137,3 +138,30 @@
         if subscribers is None:
             frame.f_locals['__grok_subscribers__'] = subscribers = []
         subscribers.append((function, self.subscribed))
+
+from zope.component._declaration import adapter as _adapter
+class adapter(_adapter):
+
+    def __init__(self, *interfaces):
+        # Override the z.c.adapter decorator to force sanity checking
+        # and have better error reporting.
+        if not interfaces:
+            raise GrokImportError(
+                "@grok.adapter requires at least one argument.")
+        if type(interfaces[0]) is types.FunctionType:
+            raise GrokImportError(
+                "@grok.adapter requires at least one argument.")
+        self.interfaces = interfaces
+
+from zope.interface.declarations import implementer as _implementer
+class implementer(_implementer):
+
+    def __call__(self, ob):
+        # XXX we do not have function grokkers (yet) so we put the annotation
+        # on the module.
+        frame = sys._getframe(1)
+        implementers = frame.f_locals.get('__implementers__', None)
+        if implementers is None:
+            frame.f_locals['__implementers__'] = implementers = []
+        implementers.append(ob)
+        return _implementer.__call__(self, ob)

Modified: grok/branches/grok-martian/src/grok/meta.py
===================================================================
--- grok/branches/grok-martian/src/grok/meta.py	2007-06-27 08:44:15 UTC (rev 77118)
+++ grok/branches/grok-martian/src/grok/meta.py	2007-06-27 09:05:56 UTC (rev 77119)
@@ -59,7 +59,7 @@
                                  provides=provides,
                                  name=name)
         return True
-        
+
 class MultiAdapterGrokker(martian.ClassGrokker):
     component_class = grok.MultiAdapter
 
@@ -93,7 +93,7 @@
         methods = util.methods_from_class(factory)
 
         default_permission = get_default_permission(factory)
-        
+
         for method in methods:
             # Make sure that the class inherits MethodPublisher, so that the
             # views have a location
@@ -113,7 +113,7 @@
                                  default_permission)
             make_checker(factory, method_view, permission)
         return True
-    
+
 class ViewGrokker(martian.ClassGrokker):
     component_class = grok.View
 
@@ -179,7 +179,7 @@
         # protect view, public by default
         default_permission = get_default_permission(factory)
         make_checker(factory, factory, default_permission)
-    
+
         # safety belt: make sure that the programmer didn't use
         # @grok.require on any of the view's methods.
         methods = util.methods_from_class(factory)
@@ -190,8 +190,8 @@
                                 'for XML-RPC methods.'
                                 % (method.__name__, factory), factory)
         return True
-    
 
+
 class JSONGrokker(martian.ClassGrokker):
     component_class = grok.JSON
 
@@ -200,7 +200,7 @@
         methods = util.methods_from_class(factory)
 
         default_permission = get_default_permission(factory)
-        
+
         for method in methods:
             # Create a new class with a __view_name__ attribute so the
             # JSON class knows what method to call.
@@ -221,7 +221,7 @@
                                  default_permission)
             make_checker(factory, method_view, permission)
         return True
-    
+
 class TraverserGrokker(martian.ClassGrokker):
     component_class = grok.Traverser
 
@@ -231,14 +231,14 @@
                                  adapts=(factory_context, IBrowserRequest),
                                  provides=IBrowserPublisher)
         return True
-    
+
 class ModulePageTemplateGrokker(martian.InstanceGrokker):
     # this needs to happen before any other grokkers execute that actually
     # use the templates
     priority = 1000
 
     component_class = grok.PageTemplate
-    
+
     def grok(self, name, instance, context, module_info, templates):
         templates.register(name, instance)
         instance._annotateGrokInfo(name, module_info.dotted_name)
@@ -269,6 +269,21 @@
                 zope.component.interface.provideInterface('', iface)
         return True
 
+class AdapterDecoratorGrokker(martian.GlobalGrokker):
+
+    def grok(self, name, module, context, module_info, templates):
+        implementers = module_info.getAnnotation('implementers', [])
+        for function in implementers:
+            interfaces = getattr(function, '__component_adapts__', None)
+            if interfaces is None:
+                # There's no explicit interfaces defined, so we assume the
+                # module context to be the thing adapted.
+                util.check_context(module_info.getModule(), context)
+                interfaces = (context, )
+            component.provideAdapter(
+                function, adapts=interfaces, provides=function.__implemented__)
+        return True
+
 class StaticResourcesGrokker(martian.GlobalGrokker):
 
     def grok(self, name, module, context, module_info, templates):
@@ -438,10 +453,10 @@
 
     if setup is not None:
         setup(utility)
-        
+
     site_manager.registerUtility(utility, provided=provides,
                                  name=name)
-    
+
 class DefinePermissionGrokker(martian.GlobalGrokker):
 
     priority = 1500
@@ -459,10 +474,10 @@
                                      name=permission)
 
         return True
-    
+
 class AnnotationGrokker(martian.ClassGrokker):
     component_class = grok.Annotation
- 
+
     def grok(self, name, factory, context, module_info, templates):
         adapter_context = util.determine_class_context(factory, context)
         provides = util.class_annotation(factory, 'grok.provides', None)
@@ -508,7 +523,7 @@
                                       name='%s.%s' % (module_info.dotted_name,
                                                       name))
         return True
-    
+
 class IndexesGrokker(martian.InstanceGrokker):
     component_class = components.IndexesClass
 
@@ -530,14 +545,14 @@
             adapts=(site,
                     grok.IObjectAddedEvent))
         return True
-    
+
 class IndexesSetupSubscriber(object):
     def __init__(self, catalog_name, indexes, context, module_info):
         self.catalog_name = catalog_name
         self.indexes = indexes
         self.context = context
         self.module_info = module_info
-        
+
     def __call__(self, site, event):
         # make sure we have an intids
         self._createIntIds(site)
@@ -567,7 +582,7 @@
         catalog = Catalog()
         setupUtility(site, catalog, ICatalog, name=self.catalog_name)
         return catalog
-    
+
     def _createIntIds(self, site):
         """Create intids if needed, and return it.
         """

Added: grok/branches/grok-martian/src/grok/tests/adapter/adapterdecorator.py
===================================================================
--- grok/branches/grok-martian/src/grok/tests/adapter/adapterdecorator.py	                        (rev 0)
+++ grok/branches/grok-martian/src/grok/tests/adapter/adapterdecorator.py	2007-06-27 09:05:56 UTC (rev 77119)
@@ -0,0 +1,71 @@
+"""
+  >>> grok.grok(__name__)
+  >>>
+  >>> cave = Cave()
+  >>> home = IHome(cave)
+  >>> IHome.providedBy(home)
+  True
+  >>>
+  >>> isinstance(home, Home)
+  True
+  >>> morehome = IMoreHome(cave)
+  >>> IHome.providedBy(morehome)
+  True
+  >>> isinstance(morehome, Home)
+  True
+  >>> yetanotherhome = IYetAnotherHome(cave)
+  >>> IHome.providedBy(yetanotherhome)
+  True
+  >>> isinstance(yetanotherhome, Home)
+  True
+
+  >>> from grok.tests.adapter import noarguments_fixture
+  Traceback (most recent call last):
+  ...
+  GrokImportError: @grok.adapter requires at least one argument.
+
+  >>> from grok.tests.adapter import functionasargument_fixture
+  Traceback (most recent call last):
+  ...
+  GrokImportError: @grok.adapter requires at least one argument.
+
+"""
+
+import grok
+from zope import interface
+
+class IDummy(interface.Interface):
+    pass
+
+class ICave(interface.Interface):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class IMoreHome(interface.Interface):
+    pass
+
+class IYetAnotherHome(interface.Interface):
+    pass
+
+class Cave(grok.Model):
+    grok.implements(ICave)
+    pass
+
+class Home(object):
+    grok.implements(IHome)
+
+ at grok.adapter(Cave)
+ at grok.implementer(IHome)
+def home_for_cave(cave):
+    return Home()
+
+ at grok.adapter(ICave)
+ at grok.implementer(IMoreHome)
+def more_home_for_cave(cave):
+    return Home()
+
+ at grok.implementer(IYetAnotherHome)
+def yet_another_home_for_cave(cave):
+    return Home()

Added: grok/branches/grok-martian/src/grok/tests/adapter/functionasargument_fixture.py
===================================================================
--- grok/branches/grok-martian/src/grok/tests/adapter/functionasargument_fixture.py	                        (rev 0)
+++ grok/branches/grok-martian/src/grok/tests/adapter/functionasargument_fixture.py	2007-06-27 09:05:56 UTC (rev 77119)
@@ -0,0 +1,10 @@
+import grok
+from zope import interface
+
+class IDummy(interface.Interface):
+    pass
+
+ at grok.adapter
+ at grok.implementer(IDummy)
+def decorator_called_with_function_as_argument(cave):
+    pass

Added: grok/branches/grok-martian/src/grok/tests/adapter/noarguments_fixture.py
===================================================================
--- grok/branches/grok-martian/src/grok/tests/adapter/noarguments_fixture.py	                        (rev 0)
+++ grok/branches/grok-martian/src/grok/tests/adapter/noarguments_fixture.py	2007-06-27 09:05:56 UTC (rev 77119)
@@ -0,0 +1,10 @@
+import grok
+from zope import interface
+
+class IDummy(interface.Interface):
+    pass
+
+ at grok.adapter()
+ at grok.implementer(IDummy)
+def decorator_called_with_no_arguments(cave):
+    pass



More information about the Checkins mailing list