[Checkins] SVN: zope.component/trunk/ Move over zope:view and zope:resource from zope.app.component into

Martijn Faassen faassen at startifact.com
Thu May 21 09:22:15 EDT 2009


Log message for revision 100192:
  Move over zope:view and zope:resource from zope.app.component into
  zope.component.
  

Changed:
  U   zope.component/trunk/CHANGES.txt
  U   zope.component/trunk/src/zope/component/meta.zcml
  A   zope.component/trunk/src/zope/component/testfiles/views.py
  U   zope.component/trunk/src/zope/component/tests.py
  U   zope.component/trunk/src/zope/component/zcml.py

-=-
Modified: zope.component/trunk/CHANGES.txt
===================================================================
--- zope.component/trunk/CHANGES.txt	2009-05-21 13:20:47 UTC (rev 100191)
+++ zope.component/trunk/CHANGES.txt	2009-05-21 13:22:14 UTC (rev 100192)
@@ -6,6 +6,9 @@
 
 - The HookableTests were not run by the testrunner.
 
+- Add in zope:view and zope:resource implementations into
+  zope.component.zcml (dependency loaded with zope.component [zcml]).
+ 
 3.6.0 (2009-03-12)
 ==================
 

Modified: zope.component/trunk/src/zope/component/meta.zcml
===================================================================
--- zope.component/trunk/src/zope/component/meta.zcml	2009-05-21 13:20:47 UTC (rev 100191)
+++ zope.component/trunk/src/zope/component/meta.zcml	2009-05-21 13:22:14 UTC (rev 100192)
@@ -28,6 +28,18 @@
         handler="zope.component.zcml.utility"
         />
 
+    <meta:directive
+        name="view"
+        schema="zope.component.zcml.IViewDirective"
+        handler="zope.component.zcml.view"
+        />
+
+    <meta:directive
+        name="resource"
+        schema="zope.component.zcml.IResourceDirective"
+        handler="zope.component.zcml.resource"
+        />
+
   </meta:directives>
 
 </configure>

Copied: zope.component/trunk/src/zope/component/testfiles/views.py (from rev 100129, zope.app.component/trunk/src/zope/app/component/tests/views.py)
===================================================================
--- zope.component/trunk/src/zope/component/testfiles/views.py	                        (rev 0)
+++ zope.component/trunk/src/zope/component/testfiles/views.py	2009-05-21 13:22:14 UTC (rev 100192)
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Views test.
+
+$Id$
+"""
+from zope.interface import Interface, implements, directlyProvides
+
+class Request(object):
+
+    def __init__(self, type):
+        directlyProvides(self, type)
+
+class IR(Interface):
+    pass
+
+class IV(Interface):
+    def index():
+        pass
+
+class IC(Interface): pass
+
+class V1(object):
+    implements(IV)
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    def index(self):
+        return 'V1 here'
+
+    def action(self):
+        return 'done'
+
+class VZMI(V1):
+    def index(self):
+        return 'ZMI here'
+
+class R1(object):
+
+    def index(self):
+        return 'R1 here'
+
+    def action(self):
+        return 'R done'
+
+    def __init__(self, request):
+        pass
+
+    implements(IV)
+
+class RZMI(R1):
+    pass

Modified: zope.component/trunk/src/zope/component/tests.py
===================================================================
--- zope.component/trunk/src/zope/component/tests.py	2009-05-21 13:20:47 UTC (rev 100191)
+++ zope.component/trunk/src/zope/component/tests.py	2009-05-21 13:22:14 UTC (rev 100192)
@@ -19,6 +19,7 @@
 import unittest
 import transaction
 import persistent
+from cStringIO import StringIO
 
 from zope import interface, component
 from zope.interface.verify import verifyObject
@@ -28,10 +29,19 @@
 from zope.component.interfaces import ComponentLookupError
 from zope.component.interfaces import IComponentArchitecture
 from zope.component.interfaces import IComponentLookup
-from zope.component.testing import setUp, tearDown
+from zope.component.testing import setUp, tearDown, PlacelessSetup
 import zope.component.persistentregistry
 import zope.component.globalregistry
 
+from zope.configuration.xmlconfig import XMLConfig, xmlconfig
+from zope.configuration.exceptions import ConfigurationError
+from zope.security.checker import ProxyFactory
+
+from zope.component.testfiles.adapter import A1, A2, A3
+from zope.component.testfiles.components import IContent, Content
+from zope.component.testfiles.components import IApp
+from zope.component.testfiles.views import Request, IC, IV, V1, R1, IR
+
 # side effect gets component-based event dispatcher installed.
 # we should obviously make this more explicit
 import zope.component.event
@@ -1042,7 +1052,6 @@
         import subprocess
         import sys
         import os
-        import StringIO
         import tempfile
         import pickle
 
@@ -1188,7 +1197,403 @@
         else:
             self.fail('Deleted implementation')
 
+class Ob3(object):
+    interface.implements(IC)
 
+template = """<configure
+   xmlns='http://namespaces.zope.org/zope'
+   i18n_domain='zope'>
+   %s
+   </configure>"""
+
+
+class ResourceViewTests(PlacelessSetup, unittest.TestCase):
+
+    def setUp(self):
+        super(ResourceViewTests, self).setUp()
+        XMLConfig('meta.zcml', zope.component)()
+        XMLConfig('meta.zcml', zope.security)()
+
+    def testView(self):
+        ob = Ob3()
+        request = Request(IV)
+        self.assertEqual(
+            zope.component.queryMultiAdapter((ob, request), name=u'test'), None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <view name="test"
+                  factory="zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IV"/>
+            '''
+            ))
+
+        self.assertEqual(
+            zope.component.queryMultiAdapter((ob, request),
+                                             name=u'test').__class__,
+            V1)
+
+
+    def testMultiView(self):
+        xmlconfig(StringIO(template %
+            '''
+            <view name="test"
+                  factory="zope.component.testfiles.adapter.A3"
+                  for="zope.component.testfiles.views.IC
+                       zope.component.testfiles.adapter.I1
+                       zope.component.testfiles.adapter.I2"
+                  type="zope.component.testfiles.views.IV"/>
+            '''
+            ))
+
+
+        ob = Ob3()
+        a1 = A1()
+        a2 = A2()
+        request = Request(IV)
+        view = zope.component.queryMultiAdapter((ob, a1, a2, request),
+                                                name=u'test')
+        self.assertEqual(view.__class__, A3)
+        self.assertEqual(view.context, (ob, a1, a2, request))
+
+
+    def testMultiView_fails_w_multiple_factories(self):
+        self.assertRaises(
+            ConfigurationError,
+            xmlconfig,
+            StringIO(template %
+              '''
+              <view name="test"
+                    factory="zope.component.testfiles.adapter.A3
+                             zope.component.testfiles.adapter.A2"
+                    for="zope.component.testfiles.views.IC
+                         zope.component.testfiles.adapter.I1
+                         zope.component.testfiles.adapter.I2"
+                    type="zope.component.testfiles.views.IV"/>
+              '''
+              )
+            )
+
+    def testView_w_multiple_factories(self):
+        xmlconfig(StringIO(template %
+            '''
+            <view name="test"
+                  factory="zope.component.testfiles.adapter.A1
+                           zope.component.testfiles.adapter.A2
+                           zope.component.testfiles.adapter.A3
+                           zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IV"/>
+            '''
+            ))
+
+        ob = Ob3()
+
+        # The view should be a V1 around an A3, around an A2, around
+        # an A1, anround ob:
+        view = zope.component.queryMultiAdapter((ob, Request(IV)), name=u'test')
+        self.assertEqual(view.__class__, V1)
+        a3 = view.context
+        self.assertEqual(a3.__class__, A3)
+        a2 = a3.context[0]
+        self.assertEqual(a2.__class__, A2)
+        a1 = a2.context[0]
+        self.assertEqual(a1.__class__, A1)
+        self.assertEqual(a1.context[0], ob)
+
+    def testView_fails_w_no_factories(self):
+        self.assertRaises(ConfigurationError,
+                          xmlconfig,
+                          StringIO(template %
+                                   '''
+                                   <view name="test"
+                                   factory=""
+                                   for="zope.component.testfiles.views.IC"
+                                   type="zope.component.testfiles.views.IV"/>
+                                   '''
+                                   ),
+                          )
+
+
+    def testViewThatProvidesAnInterface(self):
+        ob = Ob3()
+        self.assertEqual(
+            zope.component.queryMultiAdapter((ob, Request(IR)), IV, u'test'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <view name="test"
+                  factory="zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IR"
+                  />
+            '''
+            ))
+
+        self.assertEqual(
+            zope.component.queryMultiAdapter((ob, Request(IR)), IV, u'test'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <view name="test"
+                  factory="zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IR"
+                  provides="zope.component.testfiles.views.IV"
+                  />
+            '''
+            ))
+
+        v = zope.component.queryMultiAdapter((ob, Request(IR)), IV, u'test')
+        self.assertEqual(v.__class__, V1)
+
+
+    def testUnnamedViewThatProvidesAnInterface(self):
+        ob = Ob3()
+        self.assertEqual(
+            zope.component.queryMultiAdapter((ob, Request(IR)), IV), None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <view factory="zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IR"
+                  />
+            '''
+            ))
+
+        v = zope.component.queryMultiAdapter((ob, Request(IR)), IV)
+        self.assertEqual(v, None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <view factory="zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IR"
+                  provides="zope.component.testfiles.views.IV"
+                  />
+            '''
+            ))
+
+        v = zope.component.queryMultiAdapter((ob, Request(IR)), IV)
+        self.assertEqual(v.__class__, V1)
+
+    def testViewHavingARequiredClass(self):
+        xmlconfig(StringIO(template % (
+            '''
+            <view
+              for="zope.component.testfiles.components.Content"
+              type="zope.component.testfiles.views.IR"
+              factory="zope.component.testfiles.adapter.A1"
+              />
+            '''
+            )))
+
+        content = Content()
+        a1 = zope.component.getMultiAdapter((content, Request(IR)))
+        self.assert_(isinstance(a1, A1))
+
+        class MyContent:
+            interface.implements(IContent)
+
+        self.assertRaises(ComponentLookupError, zope.component.getMultiAdapter,
+                          (MyContent(), Request(IR)))
+
+    def testInterfaceProtectedView(self):
+        xmlconfig(StringIO(template %
+            '''
+            <view name="test"
+                  factory="zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IV"
+                  permission="zope.Public"
+              allowed_interface="zope.component.testfiles.views.IV"
+                  />
+            '''
+            ))
+
+        v = ProxyFactory(zope.component.getMultiAdapter((Ob3(), Request(IV)),
+                                                        name='test'))
+        self.assertEqual(v.index(), 'V1 here')
+        self.assertRaises(Exception, getattr, v, 'action')
+
+    def testAttributeProtectedView(self):
+        xmlconfig(StringIO(template %
+            '''
+            <view name="test"
+                  factory="zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IV"
+                  permission="zope.Public"
+                  allowed_attributes="action"
+                  />
+            '''
+            ))
+
+        v = ProxyFactory(zope.component.getMultiAdapter((Ob3(), Request(IV)),
+                                                        name='test'))
+        self.assertEqual(v.action(), 'done')
+        self.assertRaises(Exception, getattr, v, 'index')
+
+    def testInterfaceAndAttributeProtectedView(self):
+        xmlconfig(StringIO(template %
+            '''
+            <view name="test"
+                  factory="zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IV"
+                  permission="zope.Public"
+                  allowed_attributes="action"
+              allowed_interface="zope.component.testfiles.views.IV"
+                  />
+            '''
+            ))
+
+        v = zope.component.getMultiAdapter((Ob3(), Request(IV)), name='test')
+        self.assertEqual(v.index(), 'V1 here')
+        self.assertEqual(v.action(), 'done')
+
+    def testDuplicatedInterfaceAndAttributeProtectedView(self):
+        xmlconfig(StringIO(template %
+            '''
+            <view name="test"
+                  factory="zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IV"
+                  permission="zope.Public"
+                  allowed_attributes="action index"
+              allowed_interface="zope.component.testfiles.views.IV"
+                  />
+            '''
+            ))
+
+        v = zope.component.getMultiAdapter((Ob3(), Request(IV)), name='test')
+        self.assertEqual(v.index(), 'V1 here')
+        self.assertEqual(v.action(), 'done')
+
+    def testIncompleteProtectedViewNoPermission(self):
+        self.assertRaises(
+            ConfigurationError,
+            xmlconfig,
+            StringIO(template %
+            '''
+            <view name="test"
+                  factory="zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IV"
+                  allowed_attributes="action index"
+                  />
+            '''
+            ))
+
+    def testViewUndefinedPermission(self):
+        config = StringIO(template % (
+            '''
+            <view name="test"
+                  factory="zope.component.testfiles.views.V1"
+                  for="zope.component.testfiles.views.IC"
+                  type="zope.component.testfiles.views.IV"
+                  permission="zope.UndefinedPermission"
+                  allowed_attributes="action index"
+              allowed_interface="zope.component.testfiles.views.IV"
+                  />
+            '''
+            ))
+        self.assertRaises(ValueError, xmlconfig, config, testing=1)
+
+    def testResource(self):
+        ob = Ob3()
+        self.assertEqual(
+            zope.component.queryAdapter(Request(IV), name=u'test'), None)
+        xmlconfig(StringIO(template % (
+            '''
+            <resource name="test"
+                  factory="zope.component.testfiles.views.R1"
+                  type="zope.component.testfiles.views.IV"/>
+            '''
+            )))
+
+        self.assertEqual(
+            zope.component.queryAdapter(Request(IV), name=u'test').__class__,
+            R1)
+
+    def testResourceThatProvidesAnInterface(self):
+        ob = Ob3()
+        self.assertEqual(zope.component.queryAdapter(Request(IR), IV, u'test'),
+                         None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <resource
+                name="test"
+                factory="zope.component.testfiles.views.R1"
+                type="zope.component.testfiles.views.IR"
+                />
+            '''
+            ))
+
+        v = zope.component.queryAdapter(Request(IR), IV, name=u'test')
+        self.assertEqual(v, None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <resource
+                name="test"
+                factory="zope.component.testfiles.views.R1"
+                type="zope.component.testfiles.views.IR"
+                provides="zope.component.testfiles.views.IV"
+                />
+            '''
+            ))
+
+        v = zope.component.queryAdapter(Request(IR), IV, name=u'test')
+        self.assertEqual(v.__class__, R1)
+
+    def testUnnamedResourceThatProvidesAnInterface(self):
+        ob = Ob3()
+        self.assertEqual(zope.component.queryAdapter(Request(IR), IV), None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <resource
+                factory="zope.component.testfiles.views.R1"
+                type="zope.component.testfiles.views.IR"
+                />
+            '''
+            ))
+
+        v = zope.component.queryAdapter(Request(IR), IV)
+        self.assertEqual(v, None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <resource
+                factory="zope.component.testfiles.views.R1"
+                type="zope.component.testfiles.views.IR"
+                provides="zope.component.testfiles.views.IV"
+                />
+            '''
+            ))
+
+        v = zope.component.queryAdapter(Request(IR), IV)
+        self.assertEqual(v.__class__, R1)
+
+    def testResourceUndefinedPermission(self):
+
+        config = StringIO(template % (
+            '''
+            <resource name="test"
+                  factory="zope.component.testfiles.views.R1"
+                  type="zope.component.testfiles.views.IV"
+                  permission="zope.UndefinedPermission"/>
+            '''
+            ))
+        self.assertRaises(ValueError, xmlconfig, config, testing=1)
+
+
 def setUpRegistryTests(tests):
     setUp()
 
@@ -1200,8 +1605,6 @@
 def clearZCML(test=None):
     tearDown()
     setUp()
-
-    from zope.configuration.xmlconfig import XMLConfig
     XMLConfig('meta.zcml', component)()
 
 def test_suite():
@@ -1212,8 +1615,8 @@
         ])
 
     return unittest.TestSuite((
+        doctest.DocTestSuite(setUp=setUp, tearDown=tearDown),
         unittest.makeSuite(HookableTests),
-        doctest.DocTestSuite(setUp=setUp, tearDown=tearDown),
         doctest.DocTestSuite('zope.component.interface',
                              setUp=setUp, tearDown=tearDown),
         doctest.DocTestSuite('zope.component.nexttesting'),
@@ -1231,6 +1634,7 @@
         doctest.DocFileSuite('zcml.txt',checker=checker,
                              setUp=setUp, tearDown=tearDown),
         unittest.makeSuite(StandaloneTests),
+        unittest.makeSuite(ResourceViewTests),
         ))
 
 if __name__ == "__main__":

Modified: zope.component/trunk/src/zope/component/zcml.py
===================================================================
--- zope.component/trunk/src/zope/component/zcml.py	2009-05-21 13:20:47 UTC (rev 100191)
+++ zope.component/trunk/src/zope/component/zcml.py	2009-05-21 13:22:14 UTC (rev 100192)
@@ -17,14 +17,17 @@
 """
 __docformat__ = "reStructuredText"
 
+import warnings
 import zope.component
 import zope.interface
+import zope.schema
 import zope.configuration.fields
+from zope.configuration.exceptions import ConfigurationError
 import zope.security.zcml
 from zope.component.interface import provideInterface
 from zope.proxy import ProxyBase, getProxiedObject
 from zope.security.proxy import Proxy
-from zope.security.checker import InterfaceChecker, CheckerPublic
+from zope.security.checker import InterfaceChecker, CheckerPublic, Checker
 from zope.security.adapter import LocatingTrustedAdapterFactory
 from zope.security.adapter import LocatingUntrustedAdapterFactory
 from zope.security.adapter import TrustedAdapterFactory
@@ -458,3 +461,277 @@
         callable = provideInterface,
         args = (name, interface, type)
         )
+
+class IBasicViewInformation(zope.interface.Interface):
+    """This is the basic information for all views."""
+
+    for_ = zope.configuration.fields.Tokens(
+        title=_("Specifications of the objects to be viewed"),
+        description=_("""This should be a list of interfaces or classes
+        """),
+        required=True,
+        value_type=zope.configuration.fields.GlobalObject(
+          missing_value=object(),
+          ),
+        )
+
+    permission = zope.security.zcml.Permission(
+        title=_("Permission"),
+        description=_("The permission needed to use the view."),
+        required=False,
+        )
+
+    class_ = zope.configuration.fields.GlobalObject(
+        title=_("Class"),
+        description=_("A class that provides attributes used by the view."),
+        required=False,
+        )
+
+    layer = zope.configuration.fields.GlobalInterface(
+        title=_("The layer the view is in."),
+        description=_("""
+        A skin is composed of layers. It is common to put skin
+        specific views in a layer named after the skin. If the 'layer'
+        attribute is not supplied, it defaults to 'default'."""),
+        required=False,
+        )
+
+    allowed_interface = zope.configuration.fields.Tokens(
+        title=_("Interface that is also allowed if user has permission."),
+        description=_("""
+        By default, 'permission' only applies to viewing the view and
+        any possible sub views. By specifying this attribute, you can
+        make the permission also apply to everything described in the
+        supplied interface.
+
+        Multiple interfaces can be provided, separated by
+        whitespace."""),
+        required=False,
+        value_type=zope.configuration.fields.GlobalInterface(),
+        )
+
+    allowed_attributes = zope.configuration.fields.Tokens(
+        title=_("View attributes that are also allowed if the user"
+                " has permission."),
+        description=_("""
+        By default, 'permission' only applies to viewing the view and
+        any possible sub views. By specifying 'allowed_attributes',
+        you can make the permission also apply to the extra attributes
+        on the view object."""),
+        required=False,
+        value_type=zope.configuration.fields.PythonIdentifier(),
+        )
+
+class IBasicResourceInformation(zope.interface.Interface):
+    """
+    Basic information for resources
+    """
+
+    name = zope.schema.TextLine(
+        title=_("The name of the resource."),
+        description=_("The name shows up in URLs/paths. For example 'foo'."),
+        required=True,
+        default=u'',
+        )
+
+    provides = zope.configuration.fields.GlobalInterface(
+        title=_("The interface this component provides."),
+        description=_("""
+        A view can provide an interface.  This would be used for
+        views that support other views."""),
+        required=False,
+        default=zope.interface.Interface,
+        )
+
+    type = zope.configuration.fields.GlobalInterface(
+        title=_("Request type"),
+        required=True
+        )
+
+
+class IViewDirective(IBasicViewInformation, IBasicResourceInformation):
+    """Register a view for a component"""
+
+    factory = zope.configuration.fields.Tokens(
+        title=_("Factory"),
+        required=False,
+        value_type=zope.configuration.fields.GlobalObject(),
+        )
+
+def view(_context, factory, type, name, for_, layer=None,
+         permission=None, allowed_interface=None, allowed_attributes=None,
+         provides=zope.interface.Interface):
+
+    if ((allowed_attributes or allowed_interface)
+        and (not permission)):
+        raise ConfigurationError(
+            "Must use name attribute with allowed_interface or "
+            "allowed_attributes"
+            )
+
+    if not factory:
+        raise ConfigurationError("No view factory specified.")
+
+    if permission:
+
+        checker = _checker(_context, permission,
+                           allowed_interface, allowed_attributes)
+
+        class ProxyView(object):
+            """Class to create simple proxy views."""
+
+            def __init__(self, factory, checker):
+                self.factory = factory
+                self.checker = checker
+
+            def __call__(self, *objects):
+                return proxify(self.factory(*objects), self.checker)
+
+        factory[-1] = ProxyView(factory[-1], checker)
+
+
+    if not for_:
+        raise ValueError("No for interfaces specified");
+    for_ = tuple(for_)
+
+    # Generate a single factory from multiple factories:
+    factories = factory
+    if len(factories) == 1:
+        factory = factories[0]
+    elif len(factories) < 1:
+        raise ValueError("No factory specified")
+    elif len(factories) > 1 and len(for_) > 1:
+        raise ValueError("Can't use multiple factories and multiple for")
+    else:
+        def factory(ob, request):
+            for f in factories[:-1]:
+                ob = f(ob)
+            return factories[-1](ob, request)
+
+    # BBB 2006/02/18, to be removed after 12 months
+    if layer is not None:
+        for_ = for_ + (layer,)
+        warnings.warn_explicit(
+            "The 'layer' argument of the 'view' directive has been "
+            "deprecated.  Use the 'type' argument instead. If you have "
+            "an existing 'type' argument IBrowserRequest, replace it with the "
+            "'layer' argument (the layer subclasses IBrowserRequest). "
+            "which subclasses BrowserRequest.",
+            DeprecationWarning, _context.info.file, _context.info.line)
+    else:
+        for_ = for_ + (type,)
+
+    _context.action(
+        discriminator = ('view', for_, name, provides),
+        callable = handler,
+        args = ('registerAdapter',
+                factory, for_, provides, name, _context.info),
+        )
+    if type is not None:
+        _context.action(
+            discriminator = None,
+            callable = provideInterface,
+            args = ('', type)
+            )
+
+    _context.action(
+        discriminator = None,
+        callable = provideInterface,
+        args = ('', provides)
+        )
+
+    if for_ is not None:
+        for iface in for_:
+            if iface is not None:
+                _context.action(
+                    discriminator = None,
+                    callable = provideInterface,
+                    args = ('', iface)
+                    )
+
+    
+class IResourceDirective(IBasicComponentInformation,
+                         IBasicResourceInformation):
+    """Register a resource"""
+
+    layer = zope.configuration.fields.GlobalInterface(
+        title=_("The layer the resource is in."),
+        required=False,
+        )
+
+    allowed_interface = zope.configuration.fields.Tokens(
+        title=_("Interface that is also allowed if user has permission."),
+        required=False,
+        value_type=zope.configuration.fields.GlobalInterface(),
+        )
+
+    allowed_attributes = zope.configuration.fields.Tokens(
+        title=_("View attributes that are also allowed if user"
+                " has permission."),
+        required=False,
+        value_type=zope.configuration.fields.PythonIdentifier(),
+        )
+
+def resource(_context, factory, type, name, layer=None,
+             permission=None,
+             allowed_interface=None, allowed_attributes=None,
+             provides=zope.interface.Interface):
+
+    if ((allowed_attributes or allowed_interface)
+        and (not permission)):
+        raise ConfigurationError(
+            "Must use name attribute with allowed_interface or "
+            "allowed_attributes"
+            )
+
+    if permission:
+        checker = _checker(_context, permission,
+                           allowed_interface, allowed_attributes)
+
+        def proxyResource(request, factory=factory, checker=checker):
+            return proxify(factory(request), checker)
+
+        factory = proxyResource
+
+    if layer is not None:
+        warnings.warn_explicit(
+            "The 'layer' argument of the 'resource' directive has been "
+            "deprecated.  Use the 'type' argument instead.",
+            DeprecationWarning, _context.info.file, _context.info.line)
+        type = layer
+
+    _context.action(
+        discriminator = ('resource', name, type, provides),
+        callable = handler,
+        args = ('registerAdapter',
+                factory, (type,), provides, name, _context.info),
+        )
+    _context.action(
+        discriminator = None,
+        callable = provideInterface,
+        args = (type.__module__ + '.' + type.__name__, type)
+               )
+    _context.action(
+        discriminator = None,
+        callable = provideInterface,
+        args = (provides.__module__ + '.' + provides.__name__, type)
+               )
+
+def _checker(_context, permission, allowed_interface, allowed_attributes):
+    if (not allowed_attributes) and (not allowed_interface):
+        allowed_attributes = ["__call__"]
+
+    if permission == PublicPermission:
+        permission = CheckerPublic
+
+    require={}
+    if allowed_attributes:
+        for name in allowed_attributes:
+            require[name] = permission
+    if allowed_interface:
+        for i in allowed_interface:
+            for name in i.names(all=True):
+                require[name] = permission
+
+    checker = Checker(require)
+    return checker



More information about the Checkins mailing list