[Zope3-checkins]
SVN: Zope3/branches/isarsprint-dav-work/src/zope/app/dav/
First cut at PROPPATCH code;
based on PROPFIND code, no actual property
Martijn Pieters
mj at zopatista.com
Sun Oct 10 06:28:52 EDT 2004
Log message for revision 27883:
First cut at PROPPATCH code; based on PROPFIND code, no actual property
patching functionality implemented yet.
Changed:
U Zope3/branches/isarsprint-dav-work/src/zope/app/dav/configure.zcml
A Zope3/branches/isarsprint-dav-work/src/zope/app/dav/proppatch.py
A Zope3/branches/isarsprint-dav-work/src/zope/app/dav/tests/test_proppatch.py
-=-
Modified: Zope3/branches/isarsprint-dav-work/src/zope/app/dav/configure.zcml
===================================================================
--- Zope3/branches/isarsprint-dav-work/src/zope/app/dav/configure.zcml 2004-10-10 10:23:51 UTC (rev 27882)
+++ Zope3/branches/isarsprint-dav-work/src/zope/app/dav/configure.zcml 2004-10-10 10:28:52 UTC (rev 27883)
@@ -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"
Added: Zope3/branches/isarsprint-dav-work/src/zope/app/dav/proppatch.py
===================================================================
--- Zope3/branches/isarsprint-dav-work/src/zope/app/dav/proppatch.py 2004-10-10 10:23:51 UTC (rev 27882)
+++ Zope3/branches/isarsprint-dav-work/src/zope/app/dav/proppatch.py 2004-10-10 10:28:52 UTC (rev 27883)
@@ -0,0 +1,68 @@
+##############################################################################
+# Copyright (c) 2003 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.
+##############################################################################
+"""WebDAV method PROPPATCH
+
+$Id: propfind.py 27237 2004-08-23 23:42:11Z jim $
+"""
+__docformat__ = 'restructuredtext'
+
+from xml.dom import minidom
+
+from zope.app import zapi
+from zope.app.container.interfaces import IReadContainer
+
+class PROPPATCH(object):
+ """PROPPATCH handler for all objects"""
+
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+ ct = request.getHeader('content-type', 'text/xml')
+ if ';' in ct:
+ parts = ct.split(';', 1)
+ self.content_type = parts[0].strip().lower()
+ self.content_type_params = parts[1].strip()
+ else:
+ self.content_type = ct.lower()
+ self.content_type_params = None
+ self.default_ns = 'DAV:'
+
+ def PROPPATCH(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
+
+ xmldoc = minidom.parse(data)
+ response = minidom.Document()
+ ms = response.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)
+
+ body = response.toxml().encode('utf-8')
+ request.response.setBody(body)
+ request.response.setStatus(207)
+ return body
Added: Zope3/branches/isarsprint-dav-work/src/zope/app/dav/tests/test_proppatch.py
===================================================================
--- Zope3/branches/isarsprint-dav-work/src/zope/app/dav/tests/test_proppatch.py 2004-10-10 10:23:51 UTC (rev 27882)
+++ Zope3/branches/isarsprint-dav-work/src/zope/app/dav/tests/test_proppatch.py 2004-10-10 10:28:52 UTC (rev 27883)
@@ -0,0 +1,165 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 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 the dav PROPPATCH interactions.
+
+$Id: test_directives.py 27844 2004-10-09 15:37:29Z mj $
+"""
+__docformat__ = 'restructuredtext'
+
+import unittest
+from StringIO import StringIO
+
+from zope.interface import Interface, implements, directlyProvides
+from zope.publisher.interfaces.http import IHTTPRequest
+
+from zope.app import zapi
+from zope.app.tests import ztapi
+
+from zope.app.traversing.api import traverse
+from zope.publisher.browser import TestRequest
+from zope.app.site.tests.placefulsetup import PlacefulSetup
+from zope.app.traversing.browser import AbsoluteURL
+from zope.app.dublincore.interfaces import IZopeDublinCore
+from zope.app.dublincore.annotatableadapter import ZDCAnnotatableAdapter
+from zope.app.annotation.interfaces import IAnnotatable, IAnnotations
+from zope.app.annotation.attribute import AttributeAnnotations
+
+import zope.app.dav.tests
+from zope.app.dav.tests.unitfixtures import File, Folder, FooZPT
+
+from zope.app.dav import proppatch
+from zope.app.dav.interfaces import IDAVSchema
+from zope.app.dav.interfaces import IDAVNamespace
+
+def _createRequest(body=None, headers=None, skip_headers=None,
+ namespaces=(('Z', 'http://www.w3.com/standards/z39.50/'),),
+ set=('<Z:authors>\n<Z:Author>Jim Whitehead</Z:Author>\n',
+ '<Z:Author>Roy Fielding</Z:Author>\n</Z:authors>'),
+ remove=('<D:prop><Z:Copyright-Owner/></D:prop>\n')):
+ if body is None:
+ setProps = removeProps = ''
+ if set:
+ setProps = '<set><prop>\n%s\n</prop></set>\n' % (''.join(set))
+ if remove:
+ removeProps = '<remove><prop>\n%s\n</prop></remove>\n' % (
+ ''.join(remove))
+
+ body = '''<?xml version="1.0" ?>
+
+ <propertyupdate xmlns="DAV:"
+ xmlns:Z="http://www.w3.com/standards/z39.50/">
+ %s
+ </propertyupdate>
+ ''' % (setProps + removeProps)
+
+ _environ = {'CONTENT_TYPE': 'text/xml',
+ 'CONTENT_LENGTH': str(len(body))}
+
+ if headers is not None:
+ for key, value in headers.items():
+ _environ[key.upper().replace("-", "_")] = value
+
+ if skip_headers is not None:
+ for key in skip_headers:
+ if _environ.has_key(key.upper()):
+ del _environ[key.upper()]
+
+ request = TestRequest(StringIO(body), StringIO(), _environ)
+ return request
+
+class PropFindTests(PlacefulSetup, unittest.TestCase):
+
+ def setUp(self):
+ PlacefulSetup.setUp(self)
+ PlacefulSetup.buildFolders(self)
+ root = self.rootFolder
+ zpt = FooZPT()
+ self.content = "some content\n for testing"
+ file = File('spam', 'text/plain', self.content)
+ folder = Folder('bla')
+ root['file'] = file
+ root['zpt'] = zpt
+ root['folder'] = folder
+ self.zpt = traverse(root, 'zpt')
+ self.file = traverse(root, 'file')
+ ztapi.provideView(None, IHTTPRequest, Interface,
+ 'absolute_url', AbsoluteURL)
+ ztapi.provideView(None, IHTTPRequest, Interface,
+ 'PROPPATCH', proppatch.PROPPATCH)
+ ztapi.provideAdapter(IAnnotatable, IAnnotations, AttributeAnnotations)
+ ztapi.provideAdapter(IAnnotatable, IZopeDublinCore,
+ ZDCAnnotatableAdapter)
+ utils = zapi.getGlobalService('Utilities')
+ directlyProvides(IDAVSchema, IDAVNamespace)
+ utils.provideUtility(IDAVNamespace, IDAVSchema, 'DAV:')
+ directlyProvides(IZopeDublinCore, IDAVNamespace)
+ utils.provideUtility(IDAVNamespace, IZopeDublinCore,
+ 'http://www.purl.org/dc/1.1')
+
+ def test_contenttype1(self):
+ file = self.file
+ request = _createRequest(headers={'Content-type':'text/xml'})
+ ppatch = proppatch.PROPPATCH(file, request)
+ ppatch.PROPPATCH()
+ # Check HTTP Response
+ self.assertEqual(request.response.getStatus(), 207)
+
+ def test_contenttype2(self):
+ file = self.file
+ request = _createRequest(headers={'Content-type':'application/xml'})
+
+ ppatch = proppatch.PROPPATCH(file, request)
+ ppatch.PROPPATCH()
+ # Check HTTP Response
+ self.assertEqual(request.response.getStatus(), 207)
+
+ def test_contenttype3(self):
+ # Check for an appropriate response when the content-type has
+ # parameters, and that the major/minor parts are treated in a
+ # case-insensitive way.
+ file = self.file
+ request = _createRequest(headers={'Content-type':
+ 'TEXT/XML; charset="utf-8"'})
+ ppatch = proppatch.PROPPATCH(file, request)
+ ppatch.PROPPATCH()
+ # Check HTTP Response
+ self.assertEqual(request.response.getStatus(), 207)
+
+ def test_bad_contenttype(self):
+ file = self.file
+ request = _createRequest(headers={'Content-type':'text/foo'})
+
+ ppatch = proppatch.PROPPATCH(file, request)
+ ppatch.PROPPATCH()
+ # Check HTTP Response
+ self.assertEqual(request.response.getStatus(), 400)
+
+ def test_no_contenttype(self):
+ file = self.file
+ request = _createRequest(skip_headers=('content-type'))
+
+ ppatch = proppatch.PROPPATCH(file, request)
+ ppatch.PROPPATCH()
+ # Check HTTP Response
+ self.assertEqual(request.response.getStatus(), 207)
+ self.assertEqual(ppatch.content_type, 'text/xml')
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(PropFindTests),
+ ))
+
+if __name__ == '__main__':
+ unittest.main()
More information about the Zope3-Checkins
mailing list