[Zope-Checkins] SVN: Zope/branches/2.9/lib/python/Products/Five/
for alecm:
david whitfield Morriss
whit at longnow.org
Tue Feb 21 20:20:09 EST 2006
Log message for revision 41744:
for alecm:
Changed Traversable to call the original __bobo_traverse__ method before
attempting to use attribute access to find the desired object. This ensures
that the monkeypatched object retains the same behavior as the original
object during traversal. Also, added checks to see if the request is a
WebDAV request in which case attribute lookup is performed without
acquisition (see BaseRequest.traverse for why this is important).
Changed:
U Zope/branches/2.9/lib/python/Products/Five/browser/tests/test_traversable.py
U Zope/branches/2.9/lib/python/Products/Five/traversable.py
-=-
Modified: Zope/branches/2.9/lib/python/Products/Five/browser/tests/test_traversable.py
===================================================================
--- Zope/branches/2.9/lib/python/Products/Five/browser/tests/test_traversable.py 2006-02-21 21:37:05 UTC (rev 41743)
+++ Zope/branches/2.9/lib/python/Products/Five/browser/tests/test_traversable.py 2006-02-22 01:20:07 UTC (rev 41744)
@@ -64,6 +64,9 @@
... <five:traversable
... class="Products.Five.browser.tests.test_traversable.SimpleClass"
... />
+ ... <five:traversable
+ ... class="Products.Five.tests.testing.FiveTraversableFolder"
+ ... />
...
... <browser:page
... for="Products.Five.tests.testing.fancycontent.IFancyContent"
@@ -99,7 +102,64 @@
...
Fancy, fancy
+ Without five traversable, if there had been an attrubute something-else,
+ the __bobo_traverse__ method would have still been used instead of the
+ atribute, let's make sure we preserve that behavior.
+ >>> self.folder.fancy.an_attribute = 'This is an attribute'
+ >>> print http(r'''
+ ... GET /test_folder_1_/fancy/an_attribute HTTP/1.1
+ ... ''')
+ HTTP/1.1 200 OK
+ ...
+ an_attribute
+
+ If we use WebDAV to get an object no acquisition should be performed,
+ otherwise content creation will break:
+
+ >>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
+ >>> manage_addFiveTraversableFolder(self.folder, 'traversable_folder', 'Traversable')
+
+ Let's verify that we can get our object properties via WebDAV:
+ >>> print http(r'''
+ ... PROPFIND /test_folder_1_/fancy HTTP/1.1
+ ... Content-Type: text/xml; charset="utf-8"
+ ... Depth: 0
+ ...
+ ... <?xml version="1.0" encoding="utf-8"?>
+ ... <DAV:propfind xmlns:DAV="DAV:"
+ ... xmlns:zope="http://www.zope.org/propsets/default">
+ ... <DAV:prop><zope:title/></DAV:prop>
+ ... </DAV:propfind>
+ ... ''')
+ HTTP/1.1 200 OK
+ ...
+ PROPFIND
+
+ And that a normal http request will acquire the object:
+ >>> print http(r'''
+ ... GET /test_folder_1_/traversable_folder/fancy HTTP/1.1
+ ... ''')
+ HTTP/1.1 200 OK
+ ...
+ <FancyContent at >
+
+ But that a WebDAV request will not:
+ >>> print http(r'''
+ ... PROPFIND /test_folder_1_/traversable_folder/fancy HTTP/1.1
+ ... Content-Type: text/xml; charset="utf-8"
+ ... Depth: 0
+ ...
+ ... <?xml version="1.0" encoding="utf-8"?>
+ ... <DAV:propfind xmlns:DAV="DAV:"
+ ... xmlns:zope="http://www.zope.org/propsets/default">
+ ... <DAV:prop><zope:title/></DAV:prop>
+ ... </DAV:propfind>
+ ... ''')
+ HTTP/1.1 404 Not Found
+ ...
+
+
Clean up:
>>> from zope.app.testing.placelesssetup import tearDown
Modified: Zope/branches/2.9/lib/python/Products/Five/traversable.py
===================================================================
--- Zope/branches/2.9/lib/python/Products/Five/traversable.py 2006-02-21 21:37:05 UTC (rev 41743)
+++ Zope/branches/2.9/lib/python/Products/Five/traversable.py 2006-02-22 01:20:07 UTC (rev 41744)
@@ -16,6 +16,7 @@
$Id: traversable.py 19283 2005-10-31 17:43:51Z philikon $
"""
from zExceptions import NotFound
+from ZPublisher import xmlrpc
from zope.component import getMultiAdapter, ComponentLookupError
from zope.interface import implements, Interface
@@ -29,8 +30,11 @@
from zope.app.interface import queryType
from AccessControl import getSecurityManager
+from Acquisition import aq_base
from Products.Five.security import newInteraction
+from webdav.NullResource import NullResource
+
_marker = object
class FakeRequest(dict):
@@ -56,7 +60,7 @@
Just raise a AttributeError to indicate traversal has failed
and let Zope do it's job.
"""
- raise AttributeError, name
+ raise NotImplementedError
__fallback_traverse__.__five_method__ = True
def __bobo_traverse__(self, REQUEST, name):
@@ -86,14 +90,36 @@
AttributeError, KeyError, NotFound):
pass
try:
- return getattr(self, name)
- except AttributeError:
+ return self.__fallback_traverse__(REQUEST, name)
+ except NotImplementedError:
pass
- try:
- return self[name]
- except (AttributeError, KeyError):
- pass
- return self.__fallback_traverse__(REQUEST, name)
+ # This should at least make a half hearted attempt to care for
+ # potential WebDAV issues, in particular we should not perform
+ # acquisition for webdav requests, and should return a NullResource
+ # when appropriate.
+ method = REQUEST.get('REQUEST_METHOD', 'GET').upper()
+ if (len(REQUEST.get('TraversalRequestNameStack', ())) == 0 and
+ not (method in ('GET', 'HEAD', 'POST') and not
+ isinstance(REQUEST.RESPONSE, xmlrpc.Response))):
+ if getattr(aq_base(self), name, None) is not None:
+ return getattr(self, name)
+ else:
+ # XXX: This may be unnecessary as Zope itself doesn't do it,
+ # but it shouldn't be harmful
+ if (method in ('PUT', 'MKCOL') and not
+ isinstance(RESPONSE, xmlrpc.Response)):
+ return NullResource(self, name, REQUEST).__of__(self)
+ else:
+ try:
+ return getattr(self, name)
+ except AttributeError:
+ pass
+ try:
+ return self[name]
+ except (AttributeError, KeyError):
+ pass
+ raise AttributeError, name
+
__bobo_traverse__.__five_method__ = True
@@ -112,3 +138,5 @@
return getMultiAdapter((context, REQUEST), Interface, name)
except ComponentLookupError:
pass
+
+
More information about the Zope-Checkins
mailing list