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