[Zope3-checkins] CVS: Zope3/src/zope/app/contentdirective - __init__.py:1.2 contentdirective.py:1.2 meta.zcml:1.2

Jim Fulton jim@zope.com
Wed, 25 Dec 2002 09:13:51 -0500


Update of /cvs-repository/Zope3/src/zope/app/contentdirective
In directory cvs.zope.org:/tmp/cvs-serv15352/src/zope/app/contentdirective

Added Files:
	__init__.py contentdirective.py meta.zcml 
Log Message:
Grand renaming:

- Renamed most files (especially python modules) to lower case.

- Moved views and interfaces into separate hierarchies within each
  project, where each top-level directory under the zope package
  is a separate project.

- Moved everything to src from lib/python.

  lib/python will eventually go away. I need access to the cvs
  repository to make this happen, however.

There are probably some bits that are broken. All tests pass
and zope runs, but I haven't tried everything. There are a number
of cleanups I'll work on tomorrow.



=== Zope3/src/zope/app/contentdirective/__init__.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:51 2002
+++ Zope3/src/zope/app/contentdirective/__init__.py	Wed Dec 25 09:12:49 2002
@@ -0,0 +1,2 @@
+#
+# This file is necessary to make this directory a package.


=== Zope3/src/zope/app/contentdirective/contentdirective.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:51 2002
+++ Zope3/src/zope/app/contentdirective/contentdirective.py	Wed Dec 25 09:12:49 2002
@@ -0,0 +1,206 @@
+##############################################################################
+#
+# 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.0 (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$
+"""
+from types import ModuleType
+from zope.interface.implements import implements
+from zope.interfaces.configuration import INonEmptyDirective
+from zope.interfaces.configuration import ISubdirectiveHandler
+from zope.component import getService
+from zope.configuration.exceptions import ConfigurationError
+from zope.configuration.action import Action
+from zope.app.component.classfactory import ClassFactory
+from zope.app.security.protectclass \
+    import protectLikeUnto, protectName, checkPermission, protectSetAttribute
+from zope.app.security.registries.permissionregistry import permissionRegistry
+from zope.security.proxy import ProxyFactory
+from zope.security.checker import NamesChecker
+from zope.schema.interfaces import IField
+
+PublicPermission = 'zope.Public'
+
+class ProtectionDeclarationException(Exception):
+    """Security-protection-specific exceptions."""
+    pass
+
+def handler(serviceName, methodName, *args, **kwargs):
+    method=getattr(getService(None, serviceName), methodName)
+    method(*args, **kwargs)
+
+def assertPermission(permission=None, *args, **kw):
+    """Check if permission is defined"""
+    if permission is not None:
+        permissionRegistry.ensurePermissionDefined(permission)
+
+class ContentDirective:
+
+    __class_implements__ = INonEmptyDirective
+    __implements__ = ISubdirectiveHandler
+
+    def __init__(self, _context, class_):
+        self.__id = class_
+        self.__class = _context.resolve(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):
+        resolved_interface = _context.resolve(interface)
+        return [
+            Action(
+                discriminator = ('ContentDirective', self.__class, object()),
+                callable = implements,
+                # the last argument is check=1, which causes implements
+                # to verify that the class does implement the interface
+                args = (self.__class, resolved_interface, 1),
+                ),
+            Action(
+               discriminator = None,
+               callable = handler,
+               args = ('Interfaces', 'provideInterface',
+                       resolved_interface.__module__+
+                       '.'+
+                       resolved_interface.__name__,
+                       resolved_interface)
+               )
+            ]
+
+    def require(self, _context,
+                permission=None, attributes=None, interface=None,
+                like_class=None, set_attributes=None, set_schema=None):
+        """Require a the permission to access a specific aspect"""
+
+        if like_class:
+            r = self.__mimic(_context, like_class)
+        else:
+            r = []
+
+        if not (interface or attributes or set_attributes or set_schema):
+            if r:
+                return r
+            raise ConfigurationError("Nothing required")
+
+        if not permission:
+            raise ConfigurationError("No permission specified")
+
+
+        if interface:
+            self.__protectByInterface(interface, permission, r)
+        if attributes:
+            self.__protectNames(attributes, permission, r)
+        if set_attributes:
+            self.__protectSetAttributes(set_attributes, permission, r)
+        if set_schema:
+            self.__protectSetSchema(set_schema, permission, r)
+
+
+        return r
+
+    def __mimic(self, _context, class_):
+        """Base security requirements on those of the given class"""
+        class_to_mimic = _context.resolve(class_)
+        return [
+            Action(discriminator=('mimic', self.__class, object()),
+                   callable=protectLikeUnto,
+                   args=(self.__class, class_to_mimic),
+                   )
+            ]
+
+    def allow(self, _context, attributes=None, interface=None):
+        """Like require, but with permission_id zope.Public"""
+        return self.require(_context, PublicPermission, attributes, interface)
+
+
+
+    def __protectByInterface(self, interface, permission_id, r):
+        "Set a permission on names in an interface."
+        interface = self.__context.resolve(interface)
+        for n, d in interface.namesAndDescriptions(1):
+            self.__protectName(n, permission_id, r)
+
+    def __protectName(self, name, permission_id, r):
+        "Set a permission on a particular name."
+        r.append((
+            ('protectName', self.__class, name),
+            protectName, (self.__class, name, permission_id)))
+
+    def __protectNames(self, names, permission_id, r):
+        "Set a permission on a bunch of names."
+        for name in names.split():
+            self.__protectName(name.strip(), permission_id, r)
+
+    def __protectSetAttributes(self, names, permission_id, r):
+        "Set a permission on a bunch of names."
+        for name in names.split():
+            r.append((
+                ('protectSetAttribute', self.__class, name),
+                protectSetAttribute, (self.__class, name, permission_id)))
+
+    def __protectSetSchema(self, schema, permission_id, r):
+        "Set a permission on a bunch of names."
+        schema = self.__context.resolve(schema)
+        for name in schema:
+            field = schema[name]
+            if IField.isImplementedBy(field):
+                r.append((
+                    ('protectSetAttribute', self.__class, name),
+                    protectSetAttribute, (self.__class, name, permission_id)))
+
+
+    def __call__(self):
+        "Handle empty/simple declaration."
+        return ()
+
+
+    def factory(self, _context,
+                permission=None, title="", id=None, description=''):
+        """Register a zmi factory for this class"""
+
+        id = id or self.__id
+
+        # note factories are all in one pile, services and content,
+        # so addable names must also act as if they were all in the
+        # same namespace, despite the service/content division
+        return [
+            Action(
+                discriminator = ('FactoryFromClass', id),
+                callable = provideClass,
+                args = (id, self.__class,
+                        permission, title, description)
+                )
+            ]
+
+def provideClass(id, _class, permission=None,
+                 title='', description=''):
+    """Provide simple class setup
+
+    - create a component
+
+    - set component permission
+    """
+
+    assertPermission(permission)
+    factory = ClassFactory(_class)
+    if permission and (permission != 'zope.Public'):
+        # XXX should getInterfaces be public, as below?
+        factory = ProxyFactory(factory,
+                               NamesChecker(('getInterfaces',),
+                                            __call__=permission))
+
+    getService(None, 'Factories').provideFactory(id, factory)


=== Zope3/src/zope/app/contentdirective/meta.zcml 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:51 2002
+++ Zope3/src/zope/app/contentdirective/meta.zcml	Wed Dec 25 09:12:49 2002
@@ -0,0 +1,91 @@
+<zopeConfigure xmlns='http://namespaces.zope.org/zope'>
+
+<!-- zope.app.contentdirective -->
+<directives namespace="http://namespaces.zope.org/zope">
+
+  <directive
+      name="content"
+      handler="zope.app.contentdirective.contentdirective.ContentDirective"
+      description="Make a component available as a content object type"
+  >
+    <attribute
+        name="class"
+        required="yes"
+        description="resolvable name of a class" />
+
+    <subdirective
+        name="implements"
+        description="Declare that the class given by the content
+            directive's class attribute implements a given interface"
+    >
+      <attribute
+          name="interface"
+          required="yes"
+          description="resolvable name of an Interface" />
+    </subdirective>
+
+    <subdirective
+        name="require"
+        description="Indicate that the a specified list of names or the
+          names in a given Interface require a given permission for
+          access."
+    >
+      <attribute
+          name="permission"
+          required="yes"
+          description="a permission id" />
+      <attribute
+          name="attributes"
+          description="space-separated list of attribute names" />
+      <attribute
+          name="interface"
+          description="the resolvable name of an interface" />
+      <attribute
+          name="like_class"
+          description="a class on which the security requirements
+              for this class will be based" />
+    </subdirective>
+
+    <subdirective
+        name="allow"
+        description="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."
+    >
+      <attribute
+          name="attributes"
+          description="space-separated list of attribute names" />
+      <attribute
+          name="interface"
+          description="the resolvable name of an interface" />
+    </subdirective>
+    <subdirective
+        name="factory"
+        description="Specify the factory used to create this
+            content object"
+    >
+      <attribute
+          name="permission"
+          description="permission id required to use this factory.
+              Although optional, this attribute should normally
+              be specified." />
+      <attribute
+          name="id"
+          description="the identifier for this factory in the
+              ZMI factory identification scheme.  If not given, defaults
+              to the literal string given as the content directive's
+              'class' attribute." />
+      <attribute
+          name="title"
+          description="text suitable for use in the 'add content' menu of
+              a management interface" />
+      <attribute
+          name="description"
+          description="longer narrative description of what this
+              factory does" />
+    </subdirective> 
+  </directive>
+</directives>
+
+</zopeConfigure>