[Checkins] SVN: zope.app.publisher/trunk/ Merge the zope.app.publisher refactoring results from my sandbox.

Dan Korostelev nadako at gmail.com
Thu Aug 27 11:12:52 EDT 2009


Log message for revision 103291:
  Merge the zope.app.publisher refactoring results from my sandbox.

Changed:
  U   zope.app.publisher/trunk/CHANGES.txt
  U   zope.app.publisher/trunk/README.txt
  U   zope.app.publisher/trunk/buildout.cfg
  U   zope.app.publisher/trunk/setup.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/__init__.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/configure.zcml
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/directoryresource.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/fields.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/fileresource.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nfileresource.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nresourcemeta.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/icon.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/managementviewselector.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.py
  D   zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/meta.zcml
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/metaconfigure.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/pagetemplateresource.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/resource.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/resourcemeta.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/resources.py
  D   zope.app.publisher/trunk/src/zope/app/publisher/browser/tests/
  U   zope.app.publisher/trunk/src/zope/app/publisher/browser/viewmeta.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/configure.zcml
  U   zope.app.publisher/trunk/src/zope/app/publisher/fileresource.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/http.zcml
  U   zope.app.publisher/trunk/src/zope/app/publisher/interfaces/__init__.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/interfaces/browser.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/interfaces/ftp.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/interfaces/http.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/interfaces/xmlrpc.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/pagetemplateresource.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/__init__.py
  U   zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/configure.zcml

-=-
Modified: zope.app.publisher/trunk/CHANGES.txt
===================================================================
--- zope.app.publisher/trunk/CHANGES.txt	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/CHANGES.txt	2009-08-27 15:12:51 UTC (rev 103291)
@@ -2,11 +2,37 @@
 CHANGES
 =======
 
-3.8.5 (unreleased)
+3.9.0 (unreleased)
 ==================
 
-- ...
+Refactor package, spliting it to several new packages:
 
+   * ``zope.browserresource`` - the resources mechanism was moved here, see its
+     CHANGES.txt for more information about changes during move.
+
+   * ``zope.ptresource`` - the page template resource was moved into another
+     package so zope.browserresource doesn't depend on any templating system.
+     See zope.ptresource's CHANGES.txt for more information.
+
+   * ``zope.browsermenu`` - the menu mechanism was moved here completely.
+   
+   * ``zope.browserpage`` - the browser:page directive and friends were
+     moved here. Also, these directives don't depend hardly on menu system
+     anymore, so they simply ignore the "menu" argument when zope.browsermenu
+     is not available.
+   
+Backward-compatibility imports are provided, so there should not be much impact
+for those who uses old imports.
+
+The CacheableBrowserLanguages and ModifiableBrowserLanguages adapters were
+moved into ``zope.publisher`` package, as well as browser:defaultSkin and
+browser:defaultView ZCML directives and ZCML class configuration for
+zope.publisher classes.
+
+ZCML registrations of IXMLRPCPublisher adapters for zope.container were moved
+into zope.container for now.
+
+
 3.8.4 (2009-07-23)
 ==================
 

Modified: zope.app.publisher/trunk/README.txt
===================================================================
--- zope.app.publisher/trunk/README.txt	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/README.txt	2009-08-27 15:12:51 UTC (rev 103291)
@@ -6,97 +6,20 @@
 chunk of the Zope Toolkit and its assumptions. It is maintained by the*
 `Zope Toolkit project <http://docs.zope.org/zopetoolkit/>`_.
 
-``zope.publisher`` is a general purpose object publishing framework
-which delegates to a publication object for determining the
-to-be-published object.  With Zope 3's default publication from
-``zope.app.publication``, this is usually a view or a resource.
+This package used to provide browser page, resource and menu classes
+for use with zope.publisher object publishing framework, as well as some
+other useful utilities and adapters, but most of things was factored out
+to separate packages, leaving here only backward-compatibility imports.
 
-This package, ``zope.app.publisher``, provides base implementations
-for those.  It also provides ZCML directives for configuring views and
-resources.  More specifically, ``zope.app.publisher`` defines the
-following ZCML directives:
+However, some potentially useful things are still contained in this package:
 
-* browser:page
+ * "date" field converter for zope.publisher's BrowserRequest field converter
+   mechanism.
+ 
+ * "Browser Skins" vocabulary (a vocabulary for IBrowserSkinType utilities)
+ 
+ * ManagementViewSelector (a browser view that redirects to a first available
+   management view)
 
-* browser:pages
-
-* browser:view
-
-* browser:menu
-
-* browser:menuItem
-
-* browser:menuItems
-
-* browser:addMenuitem
-
-* browser:resource
-
-* browser:resourceDirectory
-
-* browser:defaultSkin
-
-* browser:icon
-
-* xmlrpc:view
-
-
-Views and Browser pages
-=======================
-
-XXX writeme
-
-
-Resources
-=========
-
-Resources are static files and directories that are served to the browser
-directly from the filesystem. The most common example are images, CSS style
-sheets, or JavaScript files.
-
-Resources are be registered under a symbolic name and can later be referred to
-by that name, so their usage is independent from their physical location.
-
-You can register a single file with the `<browser:resource>` directive, and a
-whole directory with the `<browser:resourceDirectory>` directive, for example
-
-  <browser:resource
-    directory="/path/to/static.file"
-    name="myfile"
-    />
-
-  <browser:resourceDirectory
-    directory="/path/to/images"
-    name="main-images"
-    />
-
-This causes a named adapter to be registered that adapts the request to
-zope.interface.Interface (XXX why do we not use an explicit interface?),
-so to later retrieve a resource, use
-`zope.component.getAdapter(request, name='myfile')`.
-
-There are two ways to traverse to a resource,
-
-1. with the 'empty' view on a site, e. g. `http://localhost/@@/myfile`
-   (This is declared by zope.app.publisher.browser)
-
-2. with the `++resource++` namespace, e. g. `http://localhost/++resource++myfile`
-   (This is declared by zope.traversing.namespace)
-
-In case of resource-directories traversal simply continues through its contents,
-e. g. `http://localhost/@@/main-images/subdir/sample.jpg`
-
-Rather than putting together the URL to a resource manually, you should use
-zope.traversing.browser.interfaces.IAbsoluteURL to get the URL, or for a
-shorthand, call the resource object. This has an additional benefit:
-
-If you want to serve resources from a different URL, for example
-because you want to use a web server specialized in serving static files instead
-of the appserver, you can register an IAbsoluteURL adapter for the site under
-the name 'resource' that will be used to compute the base URLs for resources.
-
-For example, if you register 'http://static.example.com/' as the base 'resource'
-URL, the resources from the above example would yield the following absolute
-URLs: http://static.example.com/myfile and
-http://static.example.com/main-images
-(XXX what about http://static.example.com/main-images/subdir/sample.jpg?)
+ * XML-RPC view and method publishing mechanism along with xmlrpc:view ZCML
+   directive.

Modified: zope.app.publisher/trunk/buildout.cfg
===================================================================
--- zope.app.publisher/trunk/buildout.cfg	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/buildout.cfg	2009-08-27 15:12:51 UTC (rev 103291)
@@ -1,6 +1,6 @@
 [buildout]
 develop = .
-parts = test coverage-test coverage-report
+parts = test coverage-test coverage-report pydev
 
 [test]
 recipe = zc.recipe.testrunner
@@ -16,3 +16,7 @@
 eggs = z3c.coverage
 scripts = coverage=coverage-report
 arguments = ('coverage', 'coverage/report')
+
+[pydev]
+recipe = pb.recipes.pydev
+eggs = zope.app.publisher

Modified: zope.app.publisher/trunk/setup.py
===================================================================
--- zope.app.publisher/trunk/setup.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/setup.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -19,7 +19,7 @@
                     open('CHANGES.txt').read())
 
 setup(name='zope.app.publisher',
-      version = '3.8.5dev',
+      version = '3.9.0dev',
       url='http://pypi.python.org/pypi/zope.app.publisher/',
       author='Zope Corporation and Contributors',
       author_email='zope-dev at zope.org',
@@ -41,29 +41,26 @@
       namespace_packages=['zope', 'zope.app'],
       include_package_data=True,
       install_requires=['setuptools',
-                        'zope.component>=3.7.0',
+                        'zope.browsermenu',
+                        'zope.browserpage',
+                        'zope.browserresource',
+                        'zope.component',
                         'zope.configuration',
-                        'zope.container',
-                        'zope.contenttype',
                         'zope.datetime',
-                        'zope.i18n',
                         'zope.interface',
                         'zope.location',
-                        'zope.pagetemplate>=3.5.0',
-                        'zope.publisher>=3.8.0',
+                        'zope.ptresource',
+                        'zope.publisher>=3.9',
                         'zope.schema',
-                        'zope.site',
                         'zope.security',
-                        'zope.traversing>3.7.0',
                         'zope.componentvocabulary',
-                        'zope.browser',
-                        'zope.app.pagetemplate',
                         ],
       extras_require={
           'test': ['zope.testing',
                    'zope.app.testing',
                    'zope.app.securitypolicy',
                    'zope.app.zcmlfiles',
+                   'zope.container>=3.8.3',
                    'zope.site'],
           },
 

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/__init__.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/__init__.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/__init__.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,56 +15,11 @@
 
 $Id$
 """
-
-from zope.interface import implements
+# BBB imports
 from zope.publisher.browser import BrowserLanguages
-from zope.i18n.interfaces import IUserPreferredLanguages
-from zope.i18n.interfaces import IModifiableUserPreferredLanguages
-
-from zope.publisher.defaultview import IDefaultViewNameAPI #BBB import
-from zope.publisher.defaultview import getDefaultViewName #BBB import
-from zope.publisher.defaultview import queryDefaultViewName #BBB import
-
-
-class NotCompatibleAdapterError(Exception):
-    """Adapter not compatible with
-       zope.i18n.interfaces.IModifiableBrowserLanguages has been used.
-    """
-
-key = "zope.app.publisher.browser.IUserPreferredLanguages"
-
-class CacheableBrowserLanguages(BrowserLanguages):
-
-    implements(IUserPreferredLanguages)
-
-    def getPreferredLanguages(self):
-        languages_data = self._getLanguagesData()
-        if "overridden" in languages_data:
-            return languages_data["overridden"]
-        elif "cached" not in languages_data:
-            languages_data["cached"] = super(
-                CacheableBrowserLanguages, self).getPreferredLanguages()
-        return languages_data["cached"]
-
-    def _getLanguagesData(self):
-        annotations = self.request.annotations
-        languages_data = annotations.get(key)
-        if languages_data is None:
-            annotations[key] = languages_data = {}
-        return languages_data
-
-class ModifiableBrowserLanguages(CacheableBrowserLanguages):
-
-    implements(IModifiableUserPreferredLanguages)
-
-    def setPreferredLanguages(self, languages):
-        languages_data = self.request.annotations.get(key)
-        if languages_data is None:
-            # Better way to create a compatible with
-            # IModifiableUserPreferredLanguages adapter is to use
-            # CacheableBrowserLanguages as base class or as example.
-            raise NotCompatibleAdapterError("Adapter not compatible with "
-                "zope.i18n.interfaces.IModifiableBrowserLanguages "
-                "has been used.")
-        languages_data["overridden"] = languages
-        self.request.setupLocale()
+from zope.publisher.browser import CacheableBrowserLanguages
+from zope.publisher.browser import ModifiableBrowserLanguages
+from zope.publisher.browser import NotCompatibleAdapterError
+from zope.publisher.defaultview import IDefaultViewNameAPI
+from zope.publisher.defaultview import getDefaultViewName
+from zope.publisher.defaultview import queryDefaultViewName

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/configure.zcml
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/configure.zcml	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/configure.zcml	2009-08-27 15:12:51 UTC (rev 103291)
@@ -3,72 +3,15 @@
    xmlns:browser="http://namespaces.zope.org/browser"
    xmlns:zcml="http://namespaces.zope.org/zcml">
 
-<adapter
-    factory=".ModifiableBrowserLanguages"
-    for="zope.publisher.interfaces.http.IHTTPRequest"
-    provides="zope.i18n.interfaces.IModifiableUserPreferredLanguages"
-    />
+  <include package="zope.browserresource" />
+  <include package="zope.ptresource" />
+  <include package="zope.browsermenu" />
 
-<interface
-  interface="zope.app.publisher.interfaces.browser.IMenuItemType" />
-
 <utility
     name="Browser Skins"
     component=".vocabulary.BrowserSkinsVocabulary"
     />
 
-<class class="zope.publisher.browser.BrowserRequest">
-  <allow
-    interface="zope.publisher.interfaces.browser.IBrowserApplicationRequest"
-    attributes="response locale __str__"
-    />
-</class>
-
-<class class="zope.publisher.browser.TestRequest">
-  <allow
-    interface="zope.publisher.interfaces.browser.IBrowserApplicationRequest"
-    attributes="response"
-    />
-</class>
-
-<class class="zope.publisher.browser.BrowserResponse">
-  <allow
-    interface="zope.publisher.interfaces.http.IHTTPResponse"
-    />
-</class>
-
-<class class="zope.app.publisher.browser.fileresource.FileResource">
-  <allow interface="zope.publisher.interfaces.browser.IBrowserPublisher" />
-  <allow attributes="GET HEAD __call__" />
-</class>
-
-<class class="zope.app.publisher.browser.i18nfileresource.I18nFileResource">
-  <allow interface="zope.publisher.interfaces.browser.IBrowserPublisher" />
-  <allow attributes="GET HEAD __call__" />
-</class>
-
-<class class=".pagetemplateresource.PageTemplateResource">
-  <allow interface="zope.publisher.interfaces.browser.IBrowserPublisher" />
-  <allow attributes="__call__" />
-</class>
-
-<class class=".directoryresource.DirectoryResource">
-  <allow interface="zope.publisher.interfaces.browser.IBrowserPublisher" />
-  <allow attributes="get __getitem__" />
-</class>
-
-<adapter
-    factory=".resource.AbsoluteURL"
-    />
-
-<browser:page
-    name=""
-    for="zope.location.interfaces.ISite"
-    class="zope.app.publisher.browser.resources.Resources"
-    permission="zope.Public"
-    allowed_interface="zope.publisher.interfaces.browser.IBrowserPublisher"
-    />
-
 <!-- Management view selector -->
 <!-- Get first accessible item from zmi_views menu -->
 <browser:page
@@ -88,13 +31,4 @@
     allowed_interface="zope.publisher.interfaces.browser.IBrowserPublisher"
     />
 
-<!-- Menu access -->
-<browser:page
-    for="*"
-    name="view_get_menu"
-    permission="zope.Public"
-    class=".menu.MenuAccessView"
-    allowed_interface="zope.app.publisher.interfaces.browser.IMenuAccessView"
-    />
-
 </configure>

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/directoryresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/directoryresource.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/directoryresource.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -23,97 +23,6 @@
 
 $Id$
 """
-import os
-import posixpath
-
-from zope.interface import implements
-from zope.publisher.interfaces import NotFound
-from zope.publisher.browser import BrowserView
-from zope.publisher.interfaces.browser import IBrowserPublisher
-
-from zope.app.publisher.browser.resource import Resource
-
-from fileresource import FileResourceFactory, ImageResourceFactory
-from pagetemplateresource import PageTemplateResourceFactory
-from resources import empty
-
-_marker = object()
-
-# we only need this class as a context for DirectoryResource
-class Directory(object):
-
-    def __init__(self, path, checker, name):
-        self.path = path
-        self.checker = checker
-        self.__name__ = name
-
-class DirectoryResource(BrowserView, Resource):
-
-    implements(IBrowserPublisher)
-
-    resource_factories = {
-        '.gif':  ImageResourceFactory,
-        '.png':  ImageResourceFactory,
-        '.jpg':  ImageResourceFactory,
-        '.pt':   PageTemplateResourceFactory,
-        '.zpt':  PageTemplateResourceFactory,
-        '.html': PageTemplateResourceFactory,
-        }
-
-    default_factory = FileResourceFactory
-    directory_factory = None
-
-    def publishTraverse(self, request, name):
-        '''See interface IBrowserPublisher'''
-        return self.get(name)
-
-    def browserDefault(self, request):
-        '''See interface IBrowserPublisher'''
-        return empty, ()
-
-    def __getitem__(self, name):
-        res = self.get(name, None)
-        if res is None:
-            raise KeyError(name)
-        return res
-
-    def get(self, name, default=_marker):
-        path = self.context.path
-        filename = os.path.join(path, name)
-        isfile = os.path.isfile(filename)
-        isdir = os.path.isdir(filename)
-
-        if not (isfile or isdir):
-            if default is _marker:
-                raise NotFound(None, name)
-            return default
-
-        if isfile:
-            ext = os.path.splitext(os.path.normcase(name))[1]
-            factory = self.resource_factories.get(ext, self.default_factory)
-        else:
-            factory = self.directory_factory
-
-        rname = posixpath.join(self.__name__, name)
-        resource = factory(filename, self.context.checker, rname)(self.request)
-        resource.__parent__ = self
-        return resource
-
-
-class DirectoryResourceFactory(object):
-
-    factoryClass = DirectoryResource
-
-    def __init__(self, path, checker, name):
-        self.__dir = Directory(path, checker, name)
-        self.__checker = checker
-        self.__name = name
-
-    def __call__(self, request):
-        resource = self.factoryClass(self.__dir, request)
-        resource.__Security_checker__ = self.__checker
-        resource.__name__ = self.__name
-        return resource
-
-
-DirectoryResource.directory_factory = DirectoryResourceFactory
+# BBB imports
+from zope.browserresource.directory import Directory, DirectoryResource
+from zope.browserresource.directory import DirectoryResourceFactory

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/fields.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/fields.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/fields.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,94 +15,4 @@
 
 $Id$
 """
-__docformat__ = 'restructuredtext'
-
-import zope.component
-import zope.schema
-from zope.component.interfaces import ComponentLookupError
-from zope.configuration.exceptions import ConfigurationError
-from zope.configuration.fields import GlobalObject
-from zope.app.publisher.interfaces.browser import IMenuItemType
-
-
-class MenuField(GlobalObject):
-    r"""This fields represents a menu (item type).
-
-    Besides being able to look up the menu by importing it, we also try
-    to look up the name in the site manager.
-
-    >>> from zope.interface import directlyProvides
-    >>> from zope.interface.interface import InterfaceClass
-
-    >>> menu1 = InterfaceClass('menu1', (),
-    ...                        __doc__='Menu Item Type: menu1',
-    ...                        __module__='zope.app.menus')
-    >>> directlyProvides(menu1, IMenuItemType)
-
-    >>> menus = None
-    >>> class Resolver(object):
-    ...     def resolve(self, path):
-    ...         if path.startswith('zope.app.menus') and \
-    ...             hasattr(menus, 'menu1') or \
-    ...             path == 'zope.app.publisher.menus.menu1':
-    ...             return menu1
-    ...         raise ConfigurationError('menu1')
-
-    >>> field = MenuField()
-    >>> field = field.bind(Resolver())
-
-    Test 1: Import the menu
-    -----------------------
-
-    >>> field.fromUnicode('zope.app.publisher.menus.menu1') is menu1
-    True
-
-    Test 2: We have a shortcut name. Import the menu from `zope.app.menus1`.
-    ------------------------------------------------------------------------
-
-    >>> from types import ModuleType as module
-    >>> import sys
-    >>> menus = module('menus')
-    >>> old = sys.modules.get('zope.app.menus', None)
-    >>> sys.modules['zope.app.menus'] = menus
-    >>> setattr(menus, 'menu1', menu1)
-
-    >>> field.fromUnicode('menu1') is menu1
-    True
-
-    >>> if old is not None:
-    ...     sys.modules['zope.app.menus'] = old
-
-    Test 3: Get the menu from the Site Manager
-    ------------------------------------------
-    
-    >>> from zope.app.testing import ztapi
-    >>> ztapi.provideUtility(IMenuItemType, menu1, 'menu1')
-
-    >>> field.fromUnicode('menu1') is menu1
-    True
-    """
-
-    def fromUnicode(self, u):
-        name = str(u.strip())
-
-        try:
-            value = zope.component.queryUtility(IMenuItemType, name)
-        except ComponentLookupError:
-            # The component architecture is not up and running.
-            pass
-        else: 
-            if value is not None:
-                self.validate(value)
-                return value
-
-        try:
-            value = self.context.resolve('zope.app.menus.'+name)
-        except ConfigurationError, v:
-            try:
-                value = self.context.resolve(name)
-            except ConfigurationError, v:
-                raise zope.schema.ValidationError(v)
-        
-        self.validate(value)
-        return value
+from zope.browsermenu.field import MenuField # BBB import

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/fileresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/fileresource.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/fileresource.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,133 +15,7 @@
 
 $Id$
 """
-
-import time
-from zope.interface import implements
-from zope.datetime import time as timeFromDateTimeString
-from zope.publisher.interfaces import NotFound
-from zope.publisher.interfaces.browser import IBrowserPublisher
-from zope.publisher.browser import BrowserView
-
-from zope.app.publisher.fileresource import File, Image
-from zope.app.publisher.browser.resource import Resource
-
-class FileResource(BrowserView, Resource):
-
-    implements(IBrowserPublisher)
-
-    cacheTimeout = 86400
-
-    def publishTraverse(self, request, name):
-        '''See interface IBrowserPublisher'''
-        raise NotFound(None, name)
-
-    def browserDefault(self, request):
-        '''See interface IBrowserPublisher'''
-        return getattr(self, request.method), ()
-
-    #
-    ############################################################
-
-    # for unit tests
-    def _testData(self):
-        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
-
-        setCacheControl(response, self.cacheTimeout)
-
-        # 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)
-
-        f = open(file.path,'rb')
-        data = f.read()
-        f.close()
-
-        return data
-
-    def HEAD(self):
-        file = self.chooseContext()
-        response = self.request.response
-        response.setHeader('Content-Type', file.content_type)
-        response.setHeader('Last-Modified', file.lmh)
-        setCacheControl(response, self.cacheTimeout)
-        return ''
-
-
-def setCacheControl(response, secs=86400):
-    # Cache for one day by default
-    response.setHeader('Cache-Control', 'public,max-age=%s' % secs)
-    t = time.time() + secs
-    response.setHeader('Expires',
-                       time.strftime("%a, %d %b %Y %H:%M:%S GMT",
-                                     time.gmtime(t)))
-
-
-class FileResourceFactory(object):
-
-    resourceClass = FileResource
-
-    def __init__(self, path, checker, name):
-        self.__file = File(path, name)
-        self.__checker = checker
-        self.__name = name
-
-    def __call__(self, request):
-        resource = self.resourceClass(self.__file, request)
-        resource.__Security_checker__ = self.__checker
-        resource.__name__ = self.__name
-        return resource
-
-
-class ImageResourceFactory(object):
-
-    resourceClass = FileResource
-
-    def __init__(self, path, checker, name):
-        self.__file = Image(path, name)
-        self.__checker = checker
-        self.__name = name
-
-    def __call__(self, request):
-        resource = self.resourceClass(self.__file, request)
-        resource.__Security_checker__ = self.__checker
-        resource.__name__ = self.__name
-        return resource
+# BBB imports
+from zope.browserresource.file import FileResource, setCacheControl
+from zope.browserresource.file import FileResourceFactory
+ImageResourceFactory = FileResourceFactory

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nfileresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nfileresource.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nfileresource.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,75 +15,6 @@
 
 $Id$
 """
-from zope.publisher.interfaces.browser import IBrowserPublisher
-
-from zope.app.publisher.browser.fileresource import FileResource
-
-from zope.i18n.negotiator import negotiator
-from zope.i18n.interfaces import II18nAware
-from zope.interface import implements
-
-
-class I18nFileResource(FileResource):
-
-    implements(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(object):
-
-    def __init__(self, data, defaultLanguage):
-        self.__data = data
-        self.__defaultLanguage = defaultLanguage
-
-    def __call__(self, request):
-        return I18nFileResource(self.__data, request, self.__defaultLanguage)
+# BBB imports
+from zope.browserresource.i18nfile import I18nFileResource
+from zope.browserresource.i18nfile import I18nFileResourceFactory

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nresourcemeta.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nresourcemeta.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nresourcemeta.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,108 +15,4 @@
 
 $Id$
 """
-from zope.configuration.exceptions import ConfigurationError
-from zope.interface import Interface
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.security.proxy import Proxy
-from zope.security.checker import CheckerPublic, Checker
-from zope.component.zcml import handler
-
-from zope.app.publisher.fileresource import File, Image
-from zope.app.publisher.browser.i18nfileresource import I18nFileResourceFactory
-
-
-class I18nResource(object):
-
-    type = IBrowserRequest
-    default_allowed_attributes = '__call__'
-
-    def __init__(self, _context, name=None, defaultLanguage='en',
-                 layer=IDefaultBrowserLayer, permission=None):
-        self._context = _context
-        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.name)
-            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.name)
-            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)
-
-            factory = self._proxyFactory(factory, checker)
-
-        self._context.action(
-            discriminator = ('i18n-resource', self.name, self.type, self.layer),
-            callable = handler,
-            args = ('registerAdapter',
-                    factory, (self.layer,), Interface, self.name,
-                    self._context.info)
-            )
-
-
-    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
+from zope.browserresource.metaconfigure import I18nResource # BBB import

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/icon.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/icon.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/icon.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,100 +15,6 @@
 
 $Id$
 """
-import os
-import re
-
-from zope.interface import Interface
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.configuration.exceptions import ConfigurationError
-from zope.traversing.namespace import getResource
-from zope.component.interface import provideInterface
-from zope.component.zcml import handler
-
-from zope.app.publisher.browser import metaconfigure
-
-IName = re.compile('I[A-Z][a-z]')
-
-class IconView(object):
-
-    def __init__(self, context, request, rname, alt, width, height):
-        self.context = context
-        self.request = request
-        self.rname = rname
-        self.alt = alt
-        self.width = width
-        self.height = height
-
-    def __call__(self):
-        # The context is important here, since it becomes the parent of the
-        # icon, which is needed to generate the absolute URL.
-        resource = getResource(self.context, self.rname, self.request)
-        src = resource()
-
-        return ('<img src="%s" alt="%s" width="%s" height="%s" border="0" />'
-                % (src, self.alt, self.width, self.height))
-
-    def url(self):
-        resource = getResource(self.context, self.rname, self.request)
-        src = resource()
-        return src
-
-class IconViewFactory(object):
-
-    def __init__(self, rname, alt, width, height):
-        self.rname = rname
-        self.alt = alt
-        self.width = width
-        self.height = height
-
-    def __call__(self, context, request):
-        return IconView(context, request, self.rname, self.alt,
-                       self.width, self.height)
-
-def IconDirective(_context, name, for_, file=None, resource=None,
-                  layer=IDefaultBrowserLayer, title=None,
-                  width=16, height=16):
-
-    iname = for_.getName()
-
-    if title is None:
-        title = iname
-        if IName.match(title):
-            title = title[1:] # Remove leading 'I'
-
-    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
-        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, title, width, height)
-
-    _context.action(
-        discriminator = ('view', name, vfactory, layer),
-        callable = handler,
-        args = ('registerAdapter',
-                vfactory, (for_, layer), Interface, name, _context.info)
-        )
-
-    _context.action(
-        discriminator = None,
-        callable = provideInterface,
-        args = (for_.__module__+'.'+for_.getName(),
-                for_)
-        )
-
-    
+# BBB imports
+from zope.browserresource.icon import IconView, IconViewFactory
+from zope.browserresource.metaconfigure import icon as IconDirective

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/managementviewselector.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/managementviewselector.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/managementviewselector.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -18,7 +18,7 @@
 from zope.interface import implements
 from zope.publisher.interfaces.browser import IBrowserPublisher
 from zope.publisher.browser import BrowserView
-from zope.app.publisher.browser.menu import getFirstMenuItem
+from zope.browsermenu.menu import getFirstMenuItem
 
 class ManagementViewSelector(BrowserView):
     """View that selects the first available management view.

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,197 +15,12 @@
 
 $Id$
 """
-__docformat__ = "reStructuredText"
-import sys
-
-from zope.component import getAdapters
-from zope.component import getUtility
-from zope.interface import Interface
-from zope.interface import implements
-from zope.interface import providedBy
-from zope.interface.interfaces import IInterface
-from zope.pagetemplate.engine import Engine
-from zope.publisher.browser import BrowserView
-from zope.security import canAccess
-from zope.security import checkPermission
-from zope.security.interfaces import Forbidden
-from zope.security.interfaces import Unauthorized
-from zope.security.proxy import removeSecurityProxy
-from zope.traversing.publicationtraverse import PublicationTraverser
-
-from zope.app.publisher.interfaces.browser import IMenuAccessView
-from zope.app.publisher.interfaces.browser import IBrowserMenu
-from zope.app.publisher.interfaces.browser import IBrowserMenuItem
-from zope.app.publisher.interfaces.browser import IBrowserSubMenuItem
-from zope.app.publisher.interfaces.browser import IMenuItemType
-
-class BrowserMenu(object):
-    """Browser Menu"""
-    implements(IBrowserMenu)
-
-    def __init__(self, id, title=u'', description=u''):
-        self.id = id
-        self.title = title
-        self.description = description
-
-    def getMenuItemType(self):
-        return getUtility(IMenuItemType, self.id)
-
-    def getMenuItems(self, object, request):
-        """Return menu item entries in a TAL-friendly form."""
-
-        result = []
-        for name, item in getAdapters((object, request),
-                                      self.getMenuItemType()):
-            if item.available():
-                result.append(item)
-
-        # Now order the result. This is not as easy as it seems.
-        #
-        # (1) Look at the interfaces and put the more specific menu entries
-        #     to the front. 
-        # (2) Sort unambigious entries by order and then by title.
-        ifaces = list(providedBy(removeSecurityProxy(object)).__iro__)
-        max_key = len(ifaces)
-        def iface_index(item):
-            iface = item._for
-            if not iface:
-                iface = Interface
-            if IInterface.providedBy(iface):
-                return ifaces.index(iface)
-            if isinstance(removeSecurityProxy(object), item._for):
-                # directly specified for class, this goes first.
-                return -1
-            # no idea. This goes last.
-            return max_key
-        result = [(iface_index(item), item.order, item.title, item)
-                  for item in result]
-        result.sort()
-
-        result = [
-            {'title': title,
-             'description': item.description,
-             'action': item.action,
-             'selected': (item.selected() and u'selected') or u'',
-             'icon': item.icon,
-             'extra': item.extra,
-             'submenu': (IBrowserSubMenuItem.providedBy(item) and
-                         getMenu(item.submenuId, object, request)) or None}
-            for index, order, title, item in result]
-
-        return result
-
-
-class BrowserMenuItem(BrowserView):
-    """Browser Menu Item Class"""
-    implements(IBrowserMenuItem)
-
-    # See zope.app.publisher.interfaces.browser.IBrowserMenuItem
-    title = u''
-    description = u''
-    action = u''
-    extra = None
-    order = 0
-    permission = None
-    filter = None
-    icon = None
-    _for = Interface
-
-    def available(self):
-        """See zope.app.publisher.interfaces.browser.IBrowserMenuItem"""
-        # Make sure we have the permission needed to access the menu's action
-        if self.permission is not None:
-            # If we have an explicit permission, check that we
-            # can access it.
-            if not checkPermission(self.permission, self.context):
-                return False
-
-        elif self.action != u'':
-            # Otherwise, test access by attempting access
-            path = self.action
-            l = self.action.find('?')
-            if l >= 0:
-                path = self.action[:l]
-
-            traverser = PublicationTraverser()
-            try:
-                view = traverser.traverseRelativeURL(
-                    self.request, self.context, path)
-            except (Unauthorized, Forbidden, LookupError):
-                return False
-            else:
-                # we're assuming that view pages are callable
-                # this is a pretty sound assumption
-                if not canAccess(view, '__call__'):
-                    return False
-
-        # Make sure that we really want to see this menu item
-        if self.filter is not None:
-
-            try:
-                include = self.filter(Engine.getContext(
-                    context = self.context,
-                    nothing = None,
-                    request = self.request,
-                    modules = sys.modules,
-                    ))
-            except Unauthorized:
-                return False
-            else:
-                if not include:
-                    return False
-
-        return True
-
-    def selected(self):
-        """See zope.app.publisher.interfaces.browser.IBrowserMenuItem"""
-        request_url = self.request.getURL()
-
-        normalized_action = self.action
-        if self.action.startswith('@@'):
-            normalized_action = self.action[2:]
-
-        if request_url.endswith('/'+normalized_action):
-            return True
-        if request_url.endswith('/++view++'+normalized_action):
-            return True
-        if request_url.endswith('/@@'+normalized_action):
-            return True
-
-        return False
-
-
-class BrowserSubMenuItem(BrowserMenuItem):
-    """Browser Menu Item Base Class"""
-    implements(IBrowserSubMenuItem)
-
-    # See zope.app.publisher.interfaces.browser.IBrowserSubMenuItem
-    submenuId = None
-
-    def selected(self):
-        """See zope.app.publisher.interfaces.browser.IBrowserMenuItem"""
-        if self.action is u'':
-            return False
-        return super(BrowserSubMenuItem, self).selected()
-
-
-def getMenu(id, object, request):
-    """Return menu item entries in a TAL-friendly form."""
-    menu = getUtility(IBrowserMenu, id)
-    return menu.getMenuItems(object, request)
-
-
-def getFirstMenuItem(id, object, request):
-    """Get the first item of a menu."""
-    items = getMenu(id, object, request)
-    if items:
-        return items[0]
-    return None
-
-
-class MenuAccessView(BrowserView):
-    """A view allowing easy access to menus."""
-    implements(IMenuAccessView)
-
-    def __getitem__(self, menuId):
-        return getMenu(menuId, self.context, self.request)
+# BBB imports
+from zope.browsermenu.menu import (
+    BrowserMenu,
+    BrowserMenuItem,
+    BrowserSubMenuItem,
+    getMenu,
+    getFirstMenuItem,
+    MenuAccessView,
+)

Deleted: zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt	2009-08-27 15:12:51 UTC (rev 103291)
@@ -1,697 +0,0 @@
-=============
-Browser Menus
-=============
-
-Browser menus are used to categorize browser actions, such as the views of a
-content component or the addable components of a container. In essence they
-provide the same functionality as menu bars in desktop application.
-
-  >>> from zope.app.publisher.browser import menu, menumeta
-
-Menus are simple components that have an id, title and description. They also
-must provide a method called ``getMenuItems(object, request)`` that returns a
-TAL-friendly list of information dictionaries. We will see this in detail
-later. The default menu implementation, however, makes the menu be very
-transparent by identifying the menu through an interface. So let's define and
-register a simple edit menu:
-
-  >>> import zope.interface
-  >>> class EditMenu(zope.interface.Interface):
-  ...     """This is an edit menu."""
-
-  >>> from zope.app.publisher.interfaces.browser import IMenuItemType
-  >>> zope.interface.directlyProvides(EditMenu, IMenuItemType)
-
-  >>> from zope.app.testing import ztapi
-  >>> ztapi.provideUtility(IMenuItemType, EditMenu, 'edit')
-
-Now we have to create and register the menu itself:
-
-  >>> from zope.app.publisher.interfaces.browser import IBrowserMenu
-  >>> ztapi.provideUtility(
-  ...     IBrowserMenu, menu.BrowserMenu('edit', u'Edit', u'Edit Menu'), 'edit')
-
-Note that these steps seem like a lot of boilerplate, but all this work is
-commonly done for you via ZCML. An item in a menu is simply an adapter that
-provides. In the following section we will have a closer look at the browser
-menu item:
-
-``BrowserMenuItem`` class
--------------------------
-
-The browser menu item represents an entry in the menu. Essentially, the menu
-item is a browser view of a content component. Thus we have to create a
-content component first:
-
-  >>> class IContent(zope.interface.Interface):
-  ...     pass
-
-  >>> from zope.publisher.interfaces.browser import IBrowserPublisher
-  >>> from zope.security.interfaces import Unauthorized, Forbidden
-
-  >>> class Content(object):
-  ...     zope.interface.implements(IContent, IBrowserPublisher)
-  ...
-  ...     def foo(self):
-  ...         pass
-  ...
-  ...     def browserDefault(self, r):
-  ...         return self, ()
-  ...
-  ...     def publishTraverse(self, request, name):
-  ...         if name.startswith('fb'):
-  ...             raise Forbidden, name
-  ...         if name.startswith('ua'):
-  ...             raise Unauthorized, name
-  ...         if name.startswith('le'):
-  ...             raise LookupError, name
-  ...         return self.foo
-
-We also implemented the ``IBrowserPublisher`` interface, because we want to
-make the object traversable, so that we can make availability checks later.
-
-Since the ``BrowserMenuItem`` is just a view, we can initiate it with an
-object and a request.
-
-  >>> from zope.publisher.browser import TestRequest
-  >>> item = menu.BrowserMenuItem(Content(), TestRequest())
-
-Note that the menu item knows *nothing* about the menu itself. It purely
-depends on the adapter registration to determine in which menu it will
-appear. The advantage is that a menu item can be reused in several menus.
-
-Now we add a title, description, order and icon and see whether we can then
-access the value. Note that these assignments are always automatically done by
-the framework.
-
-  >>> item.title = u'Item 1'
-  >>> item.title
-  u'Item 1'
-
-  >>> item.description = u'This is Item 1.'
-  >>> item.description
-  u'This is Item 1.'
-
-  >>> item.order
-  0
-  >>> item.order = 1
-  >>> item.order
-  1
-
-  >>> item.icon is None
-  True
-  >>> item.icon = u'/@@/icon.png'
-  >>> item.icon
-  u'/@@/icon.png'
-
-Since there is no permission or view specified yet, the menu item should
-be available and not selected.
-
-  >>> item.available()
-  True
-  >>> item.selected()
-  False
-
-There are two ways to deny availability of a menu item: (1) the current
-user does not have the correct permission to access the action or the menu
-item itself, or (2) the filter returns ``False``, in which case the menu
-item should also not be shown. 
-
-  >>> from zope.security.interfaces import IPermission
-  >>> from zope.security.permission import Permission
-  >>> from zope.app.testing import ztapi
-  >>> perm = Permission('perm', 'Permission')
-  >>> ztapi.provideUtility(IPermission, perm, 'perm')
-
-  >>> class ParticipationStub(object):
-  ...     principal = 'principal'
-  ...     interaction = None
-
-
-In the first case, the permission of the menu item was explicitely
-specified. Make sure that the user needs this permission to make the menu
-item available.
-
-  >>> item.permission = perm
-
-Now, we are not setting any user. This means that the menu item should be
-available.
-
-  >>> from zope.security.management import newInteraction, endInteraction
-  >>> endInteraction()
-  >>> newInteraction()
-  >>> item.available()
-  True
-
-Now we specify a principal that does not have the specified permission.
-
-  >>> endInteraction()
-  >>> newInteraction(ParticipationStub())
-  >>> item.available()
-  False
-
-In the second case, the permission is not explicitely defined and the
-availability is determined by the permission required to access the
-action.
-
-  >>> item.permission = None
-
-  All views starting with 'fb' are forbidden, the ones with 'ua' are
-  unauthorized and all others are allowed.
-
-  >>> item.action = u'fb'
-  >>> item.available()
-  False
-  >>> item.action = u'ua'
-  >>> item.available()
-  False
-  >>> item.action = u'a'
-  >>> item.available()
-  True
-
-Also, sometimes a menu item might be registered for a view that does not
-exist. In those cases the traversal mechanism raises a `TraversalError`, which
-is a special type of `LookupError`. All actions starting with `le` should
-raise this error:
-
-  >>> item.action = u'le'
-  >>> item.available()
-  False
-
-Now let's test filtering. If the filter is specified, it is assumed to be
-a TALES obejct.
-
-  >>> from zope.pagetemplate.engine import Engine
-  >>> item.action = u'a'
-  >>> item.filter = Engine.compile('not:context')
-  >>> item.available()
-  False
-  >>> item.filter = Engine.compile('context')
-  >>> item.available()
-  True
-
-Finally, make sure that the menu item can be selected.
-
-  >>> item.request = TestRequest(SERVER_URL='http://127.0.0.1/@@view.html',
-  ...                            PATH_INFO='/@@view.html')
-
-  >>> item.selected()
-  False
-  >>> item.action = u'view.html'
-  >>> item.selected()
-  True
-  >>> item.action = u'@@view.html'
-  >>> item.selected()
-  True
-  >>> item.request = TestRequest(
-  ...     SERVER_URL='http://127.0.0.1/++view++view.html',
-  ...     PATH_INFO='/++view++view.html')
-  >>> item.selected()
-  True
-  >>> item.action = u'otherview.html'
-  >>> item.selected()
-  False
-
-
-``BrowserSubMenuItem`` class
-----------------------------
-
-The menu framework also allows for submenus. Submenus can be inserted by
-creating a special menu item that simply points to another menu to be
-inserted:
-
-  >>> item = menu.BrowserSubMenuItem(Content(), TestRequest())
-
-The framework will always set the sub-menu automatically (we do it
-manually here):
-
-  >>> class SaveOptions(zope.interface.Interface):
-  ...     "A sub-menu that describes available save options for the content."
-
-  >>> zope.interface.directlyProvides(SaveOptions, IMenuItemType)
-
-  >>> ztapi.provideUtility(IMenuItemType, SaveOptions, 'save')
-  >>> ztapi.provideUtility(IBrowserMenu,
-  ...                      menu.BrowserMenu('save', u'Save', u'Save Menu'),
-  ...                      'save')
-
-Now we can assign the sub-menu id to the menu item: 
-
-  >>> item.submenuId = 'save'
-
-Also, the ``action`` attribute for the browser sub-menu item is optional,
-because you often do not want the item itself to represent something. The rest
-of the class is identical to the ``BrowserMenuItem`` class.
-
-
-Getting a Menu
---------------
-
-Now that we know how the single menu item works, let's have a look at how menu
-items get put together to a menu. But let's first create some menu items and
-register them as adapters with the component architecture.
-
-Register the edit menu entries first. We use the menu item factory to create
-the items:
-
-  >>> from zope.app.testing import ztapi
-  >>> from zope.publisher.interfaces.browser import IBrowserRequest
-
-  >>> undo = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="Undo", 
-  ...                                 action="undo.html")
-  >>> ztapi.provideAdapter((IContent, IBrowserRequest), EditMenu, undo, 'undo')
-
-  >>> redo = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="Redo",
-  ...                                 action="redo.html", icon="/@@/redo.png")
-  >>> ztapi.provideAdapter((IContent, IBrowserRequest), EditMenu, redo, 'redo')
-
-  >>> save = menumeta.MenuItemFactory(menu.BrowserSubMenuItem, title="Save", 
-  ...                                 submenuId='save', order=2)
-  >>> ztapi.provideAdapter((IContent, IBrowserRequest), EditMenu, save, 'save')
-
-And now the save options:
-
-  >>> saveas = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="Save as", 
-  ...                                   action="saveas.html")
-  >>> ztapi.provideAdapter((IContent, IBrowserRequest), 
-  ...                      SaveOptions, saveas, 'saveas')
-
-  >>> saveall = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="Save all",
-  ...                                    action="saveall.html")
-  >>> ztapi.provideAdapter((IContent, IBrowserRequest), 
-  ...                      SaveOptions, saveall, 'saveall')
-
-Note that we can also register menu items for classes:
-
-
-  >>> new = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="New",
-  ...                                 action="new.html", _for=Content)
-  >>> ztapi.provideAdapter((Content, IBrowserRequest), EditMenu, new, 'new')
-
-
-The utility that is used to generate the menu into a TAL-friendly
-data-structure is ``getMenu()``::
-
-  getMenu(menuId, object, request)
-
-where ``menuId`` is the id originally specified for the menu. Let's look up the
-menu now:
-
-  >>> pprint(menu.getMenu('edit', Content(), TestRequest()))
-  [{'action': 'new.html',
-    'description': u'',
-    'extra': None,
-    'icon': None,
-    'selected': u'',
-    'submenu': None,
-    'title': 'New'},
-  {'action': 'redo.html',
-    'description': u'',
-    'extra': None,
-    'icon': '/@@/redo.png',
-    'selected': u'',
-    'submenu': None,
-    'title': 'Redo'},
-   {'action': 'undo.html',
-    'description': u'',
-    'extra': None,
-    'icon': None,
-    'selected': u'',
-    'submenu': None,
-    'title': 'Undo'},
-   {'action': u'',
-    'description': u'',
-    'extra': None,
-    'icon': None,
-    'selected': u'',
-    'submenu': [{'action': 'saveall.html',
-                 'description': u'',
-                 'extra': None,
-                 'icon': None,
-                 'selected': u'',
-                 'submenu': None,
-                 'title': 'Save all'},
-                {'action': 'saveas.html',
-                 'description': u'',
-                 'extra': None,
-                 'icon': None,
-                 'selected': u'',
-                 'submenu': None,
-                 'title': 'Save as'}],
-    'title': 'Save'}]
-
-
-Custom ``IBrowserMenu`` Implementations
----------------------------------------
-
-Until now we have only seen how to use the default menu implementation. Much
-of the above boilerplate was necessary just to support custom menus. But what
-could custom menus do? Sometimes menu items are dynamically generated based on
-a certain state of the object the menu is for. For example, you might want to
-show all items in a folder-like component. So first let's create this
-folder-like component:
-
-  >>> class Folderish(Content):
-  ...     names = ['README.txt', 'logo.png', 'script.py']
-
-Now we create a menu using the names to create a menu:
-
-  >>> from zope.app.publisher.interfaces.browser import IBrowserMenu
-
-  >>> class Items(object):
-  ...     zope.interface.implements(IBrowserMenu)
-  ...  
-  ...     def __init__(self, id, title=u'', description=u''):
-  ...         self.id = id
-  ...         self.title = title
-  ...         self.description = description
-  ...     
-  ...     def getMenuItems(self, object, request):
-  ...         return [{'title': name,
-  ...                  'description': None,
-  ...                  'action': name + '/manage',
-  ...                  'selected': u'',
-  ...                  'icon': None,
-  ...                  'extra': {},
-  ...                  'submenu': None}
-  ...                 for name in object.names]
-
-and register it:
-
-  >>> ztapi.provideUtility(IBrowserMenu,
-  ...                      Items('items', u'Items', u'Items Menu'),
-  ...                      'items')
-
-We can now get the menu items using the previously introduced API:
-
-  >>> pprint(menu.getMenu('items', Folderish(), TestRequest()))
-  [{'action': 'README.txt/manage',
-    'description': None,
-    'extra': {},
-    'icon': None,
-    'selected': u'',
-    'submenu': None,
-    'title': 'README.txt'},
-   {'action': 'logo.png/manage',
-    'description': None,
-    'extra': {},
-    'icon': None,
-    'selected': u'',
-    'submenu': None,
-    'title': 'logo.png'},
-   {'action': 'script.py/manage',
-    'description': None,
-    'extra': {},
-    'icon': None,
-    'selected': u'',
-    'submenu': None,
-    'title': 'script.py'}]
-
-
-``MenuItemFactory`` class
--------------------------
-
-As you have seen above already, we have used the menu item factory to generate
-adapter factories for menu items. The factory needs a particular
-``IBrowserMenuItem`` class to instantiate. Here is an example using a dummy
-menu item class:
-  
-  >>> class DummyBrowserMenuItem(object):
-  ...     "a dummy factory for menu items"
-  ...     def __init__(self, context, request):
-  ...         self.context = context
-  ...         self.request = request
-  
-To instantiate this class, pass the factory and the other arguments as keyword
-arguments (every key in the arguments should map to an attribute of the menu
-item class). We use dummy values for this example.
-  
-  >>> factory = menumeta.MenuItemFactory(
-  ...     DummyBrowserMenuItem, title='Title', description='Description', 
-  ...     icon='Icon', action='Action', filter='Filter', 
-  ...     permission='zope.Public', extra='Extra', order='Order', _for='For')
-  >>> factory.factory is DummyBrowserMenuItem
-  True
-  
-The "zope.Public" permission needs to be translated to ``CheckerPublic``.
-  
-  >>> from zope.security.checker import CheckerPublic
-  >>> factory.kwargs['permission'] is CheckerPublic
-  True
-  
-Call the factory with context and request to return the instance.  We continue
-to use dummy values.
-  
-  >>> item = factory('Context', 'Request')
-  
-The returned value should be an instance of the ``DummyBrowserMenuItem``, and
-have all of the values we initially set on the factory.
-  
-  >>> isinstance(item, DummyBrowserMenuItem)
-  True
-  >>> item.context
-  'Context'
-  >>> item.request
-  'Request'
-  >>> item.title
-  'Title'
-  >>> item.description
-  'Description'
-  >>> item.icon
-  'Icon'
-  >>> item.action
-  'Action'
-  >>> item.filter
-  'Filter'
-  >>> item.permission is CheckerPublic
-  True
-  >>> item.extra
-  'Extra'
-  >>> item.order
-  'Order'
-  >>> item._for
-  'For'
-  
-If you pass a permission other than ``zope.Public`` to the
-``MenuItemFactory``, it should pass through unmodified.
-  
-  >>> factory = menumeta.MenuItemFactory(
-  ...     DummyBrowserMenuItem, title='Title', description='Description', 
-  ...     icon='Icon', action='Action', filter='Filter', 
-  ...     permission='another.Permission', extra='Extra', order='Order', 
-  ...     _for='For_')
-  >>> factory.kwargs['permission']
-  'another.Permission'
-
-
-Directive Handlers
-------------------
-
-``menu`` Directive Handler
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Provides a new menu (item type).
-
-  >>> class Context(object):
-  ...     info = u'doc'
-  ...     def __init__(self): 
-  ...         self.actions = []
-  ...
-  ...     def action(self, **kw): 
-  ...         self.actions.append(kw)
-
-Possibility 1: The Old Way
-++++++++++++++++++++++++++
-  
-  >>> context = Context()
-  >>> menumeta.menuDirective(context, u'menu1', title=u'Menu 1')
-  >>> iface = context.actions[0]['args'][1]
-  >>> iface.getName()
-  u'menu1'
-
-  >>> import sys
-  >>> hasattr(sys.modules['zope.app.menus'], 'menu1')
-  True
-
-  >>> del sys.modules['zope.app.menus'].menu1
-
-Possibility 2: Just specify an interface
-++++++++++++++++++++++++++++++++++++++++
-
-  >>> class menu1(zope.interface.Interface):
-  ...     pass
-
-  >>> context = Context()
-  >>> menumeta.menuDirective(context, interface=menu1)
-  >>> context.actions[0]['args'][1] is menu1
-  True
-
-Possibility 3: Specify an interface and an id
-+++++++++++++++++++++++++++++++++++++++++++++
-
-  >>> context = Context()
-  >>> menumeta.menuDirective(context, id='menu1', interface=menu1)
-
-  >>> pprint([action['discriminator'] for action in context.actions])
-  [('browser', 'MenuItemType', '__builtin__.menu1'),
-   ('interface', '__builtin__.menu1'),
-   ('browser', 'MenuItemType', 'menu1'),
-   ('utility',
-    <InterfaceClass zope.app.publisher.interfaces.browser.IBrowserMenu>,
-    'menu1'),
-   None]
-   
-Here are some disallowed configurations.
-
-  >>> context = Context()
-  >>> menumeta.menuDirective(context)
-  Traceback (most recent call last):
-  ...
-  ConfigurationError: You must specify the 'id' or 'interface' attribute.
-
-  >>> menumeta.menuDirective(context, title='Menu 1')
-  Traceback (most recent call last):
-  ...
-  ConfigurationError: You must specify the 'id' or 'interface' attribute.
-
-
-``menuItems`` Directive Handler
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Register several menu items for a particular menu.
-
-  >>> class TestMenuItemType(zope.interface.Interface):
-  ...     pass
-
-  >>> class ITest(zope.interface.Interface): 
-  ...     pass
-
-  >>> context = Context()
-  >>> items = menumeta.menuItemsDirective(context, TestMenuItemType, ITest)
-  >>> context.actions
-  []
-  >>> items.menuItem(context, u'view.html', 'View')
-  >>> items.subMenuItem(context, SaveOptions, 'Save')
-
-  >>> disc = [action['discriminator'] for action in context.actions]
-  >>> disc.sort()
-  >>> pprint(disc[-2:])
-  [('adapter',
-    (<InterfaceClass __builtin__.ITest>,
-     <InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
-    <InterfaceClass __builtin__.TestMenuItemType>,
-    'Save'),
-   ('adapter',
-    (<InterfaceClass __builtin__.ITest>,
-     <InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
-    <InterfaceClass __builtin__.TestMenuItemType>,
-    'View')]
-
-Custom menu item classes
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-We can register menu items and sub menu items with custom classes instead
-of ones used by default. For that, we need to create an implementation
-of IBrowserMenuItem or IBrowserSubMenuItem.
-
-  >>> context = Context()
-  >>> items = menumeta.menuItemsDirective(context, TestMenuItemType, ITest)
-  >>> context.actions
-  []
-
-Let's create a custom menu item class that inherits standard BrowserMenuItem:
-
-  >>> class MyMenuItem(menu.BrowserMenuItem):
-  ...    pass
-
-  >>> items.menuItem(context, u'view.html', 'View', item_class=MyMenuItem)
-
-Also create a custom sub menu item class inheriting standard BrowserSubMenuItem:
-
-  >>> class MySubMenuItem(menu.BrowserSubMenuItem):
-  ...    pass
-
-  >>> items.subMenuItem(context, SaveOptions, 'Save', item_class=MySubMenuItem)
-
-  >>> actions = sorted(context.actions, key=lambda a:a['discriminator'])
-  >>> factories = [action['args'][1] for action in actions][-2:]
-
-  >>> factories[0].factory is MySubMenuItem
-  True
-
-  >>> factories[1].factory is MyMenuItem
-  True
-
-These directive will fail if you provide an item_class that does not
-implement IBrowserMenuItem/IBrowserSubMenuItem:
-
-  >>> items.menuItem(context, u'fail', 'Failed', item_class=object)
-  Traceback (most recent call last):
-  ...
-  ValueError: Item class (<type 'object'>) must implement IBrowserMenuItem
-
-  >>> items.subMenuItem(context, SaveOptions, 'Failed', item_class=object)
-  Traceback (most recent call last):
-  ...
-  ValueError: Item class (<type 'object'>) must implement IBrowserSubMenuItem
-
-``ManagementViewSelector``
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Test the action (redirect url) of the first menu item and ensure that we don't
-redirect to the parent before we reach the item if we use actions like: '../'
-'javascript:popup()' or '++namespace++'.
-
-First setup the 'zmi_views' menu.
-
-  >>> class ZMIViews(zope.interface.Interface):
-  ...     """This is the zmi_views menu."""
-  >>> zope.interface.directlyProvides(ZMIViews, IMenuItemType)
-  >>> ztapi.provideUtility(IMenuItemType, ZMIViews, 'zmi_views')
-  >>> from zope.app.publisher.interfaces.browser import IBrowserMenu
-  >>> ztapi.provideUtility(
-  ...     IBrowserMenu, menu.BrowserMenu('zmi_views', u'ZMIViews', 
-  ...     u'ZMI Views'), 'zmi_views')
-
-Register some 'zmi_views' menu items.
-
-  >>> first = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="First", 
-  ...     action="../")
-  >>> ztapi.provideAdapter((IContent, IBrowserRequest), ZMIViews, first, 
-  ...    'first')
-
-  >>> second = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="Second", 
-  ...     action="second.html")
-  >>> ztapi.provideAdapter((IContent, IBrowserRequest), ZMIViews, second, 
-  ...    'second')
-
-Now create a new content object.
-
-  >>> content = Content()
-  >>> request = TestRequest(SERVER_URL='http://127.0.0.1/',
-  ...     PATH_INFO='/')
-
-Test the actions. Remember that this action get redirected before we traverse 
-to the content. This means actions like ``../`` will make it impossible to 
-access the view because the ``../`` will redirect us before we traverse.
-
-  >>> menus = menu.getMenu('zmi_views', content, request)
-  >>> [menu['action'] for menu in menus]
-  ['../', 'second.html']
-
-Now call the ManagementViewSelector view and we get a empty string as result.
-
-  >>> from zope.app.publisher.browser.managementviewselector import \
-  ...     ManagementViewSelector
-  >>> view = ManagementViewSelector(content, request)
-  >>> view()
-  u''
-
-Now check the more interesting redirect in the request. The redirect location
-is not like excpected '../'. We get '.' as the redirect location. This is 
-important otherwise we get redirected to the parent if we call the
-first menu item with actions like '../parentview.html' instead of traverse
-to the item.
-
-  >>> request.response.getHeader('Location')
-  '.'

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,294 +15,13 @@
 
 $Id$
 """
-from zope.browser.interfaces import IAdding
-from zope.component import getGlobalSiteManager
-from zope.component import getUtility
-from zope.component.interface import provideInterface
-from zope.component.zcml import adapter
-from zope.component.zcml import proxify
-from zope.component.zcml import utility
-from zope.configuration.exceptions import ConfigurationError
-from zope.interface.interface import InterfaceClass
-from zope.interface import Interface
-from zope.pagetemplate.engine import Engine
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.security.checker import InterfaceChecker, CheckerPublic
-from zope.security.metaconfigure import ClassDirective
-
-from zope.app.publisher.browser.menu import BrowserMenu
-from zope.app.publisher.browser.menu import BrowserMenuItem, BrowserSubMenuItem
-from zope.app.publisher.interfaces.browser import IBrowserMenu
-from zope.app.publisher.interfaces.browser import IBrowserMenuItem
-from zope.app.publisher.interfaces.browser import IBrowserSubMenuItem
-from zope.app.publisher.interfaces.browser import IMenuItemType
-from zope.app.publisher.interfaces.browser import AddMenu
-
-# Create special modules that contain all menu item types
-from types import ModuleType as module
-import sys
-menus = module('menus')
-sys.modules['zope.app.menus'] = menus
-
-
-_order_counter = {}
-
-
-def menuDirective(_context, id=None, class_=BrowserMenu, interface=None,
-                  title=u'', description=u''):
-    """Registers a new browser menu."""
-    if id is None and interface is None:
-        raise ConfigurationError(
-            "You must specify the 'id' or 'interface' attribute.")
-
-    if interface is None:
-        if id in dir(menus):
-            # reuse existing interfaces for the id, without this we are not
-            # able to override menus.
-            interface = getattr(menus, id)
-        else:
-            interface = InterfaceClass(id, (),
-                                       __doc__='Menu Item Type: %s' %id,
-                                       __module__='zope.app.menus')
-            # Add the menu item type to the `menus` module.
-            # Note: We have to do this immediately, so that directives using the
-            # MenuField can find the menu item type.
-            setattr(menus, id, interface)
-        path = 'zope.app.menus.' + id
-    else:
-        path = interface.__module__ + '.' + interface.getName()
-
-        # If an id was specified, make this menu available under this id.
-        # Note that the menu will be still available under its path, since it
-        # is an adapter, and the `MenuField` can resolve paths as well.
-        if id is None:
-            id = path
-        else:
-            # Make the interface available in the `zope.app.menus` module, so
-            # that other directives can find the interface under the name
-            # before the CA is setup.
-            _context.action(
-                discriminator = ('browser', 'MenuItemType', path),
-                callable = provideInterface,
-                args = (path, interface, IMenuItemType, _context.info)
-                )
-            setattr(menus, id, interface)
-
-    # Register the layer interface as an interface
-    _context.action(
-        discriminator = ('interface', path),
-        callable = provideInterface,
-        args = (path, interface),
-        kw = {'info': _context.info}
-        )
-
-    # Register the menu item type interface as an IMenuItemType
-    _context.action(
-        discriminator = ('browser', 'MenuItemType', id),
-        callable = provideInterface,
-        args = (id, interface, IMenuItemType, _context.info)
-        )
-
-    # Register the menu as a utility
-    utility(_context, IBrowserMenu, class_(id, title, description), name=id)
-
-
-def menuItemDirective(_context, menu, for_,
-                      action, title, description=u'', icon=None, filter=None,
-                      permission=None, layer=IDefaultBrowserLayer, extra=None,
-                      order=0, item_class=None):
-    """Register a single menu item."""
-    return menuItemsDirective(_context, menu, for_, layer).menuItem(
-        _context, action, title, description, icon, filter,
-        permission, extra, order, item_class)
-
-
-def subMenuItemDirective(_context, menu, for_, title, submenu,
-                         action=u'', description=u'', icon=None, filter=None,
-                         permission=None, layer=IDefaultBrowserLayer,
-                         extra=None, order=0, item_class=None):
-    """Register a single sub-menu menu item."""
-    return menuItemsDirective(_context, menu, for_, layer).subMenuItem(
-        _context, submenu, title, description, action, icon, filter,
-        permission, extra, order, item_class)
-
-
-class MenuItemFactory(object):
-    """generic factory for menu items."""
-
-    def __init__(self, factory, **kwargs):
-        self.factory = factory
-        if 'permission' in kwargs and kwargs['permission'] == 'zope.Public':
-            kwargs['permission'] = CheckerPublic
-        self.kwargs = kwargs
-
-    def __call__(self, context, request):
-        item = self.factory(context, request)
-
-        for key, value in self.kwargs.items():
-            setattr(item, key, value)
-
-        if item.permission is not None:
-            checker = InterfaceChecker(IBrowserMenuItem, item.permission)
-            item = proxify(item, checker)
-
-        return item
-
-
-class menuItemsDirective(object):
-    """Register several menu items for a particular menu."""
-
-    menuItemClass = BrowserMenuItem
-    subMenuItemClass = BrowserSubMenuItem
-
-    def __init__(self, _context, menu, for_, layer=IDefaultBrowserLayer,
-                 permission=None):
-        self.for_ = for_
-        self.menuItemType = menu
-        self.layer = layer
-        self.permission = permission
-
-    def menuItem(self, _context, action, title, description=u'',
-                 icon=None, filter=None, permission=None, extra=None,
-                 order=0, item_class=None):
-
-        if filter is not None:
-            filter = Engine.compile(filter)
-
-        if permission is None:
-            permission = self.permission
-
-        if order == 0:
-            order = _order_counter.get(self.for_, 1)
-            _order_counter[self.for_] = order + 1
-
-        if item_class is None:
-            item_class = self.menuItemClass
-
-        if not IBrowserMenuItem.implementedBy(item_class):
-            raise ValueError("Item class (%s) must implement IBrowserMenuItem" % item_class)
-
-        factory = MenuItemFactory(
-            item_class,
-            title=title, description=description, icon=icon, action=action,
-            filter=filter, permission=permission, extra=extra, order=order,
-            _for=self.for_)
-        adapter(_context, (factory,), self.menuItemType,
-                (self.for_, self.layer), name=title)
-
-    def subMenuItem(self, _context, submenu, title, description=u'',
-                    action=u'', icon=None, filter=None, permission=None,
-                    extra=None, order=0, item_class=None):
-
-        if filter is not None:
-            filter = Engine.compile(filter)
-
-        if permission is None:
-            permission = self.permission
-
-        if order == 0:
-            order = _order_counter.get(self.for_, 1)
-            _order_counter[self.for_] = order + 1
-
-        if item_class is None:
-            item_class = self.subMenuItemClass
-
-        if not IBrowserSubMenuItem.implementedBy(item_class):
-            raise ValueError("Item class (%s) must implement IBrowserSubMenuItem" % item_class)
-
-        factory = MenuItemFactory(
-            item_class,
-            title=title, description=description, icon=icon, action=action,
-            filter=filter, permission=permission, extra=extra, order=order,
-            _for=self.for_, submenuId=submenu)
-        adapter(_context, (factory,), self.menuItemType,
-                (self.for_, self.layer), name=title)
-
-    def __call__(self, _context):
-        # Nothing to do.
-        pass
-
-def _checkViewFor(for_=None, layer=None, view_name=None):
-    """Check if there is a view of that name registered for IAdding
-    and IBrowserRequest. If not raise a ConfigurationError
-
-    It will raise a ConfigurationError if :
-        o view=""
-        o if view_name is not registred
-    """
-
-    if view_name is None:
-        raise ConfigurationError(
-            "Within a addMenuItem directive the view attribut"
-            " is optional but can\'t be empty"
-            )
-
-    gsm = getGlobalSiteManager()
-    if gsm.adapters.lookup((for_, layer),
-                           Interface, view_name) is None:
-        raise ConfigurationError(
-            "view name %s not found " %view_name
-            )
-
-def addMenuItem(_context, title, description='', menu=None, for_=None,
-                class_=None, factory=None, view=None, icon=None, filter=None,
-                permission=None, layer=IDefaultBrowserLayer, extra=None,
-                order=0, item_class=None):
-    """Create an add menu item for a given class or factory
-
-    As a convenience, a class can be provided, in which case, a
-    factory is automatically defined based on the class.  In this
-    case, the factory id is based on the class name.
-
-    """
-
-    if for_ is not None:
-        _context.action(
-            discriminator = None,
-            callable = provideInterface,
-            args = ('', for_)
-            )
-        forname = 'For' + for_.getName()
-    else:
-        for_ = IAdding
-        forname = ''
-
-    if menu is not None:
-        if isinstance(menu, (str, unicode)):
-            menu = getUtility(IMenuItemType, menu)
-            if menu is None:
-                raise ValueError("Missing menu id '%s'" % menu)
-
-    if class_ is None:
-        if factory is None:
-            raise ValueError("Must specify either class or factory")
-    else:
-        if factory is not None:
-            raise ValueError("Can't specify both class and factory")
-        if permission is None:
-            raise ValueError(
-                "A permission must be specified when a class is used")
-        factory = "BrowserAdd%s__%s.%s" % (
-            forname, class_.__module__, class_.__name__)
-        ClassDirective(_context, class_).factory(_context, id=factory)
-
-    extra = {'factory': factory}
-
-    if view:
-        action = view
-        # This action will check if the view exists
-        _context.action(
-            discriminator = None,
-            callable = _checkViewFor,
-            args = (for_, layer, view),
-            order=999999
-            )
-    else:
-        action = factory
-
-    if menu == None:
-        menu = AddMenu
-
-    return menuItemsDirective(_context, menu, for_, layer=layer).menuItem(
-        _context, action, title, description, icon, filter,
-        permission, extra, order, item_class)
+# BBB imports
+from zope.browsermenu.metaconfigure import (
+    menuDirective,
+    menuItemDirective,
+    subMenuItemDirective,
+    MenuItemFactory,
+    menuItemsDirective,
+    _checkViewFor,
+    addMenuItem,
+)

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/meta.zcml
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/meta.zcml	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/meta.zcml	2009-08-27 15:12:51 UTC (rev 103291)
@@ -1,146 +1,8 @@
-<configure
-    xmlns="http://namespaces.zope.org/zope"
-    xmlns:meta="http://namespaces.zope.org/meta"
-    xmlns:zcml="http://namespaces.zope.org/zcml">
+<configure xmlns="http://namespaces.zope.org/zope">
 
-  <meta:directives namespace="http://namespaces.zope.org/browser">
+  <include package="zope.publisher" file="meta.zcml" />
+  <include package="zope.browserresource" file="meta.zcml" />
+  <include package="zope.browsermenu" file="meta.zcml" />
+  <include package="zope.browserpage" file="meta.zcml" />
 
-    <!-- browser menus -->
-
-    <meta:directive
-        name="menu"
-        schema=".metadirectives.IMenuDirective"
-        handler=".menumeta.menuDirective"
-        />
-
-    <meta:complexDirective
-        name="menuItems"
-        schema=".metadirectives.IMenuItemsDirective"
-        handler=".menumeta.menuItemsDirective"
-        >
-
-      <meta:subdirective
-          name="menuItem"
-          schema=".metadirectives.IMenuItemSubdirective"
-          />
-
-      <meta:subdirective
-          name="subMenuItem"
-          schema=".metadirectives.ISubMenuItemSubdirective"
-          />
-
-    </meta:complexDirective>
-
-    <meta:directive
-        name="menuItem"
-        schema=".metadirectives.IMenuItemDirective"
-        handler=".menumeta.menuItemDirective"
-        />
-
-    <meta:directive
-        name="subMenuItem"
-        schema=".metadirectives.ISubMenuItemDirective"
-        handler=".menumeta.subMenuItemDirective"
-        />
-
-    <meta:directive
-        name="addMenuItem"
-        schema=".metadirectives.IAddMenuItemDirective"
-        handler=".menumeta.addMenuItem"
-        />
-
-
-    <!-- browser views -->
-
-    <meta:complexDirective
-        name="view"
-        schema=".metadirectives.IViewDirective"
-        handler=".viewmeta.view"
-        >
-
-      <meta:subdirective
-          name="page"
-          schema=".metadirectives.IViewPageSubdirective"
-          />
-
-      <meta:subdirective
-          name="defaultPage"
-          schema=".metadirectives.IViewDefaultPageSubdirective"
-          />
-
-    </meta:complexDirective>
-
-    <meta:directive
-        name="defaultView"
-        schema=".metadirectives.IDefaultViewDirective"
-        handler=".metaconfigure.defaultView"
-        />
-
-
-    <!-- browser pages -->
-
-    <meta:directive
-        name="page"
-        schema=".metadirectives.IPageDirective"
-        handler=".viewmeta.page"
-        />
-
-    <meta:complexDirective
-        name="pages"
-        schema=".metadirectives.IPagesDirective"
-        handler=".viewmeta.pages"
-        >
-
-      <meta:subdirective
-          name="page"
-          schema=".metadirectives.IPagesPageSubdirective"
-          />
-
-    </meta:complexDirective>
-
-
-    <!-- browser resources -->
-
-    <meta:directive
-        name="resource"
-        schema=".metadirectives.IResourceDirective"
-        handler=".metaconfigure.resource"
-        />
-
-    <meta:directive
-        name="resourceDirectory"
-        schema=".metadirectives.IResourceDirectoryDirective"
-        handler=".metaconfigure.resourceDirectory"
-        />
-
-    <meta:complexDirective
-        name="i18n-resource"
-        schema=".metadirectives.II18nResourceDirective"
-        handler=".metaconfigure.I18nResource"
-        >
-
-      <meta:subdirective
-          name="translation"
-          schema=".metadirectives.II18nResourceTranslationSubdirective"
-          />
-
-    </meta:complexDirective>
-
-
-    <!-- misc. directives -->
-
-    <meta:directive
-        name="defaultSkin"
-        schema=".metadirectives.IDefaultSkinDirective"
-        handler=".metaconfigure.defaultSkin"
-        />
-
-    <meta:directive
-        name="icon"
-        schema=".metadirectives.IIconDirective"
-        handler=".icon.IconDirective"
-        />
-
-  </meta:directives>
-
 </configure>

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/metaconfigure.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/metaconfigure.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/metaconfigure.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,66 +15,9 @@
 
 $Id$
 """
-__docformat__ = 'restructuredtext'
-
-import warnings
-from zope import component
-from zope.component.interface import provideInterface
-from zope.component.zcml import handler
-from zope.publisher.interfaces import IDefaultViewName
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.publisher.interfaces.browser import IBrowserSkinType
-from zope.publisher.interfaces.browser import IDefaultSkin
-
-# referred to through ZCML
-from zope.app.publisher.browser.resourcemeta import resource
-from zope.app.publisher.browser.resourcemeta import resourceDirectory
-from zope.app.publisher.browser.i18nresourcemeta import I18nResource
-from zope.app.publisher.browser.viewmeta import view
-
-
-def setDefaultSkin(name, info=''):
-    """Set the default skin.
-
-    >>> from zope.interface import directlyProvides
-    >>> from zope.app.testing import ztapi
-
-    >>> class Skin1: pass
-    >>> directlyProvides(Skin1, IBrowserSkinType)
-
-    >>> ztapi.provideUtility(IBrowserSkinType, Skin1, 'Skin1')
-    >>> setDefaultSkin('Skin1')
-    >>> adapters = component.getSiteManager().adapters
-
-	Lookup the default skin for a request that has the
-
-    >>> adapters.lookup((IBrowserRequest,), IDefaultSkin, '') is Skin1
-    True
-    """
-    skin = component.getUtility(IBrowserSkinType, name)
-    handler('registerAdapter',
-            skin, (IBrowserRequest,), IDefaultSkin, '', info),
-
-def defaultSkin(_context, name):
-
-    _context.action(
-        discriminator = 'defaultSkin',
-        callable = setDefaultSkin,
-        args = (name, _context.info)
-        )
-
-def defaultView(_context, name, for_=None, layer=IBrowserRequest):
-
-    _context.action(
-        discriminator = ('defaultViewName', for_, layer, name),
-        callable = handler,
-        args = ('registerAdapter',
-                name, (for_, layer), IDefaultViewName, '', _context.info)
-        )
-
-    if for_ is not None:
-        _context.action(
-            discriminator = None,
-            callable = provideInterface,
-            args = ('', for_)
-            )
+# BBB imports
+from zope.browserresource.metaconfigure import resource
+from zope.browserresource.metaconfigure import resourceDirectory
+from zope.browserresource.metaconfigure import I18nResource
+from zope.browserpage.metaconfigure import view
+from zope.publisher.zcml import setDefaultSkin, defaultSkin, defaultView

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -17,643 +17,31 @@
 
 $Id$
 """
-from zope.interface import Interface
-from zope.configuration.fields import GlobalObject, GlobalInterface
-from zope.configuration.fields import Tokens, Path, PythonIdentifier, MessageID
-from zope.schema import TextLine, Id, Int, Bool
-from zope.security.zcml import Permission
-
-from zope.component.zcml import IBasicViewInformation
-from zope.app.publisher.browser.fields import MenuField
-
-#
-# browser views
-#
-
-class IPagesDirective(IBasicViewInformation):
-    """
-    Define multiple pages without repeating all of the parameters.
-
-    The pages directive allows multiple page views to be defined
-    without repeating the 'for', 'permission', 'class', 'layer',
-    'allowed_attributes', and 'allowed_interface' attributes.
-    """
-
-    for_ = GlobalObject(
-        title=u"The interface or class this view is for.",
-        required=False
-        )
-
-    permission = Permission(
-        title=u"Permission",
-        description=u"The permission needed to use the view.",
-        required=True
-        )
-
-class IViewDirective(IPagesDirective):
-    """
-    The view directive defines a view that has subpages.
-
-    The pages provided by the defined view are accessed by first
-    traversing to the view name and then traversing to the page name.
-    """
-
-    for_ = GlobalInterface(
-        title=u"The interface this view is for.",
-        required=False
-        )
-
-    name = TextLine(
-        title=u"The name of the view.",
-        description=u"The name shows up in URLs/paths. For example 'foo'.",
-        required=False,
-        default=u'',
-        )
-
-    menu = MenuField(
-        title=u"The browser menu to include the page (view) in.",
-        description=u"""
-          Many views are included in menus. It's convenient to name
-          the menu in the page directive, rather than having to give a
-          separate menuItem directive.  'zmi_views' is the menu most often
-          used in the Zope management interface.
-          </description>
-          """,
-        required=False
-        )
-
-    title = MessageID(
-        title=u"The browser menu label for the page (view)",
-        description=u"""
-          This attribute must be supplied if a menu attribute is
-          supplied.
-          """,
-        required=False
-        )
-
-    provides = GlobalInterface(
-        title=u"The interface this view provides.",
-        description=u"""
-        A view can provide an interface.  This would be used for
-        views that support other views.""",
-        required=False,
-        default=Interface,
-        )
-
-class IViewPageSubdirective(Interface):
-    """
-    Subdirective to IViewDirective.
-    """
-
-    name = TextLine(
-        title=u"The name of the page (view)",
-        description=u"""
-        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.""",
-        required=True
-        )
-
-    attribute = PythonIdentifier(
-        title=u"The name of the view attribute implementing the page.",
-        description=u"""
-        This refers to the attribute (method) on the view that is
-        implementing a specific sub page.""",
-        required=False
-        )
-
-    template = Path(
-        title=u"The name of a template that implements the page.",
-        description=u"""
-        Refers to a file containing a page template (should end in
-        extension '.pt' or '.html').""",
-        required=False
-        )
-
-class IViewDefaultPageSubdirective(Interface):
-    """
-    Subdirective to IViewDirective.
-    """
-
-    name = TextLine(
-        title=u"The name of the page that is the default.",
-        description=u"""
-        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.""",
-        required=True
-        )
-
-class IDefaultViewDirective(Interface):
-    """
-    The name of the view that should be the default.
-
-    This name refers to view that should be the
-    view used by default (if no view name is supplied
-    explicitly).
-    """
-
-    name = TextLine(
-        title=u"The name of the view that should be the default.",
-        description=u"""
-        This name refers to view that should be the view used by
-        default (if no view name is supplied explicitly).""",
-        required=True
-        )
-
-    for_ = GlobalObject(
-        title=u"The interface this view is the default for.",
-        description=u"""Specifies the interface for which the view is
-        registered. All objects implementing this interface can make use of
-        this view. If this attribute is not specified, the view is available
-        for all objects.""",
-        required=False
-        )
-
-    layer = GlobalInterface(
-        title=u"The layer the default view is declared for",
-        description=u"The default layer for which the default view is "
-                    u"applicable. By default it is applied to all layers.",
-        required=False
-        )
-
-#
-# browser pages
-#
-
-class IPagesPageSubdirective(IViewPageSubdirective):
-    """
-    Subdirective to IPagesDirective
-    """
-
-    menu = MenuField(
-        title=u"The browser menu to include the page (view) in.",
-        description=u"""
-        Many views are included in menus. It's convenient to name the
-        menu in the page directive, rather than having to give a
-        separate menuItem directive.""",
-        required=False
-        )
-
-    title = MessageID(
-        title=u"The browser menu label for the page (view)",
-        description=u"""
-        This attribute must be supplied if a menu attribute is
-        supplied.""",
-        required=False
-        )
-
-class IPageDirective(IPagesDirective, IPagesPageSubdirective):
-    """
-    The page directive is used to create views that provide a single
-    url or page.
-
-    The page directive creates a new view class from a given template
-    and/or class and registers it.
-    """
-
-
-#
-# browser resources
-#
-
-class IBasicResourceInformation(Interface):
-    """
-    This is the basic information for all browser resources.
-    """
-
-    layer = GlobalInterface(
-        title=u"The layer the resource should be found in",
-        description=u"""
-        For information on layers, see the documentation for the skin
-        directive. Defaults to "default".""",
-        required=False
-        )
-
-    permission = Permission(
-        title=u"The permission needed to access the resource.",
-        description=u"""
-        If a permission isn't specified, the resource will always be
-        accessible.""",
-        required=False
-        )
-
-class IResourceDirective(IBasicResourceInformation):
-    """
-    Defines a browser resource
-    """
-
-    name = TextLine(
-        title=u"The name of the resource",
-        description=u"""
-        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 site manager.
-
-        We make resource urls site-relative (as opposed to
-        content-relative) so as not to defeat caches.""",
-        required=True
-        )
-
-    factory = GlobalObject(
-        title=u"Resource Factory",
-        description=u"The factory used to create the resource. The factory "
-                    u"should only expect to get the request passed when "
-                    u"called.",
-        required=False
-        )
-
-    file = Path(
-        title=u"File",
-        description=u"The file containing the resource data.",
-        required=False
-        )
-
-    image = Path(
-        title=u"Image",
-        description=u"""
-        If the image attribute is used, then an image resource, rather
-        than a file resource will be created.""",
-        required=False
-        )
-
-    template = Path(
-        title=u"Template",
-        description=u"""
-        If the template attribute is used, then a page template resource,
-        rather than a file resource will be created.""",
-        required=False
-        )
-
-class II18nResourceDirective(IBasicResourceInformation):
-    """
-    Defines an i18n'd resource.
-    """
-
-    name = TextLine(
-        title=u"The name of the resource",
-        description=u"""
-        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 site manager.
-
-        We make resource urls site-relative (as opposed to
-        content-relative) so as not to defeat caches.""",
-        required=True
-        )
-
-    defaultLanguage = TextLine(
-        title=u"Default language",
-        description=u"Defines the default language",
-        required=False
-        )
-
-class II18nResourceTranslationSubdirective(IBasicResourceInformation):
-    """
-    Subdirective to II18nResourceDirective.
-    """
-
-    language = TextLine(
-        title=u"Language",
-        description=u"Language of this translation of the resource",
-        required=True
-        )
-
-    file = Path(
-        title=u"File",
-        description=u"The file containing the resource data.",
-        required=False
-        )
-
-    image = Path(
-        title=u"Image",
-        description=u"""
-        If the image attribute is used, then an image resource, rather
-        than a file resource will be created.""",
-        required=False
-        )
-
-class IResourceDirectoryDirective(IBasicResourceInformation):
-    """
-    Defines a directory containing browser resource
-    """
-
-    name = TextLine(
-        title=u"The name of the resource",
-        description=u"""
-        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 site manager.
-
-        We make resource urls site-relative (as opposed to
-        content-relative) so as not to defeat caches.""",
-        required=True
-        )
-
-    directory = Path(
-        title=u"Directory",
-        description=u"The directory containing the resource data.",
-        required=True
-        )
-
-#
-# browser menus
-#
-
-class IMenuDirective(Interface):
-    """Define a browser menu"""
-
-    id = TextLine(
-        title=u"The name of the menu.",
-        description=u"This is, effectively, an id.",
-        required=False
-        )
-
-    title = MessageID(
-        title=u"Title",
-        description=u"A descriptive title for documentation purposes",
-        required=False
-        )
-    
-    description = MessageID(
-        title=u"Description",
-        description=u"A description title of the menu.",
-        required=False
-        )
-
-    class_ = GlobalObject(
-        title=u"Menu Class",
-        description=u"The menu class used to generate the menu.",
-        required=False
-        )
-
-    interface = GlobalInterface(
-        title=u"The menu's interface.",
-        required=False
-        )
-    
-
-class IMenuItemsDirective(Interface):
-    """
-    Define a group of browser menu items
-
-    This directive is useful when many menu items are defined for the
-    same interface and menu.
-    """
-
-    menu = MenuField(
-        title=u"Menu name",
-        description=u"The (name of the) menu the items are defined for",
-        required=True,
-        )
-
-    for_ = GlobalObject(
-        title=u"Interface",
-        description=u"The interface the menu items are defined for",
-        required=True
-        )
-
-    layer = GlobalInterface(
-        title=u"Layer",
-        description=u"The Layer for which the item is declared.",
-        required=False
-        )
-
-    permission = Permission(
-        title=u"The permission needed access the item",
-        description=u"""
-        This can usually be inferred by the system, however, doing so
-        may be expensive. When displaying a menu, the system tries to
-        traverse to the URLs given in each action to determine whether
-        the url is accessible to the current user. This can be
-        avoided if the permission is given explicitly.""",
-        required=False
-        )
-
-
-class IMenuItem(Interface):
-    """Common menu item configuration
-    """
-
-    title = MessageID(
-        title=u"Title",
-        description=u"The text to be displayed for the menu item",
-        required=True
-        )
-
-    description = MessageID(
-        title=u"A longer explanation of the menu item",
-        description=u"""
-        A UI may display this with the item or display it when the
-        user requests more assistance.""",
-        required=False
-        )
-
-    icon = TextLine(
-        title=u"Icon Path",
-        description=u"Path to the icon resource representing this menu item.",
-        required=False
-        )
-
-    permission = Permission(
-        title=u"The permission needed access the item",
-        description=u"""
-        This can usually be inferred by the system, however, doing so
-        may be expensive. When displaying a menu, the system tries to
-        traverse to the URLs given in each action to determine whether
-        the url is accessible to the current user. This can be
-        avoided if the permission is given explicitly.""",
-        required=False
-        )
-
-    filter = TextLine(
-        title=u"A condition for displaying the menu item",
-        description=u"""
-        The condition is given as a TALES expression. The expression
-        has access to the variables:
-
-        context -- The object the menu is being displayed for
-
-        request -- The browser request
-
-        nothing -- None
-
-        The menu item will not be displayed if there is a filter and
-        the filter evaluates to a false value.""",
-        required=False
-        )
-
-    order = Int(
-        title=u"Order",
-        description=u"A relative position of the menu item in the menu.",
-        required=False,
-        default=0
-        )
-
-    item_class = GlobalObject(
-        title=u"Menu item class",
-        description=u"""
-        A class to be used as a factory for creating menu item""",
-        required=False
-        )
-
-class IMenuItemSubdirective(IMenuItem):
-    """Define a menu item within a group of menu items"""
-
-    action = TextLine(
-        title=u"The relative url to use if the item is selected",
-        description=u"""
-        The url is relative to the object the menu is being displayed
-        for.""",
-        required=True
-        )
-
-class IMenuItemDirective(IMenuItemsDirective, IMenuItemSubdirective):
-    """Define one menu item"""
-
-class ISubMenuItemSubdirective(IMenuItem):
-    """Define a menu item that represents a a sub menu.
-
-    For a sub-menu menu item, the action is optional, this the item itself
-    might not represent a destination, but just an entry point to the sub menu. 
-    """
-
-    action = TextLine(
-        title=u"The relative url to use if the item is selected",
-        description=u"""
-        The url is relative to the object the menu is being displayed
-        for.""",
-        required=False
-        )
-
-    submenu = TextLine(
-        title=u"Sub-Menu Id",
-        description=u"The menu that will be used to provide the sub-entries.",
-        required=True,
-        )
-    
-class ISubMenuItemDirective(IMenuItemsDirective, ISubMenuItemSubdirective):
-    """Define one menu item"""
-
-class IAddMenuItemDirective(IMenuItem):
-    """Define an add-menu item"""
-
-    for_ = GlobalInterface(
-        title=u"Interface",
-        description=u"The interface the menu items are defined for",
-        required=False
-        )
-
-    class_ = GlobalObject(
-        title=u"Class",
-        description=u"""
-        A class to be used as a factory for creating new objects""",
-        required=False
-        )
-
-    factory = Id(
-        title=u"Factory",
-        description=u"A factory id for creating new objects",
-        required = False,
-        )
-
-    view = TextLine(
-        title=u"Custom view name",
-        description=u"The name of a custom add view",
-        required = False,
-        )
-
-    menu = MenuField(
-        title=u"Menu name",
-        description=u"The (name of the) menu the items are defined for",
-        required=False,
-        )
-
-    layer = GlobalInterface(
-        title=u"The layer the custom view is declared for",
-        description=u"The default layer for which the custom view is "
-                    u"applicable. By default it is applied to all layers.",
-        required=False
-        )
-
-#
-# misc. directives
-#
-
-class IDefaultSkinDirective(Interface):
-    """Sets the default browser skin
-    """
-
-    name = TextLine(
-        title=u"Default skin name",
-        description=u"Default skin name",
-        required=True
-        )
-
-
-class IIconDirective(Interface):
-    """
-    Define an icon for an interface
-    """
-
-    name = TextLine(
-        title=u"The name of the icon.",
-        description=u"The name shows up in URLs/paths. For example 'foo'.",
-        required=True
-        )
-
-    for_ = GlobalInterface(
-        title=u"The interface this icon is for.",
-        description=u"""
-        The icon will be for all objects that implement this
-        interface.""",
-        required=True
-        )
-
-    file = Path(
-        title=u"File",
-        description=u"The file containing the icon.",
-        required=False
-        )
-
-    resource = TextLine(
-        title=u"Resource",
-        description=u"A resource containing the icon.",
-        required=False
-        )
-
-    title = MessageID(
-        title=u"Title",
-        description=u"Descriptive title",
-        required=False
-        )
-
-    layer = GlobalInterface(
-        title=u"The layer the icon should be found in",
-        description=u"""
-        For information on layers, see the documentation for the skin
-        directive. Defaults to "default".""",
-        required=False
-        )
-
-    width = Int(
-        title=u"The width of the icon.",
-        description=u"""
-        The width will be used for the <img width="..." />
-        attribute. Defaults to 16.""",
-        required=False,
-        default=16
-        )
-    
-    height = Int(
-        title=u"The height of the icon.",
-        description=u"""
-        The height will be used for the <img height="..." />
-        attribute. Defaults to 16.""",
-        required=False,
-        default=16
-        )
+# BBB imports
+from zope.browserresource.metadirectives import (
+    IBasicResourceInformation,
+    IResourceDirective,
+    II18nResourceDirective,
+    II18nResourceTranslationSubdirective,
+    IResourceDirectoryDirective,
+    IIconDirective
+)
+from zope.browsermenu.metadirectives import (
+    IMenuDirective,
+    IMenuItemsDirective,
+    IMenuItem,
+    IMenuItemSubdirective,
+    IMenuItemDirective,
+    ISubMenuItemSubdirective,
+    ISubMenuItemDirective,
+    IAddMenuItemDirective,
+)
+from zope.browserpage.metadirectives import (
+    IPagesDirective,
+    IViewDirective,
+    IViewPageSubdirective,
+    IViewDefaultPageSubdirective,
+    IPagesPageSubdirective,
+    IPageDirective,
+)
+from zope.publisher.zcml import IDefaultSkinDirective, IDefaultViewDirective

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/pagetemplateresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/pagetemplateresource.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/pagetemplateresource.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,43 +15,6 @@
 
 $Id$
 """
-
-from zope.interface import implements
-from zope.publisher.interfaces import NotFound
-from zope.publisher.browser import BrowserView
-from zope.publisher.interfaces.browser import IBrowserPublisher
-
-from zope.app.publisher.pagetemplateresource import PageTemplate
-from zope.app.publisher.browser.resource import Resource
-
-class PageTemplateResource(BrowserView, Resource):
-
-    implements(IBrowserPublisher)
-
-    def publishTraverse(self, request, name):
-        '''See interface IBrowserPublisher'''
-        raise NotFound(None, name)
-
-    def browserDefault(self, request):
-        '''See interface IBrowserPublisher'''
-        return self, ()
-
-    def __call__(self):
-        pt = self.context
-        response = self.request.response
-        if not response.getHeader("Content-Type"):
-            response.setHeader("Content-Type", pt.content_type)
-        return pt(self.request)
-
-class PageTemplateResourceFactory(object):
-
-    def __init__(self, path, checker, name):
-        self.__pt = PageTemplate(path)
-        self.__checker = checker
-        self.__name = name
-
-    def __call__(self, request):
-        resource = PageTemplateResource(self.__pt, request)
-        resource.__Security_checker__ = self.__checker
-        resource.__name__ = self.__name
-        return resource
+# BBB imports
+from zope.ptresource.ptresource import PageTemplateResource
+from zope.ptresource.ptresource import PageTemplateResourceFactory

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/resource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/resource.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/resource.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,48 +15,4 @@
 
 $Id$
 """
-from zope.app.publisher.interfaces import IResource
-from zope.component import adapts
-from zope.component import getMultiAdapter
-from zope.component import queryMultiAdapter
-from zope.interface import implements, implementsOnly
-from zope.location import Location
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.site.hooks import getSite
-from zope.traversing.browser.interfaces import IAbsoluteURL
-import zope.traversing.browser.absoluteurl
-
-class Resource(Location):
-
-    implements(IResource)
-
-    def __init__(self, request):
-        self.request = request
-
-    def __call__(self):
-        return str(getMultiAdapter((self, self.request), IAbsoluteURL))
-
-
-class AbsoluteURL(zope.traversing.browser.absoluteurl.AbsoluteURL):
-
-    implementsOnly(IAbsoluteURL)
-    adapts(IResource, IBrowserRequest)
-
-    def __init__(self, context, request):
-        self.context = context
-        self.request = request
-
-    def __str__(self):
-        name = self.context.__name__
-        if name.startswith('++resource++'):
-            name = name[12:]
-
-        site = getSite()
-        base = queryMultiAdapter((site, self.request), IAbsoluteURL,
-            name="resource")
-        if base is None:
-            url = str(getMultiAdapter((site, self.request), IAbsoluteURL))
-        else:
-            url = str(base)
-
-        return "%s/@@/%s" % (url, name)
+from zope.browserresource.resource import Resource, AbsoluteURL # BBB imports

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/resourcemeta.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/resourcemeta.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/resourcemeta.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,87 +15,10 @@
 
 $Id$
 """
-import os
-
-from zope.configuration.exceptions import ConfigurationError
-from zope.interface import Interface
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.security.checker import CheckerPublic, NamesChecker
-from zope.component.zcml import handler
-
-from fileresource import FileResourceFactory, ImageResourceFactory
-from pagetemplateresource import PageTemplateResourceFactory
-from directoryresource import DirectoryResourceFactory
-
-allowed_names = ('GET', 'HEAD', 'publishTraverse', 'browserDefault',
-                 'request', '__call__')
-
-class ResourceFactoryWrapper(object):
-
-    def __init__(self, factory, checker, name):
-        self.__factory = factory
-        self.__checker = checker
-        self.__name = name
-
-    def __call__(self, request):
-        resource = self.__factory(request)
-        resource.__Security_checker__ = self.__checker
-        resource.__name__ = self.__name
-        return resource
-    
-
-def resource(_context, name, layer=IDefaultBrowserLayer,
-             permission='zope.Public', factory=None,
-             file=None, image=None, template=None):
-
-    if permission == 'zope.Public':
-        permission = CheckerPublic
-
-    checker = NamesChecker(allowed_names, permission)
-
-    if (factory and (file or image or template)) or \
-       (file and (factory or image or template)) or \
-       (image and (factory or file or template)) or \
-       (template and (factory or file or image)):
-        raise ConfigurationError(
-            "Must use exactly one of factory or file or image or template"
-            " attributes for resource directives"
-            )
-
-    if factory is not None:
-        factory = ResourceFactoryWrapper(factory, checker, name)
-    elif file:
-        factory = FileResourceFactory(file, checker, name)
-    elif image:
-        factory = ImageResourceFactory(image, checker, name)
-    else:
-        factory = PageTemplateResourceFactory(template, checker, name)
-
-    _context.action(
-        discriminator = ('resource', name, IBrowserRequest, layer),
-        callable = handler,
-        args = ('registerAdapter',
-                factory, (layer,), Interface, name, _context.info),
-        )
-
-def resourceDirectory(_context, name, directory, layer=IDefaultBrowserLayer,
-                      permission='zope.Public'):
-    if permission == 'zope.Public':
-        permission = CheckerPublic
-
-    checker = NamesChecker(allowed_names + ('__getitem__', 'get'),
-                           permission)
-
-    if not os.path.isdir(directory):
-        raise ConfigurationError(
-            "Directory %s does not exist" % directory
-            )
-
-    factory = DirectoryResourceFactory(directory, checker, name)
-    _context.action(
-        discriminator = ('resource', name, IBrowserRequest, layer),
-        callable = handler,
-        args = ('registerAdapter',
-                factory, (layer,), Interface, name, _context.info),
-        )
+# BBB imports
+from zope.browserresource.metaconfigure import (
+    allowed_names,
+    ResourceFactoryWrapper,
+    resource,
+    resourceDirectory
+)

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/resources.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/resources.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/resources.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,37 +15,5 @@
 
 $Id$
 """
-import zope.component
-from zope.publisher.interfaces.browser import IBrowserPublisher
-from zope.publisher.interfaces import NotFound
-from zope.publisher.browser import BrowserView
-from zope.interface import implements
-from zope.location import locate
 
-class Resources(BrowserView):
-    """Provide a URL-accessible resource namespace
-    """
-
-    implements(IBrowserPublisher)
-
-    def publishTraverse(self, request, name):
-        '''See interface IBrowserPublisher'''
-
-        resource = zope.component.queryAdapter(request, name=name)
-        if resource is None:
-            raise NotFound(self, name)
-
-        sm = zope.component.getSiteManager()
-        locate(resource, sm, name)
-        return resource
-
-    def browserDefault(self, request):
-        '''See IBrowserPublisher'''
-        return empty, ()
-
-    def __getitem__(self, name):
-        return self.publishTraverse(self.request, name)
-
-
-def empty():
-    return ''
+from zope.browserresource.resources import Resources, empty # BBB imports

Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/viewmeta.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/viewmeta.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/viewmeta.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,404 +15,16 @@
 
 $Id$
 """
-import os
-
-from zope.component import queryMultiAdapter
-from zope.component.interface import provideInterface
-from zope.component.zcml import handler
-from zope.interface import implements, classImplements, Interface
-from zope.publisher.interfaces import NotFound
-from zope.security.checker import CheckerPublic, Checker, defineChecker
-from zope.configuration.exceptions import ConfigurationError
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.publisher.interfaces.browser import IBrowserPublisher
-from zope.publisher.browser import BrowserView
-
-from zope.app.pagetemplate.simpleviewclass import SimpleViewClass
-from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
-from zope.app.publisher.browser.menumeta import menuItemDirective
-
-# There are three cases we want to suport:
-#
-# Named view without pages (single-page view)
-#
-#     <browser:page
-#         for=".IContact.IContactInfo."
-#         name="info.html" 
-#         template="info.pt"
-#         class=".ContactInfoView."
-#         permission="zope.View"
-#         />
-#
-# Unnamed view with pages (multi-page view)
-#
-#     <browser:pages
-#         for=".IContact."
-#         class=".ContactEditView."
-#         permission="ZopeProducts.Contact.ManageContacts"
-#         >
-# 
-#       <browser:page name="edit.html"       template="edit.pt" />
-#       <browser:page name="editAction.html" attribute="action" />
-#       </browser:pages>
-#
-# Named view with pages (add view is a special case of this)
-#
-#        <browser:view
-#            name="ZopeProducts.Contact"
-#            for="Zope.App.OFS.Container.IAdding."
-#            class=".ContactAddView."
-#            permission="ZopeProducts.Contact.ManageContacts"
-#            >
-#
-#          <browser:page name="add.html"    template="add.pt" />
-#          <browser:page name="action.html" attribute="action" />
-#          </browser:view>
-
-# We'll also provide a convenience directive for add views:
-#
-#        <browser:add
-#            name="ZopeProducts.Contact"
-#            class=".ContactAddView."
-#            permission="ZopeProducts.Contact.ManageContacts"
-#            >
-#
-#          <browser:page name="add.html"    template="add.pt" />
-#          <browser:page name="action.html" attribute="action" />
-#          </browser:view>
-
-# page
-
-def page(_context, name, permission, for_,
-         layer=IDefaultBrowserLayer, template=None, class_=None,
-         allowed_interface=None, allowed_attributes=None,
-         attribute='__call__', menu=None, title=None, 
-         ):
-    _handle_menu(_context, menu, title, [for_], name, permission, layer)
-    required = {}
-
-    permission = _handle_permission(_context, permission)
-
-    if not (class_ or template):
-        raise ConfigurationError("Must specify a class or template")
-
-    if attribute != '__call__':
-        if template:
-            raise ConfigurationError(
-                "Attribute and template cannot be used together.")
-
-        if not class_:
-            raise ConfigurationError(
-                "A class must be provided if attribute is used")
-
-    if template:
-        template = os.path.abspath(str(_context.path(template)))
-        if not os.path.isfile(template):
-            raise ConfigurationError("No such file", template)
-        required['__getitem__'] = permission
-
-    # TODO: new __name__ attribute must be tested
-    if class_:
-        if attribute != '__call__':
-            if not hasattr(class_, attribute):
-                raise ConfigurationError(
-                    "The provided class doesn't have the specified attribute "
-                    )
-        if template:
-            # class and template
-            new_class = SimpleViewClass(template, bases=(class_, ), name=name)
-        else:
-            if not hasattr(class_, 'browserDefault'):
-                cdict = {
-                    'browserDefault':
-                    lambda self, request: (getattr(self, attribute), ())
-                    }
-            else:
-                cdict = {}
-
-            cdict['__name__'] = name
-            cdict['__page_attribute__'] = attribute
-            new_class = type(class_.__name__, (class_, simple,), cdict)
-
-        if hasattr(class_, '__implements__'):
-            classImplements(new_class, IBrowserPublisher)
-
-    else:
-        # template
-        new_class = SimpleViewClass(template, name=name)
-
-    for n in (attribute, 'browserDefault', '__call__', 'publishTraverse'):
-        required[n] = permission
-
-    _handle_allowed_interface(_context, allowed_interface, permission,
-                              required)
-    _handle_allowed_attributes(_context, allowed_attributes, permission,
-                               required)
-
-    _handle_for(_context, for_)
-
-    defineChecker(new_class, Checker(required))
-
-    _context.action(
-        discriminator = ('view', for_, name, IBrowserRequest, layer),
-        callable = handler,
-        args = ('registerAdapter',
-                new_class, (for_, layer), Interface, name, _context.info),
-        )
-
-
-# pages, which are just a short-hand for multiple page directives.
-
-# Note that a class might want to access one of the defined
-# templates. If it does though, it should use getMultiAdapter.
-
-class pages(object):
-
-    def __init__(self, _context, for_, permission,
-                 layer=IDefaultBrowserLayer, class_=None,
-                 allowed_interface=None, allowed_attributes=None,
-                 ):
-        self.opts = dict(for_=for_, permission=permission,
-                         layer=layer, class_=class_,
-                         allowed_interface=allowed_interface,
-                         allowed_attributes=allowed_attributes,
-                         )
-
-    def page(self, _context, name, attribute='__call__', template=None,
-             menu=None, title=None):
-        return page(_context,
-                    name=name,
-                    attribute=attribute,
-                    template=template,
-                    menu=menu, title=title,
-                    **(self.opts))
-
-    def __call__(self):
-        return ()
-
-# view (named view with pages)
-
-# This is a different case. We actually build a class with attributes
-# for all of the given pages.
-
-class view(object):
-
-    default = None
-
-    def __init__(self, _context, for_, permission,
-                 name='', layer=IDefaultBrowserLayer, class_=None,
-                 allowed_interface=None, allowed_attributes=None,
-                 menu=None, title=None, provides=Interface,
-                 ):
-
-        _handle_menu(_context, menu, title, [for_], name, permission, layer)
-
-        permission = _handle_permission(_context, permission)
-
-        self.args = (_context, name, for_, permission, layer, class_,
-                     allowed_interface, allowed_attributes)
-
-        self.pages = []
-        self.menu = menu
-        self.provides = provides
-
-    def page(self, _context, name, attribute=None, template=None):
-        if template:
-            template = os.path.abspath(_context.path(template))
-            if not os.path.isfile(template):
-                raise ConfigurationError("No such file", template)
-        else:
-            if not attribute:
-                raise ConfigurationError(
-                    "Must specify either a template or an attribute name")
-
-        self.pages.append((name, attribute, template))
-        return ()
-
-    def defaultPage(self, _context, name):
-        self.default = name
-        return ()
-
-    def __call__(self):
-        (_context, name, for_, permission, layer, class_,
-         allowed_interface, allowed_attributes) = self.args
-
-        required = {}
-
-        cdict = {}
-        pages = {}
-
-        for pname, attribute, template in self.pages:
-
-            if template:
-                cdict[pname] = ViewPageTemplateFile(template)
-                if attribute and attribute != name:
-                    cdict[attribute] = cdict[pname]
-            else:
-                if not hasattr(class_, attribute):
-                    raise ConfigurationError("Undefined attribute",
-                                             attribute)
-
-            attribute = attribute or pname
-            required[pname] = permission
-
-            pages[pname] = attribute
-
-        # This should go away, but noone seems to remember what to do. :-(
-        if hasattr(class_, 'publishTraverse'):
-
-            def publishTraverse(self, request, name,
-                                pages=pages, getattr=getattr):
-
-                if name in pages:
-                    return getattr(self, pages[name])
-                view = queryMultiAdapter((self, request), name=name)
-                if view is not None:
-                    return view
-
-                m = class_.publishTraverse.__get__(self)
-                return m(request, name)
-
-        else:
-            def publishTraverse(self, request, name,
-                                pages=pages, getattr=getattr):
-
-                if name in pages:
-                    return getattr(self, pages[name])
-                view = queryMultiAdapter((self, request), name=name)
-                if view is not None:
-                    return view
-
-                raise NotFound(self, name, request)
-
-        cdict['publishTraverse'] = publishTraverse
-
-        if not hasattr(class_, 'browserDefault'):
-            if self.default or self.pages:
-                default = self.default or self.pages[0][0]
-                cdict['browserDefault'] = (
-                    lambda self, request, default=default:
-                    (self, (default, ))
-                    )
-            elif providesCallable(class_):
-                cdict['browserDefault'] = (
-                    lambda self, request: (self, ())
-                    )
-
-        if class_ is not None:
-            bases = (class_, simple)
-        else:
-            bases = (simple,)
-
-        try:
-            cname = str(name)
-        except:
-            cname = "GeneratedClass"
-
-        cdict['__name__'] = name
-        newclass = type(cname, bases, cdict)
-
-        for n in ('publishTraverse', 'browserDefault', '__call__'):
-            required[n] = permission
-
-        _handle_allowed_interface(_context, allowed_interface, permission,
-                                  required)
-        _handle_allowed_attributes(_context, allowed_attributes, permission,
-                                   required)
-        _handle_for(_context, for_)
-
-        defineChecker(newclass, Checker(required))
-
-        if self.provides is not None:
-            _context.action(
-                discriminator = None,
-                callable = provideInterface,
-                args = ('', self.provides)
-                )
-
-        _context.action(
-            discriminator = ('view', (for_, layer), name, self.provides),
-            callable = handler,
-            args = ('registerAdapter',
-                    newclass, (for_, layer), self.provides, name,
-                    _context.info),
-            )
-
-def _handle_menu(_context, menu, title, for_, name, permission,
-                 layer=IDefaultBrowserLayer):
-
-    if menu or title:
-        if not (menu and title):
-            raise ConfigurationError(
-                "If either menu or title are specified, they must "
-                "both be specified.")
-            if len(for_) != 1:
-                raise ConfigurationError(
-                    "Menus can be specified only for single-view, not for "
-                    "multi-views.")
-
-        return menuItemDirective(
-            _context, menu, for_[0], '@@' + name, title,
-            permission=permission, layer=layer)
-
-    return []
-
-def _handle_permission(_context, permission):
-    if permission == 'zope.Public':
-        permission = CheckerPublic
-
-    return permission
-
-def _handle_allowed_interface(_context, allowed_interface, permission,
-                              required):
-    # Allow access for all names defined by named interfaces
-    if allowed_interface:
-        for i in allowed_interface:
-            _context.action(
-                discriminator = None,
-                callable = provideInterface,
-                args = (None, i)
-                )
-
-            for name in i:
-                required[name] = permission
-
-def _handle_allowed_attributes(_context, allowed_attributes, permission,
-                               required):
-    # Allow access for all named attributes
-    if allowed_attributes:
-        for name in allowed_attributes:
-            required[name] = permission
-
-def _handle_for(_context, for_):
-    if for_ is not None:
-        _context.action(
-            discriminator = None,
-            callable = provideInterface,
-            args = ('', for_)
-            )
-
-class simple(BrowserView):
-    implements(IBrowserPublisher)
-
-    def publishTraverse(self, request, name):
-        raise NotFound(self, name, request)
-
-    def __call__(self, *a, **k):
-        # If a class doesn't provide it's own call, then get the attribute
-        # given by the browser default.
-
-        attr = self.__page_attribute__
-        if attr == '__call__':
-            raise AttributeError("__call__")
-
-        meth = getattr(self, attr)
-        return meth(*a, **k)
-
-def providesCallable(class_):
-    if hasattr(class_, '__call__'):
-        for c in class_.__mro__:
-            if '__call__' in c.__dict__:
-                return True
-    return False
+# BBB imports
+from zope.browserpage.metaconfigure import (
+    page,
+    pages,
+    view,
+    _handle_menu,
+    _handle_permission,
+    _handle_allowed_interface,
+    _handle_allowed_attributes,
+    _handle_for,
+    simple,
+    providesCallable,
+)

Modified: zope.app.publisher/trunk/src/zope/app/publisher/configure.zcml
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/configure.zcml	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/configure.zcml	2009-08-27 15:12:51 UTC (rev 103291)
@@ -3,9 +3,9 @@
     xmlns:apidoc="http://namespaces.zope.org/apidoc"
     >
 
+  <include package="zope.publisher" />
   <include package=".browser" />
   <include package=".xmlrpc" />
-  <include file="http.zcml" />
 
 
 </configure>

Modified: zope.app.publisher/trunk/src/zope/app/publisher/fileresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/fileresource.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/fileresource.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,33 +15,7 @@
 
 $Id$
 """
-import os
-from time import time
 
-from zope.contenttype import guess_content_type
-from zope.datetime import rfc1123_date
-
-
-class File(object):
-    
-    def __init__(self, path, name):
-        self.path = path
-
-        f = open(path, 'rb')
-        data = f.read()
-        f.close()
-        self.content_type, enc = guess_content_type(path, data)
-        self.__name__ = name
-        self.lmt = float(os.path.getmtime(path)) or time()
-        self.lmh = rfc1123_date(self.lmt)
-
-
-class Image(File):
-    """Image objects stored in external files."""
-
-    def __init__(self, path, name):
-        super(Image, self).__init__(path, name)
-        if self.content_type in (None, 'application/octet-stream'):
-            ext = os.path.splitext(self.path)[1]
-            if ext:
-                self.content_type = 'image/%s' % ext[1:]
+# BBB imports
+from zope.browserresource.file import File
+Image = File

Modified: zope.app.publisher/trunk/src/zope/app/publisher/http.zcml
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/http.zcml	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/http.zcml	2009-08-27 15:12:51 UTC (rev 103291)
@@ -2,19 +2,6 @@
    xmlns="http://namespaces.zope.org/zope"
    package="zope.publisher.http">
 
-  <class class="zope.publisher.http.HTTPRequest">
-    <require
-        permission="zope.View"
-        interface="zope.publisher.interfaces.http.IHTTPApplicationRequest"/>
-  </class>
+  <!-- The contents of this file was moved into zope.publisher's configure.zcml -->
 
-  <class class="zope.publisher.http.URLGetter">
-    <allow
-        attributes="get __getitem__ __str__" />
-  </class>
-
-  <class class="zope.publisher.http.DirectResult">
-    <allow interface="zope.publisher.http.IResult" />
-  </class>
-
 </configure>

Modified: zope.app.publisher/trunk/src/zope/app/publisher/interfaces/__init__.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/interfaces/__init__.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/interfaces/__init__.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,12 +15,4 @@
 
 $Id$
 """
-from zope.interface import Interface, Attribute
-
-
-class IResource(Interface):
-
-    request = Attribute('Request object that is requesting the resource')
-
-    def __call__():
-        """return the absolute URL of this resource."""
+from zope.browserresource.interfaces import IResource # BBB import

Modified: zope.app.publisher/trunk/src/zope/app/publisher/interfaces/browser.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/interfaces/browser.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/interfaces/browser.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,147 +15,13 @@
 
 $Id$
 """
-from zope.app.publisher.i18n import ZopeMessageFactory as _
-from zope.interface import Interface, directlyProvides
-from zope.interface.interfaces import IInterface
-from zope.schema import TextLine, Text, URI, Int
 
-
-class IMenuItemType(IInterface):
-    """Menu item type
-
-    Menu item types are interfaces that define classes of
-    menu items.
-    """
-
-class AddMenu(Interface):
-    """Special menu for providing a list of addable objects."""
-
-directlyProvides(AddMenu, IMenuItemType)
-
-
-class IBrowserMenu(Interface):
-    """Menu
-
-    Menus are objects that can return a list of menu items they contain. How
-    they generate this list is up to them. Commonly, however, they will look
-    up adapters that provide the ``IBrowserMenuItem`` interface.
-    """
-
-    id = TextLine(
-        title=_("Menu Id"),
-        description=_("The id uniquely identifies this menu."),
-        required=True
-        )
-
-    title = TextLine(
-        title=_("Menu title"),
-        description=_("The title provides the basic label for the menu."),
-        required=False
-        )
-
-    description = Text(
-        title=_("Menu description"),
-        description=_("A description of the menu. This might be shown "
-                      "on menu pages or in pop-up help for menus."),
-        required=False
-        )
-
-    def getMenuItems(object, request):
-        """Return a TAL-friendly list of menu items.
-
-        The object (acts like the context) and request can be used to select
-        the items that are available.
-        """
-
-
-class IBrowserMenuItem(Interface):
-    """Menu type
-
-    An interface that defines a menu.
-    """
-
-    title = TextLine(
-        title=_("Menu item title"),
-        description=_("The title provides the basic label for the menu item."),
-        required=True
-        )
-
-    description = Text(
-        title=_("Menu item description"),
-        description=_("A description of the menu item. This might be shown "
-                      "on menu pages or in pop-up help for menu items."),
-        required=False
-        )
-
-    action = TextLine(
-        title=_("The URL to display if the item is selected"),
-        description=_("When a user selects a browser menu item, the URL"
-                      "given in the action is displayed. The action is "
-                      "usually given as a relative URL, relative to the "
-                      "object the menu item is for."),
-       required=True
-       )
-
-    order = Int(
-        title=_("Menu item ordering hint"),
-        description=_("This attribute provides a hint for menu item ordering."
-                      "Menu items will generally be sorted by the `for_`"
-                      "attribute and then by the order.")
-        )
-
-    filter_string = TextLine(
-        title=_("A condition for displaying the menu item"),
-        description=_("The condition is given as a TALES expression. The "
-                      "expression has access to the variables:\n"
-                      "\n"
-                      "context -- The object the menu is being displayed "
-                      "for\n"
-                      "\n"
-                      "request -- The browser request\n"
-                      "\n"
-                      "nothing -- None\n"
-                      "\n"
-                      "The menu item will not be displayed if there is a \n"
-                      "filter and the filter evaluates to a false value."),
-        required=False)
-
-    icon = URI(
-        title=_("Icon URI"),
-        description=_("URI of the icon representing this menu item"))
-       
-    def available():
-        """Test whether the menu item should be displayed
-        
-        A menu item might not be available for an object, for example
-        due to security limitations or constraints.
-        """
-
-class IBrowserSubMenuItem(IBrowserMenuItem):
-    """A menu item that points to a sub-menu."""
-
-    submenuId = TextLine(
-        title=_("Sub-Menu Id"),
-        description=_("The menu id of the menu that describes the "
-                      "sub-menu below this item."),
-        required=True)
-        
-    action = TextLine(
-        title=_("The URL to display if the item is selected"),
-        description=_("When a user selects a browser menu item, the URL "
-                      "given in the action is displayed. The action is "
-                      "usually given as a relative URL, relative to the "
-                      "object the menu item is for."),
-       required=False
-       )
-
-
-class IMenuAccessView(Interface):
-    """View that provides access to menus"""
-
-    def __getitem__(menu_id):
-        """Get menu information
-
-        Return a sequence of dictionaries with labels and
-        actions, where actions are relative URLs.
-        """
+# BBB imports
+from zope.browsermenu.interfaces import (
+    IMenuItemType,
+    AddMenu,
+    IBrowserMenu,
+    IBrowserMenuItem,
+    IBrowserSubMenuItem,
+    IMenuAccessView
+)

Modified: zope.app.publisher/trunk/src/zope/app/publisher/interfaces/ftp.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/interfaces/ftp.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/interfaces/ftp.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,14 +15,9 @@
 
 $Id$
 """
-from zope.publisher.interfaces import IView
-from zope.publisher.interfaces.ftp import IFTPPublisher
+from zope.publisher.interfaces.ftp import IFTPPublisher, IFTPView
 
 
-class IFTPView(IView):
-    "FTP View"
-
-
 class IFTPDirectoryPublisher(IFTPPublisher, IFTPView):
 
     def type(name):

Modified: zope.app.publisher/trunk/src/zope/app/publisher/interfaces/http.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/interfaces/http.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/interfaces/http.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,13 +15,9 @@
 
 $Id$
 """
-from zope.publisher.interfaces import IView
+from zope.publisher.interfaces.http import IHTTPView
 
 
-class IHTTPView(IView):
-    "HTTP View"
-
-
 class ILogin(IHTTPView):
     """A simple login interface."""
 

Modified: zope.app.publisher/trunk/src/zope/app/publisher/interfaces/xmlrpc.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/interfaces/xmlrpc.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/interfaces/xmlrpc.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,8 +15,4 @@
 
 $Id$
 """
-from zope.publisher.interfaces import IView
-
-
-class IXMLRPCView(IView):
-    """XMLRPC View"""
+from zope.publisher.interfaces.xmlrpc import IXMLRPCView # BBB import

Modified: zope.app.publisher/trunk/src/zope/app/publisher/pagetemplateresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/pagetemplateresource.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/pagetemplateresource.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,30 +15,5 @@
 
 $Id$
 """
+from zope.ptresource.ptresource import PageTemplate # BBB import
 
-from zope.pagetemplate.engine import TrustedAppPT
-from zope.pagetemplate.pagetemplatefile import PageTemplateFile
-
-class PageTemplate(TrustedAppPT, PageTemplateFile):
-    """
-    Resource that is a page template
-    """
-
-    def __init__(self, filename, _prefix=None, content_type=None):
-        _prefix = self.get_path_from_prefix(_prefix)
-        super(PageTemplate, self).__init__(filename, _prefix)
-        if content_type is not None:
-            self.content_type = content_type
-
-    def pt_getContext(self, request, **kw):
-        namespace = super(PageTemplate, self).pt_getContext(**kw)
-        namespace['context'] = None
-        namespace['request'] = request
-        return namespace
-
-    def __call__(self, request, **keywords):
-        namespace = self.pt_getContext(
-            request=request,
-            options=keywords
-            )
-        return self.pt_render(namespace)

Modified: zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/__init__.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/__init__.py	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/__init__.py	2009-08-27 15:12:51 UTC (rev 103291)
@@ -22,13 +22,8 @@
 import zope.publisher.interfaces.xmlrpc
 import zope.app.publisher.interfaces.xmlrpc
 
-class XMLRPCView(object):
-    """A base XML-RPC view that can be used as mix-in for XML-RPC views.""" 
-    zope.interface.implements(zope.app.publisher.interfaces.xmlrpc.IXMLRPCView)
+from zope.publisher.xmlrpc import XMLRPCView
 
-    def __init__(self, context, request):
-        self.context = context
-        self.request = request
 
 class IMethodPublisher(zope.interface.Interface):
     """Marker interface for an object that wants to publish methods

Modified: zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/configure.zcml
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/configure.zcml	2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/configure.zcml	2009-08-27 15:12:51 UTC (rev 103291)
@@ -3,31 +3,7 @@
     xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
     >
 
-  <class class="xmlrpclib.Fault">
-    <allow attributes="faultCode faultString" />
-  </class>
-
-  <class class="xmlrpclib.DateTime">
-    <allow attributes="value" />
-  </class>
-
   <view 
-      for="zope.container.interfaces.IItemContainer"
-      type="zope.publisher.interfaces.xmlrpc.IXMLRPCRequest"
-      provides="zope.publisher.interfaces.xmlrpc.IXMLRPCPublisher"
-      factory="zope.container.traversal.ItemTraverser"
-      permission="zope.Public"
-      />
-
-  <view 
-      for="zope.container.interfaces.IReadContainer"
-      type="zope.publisher.interfaces.xmlrpc.IXMLRPCRequest"
-      provides="zope.publisher.interfaces.xmlrpc.IXMLRPCPublisher"
-      factory="zope.container.traversal.ContainerTraverser"
-      permission="zope.Public"
-      />
-
-  <view 
       for=".IMethodPublisher"
       type="zope.publisher.interfaces.xmlrpc.IXMLRPCRequest"
       provides="zope.publisher.interfaces.xmlrpc.IXMLRPCPublisher"



More information about the Checkins mailing list