[Checkins] SVN: plone.z3cform/trunk/ * Split traversal tests for Zope2.10, not all traversal functionality is

Laurence Rowe l at lrowe.co.uk
Tue May 3 16:13:01 EDT 2011


Log message for revision 121528:
  * Split traversal tests for Zope2.10, not all traversal functionality is
    supported on Zope 2.10 and different errors are raised.
  

Changed:
  U   plone.z3cform/trunk/docs/HISTORY.txt
  U   plone.z3cform/trunk/plone/z3cform/tests.py
  A   plone.z3cform/trunk/plone/z3cform/zope210traversal.txt

-=-
Modified: plone.z3cform/trunk/docs/HISTORY.txt
===================================================================
--- plone.z3cform/trunk/docs/HISTORY.txt	2011-05-03 19:37:28 UTC (rev 121527)
+++ plone.z3cform/trunk/docs/HISTORY.txt	2011-05-03 20:13:01 UTC (rev 121528)
@@ -4,6 +4,10 @@
 0.7.5 - unreleased
 ------------------
 
+* Split traversal tests for Zope2.10, not all traversal functionality is
+  supported on Zope 2.10 and different errors are raised.
+  [elro]
+
 * Revert [120798] as it breaks on Zope2.10 / Plone 3.3. We can deal with Zope
   2.14 in 0.8.x.
   [elro]

Modified: plone.z3cform/trunk/plone/z3cform/tests.py
===================================================================
--- plone.z3cform/trunk/plone/z3cform/tests.py	2011-05-03 19:37:28 UTC (rev 121527)
+++ plone.z3cform/trunk/plone/z3cform/tests.py	2011-05-03 20:13:01 UTC (rev 121528)
@@ -1,4 +1,5 @@
 import os
+import sys
 import doctest
 import unittest
 
@@ -70,8 +71,14 @@
     fieldsets_txt = doctest.DocFileSuite('fieldsets/README.txt')
     fieldsets_txt.layer = testing_zcml_layer
 
-    traversal_txt = doctest.DocFileSuite('traversal.txt')
-    traversal_txt.layer = testing_zcml_layer
+    if sys.version_info[:2] == (2, 4):
+        # Zope 2.10 raises TraversalError instead of LocationError
+        # and some more advanced functionality breaks.
+        traversal_txt = doctest.DocFileSuite('zope210traversal.txt')
+        traversal_txt.layer = testing_zcml_layer
+    else:
+        traversal_txt = doctest.DocFileSuite('traversal.txt')
+        traversal_txt.layer = testing_zcml_layer        
 
     return unittest.TestSuite([
         layout_txt, inputs_txt, fieldsets_txt, traversal_txt,

Copied: plone.z3cform/trunk/plone/z3cform/zope210traversal.txt (from rev 120505, plone.z3cform/trunk/plone/z3cform/traversal.txt)
===================================================================
--- plone.z3cform/trunk/plone/z3cform/zope210traversal.txt	                        (rev 0)
+++ plone.z3cform/trunk/plone/z3cform/zope210traversal.txt	2011-05-03 20:13:01 UTC (rev 121528)
@@ -0,0 +1,169 @@
+Traversal
+=========
+
+plone.z3cform allows you to traverse to a widget using the ++widget++
+namespace adapter on a form wrapper view or standalone form view.
+
+Note that widgets may need to mix in Acquisition.Explicit to be truly
+traversable in Zope 2.10. In Zope 2.12, that is not required. However, you
+may get an error if you mix in Explicit in Zope 2.12 and the parent view
+(normally the form or the form layout wrapper) does not, as is likely to be
+the case. To be compatible with both Zope 2.10 and 2.12, you'll need to
+mix in Acquisition.Explicit, but make sure the widget does *not* provide the
+IAcquirer interface. One way to do that is by using implementsOnly(), e.g.::
+    
+    class MyWidget(Aquisition.Explicit):
+        implementsOnly(IMyWidget)
+        
+        ...
+
+If you are only targeting Zope 2.12 and later, you can avoid mixing in any
+kind of acquisition altogether.
+
+The ++widget++ namespace works both in the case of a layout wrapper view,
+and in the case of a form used directly (in Zope 2.12 or later).
+
+Traversal on a standalone form
+------------------------------
+
+First, we create a simple form and context.
+
+    >>> from zope.interface import alsoProvides
+    >>> from zope.publisher.browser import TestRequest
+    >>> from zope.annotation.interfaces import IAttributeAnnotatable
+    >>> from z3c.form.interfaces import IFormLayer
+
+    >>> def make_request(form={}):
+    ...     request = TestRequest()
+    ...     request.form.update(form)
+    ...     alsoProvides(request, IFormLayer)
+    ...     alsoProvides(request, IAttributeAnnotatable)
+    ...     return request
+
+    >>> from zope import interface, schema
+    >>> from z3c.form import form, field, button
+
+    >>> class MySchema(interface.Interface):
+    ...     age = schema.Int(title=u"Age")
+
+    >>> from z3c.form.interfaces import IFieldsForm
+    >>> from zope.interface import implements
+    >>> class MyForm(form.Form):
+    ...     implements(IFieldsForm)
+    ...     fields = field.Fields(MySchema)
+    ...     ignoreContext = True # don't use context to get widget data
+    ...     
+    ...     def update(self):
+    ...         print "Updating test form"
+    ...         super(MyForm, self).update()
+
+    >>> from zope.component import provideAdapter
+    >>> from zope.publisher.interfaces.browser import IBrowserRequest
+    >>> from zope.interface import Interface
+
+    >>> provideAdapter(adapts=(Interface, IBrowserRequest),
+    ...                provides=Interface,
+    ...                factory=MyForm,
+    ...                name=u"test-form")
+
+    >>> from Acquisition import Implicit
+    >>> class Bar(Implicit):
+    ...     __allow_access_to_unprotected_subobjects__ = 1
+    ...     implements(Interface)
+
+    >>> from zope.component import getMultiAdapter
+    >>> context = Bar()
+    >>> request = make_request()
+
+Now, let's emulate the publisher and look up the namespace traversal
+adapter. For example, let's say we'd traversed to
+../@@test-form/++widget++age. The publisher would then do:
+
+    >>> form = getMultiAdapter((context, request), name=u"test-form")
+
+    >>> from zope.traversing.interfaces import ITraversable
+    >>> traverser = getMultiAdapter((form, request), name=u"widget")
+    >>> traverser.traverse('age', [])
+    Updating test form
+    <TextWidget 'form.widgets.age'>
+
+Please note that this point, the form has been updated, but not rendered.
+
+Traversal on a layout wrapper view
+-----------------------------------
+
+Again, we create a simple form and context.
+
+    >>> from zope.interface import alsoProvides
+    >>> from zope.publisher.browser import TestRequest
+    >>> from zope.annotation.interfaces import IAttributeAnnotatable
+    >>> from z3c.form.interfaces import IFormLayer
+
+    >>> def make_request(form={}):
+    ...     request = TestRequest()
+    ...     request.form.update(form)
+    ...     alsoProvides(request, IFormLayer)
+    ...     alsoProvides(request, IAttributeAnnotatable)
+    ...     return request
+
+    >>> from zope import interface, schema
+    >>> from z3c.form import form, field, button
+    >>> from plone.z3cform.layout import FormWrapper
+
+    >>> class MySchema(interface.Interface):
+    ...     age = schema.Int(title=u"Age")
+
+    >>> from z3c.form.interfaces import IFieldsForm
+    >>> from zope.interface import implements
+    >>> class MyForm(form.Form):
+    ...     implements(IFieldsForm)
+    ...     fields = field.Fields(MySchema)
+    ...     ignoreContext = True # don't use context to get widget data
+    ...     
+    ...     def update(self):
+    ...         print "Updating test form"
+    ...         super(MyForm, self).update()
+
+    >>> class MyFormWrapper(FormWrapper):
+    ...     form = MyForm
+    ...     label = u"Please enter your age"
+
+    >>> from zope.component import provideAdapter
+    >>> from zope.publisher.interfaces.browser import IBrowserRequest
+    >>> from zope.interface import Interface
+
+    >>> provideAdapter(adapts=(Interface, IBrowserRequest),
+    ...                provides=Interface,
+    ...                factory=MyFormWrapper,
+    ...                name=u"test-form")
+
+    >>> from Acquisition import Implicit
+    >>> class Bar(Implicit):
+    ...     __allow_access_to_unprotected_subobjects__ = 1
+    ...     implements(Interface)
+
+    >>> from zope.component import getMultiAdapter
+    >>> context = Bar()
+    >>> request = make_request()
+
+Now, let's emulate the publisher and look up the namespace traversal
+adapter. For example, let's say we'd traversed to
+../@@test-form/++widget++age. The publisher would then do:
+
+    >>> form = getMultiAdapter((context, request), name=u"test-form")
+
+    >>> from zope.traversing.interfaces import ITraversable
+    >>> traverser = getMultiAdapter((form, request), name=u"widget")
+    >>> traverser.traverse('age', [])
+    Updating test form
+    <TextWidget 'form.widgets.age'>
+
+Please note that this point, the form has been updated, but not rendered.
+
+When a form field does not exist a TraversalError is raised.
+
+    >>> traverser = getMultiAdapter((form, request), name=u"widget")
+    >>> traverser.traverse('missing', [])
+    Traceback (most recent call last):
+    ...
+    TraversalError: 'missing'



More information about the checkins mailing list