[Zope3-checkins] SVN: Zope3/trunk/src/zope/ Made the for_ attribute optional in the adapter directive if

Jim Fulton jim at zope.com
Thu Jan 27 19:10:01 EST 2005


Log message for revision 28967:
  Made the for_ attribute optional in the adapter directive if
  the factory declares what it adapts.  For classes, this declaration is
  made using the zope.component.adapts function.
  
  Made the provides attribute optional in the adapter directive if the
  registered factory implements exactly one interface.
  
  Made the provides attribute optional in the utility directive if the
  registered component provides exactly one interface.
  

Changed:
  U   Zope3/trunk/src/zope/app/component/metaconfigure.py
  U   Zope3/trunk/src/zope/app/component/metadirectives.py
  U   Zope3/trunk/src/zope/app/component/tests/adapter.py
  U   Zope3/trunk/src/zope/app/component/tests/test_directives.py
  U   Zope3/trunk/src/zope/component/tests/components.py

-=-
Modified: Zope3/trunk/src/zope/app/component/metaconfigure.py
===================================================================
--- Zope3/trunk/src/zope/app/component/metaconfigure.py	2005-01-27 18:48:53 UTC (rev 28966)
+++ Zope3/trunk/src/zope/app/component/metaconfigure.py	2005-01-28 00:10:00 UTC (rev 28967)
@@ -20,6 +20,7 @@
 from zope.component.interfaces import IDefaultViewName, IFactory
 from zope.component.service import UndefinedService
 from zope.configuration.exceptions import ConfigurationError
+import zope.interface
 from zope.interface import Interface
 from zope.interface.interfaces import IInterface
 
@@ -128,16 +129,37 @@
                 args = ('', iface)
                 )
 
-def adapter(_context, factory, provides, for_, permission=None, name='',
-            trusted=False):
+def adapter(_context, factory, provides=None, for_=None, permission=None,
+            name='', trusted=False):
+
     if permission is not None:
         if permission == PublicPermission:
             permission = CheckerPublic
         checker = InterfaceChecker(provides, permission)
         factory.append(lambda c: proxify(c, checker))
 
+    if for_ is None:
+        if len(factory) == 1:
+            try:
+                for_ = factory[0].__component_adapts__
+            except AttributeError:
+                pass
+
+        if for_ is None:
+            raise TypeError("No for attribute was provided and can't "
+                            "determine what the factory adapts.")
+
     for_ = tuple(for_)
 
+    if provides is None:
+        if len(factory) == 1:
+            p = list(zope.interface.implementedBy(factory[0]))
+            if len(p) == 1:
+                provides = p[0]
+
+        if provides is None:
+            raise TypeError("Missing 'provides' attribute")            
+
     # Generate a single factory from multiple factories:
     factories = factory
     if len(factories) == 1:
@@ -177,13 +199,20 @@
                     args = ('', iface)
                     )
 
-def utility(_context, provides, component=None, factory=None,
+def utility(_context, provides=None, component=None, factory=None,
             permission=None, name=''):
     if factory:
         if component:
             raise TypeError("Can't specify factory and component.")
         component = factory()
 
+    if provides is None:
+        provides = list(zope.interface.providedBy(component))
+        if len(provides) == 1:
+            provides = provides[0]
+        else:
+            raise TypeError("Missing 'provides' attribute")
+
     if permission is not None:
         if permission == PublicPermission:
             permission = CheckerPublic

Modified: Zope3/trunk/src/zope/app/component/metadirectives.py
===================================================================
--- Zope3/trunk/src/zope/app/component/metadirectives.py	2005-01-27 18:48:53 UTC (rev 28966)
+++ Zope3/trunk/src/zope/app/component/metadirectives.py	2005-01-28 00:10:00 UTC (rev 28967)
@@ -172,13 +172,13 @@
         title=_("Interface the component provides"),
         description=_("This attribute specifes the interface the adapter"
                       " instance must provide."),
-        required=True
+        required=False,
         )
 
     for_ = zope.configuration.fields.Tokens(
         title=_("Specifications to be adapted"),
         description=_("This should be a list of interfaces or classes"),
-        required=True,
+        required=False,
         value_type=zope.configuration.fields.GlobalObject(
           missing_value=object(),
           ),
@@ -267,7 +267,7 @@
     provides = zope.configuration.fields.GlobalInterface(
         title=_("Provided interface"),
         description=_("Interface provided by the utility."),
-        required=True
+        required=False,
         )
 
     name = zope.schema.TextLine(

Modified: Zope3/trunk/src/zope/app/component/tests/adapter.py
===================================================================
--- Zope3/trunk/src/zope/app/component/tests/adapter.py	2005-01-27 18:48:53 UTC (rev 28966)
+++ Zope3/trunk/src/zope/app/component/tests/adapter.py	2005-01-28 00:10:00 UTC (rev 28967)
@@ -17,6 +17,8 @@
 """
 
 import zope.interface
+import zope.component
+import zope.component.tests.components
 
 class I1(zope.interface.Interface):
     pass
@@ -42,9 +44,19 @@
     zope.interface.implements(I2)
 
 class A3(Adapter):
+    zope.component.adapts(zope.component.tests.components.IContent, I1, I2)
     zope.interface.implements(I3)
 
+class A4:
+    pass
 
+a4 = A4()
+
+class A5:
+    zope.interface.implements(I1, I2)
+
+a5 = A5()
+
 def Handler(content, *args):
     # uninteresting handler
     content.args = getattr(content, 'args', ()) + (args, )

Modified: Zope3/trunk/src/zope/app/component/tests/test_directives.py
===================================================================
--- Zope3/trunk/src/zope/app/component/tests/test_directives.py	2005-01-27 18:48:53 UTC (rev 28966)
+++ Zope3/trunk/src/zope/app/component/tests/test_directives.py	2005-01-28 00:10:00 UTC (rev 28967)
@@ -236,6 +236,48 @@
 
         self.assertEqual(IApp(Content()).__class__, Comp)
 
+    def testAdapter_wo_provides_or_for(self):
+        # Full import is critical!
+        from zope.component.tests.components import Content, IApp, Comp
+
+        self.assertEqual(IV(Content(), None), None)
+
+        xmlconfig(StringIO(template % (
+            """
+            <adapter
+              factory="zope.component.tests.components.Comp"
+              />
+            """
+            )))
+
+        self.assertEqual(IApp(Content()).__class__, Comp)        
+
+    def testAdapter_wo_provides_and_no_implented_fails(self):
+        try:
+            xmlconfig(StringIO(template % (
+                """
+                <adapter
+                  factory="zope.app.component.tests.adapter.A4"
+                  for="zope.component.tests.components.IContent"
+                  />
+                """
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
+
+    def testAdapter_wo_provides_and_too_many_implented_fails(self):
+        try:
+            xmlconfig(StringIO(template % (
+                """
+                <adapter
+                  factory="zope.app.component.tests.adapter.A4"
+                  for="zope.component.tests.components.IContent"
+                  />
+                """
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
+
     def testTrustedAdapter(self):
         # Full import is critical!
         from zope.component.tests.components import Content
@@ -341,6 +383,26 @@
         self.assertEqual(a3.__class__, A3)
         self.assertEqual(a3.context, (content, a1, a2))
 
+    def testMultiAdapter_wo_for_or_provides(self):
+        from zope.app.component.tests.adapter import A1, A2, A3, I3
+        from zope.component.tests.components import Content
+
+        xmlconfig(StringIO(template % (
+            """
+            <adapter
+              factory="zope.app.component.tests.adapter.A3
+                      "
+              />
+            """
+            )))
+
+        content = Content()
+        a1 = A1()
+        a2 = A2()
+        a3 = zapi.queryMultiAdapter((content, a1, a2), I3)
+        self.assertEqual(a3.__class__, A3)
+        self.assertEqual(a3.context, (content, a1, a2))
+
     def testNullAdapter(self):
         from zope.app.component.tests.adapter import A3, I3
 
@@ -472,6 +534,71 @@
 
         self.assertEqual(zapi.getUtility(IApp), comp)
 
+    def testUtility_wo_provides(self):
+
+        # Full import is critical!
+        from zope.component.tests.components import IApp, comp
+
+        self.assertEqual(zapi.queryUtility(IV), None)
+
+        xmlconfig(StringIO(template % (
+            """
+            <utility
+              component="zope.component.tests.components.comp"
+              />
+            """
+            )))
+
+        self.assertEqual(zapi.getUtility(IApp), comp)
+
+    def testUtility_wo_provides_fails_if_no_provides(self):
+        try:
+            xmlconfig(StringIO(template % (
+                """
+                <utility
+                  component="zope.app.component.tests.adapter.a4"
+                  />
+                """
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
+
+    def testUtility_wo_provides_fails_if_too_many_provided(self):
+        try:
+            xmlconfig(StringIO(template % (
+                """
+                <utility
+                  component="zope.app.component.tests.adapter.a5"
+                  />
+                """
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
+
+    def testUtility_wo_provides_fails_if_no_implemented(self):
+        try:
+            xmlconfig(StringIO(template % (
+                """
+                <utility
+                  factory="zope.app.component.tests.adapter.A4"
+                  />
+                """
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
+
+    def testUtility_wo_provides_fails_if_too_many_implemented(self):
+        try:
+            xmlconfig(StringIO(template % (
+                """
+                <utility
+                  factory="zope.app.component.tests.adapter.A5"
+                  />
+                """
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
+
     def testNamedUtility(self):
 
         # Full import is critical!

Modified: Zope3/trunk/src/zope/component/tests/components.py
===================================================================
--- Zope3/trunk/src/zope/component/tests/components.py	2005-01-27 18:48:53 UTC (rev 28966)
+++ Zope3/trunk/src/zope/component/tests/components.py	2005-01-28 00:10:00 UTC (rev 28967)
@@ -16,6 +16,7 @@
 $Id$
 """
 from zope.interface import Interface, Attribute, implements
+from zope.component import adapts
 
 class RecordingAdapter(object):
 
@@ -50,7 +51,7 @@
     implements(IContent)
 
 class Comp(object):
-    __used_for__ = IContent
+    adapts(IContent)
     implements(IApp)
 
     def __init__(self, *args):



More information about the Zope3-Checkins mailing list