[Checkins] SVN: z3c.davapp.zopefile/trunk/s Since WebDAV requires a default view defined on an object define a default

Michael Kerrin michael.kerrin at openapp.ie
Thu Feb 14 14:14:06 EST 2008


Log message for revision 83840:
  Since WebDAV requires a default view defined on an object define a default
  view for zope.file content objects that is integrated with z3c.conditionalviews.
  

Changed:
  U   z3c.davapp.zopefile/trunk/setup.py
  U   z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/__init__.py
  U   z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/configure.zcml
  A   z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/defaultview.txt
  A   z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/defaultview.zcml
  U   z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/ftesting.zcml
  U   z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/properties.txt
  A   z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/properties.zcml
  U   z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/tests.py

-=-
Modified: z3c.davapp.zopefile/trunk/setup.py
===================================================================
--- z3c.davapp.zopefile/trunk/setup.py	2008-02-14 16:55:47 UTC (rev 83839)
+++ z3c.davapp.zopefile/trunk/setup.py	2008-02-14 19:14:04 UTC (rev 83840)
@@ -23,6 +23,7 @@
       namespace_packages = ["z3c", "z3c.davapp"],
       install_requires = ["setuptools",
                           "z3c.dav",
+                          "z3c.conditionalviews",
                           "zope.file",
                           ],
       extras_require = dict(test = ["cElementTree"]),

Modified: z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/__init__.py
===================================================================
--- z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/__init__.py	2008-02-14 16:55:47 UTC (rev 83839)
+++ z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/__init__.py	2008-02-14 19:14:04 UTC (rev 83840)
@@ -1,10 +1,11 @@
 import zope.interface
 import zope.component
+import zope.file.download
 import zope.file.interfaces
 
+import z3c.conditionalviews
 import z3c.dav.coreproperties
 
-
 class FileDAVSchema(object):
     """
       >>> from zope.file.file import File
@@ -42,3 +43,15 @@
     @property
     def getcontenttype(self):
         return self.context.mimeType
+
+###############################################################################
+#
+# Define default view of the file object.
+#
+###############################################################################
+
+class Display(zope.file.download.Display):
+
+    @z3c.conditionalviews.ConditionalView
+    def __call__(self):
+        return super(Display, self).__call__()

Modified: z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/configure.zcml
===================================================================
--- z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/configure.zcml	2008-02-14 16:55:47 UTC (rev 83839)
+++ z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/configure.zcml	2008-02-14 19:14:04 UTC (rev 83840)
@@ -1,41 +1,7 @@
-<configure xmlns="http://namespaces.zope.org/zope"
-           xmlns:browser="http://namespaces.zope.org/browser">
+<configure>
 
-  <adapter
-      for="zope.file.interfaces.IFile
-           zope.publisher.interfaces.http.IHTTPRequest"
-      factory="z3c.dav.adapters.DAVDublinCore"
-      />
+  <include package="z3c.davapp.zopefile" file="properties.zcml" />
 
-  <adapter
-      for="zope.file.interfaces.IFile"
-      factory="z3c.dav.adapters.OpaqueProperties"
-      trusted="1"
-      />
+  <include package="z3c.davapp.zopefile" file="defaultview.zcml" />
 
-  <adapter
-      for="zope.file.interfaces.IFile
-           zope.publisher.interfaces.http.IHTTPRequest"
-      provides="z3c.dav.coreproperties.IDAVGetcontenttype"
-      factory=".FileDAVSchema"
-      />
-
-  <adapter
-      for="zope.file.interfaces.IFile
-           zope.publisher.interfaces.http.IHTTPRequest"
-      provides="z3c.dav.coreproperties.IDAVGetcontentlength"
-      factory=".FileDAVSchema"
-      />
-
-  <!--
-      Default view
-  -->
-  <browser:view
-      for="zope.file.interfaces.IFile"
-      name="index.html"
-      class="zope.file.download.Display"
-      permission="zope.View"
-      layer="zope.publisher.interfaces.browser.IBrowserRequest"
-      />
-
 </configure>

Added: z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/defaultview.txt
===================================================================
--- z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/defaultview.txt	                        (rev 0)
+++ z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/defaultview.txt	2008-02-14 19:14:04 UTC (rev 83840)
@@ -0,0 +1,86 @@
+=================
+Default file view
+=================
+
+The default view for the content object needs to be setup in order for WebDAV
+clients to be able to get the data for the DAV compliant resource. For example
+if we have a file called `testfile.txt' in the root folder then the URL
+`http://localhost/testfile.txt' should return the contents of the file. By
+convention the default view is called `index.html' but if this is not
+the case then you will have to re-configure the view to have your default
+view name.
+
+Setup
+-----
+
+  >>> import zope.event
+  >>> import zope.datetime
+  >>> from zope.dublincore.interfaces import IZopeDublinCore
+  >>> from zope.lifecycleevent import ObjectCreatedEvent
+  >>> from zope.file.file import File
+
+Create a content object called `textfile.txt` in the root folder.
+
+  >>> f = File('text/plain', {'charset': 'ascii'})
+  >>> fp = f.open('w')
+  >>> fp.write('%s\n' %('x' * 10) * 5)
+  >>> fp.close()
+
+Emit the `CreateObjectEvent' to generate `modified' and `created' dates.
+
+  >>> zope.event.notify(ObjectCreatedEvent(f))
+
+  >>> getRootFolder()['testfile.txt'] = f
+
+GET
+===
+
+We need to be logged in access the `testfile.txt' resource. I think this is an
+issue with the current permissions defined in `zope.file'.
+
+  >>> resp = http("""
+  ... GET /testfile.txt HTTP/1.1
+  ... """, handle_errors = True)
+  >>> resp.getStatus()
+  401
+
+Log in as the site manager so that we can get the contents.
+
+  >>> resp = http("""
+  ... GET /testfile.txt HTTP/1.1
+  ... Authorization: Basic mgr:mgrpw
+  ... """)
+  >>> resp.getStatus()
+  200
+  >>> resp.getHeader('content-type')
+  'text/plain'
+  >>> resp.getHeader('content-length')
+  '55'
+  >>> print resp.getBody()
+  xxxxxxxxxx
+  xxxxxxxxxx
+  xxxxxxxxxx
+  xxxxxxxxxx
+  xxxxxxxxxx
+
+Since we have define the view I have integrated it with the
+`z3c.conditionalviews' module which can validate most of the HTTP conditional
+requests.
+
+  >>> lmd = resp.getHeader('Last-modified')
+  >>> lmd is not None
+  True
+  >>> lmd_value = long(zope.datetime.time(lmd))
+
+  >>> resp = http("""
+  ... GET /testfile.txt HTTP/1.1
+  ... If-Modified-Since: %s
+  ... Authorization: Basic mgr:mgrpw
+  ... """ % zope.datetime.rfc1123_date(lmd_value + 60))
+  >>> resp.getStatus()
+  304
+
+PUT
+===
+
+???


Property changes on: z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/defaultview.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/defaultview.zcml
===================================================================
--- z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/defaultview.zcml	                        (rev 0)
+++ z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/defaultview.zcml	2008-02-14 19:14:04 UTC (rev 83840)
@@ -0,0 +1,28 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:browser="http://namespaces.zope.org/browser">
+
+  <!--
+      `index.html' is usually the default file name.
+
+      `zope.file' doesn't define a default view of a file object so we will
+      define it here. WebDAV requires that the default view be defined. Note
+      that this declaration can be easily overriden since the adapter is
+      registered against `zope.publisher.interfaces.browser.IBrowserRequest'
+      components.
+  -->
+  <browser:view
+      for="zope.file.interfaces.IFile"
+      name="index.html"
+      class=".Display"
+      permission="zope.View"
+      layer="zope.publisher.interfaces.browser.IBrowserRequest"
+      />
+
+  <adapter
+      for="zope.file.interfaces.IFile
+           zope.publisher.interfaces.browser.IBrowserRequest
+           .Display"
+      factory="z3c.conditionalviews.adapters.LastModificationDate"
+      />
+
+</configure>

Modified: z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/ftesting.zcml
===================================================================
--- z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/ftesting.zcml	2008-02-14 16:55:47 UTC (rev 83839)
+++ z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/ftesting.zcml	2008-02-14 19:14:04 UTC (rev 83840)
@@ -2,6 +2,8 @@
 
   <include package="z3c.dav" file="ftesting.zcml" />
 
+  <include package="z3c.conditionalviews" />
+
   <include package="zope.mimetype" file="meta.zcml"/>
   <include package="zope.mimetype"/>
   <include package="zope.file" />

Modified: z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/properties.txt
===================================================================
--- z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/properties.txt	2008-02-14 16:55:47 UTC (rev 83839)
+++ z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/properties.txt	2008-02-14 19:14:04 UTC (rev 83840)
@@ -3,6 +3,8 @@
 ============================
 
   >>> import z3c.etree
+  >>> import zope.event
+  >>> from zope.lifecycleevent import ObjectCreatedEvent
   >>> from zope.file.file import File
 
   >>> etree = z3c.etree.getEngine()
@@ -14,35 +16,12 @@
   >>> fp.write('%s\n' %('x' * 10) * 5)
   >>> fp.close()
 
+Emit the `CreateObjectEvent' to generate lastmodified and created dates.
+
+  >>> zope.event.notify(ObjectCreatedEvent(f))
   >>> getRootFolder()['testfile.txt'] = f
 
-GET
-===
 
-The default view for the content object needs to be setup in order for WebDAV
-clients to be able to get the data for the DAV compliant resource.
-
-  >>> resp = http("""
-  ... GET /testfile.txt HTTP/1.1
-  ... """, handle_errors = False)
-  >>> resp.getStatus()
-  200
-  >>> resp.getHeader('content-type')
-  'text/plain'
-  >>> resp.getHeader('content-length')
-  '55'
-  >>> print resp.getBody()
-  xxxxxxxxxx
-  xxxxxxxxxx
-  xxxxxxxxxx
-  xxxxxxxxxx
-  xxxxxxxxxx
-
-PUT
-===
-
-???
-
 PROPFIND
 ========
 
@@ -67,15 +46,15 @@
   ... PROPFIND /testfile.txt HTTP/1.1
   ... """, handle_errors = False)
 
-  >>> print resp.getBody() #doctest:+XMLDATA
+  >>> print resp.getBody() #doctest:+XMLDATA,+ELLIPSIS
   <multistatus xmlns="DAV:">
     <response>
       <href>http://localhost/testfile.txt</href>
       <propstat>
         <prop>
-          <creationdate />
+          <creationdate>...</creationdate>
           <displayname />
-          <getlastmodified />
+          <getlastmodified>...</getlastmodified>
           <getcontenttype>text/plain</getcontenttype>
           <getcontentlength>55</getcontentlength>
           <resourcetype />
@@ -210,6 +189,7 @@
     </response>
   </multistatus>
 
+
 Opaque properties
 =================
 

Added: z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/properties.zcml
===================================================================
--- z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/properties.zcml	                        (rev 0)
+++ z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/properties.zcml	2008-02-14 19:14:04 UTC (rev 83840)
@@ -0,0 +1,29 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+  <adapter
+      for="zope.file.interfaces.IFile
+           zope.publisher.interfaces.http.IHTTPRequest"
+      factory="z3c.dav.adapters.DAVDublinCore"
+      />
+
+  <adapter
+      for="zope.file.interfaces.IFile"
+      factory="z3c.dav.adapters.OpaqueProperties"
+      trusted="1"
+      />
+
+  <adapter
+      for="zope.file.interfaces.IFile
+           zope.publisher.interfaces.http.IHTTPRequest"
+      provides="z3c.dav.coreproperties.IDAVGetcontenttype"
+      factory=".FileDAVSchema"
+      />
+
+  <adapter
+      for="zope.file.interfaces.IFile
+           zope.publisher.interfaces.http.IHTTPRequest"
+      provides="z3c.dav.coreproperties.IDAVGetcontentlength"
+      factory=".FileDAVSchema"
+      />
+
+</configure>

Modified: z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/tests.py
===================================================================
--- z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/tests.py	2008-02-14 16:55:47 UTC (rev 83839)
+++ z3c.davapp.zopefile/trunk/src/z3c/davapp/zopefile/tests.py	2008-02-14 19:14:04 UTC (rev 83840)
@@ -20,8 +20,17 @@
         checker = z3c.etree.testing.xmlOutputChecker,
         optionflags = doctest.REPORT_NDIFF | doctest.NORMALIZE_WHITESPACE)
     properties.layer = ZopeFileDAVLayer
+
+    defaultview = zope.file.testing.FunctionalBlobDocFileSuite(
+        "defaultview.txt",
+        setUp = z3c.dav.testing.functionalSetUp,
+        tearDown = z3c.dav.testing.functionalTearDown,
+        checker = z3c.etree.testing.xmlOutputChecker,
+        optionflags = doctest.REPORT_NDIFF | doctest.NORMALIZE_WHITESPACE)
+    defaultview.layer = ZopeFileDAVLayer
                                       
     return unittest.TestSuite((
         doctest.DocTestSuite("z3c.davapp.zopefile"),
         properties,
+        defaultview,
         ))



More information about the Checkins mailing list