[Checkins] SVN: grok/branches/jw-adapter-decorator/src/grok/ Reuse the z.c.adapter decorator and reimplement the implementer

Jan-Wijbrand Kolman jw at infrae.com
Wed Jun 6 09:28:26 EDT 2007


Log message for revision 76411:
  Reuse the z.c.adapter decorator and reimplement the implementer
  decorator.
  
  The implementer decorator implementation is now a copy of that on the
  jw-annotate-implementers-on-module branch of zope.interface.
  
  When z.i. is released with this feature, the grok implementer decorator
  can be removed.
  
  Tests might be expanded a little I guess.

Changed:
  U   grok/branches/jw-adapter-decorator/src/grok/__init__.py
  U   grok/branches/jw-adapter-decorator/src/grok/_grok.py
  U   grok/branches/jw-adapter-decorator/src/grok/meta.py
  U   grok/branches/jw-adapter-decorator/src/grok/tests/adapter/adapterdecorator.py

-=-
Modified: grok/branches/jw-adapter-decorator/src/grok/__init__.py
===================================================================
--- grok/branches/jw-adapter-decorator/src/grok/__init__.py	2007-06-06 13:25:02 UTC (rev 76410)
+++ grok/branches/jw-adapter-decorator/src/grok/__init__.py	2007-06-06 13:28:25 UTC (rev 76411)
@@ -15,7 +15,7 @@
 """
 
 from zope.interface import implements
-from zope.component import adapts
+from zope.component import adapts, adapter
 from zope.event import notify
 from zope.app.component.hooks import getSite
 from zope.lifecycleevent import (
@@ -40,7 +40,7 @@
                             define_permission, require, site)
 from grok._grok import do_grok as grok  # Avoid name clash within _grok
 from grok._grok import SubscribeDecorator as subscribe
-from grok._grok import adapter, implementer
+from grok._grok import implementer
 from grok.error import GrokError, GrokImportError
 from grok.formlib import action, AutoFields, Fields
 from grok.util import url

Modified: grok/branches/jw-adapter-decorator/src/grok/_grok.py
===================================================================
--- grok/branches/jw-adapter-decorator/src/grok/_grok.py	2007-06-06 13:25:02 UTC (rev 76410)
+++ grok/branches/jw-adapter-decorator/src/grok/_grok.py	2007-06-06 13:28:25 UTC (rev 76411)
@@ -107,42 +107,31 @@
             frame.f_locals['__grok_subscribers__'] = subscribers = []
         subscribers.append((function, self.subscribed))
 
-def implementer(interface):
-    frame = sys._getframe(1)
-    if not frame_is_module(frame):
-        raise GrokImportError(
-            "@grok.implementer can only be used on module level.")
+from zope.interface.declarations import DescriptorAwareMetaClasses, Implements
+class implementer:
 
-    def decorated(function):
-        setattr(function, '__grok_implementer__', interface)
-        return function
+    # XXX This is a copy of z.i.implementer *with* the additional annotating
+    # behaviour. This will be part of future zope.interface release. See:
+    # http://svn.zope.org/zope.interface/branches/jw-annotate-implementers-on-module/
 
-    return decorated
+    def __init__(self, *interfaces):
+        self.interfaces = interfaces
 
-def adapter(interface_or_function, *additional_interfaces):
-    frame = sys._getframe(1)
-    if not frame_is_module(frame):
-        raise GrokImportError(
-            "@grok.adapter can only be used on module level.")
+    def __call__(self, ob):
+        if isinstance(ob, DescriptorAwareMetaClasses):
+            raise TypeError("Can't use implementer with classes.  Use one of "
+                            "the class-declaration functions instead."
+                            )
 
-    def decorated(function):
-        implementer = getattr(function, '__grok_implementer__', None)
-        if implementer is None:
-            raise GrokImportError(
-                "@grok.implementer should be used as inner decorator.")
-
-        implementers = frame.f_locals.get('__grok_implementers__', None)
+        frame = sys._getframe(1)
+        implementers = frame.f_locals.get('__implementers__', None)
         if implementers is None:
-            frame.f_locals['__grok_implementers__'] = implementers = []
-        implementers.append((function, implementer, interfaces))
-        return function
+            frame.f_locals['__implementers__'] = implementers = []
+        implementers.append(ob)
 
-    if isinstance(interface_or_function, (types.FunctionType,)):
-        # The adapter decorator is without argument, which means the
-        # function to-be-decorated is passed a first argument.
-        function = interface_or_function
-        interfaces = None # we'll try to find a context during grok-time
-        return decorated(function)
-    else:
-        interfaces = (interface_or_function,)+additional_interfaces
-        return decorated
+        spec = Implements(*self.interfaces)
+        try:
+            ob.__implemented__ = spec
+        except AttributeError:
+            raise TypeError("Can't declare implements", ob)
+        return ob

Modified: grok/branches/jw-adapter-decorator/src/grok/meta.py
===================================================================
--- grok/branches/jw-adapter-decorator/src/grok/meta.py	2007-06-06 13:25:02 UTC (rev 76410)
+++ grok/branches/jw-adapter-decorator/src/grok/meta.py	2007-06-06 13:28:25 UTC (rev 76411)
@@ -261,15 +261,16 @@
 class AdapterDecoratorGrokker(grok.ModuleGrokker):
 
     def register(self, context, module_info, templates):
-        implementers = module_info.getAnnotation('grok.implementers', [])
-        for function, implementer, interfaces in implementers:
+        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=implementer)
+                function, adapts=interfaces, provides=function.__implemented__)
 
 class StaticResourcesGrokker(grok.ModuleGrokker):
 

Modified: grok/branches/jw-adapter-decorator/src/grok/tests/adapter/adapterdecorator.py
===================================================================
--- grok/branches/jw-adapter-decorator/src/grok/tests/adapter/adapterdecorator.py	2007-06-06 13:25:02 UTC (rev 76410)
+++ grok/branches/jw-adapter-decorator/src/grok/tests/adapter/adapterdecorator.py	2007-06-06 13:28:25 UTC (rev 76411)
@@ -1,28 +1,11 @@
 """
- at grok.adapter can only be used on module level::
-
-  >>> function_context()
-  Traceback (most recent call last):
-    ...
-  GrokImportError: @grok.adapter can only be used on module level.
-
-  >>> class_context()
-  Traceback (most recent call last):
-    ...
-  GrokImportError: @grok.adapter can only be used on module level.
-
-  >>> @grok.adapter(Cave)
-  ... def func():
-  ...     pass
-  Traceback (most recent call last):
-    ...
-  GrokImportError: @grok.implementer should be used as inner decorator.
-
   >>> grok.grok(__name__)
+  >>>
   >>> cave = Cave()
   >>> home = IHome(cave)
   >>> IHome.providedBy(home)
   True
+  >>>
   >>> isinstance(home, Home)
   True
   >>> anotherhome = IAnotherHome(cave)
@@ -35,6 +18,11 @@
   True
   >>> isinstance(morehome, Home)
   True
+  >>> yetanotherhome = IYetAnotherHome(cave)
+  >>> IHome.providedBy(yetanotherhome)
+  True
+  >>> isinstance(yetanotherhome, Home)
+  True
 """
 
 import grok
@@ -43,19 +31,6 @@
 class IDummy(interface.Interface):
     pass
 
-def function_context():
-    @grok.adapter(IDummy)
-    @grok.implementer(IDummy)
-    def subscriber():
-        pass
-
-def class_context():
-    class Wrapper:
-        @grok.adapter(IDummy)
-        @grok.implementer(IDummy)
-        def subscriber(self):
-            pass
-
 class ICave(interface.Interface):
     pass
 
@@ -68,6 +43,9 @@
 class IMoreHome(interface.Interface):
     pass
 
+class IYetAnotherHome(interface.Interface):
+    pass
+
 class Cave(grok.Model):
     grok.implements(ICave)
     pass
@@ -89,3 +67,7 @@
 @grok.implementer(IMoreHome)
 def more_home_for_cave(cave):
     return Home()
+
+ at grok.implementer(IYetAnotherHome)
+def yet_another_home_for_cave(cave):
+    return Home()



More information about the Checkins mailing list