Rev 38: Make the test suite pass again for bzr 0.92. in file:///v/home/vila/src/plugins/webdav/

Vincent Ladeuil v.ladeuil+lp at free.fr
Mon Sep 17 11:36:22 BST 2007


At file:///v/home/vila/src/plugins/webdav/

------------------------------------------------------------
revno: 38
revision-id: v.ladeuil+lp at free.fr-20070917103621-fjhbr0hlf2ipjx9m
parent: v.ladeuil+lp at free.fr-20070917081057-3ugmhzecgd3yucl1
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: webdav
timestamp: Mon 2007-09-17 12:36:21 +0200
message:
  Make the test suite pass again for bzr 0.92.
  
  * test_webdav.py: 
  Fix import statements, except for HttpServer which is both a
  module and a class inported in bzrlib.tests which make it
  impossible to import as a module.
  (TestingDAVRequestHandler.send_head): Override send_head because
  python-2.5 version implements the silly behavior of apache
  redirecting directories when they do not end with a slash.
  
  * __init__.py: 
  Fix import statements.
modified:
  __init__.py                    __init__.py-20060816232542-enpjxth2743ttqpq-2
  test_webdav.py                 test_webdav.py-20060823130244-qvg4wqdodnmf5nhs-1
  webdav.py                      webdav.py-20060816232542-enpjxth2743ttqpq-3
-------------- next part --------------
=== modified file '__init__.py'
--- a/__init__.py	2007-09-17 08:10:57 +0000
+++ b/__init__.py	2007-09-17 10:36:21 +0000
@@ -30,14 +30,12 @@
     trace.note('not installing http+webdav:// support'
                ' (only supported for bzr 0.92 and above)')
 else:
-    from bzrlib.transport import (
-        register_lazy_transport
-        )
+    from bzrlib import transport
 
-    register_lazy_transport('https+webdav://',
-                            'bzrlib.plugins.webdav.webdav',
-                            'HttpDavTransport')
-    register_lazy_transport('http+webdav://',
-                            'bzrlib.plugins.webdav.webdav',
-                            'HttpDavTransport')
+    transport.register_lazy_transport('https+webdav://',
+                                      'bzrlib.plugins.webdav.webdav',
+                                      'HttpDavTransport')
+    transport.register_lazy_transport('http+webdav://',
+                                      'bzrlib.plugins.webdav.webdav',
+                                      'HttpDavTransport')
 

=== modified file 'test_webdav.py'
--- a/test_webdav.py	2007-07-22 19:44:23 +0000
+++ b/test_webdav.py	2007-09-17 10:36:21 +0000
@@ -16,9 +16,8 @@
 
 """Tests for the wedav plugin.
 
-This defines the TestingDAVRequestHandler and the HttpServer_Dav
-classes which implements the DAV specification parts used by the
-webdav plugin.
+This defines the TestingDAVRequestHandler and the DAVServer classes which
+implements the DAV specification parts used by the webdav plugin.
 """
 
 # TODO: Implement the  testing of the range header  for both GET
@@ -37,22 +36,18 @@
 import re
 import socket
 import string
-from shutil import (
-    copyfile
-    )
+import shutil
 import sys
 import time
 import urlparse
 
-from bzrlib.errors import (
-    NoSuchFile,
-    )
-from bzrlib.trace import mutter
+from bzrlib import trace
 from bzrlib.tests.HttpServer import (
     HttpServer,
     TestingHTTPRequestHandler,
     )
 
+
 class TestingDAVRequestHandler(TestingHTTPRequestHandler):
     """
     Subclass of TestingHTTPRequestHandler handling DAV requests.
@@ -64,24 +59,23 @@
     _RANGE_HEADER_RE = re.compile(
         r'bytes (?P<begin>\d+)-(?P<end>\d+)/(?P<size>\d+|\*)')
 
-    # On Mac OS X 10.3 + fink, we get EAGAIN (ressource temporary
-    # unavailable)...   permanently :)  when  reading the  client
-    # socket.  The  following helps,  but still, some  tests fail
-    # with a "Broken  pipe".  I guess it may be  a problem in the
-    # test framework, but more investigations are still neeeded.
+    # On Mac OS X >= 10.3 we get EAGAIN (ressource temporary unavailable)...
+    # permanently :) when reading the client socket.  The following helps, but
+    # still, some tests fail with a "Broken pipe".  I guess it may be a problem
+    # in the test framework, but more investigations are still neeeded.
     def _retry_if_not_available(self,func,*args):
         if sys.platform != 'darwin':
             return func(*args)
         else:
             for i in range(1,10):
                 try:
-                    if i > 1: mutter('DAV request retry : [%d]' % i)
+                    if i > 1: trace.mutter('DAV request retry : [%d]' % i)
                     return func(*args)
                 except socket.error, e:
                     if e.args[0] == errno.EAGAIN:
                         time.sleep(0.05)
                         continue
-                    mutter("Hmm, that's worse than I thought")
+                    trace.mutter("Hmm, that's worse than I thought")
                     raise
 
     def _read(self, length):
@@ -131,10 +125,54 @@
             self._readline()
         return length, data
 
+    def send_head(self):
+        """Specialized version of SimpleHttpServer.
+
+        We *don't* want the apache behavior of permanently redirecting
+        directories without trailing slashes to directories with trailing
+        slashes. That's a waste and a severe penalty for clients with high
+        latency.
+
+        The installation documentation of the plugin should mention the
+        DirectorySlash apache directive and insists on turning it *Off*.
+        """
+        path = self.translate_path(self.path)
+        f = None
+        if os.path.isdir(path):
+            for index in "index.html", "index.htm":
+                index = os.path.join(path, index)
+                if os.path.exists(index):
+                    path = index
+                    break
+            else:
+                return self.list_directory(path)
+        ctype = self.guess_type(path)
+        if ctype.startswith('text/'):
+            mode = 'r'
+        else:
+            mode = 'rb'
+        try:
+            f = open(path, mode)
+        except IOError:
+            self.send_error(404, "File not found")
+            return None
+        self.send_response(200)
+        self.send_header("Content-type", ctype)
+        fs = os.fstat(f.fileno())
+        self.send_header("Content-Length", str(fs[6]))
+        self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
+        self.end_headers()
+        return f
+
     def do_PUT(self):
         """Serve a PUT request."""
+        # FIXME: test_put_file_unicode makes us emit a traceback because a
+        # UnicodeEncodeError occurs after the request headers have been sent be
+        # before the body can be send. It's harmless and do not make the test
+        # fails. Adressing that will mean protecting all reads from the socket,
+        # which is too heavy for now -- vila 20070917
         path = self.translate_path(self.path)
-        mutter("do_PUT rel: [%s], abs: [%s]" % (self.path,path))
+        trace.mutter("do_PUT rel: [%s], abs: [%s]" % (self.path,path))
 
         do_append = False
         # Check the Content-Range header
@@ -156,7 +194,7 @@
             self.end_headers()
 
         try:
-            mutter("do_PUT will try to open: [%s]" % path)
+            trace.mutter("do_PUT will try to open: [%s]" % path)
             # Always write in binary mode.
             if do_append:
                 f = open(path,'ab')
@@ -176,7 +214,7 @@
             f.close()
             return
         f.close()
-        mutter("do_PUT done: [%s]" % self.path)
+        trace.mutter("do_PUT done: [%s]" % self.path)
         self.send_response(201)
         self.end_headers()
 
@@ -187,7 +225,7 @@
         MKCOL is an mkdir in DAV terminology for our part.
         """
         path = self.translate_path(self.path)
-        mutter("do_MKCOL rel: [%s], abs: [%s]" % (self.path,path))
+        trace.mutter("do_MKCOL rel: [%s], abs: [%s]" % (self.path,path))
         try:
             os.mkdir(path)
         except (IOError, OSError),e:
@@ -211,15 +249,16 @@
             return
         (scheme, netloc, rel_to,
          params, query, fragment) = urlparse.urlparse(url_to)
-        mutter("urlparse: (%s) [%s]" % (url_to, rel_to))
-        mutter("do_COPY rel_from: [%s], rel_to: [%s]" % (self.path, rel_to))
+        trace.mutter("urlparse: (%s) [%s]" % (url_to, rel_to))
+        trace.mutter("do_COPY rel_from: [%s], rel_to: [%s]" % (self.path,
+                                                               rel_to))
         abs_from = self.translate_path(self.path)
         abs_to = self.translate_path(rel_to)
         try:
             # TODO:  Check that rel_from  exists and  rel_to does
             # not.  In the  mean  time, just  go  along and  trap
             # exceptions
-            copyfile(abs_from,abs_to)
+            shutil.copyfile(abs_from,abs_to)
         except (IOError, OSError), e:
             if e.errno == errno.ENOENT:
                 self.send_error(404,"File not found") ;
@@ -239,7 +278,7 @@
         because we *should* fail to delete a non empty dir.
         """
         path = self.translate_path(self.path)
-        mutter("do_DELETE rel: [%s], abs: [%s]" % (self.path, path))
+        trace.mutter("do_DELETE rel: [%s], abs: [%s]" % (self.path, path))
         try:
             # DAV  makes no  distinction between  files  and dirs
             # when required to nuke them,  but we have to. And we
@@ -280,8 +319,9 @@
             should_overwrite = True
         (scheme, netloc, rel_to,
          params, query, fragment) = urlparse.urlparse(url_to)
-        mutter("urlparse: (%s) [%s]" % (url_to, rel_to))
-        mutter("do_MOVE rel_from: [%s], rel_to: [%s]" % (self.path, rel_to))
+        trace.mutter("urlparse: (%s) [%s]" % (url_to, rel_to))
+        trace.mutter("do_MOVE rel_from: [%s], rel_to: [%s]" % (self.path,
+                                                               rel_to))
         abs_from = self.translate_path(self.path)
         abs_to = self.translate_path(rel_to)
         if should_overwrite is False and os.access(abs_to, os.F_OK):
@@ -313,7 +353,7 @@
     def do_APPEND(self):
         """Serve an APPEND request"""
         path = self.translate_path(self.path)
-        mutter("do_APPEND rel: [%s], abs: [%s]" % (self.path,path))
+        trace.mutter("do_APPEND rel: [%s], abs: [%s]" % (self.path,path))
 
         if self.headers.get('Expect') == '100-continue':
             # Tell the client to go ahead, we're ready to get the content
@@ -322,7 +362,7 @@
 
         try:
             # Always write in binary mode.
-            mutter("do_APPEND will try to open: [%s]" % path)
+            trace.mutter("do_APPEND will try to open: [%s]" % path)
             f = open(path, 'wb+')
         except (IOError, OSError), e :
             self.send_error(409, "Conflict")
@@ -337,7 +377,7 @@
             f.close()
             return
         f.close()
-        mutter("do_APPEND done: [%s]" % self.path)
+        trace.mutter("do_APPEND done: [%s]" % self.path)
         # FIXME: We should send 204 if the file didn't exist before
         self.send_response(201)
         self.end_headers()
@@ -347,17 +387,18 @@
     """Subclass of HttpServer that gives http+webdav urls.
 
     This is for use in testing: connections to this server will always go
-    through pycurl where possible.
+    through _urllib where possible.
     """
 
     def __init__(self):
         # We    have   special    requests    to   handle    that
-        # HttpServer_PyCurl don't know about
+        # HttpServer_urllib doesn't know about
         super(DAVServer,self).__init__(TestingDAVRequestHandler)
 
     # urls returned by this server should require the webdav client impl
     _url_protocol = 'http+webdav'
 
+
 class DAVServer_append(DAVServer):
     """Subclass of HttpServer that gives http+webdav urls.
 

=== modified file 'webdav.py'
--- a/webdav.py	2007-09-17 08:10:57 +0000
+++ b/webdav.py	2007-09-17 10:36:21 +0000
@@ -281,14 +281,6 @@
         request = PUTRequest(abspath, bytes,
                              accepted_errors=[200, 201, 204, 403, 404, 409])
 
-        # FIXME: We just make a mix between the sftp
-        # implementation and the Transport one so there may be
-        # something wrong with default Transport implementation
-        # :-/
-        # jam 20060908 The default Transport implementation just uses
-        # the atomic apis, since all transports already implemented that.
-        # It is better to use non-atomic ones, but old transports need
-        # to be upgraded for that.
         def bare_put_file_non_atomic():
 
             response = self._perform(request)



More information about the bazaar-commits mailing list