diff -r 5c931bd3dc1e -r a7766286a7be thirdparty/google_appengine/google/appengine/dist/httplib.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thirdparty/google_appengine/google/appengine/dist/httplib.py Thu Feb 12 12:30:36 2009 +0000 @@ -0,0 +1,385 @@ +#!/usr/bin/env python +# +# Copyright 2007 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Copyright 2008 Python Software Foundation, Ian Bicking, and Google.""" + +import mimetools +import StringIO +import sys + + +CONTINUE = 100 +SWITCHING_PROTOCOLS = 101 +PROCESSING = 102 +OK = 200 +CREATED = 201 +ACCEPTED = 202 +NON_AUTHORITATIVE_INFORMATION = 203 +NO_CONTENT = 204 +RESET_CONTENT = 205 +PARTIAL_CONTENT = 206 +MULTI_STATUS = 207 +IM_USED = 226 +MULTIPLE_CHOICES = 300 +MOVED_PERMANENTLY = 301 +FOUND = 302 +SEE_OTHER = 303 +NOT_MODIFIED = 304 +USE_PROXY = 305 +TEMPORARY_REDIRECT = 307 +BAD_REQUEST = 400 +UNAUTHORIZED = 401 +PAYMENT_REQUIRED = 402 +FORBIDDEN = 403 +NOT_FOUND = 404 +METHOD_NOT_ALLOWED = 405 +NOT_ACCEPTABLE = 406 +PROXY_AUTHENTICATION_REQUIRED = 407 +REQUEST_TIMEOUT = 408 +CONFLICT = 409 +GONE = 410 +LENGTH_REQUIRED = 411 +PRECONDITION_FAILED = 412 +REQUEST_ENTITY_TOO_LARGE = 413 +REQUEST_URI_TOO_LONG = 414 +UNSUPPORTED_MEDIA_TYPE = 415 +REQUESTED_RANGE_NOT_SATISFIABLE = 416 +EXPECTATION_FAILED = 417 +UNPROCESSABLE_ENTITY = 422 +LOCKED = 423 +FAILED_DEPENDENCY = 424 +UPGRADE_REQUIRED = 426 +INTERNAL_SERVER_ERROR = 500 +NOT_IMPLEMENTED = 501 +BAD_GATEWAY = 502 +SERVICE_UNAVAILABLE = 503 +GATEWAY_TIMEOUT = 504 +HTTP_VERSION_NOT_SUPPORTED = 505 +INSUFFICIENT_STORAGE = 507 +NOT_EXTENDED = 510 + +responses = { + 100: 'Continue', + 101: 'Switching Protocols', + + 200: 'OK', + 201: 'Created', + 202: 'Accepted', + 203: 'Non-Authoritative Information', + 204: 'No Content', + 205: 'Reset Content', + 206: 'Partial Content', + + 300: 'Multiple Choices', + 301: 'Moved Permanently', + 302: 'Found', + 303: 'See Other', + 304: 'Not Modified', + 305: 'Use Proxy', + 306: '(Unused)', + 307: 'Temporary Redirect', + + 400: 'Bad Request', + 401: 'Unauthorized', + 402: 'Payment Required', + 403: 'Forbidden', + 404: 'Not Found', + 405: 'Method Not Allowed', + 406: 'Not Acceptable', + 407: 'Proxy Authentication Required', + 408: 'Request Timeout', + 409: 'Conflict', + 410: 'Gone', + 411: 'Length Required', + 412: 'Precondition Failed', + 413: 'Request Entity Too Large', + 414: 'Request-URI Too Long', + 415: 'Unsupported Media Type', + 416: 'Requested Range Not Satisfiable', + 417: 'Expectation Failed', + + 500: 'Internal Server Error', + 501: 'Not Implemented', + 502: 'Bad Gateway', + 503: 'Service Unavailable', + 504: 'Gateway Timeout', + 505: 'HTTP Version Not Supported', +} + +HTTP_PORT = 80 +HTTPS_PORT = 443 + + + + + +class HTTPConnection: + + + protocol = 'http' + default_port = HTTP_PORT + _allow_truncated = True + _follow_redirects = False + + def __init__(self, host, port=None, strict=False, timeout=None): + from google.appengine.api import urlfetch + self._fetch = urlfetch.fetch + self._method_map = { + 'GET': urlfetch.GET, + 'POST': urlfetch.POST, + 'HEAD': urlfetch.HEAD, + 'PUT': urlfetch.PUT, + 'DELETE': urlfetch.DELETE, + } + self.host = host + self.port = port + self._method = self._url = None + self._body = '' + self.headers = [] + + def connect(self): + pass + + def request(self, method, url, body=None, headers=None): + self._method = method + self._url = url + try: + self._body = body.read() + except AttributeError: + self._body = body + if headers is None: + headers = [] + elif hasattr(headers, 'items'): + headers = headers.items() + self.headers = headers + + def putrequest(self, request, selector, skip_host=False, skip_accept_encoding=False): + self._method = request + self._url = selector + + def putheader(self, header, *lines): + line = '\r\n\t'.join(lines) + self.headers.append((header, line)) + + def endheaders(self): + pass + + def set_debuglevel(self, level=None): + pass + + def send(self, data): + self._body += data + + def getresponse(self): + if self.port and self.port != self.default_port: + host = '%s:%s' % (self.host, self.port) + else: + host = self.host + url = '%s://%s%s' % (self.protocol, host, self._url) + headers = dict(self.headers) + + try: + method = self._method_map[self._method.upper()] + except KeyError: + raise ValueError("%r is an unrecognized HTTP method" % self._method) + + response = self._fetch(url, self._body, method, headers, + self._allow_truncated, self._follow_redirects) + return HTTPResponse(response) + + def close(self): + pass + + +class HTTPSConnection(HTTPConnection): + + protocol = 'https' + default_port = HTTPS_PORT + + def __init__(self, host, port=None, key_file=None, cert_file=None, + strict=False, timeout=None): + if key_file is not None or cert_file is not None: + raise NotImplementedError( + "key_file and cert_file arguments are not implemented") + HTTPConnection.__init__(self, host, port=port, strict=strict, + timeout=timeout) + + +class HTTPResponse(object): + + def __init__(self, fetch_response): + self._fetch_response = fetch_response + self.fp = StringIO.StringIO(fetch_response.content) + + def __getattr__(self, attr): + return getattr(self.fp, attr) + + def getheader(self, name, default=None): + return self._fetch_response.headers.get(name, default) + + def getheaders(self): + return self._fetch_response.headers.items() + + @property + def msg(self): + msg = mimetools.Message(StringIO.StringIO('')) + for name, value in self._fetch_response.headers.items(): + msg[name] = value + return msg + + version = 11 + + @property + def status(self): + return self._fetch_response.status_code + + @property + def reason(self): + return responses.get(self._fetch_response.status_code, 'Unknown') + + +class HTTP: + "Compatibility class with httplib.py from 1.5." + + _http_vsn = 11 + _http_vsn_str = 'HTTP/1.1' + + debuglevel = 0 + + _connection_class = HTTPConnection + + def __init__(self, host='', port=None, strict=None): + "Provide a default host, since the superclass requires one." + + if port == 0: + port = None + + self._setup(self._connection_class(host, port, strict)) + + def _setup(self, conn): + self._conn = conn + + self.send = conn.send + self.putrequest = conn.putrequest + self.endheaders = conn.endheaders + self.set_debuglevel = conn.set_debuglevel + + conn._http_vsn = self._http_vsn + conn._http_vsn_str = self._http_vsn_str + + self.file = None + + def connect(self, host=None, port=None): + "Accept arguments to set the host/port, since the superclass doesn't." + self.__init__(host, port) + + def getfile(self): + "Provide a getfile, since the superclass' does not use this concept." + return self.file + + def putheader(self, header, *values): + "The superclass allows only one value argument." + self._conn.putheader(header, '\r\n\t'.join(values)) + + def getreply(self): + """Compat definition since superclass does not define it. + + Returns a tuple consisting of: + - server status code (e.g. '200' if all goes well) + - server "reason" corresponding to status code + - any RFC822 headers in the response from the server + """ + response = self._conn.getresponse() + + self.headers = response.msg + self.file = response.fp + return response.status, response.reason, response.msg + + def close(self): + self._conn.close() + + self.file = None + + +class HTTPS(HTTP): + """Compatibility with 1.5 httplib interface + + Python 1.5.2 did not have an HTTPS class, but it defined an + interface for sending http requests that is also useful for + https. + """ + + _connection_class = HTTPSConnection + + def __init__(self, host='', port=None, key_file=None, cert_file=None, + strict=None): + if key_file is not None or cert_file is not None: + raise NotImplementedError( + "key_file and cert_file arguments are not implemented") + + + if port == 0: + port = None + self._setup(self._connection_class(host, port, key_file, + cert_file, strict)) + + self.key_file = key_file + self.cert_file = cert_file + + +class HTTPException(Exception): + pass + +class NotConnected(HTTPException): + pass + +class InvalidURL(HTTPException): + pass + +class UnknownProtocol(HTTPException): + def __init__(self, version): + self.version = version + HTTPException.__init__(self, version) + +class UnknownTransferEncoding(HTTPException): + pass + +class UnimplementedFileMode(HTTPException): + pass + +class IncompleteRead(HTTPException): + def __init__(self, partial): + self.partial = partial + HTTPException.__init__(self, partial) + +class ImproperConnectionState(HTTPException): + pass + +class CannotSendRequest(ImproperConnectionState): + pass + +class CannotSendHeader(ImproperConnectionState): + pass + +class ResponseNotReady(ImproperConnectionState): + pass + +class BadStatusLine(HTTPException): + def __init__(self, line): + self.line = line + HTTPException.__init__(self, line) + +error = HTTPException