[Checkins] SVN: zope.browserzcml2/trunk/src/zope/browserzcml2/
Implement basic directive schemas and the directive handlers
for browser2:page
Philipp von Weitershausen
philikon at philikon.de
Fri Apr 21 13:23:08 EDT 2006
Log message for revision 67232:
Implement basic directive schemas and the directive handlers for browser2:page
and browser2:pageTemplate.
Changed:
A zope.browserzcml2/trunk/src/zope/browserzcml2/README.txt
A zope.browserzcml2/trunk/src/zope/browserzcml2/browserzcml2-meta.zcml
A zope.browserzcml2/trunk/src/zope/browserzcml2/interfaces.py
A zope.browserzcml2/trunk/src/zope/browserzcml2/meta.zcml
A zope.browserzcml2/trunk/src/zope/browserzcml2/test.pt
A zope.browserzcml2/trunk/src/zope/browserzcml2/tests.py
A zope.browserzcml2/trunk/src/zope/browserzcml2/zcml.py
-=-
Added: zope.browserzcml2/trunk/src/zope/browserzcml2/README.txt
===================================================================
--- zope.browserzcml2/trunk/src/zope/browserzcml2/README.txt 2006-04-21 16:43:55 UTC (rev 67231)
+++ zope.browserzcml2/trunk/src/zope/browserzcml2/README.txt 2006-04-21 17:23:03 UTC (rev 67232)
@@ -0,0 +1,192 @@
+zope.browserzcml2
+=================
+
+This package provides a few ZCML directives to register a browser
+pages in a much less magical way. The rationale behind this is that
+pages implemented in Python should themselves be fully operational, in
+other words, publishable as registered adapters. These directives are
+all part of the ``http://namespaces.zope.org/browser2`` namespace.
+
+In the following we will discuss three major use cases involving
+browser pages for which this package provides three ZCML directives:
+
+ * ``browser2:page``
+
+ * ``browser2:pageTemplate``
+
+ * ``browser2:pagesFromClass``
+
+
+Pages
+-----
+
+A browser page is nothing but a (browser) view that is *publishable*.
+Publishable means that it is basically the last piece in the traversal
+chain and the object that is responsible for the request. It will be
+published. Hence, it has to be publishable. Publishability is
+determined by the ``IBrowerPublisher`` interface. All pages should
+provide it.
+
+Simple page
+~~~~~~~~~~~
+
+Let's create a simple page. For convenience, we can inherit from
+``zope.formlib.Page`` which will give us ``IBrowserPublisher``
+conformance:
+
+ >>> import zope.formlib
+ >>> class MacGyverPage(zope.formlib.Page):
+ ... def __call__(self):
+ ... return u"I've got a Swiss Army knife"
+
+Now we register the page. This works almost like registering an
+adapter:
+
+ >>> run_config("""
+ ... <browser2:page
+ ... for="*"
+ ... name="simplepage.html"
+ ... factory="zope.browserzcml2.README.MacGyverPage"
+ ... permission="zope.Public"
+ ... />
+ ... """)
+
+Then we can look up the page as an adapter. We'll use a test request
+and a stub object.
+
+ >>> import zope.component
+ >>> from zope.publisher.browser import TestRequest
+ >>> request = TestRequest()
+ >>> page = zope.component.getMultiAdapter((object(), request),
+ ... name=u'simplepage.html')
+
+We see that the adapter is an instance of our page class above and
+that we get the expected result upon calling it.
+
+ >>> page #doctest: +ELLIPSIS
+ <zope.browserzcml2.README.MacGyverPage object at ...>
+ >>> page()
+ u"I've got a Swiss Army knife"
+
+Other factories
+~~~~~~~~~~~~~~~
+
+Note that we require the page factory to implement
+``IBrowserPublisher``. Something else won't work, e.g.:
+
+ >>> from zope.app.publisher.browser import BrowserView
+ >>> class MacGyverView(BrowserView):
+ ... def __call__(self):
+ ... return u"I drive a Jeep"
+
+ >>> run_config("""
+ ... <browser2:page
+ ... for="*"
+ ... name="justaview.html"
+ ... factory="zope.browserzcml2.README.MacGyverView"
+ ... permission="zope.Public"
+ ... />
+ ... """) # doctest: +NORMALIZE_WHITESPACE
+ Traceback (most recent call last):
+ ...
+ ZopeXMLConfigurationError: File "<string>", line 6.0-11.6
+ ConfigurationError: The browser page factory needs to provide
+ IBrowserPublisher. A convenient base class is zope.formlib.Page.
+
+It is, however, absolutely possible that the supplied factory isn't in
+fact a class. As long as it implements ``IBrowserPublisher``, it's
+ok:
+
+ >>> import zope.interface
+ >>> from zope.publisher.interfaces.browser import IBrowserPublisher
+ >>> @zope.interface.implementer(IBrowserPublisher)
+ ... def makeAMacGyverPage(context, request):
+ ... return MacGyverPage(context, request)
+
+ >>> run_config("""
+ ... <browser2:page
+ ... for="*"
+ ... name="functionfactory.html"
+ ... factory="zope.browserzcml2.README.makeAMacGyverPage"
+ ... permission="zope.Public"
+ ... />
+ ... """)
+
+ >>> page = zope.component.getMultiAdapter((object(), request),
+ ... name=u'functionfactory.html')
+ >>> page #doctest: +ELLIPSIS
+ <zope.browserzcml2.README.MacGyverPage object at ...>
+ >>> page()
+ u"I've got a Swiss Army knife"
+
+Page with page template
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Rendering HTML from Python is tedious. We therefore often turn this
+work over to Page Templates. Referring to a Page Template in a page
+is easy:
+
+ >>> from zope.app.pagetemplate import ViewPageTemplateFile
+ >>> class MacGyverTemplatePage(zope.formlib.Page):
+ ... __call__ = ViewPageTemplateFile('test.pt')
+
+The rest works just like with a pure-Python browser page:
+
+ >>> run_config("""
+ ... <browser2:page
+ ... for="*"
+ ... name="templatepage.html"
+ ... factory="zope.browserzcml2.README.MacGyverTemplatePage"
+ ... permission="zope.Public"
+ ... />
+ ... """)
+
+ >>> page = zope.component.getMultiAdapter((object(), request),
+ ... name=u'templatepage.html')
+ >>> page #doctest: +ELLIPSIS
+ <zope.browserzcml2.README.MacGyverTemplatePage object at ...>
+ >>> page()
+ u"Hi, the name's MacGyver.\n"
+
+
+Pages from Page Templates
+-------------------------
+
+We've just seen how to create pages that use Page Templates for
+rendering. If that's all a page does, we can use a shortcut provided
+by the ``browser2:pageTemplate`` directive. It works almost like the
+``browser2:page`` directive, except that it takes a ``template``
+parameter, not a ``factory`` parameter:
+
+ >>> run_config("""
+ ... <browser2:pageTemplate
+ ... for="*"
+ ... name="pagetemplate.html"
+ ... template="test.pt"
+ ... permission="zope.Public"
+ ... />
+ ... """)
+
+We can look up the page like the others before, except now it won't be
+an instance of a class that we've implemented. It'll be a dynamically
+generated class. Either way, we are still able to call it like any
+other browser page:
+
+ >>> page = zope.component.getMultiAdapter((object(), request),
+ ... name=u'pagetemplate.html')
+ >>> page #doctest: +ELLIPSIS
+ <zope.browserzcml2.zcml.TemplatePage object at ...>
+ >>> page()
+ u"Hi, the name's MacGyver.\n"
+
+
+Pages from classes
+------------------
+
+XXX
+
+
+Conflicts
+---------
+
+XXX
Property changes on: zope.browserzcml2/trunk/src/zope/browserzcml2/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zope.browserzcml2/trunk/src/zope/browserzcml2/browserzcml2-meta.zcml
===================================================================
--- zope.browserzcml2/trunk/src/zope/browserzcml2/browserzcml2-meta.zcml 2006-04-21 16:43:55 UTC (rev 67231)
+++ zope.browserzcml2/trunk/src/zope/browserzcml2/browserzcml2-meta.zcml 2006-04-21 17:23:03 UTC (rev 67232)
@@ -0,0 +1 @@
+<include package="zope.browserzcml2" file="meta.zcml" />
\ No newline at end of file
Property changes on: zope.browserzcml2/trunk/src/zope/browserzcml2/browserzcml2-meta.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zope.browserzcml2/trunk/src/zope/browserzcml2/interfaces.py
===================================================================
--- zope.browserzcml2/trunk/src/zope/browserzcml2/interfaces.py 2006-04-21 16:43:55 UTC (rev 67231)
+++ zope.browserzcml2/trunk/src/zope/browserzcml2/interfaces.py 2006-04-21 17:23:03 UTC (rev 67232)
@@ -0,0 +1,70 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Common parameters for browser directives
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import zope.interface
+import zope.configuration.fields
+import zope.schema
+import zope.i18nmessageid
+_ = zope.i18nmessageid.MessageFactory('zope')
+
+from zope.app.publisher.browser.fields import MenuField
+from zope.app.security.fields import Permission
+
+class IViewCharacteristics(zope.interface.Interface):
+
+ for_ = zope.configuration.fields.GlobalObject(
+ title=_(u'Registered for'),
+ description=_(u"The interface or class this view is for."),
+ required=False
+ )
+
+ layer = zope.configuration.fields.GlobalInterface(
+ title=_('Layer'),
+ description=_("""Layer that the view is registered for.
+ This defaults to IDefaultBrowserLayer."""),
+ required=False,
+ )
+
+ name = zope.schema.TextLine(
+ title=_(u'Name'),
+ description=_(u"""The name of a view, which will show up e.g. in
+ URLs and other paths."""),
+ required=True
+ )
+
+ permission = Permission(
+ title=_(u'Permission'),
+ description=_(u"The permission needed to use the view."),
+ required=True
+ )
+
+class IRegisterInMenu(zope.interface.Interface):
+
+ menu = MenuField(
+ title=_(u'Menu'),
+ description=_(u"A browser menu to include the page in."),
+ required=False
+ )
+
+ title = zope.configuration.fields.MessageID(
+ title=_(u'Menu label'),
+ description=_(u"""The browser menu label for the page. Must be
+ supplied when the 'menu' attribute is supplied."""),
+ required=False
+ )
Property changes on: zope.browserzcml2/trunk/src/zope/browserzcml2/interfaces.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zope.browserzcml2/trunk/src/zope/browserzcml2/meta.zcml
===================================================================
--- zope.browserzcml2/trunk/src/zope/browserzcml2/meta.zcml 2006-04-21 16:43:55 UTC (rev 67231)
+++ zope.browserzcml2/trunk/src/zope/browserzcml2/meta.zcml 2006-04-21 17:23:03 UTC (rev 67232)
@@ -0,0 +1,21 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:meta="http://namespaces.zope.org/meta">
+
+ <meta:directives namespace="http://namespaces.zope.org/browser2">
+
+ <meta:directive
+ name="pageTemplate"
+ schema=".zcml.IPageTemplateDirective"
+ handler=".zcml.pageTemplate"
+ />
+
+ <meta:directive
+ name="page"
+ schema=".zcml.IPageDirective"
+ handler=".zcml.page"
+ />
+
+ </meta:directives>
+
+</configure>
Property changes on: zope.browserzcml2/trunk/src/zope/browserzcml2/meta.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zope.browserzcml2/trunk/src/zope/browserzcml2/test.pt
===================================================================
--- zope.browserzcml2/trunk/src/zope/browserzcml2/test.pt 2006-04-21 16:43:55 UTC (rev 67231)
+++ zope.browserzcml2/trunk/src/zope/browserzcml2/test.pt 2006-04-21 17:23:03 UTC (rev 67232)
@@ -0,0 +1 @@
+Hi, the name's MacGyver.
\ No newline at end of file
Property changes on: zope.browserzcml2/trunk/src/zope/browserzcml2/test.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zope.browserzcml2/trunk/src/zope/browserzcml2/tests.py
===================================================================
--- zope.browserzcml2/trunk/src/zope/browserzcml2/tests.py 2006-04-21 16:43:55 UTC (rev 67231)
+++ zope.browserzcml2/trunk/src/zope/browserzcml2/tests.py 2006-04-21 17:23:03 UTC (rev 67232)
@@ -0,0 +1,59 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Tests
+
+$Id$
+"""
+import unittest
+from StringIO import StringIO
+
+import zope.browserzcml2
+import zope.component.testing
+from zope.testing import doctest, module
+from zope.configuration import xmlconfig
+
+__docformat__ = "reStructuredText"
+
+def run_config(snippet):
+ global _context
+ template = """\
+ <configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser2="http://namespaces.zope.org/browser2"
+ >
+ %s
+ </configure>"""
+ xmlconfig.string(template % snippet, _context)
+
+_context = None
+def setUp(test):
+ global _context
+ _context = xmlconfig.file('meta.zcml', zope.browserzcml2)
+ test.globs['run_config'] = run_config
+ module.setUp(test, 'zope.browserzcml2.README')
+ zope.component.testing.setUp(test)
+
+def tearDown(test):
+ global _context
+ _context = None
+ module.tearDown(test)
+ zope.component.testing.tearDown(test)
+
+def test_suite():
+ return unittest.TestSuite([
+ doctest.DocFileSuite('README.txt', setUp=setUp, tearDown=tearDown)
+ ])
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: zope.browserzcml2/trunk/src/zope/browserzcml2/tests.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zope.browserzcml2/trunk/src/zope/browserzcml2/zcml.py
===================================================================
--- zope.browserzcml2/trunk/src/zope/browserzcml2/zcml.py 2006-04-21 16:43:55 UTC (rev 67231)
+++ zope.browserzcml2/trunk/src/zope/browserzcml2/zcml.py 2006-04-21 17:23:03 UTC (rev 67232)
@@ -0,0 +1,105 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""ZCML directives and their handlers
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import zope.configuration.fields
+import zope.configuration.exceptions
+import zope.formlib
+import zope.i18nmessageid
+_ = zope.i18nmessageid.MessageFactory('zope')
+
+from zope.publisher.interfaces.browser import IBrowserPublisher
+from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+from zope.browserzcml2.interfaces import IViewCharacteristics
+from zope.browserzcml2.interfaces import IRegisterInMenu
+
+from zope.app.publisher.browser.viewmeta import _handle_menu
+from zope.app.pagetemplate import ViewPageTemplateFile
+from zope.app.component.metaconfigure import adapter
+
+class IPageTemplateDirective(IViewCharacteristics, IRegisterInMenu):
+
+ template = zope.configuration.fields.Path(
+ title=_(u"Template"),
+ description=_(u"""
+ Refers to a file containing a page template (should end in
+ extension '.pt' or '.html')."""),
+ required=True
+ )
+
+def pageTemplate(
+ _context, template, # IPageTemplateDirective
+ for_, name, permission, layer=IDefaultBrowserLayer, # IViewCharacteristics
+ menu=None, title=None): # IRegisterInMenu
+
+ class TemplatePage(zope.formlib.Page):
+ __call__ = ViewPageTemplateFile(template)
+
+ page(_context, TemplatePage,
+ for_, name, permission, layer,
+ menu, title)
+
+class IPageDirective(IViewCharacteristics, IRegisterInMenu):
+ """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.
+ """
+
+ factory = zope.configuration.fields.GlobalObject(
+ title=_(u"Factory"),
+ description=_(u"Adapter factory that returns the browser page. "
+ "It should implement IBrowserPublisher."),
+ required=True,
+ )
+
+def page(
+ _context, factory, # IPageDirective
+ for_, name, permission, layer=IDefaultBrowserLayer, # IViewCharacteristics
+ menu=None, title=None): # IRegisterInMenu
+ if not IBrowserPublisher.implementedBy(factory):
+ raise zope.configuration.exceptions.ConfigurationError(
+ "The browser page factory needs to provide IBrowserPublisher. "
+ "A convenient base class is zope.formlib.Page."
+ )
+ adapter(_context,
+ factory=(factory,),
+ for_=(for_, layer),
+ provides=IBrowserPublisher,
+ permission=permission,
+ name=name)
+
+ _handle_menu(_context, menu, title, (for_,), name, permission, layer)
+
+class IPagesFromClassDirective(IViewCharacteristics):
+ """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.
+ """
+
+ class_ = zope.configuration.fields.GlobalObject(
+ title=_(u"Class"),
+ description=_(u"A class from which one or more browser pages will "
+ "be dynamically created and registered"),
+ required=False,
+ )
+
+# XXX PagesFromClass
Property changes on: zope.browserzcml2/trunk/src/zope/browserzcml2/zcml.py
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the Checkins
mailing list