Rev 52: Get more info from list_dir. First step. in http://bazaar.launchpad.net/%7Ebzr/bzr.webdav/webdav

Vincent Ladeuil v.ladeuil+lp at free.fr
Sun Jun 8 22:06:07 BST 2008


At http://bazaar.launchpad.net/%7Ebzr/bzr.webdav/webdav

------------------------------------------------------------
revno: 52
revision-id: v.ladeuil+lp at free.fr-20080608210605-qxz1v5ryh9l7n0qw
parent: v.ladeuil+lp at free.fr-20080608203248-851u25jpfvhofpwp
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: webdav
timestamp: Sun 2008-06-08 23:06:05 +0200
message:
  Get more info from list_dir. First step.
  
  * webdav.py:
  (DavStatHandler.endElement): Add some hooks.
  (DavListDirHandler): Redefined from DavStatHandler to get more
  informations.
  (HttpDavTransport.list_dir): Ask for allprop to get more info.
  
  * test_webdav.py:
  (_get_list_dir_apache2_depth_1_prop,
  _get_list_dir_apache2_depth_1_allprop): Extract realy big examples
  to allow reuse and make tests lighter.
modified:
  test_webdav.py                 test_webdav.py-20060823130244-qvg4wqdodnmf5nhs-1
  webdav.py                      webdav.py-20060816232542-enpjxth2743ttqpq-3
-------------- next part --------------
=== modified file 'test_webdav.py'
--- a/test_webdav.py	2008-06-08 19:34:35 +0000
+++ b/test_webdav.py	2008-06-08 21:06:05 +0000
@@ -420,6 +420,171 @@
         super(TestCaseWithDAVServer, self).setUp()
         self.transport_server = DAVServer
 
+def _get_list_dir_apache2_depth_1_prop():
+    return """<?xml version="1.0" encoding="utf-8"?>
+<D:multistatus xmlns:D="DAV:" xmlns:ns0="DAV:">
+    <D:response>
+        <D:href>/19016477731212686926.835527/</D:href>
+        <D:propstat>
+            <D:prop>
+            </D:prop>
+            <D:status>HTTP/1.1 200 OK</D:status>
+        </D:propstat>
+    </D:response>
+    <D:response>
+        <D:href>/19016477731212686926.835527/a</D:href>
+        <D:propstat>
+            <D:prop>
+            </D:prop>
+            <D:status>HTTP/1.1 200 OK</D:status>
+        </D:propstat>
+    </D:response>
+    <D:response>
+        <D:href>/19016477731212686926.835527/b</D:href>
+        <D:propstat>
+            <D:prop>
+            </D:prop>
+            <D:status>HTTP/1.1 200 OK</D:status>
+        </D:propstat>
+    </D:response>
+    <D:response>
+        <D:href>/19016477731212686926.835527/c/</D:href>
+        <D:propstat>
+            <D:prop>
+            </D:prop>
+            <D:status>HTTP/1.1 200 OK</D:status>
+        </D:propstat>
+    </D:response>
+</D:multistatus>"""
+
+
+def _get_list_dir_apache2_depth_1_allprop():
+    return """<?xml version="1.0" encoding="utf-8"?>
+<D:multistatus xmlns:D="DAV:" xmlns:ns0="DAV:">
+    <D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
+        <D:href>/</D:href>
+        <D:propstat>
+            <D:prop>
+                <lp1:resourcetype><D:collection/></lp1:resourcetype>
+                <lp1:creationdate>2008-06-08T10:50:38Z</lp1:creationdate>
+                <lp1:getlastmodified>Sun, 08 Jun 2008 10:50:38 GMT</lp1:getlastmodified>
+                <lp1:getetag>"da7f5a-cc-7722db80"</lp1:getetag>
+                <D:supportedlock>
+                    <D:lockentry>
+                        <D:lockscope><D:exclusive/></D:lockscope>
+                        <D:locktype><D:write/></D:locktype>
+                    </D:lockentry>
+                    <D:lockentry>
+                        <D:lockscope><D:shared/></D:lockscope>
+                        <D:locktype><D:write/></D:locktype>
+                    </D:lockentry>
+                </D:supportedlock>
+                <D:lockdiscovery/>
+            </D:prop>
+            <D:status>HTTP/1.1 200 OK</D:status>
+        </D:propstat>
+    </D:response>
+    <D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
+        <D:href>/executable</D:href>
+        <D:propstat>
+            <D:prop>
+                <lp1:resourcetype/>
+                <lp1:creationdate>2008-06-08T09:50:15Z</lp1:creationdate>
+                <lp1:getcontentlength>0</lp1:getcontentlength>
+                <lp1:getlastmodified>Sun, 08 Jun 2008 09:50:11 GMT</lp1:getlastmodified>
+                <lp1:getetag>"da9f81-0-9ef33ac0"</lp1:getetag>
+                <lp2:executable>T</lp2:executable>
+                <D:supportedlock>
+                    <D:lockentry>
+                        <D:lockscope><D:exclusive/></D:lockscope>
+                        <D:locktype><D:write/></D:locktype>
+                    </D:lockentry>
+                    <D:lockentry>
+                        <D:lockscope><D:shared/></D:lockscope>
+                        <D:locktype><D:write/></D:locktype>
+                    </D:lockentry>
+                </D:supportedlock>
+                <D:lockdiscovery/>
+            </D:prop>
+            <D:status>HTTP/1.1 200 OK</D:status>
+        </D:propstat>
+    </D:response>
+    <D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
+        <D:href>/read-only</D:href>
+        <D:propstat>
+            <D:prop>
+                <lp1:resourcetype/>
+                <lp1:creationdate>2008-06-08T09:50:11Z</lp1:creationdate>
+                <lp1:getcontentlength>0</lp1:getcontentlength>
+                <lp1:getlastmodified>Sun, 08 Jun 2008 09:50:11 GMT</lp1:getlastmodified>
+                <lp1:getetag>"da9f80-0-9ef33ac0"</lp1:getetag>
+                <lp2:executable>F</lp2:executable>
+                <D:supportedlock>
+                    <D:lockentry>
+                        <D:lockscope><D:exclusive/></D:lockscope>
+                        <D:locktype><D:write/></D:locktype>
+                    </D:lockentry>
+                    <D:lockentry>
+                        <D:lockscope><D:shared/></D:lockscope>
+                        <D:locktype><D:write/></D:locktype>
+                    </D:lockentry>
+                </D:supportedlock>
+                <D:lockdiscovery/>
+            </D:prop>
+            <D:status>HTTP/1.1 200 OK</D:status>
+        </D:propstat>
+    </D:response>
+    <D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
+        <D:href>/titi</D:href>
+        <D:propstat>
+            <D:prop>
+                <lp1:resourcetype/>
+                <lp1:creationdate>2008-06-08T09:49:53Z</lp1:creationdate>
+                <lp1:getcontentlength>6</lp1:getcontentlength>
+                <lp1:getlastmodified>Sun, 08 Jun 2008 09:49:53 GMT</lp1:getlastmodified>
+                <lp1:getetag>"da8cbc-6-9de09240"</lp1:getetag>
+                <lp2:executable>F</lp2:executable>
+                <D:supportedlock>
+                    <D:lockentry>
+                        <D:lockscope><D:exclusive/></D:lockscope>
+                        <D:locktype><D:write/></D:locktype>
+                    </D:lockentry>
+                    <D:lockentry>
+                        <D:lockscope><D:shared/></D:lockscope>
+                        <D:locktype><D:write/></D:locktype>
+                    </D:lockentry>
+                </D:supportedlock>
+                <D:lockdiscovery/>
+            </D:prop>
+            <D:status>HTTP/1.1 200 OK</D:status>
+        </D:propstat>
+    </D:response>
+    <D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
+        <D:href>/toto/</D:href>
+        <D:propstat>
+            <D:prop>
+                <lp1:resourcetype><D:collection/></lp1:resourcetype>
+                <lp1:creationdate>2008-06-06T08:07:07Z</lp1:creationdate>
+                <lp1:getlastmodified>Fri, 06 Jun 2008 08:07:07 GMT</lp1:getlastmodified>
+                <lp1:getetag>"da8cb9-44-f2ac20c0"</lp1:getetag>
+                <D:supportedlock>
+                    <D:lockentry>
+                        <D:lockscope><D:exclusive/></D:lockscope>
+                        <D:locktype><D:write/></D:locktype>
+                    </D:lockentry>
+                    <D:lockentry>
+                        <D:lockscope><D:shared/></D:lockscope>
+                        <D:locktype><D:write/></D:locktype>
+                    </D:lockentry>
+                </D:supportedlock>
+                <D:lockdiscovery/>
+            </D:prop>
+            <D:status>HTTP/1.1 200 OK</D:status>
+        </D:propstat>
+    </D:response>
+</D:multistatus>
+"""
+
 
 class TestDavSaxParser(tests.TestCase):
 
@@ -466,41 +631,7 @@
         self.assertEqual(['titi'], self._extract_dir_content_from_str(example))
 
     def test_list_dir_apache2_example(self):
-        example = """<?xml version="1.0" encoding="utf-8"?>
-<D:multistatus xmlns:D="DAV:" xmlns:ns0="DAV:">
-    <D:response>
-        <D:href>/19016477731212686926.835527/</D:href>
-        <D:propstat>
-            <D:prop>
-            </D:prop>
-            <D:status>HTTP/1.1 200 OK</D:status>
-        </D:propstat>
-    </D:response>
-    <D:response>
-        <D:href>/19016477731212686926.835527/a</D:href>
-        <D:propstat>
-            <D:prop>
-            </D:prop>
-            <D:status>HTTP/1.1 200 OK</D:status>
-        </D:propstat>
-    </D:response>
-    <D:response>
-        <D:href>/19016477731212686926.835527/b</D:href>
-        <D:propstat>
-            <D:prop>
-            </D:prop>
-            <D:status>HTTP/1.1 200 OK</D:status>
-        </D:propstat>
-    </D:response>
-    <D:response>
-        <D:href>/19016477731212686926.835527/c/</D:href>
-        <D:propstat>
-            <D:prop>
-            </D:prop>
-            <D:status>HTTP/1.1 200 OK</D:status>
-        </D:propstat>
-    </D:response>
-</D:multistatus>"""
+        example = _get_list_dir_apache2_depth_1_prop()
         self.assertEqual(['a', 'b', 'c'],
                          self._extract_dir_content_from_str(example))
 
@@ -579,131 +710,7 @@
         self.assertTrue(st.st_mode & stat.S_IXUSR)
 
     def test_stat_apache2_dir_depth_1_example(self):
-        example = """<?xml version="1.0" encoding="utf-8"?>
-<D:multistatus xmlns:D="DAV:" xmlns:ns0="DAV:">
-<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
-<D:href>/</D:href>
-<D:propstat>
-<D:prop>
-<lp1:resourcetype><D:collection/></lp1:resourcetype>
-<lp1:creationdate>2008-06-08T10:50:38Z</lp1:creationdate>
-<lp1:getlastmodified>Sun, 08 Jun 2008 10:50:38 GMT</lp1:getlastmodified>
-<lp1:getetag>"da7f5a-cc-7722db80"</lp1:getetag>
-<D:supportedlock>
-<D:lockentry>
-<D:lockscope><D:exclusive/></D:lockscope>
-<D:locktype><D:write/></D:locktype>
-</D:lockentry>
-<D:lockentry>
-<D:lockscope><D:shared/></D:lockscope>
-<D:locktype><D:write/></D:locktype>
-</D:lockentry>
-</D:supportedlock>
-<D:lockdiscovery/>
-</D:prop>
-<D:status>HTTP/1.1 200 OK</D:status>
-</D:propstat>
-</D:response>
-<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
-<D:href>/executable</D:href>
-<D:propstat>
-<D:prop>
-<lp1:resourcetype/>
-<lp1:creationdate>2008-06-08T09:50:15Z</lp1:creationdate>
-<lp1:getcontentlength>0</lp1:getcontentlength>
-<lp1:getlastmodified>Sun, 08 Jun 2008 09:50:11 GMT</lp1:getlastmodified>
-<lp1:getetag>"da9f81-0-9ef33ac0"</lp1:getetag>
-<lp2:executable>T</lp2:executable>
-<D:supportedlock>
-<D:lockentry>
-<D:lockscope><D:exclusive/></D:lockscope>
-<D:locktype><D:write/></D:locktype>
-</D:lockentry>
-<D:lockentry>
-<D:lockscope><D:shared/></D:lockscope>
-<D:locktype><D:write/></D:locktype>
-</D:lockentry>
-</D:supportedlock>
-<D:lockdiscovery/>
-</D:prop>
-<D:status>HTTP/1.1 200 OK</D:status>
-</D:propstat>
-</D:response>
-<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
-<D:href>/read-only</D:href>
-<D:propstat>
-<D:prop>
-<lp1:resourcetype/>
-<lp1:creationdate>2008-06-08T09:50:11Z</lp1:creationdate>
-<lp1:getcontentlength>0</lp1:getcontentlength>
-<lp1:getlastmodified>Sun, 08 Jun 2008 09:50:11 GMT</lp1:getlastmodified>
-<lp1:getetag>"da9f80-0-9ef33ac0"</lp1:getetag>
-<lp2:executable>F</lp2:executable>
-<D:supportedlock>
-<D:lockentry>
-<D:lockscope><D:exclusive/></D:lockscope>
-<D:locktype><D:write/></D:locktype>
-</D:lockentry>
-<D:lockentry>
-<D:lockscope><D:shared/></D:lockscope>
-<D:locktype><D:write/></D:locktype>
-</D:lockentry>
-</D:supportedlock>
-<D:lockdiscovery/>
-</D:prop>
-<D:status>HTTP/1.1 200 OK</D:status>
-</D:propstat>
-</D:response>
-<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
-<D:href>/titi</D:href>
-<D:propstat>
-<D:prop>
-<lp1:resourcetype/>
-<lp1:creationdate>2008-06-08T09:49:53Z</lp1:creationdate>
-<lp1:getcontentlength>6</lp1:getcontentlength>
-<lp1:getlastmodified>Sun, 08 Jun 2008 09:49:53 GMT</lp1:getlastmodified>
-<lp1:getetag>"da8cbc-6-9de09240"</lp1:getetag>
-<lp2:executable>F</lp2:executable>
-<D:supportedlock>
-<D:lockentry>
-<D:lockscope><D:exclusive/></D:lockscope>
-<D:locktype><D:write/></D:locktype>
-</D:lockentry>
-<D:lockentry>
-<D:lockscope><D:shared/></D:lockscope>
-<D:locktype><D:write/></D:locktype>
-</D:lockentry>
-</D:supportedlock>
-<D:lockdiscovery/>
-</D:prop>
-<D:status>HTTP/1.1 200 OK</D:status>
-</D:propstat>
-</D:response>
-<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
-<D:href>/toto/</D:href>
-<D:propstat>
-<D:prop>
-<lp1:resourcetype><D:collection/></lp1:resourcetype>
-<lp1:creationdate>2008-06-06T08:07:07Z</lp1:creationdate>
-<lp1:getlastmodified>Fri, 06 Jun 2008 08:07:07 GMT</lp1:getlastmodified>
-<lp1:getetag>"da8cb9-44-f2ac20c0"</lp1:getetag>
-<D:supportedlock>
-<D:lockentry>
-<D:lockscope><D:exclusive/></D:lockscope>
-<D:locktype><D:write/></D:locktype>
-</D:lockentry>
-<D:lockentry>
-<D:lockscope><D:shared/></D:lockscope>
-<D:locktype><D:write/></D:locktype>
-</D:lockentry>
-</D:supportedlock>
-<D:lockdiscovery/>
-</D:prop>
-<D:status>HTTP/1.1 200 OK</D:status>
-</D:propstat>
-</D:response>
-</D:multistatus>
-"""
+        example = _get_list_dir_apache2_depth_1_allprop()
         self.assertRaises(errors.InvalidHttpResponse,
                           self._extract_stat_from_str, example)
 

=== modified file 'webdav.py'
--- a/webdav.py	2008-06-08 20:32:48 +0000
+++ b/webdav.py	2008-06-08 21:06:05 +0000
@@ -151,7 +151,7 @@
 
 
 class DavStatHandler(DavResponseHandler):
-    """Handle a PROPPFIND depth 0 DAV response for a file or directory.
+    """Handle a PROPPFIND DAV response for a file or directory.
 
     The expected content is:
     - a multi-status element containing
@@ -182,23 +182,33 @@
         DavResponseHandler.startElement(self, name, attrs)
 
     def endElement(self, name):
-        sname = self._strip_ns(name)
         if self._response_seen:
-            if sname != 'multistatus':
-                raise errors.InvalidHttpResponse(
-                    self.url, msg='Unexpected %s element' % name)
-        else:
-            # We process only the first response (just in case)
-            if self._href_end():
-                self.href = self.chars
-            elif self._getcontentlength_end():
-                self.length = self.chars
-            elif self._executable_end():
-                self.executable = self.chars
-        if sname == 'response':
+            self._additional_response_starting(name)
+
+        if self._href_end():
+            self.href = self.chars
+        elif self._getcontentlength_end():
+            self.length = self.chars
+        elif self._executable_end():
+            self.executable = self.chars
+
+        if self._strip_ns(name) == 'response':
             self._response_seen = True
+            self._response_handled()
         DavResponseHandler.endElement(self, name)
 
+
+    def _response_handled(self):
+        """A response element inside a multistatus have been parsed."""
+        pass
+
+    def _additional_response_starting(self, name):
+        """A additional response element inside a multistatus begins."""
+        sname = self._strip_ns(name)
+        if sname != 'multistatus':
+            raise errors.InvalidHttpResponse(
+                self.url, msg='Unexpected %s element' % name)
+
     def _href_end(self):
         stack = self.elt_stack
         return (len(stack) == 3
@@ -272,35 +282,32 @@
     return _DAVStat(size, is_dir, is_exec)
 
 
-class DavListDirHandler(DavResponseHandler):
-    """Handle a PROPPFIND depth 1 DAV response for a directory.
-
-    The expected content is a multi-status containing a list of response
-    containing at least a href property.
-    """
+class DavListDirHandler(DavStatHandler):
+    """Handle a PROPPFIND depth 1 DAV response for a directory."""
     def __init__(self):
-        DavResponseHandler.__init__(self)
+        DavStatHandler.__init__(self)
         self.dir_content = None
 
     def _validate_handling(self):
         if self.dir_content is not None:
             self.expected_content_handled = True
 
-    def startElement(self, name, attrs):
-        self.chars_wanted = (self._strip_ns(name) == 'href')
-        DavResponseHandler.startElement(self, name, attrs)
-
-    def endElement(self, name):
-        stack = self.elt_stack
-        if (len(stack) == 3
-            and stack[0] == 'multistatus'
-            and stack[1] == 'response'
-             # sax guarantees that name is also href (when ns is stripped)
-            and stack[2] == 'href'):
-            if self.dir_content is None:
-                self.dir_content = []
-            self.dir_content.append(self.chars)
-        DavResponseHandler.endElement(self, name)
+    def _make_response_tuple(self):
+        return (self.href, self.length, self.executable)
+
+    def _response_handled(self):
+        """A response element inside a multistatus have been parsed."""
+        if self.dir_content is None:
+            self.dir_content = []
+        self.dir_content.append(self._make_response_tuple())
+        # Resest the attributes for the next response if any
+        self.href = None
+        self.length = None
+        self.executable = None
+
+    def _additional_response_starting(self, name):
+        """A additional response element inside a multistatus begins."""
+        pass
 
 
 def _extract_dir_content(url, infile):
@@ -321,10 +328,10 @@
             url, msg='Malformed xml response: %s' % e)
     # Reformat for bzr needs
     dir_content = handler.dir_content
-    dir = dir_content[0]
+    dir = dir_content[0][0]
     dir_len = len(dir)
     elements = []
-    for href in dir_content[1:]: # Ignore first element
+    for (href, size, is_exec) in dir_content[1:]: # Ignore first element
         if href.startswith(dir):
             name = href[dir_len:]
             if name.endswith('/'):
@@ -738,7 +745,7 @@
         abspath = self._remote_path(relpath)
         propfind = """<?xml version="1.0" encoding="utf-8" ?>
    <D:propfind xmlns:D="DAV:">
-     <D:prop/>
+     <D:allprop/>
    </D:propfind>
 """
         request = _urllib2_wrappers.Request('PROPFIND', abspath, propfind,



More information about the bazaar-commits mailing list