[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/dav/ Merged isarsprint-dav-work changes r27855:28053 into the trunk; this adds opaque properties and PROPPATCH support.

Martijn Pieters mj at zopatista.com
Wed Oct 13 05:59:49 EDT 2004


Log message for revision 28056:
  Merged isarsprint-dav-work changes r27855:28053 into the trunk; this adds opaque properties and PROPPATCH support.

Changed:
  U   Zope3/trunk/src/zope/app/dav/configure.zcml
  A   Zope3/trunk/src/zope/app/dav/opaquenamespaces.py
  U   Zope3/trunk/src/zope/app/dav/propfind.py
  A   Zope3/trunk/src/zope/app/dav/proppatch.py
  A   Zope3/trunk/src/zope/app/dav/tests/test_doctests.py
  U   Zope3/trunk/src/zope/app/dav/tests/test_propfind.py
  A   Zope3/trunk/src/zope/app/dav/tests/test_proppatch.py
  A   Zope3/trunk/src/zope/app/dav/tests/unitfixtures.py

-=-
Modified: Zope3/trunk/src/zope/app/dav/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/dav/configure.zcml	2004-10-13 09:49:58 UTC (rev 28055)
+++ Zope3/trunk/src/zope/app/dav/configure.zcml	2004-10-13 09:59:47 UTC (rev 28056)
@@ -11,6 +11,14 @@
       allowed_attributes="PROPFIND setDepth getDepth" />
   
   <view
+      for="*"
+      name="PROPPATCH"
+      type="zope.publisher.interfaces.http.IHTTPRequest"
+      factory=".proppatch.PROPPATCH"
+      permission="zope.ManageContent"
+      allowed_attributes="PROPPATCH" />
+  
+  <view
       for="zope.app.http.interfaces.INullResource"
       name="MKCOL"
       type="zope.publisher.interfaces.http.IHTTPRequest"
@@ -99,7 +107,23 @@
       for="*"
       permission="zope.Public"
       factory=".adapter.DAVSchemaAdapter" />
-  
+
+  <!-- XXX: This interface needs to be split up so we can apply seperate 
+       permissions for reading and writing -->
+  <adapter
+      factory=".opaquenamespaces.DAVOpaqueNamespacesAdapter"
+      provides=".opaquenamespaces.IDAVOpaqueNamespaces"
+      for="zope.app.annotation.interfaces.IAnnotatable"
+      trusted="true"
+      />
+      
+  <class class=".opaquenamespaces.DAVOpaqueNamespacesAdapter">
+    <require
+        permission="zope.ManageContent"
+        interface=".opaquenamespaces.IDAVOpaqueNamespaces"
+        />
+  </class>
+
   <dav:provideInterface
       for="http://purl.org/dc/1.1"
       interface="zope.app.dublincore.interfaces.IZopeDublinCore" />

Copied: Zope3/trunk/src/zope/app/dav/opaquenamespaces.py (from rev 28054, Zope3/branches/isarsprint-dav-work/src/zope/app/dav/opaquenamespaces.py)

Modified: Zope3/trunk/src/zope/app/dav/propfind.py
===================================================================
--- Zope3/trunk/src/zope/app/dav/propfind.py	2004-10-13 09:49:58 UTC (rev 28055)
+++ Zope3/trunk/src/zope/app/dav/propfind.py	2004-10-13 09:59:47 UTC (rev 28056)
@@ -19,12 +19,11 @@
 from zope.schema import getFieldNamesInOrder
 from zope.app import zapi
 from zope.app.container.interfaces import IReadContainer
-from zope.app.dav.interfaces import IDAVWidget
 from zope.app.form.utility import setUpWidgets
 
-from interfaces import IDAVNamespace
+from interfaces import IDAVWidget, IDAVNamespace
+from opaquenamespaces import IDAVOpaqueNamespaces
 
-
 class PROPFIND(object):
     """PROPFIND handler for all objects"""
 
@@ -49,169 +48,92 @@
         self._depth = depth.lower()
 
     def PROPFIND(self):
-        request = self.request
-        resource_url = str(zapi.getView(self.context, 'absolute_url', request))
-        if IReadContainer.providedBy(self.context):
-            resource_url = resource_url + '/'
-        data = request.bodyFile
-        data.seek(0)
-        response = ''
-        body = ''
-
         if self.content_type not in ['text/xml', 'application/xml']:
-            request.response.setStatus(400)
-            return body
-
+            self.request.response.setStatus(400)
+            return ''
         if self.getDepth() not in ['0', '1', 'infinity']:
-            request.response.setStatus(400)
-            return body
+            self.request.response.setStatus(400)
+            return ''
 
-        xmldoc = minidom.parse(data)
-        response = minidom.Document()
-        ms = response.createElement('multistatus')
+        resource_url = str(zapi.getView(self.context, 'absolute_url', 
+                                        self.request))
+        if IReadContainer.providedBy(self.context):
+            resource_url += '/'
+
+        self.request.bodyFile.seek(0)
+        xmldoc = minidom.parse(self.request.bodyFile)
+        resp = minidom.Document()
+        ms = resp.createElement('multistatus')
         ms.setAttribute('xmlns', self.default_ns)
-        response.appendChild(ms)
-        re = response.createElement('response')
-        ms.appendChild(re)
-        href = response.createElement('href')
-        re.appendChild(href)
-        r_url = response.createTextNode(resource_url)
-        href.appendChild(r_url)
+        resp.appendChild(ms)
+        ms.appendChild(resp.createElement('response'))
+        ms.lastChild.appendChild(resp.createElement('href'))
+        ms.lastChild.lastChild.appendChild(resp.createTextNode(resource_url))
+
         _avail_props = {}
-        # TODO: For now, list the propnames for the all namespaces
-        # but later on, we need to list *all* propnames from *all* known
-        # namespaces that this object has.
+        # List all *registered* DAV interface namespaces and their properties
         for ns, iface in zapi.getUtilitiesFor(IDAVNamespace):
-            _avail_props[ns] = getFieldNamesInOrder(iface)
+            _avail_props[ns] = getFieldNamesInOrder(iface)    
+        # List all opaque DAV namespaces and the properties we know of
+        for ns, oprops in IDAVOpaqueNamespaces(self.context, {}).items():
+            _avail_props[ns] = oprops.keys()
+        
         propname = xmldoc.getElementsByTagNameNS(self.default_ns, 'propname')
         if propname:
-            self._handlePropname(response, re, _avail_props)
+            self._handlePropname(resp, _avail_props)
+        else:
+            source = xmldoc.getElementsByTagNameNS(self.default_ns, 'prop')
+            self._handlePropvalues(source, resp, _avail_props)
 
-        source = xmldoc.getElementsByTagNameNS(self.default_ns, 'prop')
-        _props = {}
-        if not source and not propname:
-            _props = self._handleAllprop(_avail_props, _props)
-
-        if source and not propname:
-            _props = self._handleProp(source, _props)
-
-        avail, not_avail = self._propertyResolver(_props)
-
-        if avail:
-            pstat = response.createElement('propstat')
-            re.appendChild(pstat)
-            prop = response.createElement('prop')
-            pstat.appendChild(prop)
-            status = response.createElement('status')
-            pstat.appendChild(status)
-            text = response.createTextNode('HTTP/1.1 200 OK')
-            status.appendChild(text)
-            count = 0
-            for ns in avail.keys():
-                attr_name = 'a%s' % count
-                if ns is not None and ns != self.default_ns:
-                    count += 1
-                    prop.setAttribute('xmlns:%s' % attr_name, ns)
-                iface = _props[ns]['iface']
-                adapter = iface(self.context, None)
-                initial = {}
-                for name in avail.get(ns):
-                    value = getattr(adapter, name, None)
-                    if value is not None:
-                        initial[name] = value
-                setUpWidgets(self, iface, IDAVWidget,
-                    ignoreStickyValues=True, initial=initial, 
-                    names=avail.get(ns))
-                for p in avail.get(ns):
-                    el = response.createElement('%s' % p )
-                    if ns is not None and ns != self.default_ns:
-                        el.setAttribute('xmlns', attr_name)
-                    prop.appendChild(el)
-                    value = getattr(self, p+'_widget')()
-                    if isinstance(value, (unicode, str)):
-                        # Get the widget value here
-                        value = response.createTextNode(value)
-                        el.appendChild(value)
-                    else:
-                        if zapi.isinstance(value, minidom.Node):
-                            el.appendChild(value)
-                        else:
-                            # Try to string-ify
-                            value = str(getattr(self, p+'_widget'))
-                            # Get the widget value here
-                            value = response.createTextNode(value)
-                            el.appendChild(value)
-
-        if not_avail:
-            pstat = response.createElement('propstat')
-            re.appendChild(pstat)
-            prop = response.createElement('prop')
-            pstat.appendChild(prop)
-            status = response.createElement('status')
-            pstat.appendChild(status)
-            text = response.createTextNode('HTTP/1.1 404 Not Found')
-            status.appendChild(text)
-            count = 0
-            for ns in not_avail.keys():
-                attr_name = 'a%s' % count
-                if ns is not None and ns != self.default_ns:
-                    count += 1
-                    prop.setAttribute('xmlns:%s' % attr_name, ns)
-                for p in not_avail.get(ns):
-                    el = response.createElement('%s' % p )
-                    prop.appendChild(el)
-                    if ns is not None and ns != self.default_ns:
-                        el.setAttribute('xmlns', attr_name)
-
         self._depthRecurse(ms)
 
-        body = response.toxml().encode('utf-8')
-        request.response.setBody(body)
-        request.response.setStatus(207)
+        body = resp.toxml().encode('utf-8')
+        self.request.response.setBody(body)
+        self.request.response.setStatus(207)
         return body
 
     def _depthRecurse(self, ms):
         depth = self.getDepth()
-        if depth == '1':
-            subdepth = '0'
-        if depth == 'infinity':
-            subdepth = 'infinity'
-        if depth != '0':
-            if IReadContainer.providedBy(self.context):
-                for id, obj in self.context.items():
-                    pfind = zapi.queryView(obj, 'PROPFIND', self.request, None)
-                    if pfind is not None:
-                        pfind.setDepth(subdepth)
-                        value = pfind.PROPFIND()
-                        parsed = minidom.parseString(value)
-                        responses = parsed.getElementsByTagNameNS(
-                            self.default_ns, 'response')
-                        for r in responses:
-                            ms.appendChild(r)
+        if depth == '0' or not IReadContainer.providedBy(self.context):
+            return
+        subdepth = (depth == '1') and '0' or 'infinity'
+        for id, obj in self.context.items():
+            pfind = zapi.queryView(obj, 'PROPFIND', self.request, None)
+            if pfind is None:
+                continue
+            pfind.setDepth(subdepth)
+            value = pfind.PROPFIND()
+            parsed = minidom.parseString(value)
+            responses = parsed.getElementsByTagNameNS(
+                self.default_ns, 'response')
+            for r in responses:
+                ms.appendChild(ms.ownerDocument.importNode(r, True))
 
-    def _handleProp(self, source, _props):
+    def _handleProp(self, source):
+        props = {}
         source = source[0]
         childs = [e for e in source.childNodes
                   if e.nodeType == e.ELEMENT_NODE]
         for node in childs:
             ns = node.namespaceURI
             iface = zapi.queryUtility(IDAVNamespace, ns)
-            value = _props.get(ns, {'iface': iface, 'props': []})
+            value = props.get(ns, {'iface': iface, 'props': []})
             value['props'].append(node.localName)
-            _props[ns] = value
-        return _props
+            props[ns] = value
+        return props
 
-    def _handleAllprop(self, _avail_props, _props):
+    def _handleAllprop(self, _avail_props):
+        props = {}
         for ns in _avail_props.keys():
             iface = zapi.queryUtility(IDAVNamespace, ns)
-            _props[ns] = {'iface': iface, 'props': _avail_props.get(ns)}
-        return _props
+            props[ns] = {'iface': iface, 'props': _avail_props.get(ns)}
+        return props
 
-    def _handlePropname(self, response, re, _avail_props):
-        pstat = response.createElement('propstat')
-        re.appendChild(pstat)
-        prop = response.createElement('prop')
-        pstat.appendChild(prop)
+    def _handlePropname(self, resp, _avail_props):
+        re = resp.lastChild.lastChild
+        re.appendChild(resp.createElement('propstat'))
+        prop = resp.createElement('prop')
+        re.lastChild.appendChild(prop)
         count = 0
         for ns in _avail_props.keys():
             attr_name = 'a%s' % count
@@ -219,25 +141,42 @@
                 count += 1
                 prop.setAttribute('xmlns:%s' % attr_name, ns)
             for p in _avail_props.get(ns):
-                el = response.createElement(p)
+                el = resp.createElement(p)
                 prop.appendChild(el)
                 if ns is not None and ns != self.default_ns:
                     el.setAttribute('xmlns', attr_name)
-        status = response.createElement('status')
-        pstat.appendChild(status)
-        text = response.createTextNode('HTTP/1.1 200 OK')
-        status.appendChild(text)
+        re.lastChild.appendChild(resp.createElement('status'))
+        re.lastChild.lastChild.appendChild(
+            resp.createTextNode('HTTP/1.1 200 OK'))
 
+    def _handlePropvalues(self, source, resp, _avail_props):
+        if not source:
+            _props = self._handleAllprop(_avail_props)
+        else:
+            _props = self._handleProp(source)
+
+        avail, not_avail = self._propertyResolver(_props)
+        if avail: 
+            self._renderAvail(avail, resp, _props)
+        if not_avail: 
+            self._renderNotAvail(not_avail, resp)
+
     def _propertyResolver(self, _props):
         avail = {}
         not_avail = {}
+        oprops = IDAVOpaqueNamespaces(self.context, {})
         for ns in _props.keys():
             iface = _props[ns]['iface']
             for p in _props[ns]['props']:
-                if _props[ns]['iface'] is None:
-                    l = not_avail.get(ns, [])
-                    l.append(p)
-                    not_avail[ns] = l
+                if iface is None:
+                    if oprops.get(ns, {}).get(p):
+                        l = avail.get(ns, [])
+                        l.append(p)
+                        avail[ns] = l
+                    else:    
+                        l = not_avail.get(ns, [])
+                        l.append(p)
+                        not_avail[ns] = l
                     continue
                 adapter = iface(self.context, None)
                 if adapter is None:
@@ -255,3 +194,76 @@
                     not_avail[ns] = l
 
         return avail, not_avail
+    
+    def _renderAvail(self, avail, resp, _props):
+        re = resp.lastChild.lastChild
+        re.appendChild(resp.createElement('propstat'))
+        prop = resp.createElement('prop')
+        re.lastChild.appendChild(prop)
+        re.lastChild.appendChild(resp.createElement('status'))
+        re.lastChild.lastChild.appendChild(
+            resp.createTextNode('HTTP/1.1 200 OK'))
+        count = 0
+        for ns in avail.keys():
+            attr_name = 'a%s' % count
+            if ns is not None and ns != self.default_ns:
+                count += 1
+                prop.setAttribute('xmlns:%s' % attr_name, ns)
+            iface = _props[ns]['iface']
+
+            if not iface:
+                # The opaque properties case, hand it off
+                oprops = IDAVOpaqueNamespaces(self.context, {})
+                for name in avail.get(ns):
+                    oprops.renderProperty(ns, attr_name, name, prop)
+                continue
+            
+            # The registered namespace case
+            initial = {}
+            adapter = iface(self.context, None)
+            for name in avail.get(ns):
+                value = getattr(adapter, name, None)
+                if value is not None:
+                    initial[name] = value
+            setUpWidgets(self, iface, IDAVWidget,
+                ignoreStickyValues=True, initial=initial, 
+                names=avail.get(ns))
+                        
+            for p in avail.get(ns):
+                el = resp.createElement('%s' % p )
+                if ns is not None and ns != self.default_ns:
+                    el.setAttribute('xmlns', attr_name)
+                prop.appendChild(el)
+                value = getattr(self, p+'_widget')()
+                    
+                if isinstance(value, (unicode, str)):
+                    # Get the widget value here
+                    el.appendChild(resp.createTextNode(value))
+                else:
+                    if zapi.isinstance(value, minidom.Node):
+                        el.appendChild(value)
+                    else:
+                        # Try to string-ify
+                        value = str(getattr(self, p+'_widget'))
+                        # Get the widget value here
+                        el.appendChild(resp.createTextNode(value))
+
+    def _renderNotAvail(self, not_avail, resp):
+        re = resp.lastChild.lastChild
+        re.appendChild(resp.createElement('propstat'))
+        prop = resp.createElement('prop')
+        re.lastChild.appendChild(prop)
+        re.lastChild.appendChild(resp.createElement('status'))
+        re.lastChild.lastChild.appendChild(
+            resp.createTextNode('HTTP/1.1 404 Not Found'))
+        count = 0
+        for ns in not_avail.keys():
+            attr_name = 'a%s' % count
+            if ns is not None and ns != self.default_ns:
+                count += 1
+                prop.setAttribute('xmlns:%s' % attr_name, ns)
+            for p in not_avail.get(ns):
+                el = resp.createElement('%s' % p )
+                prop.appendChild(el)
+                if ns is not None and ns != self.default_ns:
+                    el.setAttribute('xmlns', attr_name)

Copied: Zope3/trunk/src/zope/app/dav/proppatch.py (from rev 28054, Zope3/branches/isarsprint-dav-work/src/zope/app/dav/proppatch.py)


Property changes on: Zope3/trunk/src/zope/app/dav/proppatch.py
___________________________________________________________________
Name: svn:keywords
   + id
Name: svn:eol-style
   + native

Added: Zope3/trunk/src/zope/app/dav/tests/test_doctests.py
===================================================================
--- Zope3/trunk/src/zope/app/dav/tests/test_doctests.py	2004-10-13 09:49:58 UTC (rev 28055)
+++ Zope3/trunk/src/zope/app/dav/tests/test_doctests.py	2004-10-13 09:59:47 UTC (rev 28056)
@@ -0,0 +1,27 @@
+##############################################################################
+#
+# Copyright (c) 2004 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 makeDOMStandalone utility
+
+$Id: test_adapter.py 27505 2004-09-12 14:46:41Z philikon $
+"""
+import unittest
+from zope.testing.doctestunit import DocTestSuite
+
+def test_suite():
+    return unittest.TestSuite((
+            DocTestSuite('zope.app.dav.opaquenamespaces'),
+            ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Modified: Zope3/trunk/src/zope/app/dav/tests/test_propfind.py
===================================================================
--- Zope3/trunk/src/zope/app/dav/tests/test_propfind.py	2004-10-13 09:49:58 UTC (rev 28055)
+++ Zope3/trunk/src/zope/app/dav/tests/test_propfind.py	2004-10-13 09:59:47 UTC (rev 28056)
@@ -22,6 +22,8 @@
 
 from zope.interface import Interface, implements, directlyProvides
 from zope.publisher.interfaces.http import IHTTPRequest
+from zope.publisher.http import status_reasons
+
 from zope.pagetemplate.tests.util import normalize_xml
 from zope.schema import getFieldNamesInOrder
 from zope.schema.interfaces import IText, ITextLine, IDatetime, ISequence
@@ -30,11 +32,10 @@
 from zope.app.tests import ztapi
 
 from zope.app.traversing.api import traverse
+from zope.app.container.interfaces import IReadContainer
 from zope.publisher.browser import TestRequest
-from zope.app.filerepresentation.interfaces import IWriteFile
 from zope.app.site.tests.placefulsetup import PlacefulSetup
 from zope.app.traversing.browser import AbsoluteURL
-from zope.app.container.interfaces import IReadContainer
 from zope.app.dublincore.interfaces import IZopeDublinCore
 from zope.app.dublincore.annotatableadapter import ZDCAnnotatableAdapter
 from zope.app.annotation.interfaces import IAnnotatable, IAnnotations
@@ -45,50 +46,14 @@
 from zope.app.dav.interfaces import IDAVNamespace
 from zope.app.dav.interfaces import IDAVWidget
 from zope.app.dav.widget import TextDAVWidget, SequenceDAVWidget
+from zope.app.dav.opaquenamespaces import DAVOpaqueNamespacesAdapter
+from zope.app.dav.opaquenamespaces import IDAVOpaqueNamespaces
 
+from unitfixtures import File, Folder, FooZPT
+
 import zope.app.location
 
-class Folder(zope.app.location.Location):
 
-    implements(IReadContainer)
-
-    def __init__(self, name, level=0, parent=None):
-        self.name = self.__name__ = name
-        self.level=level
-        self.__parent__ = parent
-
-    def items(self):
-        if self.level == 2:
-            return (('last', File('last', 'text/plain', 'blablabla', self)),)
-        result = []
-        for i in range(1, 3):
-            result.append((str(i),
-                           File(str(i), 'text/plain', 'blablabla', self)))
-        result.append(('sub1',
-                       Folder('sub1', level=self.level+1, parent=self)))
-        return tuple(result)
-
-class File(zope.app.location.Location):
-
-    implements(IWriteFile)
-
-    def __init__(self, name, content_type, data, parent=None):
-        self.name = self.__name__ = name
-        self.content_type = content_type
-        self.data = data
-        self.__parent__ = parent
-
-    def write(self, data):
-        self.data = data
-
-class FooZPT(zope.app.location.Location):
-
-    implements(IAnnotatable)
-
-    def getSource(self):
-        return 'bla bla bla'
-
-
 def _createRequest(body=None, headers=None, skip_headers=None):
     if body is None:
         body = '''<?xml version="1.0"  ?>
@@ -144,6 +109,8 @@
         ztapi.provideAdapter(IAnnotatable, IAnnotations, AttributeAnnotations)
         ztapi.provideAdapter(IAnnotatable, IZopeDublinCore,
                              ZDCAnnotatableAdapter)
+        ztapi.provideAdapter(IAnnotatable, IDAVOpaqueNamespaces,
+                             DAVOpaqueNamespacesAdapter)
         utils = zapi.getGlobalService('Utilities')
         directlyProvides(IDAVSchema, IDAVNamespace)
         utils.provideUtility(IDAVNamespace, IDAVSchema, 'DAV:')
@@ -252,239 +219,112 @@
         # Check HTTP Response
         self.assertEqual(request.response.getStatus(), 400)
         self.assertEqual(pfind.getDepth(), 'full')
-
-    def test_davpropdctitle(self):
-        root = self.rootFolder
-        zpt = traverse(root, 'zpt')
-        dc = IZopeDublinCore(zpt)
-        dc.title = u'Test Title'
+        
+    def _checkPropfind(self, obj, req, expect, depth='0', resp=None):
         body = '''<?xml version="1.0" ?>
-        <propfind xmlns="DAV:">
-        <prop xmlns:DC="http://www.purl.org/dc/1.1">
-        <DC:title />
-        </prop>
-        </propfind>
-        '''
-
-        request = _createRequest(body=body,
-                                 headers={'Content-type':'text/xml',
-                                          'Depth':'0'})
-
-        resource_url = str(zapi.getView(zpt, 'absolute_url', request))
-        expect = '''<?xml version="1.0" ?>
-        <multistatus xmlns="DAV:">
-        <response>
-        <href>%(resource_url)s</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0">Test Title</title>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        </multistatus>
-        ''' % {'resource_url':resource_url}
-
-        pfind = propfind.PROPFIND(zpt, request)
+        <propfind xmlns="DAV:">%s</propfind>
+        ''' % req
+        request = _createRequest(body=body, headers={
+            'Content-type': 'text/xml', 'Depth': depth})
+        resource_url = str(zapi.getView(obj, 'absolute_url', request))
+        if IReadContainer.providedBy(obj):
+            resource_url += '/'
+        if resp is None:
+            resp = '''<?xml version="1.0" ?>
+            <multistatus xmlns="DAV:"><response>
+            <href>%%(resource_url)s</href>
+            <propstat>%s
+            <status>HTTP/1.1 200 OK</status>
+            </propstat></response></multistatus>
+            '''
+        expect = resp % expect
+        expect = expect % {'resource_url': resource_url}
+        pfind = propfind.PROPFIND(obj, request)
         pfind.PROPFIND()
         # Check HTTP Response
         self.assertEqual(request.response.getStatus(), 207)
-        self.assertEqual(pfind.getDepth(), '0')
+        self.assertEqual(pfind.getDepth(), depth)
         s1 = normalize_xml(request.response._body)
         s2 = normalize_xml(expect)
         self.assertEqual(s1, s2)
-
+        
+    def test_davpropdctitle(self):
+        root = self.rootFolder
+        zpt = traverse(root, 'zpt')
+        dc = IZopeDublinCore(zpt)
+        dc.title = u'Test Title'
+        req = '''<prop xmlns:DC="http://www.purl.org/dc/1.1">
+        <DC:title />
+        </prop>'''
+        
+        expect = '''<prop xmlns:a0="http://www.purl.org/dc/1.1">
+        <title xmlns="a0">Test Title</title></prop>'''
+        self._checkPropfind(zpt, req, expect)
+        
     def test_davpropdccreated(self):
         root = self.rootFolder
         zpt = traverse(root, 'zpt')
         dc = IZopeDublinCore(zpt)
         dc.created = datetime.utcnow()
-        body = '''<?xml version="1.0" ?>
-        <propfind xmlns="DAV:">
-        <prop xmlns:DC="http://www.purl.org/dc/1.1">
-        <DC:created />
-        </prop>
-        </propfind>
-        '''
+        req = '''<prop xmlns:DC="http://www.purl.org/dc/1.1">
+        <DC:created /></prop>'''
+        expect = '''<prop xmlns:a0="http://www.purl.org/dc/1.1">
+        <created xmlns="a0">%s</created></prop>''' % dc.created
+        self._checkPropfind(zpt, req, expect)
 
-        request = _createRequest(body=body,
-                                 headers={'Content-type':'text/xml',
-                                          'Depth':'0'})
-
-        resource_url = str(zapi.getView(zpt, 'absolute_url', request))
-        expect = '''<?xml version="1.0" ?>
-        <multistatus xmlns="DAV:">
-        <response>
-        <href>%(resource_url)s</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <created xmlns="a0">%(created)s</created>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        </multistatus>
-        ''' % {'resource_url':resource_url,
-               'created': dc.created }
-
-        pfind = propfind.PROPFIND(zpt, request)
-        pfind.PROPFIND()
-        # Check HTTP Response
-        self.assertEqual(request.response.getStatus(), 207)
-        self.assertEqual(pfind.getDepth(), '0')
-        s1 = normalize_xml(request.response._body)
-        s2 = normalize_xml(expect)
-        self.assertEqual(s1, s2)
-
     def test_davpropdcsubjects(self):
         root = self.rootFolder
         zpt = traverse(root, 'zpt')
         dc = IZopeDublinCore(zpt)
         dc.subjects = (u'Bla', u'Ble', u'Bli')
-        body = '''<?xml version="1.0" ?>
-        <propfind xmlns="DAV:">
-        <prop xmlns:DC="http://www.purl.org/dc/1.1">
-        <DC:subjects />
-        </prop>
-        </propfind>
-        '''
+        req = '''<prop xmlns:DC="http://www.purl.org/dc/1.1">
+        <DC:subjects /></prop>'''
 
-        request = _createRequest(body=body,
-                                 headers={'Content-type':'text/xml',
-                                          'Depth':'0'})
+        expect = '''<prop xmlns:a0="http://www.purl.org/dc/1.1">
+        <subjects xmlns="a0">%s</subjects></prop>''' % u', '.join(dc.subjects)
+        self._checkPropfind(zpt, req, expect)
 
-        resource_url = str(zapi.getView(zpt, 'absolute_url', request))
-        expect = '''<?xml version="1.0" ?>
-        <multistatus xmlns="DAV:">
-        <response>
-        <href>%(resource_url)s</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <subjects xmlns="a0">%(subjects)s</subjects>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        </multistatus>
-        ''' % {'resource_url':resource_url,
-               'subjects': u', '.join(dc.subjects) }
-
-        pfind = propfind.PROPFIND(zpt, request)
-        pfind.PROPFIND()
-        # Check HTTP Response
-        self.assertEqual(request.response.getStatus(), 207)
-        self.assertEqual(pfind.getDepth(), '0')
-        s1 = normalize_xml(request.response._body)
-        s2 = normalize_xml(expect)
-        self.assertEqual(s1, s2)
-
     def test_davpropname(self):
         root = self.rootFolder
         zpt = traverse(root, 'zpt')
-        body = '''<?xml version="1.0" ?>
-        <propfind xmlns="DAV:">
-        <propname/>
-        </propfind>
-        '''
+        oprops = IDAVOpaqueNamespaces(zpt)
+        oprops[u'http://foo/bar'] = {u'egg': '<egg>spam</egg>'}
+        req = '''<propname/>'''
 
-        request = _createRequest(body=body,
-                                 headers={'Content-type':'text/xml',
-                                          'Depth':'0'})
-
-        resource_url = str(zapi.getView(zpt, 'absolute_url', request))
-        props_xml = ''
+        expect = ''
         props = getFieldNamesInOrder(IZopeDublinCore)
         for p in props:
-            props_xml += '<%s xmlns="a0"/>' % p
+            expect += '<%s xmlns="a0"/>' % p
+        expect += '<egg xmlns="a1"/>'
         props = getFieldNamesInOrder(IDAVSchema)
         for p in props:
-            props_xml += '<%s/>' % p
-        expect = '''<?xml version="1.0" ?>
-        <multistatus xmlns="DAV:">
-        <response>
-        <href>%(resource_url)s</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        %(props_xml)s
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        </multistatus>
-        ''' % {'resource_url':resource_url,
-               'props_xml':props_xml}
+            expect += '<%s/>' % p
+        expect = '''
+        <prop xmlns:a0="http://www.purl.org/dc/1.1" xmlns:a1="http://foo/bar">
+        %s</prop>''' % expect
+        self._checkPropfind(zpt, req, expect)
 
-        pfind = propfind.PROPFIND(zpt, request)
-        pfind.PROPFIND()
-        # Check HTTP Response
-        self.assertEqual(request.response.getStatus(), 207)
-        self.assertEqual(pfind.getDepth(), '0')
-        s1 = normalize_xml(request.response._body)
-        s2 = normalize_xml(expect)
-        self.assertEqual(s1, s2)
-
     def test_davpropnamefolderdepth0(self):
         root = self.rootFolder
         folder = traverse(root, 'folder')
-        body = '''<?xml version="1.0" ?>
-        <propfind xmlns="DAV:">
-        <propname/>
-        </propfind>
-        '''
+        req = '''<propname/>'''
 
-        request = _createRequest(body=body,
-                                 headers={'Content-type':'text/xml',
-                                          'Depth':'0'})
-
-        resource_url = str(zapi.getView(folder, 'absolute_url', request))
-        resource_url = "%s/" % resource_url
-        props_xml = ''
+        expect = ''
         props = getFieldNamesInOrder(IZopeDublinCore)
         for p in props:
-            props_xml += '<%s xmlns="a0"/>' % p
+            expect += '<%s xmlns="a0"/>' % p
         props = getFieldNamesInOrder(IDAVSchema)
         for p in props:
-            props_xml += '<%s/>' % p
-        expect = '''<?xml version="1.0" ?>
-        <multistatus xmlns="DAV:">
-        <response>
-        <href>%(resource_url)s</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        %(props_xml)s
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        </multistatus>
-        ''' % {'resource_url':resource_url,
-               'props_xml':props_xml}
+            expect += '<%s/>' % p
+        expect = '''<prop xmlns:a0="http://www.purl.org/dc/1.1">
+        %s</prop>''' % expect
+        self._checkPropfind(folder, req, expect)
 
-        pfind = propfind.PROPFIND(folder, request)
-
-        pfind.PROPFIND()
-        # Check HTTP Response
-        self.assertEqual(request.response.getStatus(), 207)
-        self.assertEqual(pfind.getDepth(), '0')
-        s1 = normalize_xml(request.response._body)
-        s2 = normalize_xml(expect)
-        self.assertEqual(s1, s2)
-
     def test_davpropnamefolderdepth1(self):
         root = self.rootFolder
         folder = traverse(root, 'folder')
-        body = '''<?xml version="1.0" ?>
-        <propfind xmlns="DAV:">
-        <propname/>
-        </propfind>
-        '''
+        req = '''<propname/>'''
 
-        request = _createRequest(body=body,
-                                 headers={'Content-type':'text/xml',
-                                          'Depth':'1'})
-
-        resource_url = str(zapi.getView(folder, 'absolute_url', request))
-        resource_url = "%s/" % resource_url
         props_xml = ''
         props = getFieldNamesInOrder(IZopeDublinCore)
         for p in props:
@@ -493,152 +333,24 @@
         for p in props:
             props_xml += '<%s/>' % p
 
-        expect = '''<?xml version="1.0" ?>
-        <multistatus xmlns="DAV:">
-        <response>
-        <href>http://127.0.0.1/folder/</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        <response>
-        <href>http://127.0.0.1/folder/1</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        <response>
-        <href>http://127.0.0.1/folder/2</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        <response>
-        <href>http://127.0.0.1/folder/sub1/</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        </multistatus>'''
+        expect = ''
+        for p in ('', '1', '2', 'sub1/'):
+            expect += '''
+            <response><href>%(path)s</href>
+            <propstat><prop xmlns:a0="http://www.purl.org/dc/1.1">
+            %(props_xml)s</prop><status>HTTP/1.1 200 OK</status>
+            </propstat></response>
+            ''' % {'path': '%(resource_url)s' + p, 'props_xml': props_xml}
 
+        resp = '''<?xml version="1.0" ?>
+        <multistatus xmlns="DAV:">%s</multistatus>'''
+        self._checkPropfind(folder, req, expect, depth='1', resp=resp)
 
-        pfind = propfind.PROPFIND(folder, request)
-
-        pfind.PROPFIND()
-        # Check HTTP Response
-        self.assertEqual(request.response.getStatus(), 207)
-        self.assertEqual(pfind.getDepth(), '1')
-        s1 = normalize_xml(request.response._body)
-        s2 = normalize_xml(expect)
-        self.assertEqual(s1, s2)
-
     def test_davpropnamefolderdepthinfinity(self):
         root = self.rootFolder
         folder = traverse(root, 'folder')
-        body = '''<?xml version="1.0" ?>
-        <propfind xmlns="DAV:">
-        <propname/>
-        </propfind>
-        '''
+        req = '''<propname/>'''
 
-        request = _createRequest(body=body,
-                                 headers={'Content-type':'text/xml',
-                                          'Depth':'infinity'})
-
-        resource_url = str(zapi.getView(folder, 'absolute_url', request))
-        resource_url = "%s/" % resource_url
         props_xml = ''
         props = getFieldNamesInOrder(IZopeDublinCore)
         for p in props:
@@ -647,252 +359,47 @@
         for p in props:
             props_xml += '<%s/>' % p
 
-        expect = '''<?xml version="1.0" ?>
-        <multistatus xmlns="DAV:">
-        <response>
-        <href>http://127.0.0.1/folder/</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        <response>
-        <href>http://127.0.0.1/folder/1</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        <response>
-        <href>http://127.0.0.1/folder/2</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        <response>
-        <href>http://127.0.0.1/folder/sub1/</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        <response>
-        <href>http://127.0.0.1/folder/sub1/1</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        <response>
-        <href>http://127.0.0.1/folder/sub1/2</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        <response>
-        <href>http://127.0.0.1/folder/sub1/sub1/</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        <response>
-        <href>http://127.0.0.1/folder/sub1/sub1/last</href>
-        <propstat>
-        <prop xmlns:a0="http://www.purl.org/dc/1.1">
-        <title xmlns="a0"/>
-        <description xmlns="a0"/>
-        <created xmlns="a0"/>
-        <modified xmlns="a0"/>
-        <effective xmlns="a0"/>
-        <expires xmlns="a0"/>
-        <creators xmlns="a0"/>
-        <subjects xmlns="a0"/>
-        <publisher xmlns="a0"/>
-        <contributors xmlns="a0"/>
-        <creationdate/>
-        <displayname/>
-        <source/>
-        <getcontentlanguage/>
-        <getcontentlength/>
-        <getcontenttype/>
-        <getetag/>
-        <getlastmodified/>
-        <resourcetype/>
-        <lockdiscovery/>
-        <supportedlock/>
-        </prop>
-        <status>HTTP/1.1 200 OK</status>
-        </propstat>
-        </response>
-        </multistatus>'''
+        expect = ''
+        for p in ('', '1', '2', 'sub1/', 'sub1/1', 'sub1/2', 'sub1/sub1/',
+                  'sub1/sub1/last'):
+            expect += '''
+            <response><href>%(path)s</href>
+            <propstat><prop xmlns:a0="http://www.purl.org/dc/1.1">
+            %(props_xml)s</prop><status>HTTP/1.1 200 OK</status>
+            </propstat></response>
+            ''' % {'path': '%(resource_url)s' + p, 'props_xml': props_xml}
 
-        pfind = propfind.PROPFIND(folder, request)
+        resp = '''<?xml version="1.0" ?>
+        <multistatus xmlns="DAV:">%s</multistatus>'''
+        self._checkPropfind(folder, req, expect, depth='infinity', resp=resp)
+        
+    def test_propfind_opaque_simple(self):
+        root = self.rootFolder
+        zpt = traverse(root, 'zpt')
+        oprops = IDAVOpaqueNamespaces(zpt)
+        oprops[u'http://foo/bar'] = {u'egg': '<egg>spam</egg>'}
+        req = '<prop xmlns:foo="http://foo/bar"><foo:egg /></prop>'
 
-        pfind.PROPFIND()
-        # Check HTTP Response
-        self.assertEqual(request.response.getStatus(), 207)
-        self.assertEqual(pfind.getDepth(), 'infinity')
-        s1 = normalize_xml(request.response._body)
-        s2 = normalize_xml(expect)
-        self.assertEqual(s1, s2)
+        expect = '''<prop xmlns:a0="http://foo/bar"><egg xmlns="a0">spam</egg>
+        </prop>'''
+        self._checkPropfind(zpt, req, expect)
 
+    def test_propfind_opaque_complex(self):
+        root = self.rootFolder
+        zpt = traverse(root, 'zpt')
+        oprops = IDAVOpaqueNamespaces(zpt)
+        oprops[u'http://foo/bar'] = {u'egg': 
+            '<egg xmlns:bacon="http://bacon">\n'
+            '  <bacon:pork>crispy</bacon:pork>\n'
+            '</egg>\n'}
+        req = '<prop xmlns:foo="http://foo/bar"><foo:egg /></prop>'
+
+        expect = '''<prop xmlns:a0="http://foo/bar">
+        <egg xmlns="a0" xmlns:bacon="http://bacon">
+            <bacon:pork>crispy</bacon:pork>
+        </egg></prop>'''
+        self._checkPropfind(zpt, req, expect)
+
 def test_suite():
     return TestSuite((
         makeSuite(TestPlacefulPROPFIND),

Copied: Zope3/trunk/src/zope/app/dav/tests/test_proppatch.py (from rev 28054, Zope3/branches/isarsprint-dav-work/src/zope/app/dav/tests/test_proppatch.py)

Copied: Zope3/trunk/src/zope/app/dav/tests/unitfixtures.py (from rev 28054, Zope3/branches/isarsprint-dav-work/src/zope/app/dav/tests/unitfixtures.py)


Property changes on: Zope3/trunk/src/zope/app/dav/tests/unitfixtures.py
___________________________________________________________________
Name: svn:keywords
   + id
Name: svn:eol-style
   + native



More information about the Zope3-Checkins mailing list