[Checkins] SVN: grokcore.component/branches/sylvain-subscribers/src/grokcore/component/ Add more tests.
Sylvain Viollon
sylvain at infrae.com
Wed Jan 26 08:31:06 EST 2011
Log message for revision 119944:
Add more tests.
Support subscriber registration using decorators.
Changed:
U grokcore.component/branches/sylvain-subscribers/src/grokcore/component/decorators.py
U grokcore.component/branches/sylvain-subscribers/src/grokcore/component/meta.py
U grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/event/subscriber.py
A grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/decorator.py
U grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/ordered_multisubscribers.py
U grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/subscribers.py
U grokcore.component/branches/sylvain-subscribers/src/grokcore/component/util.py
-=-
Modified: grokcore.component/branches/sylvain-subscribers/src/grokcore/component/decorators.py
===================================================================
--- grokcore.component/branches/sylvain-subscribers/src/grokcore/component/decorators.py 2011-01-26 11:31:48 UTC (rev 119943)
+++ grokcore.component/branches/sylvain-subscribers/src/grokcore/component/decorators.py 2011-01-26 13:31:06 UTC (rev 119944)
@@ -37,14 +37,17 @@
raise GrokImportError("@grok.subscribe requires at least one "
"argument.")
+ # Add the function and subscribed interfaces to the
+ # grok.subscribers module annotation.
subscribers = frame.f_locals.get('__grok_subscribers__', None)
if subscribers is None:
frame.f_locals['__grok_subscribers__'] = subscribers = []
subscribers.append((function, self.subscribed))
- # Also add __grok_adapts__ attribute to the function so that
- # you can manually register the subscriber with, say,
- # provideHandler.
+ # Also store the subscribed interfaces on the
+ # attribute__component_adapts__ for provideHandler to register
+ # the subscriber (in case you don't grok your package and
+ # register it manually)
return zope.component.adapter(*self.subscribed)(function)
class adapter(zope.component.adapter):
@@ -59,18 +62,18 @@
if type(interfaces[0]) is types.FunctionType:
raise GrokImportError(
"@grok.adapter requires at least one argument.")
-
+
self.name = u""
-
+
if kw:
if 'name' in kw:
self.name = kw.pop('name')
if kw:
raise GrokImportError(
"@grok.adapter got unexpected keyword arguments: %s" % ','.join(kw.keys()))
-
+
zope.component.adapter.__init__(self, *interfaces)
-
+
def __call__(self, ob):
ob = zope.component.adapter.__call__(self, ob)
if self.name:
@@ -87,6 +90,7 @@
if adapters is None:
frame.f_locals['__grok_adapters__'] = adapters = []
adapters.append(ob)
+
return zope.interface.implementer.__call__(self, ob)
class provider:
Modified: grokcore.component/branches/sylvain-subscribers/src/grokcore/component/meta.py
===================================================================
--- grokcore.component/branches/sylvain-subscribers/src/grokcore/component/meta.py 2011-01-26 11:31:48 UTC (rev 119943)
+++ grokcore.component/branches/sylvain-subscribers/src/grokcore/component/meta.py 2011-01-26 13:31:06 UTC (rev 119944)
@@ -13,12 +13,15 @@
##############################################################################
"""Grokkers for the various components."""
+import operator
+
import martian
import martian.util
import grokcore.component
import zope.component.interface
from zope import component, interface
from martian.error import GrokError
+from zope.interface import implementedBy
def _provides(component, module=None, **data):
martian.util.check_implements_one(component)
@@ -125,11 +128,18 @@
return True
-class AdapterDecoratorGrokker(martian.GlobalGrokker):
+class ImplementerDecoratorGrokker(martian.GlobalGrokker):
def grok(self, name, module, module_info, config, **kw):
adapters = module_info.getAnnotation('grok.adapters', [])
+ subscribers = set(map(operator.itemgetter(0),
+ module_info.getAnnotation('grok.subscribers', [])))
+
for function in adapters:
+ if function in subscribers:
+ # We don't register function that uses the
+ # grok.subscribe directive with grok.implementer.
+ continue
interfaces = getattr(function, '__component_adapts__', None)
if interfaces is None:
context = grokcore.component.context.bind().get(module)
@@ -205,16 +215,29 @@
subscribers = module_info.getAnnotation('grok.subscribers', [])
for factory, subscribed in subscribers:
- config.action(
- discriminator=None,
- callable=component.provideHandler,
- args=(factory, subscribed),
- )
+ provides = None
+ implemented = list(implementedBy(factory))
+ if len(implemented) == 1:
+ provides = implemented[0]
+ # provideHandler is the same as
+ # provideSubscriptionAdapter, where provides=None. You
+ # can't use provideSubscriptionAdapter with provides=None
+ # since None is used as a marker value.
+ if provides is None:
+ config.action(
+ discriminator=None,
+ callable=component.provideHandler,
+ args=(factory, subscribed))
+ else:
+ config.action(
+ discriminator=None,
+ callable=component.provideSubscriptionAdapter,
+ args=(factory, subscribed, provides))
+
for iface in subscribed:
config.action(
discriminator=None,
callable=zope.component.interface.provideInterface,
- args=('', iface)
- )
+ args=('', iface))
return True
Modified: grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/event/subscriber.py
===================================================================
--- grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/event/subscriber.py 2011-01-26 11:31:48 UTC (rev 119943)
+++ grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/event/subscriber.py 2011-01-26 13:31:06 UTC (rev 119944)
@@ -8,9 +8,9 @@
['Manfred']
>>> mammoths2
['Manfred']
-
-The decorated event handling function can also be called directly:
-
+
+The decorated event handling function can also be called directly:
+
>>> mammothAdded(Mammoth('Max'),None)
>>> mammoths
['Manfred', 'Max']
Added: grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/decorator.py
===================================================================
--- grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/decorator.py (rev 0)
+++ grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/decorator.py 2011-01-26 13:31:06 UTC (rev 119944)
@@ -0,0 +1,39 @@
+"""
+ >>> grok.testing.grok(__name__)
+
+ >>> cave = Cave('sweet home')
+
+ >>> subscribers = grok.querySubscribers((cave,), IActivity)
+ >>> subscribers
+ [<grokcore.component.tests.subscriber.decorator.DebuggingGrokcore object at ...>]
+
+ Subscribers are not registered as adapters:
+
+ >>> component.queryAdapter(cave, IActivity)
+
+"""
+
+
+import grokcore.component as grok
+from zope import interface, component
+
+
+class Cave(grok.Context):
+
+ def __init__(self, name):
+ self.name = name
+
+class IActivity(interface.Interface):
+ pass
+
+
+class DebuggingGrokcore(object):
+
+ def __init__(self, where):
+ self.where = where
+
+
+ at grok.subscribe(Cave)
+ at grok.implementer(IActivity)
+def debugging(content):
+ return DebuggingGrokcore(content)
Property changes on: grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/decorator.py
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision
Modified: grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/ordered_multisubscribers.py
===================================================================
--- grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/ordered_multisubscribers.py 2011-01-26 11:31:48 UTC (rev 119943)
+++ grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/ordered_multisubscribers.py 2011-01-26 13:31:06 UTC (rev 119944)
@@ -7,17 +7,35 @@
You can query a subscribers using multiple components and sort them
using `grok.order` information:
- >>> subscribers = grok.queryOrderedSubscribers((cave, martijn), IActivity)
- >>> subscribers
+ >>> ordered_subscribers = grok.queryOrderedSubscribers((cave, martijn), IActivity)
+ >>> ordered_subscribers
[<grokcore.component.tests.subscriber.ordered_multisubscribers.Cooking object at ...>,
<grokcore.component.tests.subscriber.ordered_multisubscribers.Gardening object at ...>,
<grokcore.component.tests.subscriber.ordered_multisubscribers.Cleaning object at ...>]
- >>> _ = map(lambda a: a.do(), subscribers)
+ >>> _ = map(lambda a: a.do(), ordered_subscribers)
Martijn is cooking in Tilburg cave!
Martijn is growing pumpkins in Tilburg cave!
Martijn is cleaning the Tilburg cave.
+ Or choose not to:
+
+ >>> subscribers = grok.querySubscribers((cave, martijn), IActivity)
+
+ (still need to sort them on class name in order to have a working doctest)
+
+ >>> subscribers = sorted(subscribers, key=lambda s: s.__class__.__name__)
+ >>> subscribers
+ [<grokcore.component.tests.subscriber.ordered_multisubscribers.Cleaning object at ...>,
+ <grokcore.component.tests.subscriber.ordered_multisubscribers.Cooking object at ...>,
+ <grokcore.component.tests.subscriber.ordered_multisubscribers.Gardening object at ...>]
+
+ >>> _ = map(lambda a: a.do(), subscribers)
+ Martijn is cleaning the Tilburg cave.
+ Martijn is cooking in Tilburg cave!
+ Martijn is growing pumpkins in Tilburg cave!
+
+
"""
import grokcore.component as grok
Modified: grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/subscribers.py
===================================================================
--- grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/subscribers.py 2011-01-26 11:31:48 UTC (rev 119943)
+++ grokcore.component/branches/sylvain-subscribers/src/grokcore/component/tests/subscriber/subscribers.py 2011-01-26 13:31:06 UTC (rev 119944)
@@ -14,10 +14,14 @@
Saturday cleaning sweet home!
Wednesday cleaning sweet home!
+ Subscribers are not registered as adapters:
+
+ >>> component.queryAdapter(cave, ICleaner)
+
"""
import grokcore.component as grok
-from zope import interface
+from zope import interface, component
class Cave(grok.Context):
Modified: grokcore.component/branches/sylvain-subscribers/src/grokcore/component/util.py
===================================================================
--- grokcore.component/branches/sylvain-subscribers/src/grokcore/component/util.py 2011-01-26 11:31:48 UTC (rev 119943)
+++ grokcore.component/branches/sylvain-subscribers/src/grokcore/component/util.py 2011-01-26 13:31:06 UTC (rev 119944)
@@ -38,6 +38,10 @@
def querySubscribers(components, interface):
"""Query a list of subscribers on `component` which implements
- `interface`
+ `interface`.
+
+ :parameter components: list of components to look the subscribers for.
+ :parameter interface: interface that the subscribers should provides.
+ :return: a list of subscribers.
"""
return component.subscribers(components, interface)
More information about the checkins
mailing list