[svn r16] svn merge -r8:14 https://svn.secondlife.com/svn/eventlet/branches/beta-1 into https://svn.secondlife.com/svn/eventlet/trunk
This commit is contained in:
@@ -38,9 +38,12 @@ except ImportError:
|
|||||||
pylibsupport.emulate()
|
pylibsupport.emulate()
|
||||||
greenlet = sys.modules['greenlet']
|
greenlet = sys.modules['greenlet']
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import stacklesssupport
|
try:
|
||||||
stacklesssupport.emulate()
|
import stacklesssupport
|
||||||
greenlet = sys.modules['greenlet']
|
stacklesssupport.emulate()
|
||||||
|
greenlet = sys.modules['greenlet']
|
||||||
|
except ImportError:
|
||||||
|
raise ImportError("Unable to find an implementation of greenlet.")
|
||||||
|
|
||||||
from eventlet import greenlib, tls
|
from eventlet import greenlib, tls
|
||||||
|
|
||||||
|
@@ -50,7 +50,6 @@ def host_and_port_from_url(url):
|
|||||||
"""
|
"""
|
||||||
host = None
|
host = None
|
||||||
port = None
|
port = None
|
||||||
#print url
|
|
||||||
parsed_url = urlparse.urlparse(url)
|
parsed_url = urlparse.urlparse(url)
|
||||||
try:
|
try:
|
||||||
host, port = parsed_url[1].split(':')
|
host, port = parsed_url[1].split(':')
|
||||||
@@ -81,19 +80,28 @@ class HttpClient(httplib.HTTPConnection):
|
|||||||
old_putrequest = httplib.HTTPConnection.putrequest
|
old_putrequest = httplib.HTTPConnection.putrequest
|
||||||
putrequest = better_putrequest
|
putrequest = better_putrequest
|
||||||
|
|
||||||
|
|
||||||
def wrap_httplib_with_httpc():
|
|
||||||
httplib.HTTP._connection_class = httplib.HTTPConnection = HttpClient
|
|
||||||
httplib.HTTPS._connection_class = httplib.HTTPSConnection = HttpsClient
|
|
||||||
|
|
||||||
|
|
||||||
class HttpsClient(httplib.HTTPSConnection):
|
class HttpsClient(httplib.HTTPSConnection):
|
||||||
|
"""A subclass of httplib.HTTPSConnection which works around a bug
|
||||||
|
in the interaction between eventlet sockets and httplib. httplib relies
|
||||||
|
on gc to close the socket, causing the socket to be closed too early.
|
||||||
|
|
||||||
|
This is an awful hack and the bug should be fixed properly ASAP.
|
||||||
|
"""
|
||||||
def close(self):
|
def close(self):
|
||||||
pass
|
pass
|
||||||
old_putrequest = httplib.HTTPSConnection.putrequest
|
old_putrequest = httplib.HTTPSConnection.putrequest
|
||||||
putrequest = better_putrequest
|
putrequest = better_putrequest
|
||||||
|
|
||||||
|
|
||||||
|
def wrap_httplib_with_httpc():
|
||||||
|
"""Replace httplib's implementations of these classes with our enhanced ones.
|
||||||
|
|
||||||
|
Needed to work around code that uses httplib directly."""
|
||||||
|
httplib.HTTP._connection_class = httplib.HTTPConnection = HttpClient
|
||||||
|
httplib.HTTPS._connection_class = httplib.HTTPSConnection = HttpsClient
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FileScheme(object):
|
class FileScheme(object):
|
||||||
"""Retarded scheme to local file wrapper."""
|
"""Retarded scheme to local file wrapper."""
|
||||||
host = '<file>'
|
host = '<file>'
|
||||||
@@ -161,6 +169,10 @@ class FileScheme(object):
|
|||||||
|
|
||||||
|
|
||||||
class ConnectionError(Exception):
|
class ConnectionError(Exception):
|
||||||
|
"""Detailed exception class for reporting on http connection problems.
|
||||||
|
|
||||||
|
There are lots of subclasses so you can use closely-specified
|
||||||
|
exception clauses."""
|
||||||
def __init__(self, method, host, port, path, status, reason, body):
|
def __init__(self, method, host, port, path, status, reason, body):
|
||||||
self.method = method
|
self.method = method
|
||||||
self.host = host
|
self.host = host
|
||||||
@@ -180,6 +192,7 @@ class ConnectionError(Exception):
|
|||||||
|
|
||||||
|
|
||||||
class UnparseableResponse(ConnectionError):
|
class UnparseableResponse(ConnectionError):
|
||||||
|
"""Raised when a loader cannot parse the response from the server."""
|
||||||
def __init__(self, content_type, response):
|
def __init__(self, content_type, response):
|
||||||
self.content_type = content_type
|
self.content_type = content_type
|
||||||
self.response = response
|
self.response = response
|
||||||
@@ -193,22 +206,27 @@ class UnparseableResponse(ConnectionError):
|
|||||||
|
|
||||||
|
|
||||||
class Accepted(ConnectionError):
|
class Accepted(ConnectionError):
|
||||||
|
""" 202 Accepted """
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NotFound(ConnectionError):
|
class NotFound(ConnectionError):
|
||||||
|
""" 404 Not Found """
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Forbidden(ConnectionError):
|
class Forbidden(ConnectionError):
|
||||||
|
""" 403 Forbidden """
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class InternalServerError(ConnectionError):
|
class InternalServerError(ConnectionError):
|
||||||
|
""" 500 Internal Server Error """
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Gone(ConnectionError):
|
class Gone(ConnectionError):
|
||||||
|
""" 410 Gone """
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -233,6 +251,12 @@ scheme_to_factory_map = {
|
|||||||
|
|
||||||
|
|
||||||
def make_connection(scheme, location, use_proxy):
|
def make_connection(scheme, location, use_proxy):
|
||||||
|
""" Create a connection object to a host:port.
|
||||||
|
|
||||||
|
@param scheme Protocol, scheme, whatever you want to call it. http, file, https are currently supported.
|
||||||
|
@param location Hostname and port number, formatted as host:port or http://host:port if you're so inclined.
|
||||||
|
@param use_proxy Connect to a proxy instead of the actual location. Uses environment variables to decide where the proxy actually lives.
|
||||||
|
"""
|
||||||
if use_proxy:
|
if use_proxy:
|
||||||
if "http_proxy" in os.environ:
|
if "http_proxy" in os.environ:
|
||||||
location = os.environ["http_proxy"]
|
location = os.environ["http_proxy"]
|
||||||
@@ -241,7 +265,7 @@ def make_connection(scheme, location, use_proxy):
|
|||||||
else:
|
else:
|
||||||
location = "localhost:3128" #default to local squid
|
location = "localhost:3128" #default to local squid
|
||||||
|
|
||||||
# run a little heuristic to see if it's an url, and if so parse out the hostpart
|
# run a little heuristic to see if location is an url, and if so parse out the hostpart
|
||||||
if location.startswith('http'):
|
if location.startswith('http'):
|
||||||
_scheme, location, path, parameters, query, fragment = urlparse.urlparse(location)
|
_scheme, location, path, parameters, query, fragment = urlparse.urlparse(location)
|
||||||
|
|
||||||
@@ -251,11 +275,25 @@ def make_connection(scheme, location, use_proxy):
|
|||||||
|
|
||||||
|
|
||||||
def connect(url, use_proxy=False):
|
def connect(url, use_proxy=False):
|
||||||
|
""" Create a connection object to the host specified in a url. Convenience function for make_connection."""
|
||||||
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
||||||
return make_connection(scheme, location, use_proxy)
|
return make_connection(scheme, location, use_proxy)
|
||||||
|
|
||||||
|
|
||||||
def request(connection, method, url, body='', headers=None, dumper=None, loader=None, use_proxy=False, verbose=False, ok=None):
|
def request(connection, method, url, body='', headers=None, dumper=None, loader=None, use_proxy=False, verbose=False, ok=None):
|
||||||
|
"""Make an http request to a url, for internal use mostly.
|
||||||
|
|
||||||
|
@param connection The connection (as returned by make_connection) to use for the request.
|
||||||
|
@param method HTTP method
|
||||||
|
@param url Full url to make request on.
|
||||||
|
@param body HTTP body, if necessary for the method. Can be any object, assuming an appropriate dumper is also provided.
|
||||||
|
@param headers Dict of header name to header value
|
||||||
|
@param dumper Method that formats the body as a string.
|
||||||
|
@param loader Method that converts the response body into an object.
|
||||||
|
@param use_proxy Set to True if the connection is to a proxy.
|
||||||
|
@param verbose Set to true to change the return value of the function to: status, status_message, body
|
||||||
|
@param ok Set of valid response statuses. If the returned status is not in this list, an exception is thrown.
|
||||||
|
"""
|
||||||
if ok is None:
|
if ok is None:
|
||||||
ok = (200, 201, 204)
|
ok = (200, 201, 204)
|
||||||
if headers is None:
|
if headers is None:
|
||||||
@@ -271,10 +309,12 @@ def request(connection, method, url, body='', headers=None, dumper=None, loader=
|
|||||||
if scheme == 'file':
|
if scheme == 'file':
|
||||||
use_proxy = False
|
use_proxy = False
|
||||||
|
|
||||||
|
if method in ('PUT', 'POST'):
|
||||||
if dumper is not None:
|
if dumper is not None:
|
||||||
body = dumper(body)
|
body = dumper(body)
|
||||||
headers['content-length'] = len(body)
|
# don't set content-length header because httplib does it for us in _send_request
|
||||||
|
else:
|
||||||
|
body = ''
|
||||||
|
|
||||||
connection.request(method, url, body, headers)
|
connection.request(method, url, body, headers)
|
||||||
response = connection.getresponse()
|
response = connection.getresponse()
|
||||||
@@ -286,13 +326,11 @@ def request(connection, method, url, body='', headers=None, dumper=None, loader=
|
|||||||
|
|
||||||
body = response.read()
|
body = response.read()
|
||||||
|
|
||||||
if loader is None:
|
if loader is not None:
|
||||||
return body
|
try:
|
||||||
|
body = loader(body)
|
||||||
try:
|
except Exception, e:
|
||||||
body = loader(body)
|
raise UnparseableResponse(loader, body)
|
||||||
except Exception, e:
|
|
||||||
raise UnparseableResponse(loader, body)
|
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
return response.status, response.msg, body
|
return response.status, response.msg, body
|
||||||
@@ -324,7 +362,7 @@ class HttpSuite(object):
|
|||||||
#import pdb; pdb.Pdb().set_trace()
|
#import pdb; pdb.Pdb().set_trace()
|
||||||
if headers is None:
|
if headers is None:
|
||||||
headers = {}
|
headers = {}
|
||||||
connection = connect(url)
|
connection = connect(url, use_proxy)
|
||||||
return request(connection, 'GET', url, '', headers, None, self.loader, use_proxy, verbose, ok)
|
return request(connection, 'GET', url, '', headers, None, self.loader, use_proxy, verbose, ok)
|
||||||
|
|
||||||
def put(self, url, data, headers=None, content_type=None, verbose=False, ok=None):
|
def put(self, url, data, headers=None, content_type=None, verbose=False, ok=None):
|
||||||
@@ -341,7 +379,6 @@ class HttpSuite(object):
|
|||||||
return request(connect(url), 'DELETE', url, verbose=verbose, ok=ok)
|
return request(connect(url), 'DELETE', url, verbose=verbose, ok=ok)
|
||||||
|
|
||||||
def post(self, url, data='', headers=None, content_type=None, verbose=False, ok=None):
|
def post(self, url, data='', headers=None, content_type=None, verbose=False, ok=None):
|
||||||
connection = connect(url)
|
|
||||||
if headers is None:
|
if headers is None:
|
||||||
headers = {}
|
headers = {}
|
||||||
if 'content-type' not in headers:
|
if 'content-type' not in headers:
|
||||||
@@ -353,6 +390,7 @@ class HttpSuite(object):
|
|||||||
|
|
||||||
|
|
||||||
def make_suite(dumper, loader, fallback_content_type):
|
def make_suite(dumper, loader, fallback_content_type):
|
||||||
|
""" Return a tuple of methods for making http requests with automatic bidirectional formatting with a particular content-type."""
|
||||||
suite = HttpSuite(dumper, loader, fallback_content_type)
|
suite = HttpSuite(dumper, loader, fallback_content_type)
|
||||||
return suite.get, suite.put, suite.delete, suite.post
|
return suite.get, suite.put, suite.delete, suite.post
|
||||||
|
|
||||||
|
@@ -295,7 +295,7 @@ class Request(object):
|
|||||||
typ, val, tb = sys.exc_info()
|
typ, val, tb = sys.exc_info()
|
||||||
body = dict(type=str(typ), error=True, reason=str(val))
|
body = dict(type=str(typ), error=True, reason=str(val))
|
||||||
self.response(response)
|
self.response(response)
|
||||||
if type(body) is str:
|
if(type(body) is str and not self.response_written()):
|
||||||
self.write(body)
|
self.write(body)
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@@ -450,7 +450,7 @@ class Server(BaseHTTPServer.HTTPServer):
|
|||||||
self.log = self
|
self.log = self
|
||||||
|
|
||||||
def write(self, something):
|
def write(self, something):
|
||||||
sys.stdout.write('%s\n' % (something, ))
|
sys.stdout.write('%s' % (something, ))
|
||||||
|
|
||||||
def log_message(self, message):
|
def log_message(self, message):
|
||||||
self.log.write(message)
|
self.log.write(message)
|
||||||
@@ -463,7 +463,7 @@ class Server(BaseHTTPServer.HTTPServer):
|
|||||||
client_address, date_time, requestline, code, size, request_time
|
client_address, date_time, requestline, code, size, request_time
|
||||||
"""
|
"""
|
||||||
self.log.write(
|
self.log.write(
|
||||||
'%s - - [%s] "%s" %s %s %.6f' % args)
|
'%s - - [%s] "%s" %s %s %.6f\n' % args)
|
||||||
|
|
||||||
|
|
||||||
def server(sock, site, log=None, max_size=512):
|
def server(sock, site, log=None, max_size=512):
|
||||||
|
@@ -42,6 +42,9 @@ class Process(object):
|
|||||||
self.command = command
|
self.command = command
|
||||||
self.args = args
|
self.args = args
|
||||||
self._dead_callback = dead_callback
|
self._dead_callback = dead_callback
|
||||||
|
self.run()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
self.dead = False
|
self.dead = False
|
||||||
self.started = False
|
self.started = False
|
||||||
self.popen4 = None
|
self.popen4 = None
|
||||||
|
@@ -86,7 +86,7 @@ class Hub(object):
|
|||||||
pass
|
pass
|
||||||
if exc is not None:
|
if exc is not None:
|
||||||
try:
|
try:
|
||||||
exc()
|
exc(fileno)
|
||||||
except self.runloop.SYSTEM_EXCEPTIONS:
|
except self.runloop.SYSTEM_EXCEPTIONS:
|
||||||
self.squelch_exception(fileno, sys.exc_info())
|
self.squelch_exception(fileno, sys.exc_info())
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ class Hub(object):
|
|||||||
writers = self.writers
|
writers = self.writers
|
||||||
excs = self.excs
|
excs = self.excs
|
||||||
try:
|
try:
|
||||||
r, w, ig = select.select(readers, writers, [], seconds)
|
r, w, ig = select.select(readers.keys(), writers.keys(), [], seconds)
|
||||||
except select.error, e:
|
except select.error, e:
|
||||||
if e.args[0] == errno.EINTR:
|
if e.args[0] == errno.EINTR:
|
||||||
return
|
return
|
||||||
|
Reference in New Issue
Block a user