Index: third_party/twisted_8_1/twisted/web/client.py |
diff --git a/third_party/twisted_8_1/twisted/web/client.py b/third_party/twisted_8_1/twisted/web/client.py |
deleted file mode 100644 |
index bdc50b71b6bc4b6ed5ef9f4192b0df34068a026d..0000000000000000000000000000000000000000 |
--- a/third_party/twisted_8_1/twisted/web/client.py |
+++ /dev/null |
@@ -1,434 +0,0 @@ |
-# -*- test-case-name: twisted.web.test.test_webclient -*- |
-# Copyright (c) 2001-2008 Twisted Matrix Laboratories. |
-# See LICENSE for details. |
- |
-""" |
-HTTP client. |
-""" |
- |
-import os, types |
-from urlparse import urlunparse |
- |
-from twisted.web import http |
-from twisted.internet import defer, protocol, reactor |
-from twisted.python import failure |
-from twisted.python.util import InsensitiveDict |
-from twisted.web import error |
- |
- |
-class PartialDownloadError(error.Error): |
- """Page was only partially downloaded, we got disconnected in middle. |
- |
- The bit that was downloaded is in the response attribute. |
- """ |
- |
- |
-class HTTPPageGetter(http.HTTPClient): |
- |
- quietLoss = 0 |
- followRedirect = 1 |
- failed = 0 |
- |
- def connectionMade(self): |
- method = getattr(self.factory, 'method', 'GET') |
- self.sendCommand(method, self.factory.path) |
- self.sendHeader('Host', self.factory.headers.get("host", self.factory.host)) |
- self.sendHeader('User-Agent', self.factory.agent) |
- if self.factory.cookies: |
- l=[] |
- for cookie, cookval in self.factory.cookies.items(): |
- l.append('%s=%s' % (cookie, cookval)) |
- self.sendHeader('Cookie', '; '.join(l)) |
- data = getattr(self.factory, 'postdata', None) |
- if data is not None: |
- self.sendHeader("Content-Length", str(len(data))) |
- for (key, value) in self.factory.headers.items(): |
- if key.lower() != "content-length": |
- # we calculated it on our own |
- self.sendHeader(key, value) |
- self.endHeaders() |
- self.headers = {} |
- |
- if data is not None: |
- self.transport.write(data) |
- |
- def handleHeader(self, key, value): |
- key = key.lower() |
- l = self.headers[key] = self.headers.get(key, []) |
- l.append(value) |
- |
- def handleStatus(self, version, status, message): |
- self.version, self.status, self.message = version, status, message |
- self.factory.gotStatus(version, status, message) |
- |
- def handleEndHeaders(self): |
- self.factory.gotHeaders(self.headers) |
- m = getattr(self, 'handleStatus_'+self.status, self.handleStatusDefault) |
- m() |
- |
- def handleStatus_200(self): |
- pass |
- |
- handleStatus_201 = lambda self: self.handleStatus_200() |
- handleStatus_202 = lambda self: self.handleStatus_200() |
- |
- def handleStatusDefault(self): |
- self.failed = 1 |
- |
- def handleStatus_301(self): |
- l = self.headers.get('location') |
- if not l: |
- self.handleStatusDefault() |
- return |
- url = l[0] |
- if self.followRedirect: |
- scheme, host, port, path = \ |
- _parse(url, defaultPort=self.transport.getPeer().port) |
- self.factory.setURL(url) |
- |
- if self.factory.scheme == 'https': |
- from twisted.internet import ssl |
- contextFactory = ssl.ClientContextFactory() |
- reactor.connectSSL(self.factory.host, self.factory.port, |
- self.factory, contextFactory) |
- else: |
- reactor.connectTCP(self.factory.host, self.factory.port, |
- self.factory) |
- else: |
- self.handleStatusDefault() |
- self.factory.noPage( |
- failure.Failure( |
- error.PageRedirect( |
- self.status, self.message, location = url))) |
- self.quietLoss = 1 |
- self.transport.loseConnection() |
- |
- handleStatus_302 = lambda self: self.handleStatus_301() |
- |
- def handleStatus_303(self): |
- self.factory.method = 'GET' |
- self.handleStatus_301() |
- |
- def connectionLost(self, reason): |
- if not self.quietLoss: |
- http.HTTPClient.connectionLost(self, reason) |
- self.factory.noPage(reason) |
- |
- def handleResponse(self, response): |
- if self.quietLoss: |
- return |
- if self.failed: |
- self.factory.noPage( |
- failure.Failure( |
- error.Error( |
- self.status, self.message, response))) |
- if self.factory.method.upper() == 'HEAD': |
- # Callback with empty string, since there is never a response |
- # body for HEAD requests. |
- self.factory.page('') |
- elif self.length != None and self.length != 0: |
- self.factory.noPage(failure.Failure( |
- PartialDownloadError(self.status, self.message, response))) |
- else: |
- self.factory.page(response) |
- # server might be stupid and not close connection. admittedly |
- # the fact we do only one request per connection is also |
- # stupid... |
- self.transport.loseConnection() |
- |
- def timeout(self): |
- self.quietLoss = True |
- self.transport.loseConnection() |
- self.factory.noPage(defer.TimeoutError("Getting %s took longer than %s seconds." % (self.factory.url, self.factory.timeout))) |
- |
- |
-class HTTPPageDownloader(HTTPPageGetter): |
- |
- transmittingPage = 0 |
- |
- def handleStatus_200(self, partialContent=0): |
- HTTPPageGetter.handleStatus_200(self) |
- self.transmittingPage = 1 |
- self.factory.pageStart(partialContent) |
- |
- def handleStatus_206(self): |
- self.handleStatus_200(partialContent=1) |
- |
- def handleResponsePart(self, data): |
- if self.transmittingPage: |
- self.factory.pagePart(data) |
- |
- def handleResponseEnd(self): |
- if self.transmittingPage: |
- self.factory.pageEnd() |
- self.transmittingPage = 0 |
- if self.failed: |
- self.factory.noPage( |
- failure.Failure( |
- error.Error( |
- self.status, self.message, None))) |
- self.transport.loseConnection() |
- |
- |
-class HTTPClientFactory(protocol.ClientFactory): |
- """Download a given URL. |
- |
- @type deferred: Deferred |
- @ivar deferred: A Deferred that will fire when the content has |
- been retrieved. Once this is fired, the ivars `status', `version', |
- and `message' will be set. |
- |
- @type status: str |
- @ivar status: The status of the response. |
- |
- @type version: str |
- @ivar version: The version of the response. |
- |
- @type message: str |
- @ivar message: The text message returned with the status. |
- |
- @type response_headers: dict |
- @ivar response_headers: The headers that were specified in the |
- response from the server. |
- """ |
- |
- protocol = HTTPPageGetter |
- |
- url = None |
- scheme = None |
- host = '' |
- port = None |
- path = None |
- |
- def __init__(self, url, method='GET', postdata=None, headers=None, |
- agent="Twisted PageGetter", timeout=0, cookies=None, |
- followRedirect=1): |
- self.protocol.followRedirect = followRedirect |
- self.timeout = timeout |
- self.agent = agent |
- |
- if cookies is None: |
- cookies = {} |
- self.cookies = cookies |
- if headers is not None: |
- self.headers = InsensitiveDict(headers) |
- else: |
- self.headers = InsensitiveDict() |
- if postdata is not None: |
- self.headers.setdefault('Content-Length', len(postdata)) |
- # just in case a broken http/1.1 decides to keep connection alive |
- self.headers.setdefault("connection", "close") |
- self.postdata = postdata |
- self.method = method |
- |
- self.setURL(url) |
- |
- self.waiting = 1 |
- self.deferred = defer.Deferred() |
- self.response_headers = None |
- |
- def __repr__(self): |
- return "<%s: %s>" % (self.__class__.__name__, self.url) |
- |
- def setURL(self, url): |
- self.url = url |
- scheme, host, port, path = _parse(url) |
- if scheme and host: |
- self.scheme = scheme |
- self.host = host |
- self.port = port |
- self.path = path |
- |
- def buildProtocol(self, addr): |
- p = protocol.ClientFactory.buildProtocol(self, addr) |
- if self.timeout: |
- timeoutCall = reactor.callLater(self.timeout, p.timeout) |
- self.deferred.addBoth(self._cancelTimeout, timeoutCall) |
- return p |
- |
- def _cancelTimeout(self, result, timeoutCall): |
- if timeoutCall.active(): |
- timeoutCall.cancel() |
- return result |
- |
- def gotHeaders(self, headers): |
- self.response_headers = headers |
- if headers.has_key('set-cookie'): |
- for cookie in headers['set-cookie']: |
- cookparts = cookie.split(';') |
- cook = cookparts[0] |
- cook.lstrip() |
- k, v = cook.split('=', 1) |
- self.cookies[k.lstrip()] = v.lstrip() |
- |
- def gotStatus(self, version, status, message): |
- self.version, self.status, self.message = version, status, message |
- |
- def page(self, page): |
- if self.waiting: |
- self.waiting = 0 |
- self.deferred.callback(page) |
- |
- def noPage(self, reason): |
- if self.waiting: |
- self.waiting = 0 |
- self.deferred.errback(reason) |
- |
- def clientConnectionFailed(self, _, reason): |
- if self.waiting: |
- self.waiting = 0 |
- self.deferred.errback(reason) |
- |
- |
-class HTTPDownloader(HTTPClientFactory): |
- """Download to a file.""" |
- |
- protocol = HTTPPageDownloader |
- value = None |
- |
- def __init__(self, url, fileOrName, |
- method='GET', postdata=None, headers=None, |
- agent="Twisted client", supportPartial=0): |
- self.requestedPartial = 0 |
- if isinstance(fileOrName, types.StringTypes): |
- self.fileName = fileOrName |
- self.file = None |
- if supportPartial and os.path.exists(self.fileName): |
- fileLength = os.path.getsize(self.fileName) |
- if fileLength: |
- self.requestedPartial = fileLength |
- if headers == None: |
- headers = {} |
- headers["range"] = "bytes=%d-" % fileLength |
- else: |
- self.file = fileOrName |
- HTTPClientFactory.__init__(self, url, method=method, postdata=postdata, headers=headers, agent=agent) |
- self.deferred = defer.Deferred() |
- self.waiting = 1 |
- |
- def gotHeaders(self, headers): |
- if self.requestedPartial: |
- contentRange = headers.get("content-range", None) |
- if not contentRange: |
- # server doesn't support partial requests, oh well |
- self.requestedPartial = 0 |
- return |
- start, end, realLength = http.parseContentRange(contentRange[0]) |
- if start != self.requestedPartial: |
- # server is acting wierdly |
- self.requestedPartial = 0 |
- |
- def openFile(self, partialContent): |
- if partialContent: |
- file = open(self.fileName, 'rb+') |
- file.seek(0, 2) |
- else: |
- file = open(self.fileName, 'wb') |
- return file |
- |
- def pageStart(self, partialContent): |
- """Called on page download start. |
- |
- @param partialContent: tells us if the download is partial download we requested. |
- """ |
- if partialContent and not self.requestedPartial: |
- raise ValueError, "we shouldn't get partial content response if we didn't want it!" |
- if self.waiting: |
- self.waiting = 0 |
- try: |
- if not self.file: |
- self.file = self.openFile(partialContent) |
- except IOError: |
- #raise |
- self.deferred.errback(failure.Failure()) |
- |
- def pagePart(self, data): |
- if not self.file: |
- return |
- try: |
- self.file.write(data) |
- except IOError: |
- #raise |
- self.file = None |
- self.deferred.errback(failure.Failure()) |
- |
- def pageEnd(self): |
- if not self.file: |
- return |
- try: |
- self.file.close() |
- except IOError: |
- self.deferred.errback(failure.Failure()) |
- return |
- self.deferred.callback(self.value) |
- |
- |
-def _parse(url, defaultPort=None): |
- """ |
- Split the given URL into the scheme, host, port, and path. |
- |
- @type url: C{str} |
- @param url: An URL to parse. |
- |
- @type defaultPort: C{int} or C{None} |
- @param defaultPort: An alternate value to use as the port if the URL does |
- not include one. |
- |
- @return: A four-tuple of the scheme, host, port, and path of the URL. All |
- of these are C{str} instances except for port, which is an C{int}. |
- """ |
- url = url.strip() |
- parsed = http.urlparse(url) |
- scheme = parsed[0] |
- path = urlunparse(('','')+parsed[2:]) |
- if defaultPort is None: |
- if scheme == 'https': |
- defaultPort = 443 |
- else: |
- defaultPort = 80 |
- host, port = parsed[1], defaultPort |
- if ':' in host: |
- host, port = host.split(':') |
- port = int(port) |
- if path == "": |
- path = "/" |
- return scheme, host, port, path |
- |
- |
-def getPage(url, contextFactory=None, *args, **kwargs): |
- """Download a web page as a string. |
- |
- Download a page. Return a deferred, which will callback with a |
- page (as a string) or errback with a description of the error. |
- |
- See HTTPClientFactory to see what extra args can be passed. |
- """ |
- scheme, host, port, path = _parse(url) |
- factory = HTTPClientFactory(url, *args, **kwargs) |
- if scheme == 'https': |
- from twisted.internet import ssl |
- if contextFactory is None: |
- contextFactory = ssl.ClientContextFactory() |
- reactor.connectSSL(host, port, factory, contextFactory) |
- else: |
- reactor.connectTCP(host, port, factory) |
- return factory.deferred |
- |
- |
-def downloadPage(url, file, contextFactory=None, *args, **kwargs): |
- """Download a web page to a file. |
- |
- @param file: path to file on filesystem, or file-like object. |
- |
- See HTTPDownloader to see what extra args can be passed. |
- """ |
- scheme, host, port, path = _parse(url) |
- factory = HTTPDownloader(url, file, *args, **kwargs) |
- if scheme == 'https': |
- from twisted.internet import ssl |
- if contextFactory is None: |
- contextFactory = ssl.ClientContextFactory() |
- reactor.connectSSL(host, port, factory, contextFactory) |
- else: |
- reactor.connectTCP(host, port, factory) |
- return factory.deferred |