[z3-checkins] r5175 - in z3/Five/trunk: . demo/FiveViewsDemo directives handlers security tests

dreamcatcher at codespeak.net dreamcatcher at codespeak.net
Sun Jun 20 05:28:09 MEST 2004


Author: dreamcatcher
Date: Sun Jun 20 05:28:07 2004
New Revision: 5175

Added:
   z3/Five/trunk/directives/
   z3/Five/trunk/directives/__init__.py   (contents, props changed)
   z3/Five/trunk/directives/content.py   (contents, props changed)
   z3/Five/trunk/handlers/
   z3/Five/trunk/handlers/__init__.py   (contents, props changed)
   z3/Five/trunk/handlers/content.py   (contents, props changed)
   z3/Five/trunk/permissions.zcml
   z3/Five/trunk/security/
   z3/Five/trunk/security/__init__.py   (contents, props changed)
   z3/Five/trunk/security/fields.py   (contents, props changed)
   z3/Five/trunk/security/interfaces.py   (contents, props changed)
   z3/Five/trunk/security/permission.py   (contents, props changed)
   z3/Five/trunk/tests/__init__.py   (contents, props changed)
   z3/Five/trunk/tests/test_security.py   (contents, props changed)
Modified:
   z3/Five/trunk/demo/FiveViewsDemo/browser.py
   z3/Five/trunk/demo/FiveViewsDemo/configure.zcml
   z3/Five/trunk/demo/FiveViewsDemo/interfaces.py
   z3/Five/trunk/five.zcml
   z3/Five/trunk/fivedirectives.py
   z3/Five/trunk/meta.zcml
   z3/Five/trunk/metaconfigure.py
   z3/Five/trunk/metadirectives.py
   z3/Five/trunk/tests/test_five.py
Log:
Implementation of z3-like zcml 'content' directive for z2 security. Pending tests.

Modified: z3/Five/trunk/demo/FiveViewsDemo/browser.py
==============================================================================
--- z3/Five/trunk/demo/FiveViewsDemo/browser.py	(original)
+++ z3/Five/trunk/demo/FiveViewsDemo/browser.py	Sun Jun 20 05:28:07 2004
@@ -1,31 +1,20 @@
-from AccessControl import ClassSecurityInfo
-from Globals import InitializeClass
 from Products.Five.api import BrowserView
 
 class SimpleContentView(BrowserView):
     """More docstring. Please Zope"""
-    security = ClassSecurityInfo()
 
-    security.declareProtected('View Management Screens', 'eagle')
     def eagle(self):
         """Docstring"""
         return "The eagle has landed"
-    
-InitializeClass(SimpleContentView)
 
 class SimpleFolderView(BrowserView):
-    security = ClassSecurityInfo()
 
-    security.declarePublic('eagle')
     def eagle(self):
         """Test
         """
         return "The eagle has landed: %s" % self.context.objectIds()
 
-    security.declareProtected('View management screens', 'mydefault')
     def mydefault(self):
         """Test
         """
         return "This is default view for %s" % self.context.absolute_url()
-    
-InitializeClass(SimpleFolderView)

Modified: z3/Five/trunk/demo/FiveViewsDemo/configure.zcml
==============================================================================
--- z3/Five/trunk/demo/FiveViewsDemo/configure.zcml	(original)
+++ z3/Five/trunk/demo/FiveViewsDemo/configure.zcml	Sun Jun 20 05:28:07 2004
@@ -1,7 +1,7 @@
 <configure xmlns="http://namespaces.zope.org/zope"
            xmlns:five="http://namespaces.zope.org/five">
 
-  <five:page 
+  <five:page
     for=".interfaces.ISimpleContent"
     class=".browser.SimpleContentView"
     attribute="eagle"
@@ -14,7 +14,7 @@
     />
 
   <five:viewable
-    class="OFS.Folder.Folder" 
+    class="OFS.Folder.Folder"
     />
 
   <five:page
@@ -23,5 +23,27 @@
     attribute="eagle"
     name="eagle.txt"
     />
-  
+
+  <five:content class=".browser.SimpleContentView">
+
+    <five:require attributes="eagle"
+	     permission="zope.ViewManagementScreens"
+	     />
+
+  </five:content>
+
+  <five:content class=".browser.SimpleFolderView">
+
+    <implements interface=".interfaces.ISimpleFolderView"
+		/>
+
+    <require interface=".interfaces.IWriteSimpleFolderView"
+	     permission="zope.ViewManagementScreens"
+	     />
+
+    <allow interface=".interfaces.IReadSimpleFolderView"
+	   />
+
+  </five:content>
+
 </configure>

Modified: z3/Five/trunk/demo/FiveViewsDemo/interfaces.py
==============================================================================
--- z3/Five/trunk/demo/FiveViewsDemo/interfaces.py	(original)
+++ z3/Five/trunk/demo/FiveViewsDemo/interfaces.py	Sun Jun 20 05:28:07 2004
@@ -7,3 +7,17 @@
 
 class IFolder(Interface):
     pass
+
+
+class IReadSimpleFolderView(Interface):
+
+    def eagle():
+        """Just a sample method"""
+
+class IWriteSimpleFolderView(Interface):
+
+    def mydefault():
+        """Just a sample method"""
+
+class ISimpleFolderView(IReadSimpleFolderView, IWriteSimpleFolderView):
+    """Interface for SimpleFolderView"""

Added: z3/Five/trunk/directives/__init__.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/directives/__init__.py	Sun Jun 20 05:28:07 2004
@@ -0,0 +1 @@
+# import this

Added: z3/Five/trunk/directives/content.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/directives/content.py	Sun Jun 20 05:28:07 2004
@@ -0,0 +1,94 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+$Id: metadirectives.py 25177 2004-06-02 13:17:31Z jim $
+"""
+from zope.interface import Interface
+from zope.configuration.fields import GlobalObject, Tokens, \
+     PythonIdentifier, MessageID
+from zope.schema import TextLine, Id
+
+from Products.Five.security.fields import Permission
+
+class IContentDirective(Interface):
+    """
+    Make statements about a content class
+    """
+
+    class_ = GlobalObject(
+        title=u"Class",
+        required=True
+        )
+
+class IImplementsSubdirective(Interface):
+    """
+    Declare that the class given by the content directive's class
+    attribute implements a given interface
+    """
+
+    interface = Tokens(
+        title=u"One or more interfaces",
+        required=True,
+        value_type=GlobalObject()
+        )
+
+class IRequireSubdirective(Interface):
+    """
+    Indicate that the a specified list of names or the names in a
+    given Interface require a given permission for access.
+    """
+
+    permission = Permission(
+        title=u"Permission",
+        description=u"""
+        Specifies the permission by id that will be required to
+        access or mutate the attributes and methods specified.""",
+        required=False
+        )
+
+    attributes = Tokens(
+        title=u"Attributes and methods",
+        description=u"""
+        This is a list of attributes and methods that can be accessed.""",
+        required=False,
+        value_type=PythonIdentifier()
+        )
+
+    interface = Tokens(
+        title=u"Interfaces",
+        description=u"""
+        The listed interfaces' methods and attributes can be accessed.""",
+        required=False,
+        value_type=GlobalObject()
+        )
+
+class IAllowSubdirective(Interface):
+    """
+    Declare a part of the class to be publicly viewable (that is,
+    requires the zope.Public permission). Only one of the following
+    two attributes may be used.
+    """
+
+    attributes = Tokens(
+        title=u"Attributes",
+        required=False,
+        value_type=PythonIdentifier()
+        )
+
+    interface = Tokens(
+        title=u"Interface",
+        required=False,
+        value_type=GlobalObject()
+        )
+

Modified: z3/Five/trunk/five.zcml
==============================================================================
--- z3/Five/trunk/five.zcml	(original)
+++ z3/Five/trunk/five.zcml	Sun Jun 20 05:28:07 2004
@@ -1,12 +1,13 @@
 <configure xmlns="http://namespaces.zope.org/zope"
            xmlns:five="http://namespaces.zope.org/five">
-  
+
   <include file="meta.zcml" />
   <include file="services.zcml" />
+  <include file="permissions.zcml" />
 
   <!-- do 'traditional' traversing for ZPT by default -->
 
-  <adapter 
+  <adapter
       for="*"
       factory="zope.app.traversing.adapters.DefaultTraversable"
       provides="zope.app.traversing.interfaces.ITraversable" />

Modified: z3/Five/trunk/fivedirectives.py
==============================================================================
--- z3/Five/trunk/fivedirectives.py	(original)
+++ z3/Five/trunk/fivedirectives.py	Sun Jun 20 05:28:07 2004
@@ -7,7 +7,7 @@
     """
     This is the basic information for all views.
     """
-    
+
     for_ = Tokens(
         title=u"Specifications of the objects to be viewed",
         description=u"""This should be a list of interfaces or classes
@@ -119,7 +119,7 @@
         title=u"Class",
         required=True
         )
-    
+
 class ILayerDirective(Interface):
     """
     Register a layer

Added: z3/Five/trunk/handlers/__init__.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/handlers/__init__.py	Sun Jun 20 05:28:07 2004
@@ -0,0 +1 @@
+# import this

Added: z3/Five/trunk/handlers/content.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/handlers/content.py	Sun Jun 20 05:28:07 2004
@@ -0,0 +1,129 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" Register class directive.
+
+$Id: contentdirective.py 25177 2004-06-02 13:17:31Z jim $
+"""
+from types import ModuleType
+from zope.interface import classImplements
+from zope.configuration.exceptions import ConfigurationError
+from zope.component import getUtility
+
+# Zope 2 stuff
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from Products.Five.metaconfigure import interface as provideInterface
+from Products.Five.security.interfaces import IPermission
+from Products.Five.security.permission import CheckerPublic
+
+def dottedName(klass):
+    if klass is None:
+        return 'None'
+    return klass.__module__ + '.' + klass.__name__
+
+class ProtectionDeclarationException(Exception):
+    """Security-protection-specific exceptions."""
+    pass
+
+class ContentDirective:
+
+    def __init__(self, _context, class_):
+        self.__id = dottedName(class_)
+        self.__class = class_
+        if isinstance(self.__class, ModuleType):
+            raise ConfigurationError('Content class attribute must be a class')
+        # not used yet
+        #self.__name = class_
+        #self.__normalized_name = _context.getNormalizedName(class_)
+        self.__context = _context
+
+    def implements(self, _context, interface):
+        for interface in interface:
+            _context.action(
+                discriminator = (
+                'five::directive:content', self.__class, object()),
+                callable = classImplements,
+                args = (self.__class, interface),
+                )
+            provideInterface(_context, interface)
+
+    def require(self, _context, permission=None,
+                attributes=None, interface=None):
+        """Require a the permission to access a specific aspect"""
+
+        if not (interface or attributes):
+            raise ConfigurationError("Nothing required")
+
+        if interface:
+            for i in interface:
+                if i:
+                    self.__protectByInterface(i, permission)
+        if attributes:
+            self.__protectNames(attributes, permission)
+
+    def allow(self, _context, attributes=None, interface=None):
+        """Like require, but with permission_id zope.Public"""
+        return self.require(_context, CheckerPublic, attributes, interface)
+
+
+    def __protectByInterface(self, interface, permission_id):
+        "Set a permission on names in an interface."
+        for n, d in interface.namesAndDescriptions(1):
+            self.__protectName(n, permission_id)
+        provideInterface(self.__context, interface)
+
+    def __protectName(self, name, permission_id):
+        "Set a permission on a particular name."
+        self.__context.action(
+            discriminator = ('protectName', self.__class, name),
+            callable = protectName,
+            args = (self.__class, name, permission_id)
+            )
+
+    def __protectNames(self, names, permission_id):
+        "Set a permission on a bunch of names."
+        for name in names:
+            self.__protectName(name, permission_id)
+
+    def __call__(self):
+        "Handle empty/simple declaration."
+        return self.__context.action(
+            discriminator = ('five:initialize:class', self.__class),
+            callable = initializeClass,
+            args = (self.__class,)
+            )
+
+
+def initializeClass(klass):
+    print 'Initializing class %r' % klass
+    InitializeClass(klass)
+
+def _getSecurity(klass):
+    info = vars(klass)
+    for k, v in info.items():
+        if hasattr(v, '__security_info__'):
+            return v
+    security = ClassSecurityInfo()
+    setattr(klass, '__security__', security)
+    return security
+
+def protectName(klass, name, permission_id):
+    print klass, name, permission_id
+    security = _getSecurity(klass)
+    if permission_id == CheckerPublic:
+        security.declarePublic(name)
+    else:
+        permission = getUtility(IPermission, name=permission_id)
+        security.declareProtected(permission.title, name)
+

Modified: z3/Five/trunk/meta.zcml
==============================================================================
--- z3/Five/trunk/meta.zcml	(original)
+++ z3/Five/trunk/meta.zcml	Sun Jun 20 05:28:07 2004
@@ -5,6 +5,11 @@
   <meta:directives namespace="http://namespaces.zope.org/zope">
 
     <meta:directive
+        name="permission"
+        schema=".metadirectives.IDefinePermissionDirective"
+        handler=".metaconfigure.definePermission" />
+
+    <meta:directive
         name="interface"
         schema=".metadirectives.IInterfaceDirective"
         handler=".metaconfigure.interface"
@@ -27,7 +32,7 @@
         schema=".metadirectives.IServiceTypeDirective"
         handler=".metaconfigure.serviceType"
         />
-                                                                                
+
     <meta:directive
         name="service"
         schema=".metadirectives.IServiceDirective"
@@ -37,13 +42,13 @@
   </meta:directives>
 
   <meta:directives namespace="http://namespaces.zope.org/five">
-    
+
     <meta:directive
         name="page"
         schema=".fivedirectives.IPageDirective"
         handler=".fiveconfigure.page"
         />
- 
+
     <meta:directive
        name="layer"
        schema=".fivedirectives.ILayerDirective"
@@ -62,6 +67,33 @@
        handler=".fiveconfigure.defaultSkin"
        />
 
+
+     <!-- This is a simplified version of z3's content directive,        -->
+     <!-- to accomodate the fact that z2's security is not as powerful -->
+
+    <meta:complexDirective
+        name="content"
+        schema=".directives.content.IContentDirective"
+        handler=".handlers.content.ContentDirective"
+        >
+
+      <meta:subdirective
+          name="implements"
+          schema=".directives.content.IImplementsSubdirective"
+          />
+
+      <meta:subdirective
+          name="require"
+          schema=".directives.content.IRequireSubdirective"
+          />
+
+      <meta:subdirective
+          name="allow"
+          schema=".directives.content.IAllowSubdirective"
+          />
+
+    </meta:complexDirective>
+
     <!-- specific to Five -->
     <meta:directive
        name="implements"

Modified: z3/Five/trunk/metaconfigure.py
==============================================================================
--- z3/Five/trunk/metaconfigure.py	(original)
+++ z3/Five/trunk/metaconfigure.py	Sun Jun 20 05:28:07 2004
@@ -18,6 +18,8 @@
 from zope.component import getService, getServices
 from zope.component.servicenames import Adapters
 from provideinterface import provideInterface
+from Products.Five.security.permission import Permission
+from Products.Five.security.interfaces import IPermission
 
 def handler(serviceName, methodName, *args, **kwargs):
     method=getattr(getService(serviceName), methodName)
@@ -126,3 +128,7 @@
         callable = provideInterface,
         args = (provides.__module__ + '.' + provides.getName(), provides)
                )
+
+def definePermission(_context, id, title, description=''):
+    permission = Permission(id, title, description)
+    utility(_context, IPermission, permission, name=id)

Modified: z3/Five/trunk/metadirectives.py
==============================================================================
--- z3/Five/trunk/metadirectives.py	(original)
+++ z3/Five/trunk/metadirectives.py	Sun Jun 20 05:28:07 2004
@@ -32,22 +32,22 @@
         )
 
 class IServiceTypeDirective(Interface):
-                                                           
+
     id = TextLine(
         title=u"ID of the service type",
         required=True
         )
- 
+
     interface = GlobalObject(
         title=u"Interface of the service type",
         required=True
         )
- 
+
 class IServiceDirective(IBasicComponentInformation):
     """
     Register a service
     """
- 
+
     serviceType = TextLine(
         title=u"ID of service type",
         required=True
@@ -57,7 +57,7 @@
     """
     Define an interface
     """
-    
+
     interface = GlobalObject(
         title=u"Interface",
         required=True
@@ -118,3 +118,25 @@
         required=False
         )
 
+class IBaseDefineDirective(Interface):
+    """Define a new security object."""
+
+    id = Id(
+        title=u"Id",
+        description=u"Id as which this object will be known and used.",
+        required=True)
+
+    title = MessageID(
+        title=u"Title",
+        description=u"Provides a title for the object.",
+        required=True)
+
+    description = MessageID(
+        title=u"Description",
+        description=u"Provides a description for the object.",
+        required=False)
+
+
+class IDefinePermissionDirective(IBaseDefineDirective):
+    """Define a new permission."""
+

Added: z3/Five/trunk/permissions.zcml
==============================================================================
--- (empty file)
+++ z3/Five/trunk/permissions.zcml	Sun Jun 20 05:28:07 2004
@@ -0,0 +1,9 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+	   i18n_domain="Five">
+
+  <permission
+    id="zope.ViewManagementScreens"
+    title="View Management Screens"
+    />
+
+</configure>

Added: z3/Five/trunk/security/__init__.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/security/__init__.py	Sun Jun 20 05:28:07 2004
@@ -0,0 +1 @@
+# import this

Added: z3/Five/trunk/security/fields.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/security/fields.py	Sun Jun 20 05:28:07 2004
@@ -0,0 +1,82 @@
+##############################################################################
+#
+# Copyright (c) 2004 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.
+#
+##############################################################################
+"""Security related configuration fields.
+
+$Id: fields.py 25253 2004-06-04 15:20:26Z jim $
+"""
+from zope import schema
+from zope.interface import implements
+from zope.schema.interfaces import IFromUnicode
+
+from Products.Five.security.permission import checkPermission
+
+class Permission(schema.Id):
+    r"""This field describes a permission.
+
+    Let's look at an example:
+
+    >>> class FauxContext:
+    ...     permission_mapping = {'zope.ManageCode':'zope.private'}
+    ...     _actions = []
+    ...     def action(self, **kws):
+    ...        self._actions.append(kws)
+    >>> context = FauxContext()
+    >>> field = Permission().bind(context)
+
+    Let's test the fromUnicode method:
+
+    >>> field.fromUnicode(u'zope.foo')
+    'zope.foo'
+    >>> field.fromUnicode(u'zope.ManageCode')
+    'zope.private'
+
+    Now let's see whether validation works alright
+
+    >>> field._validate('zope.ManageCode')
+    >>> context._actions[0]['args']
+    (None, 'zope.foo')
+    >>> field._validate('3 foo')
+    Traceback (most recent call last):
+    ...
+    InvalidId: 3 foo
+
+    zope.Public is always valid
+    >>> field._validate('zope.Public')
+    """
+    implements(IFromUnicode)
+
+    def fromUnicode(self, u):
+        u = super(Permission, self).fromUnicode(u)
+
+        map = getattr(self.context, 'permission_mapping', {})
+        return map.get(u, u)
+
+    def _validate(self, value):
+        super(Permission, self)._validate(value)
+
+        if value != 'zope.Public':
+            self.context.action(
+                discriminator = None,
+                callable = checkPermission,
+                args = (None, value),
+
+                # Delay execution till end. This is an
+                # optimization. We don't want to intersperse utility
+                # lookup, done when checking permissions, with utility
+                # definitions. Utility lookup is expensive after
+                # utility definition, as extensive caches have to be
+                # rebuilt.
+                order=9999999,
+                )
+

Added: z3/Five/trunk/security/interfaces.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/security/interfaces.py	Sun Jun 20 05:28:07 2004
@@ -0,0 +1,21 @@
+from zope.interface import Interface
+from zope.schema import TextLine, Text
+
+class IPermission(Interface):
+    """A permission object."""
+
+    id = TextLine(
+        title=u"Id",
+        description=u"Id as which this permission will be known and used.",
+        readonly=True,
+        required=True)
+
+    title = TextLine(
+        title=u"Title",
+        description=u"Provides a title for the permission.",
+        required=True)
+
+    description = Text(
+        title=u"Description",
+        description=u"Provides a description for the permission.",
+        required=False)

Added: z3/Five/trunk/security/permission.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/security/permission.py	Sun Jun 20 05:28:07 2004
@@ -0,0 +1,35 @@
+from zope.interface import implements
+from zope.component import queryUtility
+from Products.Five.security.interfaces import IPermission
+
+CheckerPublic = 'zope.Public'
+
+def checkPermission(context, permission_id):
+    """Check whether a given permission exists in the provided context.
+
+    >>> from zope.app.tests.placelesssetup import setUp, tearDown
+    >>> setUp()
+
+    >>> from zope.app.tests.ztapi import provideUtility
+    >>> provideUtility(IPermission, Permission('x'), 'x')
+
+    >>> checkPermission(None, 'x')
+    >>> checkPermission(None, 'y')
+    Traceback (most recent call last):
+    ...
+    ValueError: ('Undefined permission id', 'y')
+
+    >>> tearDown()
+    """
+    if permission_id == CheckerPublic:
+        return
+    if not queryUtility(IPermission, permission_id, context=context):
+        raise ValueError("Undefined permission id", permission_id)
+
+class Permission(object):
+    implements(IPermission)
+
+    def __init__(self, id, title="", description=""):
+        self.id = id
+        self.title = title
+        self.description = description

Added: z3/Five/trunk/tests/__init__.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/tests/__init__.py	Sun Jun 20 05:28:07 2004
@@ -0,0 +1 @@
+# import this

Modified: z3/Five/trunk/tests/test_five.py
==============================================================================
--- z3/Five/trunk/tests/test_five.py	(original)
+++ z3/Five/trunk/tests/test_five.py	Sun Jun 20 05:28:07 2004
@@ -1,11 +1,22 @@
 import os, sys
+from os import curdir
+from os.path import join, abspath, dirname, split
+
+try:
+    __file__
+except NameError:
+    # Test was called directly, so no __file__ global exists.
+    _prefix = abspath(curdir)
+else:
+    # Test was called by another test.
+    _prefix = abspath(dirname(__file__))
 
 if __name__ == '__main__':
     execfile(os.path.join(sys.path[0], 'framework.py'))
 
 # XXX hack but no other way to initialize options apparently
 from Zope.Startup.run import configure
-configure('../../../etc/zope.conf')
+configure(join(_prefix, '..', '..', '..', 'etc', 'zope.conf'))
 
 from Testing import ZopeTestCase
 
@@ -35,7 +46,7 @@
             "Adapted: The method",
             adapted.adaptedMethod())
 
-    def test_attribute_view(self):        
+    def test_attribute_view(self):
         self.root.manage_addProduct['FiveTest'].manage_addSimpleContent(
             'testoid', 'Testoid')
         test = self.root.testoid
@@ -67,7 +78,7 @@
             'testoid', 'Testoid')
         view = self.root.unrestrictedTraverse('testoid/flamingo2.html')
         self.assertEquals(u'<p>Hello world</p>\n', view())
-        
+
     def test_view_backwards_compatibility(self):
         self.root.manage_addProduct['FiveTest'].manage_addSimpleContent(
             'testoid', 'Testoid')
@@ -84,13 +95,13 @@
 <p>Hello world</p>
 """
         self.assertEquals(expected, view())
-        
-                          
+
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(FiveTestCase))
+    return suite
+
 if __name__ == '__main__':
     framework()
-else:
-    import unittest
-    def test_suite():
-        suite = unittest.TestSuite()
-        suite.addTest(unittest.makeSuite(FiveTestCase))
-        return suite
+

Added: z3/Five/trunk/tests/test_security.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/tests/test_security.py	Sun Jun 20 05:28:07 2004
@@ -0,0 +1,73 @@
+import os, sys
+from os import curdir
+from os.path import join, abspath, dirname, split
+
+try:
+    __file__
+except NameError:
+    # Test was called directly, so no __file__ global exists.
+    _prefix = abspath(curdir)
+else:
+    # Test was called by another test.
+    _prefix = abspath(dirname(__file__))
+
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+# XXX hack but no other way to initialize options apparently
+from Zope.Startup.run import configure
+configure(join(_prefix, '..', '..', '..', 'etc', 'zope.conf'))
+
+import unittest
+from Testing import ZopeTestCase
+
+ZopeTestCase.installProduct('Five')
+
+from AccessControl import ClassSecurityInfo
+
+class Dummy:
+
+    def foo(self): pass
+    def bar(self): pass
+    def baz(self): pass
+    def keg(self): pass
+    def wot(self): pass
+
+class Dummy1(Dummy):
+
+    security = ClassSecurityInfo()
+    security.declareProtected('View', 'foo')
+
+class Dummy2(Dummy):
+
+    security = ClassSecurityInfo()
+    security.declarePublic('foo')
+    security.declareProtected('View', 'bar')
+    security.declarePrivate('baz')
+    security.declareProtected('Edit', 'keg')
+
+
+class SecurityTestCase(ZopeTestCase.ZopeTestCase):
+
+    def test_require(self):
+        # Need to use xmlconfig() to run a
+        # small zcml snippet and then check
+        # the class __ac_permissions__ to see
+        # if the declaration took effect.
+        pass
+
+    def test_allow(self):
+        pass
+
+    def test_initialize(self):
+        pass
+
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(SecurityTestCase))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+


More information about the z3-checkins mailing list