[Checkins] SVN: zope.app.dav/trunk/ * Get ready for a 3.4.0 release.

Stephan Richter srichter at cosmos.phy.tufts.edu
Tue Oct 23 21:19:48 EDT 2007


Log message for revision 81002:
  * Get ready for a 3.4.0 release.
  
  * Move functional tests together with the regular ones.
  
  

Changed:
  A   zope.app.dav/trunk/CHANGES.txt
  A   zope.app.dav/trunk/README.txt
  U   zope.app.dav/trunk/buildout.cfg
  D   zope.app.dav/trunk/setup.cfg
  U   zope.app.dav/trunk/setup.py
  _U  zope.app.dav/trunk/src/
  D   zope.app.dav/trunk/src/zope/app/dav/ftests/
  A   zope.app.dav/trunk/src/zope/app/dav/tests/dav.py
  A   zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_mkcol.py
  A   zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_propfind.py
  A   zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_proppatch.py

-=-
Added: zope.app.dav/trunk/CHANGES.txt
===================================================================
--- zope.app.dav/trunk/CHANGES.txt	                        (rev 0)
+++ zope.app.dav/trunk/CHANGES.txt	2007-10-24 01:19:47 UTC (rev 81002)
@@ -0,0 +1,8 @@
+=======
+CHANGES
+=======
+
+3.4.0 (2007-10-11)
+------------------
+
+- Initial release independent of the main Zope tree.


Property changes on: zope.app.dav/trunk/CHANGES.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zope.app.dav/trunk/README.txt
===================================================================
--- zope.app.dav/trunk/README.txt	                        (rev 0)
+++ zope.app.dav/trunk/README.txt	2007-10-24 01:19:47 UTC (rev 81002)
@@ -0,0 +1,2 @@
+This package provides basic WebDAV support for a Zope application. A more
+advanced implementation is available in ``z3c.dav``.


Property changes on: zope.app.dav/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: zope.app.dav/trunk/buildout.cfg
===================================================================
--- zope.app.dav/trunk/buildout.cfg	2007-10-24 01:15:50 UTC (rev 81001)
+++ zope.app.dav/trunk/buildout.cfg	2007-10-24 01:19:47 UTC (rev 81002)
@@ -1,10 +1,8 @@
 [buildout]
-develop = . 
+develop = .
 parts = test
-find-links = http://download.zope.org/distribution/
 
 [test]
 recipe = zc.recipe.testrunner
-defaults = ['--tests-pattern', '^f?tests$']
 eggs = zope.app.dav [test]
 

Deleted: zope.app.dav/trunk/setup.cfg
===================================================================
--- zope.app.dav/trunk/setup.cfg	2007-10-24 01:15:50 UTC (rev 81001)
+++ zope.app.dav/trunk/setup.cfg	2007-10-24 01:19:47 UTC (rev 81002)
@@ -1,2 +0,0 @@
-[egg_info]
-tag_svn_revision = 1
\ No newline at end of file

Modified: zope.app.dav/trunk/setup.py
===================================================================
--- zope.app.dav/trunk/setup.py	2007-10-24 01:15:50 UTC (rev 81001)
+++ zope.app.dav/trunk/setup.py	2007-10-24 01:19:47 UTC (rev 81002)
@@ -15,18 +15,36 @@
 
 $Id$
 """
-
 import os
+from setuptools import setup, find_packages
 
-from setuptools import setup, find_packages, Extension
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
 
+
 setup(name='zope.app.dav',
-      version = '3.4.0b1',
-      url='http://svn.zope.org/zope.app.dav',
-      license='ZPL 2.1',
-      description='Zope dav',
+      version = '3.4.0',
       author='Zope Corporation and Contributors',
       author_email='zope3-dev at zope.org',
+      description='Zope WebDAV Support(Basic)',
+      long_description=(
+          read('README.txt')
+          + '\n\n' +
+          read('CHANGES.txt')
+          ),
+      keywords = "zope3 webdav",
+      classifiers = [
+          'Development Status :: 5 - Production/Stable',
+          'Environment :: Web Environment',
+          'Intended Audience :: Developers',
+          'License :: OSI Approved :: Zope Public License',
+          'Programming Language :: Python',
+          'Natural Language :: English',
+          'Operating System :: OS Independent',
+          'Topic :: Internet :: WWW/HTTP',
+          'Framework :: Zope3'],
+      url='http://cheeseshop.python.org/pypi/zope.app.dav',
+      license='ZPL 2.1',
       packages=find_packages('src'),
       package_dir = {'': 'src'},
       namespace_packages=['zope', 'zope.app'],


Property changes on: zope.app.dav/trunk/src
___________________________________________________________________
Name: svn:ignore
   + zope.app.dav.egg-info


Copied: zope.app.dav/trunk/src/zope/app/dav/tests/dav.py (from rev 80844, zope.app.dav/trunk/src/zope/app/dav/ftests/dav.py)
===================================================================
--- zope.app.dav/trunk/src/zope/app/dav/tests/dav.py	                        (rev 0)
+++ zope.app.dav/trunk/src/zope/app/dav/tests/dav.py	2007-10-24 01:19:47 UTC (rev 81002)
@@ -0,0 +1,55 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Base class for DAV functional tests.
+
+$Id$
+"""
+import transaction
+from persistent import Persistent
+from zope.interface import implements
+from zope.annotation.interfaces import IAttributeAnnotatable
+
+from zope.app.testing.functional import HTTPTestCase
+from zope.app.folder import Folder
+
+class Page(Persistent):
+    implements(IAttributeAnnotatable)    
+
+class DAVTestCase(HTTPTestCase):
+
+    def createFolders(self, path):
+        """createFolders('/a/b/c/d') would traverse and/or create three nested
+        folders (a, b, c) and return a tuple (c, 'd') where c is a Folder
+        instance at /a/b/c."""
+        folder = self.getRootFolder()
+        if path[0] == '/':
+            path = path[1:]
+        path = path.split('/')
+        for id in path[:-1]:
+            try:
+                folder = folder[id]
+            except KeyError:
+                folder[id] = Folder()
+                folder = folder[id]
+        return folder, path[-1]
+
+    def createObject(self, path, obj):
+        folder, id = self.createFolders(path)
+        folder[id] = obj
+        transaction.commit()
+
+    def addPage(self, path, content):
+        page = Page()
+        page.source = content
+        self.createObject(path, page)

Copied: zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_mkcol.py (from rev 80844, zope.app.dav/trunk/src/zope/app/dav/ftests/test_mkcol.py)
===================================================================
--- zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_mkcol.py	                        (rev 0)
+++ zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_mkcol.py	2007-10-24 01:19:47 UTC (rev 81002)
@@ -0,0 +1,71 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Functional tests for MKCOL.
+
+$Id$
+"""
+import unittest
+
+from zope.app.dav.tests.dav import DAVTestCase
+import transaction
+from zope.app.dav.testing import AppDavLayer
+
+class TestMKCOL(DAVTestCase):
+
+    def test_mkcol_not_folderish(self):
+        self.addPage('/bar/pt', u'<span />')
+        transaction.commit()
+        self.verifyStatus(path='/bar/pt/foo', body='', basic='mgr:mgrpw',
+                          expected=404)
+
+    def test_mkcol_not_folderish_existing(self):
+        self.addPage('/bar/pt', u'<span />')
+        transaction.commit()
+        self.verifyStatus(path='/bar/pt', body='', basic='mgr:mgrpw',
+                          expected=405)
+
+    def test_mkcol_not_existing(self):
+        self.verifyStatus(path='/mkcol_test', body='', basic='mgr:mgrpw',
+                          expected=201)
+
+    def test_mkcol_parent_not_existing(self):
+        self.verifyStatus(path='/bar/mkcol_test', body='', basic='mgr:mgrpw',
+                          expected=409)
+
+    def test_mkcol_existing(self):
+        self.createFolders('/bar/mkcol_test')
+        transaction.commit()
+        self.verifyStatus(path='/bar', body='', basic='mgr:mgrpw',
+                          expected=405)
+
+    def test_mkcol_with_body(self):
+        self.verifyStatus(path='/mkcol_test', body='bla', basic='mgr:mgrpw',
+                          expected=415)
+
+    def verifyStatus(self, path, body, basic, expected=201):
+        clen = len(body)
+        result = self.publish(path, basic, env={'REQUEST_METHOD':'MKCOL',
+                                                'CONTENT-LENGHT': clen},
+                              request_body=body, handle_errors=True)
+        self.assertEquals(result.getStatus(), expected)
+
+def test_suite():
+    suite = unittest.TestSuite()
+    TestMKCOL.layer = AppDavLayer
+    suite.addTest(unittest.makeSuite(TestMKCOL))
+    return suite
+
+
+if __name__ == '__main__':
+    unittest.main()

Copied: zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_propfind.py (from rev 80844, zope.app.dav/trunk/src/zope/app/dav/ftests/test_propfind.py)
===================================================================
--- zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_propfind.py	                        (rev 0)
+++ zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_propfind.py	2007-10-24 01:19:47 UTC (rev 81002)
@@ -0,0 +1,111 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Functional tests for PROPFIND.
+
+$Id$
+"""
+import unittest
+import transaction
+from datetime import datetime
+from zope.pagetemplate.tests.util import normalize_xml
+from zope.traversing.api import traverse
+from zope.dublincore.interfaces import IZopeDublinCore
+
+from zope.app.dav.tests.dav import DAVTestCase
+from zope.app.dav.opaquenamespaces import IDAVOpaqueNamespaces
+from zope.app.dav.testing import AppDavLayer
+
+class TestPROPFIND(DAVTestCase):
+
+    def test_dctitle(self):
+        self.addPage('/pt', u'<span />')
+        self.verifyPropOK(path='/pt', ns='http://purl.org/dc/1.1',
+                          prop='title', expect='', basic='mgr:mgrpw')
+
+    def test_dctitle2(self):
+        self.addPage('/pt', u'<span />')
+        pt = traverse(self.getRootFolder(), '/pt')
+        adapted = IZopeDublinCore(pt)
+        adapted.title = u'Test Title'
+        transaction.commit()
+        self.verifyPropOK(path='/pt', ns='http://purl.org/dc/1.1',
+                          prop='title', expect='Test Title', basic='mgr:mgrpw')
+
+    def test_dccreated(self):
+        self.addPage('/pt', u'<span />')
+        pt = traverse(self.getRootFolder(), '/pt')
+        adapted = IZopeDublinCore(pt)
+        adapted.created = datetime.utcnow()
+        transaction.commit()
+        expect = str(adapted.created)
+        self.verifyPropOK(path='/pt', ns='http://purl.org/dc/1.1',
+                          prop='created', expect=expect, basic='mgr:mgrpw')
+
+    def test_dcsubject(self):
+        self.addPage('/pt', u'<span />')
+        pt = traverse(self.getRootFolder(), '/pt')
+        adapted = IZopeDublinCore(pt)
+        adapted.subjects = (u'Bla', u'Ble', u'Bli')
+        transaction.commit()
+        expect = ', '.join(adapted.subjects)
+        self.verifyPropOK(path='/pt', ns='http://purl.org/dc/1.1',
+                          prop='subjects', expect=expect, basic='mgr:mgrpw')
+
+    def test_opaque(self):
+        self.addPage('/pt', u'<span />')
+        pt = traverse(self.getRootFolder(), '/pt')
+        adapted = IDAVOpaqueNamespaces(pt)
+        adapted[u'uri://bar'] = {u'foo': '<foo>spam</foo>'}
+        transaction.commit()
+        expect = 'spam'
+        self.verifyPropOK(path='/pt', ns='uri://bar',
+                          prop='foo', expect=expect, basic='mgr:mgrpw')
+
+    def verifyPropOK(self, path, ns, prop, expect, basic):
+        body = """<?xml version="1.0" ?>
+        <propfind xmlns="DAV:">
+        <prop xmlns:a0="%(ns)s">
+        <a0:%(prop)s />
+        </prop>
+        </propfind>""" % {'ns':ns, 'prop':prop}
+        clen = len(body)
+        result = self.publish(path, basic, env={'REQUEST_METHOD':'PROPFIND',
+                                                'CONTENT-LENGHT': clen},
+                              request_body=body)
+        self.assertEquals(result.getStatus(), 207)
+        s1 = normalize_xml(result.getBody())
+        s2 = normalize_xml("""<?xml version="1.0" encoding="utf-8"?>
+        <multistatus xmlns="DAV:">
+        <response>
+        <href>http://localhost/pt</href>
+        <propstat>
+        <prop xmlns:a0="%(ns)s">
+        <%(prop)s xmlns="a0">%(expect)s</%(prop)s>
+        </prop>
+        <status>HTTP/1.1 200 OK</status>
+        </propstat>
+        </response>
+        </multistatus>""" % {'ns':ns, 'prop':prop, 'expect':expect})
+        self.assertEquals(s1, s2)
+
+
+def test_suite():
+    suite = unittest.TestSuite()
+    TestPROPFIND.layer = AppDavLayer
+    suite.addTest(unittest.makeSuite(TestPROPFIND))
+    return suite
+
+
+if __name__ == '__main__':
+    unittest.main()

Copied: zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_proppatch.py (from rev 80844, zope.app.dav/trunk/src/zope/app/dav/ftests/test_proppatch.py)
===================================================================
--- zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_proppatch.py	                        (rev 0)
+++ zope.app.dav/trunk/src/zope/app/dav/tests/test_functional_proppatch.py	2007-10-24 01:19:47 UTC (rev 81002)
@@ -0,0 +1,168 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Functional tests for PROPPATCH.
+
+$Id$
+"""
+import unittest
+import transaction
+from zope.pagetemplate.tests.util import normalize_xml
+from zope.publisher.http import status_reasons
+from zope.traversing.api import traverse
+from zope.dublincore.interfaces import IZopeDublinCore
+
+from zope.app.dav.tests.dav import DAVTestCase
+from zope.app.dav.opaquenamespaces import IDAVOpaqueNamespaces
+from zope.app.dav.testing import AppDavLayer
+
+class TestPROPPATCH(DAVTestCase):
+
+    def test_set(self):
+        self.addPage('/pt', u'<span />')
+        transaction.commit()
+        expect = self._makePropstat(('uri://foo',), '<bar xmlns="a0"/>')
+        self.verifyPropOK(path='/pt', namespaces=(('foo', 'uri://foo'),),
+            set=('<foo:bar>spam</foo:bar>',), expect=expect)
+        pt = traverse(self.getRootFolder(), '/pt')
+        self._assertOPropsEqual(pt,
+            {u'uri://foo': {u'bar': '<bar>spam</bar>'}})
+
+    def test_remove(self):
+        self.addPage('/pt', u'<span />')
+        pt = traverse(self.getRootFolder(), '/pt')
+        adapted = IDAVOpaqueNamespaces(pt)
+        adapted[u'uri://foo'] = {u'bar': '<bar>spam</bar>'}
+        transaction.commit()
+        expect = self._makePropstat(('uri://foo',), '<bar xmlns="a0"/>')
+        self.verifyPropOK(path='/pt', namespaces=(('foo', 'uri://foo'),),
+            rm=('<foo:bar/>',), expect=expect)
+        self._assertOPropsEqual(pt, {})
+
+    def test_complex(self):
+        self.addPage('/pt', u'<span />')
+        pt = traverse(self.getRootFolder(), '/pt')
+        adapted = IDAVOpaqueNamespaces(pt)
+        adapted[u'uri://foo'] = {u'bar': '<bar>eggs</bar>'}
+        adapted[u'uri://montypython'] = {u'castle': '<castle>camelot</castle>'}
+        transaction.commit()
+        expect = self._makePropstat(('uri://foo', 'uri://montypython'),
+            '<bar xmlns="a0"/><castle xmlns="a1"/><song xmlns="a1"/>')
+        self.verifyPropOK(path='/pt',
+            namespaces=(('foo', 'uri://foo'), ('mp', 'uri://montypython')),
+            set=('<foo:bar>spam</foo:bar>',),
+            rm=('<mp:castle/>', '<mp:song/>'), expect=expect)
+        self._assertOPropsEqual(pt,
+            {u'uri://foo': {u'bar': '<bar>spam</bar>'}})
+
+    def test_remove_dctitle(self):
+        self.addPage('/pt', u'<span />')
+        pt = traverse(self.getRootFolder(), '/pt')
+        adapted = IZopeDublinCore(pt)
+        adapted.title = u'Test'
+        transaction.commit()
+        # DC Title is a required field with no default, so a 409 is expected
+        expect = self._makePropstat(('http://purl.org/dc/1.1',),
+                                    '<title xmlns="a0"/>', 409)
+        self.verifyPropOK(path='/pt',
+            namespaces=(('DC', 'http://purl.org/dc/1.1'),),
+            rm=('<DC:title/>',), expect=expect)
+
+    def test_set_dctitle(self):
+        self.addPage('/pt', u'<span />')
+        pt = traverse(self.getRootFolder(), '/pt')
+        adapted = IZopeDublinCore(pt)
+        transaction.commit()
+        expect = self._makePropstat(('http://purl.org/dc/1.1',),
+                                    '<title xmlns="a0"/>')
+        self.verifyPropOK(path='/pt',
+            namespaces=(('DC', 'http://purl.org/dc/1.1'),),
+            set=('<DC:title>Test Title</DC:title>',), expect=expect)
+        self.assertEqual(IZopeDublinCore(pt).title, u'Test Title')
+
+    def _assertOPropsEqual(self, obj, expect):
+        oprops = IDAVOpaqueNamespaces(obj)
+        namespacesA = list(oprops.keys())
+        namespacesA.sort()
+        namespacesB = expect.keys()
+        namespacesB.sort()
+        self.assertEqual(namespacesA, namespacesB,
+                         'available opaque namespaces were %s, '
+                         'expected %s' % (namespacesA, namespacesB))
+
+        for ns in namespacesA:
+            propnamesA = list(oprops[ns].keys())
+            propnamesA.sort()
+            propnamesB = expect[ns].keys()
+            propnamesB.sort()
+            self.assertEqual(propnamesA, propnamesB,
+                             'props for opaque namespaces %s were %s, '
+                             'expected %s' % (ns, propnamesA, propnamesB))
+            for prop in propnamesA:
+                valueA = oprops[ns][prop]
+                valueB = expect[ns][prop]
+                self.assertEqual(valueA, valueB,
+                                 'opaque prop %s:%s was %s, '
+                                 'expected %s' % (ns, prop, valueA, valueB))
+
+
+    def _makePropstat(self, ns, properties, status=200):
+        nsattrs = ''
+        count = 0
+        for uri in ns:
+            nsattrs += ' xmlns:a%d="%s"' % (count, uri)
+            count += 1
+        reason = status_reasons[status]
+        return '''<propstat>
+            <prop%s>%s</prop>
+            <status>HTTP/1.1 %d %s</status>
+            </propstat>''' % (nsattrs, properties, status, reason)
+
+    def verifyPropOK(self, path, namespaces=(), set=(), rm=(), expect='',
+                     basic='mgr:mgrpw'):
+        nsAttrs = setProps = removeProps = ''
+        if set:
+            setProps = '<set><prop>\n%s\n</prop></set>\n' % (''.join(set))
+        if rm:
+            removeProps = '<remove><prop>\n%s\n</prop></remove>\n' % (
+                ''.join(rm))
+        for prefix, ns in namespaces:
+            nsAttrs += ' xmlns:%s="%s"' % (prefix, ns)
+        body = """<?xml version="1.0" encoding="utf-8"?>
+        <propertyupdate xmlns="DAV:"%s>
+        %s
+        </propertyupdate>""" % (nsAttrs, setProps + removeProps)
+        result = self.publish(path, basic, env={'REQUEST_METHOD':'PROPPATCH',
+                                                'CONTENT-LENGHT': len(body)},
+                              request_body=body)
+        self.assertEquals(result.getStatus(), 207)
+        s1 = normalize_xml(result.getBody())
+        s2 = normalize_xml("""<?xml version="1.0" encoding="utf-8"?>
+        <multistatus xmlns="DAV:">
+        <response>
+        <href>http://localhost/pt</href>
+        %s
+        </response>
+        </multistatus>""" % expect)
+        self.assertEquals(s1, s2)
+
+
+def test_suite():
+    suite = unittest.TestSuite()
+    TestPROPPATCH.layer = AppDavLayer
+    suite.addTest(unittest.makeSuite(TestPROPPATCH))
+    return suite
+
+
+if __name__ == '__main__':
+    unittest.main()



More information about the Checkins mailing list