[Zope-Checkins] SVN: Products.Five/branches/1.3/ Backporting ree's
fix to 1.3 branch
Alec Mitchell
apm13 at columbia.edu
Tue Aug 29 10:48:03 EDT 2006
Log message for revision 69843:
Backporting ree's fix to 1.3 branch
Changed:
U Products.Five/branches/1.3/CHANGES.txt
U Products.Five/branches/1.3/browser/metaconfigure.py
A Products.Five/branches/1.3/browser/tests/classes.py
U Products.Five/branches/1.3/browser/tests/test_defaultview.py
-=-
Modified: Products.Five/branches/1.3/CHANGES.txt
===================================================================
--- Products.Five/branches/1.3/CHANGES.txt 2006-08-29 14:47:07 UTC (rev 69842)
+++ Products.Five/branches/1.3/CHANGES.txt 2006-08-29 14:48:01 UTC (rev 69843)
@@ -8,6 +8,10 @@
Bugfixes
--------
+* Made the __call__ method of ViewMixinForAttributes have the same signature
+ as the original attribute. This aids some pathological request parameter
+ marshalling.
+
* Allow multiple uses of the <class>/<content> directive.
* Fix problem with WebDAV/HEAD requests due to new traversal order.
Modified: Products.Five/branches/1.3/browser/metaconfigure.py
===================================================================
--- Products.Five/branches/1.3/browser/metaconfigure.py 2006-08-29 14:47:07 UTC (rev 69842)
+++ Products.Five/branches/1.3/browser/metaconfigure.py 2006-08-29 14:48:01 UTC (rev 69843)
@@ -382,10 +382,7 @@
# this is technically not needed because ZPublisher finds our
# attribute through __browser_default__; but we also want to be
# able to call pages from python modules, PythonScripts or ZPT
- def __call__(self, *args, **kw):
- attr = self.__page_attribute__
- meth = getattr(self, attr)
- return meth(*args, **kw)
+ __call__ = property(lambda self: getattr(self, self.__page_attribute__))
class ViewMixinForTemplates(BrowserView):
Added: Products.Five/branches/1.3/browser/tests/classes.py
===================================================================
--- Products.Five/branches/1.3/browser/tests/classes.py 2006-08-29 14:47:07 UTC (rev 69842)
+++ Products.Five/branches/1.3/browser/tests/classes.py 2006-08-29 14:48:01 UTC (rev 69843)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Test fixtures
+"""
+from zope.interface import Interface, implements
+from Products.Five import BrowserView
+
+class IOne(Interface):
+ """This is a Zope 3 interface.
+ """
+
+class One(object):
+ 'A class'
+ implements(IOne)
+
+class ViewOne(BrowserView):
+ 'Yet another class'
+
+ def my_method(self, arg1, arg2, kw1=None, kw2='D'):
+ print "CALLED %s %s %s %s" % (arg1, arg2, kw1, kw2)
Modified: Products.Five/branches/1.3/browser/tests/test_defaultview.py
===================================================================
--- Products.Five/branches/1.3/browser/tests/test_defaultview.py 2006-08-29 14:47:07 UTC (rev 69842)
+++ Products.Five/branches/1.3/browser/tests/test_defaultview.py 2006-08-29 14:48:01 UTC (rev 69843)
@@ -83,6 +83,98 @@
>>> tearDown()
"""
+def test_default_method_args_marshalling():
+ """\
+ Test the default call method of a view, with respect to possible
+ breakage of argument marshalling from other components
+
+ This is not directly a bug in Five, just a change that enables
+ components have simpler code to imitate ZPublisher's arguments
+ marshalling strategy on default view methods.
+
+ The ZPublisher marshalls arguments to called methods from the
+ request based on the method's signature. This however assumes
+ that it finds the real callable method. However in case of the
+ autogenerated __call__ method of a view, the real method is
+ wrapped. Although the publisher correctly handles this by
+ looking at the __browser_default__ and applying the request on
+ the real method, Plone's portal factory does not do this
+ correctly, thus causing these method calls fail with TypeError,
+ since no parameters will be marshalled to the browser default
+ methods if within the portal factory.
+
+ The applied fix changes the __call__ in such a way that it is
+ not wrapper any more, but yields the original callable instead.
+ This test simply checks that this is so, in other words this is
+ a check that would have failed with the original version.
+
+ First, we load the configuration file:
+
+ >>> import Products.Five.tests
+ >>> from Products.Five import zcml
+ >>> zcml.load_config('meta.zcml', Products.Five)
+ >>> zcml.load_config("permissions.zcml", Products.Five)
+ >>> zcml.load_config('directives.zcml', Products.Five.tests)
+
+ Define a view, with a single attribute and the name of the view
+ is the same as the attribute. Important is that we will use the
+ default browser view.
+
+ >>> zcml.load_string('''
+ ... <configure xmlns="http://namespaces.zope.org/zope"
+ ... xmlns:browser="http://namespaces.zope.org/browser">
+ ... <browser:page
+ ... for="Products.Five.browser.tests.classes.IOne"
+ ... class="Products.Five.browser.tests.classes.ViewOne"
+ ... attribute="my_method"
+ ... name="my_method"
+ ... permission="zope2.Public"
+ ... />
+ ... </configure>
+ ... ''')
+
+ Create a context object and a request. Provide parameters on the
+ request.
+
+ >>> from Products.Five.browser.tests.classes import One
+ >>> context = One()
+ >>> from zope.publisher.browser import TestRequest
+ >>> request = TestRequest(form={'arg1': 'A', 'arg2': 'B', 'kw1': 'C'})
+
+ Create the view.
+
+ >>> from zope.component import getMultiAdapter
+ >>> from zope.interface import Interface
+ >>> view = getMultiAdapter((context, request), Interface, 'my_method')
+
+ Check that the __call__ method's signature equals to the real
+ method's signature. They both should yield the four parameters.
+
+ >>> def args(method):
+ ... f = method.im_func
+ ... c = f.func_code
+ ... defaults = f.func_defaults
+ ... names = c.co_varnames[1:c.co_argcount]
+ ... return names
+ >>> args(view.my_method)
+ ('arg1', 'arg2', 'kw1', 'kw2')
+ >>> args(view.__call__)
+ ('arg1', 'arg2', 'kw1', 'kw2')
+
+ Finally, call the view's default method. Important is, if this
+ gives a TypeError then the portal factory will fail. This is in
+ effect the same as the previous argument check was.
+
+ >>> from ZPublisher.mapply import mapply
+ >>> mapply(view.__call__, (), request)
+ CALLED A B C D
+
+ Clean up adapter registry and others:
+
+ >>> from zope.testing.cleanup import cleanUp
+ >>> cleanUp()
+ """
+
def test_suite():
from Testing.ZopeTestCase import FunctionalDocTestSuite
return FunctionalDocTestSuite()
More information about the Zope-Checkins
mailing list