[Zope3-checkins] CVS: Zope3/src/zope/fssync - fssync.py:1.26
Guido van Rossum
guido@python.org
Tue, 27 May 2003 09:50:56 -0400
Update of /cvs-repository/Zope3/src/zope/fssync
In directory cvs.zope.org:/tmp/cvs-serv15751
Modified Files:
fssync.py
Log Message:
Use an HTTPConnection object rather than the 1.5.2 HTTP compatibility
class. Write the snarfed stream directly to the connection using the
"chunked" transfer-encoding.
=== Zope3/src/zope/fssync/fssync.py 1.25 => 1.26 ===
--- Zope3/src/zope/fssync/fssync.py:1.25 Sun May 25 02:10:03 2003
+++ Zope3/src/zope/fssync/fssync.py Tue May 27 09:50:56 2003
@@ -157,7 +157,7 @@
finally:
f.close()
- def httpreq(self, path, view, datafp=None,
+ def httpreq(self, path, view, datasource=None,
content_type="application/x-snarf"):
"""Issue an HTTP or HTTPS request.
@@ -165,12 +165,13 @@
that the requested path is constructed by concatenating the
path and view arguments.
- If the optional 'datafp' argument is not None, it should be a
- seekable stream from which the input document for the request
- is taken. In this case, a POST request is issued, and the
- content-type header is set to the 'content_type' argument,
- defaulting to 'application/x-snarf'. Otherwise (if datafp is
- None), a GET request is issued and no input document is sent.
+ If the optional 'datasource' argument is not None, it should
+ be a callable with a stream argument which, when called,
+ writes data to the stream. In this case, a POST request is
+ issued, and the content-type header is set to the
+ 'content_type' argument, defaulting to 'application/x-snarf'.
+ Otherwise (if datasource is None), a GET request is issued and
+ no input document is sent.
If the request succeeds and returns a document whose
content-type is 'application/x-snarf', the return value is a tuple
@@ -195,42 +196,33 @@
path += "/"
path += view
if self.roottype == "https":
- h = httplib.HTTPS(self.host_port)
+ conn = httplib.HTTPSConnection(self.host_port)
else:
- h = httplib.HTTP(self.host_port)
- if datafp is None:
- h.putrequest("GET", path)
- filesize = 0 # for PyChecker
+ conn = httplib.HTTPConnection(self.host_port)
+ if datasource is None:
+ conn.putrequest("GET", path)
else:
- datafp.seek(0, 2)
- filesize = datafp.tell()
- datafp.seek(0)
- h.putrequest("POST", path)
- h.putheader("Content-type", content_type)
- h.putheader("Content-length", str(filesize))
+ conn.putrequest("POST", path)
+ conn.putheader("Content-type", content_type)
+ conn.putheader("Transfer-encoding", "chunked")
if self.user_passwd:
auth = base64.encodestring(self.user_passwd).strip()
- h.putheader('Authorization', 'Basic %s' % auth)
- h.putheader("Host", self.host_port)
- h.endheaders()
- if datafp is not None:
- nbytes = 0
- while True:
- buf = datafp.read(8192)
- if not buf:
- break
- nbytes += len(buf)
- h.send(buf)
- assert nbytes == filesize
- errcode, errmsg, headers = h.getreply()
- fp = h.getfile()
- if errcode != 200:
+ conn.putheader('Authorization', 'Basic %s' % auth)
+ conn.putheader("Host", self.host_port)
+ conn.putheader("Connection", "close")
+ conn.endheaders()
+ if datasource is not None:
+ datasource(PretendStream(conn))
+ conn.send("0\r\n\r\n")
+ response = conn.getresponse()
+ if response.status != 200:
raise Error("HTTP error %s (%s); error document:\n%s",
- errcode, errmsg,
- self.slurptext(fp, headers))
- if headers["Content-type"] != "application/x-snarf":
- raise Error(self.slurptext(fp, headers))
- return fp, headers
+ response.status, response.reason,
+ self.slurptext(response.fp, response.msg))
+ elif response.msg["Content-type"] != "application/x-snarf":
+ raise Error(self.slurptext(response.fp, response.msg))
+ else:
+ return response.fp, response.msg
def slurptext(self, fp, headers):
"""Helper to read the result document.
@@ -252,6 +244,17 @@
return data.strip()
return "Content-type: %s" % ctype
+class PretendStream(object):
+
+ """Helper class to turn writes into chunked sends."""
+
+ def __init__(self, conn):
+ self.conn = conn
+
+ def write(self, s):
+ self.conn.send("%x\r\n" % len(s))
+ self.conn.send(s)
+
class FSSync(object):
def __init__(self, metadata=None, network=None, rooturl=None):
@@ -306,19 +309,12 @@
snarffile = tempfile.mktemp(".snf")
head, tail = split(realpath(target))
try:
- f = open(snarffile, "wb")
- try:
+ view = "@@fromFS.snarf?note=%s" % urllib.quote(note)
+ def datasource(f):
snf = Snarfer(f)
snf.add(join(head, tail), tail)
snf.addtree(join(head, "@@Zope"), "@@Zope/")
- finally:
- f.close()
- infp = open(snarffile, "rb")
- view = "@@fromFS.snarf?note=%s" % urllib.quote(note)
- try:
- outfp, headers = self.network.httpreq(path, view, infp)
- finally:
- infp.close()
+ outfp, headers = self.network.httpreq(path, view, datasource)
finally:
pass
if isfile(snarffile):