[Checkins] SVN: grok/trunk/src/grok/ Do the right thing for local utilities that implement various kinds of interfaces that do or do not subclass from IPersistent and friends and use grok.provides in various manners

Wolfgang Schnerring wosc at wosc.de
Sun Jan 7 06:14:00 EST 2007


Log message for revision 71755:
  Do the right thing for local utilities that implement various kinds of interfaces that do or do not subclass from IPersistent and friends and use grok.provides in various manners

Changed:
  U   grok/trunk/src/grok/directive.py
  U   grok/trunk/src/grok/ftests/utility/local.py
  U   grok/trunk/src/grok/meta.py
  A   grok/trunk/src/grok/tests/utility/local_implementsmany.py
  A   grok/trunk/src/grok/tests/utility/local_implementsnone.py
  A   grok/trunk/src/grok/tests/utility/local_implementsnone2.py
  U   grok/trunk/src/grok/util.py

-=-
Modified: grok/trunk/src/grok/directive.py
===================================================================
--- grok/trunk/src/grok/directive.py	2007-01-07 10:59:36 UTC (rev 71754)
+++ grok/trunk/src/grok/directive.py	2007-01-07 11:13:59 UTC (rev 71755)
@@ -19,6 +19,7 @@
 from zope import interface
 from zope.interface.interfaces import IInterface
 
+import grok
 from grok import util
 from grok.error import GrokImportError
 
@@ -195,6 +196,8 @@
     def __init__(self, factory, provides=None, name=u'',
                  setup=None, hide=True, name_in_container=None):
         self.factory = factory
+        if provides is None:
+            provides = util.class_annotation(factory, 'grok.provides', None)
         self.provides = provides
         self.name = name
         self.setup = setup

Modified: grok/trunk/src/grok/ftests/utility/local.py
===================================================================
--- grok/trunk/src/grok/ftests/utility/local.py	2007-01-07 10:59:36 UTC (rev 71754)
+++ grok/trunk/src/grok/ftests/utility/local.py	2007-01-07 11:13:59 UTC (rev 71755)
@@ -4,7 +4,7 @@
 
   >>> import grok
   >>> from zope import component
-  >>> from grok.ftests.utility.local import Cave, Fireplace, IFireplace
+  >>> from grok.ftests.utility.local import *
 
   >>> grok.grok('grok.ftests.utility.local')
 
@@ -13,12 +13,55 @@
 
   >>> from zope.app.component.hooks import getSite, setSite
   >>> setSite(cave)
+  
   >>> fireplace = component.getUtility(IFireplace)
   >>> IFireplace.providedBy(fireplace)
   True
   >>> isinstance(fireplace, Fireplace)
   True
+  
+  >>> club = component.getUtility(IClub)
+  >>> IClub.providedBy(club)
+  True
+  >>> isinstance(club, Club)
+  True
 
+  >>> spiky = component.getUtility(IClub, name='spiky')
+  >>> IClub.providedBy(spiky)
+  True
+  >>> isinstance(spiky, SpikyClub)
+  True
+
+  >>> sharp = component.getUtility(IClub, name='sharp')
+  >>> IClub.providedBy(sharp)
+  True
+  >>> isinstance(sharp, SharpClub)
+  True
+
+  >>> mammoth = component.getUtility(IMammoth)
+  >>> IMammoth.providedBy(mammoth)
+  True
+  >>> isinstance(mammoth, Mammoth)
+  True
+
+  >>> tiger = component.getUtility(IMammoth, name='tiger')
+  >>> IMammoth.providedBy(tiger)
+  True
+  >>> isinstance(tiger, SabretoothTiger)
+  True
+
+  >>> painting = component.getUtility(IPainting, name='blackandwhite')
+  >>> IPainting.providedBy(painting)
+  True
+  >>> isinstance(painting, CavePainting)
+  True
+
+  >>> colored = component.getUtility(IPainting, name='color')
+  >>> IPainting.providedBy(colored)
+  True
+  >>> isinstance(colored, ColoredCavePainting)
+  True
+
 Since it is a local utility, it is not available outside its site:
 
   >>> setSite(None)
@@ -26,15 +69,94 @@
   Traceback (most recent call last):
     ...
   ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IFireplace>, '')
+
+  >>> component.getUtility(IClub)
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IClub>, '')
+
+  >>> component.getUtility(IClub, name='spiky')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IClub>, 'spiky')
+
+  >>> component.getUtility(IClub, name='sharp')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IClub>, 'sharp')
+
+  >>> component.getUtility(IMammoth)
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IMammoth>, '')
+
+  >>> component.getUtility(IMammoth, name='tiger')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IMammoth>, 'tiger')
+
+  >>> component.getUtility(IPainting, name='blackandwhite')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IPainting>, 'blackandwhite')
+
+  >>> component.getUtility(IPainting, name='color')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IPainting>, 'color')
 """
 import grok
 from zope import interface
+import persistent
 
 class IFireplace(interface.Interface):
     pass
 
+class IClub(interface.Interface):
+    pass
+
+class ISpiky(interface.Interface):
+    pass
+
+class IMammoth(interface.Interface):
+    pass
+
 class Fireplace(grok.LocalUtility):
     grok.implements(IFireplace)
 
+class Club(object):
+    grok.implements(IClub)
+
+class SpikyClub(object):
+    grok.implements(IClub, ISpiky)
+
+class SharpClub(object):
+    grok.implements(IClub, ISpiky)
+    grok.provides(IClub)
+
+class Mammoth(grok.LocalUtility):
+    grok.implements(IMammoth, IClub)
+
+class SabretoothTiger(grok.LocalUtility):
+    grok.implements(IMammoth, IClub)
+    grok.provides(IMammoth)
+
+class IPainting(persistent.interfaces.IPersistent):
+    pass
+
+class CavePainting(grok.LocalUtility):
+    grok.implements(IPainting)
+
+class ColoredCavePainting(grok.LocalUtility):
+    grok.implements(IPainting)
+    grok.provides(IPainting)
+
 class Cave(grok.Model, grok.Site):
-    grok.local_utility(Fireplace, provides=IFireplace)
+    grok.local_utility(Fireplace)
+    grok.local_utility(Club)
+    grok.local_utility(SpikyClub, provides=IClub, name='spiky')
+    grok.local_utility(SharpClub, name='sharp')
+    grok.local_utility(Mammoth, provides=IMammoth)
+    grok.local_utility(SabretoothTiger, name='tiger')
+    grok.local_utility(CavePainting, name='blackandwhite', provides=IPainting)
+    grok.local_utility(ColoredCavePainting, name='color')

Modified: grok/trunk/src/grok/meta.py
===================================================================
--- grok/trunk/src/grok/meta.py	2007-01-07 10:59:36 UTC (rev 71754)
+++ grok/trunk/src/grok/meta.py	2007-01-07 11:13:59 UTC (rev 71755)
@@ -259,6 +259,30 @@
         infos = util.class_annotation(factory, 'grok.local_utility', None)
         if infos is None:
             return
+
+        for info in infos:
+            if info.provides is None:
+                provides = []
+                if util.check_subclass(info.factory, grok.LocalUtility):
+                    baseInterfaces = interface.implementedBy(grok.LocalUtility)
+                    utilityInterfaces = interface.implementedBy(info.factory)
+                    provides = list(utilityInterfaces - baseInterfaces)
+
+                    if len(provides) == 0 and len(list(utilityInterfaces)) > 0:
+                        raise GrokError(
+                            "Cannot determine which interface to use "
+                            "for utility registration of %r. "
+                            "It implements an interface that is a specialization "
+                            "of an interface implemented by grok.LocalUtility. "
+                            "Specify the interface by either using grok.provides "
+                            "on the utility or passing 'provides' to "
+                            "grok.local_utility." % info.factory, info.factory)
+                else:
+                    provides = list(interface.implementedBy(info.factory))
+
+                util.check_implements_one_from_list(provides, info.factory)
+                info.provides = provides[0]
+        
         subscriber = LocalUtilityRegistrationSubscriber(infos)
         component.provideHandler(subscriber,
                                  adapts=(factory, grok.IObjectAddedEvent))

Added: grok/trunk/src/grok/tests/utility/local_implementsmany.py
===================================================================
--- grok/trunk/src/grok/tests/utility/local_implementsmany.py	2007-01-07 10:59:36 UTC (rev 71754)
+++ grok/trunk/src/grok/tests/utility/local_implementsmany.py	2007-01-07 11:13:59 UTC (rev 71755)
@@ -0,0 +1,30 @@
+"""
+Anything can be registered as a local utility. If it implements a single
+interface, there is no need to specify which interface it provides.
+
+In this test, the utility implements more than one interface, so it cannot be
+registered as a local utility.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.utility.local_implementsmany.Fireplace'>
+  is implementing more than one interface (use grok.provides to specify
+  which one to use).
+
+"""
+
+import grok
+from zope import interface
+
+class IHome(interface.Interface):
+    pass
+
+class IFireplace(interface.Interface):
+    pass
+
+class Fireplace(object):
+    interface.implements(IHome, IFireplace)
+
+class Cave(grok.Model, grok.Site):
+    grok.local_utility(Fireplace)

Added: grok/trunk/src/grok/tests/utility/local_implementsnone.py
===================================================================
--- grok/trunk/src/grok/tests/utility/local_implementsnone.py	2007-01-07 10:59:36 UTC (rev 71754)
+++ grok/trunk/src/grok/tests/utility/local_implementsnone.py	2007-01-07 11:13:59 UTC (rev 71755)
@@ -0,0 +1,23 @@
+"""
+Anything can be registered as a local utility. If it implements a single
+interface, there is no need to specify which interface it provides.
+
+In this test, the utility does not implement any interface, so it cannot be
+registered as a local utility.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.utility.local_implementsnone.Fireplace'>
+  must implement at least one interface (use grok.implements to specify).
+
+"""
+
+import grok
+from zope import interface
+
+class Fireplace(object):
+    pass
+
+class Cave(grok.Model, grok.Site):
+    grok.local_utility(Fireplace)

Added: grok/trunk/src/grok/tests/utility/local_implementsnone2.py
===================================================================
--- grok/trunk/src/grok/tests/utility/local_implementsnone2.py	2007-01-07 10:59:36 UTC (rev 71754)
+++ grok/trunk/src/grok/tests/utility/local_implementsnone2.py	2007-01-07 11:13:59 UTC (rev 71755)
@@ -0,0 +1,24 @@
+"""
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: Cannot determine which interface to use for utility registration of
+  <class 'grok.tests.utility.local_implementsnone2.Fireplace'>. It implements
+  an interface that is a specialization of an interface implemented
+  by grok.LocalUtility. Specify the interface by either using grok.provides on
+  the utility or passing 'provides' to grok.local_utility.
+
+"""
+
+import grok
+from zope import interface
+import persistent
+
+class ISpecialPersistent(persistent.interfaces.IPersistent):
+    pass
+
+class Fireplace(grok.LocalUtility):
+    grok.implements(ISpecialPersistent)
+
+class Cave(grok.Model, grok.Site):
+    grok.local_utility(Fireplace)

Modified: grok/trunk/src/grok/util.py
===================================================================
--- grok/trunk/src/grok/util.py	2007-01-07 10:59:36 UTC (rev 71754)
+++ grok/trunk/src/grok/util.py	2007-01-07 11:13:59 UTC (rev 71755)
@@ -71,11 +71,14 @@
 
 
 def check_implements_one(class_):
-    if len(list(interface.implementedBy(class_))) < 1:
+    check_implements_one_from_list(list(interface.implementedBy(class_)), class_)
+
+def check_implements_one_from_list(list, class_):
+    if len(list) < 1:
         raise GrokError("%r must implement at least one interface "
                         "(use grok.implements to specify)."
                         % class_, class_)
-    elif len(list(interface.implementedBy(class_))) > 1:
+    elif len(list) > 1:
         raise GrokError("%r is implementing more than one interface "
                         "(use grok.provides to specify which one to use)."
                         % class_, class_)



More information about the Checkins mailing list