[Zope3-checkins] CVS: Zope3/src/zope/app/publisher/browser - __init__.py:1.2 configure.zcml:1.2 fileresource.py:1.2 globalbrowsermenuservice.py:1.2 i18nfileresource.py:1.2 i18nresourcemeta.py:1.2 meta.zcml:1.2 metaconfigure.py:1.2 resource.py:1.2 resourcemeta.py:1.2 resources.py:1.2 viewmeta.py:1.2

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


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

Added Files:
	__init__.py configure.zcml fileresource.py 
	globalbrowsermenuservice.py i18nfileresource.py 
	i18nresourcemeta.py meta.zcml metaconfigure.py resource.py 
	resourcemeta.py resources.py viewmeta.py 
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/publisher/browser/__init__.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:10 2002
+++ Zope3/src/zope/app/publisher/browser/__init__.py	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,2 @@
+#
+# This file is necessary to make this directory a package.


=== Zope3/src/zope/app/publisher/browser/configure.zcml 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:10 2002
+++ Zope3/src/zope/app/publisher/browser/configure.zcml	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,39 @@
+<zopeConfigure
+   xmlns='http://namespaces.zope.org/zope'
+   xmlns:browser='http://namespaces.zope.org/browser'
+>
+
+
+<serviceType id="BrowserMenu"
+             interface="zope.app.interfaces.publisher.browser.IBrowserMenuService" />
+<service serviceType="BrowserMenu"
+         permission="zope.Public"
+         component="zope.app.publisher.browser.globalbrowsermenuservice.globalBrowserMenuService" />
+
+
+<content class="zope.publisher.browser.BrowserRequest">
+  <allow
+      interface="zope.publisher.interfaces.browser.IBrowserApplicationRequest" />
+  <allow
+      interface="zope.component.interfaces.IPresentationRequest" />
+</content>
+
+<content class="zope.app.publisher.browser.fileresource.FileResource">
+  <allow interface="zope.publisher.interfaces.browser.IBrowserPublisher" />
+  <allow attributes="GET HEAD __call__" />
+</content>
+
+<content class="zope.app.publisher.browser.i18nfileresource.I18nFileResource">
+  <allow interface="zope.publisher.interfaces.browser.IBrowserPublisher" />
+  <allow attributes="GET HEAD __call__" />
+</content>
+
+
+<browser:view name=""
+              factory="zope.app.publisher.browser.resources.Resources"
+              for="zope.app.interfaces.services.service.IServiceManagerContainer"
+              permission="zope.Public"
+              allowed_interface="zope.publisher.interfaces.browser.IBrowserPublisher"
+              />
+
+</zopeConfigure>


=== Zope3/src/zope/app/publisher/browser/fileresource.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:10 2002
+++ Zope3/src/zope/app/publisher/browser/fileresource.py	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,128 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+__metaclass__ = type # All classes are new style when run with Python 2.2+
+
+from zope.exceptions import NotFoundError
+
+from zope.publisher.browser import BrowserView
+from zope.publisher.interfaces.browser import IBrowserResource
+from zope.publisher.interfaces.browser import IBrowserPublisher
+
+from zope.app.publisher.fileresource import File, Image
+from zope.app.publisher.browser.resource import Resource
+from zope.app.datetimeutils import time as timeFromDateTimeString
+
+from zope.security.proxy import ProxyFactory
+
+class FileResource(BrowserView, Resource):
+
+    __implements__ = IBrowserResource, IBrowserPublisher
+
+    def publishTraverse(self, request, name):
+        '''See interface IBrowserPublisher'''
+        raise NotFoundError(name)
+
+    def browserDefault(self, request):
+        '''See interface IBrowserPublisher'''
+        method = request.get('REQUEST_METHOD', 'GET').upper()
+        return getattr(self, method), ()
+
+    #
+    ############################################################
+
+    # for unit tests
+    def _testData(self):
+        file = self.chooseContext()
+        f=open(self.context.path,'rb')
+        data=f.read()
+        f.close()
+        return data
+
+
+    def chooseContext(self):
+        """Choose the appropriate context"""
+        return self.context
+
+
+    def GET(self):
+        """Default document"""
+
+        file = self.chooseContext()
+        request = self.request
+        response = request.response
+
+        # HTTP If-Modified-Since header handling. This is duplicated
+        # from OFS.Image.Image - it really should be consolidated
+        # somewhere...
+        header = request.getHeader('If-Modified-Since', None)
+        if header is not None:
+            header = header.split(';')[0]
+            # Some proxies seem to send invalid date strings for this
+            # header. If the date string is not valid, we ignore it
+            # rather than raise an error to be generally consistent
+            # with common servers such as Apache (which can usually
+            # understand the screwy date string as a lucky side effect
+            # of the way they parse it).
+            try:    mod_since=long(timeFromDateTimeString(header))
+            except: mod_since=None
+            if mod_since is not None:
+                if getattr(file, 'lmt', None):
+                    last_mod = long(file.lmt)
+                else:
+                    last_mod = long(0)
+                if last_mod > 0 and last_mod <= mod_since:
+                    response.setStatus(304)
+                    return ''
+
+        response.setHeader('Content-Type', file.content_type)
+        response.setHeader('Last-Modified', file.lmh)
+
+        # Cache for one day
+        response.setHeader('Cache-Control', 'public,max-age=86400')
+        f=open(file.path,'rb')
+        data=f.read()
+        f.close()
+
+        return data
+
+    def HEAD(self):
+        file = self.chooseContext()
+        response = self.request.response
+        response = self.request.response
+        response.setHeader('Content-Type', file.content_type)
+        response.setHeader('Last-Modified', file.lmh)
+        # Cache for one day
+        response.setHeader('Cache-Control', 'public,max-age=86400')
+        return ''
+
+
+class FileResourceFactory:
+
+    def __init__(self, path):
+        self.__file = File(path)
+
+    def __call__(self, request):
+        return ProxyFactory(FileResource(self.__file, request))
+
+class ImageResourceFactory:
+
+    def __init__(self, path):
+        self.__file = Image(path)
+
+    def __call__(self, request):
+        return ProxyFactory(FileResource(self.__file, request))


=== Zope3/src/zope/app/publisher/browser/globalbrowsermenuservice.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:11 2002
+++ Zope3/src/zope/app/publisher/browser/globalbrowsermenuservice.py	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,178 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+
+from zope.app.interfaces.publisher.browser import IBrowserMenuService
+from zope.interfaces.configuration import INonEmptyDirective
+from zope.interfaces.configuration import ISubdirectiveHandler
+from zope.configuration.action import Action
+from zope.interface.type import TypeRegistry
+from zope.exceptions import DuplicationError, Unauthorized, Forbidden
+from zope.app.pagetemplate.engine import Engine
+from zope.app.publication.browser \
+     import PublicationTraverser
+from zope.app.component.metaconfigure import handler
+
+class GlobalBrowserMenuService:
+    """Global Browser Menu Service
+    """
+
+    __implements__ = IBrowserMenuService
+
+    def __init__(self):
+        self._registry = {}
+
+    _clear = __init__
+
+    def menu(self, menu_id, title, description=''):
+        # XXX we have nothing to do with the title and description. ;)
+
+        if menu_id in self._registry:
+            raise DuplicationError("Menu %s is already defined." % menu_id)
+
+        self._registry[menu_id] = TypeRegistry()
+
+    def menuItem(self, menu_id, interface,
+                 action, title, description='', filter_string=None):
+
+        registry = self._registry[menu_id]
+
+        if filter_string:
+            filter = Engine.compile(filter_string)
+        else:
+            filter = None
+
+        data = registry.get(interface) or []
+        data.append((action, title, description, filter))
+        registry.register(interface, data)
+
+    def getMenu(self, menu_id, object, request, max=999999):
+        registry = self._registry[menu_id]
+        traverser = PublicationTraverser()
+
+        result = []
+        seen = {}
+
+        for items in registry.getAllForObject(object):
+            for action, title, description, filter in items:
+
+                # Make sure we don't repeat a specification for a given title
+                if title in seen:
+                    continue
+                seen[title] = 1
+
+                if filter is not None:
+
+                    try:
+                        include = filter(Engine.getContext(
+                            context = object,
+                            nothing = None))
+                    except Unauthorized:
+                        include = 0
+
+                    if not include:
+                        continue
+
+                if action:
+                    try:
+                        v = traverser.traverseRelativeURL(
+                            request, object, action)
+                        # XXX
+                        # tickle the security proxy's checker
+                        # we're assuming that view pages are callable
+                        # this is a pretty sound assumption
+                        v.__call__
+                    except (Unauthorized, Forbidden):
+                        continue # Skip unauthorized or forbidden
+
+                if request.getURL().endswith(action):
+                    selected='selected'
+                else:
+                    selected=''
+
+                result.append({
+                    'title': title,
+                    'description': description,
+                    'action': "%s" % action,
+                    'selected': selected
+                    })
+
+                if len(result) >= max:
+                    return result
+
+        return result
+
+    def getFirstMenuItem(self, menu_id, object, request):
+        r = self.getMenu(menu_id, object, request, max=1)
+        if r:
+            return r[0]
+        return None
+
+def menuDirective(_context, id, title, description=''):
+    return [Action(
+        discriminator = ('browser:menu', id),
+        callable = globalBrowserMenuService.menu,
+        args = (id, title, description),
+        )]
+
+def menuItemDirective(_context, menu, for_,
+                      action, title, description='', filter=None):
+    return menuItemsDirective(_context, menu, for_).menuItem(
+        _context, action, title, description, filter)
+
+
+class menuItemsDirective:
+
+    __class_implements__ = INonEmptyDirective
+    __implements__ = ISubdirectiveHandler
+
+    def __init__(self, _context, menu, for_):
+        self.menu = menu
+        self.interface = _context.resolve(for_)
+
+    def menuItem(self, _context, action, title, description='', filter=None):
+        return [
+            Action(
+              discriminator = ('browser:menuItem',
+                               self.menu, self.interface, title),
+              callable = globalBrowserMenuService.menuItem,
+              args = (self.menu, self.interface,
+                      action, title, description, filter),
+              ),
+                ]
+
+    def __call__(self):
+        return [
+            Action(
+              discriminator = None,
+              callable = handler,
+              args = ('Interfaces', 'provideInterface',
+                      self.interface.__module__+'.'+self.interface.__name__,
+                      self.interface)
+              )
+            ]
+
+
+globalBrowserMenuService = GlobalBrowserMenuService()
+
+_clear = globalBrowserMenuService._clear
+
+# Register our cleanup with Testing.CleanUp to make writing unit tests simpler.
+from zope.testing.cleanup import addCleanUp
+addCleanUp(_clear)
+del addCleanUp
+
+__doc__ = GlobalBrowserMenuService.__doc__ + """
+
+$Id$
+"""


=== Zope3/src/zope/app/publisher/browser/i18nfileresource.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:11 2002
+++ Zope3/src/zope/app/publisher/browser/i18nfileresource.py	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,94 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+Internationalized file resource.
+
+$Id$
+"""
+__metaclass__ = type # All classes are new style when run with Python 2.2+
+
+from zope.publisher.interfaces.browser import IBrowserResource
+from zope.publisher.interfaces.browser import IBrowserPublisher
+
+from zope.app.publisher.fileresource import File, Image
+
+from zope.app.publisher.browser.fileresource import FileResource
+
+from zope.i18n.negotiator import negotiator
+from zope.interfaces.i18n import II18nAware
+
+
+class I18nFileResource(FileResource):
+
+    __implements__ = IBrowserResource, IBrowserPublisher, II18nAware
+
+    def __init__(self, data, request, defaultLanguage='en'):
+        """Creates an internationalized file resource.  data should be
+        a mapping from languages to File or Image objects.
+        """
+        self._data = data
+        self.request = request
+        self.defaultLanguage = defaultLanguage
+
+
+    def chooseContext(self):
+        """Choose the appropriate context according to language"""
+        langs = self.getAvailableLanguages()
+        language = negotiator.getLanguage(langs, self.request)
+        try:
+            return self._data[language]
+        except KeyError:
+            return self._data[self.defaultLanguage]
+
+
+    # for unit tests
+    def _testData(self, language):
+        file = self._data[language]
+        f=open(file.path,'rb')
+        data=f.read()
+        f.close()
+        return data
+
+
+    ############################################################
+    # Implementation methods for interface
+    # II18nAware.py
+
+    def getDefaultLanguage(self):
+        'See II18nAware'
+        return self.defaultLanguage
+
+    def setDefaultLanguage(self, language):
+        'See II18nAware'
+        if not self._data.has_key(language):
+            raise ValueError, \
+                  'cannot set nonexistent language (%s) as default' % language
+        self.defaultLanguage = language
+
+    def getAvailableLanguages(self):
+        'See II18nAware'
+        return self._data.keys()
+
+    #
+    ############################################################
+
+
+class I18nFileResourceFactory:
+
+    def __init__(self, data, defaultLanguage):
+        self.__data = data
+        self.__defaultLanguage = defaultLanguage
+
+    def __call__(self, request):
+        return I18nFileResource(self.__data, request, self.__defaultLanguage)


=== Zope3/src/zope/app/publisher/browser/i18nresourcemeta.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:11 2002
+++ Zope3/src/zope/app/publisher/browser/i18nresourcemeta.py	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,133 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Browser configuration code
+
+$Id$
+"""
+
+from zope.security.proxy import Proxy
+from zope.security.checker \
+     import CheckerPublic, NamesChecker, Checker
+
+from zope.interfaces.configuration import ISubdirectiveHandler
+from zope.interfaces.configuration import INonEmptyDirective
+from zope.configuration.action import Action
+from zope.configuration.exceptions import ConfigurationError
+
+from zope.publisher.interfaces.browser import IBrowserPresentation
+
+from zope.app.component.metaconfigure import handler
+
+from zope.app.publisher.fileresource import File, Image
+from zope.app.publisher.browser.i18nfileresource \
+     import I18nFileResourceFactory
+
+class I18nResource(object):
+
+    __class_implements__ = INonEmptyDirective
+    __implements__ = ISubdirectiveHandler
+
+    type = IBrowserPresentation
+    default_allowed_attributes = '__call__'
+
+    def __init__(self, _context, name=None, defaultLanguage='en',
+                 layer='default', permission=None):
+        self.name = name
+        self.defaultLanguage = defaultLanguage
+        self.layer = layer
+        self.permission = permission
+        self.__data = {}
+        self.__format = None
+
+
+    def translation(self, _context, language, file=None, image=None):
+
+        if file is not None and image is not None:
+            raise ConfigurationError(
+                "Can't use more than one of file, and image "
+                "attributes for resource directives"
+                )
+        elif file is not None:
+            if self.__format is not None and self.__format != File:
+                raise ConfigurationError(
+                    "Can't use both files and images in the same "
+                    "i18n-resource directive"
+                    )
+            self.__data[language] = File(_context.path(file))
+            self.__format = File
+        elif image is not None:
+            if self.__format is not None and self.__format != Image:
+                raise ConfigurationError(
+                    "Can't use both files and images in the same "
+                    "i18n-resource directive"
+                    )
+            self.__data[language] = Image(_context.path(image))
+            self.__format = Image
+        else:
+            raise ConfigurationError(
+                "At least one of the file, and image "
+                "attributes for resource directives must be specified"
+                )
+
+        return ()
+
+
+    def __call__(self, require = None):
+        if self.name is None:
+            return ()
+
+        if not self.__data.has_key(self.defaultLanguage):
+            raise ConfigurationError(
+                "A translation for the default language (%s) "
+                "must be specified" % self.defaultLanguage
+                )
+
+        permission = self.permission
+        factory = I18nFileResourceFactory(self.__data, self.defaultLanguage)
+
+        if permission:
+            if require is None:
+                require = {}
+
+            if permission == 'zope.Public':
+                permission = CheckerPublic
+
+        if require:
+            checker = Checker(require.get)
+
+            factory = self._proxyFactory(factory, checker)
+
+        return [
+            Action(
+                discriminator = ('i18n-resource', self.name, self.type,
+                                 self.layer),
+                callable = handler,
+                args = ('Resources', 'provideResource', self.name, self.type,
+                        factory, self.layer)
+                )
+            ]
+
+
+    def _proxyFactory(self, factory, checker):
+        def proxyView(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 proxyView


=== Zope3/src/zope/app/publisher/browser/meta.zcml 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:11 2002
+++ Zope3/src/zope/app/publisher/browser/meta.zcml	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,302 @@
+<zopeConfigure xmlns='http://namespaces.zope.org/zope'>
+  
+  <directives namespace="http://namespaces.zope.org/browser">
+
+    <directive 
+        name="view" 
+        handler="zope.app.publisher.browser.metaconfigure.view" >
+      <attribute
+          name="name"
+          description="The name of the view. 
+ 
+              The name shows up in URLs/paths. For example 'foo' or 
+              'foo.html'. This attribute is required unless you use the
+              subdirective 'page' to create sub views. If you do not have
+              sub pages, it is common to use an extension for the view name 
+              such as '.html'. If you do have sub pages and you want to
+              provide a view name, you shouldn't use extensions." />
+       <attribute
+          name="for"
+          description="The interface this view applies to. 
+
+              The view will be for all objects that implement this interface.
+              If 'for' is not supplied, the view applies to all objects 
+              (XXX this ought to change)." />
+      <attribute
+          name="factory"
+          description="A callable that realizes the view. 
+
+              The view factory interface is documented in IViewFactory. View
+              factories are passed two arguments, the context object
+              and the request object. You must specify either 'factory' or 
+              'template'. If it not allowed to use 'class' when you use
+              the 'factory' attribute. Attributes of the view can be exposed 
+              as pages with the 'page' subdirective." />
+       <attribute
+          name="template"
+          description="The name of a page template.
+
+              Refers to a file containing a page template (must end in
+              extension '.pt'). You must specify either 'template' or
+              'factory'. If you supply a template, you must
+              also supply a name. You can also optionally supply a
+              'class' attribute which contains a view class that has
+              methods that can be used by the template.
+
+              You cannot have sub pages if you use 'template'." />
+       <attribute
+          name="class"
+          description="A class to use with the template.
+
+              If you use the 'template' attribute you can optionally use
+              the 'class' attribute. This should point to a class that
+              provides methods that can be used in the template. This class
+              will be mixed in with the page template. From the template
+              you can refer to the methods using 'view/method_name'.
+    
+              You cannot use the 'class' attribute in combination with the
+              'factory' attribute." />
+       <attribute
+          name="permission" 
+          description="The permission needed to use the view. 
+
+              This attribute is required." />
+       <attribute
+          name="layer"
+          description="The layer the view is in. 
+
+              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'." />
+       <attribute
+          name="allowed_interface"
+          description="Interface that is also allowed if user has permission.
+
+              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." />
+       <attribute
+          name="allowed_attributes"
+          description="View attributes that are also allowed if user has permission.
+
+              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." />
+       <subdirective name="page">
+         <attribute
+             name="name" 
+             description="The name of a sub page of a view.
+
+                 The name attribute is always required for the 'page'
+                 directive. It is common to use an extension for the name, 
+                 such as '.html'." />
+         <attribute
+             name="attribute"
+             description="The name of the view attribute implementing the page.
+
+                 This refers to the attribute (method) on the view that is 
+                 implementing a specific sub page." />
+         <attribute
+             name="permission"
+             description="The permission needed to use this page.
+ 
+                 XXX Should we deprecate this? Could always be the same as
+                 the main view." />
+         <attribute
+             name="layer" 
+             description="XXX deprecated" />
+       </subdirective>
+       <subdirective name="defaultPage">
+         <attribute
+             name="name"
+             description="The name of the page that is the default.
+
+                 The named page will be used as the default if no name is
+                 specified explicitly in the path. If no defaultPage 
+                 directive is supplied, the default page will be the
+                 first page listed." />
+         <attribute
+             name="attribute"
+             description="XXX deprecated" />
+         <attribute
+             name="permission"
+             description="XXX deprecated" />
+       </subdirective>
+    </directive>
+
+    <directive 
+       name="defaultView" 
+       handler="zope.app.publisher.browser.metaconfigure.defaultView">
+      <attribute
+          name="name" 
+          description="The name of the view that should be the default.
+              
+              This name refers to another view that should be the
+              view used by default (if no view name is supplied
+              explicitly)." />
+       <attribute
+          name="for"
+          description="The interface this view is the default for.
+
+              The view is the default view for the supplied interface." />
+       <attribute
+          name="layer"
+          description="The layer the named view is the default view.
+
+              The named view is only the default view in the supplied
+              layer" />
+      <attribute
+          name="factory"
+          description="XXX deprecated" />
+       <attribute
+          name="template"
+          description="XXX deprecated" />
+       <attribute
+          name="permission"
+          description="XXX deprecated" />
+       <attribute
+          name="allowed_interface" 
+          description="XXX deprecated" />
+       <attribute
+          name="allowed_attributes"
+          description="XXX deprecated" />
+    </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="i18n-resource"
+        attributes="name default_language"
+        handler="zope.app.publisher.browser.metaconfigure.I18nResource">
+      <attribute
+          name="name" />
+      <attribute
+          name="default_language" />
+      <subdirective name="translation">
+        <attribute
+            name="language" />
+        <attribute
+            name="file" />
+        <attribute
+            name="image" />
+      </subdirective>
+    </directive>
+
+    <directive
+        name="skin"
+        handler="zope.app.publisher.browser.metaconfigure.skin">
+      <attribute
+          name="name"
+          description="The name of the skin." />
+      <attribute
+          name="layers"
+          description="A list of names of layers. 
+
+              This should be in order of lookup. Usually one of the layers
+              has the same name as the skin, and the last skin should be
+              'default', unless you want to completely override all views." />
+    </directive>
+
+    <directive
+        name="menu"
+        handler="
+            zope.app.publisher.browser.globalbrowsermenuservice.menuDirective">
+      <attribute
+          name="name" />
+      <attribute
+          name="title" />
+      <attribute
+          name="description" />
+    </directive>
+
+    <directive
+        name="menuItems"
+        attributes="menu for" 
+        handler="
+        zope.app.publisher.browser.globalbrowsermenuservice.menuItemsDirective"
+    >
+      <subdirective
+          name="menuItem" 
+      >
+        <attribute
+            name="action" />
+        <attribute
+            name="title" />
+        <attribute
+            name="description" />
+        <attribute
+            name="filter" />
+       </subdirective> 
+    </directive>
+
+    <directive 
+        name="menuItem" 
+        handler="
+        zope.app.publisher.browser.globalbrowsermenuservice.menuItemDirective"
+    >
+      <attribute
+          name="menu" />
+      <attribute
+          name="for" />
+      <attribute
+          name="action" />
+      <attribute
+          name="title" />
+      <attribute
+          name="description" />
+      <attribute
+          name="filter" />
+    </directive>
+
+    <directive
+        name="icon"
+        handler="zope.app.interfaces.publisher.browser.IconDirective"
+    >
+      <attribute
+          name="name" />
+      <attribute
+          name="for" />
+      <attribute
+          name="file" />
+      <attribute
+          name="resource" />
+      <attribute
+          name="alt" />
+      <attribute
+          name="layer" />
+    </directive>
+
+  </directives>
+
+</zopeConfigure>


=== Zope3/src/zope/app/publisher/browser/metaconfigure.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:11 2002
+++ Zope3/src/zope/app/publisher/browser/metaconfigure.py	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,68 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Browser configuration code
+
+$Id$
+"""
+
+from zope.configuration.action import Action
+
+from zope.publisher.interfaces.browser import IBrowserPresentation
+
+from zope.app.component.metaconfigure \
+     import defaultView as _defaultView, skin as _skin, handler
+
+from zope.app.publisher.browser.resourcemeta import resource
+from zope.app.publisher.browser.i18nresourcemeta import I18nResource
+from zope.app.publisher.browser.viewmeta import view
+from zope.interface import Interface
+
+def skin(_context, **__kw):
+    return _skin(_context,
+                 type='zope.publisher.interfaces.browser.IBrowserPresentation',
+                 **__kw)
+
+def defaultView(_context, name, for_=None, **__kw):
+
+    if __kw:
+        actions = view(_context, name=name, for_=for_, **__kw)()
+    else:
+        actions = []
+
+    if for_ is not None:
+        for_ = _context.resolve(for_)
+
+    type = IBrowserPresentation
+
+    actions += [
+        Action(
+        discriminator = ('defaultViewName', for_, type, name),
+        callable = handler,
+        args = ('Views','setDefaultViewName', for_, type, name),
+        )
+        ]
+    if for_ is not None:
+        actions.append
+        (
+        Action(
+        discriminator = None,
+        callable = handler,
+        args = ('Interfaces', 'provideInterface',
+                for_.__module__+'.'+for_.__name__,
+                for_)
+              )
+        )
+
+
+    return actions


=== Zope3/src/zope/app/publisher/browser/resource.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:11 2002
+++ Zope3/src/zope/app/publisher/browser/resource.py	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,55 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+__metaclass__ = type # All classes are new style when run with Python 2.2+
+
+from zope.component import queryView
+from zope.proxy.context import getWrapperContainer, getInnerWrapperData
+from zope.proxy.context import ContextMethod
+
+class Resource:
+
+    def __init__(self, request):
+        self.request = request
+
+    def __call__(wrapped_self):
+        name = getInnerWrapperData(wrapped_self)['name']
+        if name.startswith('++resource++'):
+            name = name[12:]
+
+        service = getWrapperContainer(wrapped_self)
+        site = getWrapperContainer(service)
+
+        skin = wrapped_self.request.getPresentationSkin()
+        if skin:
+            skin = "++skin++%s/" % skin
+
+        if site is None:
+            return "/%s@@/%s" % (skin, name)
+
+        absolute_url = queryView(service,
+                                 'absolute_url',
+                                 wrapped_self.request)
+
+        if absolute_url is None:
+            return "/%s@@/%s" % (skin, name)
+
+        site_url = absolute_url()
+
+        return "%s/%s@@/%s" % (site_url, skin, name)
+
+    __call__ = ContextMethod(__call__)


=== Zope3/src/zope/app/publisher/browser/resourcemeta.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:11 2002
+++ Zope3/src/zope/app/publisher/browser/resourcemeta.py	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,193 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Browser configuration code
+
+$Id$
+"""
+
+from zope.security.proxy import Proxy
+from zope.security.checker \
+     import CheckerPublic, NamesChecker, Checker
+
+from zope.interfaces.configuration import INonEmptyDirective
+from zope.interfaces.configuration import ISubdirectiveHandler
+from zope.configuration.action import Action
+from zope.configuration.exceptions import ConfigurationError
+
+from zope.publisher.interfaces.browser import IBrowserPresentation
+
+from zope.app.component.metaconfigure import handler
+
+from zope.app.publisher.browser.fileresource \
+     import FileResourceFactory, ImageResourceFactory
+
+class resource(object):
+
+    __class_implements__ = INonEmptyDirective
+    __implements__ = ISubdirectiveHandler
+
+    type = IBrowserPresentation
+    default_allowed_attributes = '__call__'  # space separated string
+
+    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 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))
+
+        raise ConfigurationError(
+            "At least one of the factory, file, and image "
+            "attributes for resource directives must be specified"
+            )
+
+
+    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 = self._discriminator(name, layer),
+                callable = handler,
+                args = self._args(name, factory, layer),
+                )
+            ]
+
+    def _discriminator(self, name, layer):
+        return ('resource', name, self.type, layer)
+
+    def _args(self, name, factory, layer):
+        return ('Resources', 'provideResource',
+                name, self.type, 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 = self.default_allowed_attributes
+
+            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 = self._discriminator(self.name, self.layer),
+                callable = handler,
+                args = self._args(self.name, factory, self.layer),
+                )
+            ]
+
+    def _proxyFactory(self, factory, checker):
+        def proxyView(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 proxyView


=== Zope3/src/zope/app/publisher/browser/resources.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:11 2002
+++ Zope3/src/zope/app/publisher/browser/resources.py	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Resource URL acess
+
+$Id$
+"""
+__metaclass__ = type # All classes are new style when run with Python 2.2+
+
+from zope.publisher.browser import BrowserView
+from zope.publisher.interfaces.browser import IBrowserPublisher
+from zope.component import getService
+from zope.proxy.context import ContextWrapper
+from zope.proxy.context import ContextMethod
+from zope.exceptions import NotFoundError
+
+class Resources(BrowserView):
+    """Provide a URL-accessible resource namespace
+    """
+
+    __implements__ = BrowserView.__implements__, IBrowserPublisher
+
+    def publishTraverse(wrapped_self, request, name):
+        '''See interface IBrowserPublisher'''
+
+        resource_service = getService(wrapped_self, 'Resources')
+        resource = resource_service.queryResource(wrapped_self, name, request)
+        if resource is None:
+            raise NotFoundError(wrapped_self, name)
+        return ContextWrapper(resource, resource_service)
+
+    publishTraverse = ContextMethod(publishTraverse)
+
+    def browserDefault(self, request):
+        '''See interface IBrowserPublisher'''
+        return empty, ()
+
+    #
+    ############################################################
+
+def empty():
+    return ''


=== Zope3/src/zope/app/publisher/browser/viewmeta.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:11 2002
+++ Zope3/src/zope/app/publisher/browser/viewmeta.py	Wed Dec 25 09:13:09 2002
@@ -0,0 +1,303 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Browser configuration code
+
+$Id$
+"""
+
+# XXX this will need to be refactored soon. :)
+
+from zope.security.proxy import Proxy
+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
+
+from zope.publisher.interfaces.browser import IBrowserPresentation
+from zope.publisher.interfaces.browser import IBrowserPublisher
+
+from zope.app.component.metaconfigure import handler
+
+from zope.app.pagetemplate.simpleviewclass import SimpleViewClass
+from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
+
+from zope.app.publisher.browser.resourcemeta import resource
+
+from zope.proxy.context import ContextMethod
+
+
+class view(resource):
+
+    __class_implements__ = INonEmptyDirective
+    __implements__ = ISubdirectiveHandler
+
+    __pages = None
+    __default = None
+
+    def __init__(self, _context, factory=None, name=None, for_=None,
+                 layer='default',
+                 permission=None,
+                 allowed_interface=None, allowed_attributes=None,
+                 template=None, class_=None):
+
+        if class_ and factory:
+            raise ConfigurationError("Can't specify a class and a factory")
+
+        factory = factory or class_
+
+        if template:
+            if name is None:
+                raise ConfigurationError(
+                    "Must specify name for template view")
+
+            self.default_allowed_attributes = (
+                '__call__ __getitem__ browserDefault')
+
+            template = _context.path(template)
+
+        self.template = template
+
+        if for_ is not None:
+            for_ = _context.resolve(for_)
+        self.for_ = for_
+
+        resource.__init__(self, _context, factory, name, layer,
+                          permission, allowed_interface, allowed_attributes)
+
+        if name:
+            self.__pages = {}
+
+
+    def page(self, _context, name, attribute=None, permission=None,
+             layer=None, template=None):
+
+        if self.template:
+            raise ConfigurationError(
+                "Can't use page or defaultPage subdirectives for simple "
+                "template views")
+
+        if self.name:
+            # Named view with pages.
+
+            if layer is not None:
+                raise ConfigurationError(
+                    "Can't specify a separate layer for pages of named "
+                    "templates.")
+
+            if template is not None:
+                template = _context.path(template)
+
+            self.__pages[name] = attribute, permission, template
+            if self.__default is None:
+                self.__default = name
+
+            # Call super(view, self).page() in order to get the side
+            # effects. (At the time of writing, this is to increment
+            # self.pages by one.)
+            # Throw away the result, as all the pages are accessed by
+            # traversing the PageTraverser subclass.
+            super(view, self).page(_context, name, attribute)
+            return ()
+
+        factory = self.factory
+
+        if template is not None:
+            attribute = attribute or '__template__'
+            klass = factory[-1]
+            klass = type(klass.__name__, (klass, object), {
+                attribute:
+                ViewPageTemplateFile(_context.path(template))
+                })
+            factory = factory[:]
+            factory[-1] = klass
+
+        return super(view, self).page(
+            _context, name, attribute, permission, layer,
+            factory=factory)
+
+    def defaultPage(self, _context, name):
+        if self.name:
+            self.__default = name
+            return ()
+
+        return [Action(
+            discriminator = ('defaultViewName', self.for_, self.type, name),
+            callable = handler,
+            args = ('Views','setDefaultViewName', self.for_, self.type, name),
+            )]
+
+
+    def _factory(self, _context, factory):
+        if self.template:
+            if factory:
+                factory = map(_context.resolve, factory.strip().split())
+                bases = (factory[-1], )
+                klass = SimpleViewClass(
+                    str(_context.path(self.template)),
+                    used_for=self.for_, bases=bases
+                    )
+                factory[-1] = klass
+                return factory
+
+            return [SimpleViewClass(
+                str(_context.path(self.template)),
+                used_for = self.for_
+                )]
+        else:
+            return map(_context.resolve, factory.strip().split())
+
+    def _discriminator(self, name, layer):
+        return ('view', self.for_, name, self.type, layer)
+
+    def _args(self, name, factory, layer):
+        return ('Views', 'provideView',
+                self.for_, name, self.type, factory, layer)
+
+    def _pageFactory(self, factory, attribute, permission):
+        factory = factory[:]
+        if permission:
+            if permission == 'zope.Public':
+                permission = CheckerPublic
+
+            def pageView(context, request,
+                         factory=factory[-1], attribute=attribute,
+                         permission=permission):
+                return Proxy(getattr(factory(context, request), attribute),
+                             NamesChecker(__call__ = permission))
+        else:
+            def pageView(context, request,
+                         factory=factory[-1], attribute=attribute):
+                return getattr(factory(context, request), attribute)
+        factory[-1] = pageView
+        return factory
+
+    def _proxyFactory(self, factory, checker):
+        factory = factory[:]
+
+        def proxyView(context, request,
+                      factory=factory[-1], checker=checker):
+
+            view = factory(context, request)
+
+            # We need this in case the resource gets unwrapped and
+            # needs to be rewrapped
+            view.__Security_checker__ = checker
+
+            return Proxy(view, checker)
+
+        factory[-1] =  proxyView
+
+        return factory
+
+    def __call__(self):
+        if not self.__pages:
+            return super(view, self).__call__()
+
+        # OK, we have named pages on a named view.
+        # We'll replace the original class with a new subclass that
+        # can traverse to the necessary pages.
+
+        require = {}
+
+        factory = self.factory[:]
+        klass = factory[-1]
+
+        klassdict = {'_PageTraverser__pages': {},
+                     '_PageTraverser__default': self.__default,
+                     '__implements__':
+                     (klass.__implements__, PageTraverser.__implements__),
+                     }
+        for name in self.__pages:
+            attribute, permission, template = self.__pages[name]
+
+            # We need to set the default permission on pages if the pages
+            # don't already have a permission explicitly set
+            permission = permission or self.permission
+            if permission == 'zope.Public':
+                permission = CheckerPublic
+
+            if not attribute:
+                attribute = name
+
+            require[attribute] = permission
+
+            if template:
+                klassdict[attribute] = ViewPageTemplateFile(template)
+
+            klassdict['_PageTraverser__pages'][name] = attribute, permission
+
+        klass = type(klass.__name__,
+                     (klass, PageTraverser, object),
+                     klassdict)
+        factory[-1] = klass
+        self.factory = factory
+
+        permission_for_browser_publisher = self.permission
+        if permission_for_browser_publisher == 'zope.Public':
+            permission_for_browser_publisher = CheckerPublic
+        for name in IBrowserPublisher.names(all=1):
+            require[name] = permission_for_browser_publisher
+
+        return super(view, self).__call__(require=require)
+
+
+class PageTraverser:
+
+    __implements__ = IBrowserPublisher
+
+    def publishTraverse(self, request, name):
+        attribute, permission = self._PageTraverser__pages[name]
+        return Proxy(getattr(self, attribute),
+                     NamesChecker(__call__=permission)
+                     )
+    publishTraverse = ContextMethod(publishTraverse)
+
+    def browserDefault(self, request):
+        return self, (self._PageTraverser__default, )
+    browserDefault = ContextMethod(browserDefault)
+
+
+def defaultView(_context, name, for_=None, **__kw):
+
+    if __kw:
+        actions = view(_context, name=name, for_=for_, **__kw)()
+    else:
+        actions = []
+
+    if for_ is not None:
+        for_ = _context.resolve(for_)
+
+    type = IBrowserPresentation
+
+    actions += [
+        Action(
+        discriminator = ('defaultViewName', for_, type, name),
+        callable = handler,
+        args = ('Views','setDefaultViewName', for_, type, name),
+        )]
+
+    if for_ is not None:
+        actions += [
+        Action(
+        discriminator = None,
+        callable = handler,
+        args = ('Interfaces', 'provideInterface',
+                for_.__module__+'.'+for_.__name__,
+                for_)
+        )
+        ]
+
+    return actions