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