thirdparty/google_appengine/google/appengine/dist/httplib.py
changeset 1278 a7766286a7be
child 2413 d0b7dac5325c
--- /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