[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