[Checkins] SVN: zope.browserpage/tags/ Tag 3.9.0

Dan Korostelev nadako at gmail.com
Thu Aug 27 10:16:23 EDT 2009


Log message for revision 103274:
  Tag 3.9.0

Changed:
  A   zope.browserpage/tags/
  A   zope.browserpage/tags/3.9.0/
  U   zope.browserpage/tags/3.9.0/CHANGES.txt
  D   zope.browserpage/tags/3.9.0/bootstrap.py
  A   zope.browserpage/tags/3.9.0/bootstrap.py
  D   zope.browserpage/tags/3.9.0/buildout.cfg
  A   zope.browserpage/tags/3.9.0/buildout.cfg
  D   zope.browserpage/tags/3.9.0/setup.py
  A   zope.browserpage/tags/3.9.0/setup.py
  D   zope.browserpage/tags/3.9.0/src/zope/__init__.py
  A   zope.browserpage/tags/3.9.0/src/zope/__init__.py
  D   zope.browserpage/tags/3.9.0/src/zope/browserpage/__init__.py
  A   zope.browserpage/tags/3.9.0/src/zope/browserpage/__init__.py
  D   zope.browserpage/tags/3.9.0/src/zope/browserpage/metaconfigure.py
  A   zope.browserpage/tags/3.9.0/src/zope/browserpage/metaconfigure.py
  D   zope.browserpage/tags/3.9.0/src/zope/browserpage/metadirectives.py
  A   zope.browserpage/tags/3.9.0/src/zope/browserpage/metadirectives.py
  D   zope.browserpage/tags/3.9.0/src/zope/browserpage/tests.py
  A   zope.browserpage/tags/3.9.0/src/zope/browserpage/tests.py

-=-
Modified: zope.browserpage/tags/3.9.0/CHANGES.txt
===================================================================
--- zope.browserpage/trunk/CHANGES.txt	2009-08-27 14:07:47 UTC (rev 103272)
+++ zope.browserpage/tags/3.9.0/CHANGES.txt	2009-08-27 14:16:22 UTC (rev 103274)
@@ -2,7 +2,7 @@
 CHANGES
 =======
 
-3.9.0 (unreleased)
+3.9.0 (2009-08-27)
 ==================
 
 Initial release. This package was splitted off from zope.app.publisher.

Deleted: zope.browserpage/tags/3.9.0/bootstrap.py
===================================================================
--- zope.browserpage/trunk/bootstrap.py	2009-08-27 14:07:47 UTC (rev 103272)
+++ zope.browserpage/tags/3.9.0/bootstrap.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -1,52 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Bootstrap a buildout-based project
-
-Simply run this script in a directory containing a buildout.cfg.
-The script accepts buildout command-line options, so you can
-use the -c option to specify an alternate configuration file.
-
-$Id: bootstrap.py 73800 2007-03-27 16:16:42Z dobe $
-"""
-
-import os, shutil, sys, tempfile, urllib2
-
-tmpeggs = tempfile.mkdtemp()
-
-ez = {}
-exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
-                     ).read() in ez
-ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
-
-import pkg_resources
-
-cmd = 'from setuptools.command.easy_install import main; main()'
-if sys.platform == 'win32':
-    cmd = '"%s"' % cmd # work around spawn lamosity on windows
-
-ws = pkg_resources.working_set
-assert os.spawnle(
-    os.P_WAIT, sys.executable, sys.executable,
-    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
-    dict(os.environ,
-         PYTHONPATH=
-         ws.find(pkg_resources.Requirement.parse('setuptools')).location
-         ),
-    ) == 0
-
-ws.add_entry(tmpeggs)
-ws.require('zc.buildout')
-import zc.buildout.buildout
-zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
-shutil.rmtree(tmpeggs)

Copied: zope.browserpage/tags/3.9.0/bootstrap.py (from rev 103273, zope.browserpage/trunk/bootstrap.py)
===================================================================
--- zope.browserpage/tags/3.9.0/bootstrap.py	                        (rev 0)
+++ zope.browserpage/tags/3.9.0/bootstrap.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                     ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)

Deleted: zope.browserpage/tags/3.9.0/buildout.cfg
===================================================================
--- zope.browserpage/trunk/buildout.cfg	2009-08-27 14:07:47 UTC (rev 103272)
+++ zope.browserpage/tags/3.9.0/buildout.cfg	2009-08-27 14:16:22 UTC (rev 103274)
@@ -1,22 +0,0 @@
-[buildout]
-develop = . ../zope.browsermenu
-parts = test coverage-test coverage-report pydev
-
-[test]
-recipe = zc.recipe.testrunner
-eggs = zope.browserpage [test]
-
-[coverage-test]
-recipe = zc.recipe.testrunner
-eggs = zope.browserpage [test]
-defaults = ['--coverage', '../../coverage']
-
-[coverage-report]
-recipe = zc.recipe.egg
-eggs = z3c.coverage
-scripts = coverage=coverage-report
-arguments = ('coverage', 'coverage/report')
-
-[pydev]
-recipe = pb.recipes.pydev
-eggs = zope.browserpage

Copied: zope.browserpage/tags/3.9.0/buildout.cfg (from rev 103273, zope.browserpage/trunk/buildout.cfg)
===================================================================
--- zope.browserpage/tags/3.9.0/buildout.cfg	                        (rev 0)
+++ zope.browserpage/tags/3.9.0/buildout.cfg	2009-08-27 14:16:22 UTC (rev 103274)
@@ -0,0 +1,22 @@
+[buildout]
+develop = .
+parts = test coverage-test coverage-report pydev
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = zope.browserpage [test]
+
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = zope.browserpage [test]
+defaults = ['--coverage', '../../coverage']
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')
+
+[pydev]
+recipe = pb.recipes.pydev
+eggs = zope.browserpage

Deleted: zope.browserpage/tags/3.9.0/setup.py
===================================================================
--- zope.browserpage/trunk/setup.py	2009-08-27 14:07:47 UTC (rev 103272)
+++ zope.browserpage/tags/3.9.0/setup.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -1,59 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2007 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""zope.browserpage setup
-"""
-from setuptools import setup, find_packages, Extension
-
-long_description = (open('README.txt').read() + '\n\n' +
-                    open('CHANGES.txt').read())
-
-setup(name='zope.browserpage',
-      version = '3.9.0dev',
-      url='http://pypi.python.org/pypi/zope.browserpage/',
-      author='Zope Corporation and Contributors',
-      author_email='zope-dev at zope.org',
-      classifiers = ['Environment :: Web Environment',
-                     'Intended Audience :: Developers',
-                     'License :: OSI Approved :: Zope Public License',
-                     'Programming Language :: Python',
-                     'Operating System :: OS Independent',
-                     'Topic :: Internet :: WWW/HTTP',
-                     'Framework :: Zope3',
-                     ],
-      description='ZCML directives for configuration browser views for Zope 3.',
-      long_description=long_description,
-
-      packages=find_packages('src'),
-      package_dir={'': 'src'},
-
-      namespace_packages=['zope'],
-      include_package_data=True,
-      install_requires=['setuptools',
-                        'zope.app.pagetemplate',
-                        'zope.browser',
-                        'zope.component>=3.7.0',
-                        'zope.configuration',
-                        'zope.interface',
-                        'zope.publisher>=3.8.0',
-                        'zope.schema',
-                        'zope.security',
-                        'zope.traversing>3.7.0',
-                        ],
-      extras_require={
-          'menu': ['zope.browsermenu'],
-          'test': ['zope.testing', 'zope.browsermenu'],
-          },
-
-      zip_safe = False,
-      )

Copied: zope.browserpage/tags/3.9.0/setup.py (from rev 103273, zope.browserpage/trunk/setup.py)
===================================================================
--- zope.browserpage/tags/3.9.0/setup.py	                        (rev 0)
+++ zope.browserpage/tags/3.9.0/setup.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -0,0 +1,57 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""zope.browserpage setup
+"""
+from setuptools import setup, find_packages, Extension
+
+long_description = (open('README.txt').read() + '\n\n' +
+                    open('CHANGES.txt').read())
+
+setup(name='zope.browserpage',
+      version = '3.9.0',
+      url='http://pypi.python.org/pypi/zope.browserpage/',
+      author='Zope Corporation and Contributors',
+      author_email='zope-dev at zope.org',
+      classifiers = ['Environment :: Web Environment',
+                     'Intended Audience :: Developers',
+                     'License :: OSI Approved :: Zope Public License',
+                     'Programming Language :: Python',
+                     'Operating System :: OS Independent',
+                     'Topic :: Internet :: WWW/HTTP',
+                     'Framework :: Zope3',
+                     ],
+      description='ZCML directives for configuration browser views for Zope 3.',
+      long_description=long_description,
+
+      packages=find_packages('src'),
+      package_dir={'': 'src'},
+
+      namespace_packages=['zope'],
+      include_package_data=True,
+      install_requires=['setuptools',
+                        'zope.app.pagetemplate',
+                        'zope.component>=3.7',
+                        'zope.configuration',
+                        'zope.interface',
+                        'zope.publisher>=3.8',
+                        'zope.schema',
+                        'zope.security',
+                        ],
+      extras_require={
+          'menu': ['zope.browsermenu'],
+          'test': ['zope.testing', 'zope.browsermenu'],
+          },
+
+      zip_safe = False,
+      )

Deleted: zope.browserpage/tags/3.9.0/src/zope/__init__.py
===================================================================
--- zope.browserpage/trunk/src/zope/__init__.py	2009-08-27 14:07:47 UTC (rev 103272)
+++ zope.browserpage/tags/3.9.0/src/zope/__init__.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -1,7 +0,0 @@
-# this is a namespace package
-try:
-    import pkg_resources
-    pkg_resources.declare_namespace(__name__)
-except ImportError:
-    import pkgutil
-    __path__ = pkgutil.extend_path(__path__, __name__)

Copied: zope.browserpage/tags/3.9.0/src/zope/__init__.py (from rev 103273, zope.browserpage/trunk/src/zope/__init__.py)
===================================================================
--- zope.browserpage/tags/3.9.0/src/zope/__init__.py	                        (rev 0)
+++ zope.browserpage/tags/3.9.0/src/zope/__init__.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)

Deleted: zope.browserpage/tags/3.9.0/src/zope/browserpage/metaconfigure.py
===================================================================
--- zope.browserpage/trunk/src/zope/browserpage/metaconfigure.py	2009-08-27 14:07:47 UTC (rev 103272)
+++ zope.browserpage/tags/3.9.0/src/zope/browserpage/metaconfigure.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -1,431 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Browser configuration code
-
-$Id: viewmeta.py 103154 2009-08-24 14:45:16Z nadako $
-"""
-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
-
-try:
-    from zope.browsermenu.metaconfigure import menuItemDirective
-except ImportError:
-    menuItemDirective = None
-
-# 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_=Interface,
-         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, permission, for_=Interface,
-                 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, permission, for_=Interface,
-                 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.")
-
-        if menuItemDirective is None:
-            import warnings
-            warnings.warn_explicit(
-                'Page directive used with "menu" argument, while "zope.browsermenu" '
-                'package is not installed. Doing nothing.',
-                UserWarning,
-                _context.info.file, _context.info.line)
-            return []
-    
-        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

Copied: zope.browserpage/tags/3.9.0/src/zope/browserpage/metaconfigure.py (from rev 103273, zope.browserpage/trunk/src/zope/browserpage/metaconfigure.py)
===================================================================
--- zope.browserpage/tags/3.9.0/src/zope/browserpage/metaconfigure.py	                        (rev 0)
+++ zope.browserpage/tags/3.9.0/src/zope/browserpage/metaconfigure.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -0,0 +1,431 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Browser page ZCML configuration code
+
+$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
+
+try:
+    from zope.browsermenu.metaconfigure import menuItemDirective
+except ImportError:
+    menuItemDirective = None
+
+# 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_=Interface,
+         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, permission, for_=Interface,
+                 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, permission, for_=Interface,
+                 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.")
+
+        if menuItemDirective is None:
+            import warnings
+            warnings.warn_explicit(
+                'Page directive used with "menu" argument, while "zope.browsermenu" '
+                'package is not installed. Doing nothing.',
+                UserWarning,
+                _context.info.file, _context.info.line)
+            return []
+    
+        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

Deleted: zope.browserpage/tags/3.9.0/src/zope/browserpage/metadirectives.py
===================================================================
--- zope.browserpage/trunk/src/zope/browserpage/metadirectives.py	2009-08-27 14:07:47 UTC (rev 103272)
+++ zope.browserpage/tags/3.9.0/src/zope/browserpage/metadirectives.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -1,191 +0,0 @@
-#############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Browser configuration code
-
-This module defines the schemas for browser directives.
-
-$Id: metadirectives.py 103154 2009-08-24 14:45:16Z nadako $
-"""
-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
-
-try:
-    from zope.browsermenu.field import MenuField
-except ImportError: # avoid hard dependency on zope.browsermenu
-    MenuField = TextLine
-
-
-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.
-          
-          This attribute will only work if zope.browsermenu is installed.
-          """,
-        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.
-
-          This attribute will only work if zope.browsermenu is installed.
-          """,
-        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 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.
-
-        This attribute will only work if zope.browsermenu is installed.
-        """,
-        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.
-
-        This attribute will only work if zope.browsermenu is installed.
-        """,
-        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.
-    """

Copied: zope.browserpage/tags/3.9.0/src/zope/browserpage/metadirectives.py (from rev 103273, zope.browserpage/trunk/src/zope/browserpage/metadirectives.py)
===================================================================
--- zope.browserpage/tags/3.9.0/src/zope/browserpage/metadirectives.py	                        (rev 0)
+++ zope.browserpage/tags/3.9.0/src/zope/browserpage/metadirectives.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -0,0 +1,189 @@
+#############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""ZCML directives for defining browser pages
+
+$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
+
+try:
+    from zope.browsermenu.field import MenuField
+except ImportError: # avoid hard dependency on zope.browsermenu
+    MenuField = TextLine
+
+
+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.
+          
+          This attribute will only work if zope.browsermenu is installed.
+          """,
+        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.
+
+          This attribute will only work if zope.browsermenu is installed.
+          """,
+        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 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.
+
+        This attribute will only work if zope.browsermenu is installed.
+        """,
+        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.
+
+        This attribute will only work if zope.browsermenu is installed.
+        """,
+        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.
+    """

Deleted: zope.browserpage/tags/3.9.0/src/zope/browserpage/tests.py
===================================================================
--- zope.browserpage/trunk/src/zope/browserpage/tests.py	2009-08-27 14:07:47 UTC (rev 103272)
+++ zope.browserpage/tags/3.9.0/src/zope/browserpage/tests.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -1,961 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""'browser' namespace directive tests
-
-$Id: test_directives.py 103154 2009-08-24 14:45:16Z nadako $
-"""
-
-import sys
-import os
-import unittest
-from cStringIO import StringIO
-
-from zope import component
-from zope.interface import Interface, implements, directlyProvides, providedBy
-
-import zope.security.management
-from zope.configuration.xmlconfig import xmlconfig, XMLConfig
-from zope.configuration.exceptions import ConfigurationError
-from zope.publisher.browser import TestRequest
-from zope.publisher.interfaces import IDefaultViewName
-from zope.publisher.interfaces.browser import IBrowserPublisher
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.publisher.interfaces.browser import IBrowserSkinType, IDefaultSkin
-from zope.security.proxy import removeSecurityProxy, ProxyFactory
-from zope.security.permission import Permission
-from zope.security.interfaces import IPermission
-from zope.testing.doctestunit import DocTestSuite
-from zope.testing import cleanup
-from zope.traversing.adapters import DefaultTraversable
-from zope.traversing.interfaces import ITraversable
-
-import zope.publisher.defaultview
-import zope.browserpage
-import zope.browsermenu
-from zope.browsermenu.menu import getFirstMenuItem
-from zope.browsermenu.interfaces import IMenuItemType
-from zope.component.testfiles.views import IC, V1, VZMI, R1, IV
-
-tests_path = os.path.dirname(__file__)
-
-template = """<configure
-   xmlns='http://namespaces.zope.org/zope'
-   xmlns:browser='http://namespaces.zope.org/browser'
-   i18n_domain='zope'>
-   %s
-   </configure>"""
-
-class templateclass(object):
-    def data(self): return 42
-
-request = TestRequest()
-
-class V2(V1, object):
-
-    def action(self):
-        return self.action2()
-
-    def action2(self):
-        return "done"
-
-class VT(V1, object):
-    def publishTraverse(self, request, name):
-        try:
-            return int(name)
-        except:
-            return super(VT, self).publishTraverse(request, name)
-
-class Ob(object):
-    implements(IC)
-
-ob = Ob()
-
-class NCV(object):
-    "non callable view"
-
-    def __init__(self, context, request):
-        pass
-
-class CV(NCV):
-    "callable view"
-    def __call__(self):
-        pass
-
-
-class C_w_implements(NCV):
-    implements(Interface)
-
-    def index(self):
-        return self
-
-class ITestLayer(IBrowserRequest):
-    """Test Layer."""
-
-class ITestSkin(ITestLayer):
-    """Test Skin."""
-
-
-class ITestMenu(Interface):
-    """Test menu."""
-
-directlyProvides(ITestMenu, IMenuItemType)
-
-class Test(cleanup.CleanUp, unittest.TestCase):
-
-    def setUp(self):
-        super(Test, self).setUp()
-        XMLConfig('meta.zcml', zope.browserpage)()
-        XMLConfig('meta.zcml', zope.browsermenu)()
-        component.provideAdapter(DefaultTraversable, (None,), ITraversable, )
-        zope.security.management.newInteraction()
-
-    def testPage(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-
-        xmlconfig(StringIO(template % (
-            '''
-            <browser:page
-                name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                attribute="index"
-                />
-            '''
-            )))
-
-        v = component.queryMultiAdapter((ob, request), name='test')
-        self.assert_(issubclass(v.__class__, V1))
-
-
-    def testPageWithClassWithMenu(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-        testtemplate = os.path.join(tests_path, 'testfiles', 'test.pt')
-
-
-        xmlconfig(StringIO(template % (
-            '''
-            <browser:menu
-                id="test_menu" title="Test menu" />
-            <browser:page
-                name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                template="%s"
-                menu="test_menu"
-                title="Test View"
-                />
-            ''' % testtemplate
-            )))
-        menuItem = getFirstMenuItem('test_menu', ob, TestRequest())
-        self.assertEqual(menuItem["title"], "Test View")
-        self.assertEqual(menuItem["action"], "@@test")
-        v = component.queryMultiAdapter((ob, request), name='test')
-        self.assertEqual(v(), "<html><body><p>test</p></body></html>\n")
-
-
-    def testPageWithTemplateWithMenu(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-        testtemplate = os.path.join(tests_path, 'testfiles', 'test.pt')
-
-        xmlconfig(StringIO(template % (
-            '''
-            <browser:menu
-                id="test_menu" title="Test menu"/>
-            <browser:page
-                name="test"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                template="%s"
-                menu="test_menu"
-                title="Test View"
-                />
-            ''' % testtemplate
-            )))
-
-        menuItem = getFirstMenuItem('test_menu', ob, TestRequest())
-        self.assertEqual(menuItem["title"], "Test View")
-        self.assertEqual(menuItem["action"], "@@test")
-        v = component.queryMultiAdapter((ob, request), name='test')
-        self.assertEqual(v(), "<html><body><p>test</p></body></html>\n")
-
-
-    def testPageInPagesWithTemplateWithMenu(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-        testtemplate = os.path.join(tests_path, 'testfiles', 'test.pt')
-
-        xmlconfig(StringIO(template % (
-            '''
-            <browser:menu
-                id="test_menu" title="Test menu" />
-            <browser:pages
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public">
-              <browser:page
-                  name="test"
-                  template="%s"
-                  menu="test_menu"
-                  title="Test View"
-                  />
-            </browser:pages>
-            ''' % testtemplate
-            )))
-
-        menuItem = getFirstMenuItem('test_menu', ob, TestRequest())
-        self.assertEqual(menuItem["title"], "Test View")
-        self.assertEqual(menuItem["action"], "@@test")
-        v = component.queryMultiAdapter((ob, request), name='test')
-        self.assertEqual(v(), "<html><body><p>test</p></body></html>\n")
-
-
-    def testPageInPagesWithClassWithMenu(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-        testtemplate = os.path.join(tests_path, 'testfiles', 'test.pt')
-
-        xmlconfig(StringIO(template % (
-            '''
-            <browser:menu
-                id="test_menu" title="Test menu" />
-            <browser:pages
-                for="zope.component.testfiles.views.IC"
-                class="zope.component.testfiles.views.V1"
-                permission="zope.Public">
-              <browser:page
-                  name="test"
-                  template="%s"
-                  menu="test_menu"
-                  title="Test View"
-                  />
-            </browser:pages>
-            ''' % testtemplate
-            )))
-
-        menuItem = getFirstMenuItem('test_menu', ob, TestRequest())
-        self.assertEqual(menuItem["title"], "Test View")
-        self.assertEqual(menuItem["action"], "@@test")
-        v = component.queryMultiAdapter((ob, request), name='test')
-        self.assertEqual(v(), "<html><body><p>test</p></body></html>\n")
-
-    def testSkinPage(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-
-        xmlconfig(StringIO(template % (
-            '''
-            <browser:page name="test"
-                class="zope.component.testfiles.views.VZMI"
-                layer="
-                  zope.browserpage.tests.ITestLayer"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                attribute="index"
-                />
-            <browser:page name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                attribute="index"
-                />
-            '''
-            )))
-
-        v = component.queryMultiAdapter((ob, request), name='test')
-        self.assert_(issubclass(v.__class__, V1))
-        v = component.queryMultiAdapter(
-            (ob, TestRequest(skin=ITestSkin)), name='test')
-        self.assert_(issubclass(v.__class__, VZMI))
-
-
-    def testInterfaceProtectedPage(self):
-        xmlconfig(StringIO(template %
-            '''
-            <browser:page name="test"
-                class="zope.component.testfiles.views.V1"
-                attribute="index"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                allowed_interface="zope.component.testfiles.views.IV"
-                />
-            '''
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='test')
-        v = ProxyFactory(v)
-        self.assertEqual(v.index(), 'V1 here')
-        self.assertRaises(Exception, getattr, v, 'action')
-
-    def testAttributeProtectedPage(self):
-        xmlconfig(StringIO(template %
-            '''
-            <browser:page name="test"
-                class="zope.browserpage.tests.V2"
-                for="zope.component.testfiles.views.IC"
-                attribute="action"
-                permission="zope.Public"
-                allowed_attributes="action2"
-                />
-            '''
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='test')
-        v = ProxyFactory(v)
-        self.assertEqual(v.action(), 'done')
-        self.assertEqual(v.action2(), 'done')
-        self.assertRaises(Exception, getattr, v, 'index')
-
-    def testAttributeProtectedView(self):
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view name="test"
-                class="zope.browserpage.tests.V2"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                allowed_attributes="action2"
-                >
-              <browser:page name="index.html" attribute="action" />
-           </browser:view>
-            '''
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='test')
-        v = ProxyFactory(v)
-        page = v.publishTraverse(request, 'index.html')
-        self.assertEqual(page(), 'done')
-        self.assertEqual(v.action2(), 'done')
-        self.assertRaises(Exception, getattr, page, 'index')
-
-    def testInterfaceAndAttributeProtectedPage(self):
-        xmlconfig(StringIO(template %
-            '''
-            <browser:page name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                attribute="index"
-                allowed_attributes="action"
-                allowed_interface="zope.component.testfiles.views.IV"
-                />
-            '''
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='test')
-        self.assertEqual(v.index(), 'V1 here')
-        self.assertEqual(v.action(), 'done')
-
-    def testDuplicatedInterfaceAndAttributeProtectedPage(self):
-        xmlconfig(StringIO(template %
-            '''
-            <browser:page name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                attribute="index"
-                permission="zope.Public"
-                allowed_attributes="action index"
-                allowed_interface="zope.component.testfiles.views.IV"
-                />
-            '''
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='test')
-        self.assertEqual(v.index(), 'V1 here')
-        self.assertEqual(v.action(), 'done')
-
-    def test_class_w_implements(self):
-        xmlconfig(StringIO(template %
-            '''
-            <browser:page
-                name="test"
-                class="
-             zope.browserpage.tests.C_w_implements"
-                for="zope.component.testfiles.views.IC"
-                attribute="index"
-                permission="zope.Public"
-                />
-            '''
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='test')
-        self.assertEqual(v.index(), v)
-        self.assert_(IBrowserPublisher.providedBy(v))
-
-    def testIncompleteProtectedPageNoPermission(self):
-        self.assertRaises(
-            ConfigurationError,
-            xmlconfig,
-            StringIO(template %
-            '''
-            <browser:page name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                attribute="index"
-                allowed_attributes="action index"
-                />
-            '''
-            ))
-
-
-    def testPageViews(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-        test3 = os.path.join(tests_path, 'testfiles', 'test3.pt')
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:pages
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                >
-
-              <browser:page name="index.html" attribute="index" />
-              <browser:page name="action.html" attribute="action" />
-              <browser:page name="test.html" template="%s" />
-            </browser:pages>
-            ''' % test3
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='index.html')
-        self.assertEqual(v(), 'V1 here')
-        v = component.getMultiAdapter((ob, request), name='action.html')
-        self.assertEqual(v(), 'done')
-        v = component.getMultiAdapter((ob, request), name='test.html')
-        self.assertEqual(str(v()), '<html><body><p>done</p></body></html>\n')
-
-    def testNamedViewPageViewsCustomTraversr(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view
-                name="test"
-                class="zope.browserpage.tests.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                >
-
-              <browser:page name="index.html" attribute="index" />
-              <browser:page name="action.html" attribute="action" />
-            </browser:view>
-            '''
-            ))
-
-        view = component.getMultiAdapter((ob, request), name='test')
-        view = removeSecurityProxy(view)
-        self.assertEqual(view.browserDefault(request)[1], (u'index.html', ))
-
-
-        v = view.publishTraverse(request, 'index.html')
-        v = removeSecurityProxy(v)
-        self.assertEqual(v(), 'V1 here')
-        v = view.publishTraverse(request, 'action.html')
-        v = removeSecurityProxy(v)
-        self.assertEqual(v(), 'done')
-
-
-    def testNamedViewNoPagesForCallable(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view
-                name="test"
-                class="zope.browserpage.tests.CV"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                />
-            '''
-            ))
-
-        view = component.getMultiAdapter((ob, request), name='test')
-        view = removeSecurityProxy(view)
-        self.assertEqual(view.browserDefault(request), (view, ()))
-
-    def testNamedViewNoPagesForNonCallable(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view
-                name="test"
-                class="zope.browserpage.tests.NCV"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                />
-            '''
-            ))
-
-        view = component.getMultiAdapter((ob, request), name='test')
-        view = removeSecurityProxy(view)
-        self.assertEqual(getattr(view, 'browserDefault', None), None)
-
-    def testNamedViewPageViewsNoDefault(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-        test3 = os.path.join(tests_path, 'testfiles', 'test3.pt')
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view
-                name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                >
-
-              <browser:page name="index.html" attribute="index" />
-              <browser:page name="action.html" attribute="action" />
-              <browser:page name="test.html" template="%s" />
-            </browser:view>
-            ''' % test3
-            ))
-
-        view = component.getMultiAdapter((ob, request), name='test')
-        view = removeSecurityProxy(view)
-        self.assertEqual(view.browserDefault(request)[1], (u'index.html', ))
-
-
-        v = view.publishTraverse(request, 'index.html')
-        v = removeSecurityProxy(v)
-        self.assertEqual(v(), 'V1 here')
-        v = view.publishTraverse(request, 'action.html')
-        v = removeSecurityProxy(v)
-        self.assertEqual(v(), 'done')
-        v = view.publishTraverse(request, 'test.html')
-        v = removeSecurityProxy(v)
-        self.assertEqual(str(v()), '<html><body><p>done</p></body></html>\n')
-
-    def testNamedViewPageViewsWithDefault(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-        test3 = os.path.join(tests_path, 'testfiles', 'test3.pt')
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view
-                name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                >
-
-              <browser:defaultPage name="test.html" />
-              <browser:page name="index.html" attribute="index" />
-              <browser:page name="action.html" attribute="action" />
-              <browser:page name="test.html" template="%s" />
-            </browser:view>
-            ''' % test3
-            ))
-
-        view = component.getMultiAdapter((ob, request), name='test')
-        view = removeSecurityProxy(view)
-        self.assertEqual(view.browserDefault(request)[1], (u'test.html', ))
-
-
-        v = view.publishTraverse(request, 'index.html')
-        v = removeSecurityProxy(v)
-        self.assertEqual(v(), 'V1 here')
-        v = view.publishTraverse(request, 'action.html')
-        v = removeSecurityProxy(v)
-        self.assertEqual(v(), 'done')
-        v = view.publishTraverse(request, 'test.html')
-        v = removeSecurityProxy(v)
-        self.assertEqual(str(v()), '<html><body><p>done</p></body></html>\n')
-
-    def testTraversalOfPageForView(self):
-        """Tests proper traversal of a page defined for a view."""
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view
-                name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public" />
-
-            <browser:page name="index.html"
-                for="zope.component.testfiles.views.IV"
-                class="zope.browserpage.tests.CV"
-                permission="zope.Public" />
-            '''
-            ))
-
-        view = component.getMultiAdapter((ob, request), name='test')
-        view = removeSecurityProxy(view)
-        view.publishTraverse(request, 'index.html')
-
-    def testTraversalOfPageForViewWithPublishTraverse(self):
-        """Tests proper traversal of a page defined for a view.
-
-        This test is different from testTraversalOfPageForView in that it
-        tests the behavior on a view that has a publishTraverse method --
-        the implementation of the lookup is slightly different in such a
-        case.
-        """
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view
-                name="test"
-                class="zope.browserpage.tests.VT"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public" />
-
-            <browser:page name="index.html"
-                for="zope.component.testfiles.views.IV"
-                class="zope.browserpage.tests.CV"
-                permission="zope.Public" />
-            '''
-            ))
-
-        view = component.getMultiAdapter((ob, request), name='test')
-        view = removeSecurityProxy(view)
-        view.publishTraverse(request, 'index.html')
-
-    def testProtectedPageViews(self):
-        component.provideUtility(Permission('p', 'P'), IPermission, 'p')
-
-        request = TestRequest()
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <include package="zope.security" file="meta.zcml" />
-
-            <permission id="zope.TestPermission" title="Test permission" />
-
-            <browser:pages
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.TestPermission"
-                >
-
-              <browser:page name="index.html" attribute="index" />
-              <browser:page name="action.html" attribute="action" />
-            </browser:pages>
-            '''
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='index.html')
-        v = ProxyFactory(v)
-        zope.security.management.getInteraction().add(request)
-        self.assertRaises(Exception, v)
-        v = component.getMultiAdapter((ob, request), name='action.html')
-        v = ProxyFactory(v)
-        self.assertRaises(Exception, v)
-
-    def testProtectedNamedViewPageViews(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <include package="zope.security" file="meta.zcml" />
-
-            <permission id="zope.TestPermission" title="Test permission" />
-
-            <browser:view
-                name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                >
-
-              <browser:page name="index.html" attribute="index" />
-              <browser:page name="action.html" attribute="action" />
-            </browser:view>
-            '''
-            ))
-
-        view = component.getMultiAdapter((ob, request), name='test')
-        self.assertEqual(view.browserDefault(request)[1], (u'index.html', ))
-
-        v = view.publishTraverse(request, 'index.html')
-        self.assertEqual(v(), 'V1 here')
-
-    def testSkinnedPageView(self):
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:pages
-                for="*"
-                class="zope.component.testfiles.views.V1"
-                permission="zope.Public"
-                >
-              <browser:page name="index.html" attribute="index" />
-            </browser:pages>
-
-            <browser:pages
-                for="*"
-                class="zope.component.testfiles.views.V1"
-                layer="
-                  zope.browserpage.tests.ITestLayer"
-                permission="zope.Public"
-                >
-              <browser:page name="index.html" attribute="action" />
-            </browser:pages>
-            '''
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='index.html')
-        self.assertEqual(v(), 'V1 here')
-        v = component.getMultiAdapter((ob, TestRequest(skin=ITestSkin)),
-                                 name='index.html')
-        self.assertEqual(v(), 'done')
-
-
-    def test_template_page(self):
-        path = os.path.join(tests_path, 'testfiles', 'test.pt')
-
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='index.html'),
-            None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:page
-                name="index.html"
-                template="%s"
-                permission="zope.Public"
-                for="zope.component.testfiles.views.IC" />
-            ''' % path
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='index.html')
-        self.assertEqual(v().strip(), '<html><body><p>test</p></body></html>')
-
-    def test_page_menu_within_different_layers(self):
-        path = os.path.join(tests_path, 'testfiles', 'test.pt')
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='index.html'),
-            None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:menu
-                id="test_menu"
-                title="Test menu"
-                interface="zope.browserpage.tests.ITestMenu"/>
-
-            <browser:page
-                name="index.html"
-                permission="zope.Public"
-                for="zope.component.testfiles.views.IC"
-                template="%s"
-                menu="test_menu" title="Index"/>
-
-            <browser:page
-                name="index.html"
-                permission="zope.Public"
-                for="zope.component.testfiles.views.IC"
-                menu="test_menu" title="Index"
-                template="%s"
-                layer="zope.browserpage.tests.ITestLayer"/>
-            ''' % (path, path)
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='index.html')
-        self.assertEqual(v().strip(), '<html><body><p>test</p></body></html>')
-
-    def testtemplateWClass(self):
-        path = os.path.join(tests_path, 'testfiles', 'test2.pt')
-
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='index.html'),
-            None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:page
-                name="index.html"
-                template="%s"
-                permission="zope.Public"
-          class="zope.browserpage.tests.templateclass"
-                for="zope.component.testfiles.views.IC" />
-            ''' % path
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='index.html')
-        self.assertEqual(v().strip(), '<html><body><p>42</p></body></html>')
-
-    def testProtectedtemplate(self):
-
-        path = os.path.join(tests_path, 'testfiles', 'test.pt')
-
-        request = TestRequest()
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), name='test'),
-            None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <include package="zope.security" file="meta.zcml" />
-
-            <permission id="zope.TestPermission" title="Test permission" />
-
-            <browser:page
-                name="xxx.html"
-                template="%s"
-                permission="zope.TestPermission"
-                for="zope.component.testfiles.views.IC" />
-            ''' % path
-            ))
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:page
-                name="index.html"
-                template="%s"
-                permission="zope.Public"
-                for="zope.component.testfiles.views.IC" />
-            ''' % path
-            ))
-
-        v = component.getMultiAdapter((ob, request), name='xxx.html')
-        v = ProxyFactory(v)
-        zope.security.management.getInteraction().add(request)
-        self.assertRaises(Exception, v)
-
-        v = component.getMultiAdapter((ob, request), name='index.html')
-        v = ProxyFactory(v)
-        self.assertEqual(v().strip(), '<html><body><p>test</p></body></html>')
-
-
-    def testtemplateNoName(self):
-        path = os.path.join(tests_path, 'testfiles', 'test.pt')
-        self.assertRaises(
-            ConfigurationError,
-            xmlconfig,
-            StringIO(template %
-            '''
-            <browser:page
-                template="%s"
-                for="zope.component.testfiles.views.IC"
-                />
-            ''' % path
-            ))
-
-    def testtemplateAndPage(self):
-        path = os.path.join(tests_path, 'testfiles', 'test.pt')
-        self.assertRaises(
-            ConfigurationError,
-            xmlconfig,
-            StringIO(template %
-            '''
-            <browser:view
-                name="index.html"
-                template="%s"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                >
-              <browser:page name="foo.html" attribute="index" />
-            </browser:view>
-            ''' % path
-            ))
-
-    def testViewThatProvidesAnInterface(self):
-        request = TestRequest()
-        self.assertEqual(
-            component.queryMultiAdapter((ob, request), IV, name='test'), None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view
-                name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                />
-            '''
-            ))
-
-        v = component.queryMultiAdapter((ob, request), IV, name='test')
-        self.assertEqual(v, None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view
-                name="test"
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                provides="zope.component.testfiles.views.IV"
-                permission="zope.Public"
-                />
-            '''
-            ))
-
-        v = component.queryMultiAdapter((ob, request), IV, name='test')
-        self.assert_(isinstance(v, V1))
-
-    def testUnnamedViewThatProvidesAnInterface(self):
-        request = TestRequest()
-        self.assertEqual(component.queryMultiAdapter((ob, request), IV),
-                         None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                permission="zope.Public"
-                />
-            '''
-            ))
-
-        v = component.queryMultiAdapter((ob, request), IV)
-        self.assertEqual(v, None)
-
-        xmlconfig(StringIO(template %
-            '''
-            <browser:view
-                class="zope.component.testfiles.views.V1"
-                for="zope.component.testfiles.views.IC"
-                provides="zope.component.testfiles.views.IV"
-                permission="zope.Public"
-                />
-            '''
-            ))
-
-        v = component.queryMultiAdapter((ob, request), IV)
-
-        self.assert_(isinstance(v, V1))
-
-
-def test_suite():
-    return unittest.makeSuite(Test)

Copied: zope.browserpage/tags/3.9.0/src/zope/browserpage/tests.py (from rev 103273, zope.browserpage/trunk/src/zope/browserpage/tests.py)
===================================================================
--- zope.browserpage/tags/3.9.0/src/zope/browserpage/tests.py	                        (rev 0)
+++ zope.browserpage/tags/3.9.0/src/zope/browserpage/tests.py	2009-08-27 14:16:22 UTC (rev 103274)
@@ -0,0 +1,961 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tests for browser:page directive and friends
+
+$Id$
+"""
+
+import sys
+import os
+import unittest
+from cStringIO import StringIO
+
+from zope import component
+from zope.interface import Interface, implements, directlyProvides, providedBy
+
+import zope.security.management
+from zope.configuration.xmlconfig import xmlconfig, XMLConfig
+from zope.configuration.exceptions import ConfigurationError
+from zope.publisher.browser import TestRequest
+from zope.publisher.interfaces import IDefaultViewName
+from zope.publisher.interfaces.browser import IBrowserPublisher
+from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.publisher.interfaces.browser import IBrowserSkinType, IDefaultSkin
+from zope.security.proxy import removeSecurityProxy, ProxyFactory
+from zope.security.permission import Permission
+from zope.security.interfaces import IPermission
+from zope.testing.doctestunit import DocTestSuite
+from zope.testing import cleanup
+from zope.traversing.adapters import DefaultTraversable
+from zope.traversing.interfaces import ITraversable
+
+import zope.publisher.defaultview
+import zope.browserpage
+import zope.browsermenu
+from zope.browsermenu.menu import getFirstMenuItem
+from zope.browsermenu.interfaces import IMenuItemType
+from zope.component.testfiles.views import IC, V1, VZMI, R1, IV
+
+tests_path = os.path.dirname(__file__)
+
+template = """<configure
+   xmlns='http://namespaces.zope.org/zope'
+   xmlns:browser='http://namespaces.zope.org/browser'
+   i18n_domain='zope'>
+   %s
+   </configure>"""
+
+class templateclass(object):
+    def data(self): return 42
+
+request = TestRequest()
+
+class V2(V1, object):
+
+    def action(self):
+        return self.action2()
+
+    def action2(self):
+        return "done"
+
+class VT(V1, object):
+    def publishTraverse(self, request, name):
+        try:
+            return int(name)
+        except:
+            return super(VT, self).publishTraverse(request, name)
+
+class Ob(object):
+    implements(IC)
+
+ob = Ob()
+
+class NCV(object):
+    "non callable view"
+
+    def __init__(self, context, request):
+        pass
+
+class CV(NCV):
+    "callable view"
+    def __call__(self):
+        pass
+
+
+class C_w_implements(NCV):
+    implements(Interface)
+
+    def index(self):
+        return self
+
+class ITestLayer(IBrowserRequest):
+    """Test Layer."""
+
+class ITestSkin(ITestLayer):
+    """Test Skin."""
+
+
+class ITestMenu(Interface):
+    """Test menu."""
+
+directlyProvides(ITestMenu, IMenuItemType)
+
+class Test(cleanup.CleanUp, unittest.TestCase):
+
+    def setUp(self):
+        super(Test, self).setUp()
+        XMLConfig('meta.zcml', zope.browserpage)()
+        XMLConfig('meta.zcml', zope.browsermenu)()
+        component.provideAdapter(DefaultTraversable, (None,), ITraversable, )
+        zope.security.management.newInteraction()
+
+    def testPage(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+
+        xmlconfig(StringIO(template % (
+            '''
+            <browser:page
+                name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                attribute="index"
+                />
+            '''
+            )))
+
+        v = component.queryMultiAdapter((ob, request), name='test')
+        self.assert_(issubclass(v.__class__, V1))
+
+
+    def testPageWithClassWithMenu(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+        testtemplate = os.path.join(tests_path, 'testfiles', 'test.pt')
+
+
+        xmlconfig(StringIO(template % (
+            '''
+            <browser:menu
+                id="test_menu" title="Test menu" />
+            <browser:page
+                name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                template="%s"
+                menu="test_menu"
+                title="Test View"
+                />
+            ''' % testtemplate
+            )))
+        menuItem = getFirstMenuItem('test_menu', ob, TestRequest())
+        self.assertEqual(menuItem["title"], "Test View")
+        self.assertEqual(menuItem["action"], "@@test")
+        v = component.queryMultiAdapter((ob, request), name='test')
+        self.assertEqual(v(), "<html><body><p>test</p></body></html>\n")
+
+
+    def testPageWithTemplateWithMenu(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+        testtemplate = os.path.join(tests_path, 'testfiles', 'test.pt')
+
+        xmlconfig(StringIO(template % (
+            '''
+            <browser:menu
+                id="test_menu" title="Test menu"/>
+            <browser:page
+                name="test"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                template="%s"
+                menu="test_menu"
+                title="Test View"
+                />
+            ''' % testtemplate
+            )))
+
+        menuItem = getFirstMenuItem('test_menu', ob, TestRequest())
+        self.assertEqual(menuItem["title"], "Test View")
+        self.assertEqual(menuItem["action"], "@@test")
+        v = component.queryMultiAdapter((ob, request), name='test')
+        self.assertEqual(v(), "<html><body><p>test</p></body></html>\n")
+
+
+    def testPageInPagesWithTemplateWithMenu(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+        testtemplate = os.path.join(tests_path, 'testfiles', 'test.pt')
+
+        xmlconfig(StringIO(template % (
+            '''
+            <browser:menu
+                id="test_menu" title="Test menu" />
+            <browser:pages
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public">
+              <browser:page
+                  name="test"
+                  template="%s"
+                  menu="test_menu"
+                  title="Test View"
+                  />
+            </browser:pages>
+            ''' % testtemplate
+            )))
+
+        menuItem = getFirstMenuItem('test_menu', ob, TestRequest())
+        self.assertEqual(menuItem["title"], "Test View")
+        self.assertEqual(menuItem["action"], "@@test")
+        v = component.queryMultiAdapter((ob, request), name='test')
+        self.assertEqual(v(), "<html><body><p>test</p></body></html>\n")
+
+
+    def testPageInPagesWithClassWithMenu(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+        testtemplate = os.path.join(tests_path, 'testfiles', 'test.pt')
+
+        xmlconfig(StringIO(template % (
+            '''
+            <browser:menu
+                id="test_menu" title="Test menu" />
+            <browser:pages
+                for="zope.component.testfiles.views.IC"
+                class="zope.component.testfiles.views.V1"
+                permission="zope.Public">
+              <browser:page
+                  name="test"
+                  template="%s"
+                  menu="test_menu"
+                  title="Test View"
+                  />
+            </browser:pages>
+            ''' % testtemplate
+            )))
+
+        menuItem = getFirstMenuItem('test_menu', ob, TestRequest())
+        self.assertEqual(menuItem["title"], "Test View")
+        self.assertEqual(menuItem["action"], "@@test")
+        v = component.queryMultiAdapter((ob, request), name='test')
+        self.assertEqual(v(), "<html><body><p>test</p></body></html>\n")
+
+    def testSkinPage(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+
+        xmlconfig(StringIO(template % (
+            '''
+            <browser:page name="test"
+                class="zope.component.testfiles.views.VZMI"
+                layer="
+                  zope.browserpage.tests.ITestLayer"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                attribute="index"
+                />
+            <browser:page name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                attribute="index"
+                />
+            '''
+            )))
+
+        v = component.queryMultiAdapter((ob, request), name='test')
+        self.assert_(issubclass(v.__class__, V1))
+        v = component.queryMultiAdapter(
+            (ob, TestRequest(skin=ITestSkin)), name='test')
+        self.assert_(issubclass(v.__class__, VZMI))
+
+
+    def testInterfaceProtectedPage(self):
+        xmlconfig(StringIO(template %
+            '''
+            <browser:page name="test"
+                class="zope.component.testfiles.views.V1"
+                attribute="index"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                allowed_interface="zope.component.testfiles.views.IV"
+                />
+            '''
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='test')
+        v = ProxyFactory(v)
+        self.assertEqual(v.index(), 'V1 here')
+        self.assertRaises(Exception, getattr, v, 'action')
+
+    def testAttributeProtectedPage(self):
+        xmlconfig(StringIO(template %
+            '''
+            <browser:page name="test"
+                class="zope.browserpage.tests.V2"
+                for="zope.component.testfiles.views.IC"
+                attribute="action"
+                permission="zope.Public"
+                allowed_attributes="action2"
+                />
+            '''
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='test')
+        v = ProxyFactory(v)
+        self.assertEqual(v.action(), 'done')
+        self.assertEqual(v.action2(), 'done')
+        self.assertRaises(Exception, getattr, v, 'index')
+
+    def testAttributeProtectedView(self):
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view name="test"
+                class="zope.browserpage.tests.V2"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                allowed_attributes="action2"
+                >
+              <browser:page name="index.html" attribute="action" />
+           </browser:view>
+            '''
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='test')
+        v = ProxyFactory(v)
+        page = v.publishTraverse(request, 'index.html')
+        self.assertEqual(page(), 'done')
+        self.assertEqual(v.action2(), 'done')
+        self.assertRaises(Exception, getattr, page, 'index')
+
+    def testInterfaceAndAttributeProtectedPage(self):
+        xmlconfig(StringIO(template %
+            '''
+            <browser:page name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                attribute="index"
+                allowed_attributes="action"
+                allowed_interface="zope.component.testfiles.views.IV"
+                />
+            '''
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='test')
+        self.assertEqual(v.index(), 'V1 here')
+        self.assertEqual(v.action(), 'done')
+
+    def testDuplicatedInterfaceAndAttributeProtectedPage(self):
+        xmlconfig(StringIO(template %
+            '''
+            <browser:page name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                attribute="index"
+                permission="zope.Public"
+                allowed_attributes="action index"
+                allowed_interface="zope.component.testfiles.views.IV"
+                />
+            '''
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='test')
+        self.assertEqual(v.index(), 'V1 here')
+        self.assertEqual(v.action(), 'done')
+
+    def test_class_w_implements(self):
+        xmlconfig(StringIO(template %
+            '''
+            <browser:page
+                name="test"
+                class="
+             zope.browserpage.tests.C_w_implements"
+                for="zope.component.testfiles.views.IC"
+                attribute="index"
+                permission="zope.Public"
+                />
+            '''
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='test')
+        self.assertEqual(v.index(), v)
+        self.assert_(IBrowserPublisher.providedBy(v))
+
+    def testIncompleteProtectedPageNoPermission(self):
+        self.assertRaises(
+            ConfigurationError,
+            xmlconfig,
+            StringIO(template %
+            '''
+            <browser:page name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                attribute="index"
+                allowed_attributes="action index"
+                />
+            '''
+            ))
+
+
+    def testPageViews(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+        test3 = os.path.join(tests_path, 'testfiles', 'test3.pt')
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:pages
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                >
+
+              <browser:page name="index.html" attribute="index" />
+              <browser:page name="action.html" attribute="action" />
+              <browser:page name="test.html" template="%s" />
+            </browser:pages>
+            ''' % test3
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='index.html')
+        self.assertEqual(v(), 'V1 here')
+        v = component.getMultiAdapter((ob, request), name='action.html')
+        self.assertEqual(v(), 'done')
+        v = component.getMultiAdapter((ob, request), name='test.html')
+        self.assertEqual(str(v()), '<html><body><p>done</p></body></html>\n')
+
+    def testNamedViewPageViewsCustomTraversr(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view
+                name="test"
+                class="zope.browserpage.tests.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                >
+
+              <browser:page name="index.html" attribute="index" />
+              <browser:page name="action.html" attribute="action" />
+            </browser:view>
+            '''
+            ))
+
+        view = component.getMultiAdapter((ob, request), name='test')
+        view = removeSecurityProxy(view)
+        self.assertEqual(view.browserDefault(request)[1], (u'index.html', ))
+
+
+        v = view.publishTraverse(request, 'index.html')
+        v = removeSecurityProxy(v)
+        self.assertEqual(v(), 'V1 here')
+        v = view.publishTraverse(request, 'action.html')
+        v = removeSecurityProxy(v)
+        self.assertEqual(v(), 'done')
+
+
+    def testNamedViewNoPagesForCallable(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view
+                name="test"
+                class="zope.browserpage.tests.CV"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                />
+            '''
+            ))
+
+        view = component.getMultiAdapter((ob, request), name='test')
+        view = removeSecurityProxy(view)
+        self.assertEqual(view.browserDefault(request), (view, ()))
+
+    def testNamedViewNoPagesForNonCallable(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view
+                name="test"
+                class="zope.browserpage.tests.NCV"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                />
+            '''
+            ))
+
+        view = component.getMultiAdapter((ob, request), name='test')
+        view = removeSecurityProxy(view)
+        self.assertEqual(getattr(view, 'browserDefault', None), None)
+
+    def testNamedViewPageViewsNoDefault(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+        test3 = os.path.join(tests_path, 'testfiles', 'test3.pt')
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view
+                name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                >
+
+              <browser:page name="index.html" attribute="index" />
+              <browser:page name="action.html" attribute="action" />
+              <browser:page name="test.html" template="%s" />
+            </browser:view>
+            ''' % test3
+            ))
+
+        view = component.getMultiAdapter((ob, request), name='test')
+        view = removeSecurityProxy(view)
+        self.assertEqual(view.browserDefault(request)[1], (u'index.html', ))
+
+
+        v = view.publishTraverse(request, 'index.html')
+        v = removeSecurityProxy(v)
+        self.assertEqual(v(), 'V1 here')
+        v = view.publishTraverse(request, 'action.html')
+        v = removeSecurityProxy(v)
+        self.assertEqual(v(), 'done')
+        v = view.publishTraverse(request, 'test.html')
+        v = removeSecurityProxy(v)
+        self.assertEqual(str(v()), '<html><body><p>done</p></body></html>\n')
+
+    def testNamedViewPageViewsWithDefault(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+        test3 = os.path.join(tests_path, 'testfiles', 'test3.pt')
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view
+                name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                >
+
+              <browser:defaultPage name="test.html" />
+              <browser:page name="index.html" attribute="index" />
+              <browser:page name="action.html" attribute="action" />
+              <browser:page name="test.html" template="%s" />
+            </browser:view>
+            ''' % test3
+            ))
+
+        view = component.getMultiAdapter((ob, request), name='test')
+        view = removeSecurityProxy(view)
+        self.assertEqual(view.browserDefault(request)[1], (u'test.html', ))
+
+
+        v = view.publishTraverse(request, 'index.html')
+        v = removeSecurityProxy(v)
+        self.assertEqual(v(), 'V1 here')
+        v = view.publishTraverse(request, 'action.html')
+        v = removeSecurityProxy(v)
+        self.assertEqual(v(), 'done')
+        v = view.publishTraverse(request, 'test.html')
+        v = removeSecurityProxy(v)
+        self.assertEqual(str(v()), '<html><body><p>done</p></body></html>\n')
+
+    def testTraversalOfPageForView(self):
+        """Tests proper traversal of a page defined for a view."""
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view
+                name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public" />
+
+            <browser:page name="index.html"
+                for="zope.component.testfiles.views.IV"
+                class="zope.browserpage.tests.CV"
+                permission="zope.Public" />
+            '''
+            ))
+
+        view = component.getMultiAdapter((ob, request), name='test')
+        view = removeSecurityProxy(view)
+        view.publishTraverse(request, 'index.html')
+
+    def testTraversalOfPageForViewWithPublishTraverse(self):
+        """Tests proper traversal of a page defined for a view.
+
+        This test is different from testTraversalOfPageForView in that it
+        tests the behavior on a view that has a publishTraverse method --
+        the implementation of the lookup is slightly different in such a
+        case.
+        """
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view
+                name="test"
+                class="zope.browserpage.tests.VT"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public" />
+
+            <browser:page name="index.html"
+                for="zope.component.testfiles.views.IV"
+                class="zope.browserpage.tests.CV"
+                permission="zope.Public" />
+            '''
+            ))
+
+        view = component.getMultiAdapter((ob, request), name='test')
+        view = removeSecurityProxy(view)
+        view.publishTraverse(request, 'index.html')
+
+    def testProtectedPageViews(self):
+        component.provideUtility(Permission('p', 'P'), IPermission, 'p')
+
+        request = TestRequest()
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <include package="zope.security" file="meta.zcml" />
+
+            <permission id="zope.TestPermission" title="Test permission" />
+
+            <browser:pages
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.TestPermission"
+                >
+
+              <browser:page name="index.html" attribute="index" />
+              <browser:page name="action.html" attribute="action" />
+            </browser:pages>
+            '''
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='index.html')
+        v = ProxyFactory(v)
+        zope.security.management.getInteraction().add(request)
+        self.assertRaises(Exception, v)
+        v = component.getMultiAdapter((ob, request), name='action.html')
+        v = ProxyFactory(v)
+        self.assertRaises(Exception, v)
+
+    def testProtectedNamedViewPageViews(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <include package="zope.security" file="meta.zcml" />
+
+            <permission id="zope.TestPermission" title="Test permission" />
+
+            <browser:view
+                name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                >
+
+              <browser:page name="index.html" attribute="index" />
+              <browser:page name="action.html" attribute="action" />
+            </browser:view>
+            '''
+            ))
+
+        view = component.getMultiAdapter((ob, request), name='test')
+        self.assertEqual(view.browserDefault(request)[1], (u'index.html', ))
+
+        v = view.publishTraverse(request, 'index.html')
+        self.assertEqual(v(), 'V1 here')
+
+    def testSkinnedPageView(self):
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:pages
+                for="*"
+                class="zope.component.testfiles.views.V1"
+                permission="zope.Public"
+                >
+              <browser:page name="index.html" attribute="index" />
+            </browser:pages>
+
+            <browser:pages
+                for="*"
+                class="zope.component.testfiles.views.V1"
+                layer="
+                  zope.browserpage.tests.ITestLayer"
+                permission="zope.Public"
+                >
+              <browser:page name="index.html" attribute="action" />
+            </browser:pages>
+            '''
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='index.html')
+        self.assertEqual(v(), 'V1 here')
+        v = component.getMultiAdapter((ob, TestRequest(skin=ITestSkin)),
+                                 name='index.html')
+        self.assertEqual(v(), 'done')
+
+
+    def test_template_page(self):
+        path = os.path.join(tests_path, 'testfiles', 'test.pt')
+
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='index.html'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:page
+                name="index.html"
+                template="%s"
+                permission="zope.Public"
+                for="zope.component.testfiles.views.IC" />
+            ''' % path
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='index.html')
+        self.assertEqual(v().strip(), '<html><body><p>test</p></body></html>')
+
+    def test_page_menu_within_different_layers(self):
+        path = os.path.join(tests_path, 'testfiles', 'test.pt')
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='index.html'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:menu
+                id="test_menu"
+                title="Test menu"
+                interface="zope.browserpage.tests.ITestMenu"/>
+
+            <browser:page
+                name="index.html"
+                permission="zope.Public"
+                for="zope.component.testfiles.views.IC"
+                template="%s"
+                menu="test_menu" title="Index"/>
+
+            <browser:page
+                name="index.html"
+                permission="zope.Public"
+                for="zope.component.testfiles.views.IC"
+                menu="test_menu" title="Index"
+                template="%s"
+                layer="zope.browserpage.tests.ITestLayer"/>
+            ''' % (path, path)
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='index.html')
+        self.assertEqual(v().strip(), '<html><body><p>test</p></body></html>')
+
+    def testtemplateWClass(self):
+        path = os.path.join(tests_path, 'testfiles', 'test2.pt')
+
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='index.html'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:page
+                name="index.html"
+                template="%s"
+                permission="zope.Public"
+          class="zope.browserpage.tests.templateclass"
+                for="zope.component.testfiles.views.IC" />
+            ''' % path
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='index.html')
+        self.assertEqual(v().strip(), '<html><body><p>42</p></body></html>')
+
+    def testProtectedtemplate(self):
+
+        path = os.path.join(tests_path, 'testfiles', 'test.pt')
+
+        request = TestRequest()
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), name='test'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <include package="zope.security" file="meta.zcml" />
+
+            <permission id="zope.TestPermission" title="Test permission" />
+
+            <browser:page
+                name="xxx.html"
+                template="%s"
+                permission="zope.TestPermission"
+                for="zope.component.testfiles.views.IC" />
+            ''' % path
+            ))
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:page
+                name="index.html"
+                template="%s"
+                permission="zope.Public"
+                for="zope.component.testfiles.views.IC" />
+            ''' % path
+            ))
+
+        v = component.getMultiAdapter((ob, request), name='xxx.html')
+        v = ProxyFactory(v)
+        zope.security.management.getInteraction().add(request)
+        self.assertRaises(Exception, v)
+
+        v = component.getMultiAdapter((ob, request), name='index.html')
+        v = ProxyFactory(v)
+        self.assertEqual(v().strip(), '<html><body><p>test</p></body></html>')
+
+
+    def testtemplateNoName(self):
+        path = os.path.join(tests_path, 'testfiles', 'test.pt')
+        self.assertRaises(
+            ConfigurationError,
+            xmlconfig,
+            StringIO(template %
+            '''
+            <browser:page
+                template="%s"
+                for="zope.component.testfiles.views.IC"
+                />
+            ''' % path
+            ))
+
+    def testtemplateAndPage(self):
+        path = os.path.join(tests_path, 'testfiles', 'test.pt')
+        self.assertRaises(
+            ConfigurationError,
+            xmlconfig,
+            StringIO(template %
+            '''
+            <browser:view
+                name="index.html"
+                template="%s"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                >
+              <browser:page name="foo.html" attribute="index" />
+            </browser:view>
+            ''' % path
+            ))
+
+    def testViewThatProvidesAnInterface(self):
+        request = TestRequest()
+        self.assertEqual(
+            component.queryMultiAdapter((ob, request), IV, name='test'), None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view
+                name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                />
+            '''
+            ))
+
+        v = component.queryMultiAdapter((ob, request), IV, name='test')
+        self.assertEqual(v, None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view
+                name="test"
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                provides="zope.component.testfiles.views.IV"
+                permission="zope.Public"
+                />
+            '''
+            ))
+
+        v = component.queryMultiAdapter((ob, request), IV, name='test')
+        self.assert_(isinstance(v, V1))
+
+    def testUnnamedViewThatProvidesAnInterface(self):
+        request = TestRequest()
+        self.assertEqual(component.queryMultiAdapter((ob, request), IV),
+                         None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                permission="zope.Public"
+                />
+            '''
+            ))
+
+        v = component.queryMultiAdapter((ob, request), IV)
+        self.assertEqual(v, None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:view
+                class="zope.component.testfiles.views.V1"
+                for="zope.component.testfiles.views.IC"
+                provides="zope.component.testfiles.views.IV"
+                permission="zope.Public"
+                />
+            '''
+            ))
+
+        v = component.queryMultiAdapter((ob, request), IV)
+
+        self.assert_(isinstance(v, V1))
+
+
+def test_suite():
+    return unittest.makeSuite(Test)



More information about the Checkins mailing list