[Zope3-checkins] CVS: Zope3/src/zope/app/publisher/browser - icon.py:1.1 fileresource.py:1.3 meta.zcml:1.4 resourcemeta.py:1.4

Jim Fulton jim@zope.com
Sat, 28 Dec 2002 11:14:31 -0500


Update of /cvs-repository/Zope3/src/zope/app/publisher/browser
In directory cvs.zope.org:/tmp/cvs-serv21770/browser

Modified Files:
	fileresource.py meta.zcml resourcemeta.py 
Added Files:
	icon.py 
Log Message:

Vastly simplified resource configuration be removing a bunch of unused 
features.  Also always put security proxies around resources, with 
default access of always public for needed methods or attributes.

Moved the missplaced icon configuration here.



=== Added File Zope3/src/zope/app/publisher/browser/icon.py ===
##############################################################################
#
# Copyright (c) 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.
# 
##############################################################################
"""Icon support


$Id: icon.py,v 1.1 2002/12/28 16:14:00 jim Exp $
"""

import os
import re

from zope.app.component.metaconfigure import handler
from zope.configuration.action import Action
from zope.component import getResource
from zope.app.publisher.browser import metaconfigure
from zope.app.traversing.getresource import getResource
from zope.publisher.interfaces.browser import IBrowserPresentation
from zope.configuration.exceptions import ConfigurationError

__metaclass__ = type

IName = re.compile('I[A-Z][a-z]')

class IconView:

    def __init__(self, context, request, rname, alt):
        self.context = context
        self.request = request
        self.rname = rname
        self.alt = alt

    def __call__(self):
        resource = getResource(self.context, self.rname, self.request)
        src = resource()

        return ('<img src="%s" alt="%s" width="16" height="16" border="0" />'
                % (src, self.alt))

    def url(self):
        resource = getResource(self.context, self.rname, self.request)
        src = resource()
        return src

class IconViewFactory:

    def __init__(self, rname, alt):
        self.rname = rname
        self.alt = alt

    def __call__(self, context, request):
        return IconView(context, request, self.rname, self.alt)

def IconDirective(_context, name, for_, file=None, resource=None,
                  layer='default', alt=None):

    for_ = _context.resolve(for_)
    iname = for_.__name__

    if alt is None:
        alt = iname
        if IName.match(alt):
            alt = alt[1:] # Remove leading 'I'

    results = []
    if file is not None and resource is not None:
        raise ConfigurationError(
            "Can't use more than one of file, and resource "
            "attributes for icon directives"
            )
    elif file is not None:
        resource = '-'.join(for_.__module__.split('.'))
        resource = "%s-%s-%s" % (resource, iname, name)
        ext = os.path.splitext(file)[1]
        if ext:
            resource += ext
        results = metaconfigure.resource(_context, image=file,
                                         name=resource, layer=layer)
    elif resource is None:
        raise ConfigurationError(
            "At least one of the file, and resource "
            "attributes for resource directives must be specified"
            )

    vfactory = IconViewFactory(resource, alt)

    return results + [
        Action(
        discriminator = ('view', name, vfactory, layer),
        callable = handler,
        args = ('Views', 'provideView',
                for_, name, IBrowserPresentation,
                vfactory, layer)),
        Action(
        discriminator = None,
        callable = handler,
        args = ('Interfaces', 'provideInterface',
                for_.__module__+'.'+for_.__name__,
                for_)
        )
        ]


=== Zope3/src/zope/app/publisher/browser/fileresource.py 1.2 => 1.3 ===
--- Zope3/src/zope/app/publisher/browser/fileresource.py:1.2	Wed Dec 25 09:13:09 2002
+++ Zope3/src/zope/app/publisher/browser/fileresource.py	Sat Dec 28 11:14:00 2002
@@ -27,7 +27,7 @@
 from zope.app.publisher.browser.resource import Resource
 from zope.app.datetimeutils import time as timeFromDateTimeString
 
-from zope.security.proxy import ProxyFactory
+from zope.security.proxy import Proxy
 
 class FileResource(BrowserView, Resource):
 
@@ -113,16 +113,18 @@
 
 class FileResourceFactory:
 
-    def __init__(self, path):
+    def __init__(self, path, checker):
         self.__file = File(path)
+        self.__checker = checker
 
     def __call__(self, request):
-        return ProxyFactory(FileResource(self.__file, request))
+        return Proxy(FileResource(self.__file, request), self.__checker)
 
 class ImageResourceFactory:
 
-    def __init__(self, path):
+    def __init__(self, path, checker):
         self.__file = Image(path)
+        self.__checker = checker
 
     def __call__(self, request):
-        return ProxyFactory(FileResource(self.__file, request))
+        return Proxy(FileResource(self.__file, request), self.__checker)


=== Zope3/src/zope/app/publisher/browser/meta.zcml 1.3 => 1.4 ===
--- Zope3/src/zope/app/publisher/browser/meta.zcml:1.3	Fri Dec 27 18:29:56 2002
+++ Zope3/src/zope/app/publisher/browser/meta.zcml	Sat Dec 28 11:14:00 2002
@@ -2,9 +2,9 @@
   
   <directives namespace="http://namespaces.zope.org/browser">
 
-    <directive 
-        name="view" 
-        handler="zope.app.publisher.browser.metaconfigure.view" >
+    <directive name="view" 
+               handler="zope.app.publisher.browser.metaconfigure.view" 
+               >
       <attribute name="name">
         <description>
               The name of the view. 
@@ -167,11 +167,11 @@
              name="permission"
              description="XXX deprecated" />
        </subdirective>
-    </directive>
+      </directive>
 
-    <directive 
-       name="defaultView" 
-       handler="zope.app.publisher.browser.metaconfigure.defaultView">
+    <directive name="defaultView" 
+               handler="zope.app.publisher.browser.metaconfigure.defaultView"
+               >
       <attribute name="name" >
         <description>
               The name of the view that should be the default.
@@ -215,38 +215,71 @@
        <attribute
           name="allowed_attributes"
           description="XXX deprecated" />
-    </directive>
+      </directive>
 
-    <directive
-        name="resource"
-        handler="zope.app.publisher.browser.metaconfigure.resource">
-      <attribute
-          name="name" />
-      <attribute
-          name="factory" />
-       <attribute
-          name="layer" />
-       <attribute
-          name="file" />
-       <attribute
-          name="image" />
-       <attribute
-          name="permission" />
-       <attribute
-          name="allowed_interface" />
-       <attribute
-          name="allowed_attributes" />
-       <subdirective name="page"> 
-         <attribute
-             name="name" />
-         <attribute
-             name="attribute" />
-         <attribute
-             name="permission" />
-         <attribute
-             name="layer" />
-       </subdirective>
-    </directive>
+    <directive name="resource"
+        handler="zope.app.publisher.browser.metaconfigure.resource"
+        >
+
+      <attribute name="name" required="yes">
+
+         <description>
+           The name of the resource
+
+           This is the name used in resource urls.  Resource urls are
+           of the form site/@@/resourcename, where site is the url of
+           "site", a folder with a service manager.
+
+           We make resource urls site-relative (as opposed to
+           content-relative) so as not to defeat caches.
+         </description>
+
+         </attribute>
+
+       <attribute name="layer" required="no">
+
+         <description>
+           The layer the resource should be found in
+
+           For information on layers, see the documentation for the
+           skin directive.
+
+           Defaults to "default".
+         </description>
+
+         </attribute>
+
+       <attribute name="file">
+
+         <description>
+            The file containing the resource data.
+         </description>
+
+         </attribute>
+
+       <attribute name="image">
+
+         <description>
+            The file containing the resource data.
+
+            If the image attribute is used, then an image resource,
+            rather than a file resource will be created.
+         </description>
+
+         </attribute>
+
+       <attribute name="permission" required="no">
+
+         <description>
+           The id of the permission needed to access the resource.
+
+           If a permission isn't specified, the resource will always
+           be accessible.
+         </description>
+
+         </attribute>
+
+       </directive>
 
     <directive
         name="i18n-resource"
@@ -264,11 +297,12 @@
         <attribute
             name="image" />
       </subdirective>
-    </directive>
+      </directive>
+
+    <directive name="skin"
+        handler="zope.app.publisher.browser.metaconfigure.skin"
+        >
 
-    <directive
-        name="skin"
-        handler="zope.app.publisher.browser.metaconfigure.skin">
       <attribute
           name="name"
           description="The name of the skin." />
@@ -283,10 +317,9 @@
           </description>
         </attribute>
 
-    </directive>
+      </directive>
 
-    <directive
-        name="menu"
+    <directive name="menu"
         handler="
             zope.app.publisher.browser.globalbrowsermenuservice.menuDirective"
         description="Define a new browser menu"
@@ -305,7 +338,7 @@
           name="title"
           description="A descriptive title for documentation purposes"
           />
-    </directive>
+      </directive>
 
     <directive
         name="menuItems"
@@ -391,13 +424,13 @@
           </description>
         </attribute>
        </subdirective> 
-    </directive>
+      </directive>
 
-    <directive 
-        name="menuItem" 
+    <directive name="menuItem" 
         handler="
         zope.app.publisher.browser.globalbrowsermenuservice.menuItemDirective"
-    >
+        >
+
       <attribute
           name="menu" />
       <attribute
@@ -410,12 +443,10 @@
           name="description" />
       <attribute
           name="filter" />
-    </directive>
+      </directive>
+
+    <directive name="icon" handler=".icon.IconDirective">
 
-    <directive
-        name="icon"
-        handler="zope.app.interfaces.publisher.browser.IconDirective"
-    >
       <attribute
           name="name" />
       <attribute


=== Zope3/src/zope/app/publisher/browser/resourcemeta.py 1.3 => 1.4 ===
--- Zope3/src/zope/app/publisher/browser/resourcemeta.py:1.3	Sat Dec 28 09:16:15 2002
+++ Zope3/src/zope/app/publisher/browser/resourcemeta.py	Sat Dec 28 11:14:00 2002
@@ -16,11 +16,8 @@
 $Id$
 """
 
-from zope.security.proxy import Proxy
-from zope.security.checker import CheckerPublic, NamesChecker, Checker
+from zope.security.checker import CheckerPublic, NamesChecker
 
-from zope.interfaces.configuration import INonEmptyDirective
-from zope.interfaces.configuration import ISubdirectiveHandler
 from zope.configuration.action import Action
 from zope.configuration.exceptions import ConfigurationError
 
@@ -28,160 +25,36 @@
 
 from zope.app.component.metaconfigure import handler
 
-from zope.app.publisher.browser.fileresource \
-     import FileResourceFactory, ImageResourceFactory
+from zope.app.publisher.browser.fileresource import FileResourceFactory
+from zope.app.publisher.browser.fileresource import ImageResourceFactory
 
-class resource(object):
+allowed_names = ('GET', 'HEAD', 'publishTraverse', 'browserDefault',
+                 'request', '__call__')
 
-    __class_implements__ = INonEmptyDirective
-    __implements__ = ISubdirectiveHandler
+def resource(_context, name, layer='default', permission='zope.Public',
+             file=None, image=None):
 
-    def __init__(self, _context, factory=None, name=None, layer='default',
-                 permission=None,
-                 allowed_interface=None, allowed_attributes=None,
-                 file=None, image=None):
-
-        if ((allowed_attributes or allowed_interface)
-            and ((name is None) or not permission)):
-            raise ConfigurationError(
-                "Must use name attribute with allowed_interface or "
-                "allowed_attributes"
-                )
-
-        if allowed_interface is not None:
-            allowed_interface = _context.resolve(allowed_interface)
-
-        self.__file = file
-        self.__image = image
-
-        self.factory = self._factory(_context, factory)
-        self.layer = layer
-        self.name = name
-        self.permission = permission
-        self.allowed_attributes = allowed_attributes
-        self.allowed_interface = allowed_interface
-        self.pages = 0
-
-    def _factory(self, _context, factory):
-        if ((factory is not None)
-            + (self.__file is not None)
-            + (self.__image is not None)
-            ) > 1:
-            raise ConfigurationError(
-                "Can't use more than one of factory, file, and image "
-                "attributes for resource directives"
-                )
+    if permission == 'zope.Public':
+        permission = CheckerPublic
 
-        if factory is not None:
-            return _context.resolve(factory)
-
-        if self.__file is not None:
-            return FileResourceFactory(_context.path(self.__file))
-
-        if self.__image is not None:
-            return ImageResourceFactory(_context.path(self.__image))
+    checker = NamesChecker(allowed_names, permission)
 
+    if file and image or not (file or image):
         raise ConfigurationError(
-            "At least one of the factory, file, and image "
-            "attributes for resource directives must be specified"
+            "Must use exactly one of file or image "
+            "attributes for resource directives"
             )
 
-
-    def page(self, _context, name, attribute, permission=None,
-             layer=None, factory=None):
-
-        permission = permission or self.permission
-
-        factory = self._pageFactory(factory or self.factory,
-                                    attribute, permission)
-
-        self.pages += 1
-
-        if layer is None:
-            layer = self.layer
-
-        return [
-            Action(
-                discriminator = ('resource', name, IBrowserPresentation,
-                                 layer),
-                callable = handler,
-                args = ('Resources', 'provideResource',
-                        name, IBrowserPresentation, factory, layer),
-                )
-            ]
-
-    def _pageFactory(self, factory, attribute, permission):
-        if permission:
-            if permission == 'zope.Public':
-                permission = CheckerPublic
-
-            def pageView(request,
-                         factory=factory, attribute=attribute,
-                         permission=permission):
-                return Proxy(getattr(factory(request), attribute),
-                             NamesChecker(__call__ = permission))
-
-        else:
-
-            def pageView(request,
-                         factory=factory, attribute=attribute):
-                return getattr(factory(request), attribute)
-
-        return pageView
-
-    def __call__(self, require=None):
-        if self.name is None:
-            return ()
-
-        permission = self.permission
-        allowed_interface = self.allowed_interface
-        allowed_attributes = self.allowed_attributes
-        factory = self.factory
-
-        if permission:
-            if require is None:
-                require = {}
-
-            if permission == 'zope.Public':
-                permission = CheckerPublic
-
-            if ((not allowed_attributes) and (allowed_interface is None)
-                and (not self.pages)):
-                allowed_attributes = '__call__'
-
-            for name in (allowed_attributes or '').split():
-                require[name] = permission
-
-            if allowed_interface:
-                for name in allowed_interface.names(1):
-                    require[name] = permission
-
-        if require:
-            checker = Checker(require.get)
-
-            factory = self._proxyFactory(factory, checker)
-
-
-        return [
-            Action(
-                discriminator = ('resource', self.name, IBrowserPresentation,
-                                 self.layer),
-                callable = handler,
-                args = ('Resources', 'provideResource',
-                        self.name, IBrowserPresentation, factory, self.layer),
-                )
-            ]
-
-    def _proxyFactory(self, factory, checker):
-
-        def proxyResource(request,
-                          factory=factory, checker=checker):
-            resource = factory(request)
-
-            # We need this in case the resource gets unwrapped and
-            # needs to be rewrapped
-            resource.__Security_checker__ = checker
-
-            return Proxy(resource, checker)
-
-        return proxyResource
+    if file:
+        factory = FileResourceFactory(_context.path(file), checker)
+    else:
+        factory = ImageResourceFactory(_context.path(image), checker)
+
+    return [
+        Action(
+            discriminator = ('resource', name, IBrowserPresentation, layer),
+            callable = handler,
+            args = ('Resources', 'provideResource',
+                    name, IBrowserPresentation, factory, layer),
+            )
+        ]