[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