many pep8 improvements

This commit is contained in:
mdipierro
2012-10-19 12:33:53 -05:00
parent b716df1a05
commit 4b2ba185ae
117 changed files with 7160 additions and 5670 deletions
+121 -92
View File
@@ -16,21 +16,23 @@ import traceback
VERSION = '1.2.5'
SERVER_NAME = socket.gethostname()
SERVER_SOFTWARE = 'Rocket %s' % VERSION
HTTP_SERVER_SOFTWARE = '%s Python/%s' % (SERVER_SOFTWARE, sys.version.split(' ')[0])
HTTP_SERVER_SOFTWARE = '%s Python/%s' % (
SERVER_SOFTWARE, sys.version.split(' ')[0])
BUF_SIZE = 16384
SOCKET_TIMEOUT = 10 # in secs
THREAD_STOP_CHECK_INTERVAL = 1 # in secs, How often should threads check for a server stop message?
IS_JYTHON = platform.system() == 'Java' # Handle special cases for Jython
SOCKET_TIMEOUT = 10 # in secs
THREAD_STOP_CHECK_INTERVAL = 1 # in secs, How often should threads check for a server stop message?
IS_JYTHON = platform.system() == 'Java' # Handle special cases for Jython
IGNORE_ERRORS_ON_CLOSE = set([errno.ECONNABORTED, errno.ECONNRESET])
DEFAULT_LISTEN_QUEUE_SIZE = 5
DEFAULT_MIN_THREADS = 10
DEFAULT_MAX_THREADS = 0
DEFAULTS = dict(LISTEN_QUEUE_SIZE = DEFAULT_LISTEN_QUEUE_SIZE,
MIN_THREADS = DEFAULT_MIN_THREADS,
MAX_THREADS = DEFAULT_MAX_THREADS)
DEFAULTS = dict(LISTEN_QUEUE_SIZE=DEFAULT_LISTEN_QUEUE_SIZE,
MIN_THREADS=DEFAULT_MIN_THREADS,
MAX_THREADS=DEFAULT_MAX_THREADS)
PY3K = sys.version_info[0] > 2
class NullHandler(logging.Handler):
"A Logging handler to prevent library errors."
def emit(self, record):
@@ -94,6 +96,7 @@ except ImportError:
# TODO - This part is still very experimental.
#from .filelike import FileLikeSocket
class Connection(object):
__slots__ = [
'setblocking',
@@ -170,6 +173,7 @@ except ImportError:
# Import Package Modules
# package imports removed in monolithic build
class FileLikeSocket(object):
def __init__(self, conn, buf_size=BUF_SIZE):
self.conn = conn
@@ -317,13 +321,12 @@ class WSGIFuture(Future):
else:
return super(WSGIFuture, self).set_running_or_notify_cancel()
def remember(self, name, lifespan=None):
self._lifespan = lifespan or self._lifespan
if name in self._mem_dict:
raise NameError('Cannot remember future by name "%s". ' % name + \
'A future already exists with that name.' )
raise NameError('Cannot remember future by name "%s". ' % name +
'A future already exists with that name.')
self._name = name
self._mem_dict[name] = self
@@ -334,6 +337,7 @@ class WSGIFuture(Future):
del self._mem_dict[self._name]
self._name = None
class _WorkItem(object):
def __init__(self, future, fn, args, kwargs):
self.future = future
@@ -353,6 +357,7 @@ class _WorkItem(object):
else:
self.future.set_result(result)
class WSGIExecutor(ThreadPoolExecutor):
multithread = True
multiprocess = False
@@ -366,7 +371,8 @@ class WSGIExecutor(ThreadPoolExecutor):
if self._shutdown_lock.acquire():
if self._shutdown:
self._shutdown_lock.release()
raise RuntimeError('Cannot schedule new futures after shutdown')
raise RuntimeError(
'Cannot schedule new futures after shutdown')
f = WSGIFuture(self.futures)
w = _WorkItem(f, fn, args, kwargs)
@@ -378,6 +384,7 @@ class WSGIExecutor(ThreadPoolExecutor):
else:
return False
class FuturesMiddleware(object):
"Futures middleware that adds a Futures Executor to the environment"
def __init__(self, app, threads=5):
@@ -405,11 +412,13 @@ try:
has_ssl = True
except ImportError:
has_ssl = False
class SSLError(socket.error):
pass
# Import Package Modules
# package imports removed in monolithic build
class Listener(Thread):
"""The Listener class is a class responsible for accepting connections
and queuing them to be processed by a worker thread."""
@@ -446,18 +455,18 @@ class Listener(Thread):
elif not os.path.exists(interface[2]):
data = (interface[2], interface[0], interface[1])
self.err_log.error("Cannot find key file "
"'%s'. Cannot bind to %s:%s" % data)
"'%s'. Cannot bind to %s:%s" % data)
return
elif not os.path.exists(interface[3]):
data = (interface[3], interface[0], interface[1])
self.err_log.error("Cannot find certificate file "
"'%s'. Cannot bind to %s:%s" % data)
"'%s'. Cannot bind to %s:%s" % data)
return
if self.clientcert_req and not os.path.exists(interface[4]):
data = (interface[4], interface[0], interface[1])
self.err_log.error("Cannot find root ca certificate file "
"'%s'. Cannot bind to %s:%s" % data)
"'%s'. Cannot bind to %s:%s" % data)
return
# Set socket options
@@ -499,18 +508,18 @@ class Listener(Thread):
ca_certs = self.interface[4]
cert_reqs = ssl.CERT_OPTIONAL
sock = ssl.wrap_socket(sock,
keyfile = self.interface[2],
certfile = self.interface[3],
server_side = True,
cert_reqs = cert_reqs,
ca_certs = ca_certs,
ssl_version = ssl.PROTOCOL_SSLv23)
keyfile=self.interface[2],
certfile=self.interface[3],
server_side=True,
cert_reqs=cert_reqs,
ca_certs=ca_certs,
ssl_version=ssl.PROTOCOL_SSLv23)
else:
sock = ssl.wrap_socket(sock,
keyfile = self.interface[2],
certfile = self.interface[3],
server_side = True,
ssl_version = ssl.PROTOCOL_SSLv23)
keyfile=self.interface[2],
certfile=self.interface[3],
server_side=True,
ssl_version=ssl.PROTOCOL_SSLv23)
except SSLError:
# Generally this happens when an HTTP request is received on a
@@ -598,19 +607,17 @@ except ImportError:
# package imports removed in monolithic build
# Setup Logging
log = logging.getLogger('Rocket')
log.addHandler(NullHandler())
class Rocket(object):
"""The Rocket class is responsible for handling threads and accepting and
dispatching connections."""
def __init__(self,
interfaces = ('127.0.0.1', 8000),
interfaces=('127.0.0.1', 8000),
method = 'wsgi',
app_info = None,
min_threads = None,
@@ -650,15 +657,16 @@ class Rocket(object):
self.active_queue = Queue()
self._threadpool = ThreadPool(get_method(method),
app_info = app_info,
active_queue = self.active_queue,
monitor_queue = self.monitor_queue,
min_threads = min_threads,
max_threads = max_threads)
app_info=app_info,
active_queue=self.active_queue,
monitor_queue=self.monitor_queue,
min_threads=min_threads,
max_threads=max_threads)
# Build our socket listeners
self.listeners = [Listener(i, queue_size, self.active_queue) for i in self.interfaces]
for ndx in range(len(self.listeners)-1, 0, -1):
self.listeners = [Listener(
i, queue_size, self.active_queue) for i in self.interfaces]
for ndx in range(len(self.listeners) - 1, 0, -1):
if not self.listeners[ndx].ready:
del self.listeners[ndx]
@@ -705,7 +713,8 @@ class Rocket(object):
str_extract = lambda l: (l.addr, l.port, l.secure and '*' or '')
msg = 'Listening on sockets: '
msg += ', '.join(['%s:%i%s' % str_extract(l) for l in self.listeners])
msg += ', '.join(
['%s:%i%s' % str_extract(l) for l in self.listeners])
log.info(msg)
for l in self.listeners:
@@ -730,7 +739,7 @@ class Rocket(object):
return self.stop()
def stop(self, stoplogging = False):
def stop(self, stoplogging=False):
log.info('Stopping %s' % SERVER_SOFTWARE)
self.startstop_lock.acquire()
@@ -773,23 +782,24 @@ class Rocket(object):
self.stop()
self.start()
def CherryPyWSGIServer(bind_addr,
wsgi_app,
numthreads = 10,
server_name = None,
max = -1,
request_queue_size = 5,
timeout = 10,
shutdown_timeout = 5):
numthreads=10,
server_name=None,
max=-1,
request_queue_size=5,
timeout=10,
shutdown_timeout=5):
""" A Cherrypy wsgiserver-compatible wrapper. """
max_threads = max
if max_threads < 0:
max_threads = 0
return Rocket(bind_addr, 'wsgi', {'wsgi_app': wsgi_app},
min_threads = numthreads,
max_threads = max_threads,
queue_size = request_queue_size,
timeout = timeout)
min_threads=numthreads,
max_threads=max_threads,
queue_size=request_queue_size,
timeout=timeout)
# Monolithic build...end of module: rocket\main.py
# Monolithic build...start of module: rocket\monitor.py
@@ -803,6 +813,7 @@ from threading import Thread
# Import Package Modules
# package imports removed in monolithic build
class Monitor(Thread):
# Monitor worker class.
@@ -926,8 +937,10 @@ class Monitor(Thread):
for c in stale:
if __debug__:
# "EXPR and A or B" kept for Py2.4 compatibility
data = (c.client_addr, c.server_port, c.ssl and '*' or '')
self.log.debug('Flushing stale connection: %s:%i%s' % data)
data = (
c.client_addr, c.server_port, c.ssl and '*' or '')
self.log.debug(
'Flushing stale connection: %s:%i%s' % data)
self.connections.remove(c)
list_changed = True
@@ -940,7 +953,6 @@ class Monitor(Thread):
# Dynamically resize the threadpool to adapt to our changing needs.
self._threadpool.dynamic_resize()
def stop(self):
self.active = False
@@ -984,6 +996,7 @@ import logging
log = logging.getLogger('Rocket.Errors.ThreadPool')
log.addHandler(NullHandler())
class ThreadPool:
"""The ThreadPool class is a container class for all the worker threads. It
manages the number of actively running threads."""
@@ -1011,7 +1024,7 @@ class ThreadPool:
self.alive = False
# TODO - Optimize this based on some real-world usage data
self.grow_threshold = int(max_threads/10) + 2
self.grow_threshold = int(max_threads / 10) + 2
if not isinstance(app_info, dict):
app_info = dict()
@@ -1193,7 +1206,9 @@ Content-Type: %s
%s
'''
if IS_JYTHON:
HTTP_METHODS = set(['OPTIONS', 'GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT'])
HTTP_METHODS = set(['OPTIONS', 'GET', 'HEAD', 'POST', 'PUT',
'DELETE', 'TRACE', 'CONNECT'])
class Worker(Thread):
"""The Worker class is a base class responsible for receiving connections
@@ -1223,7 +1238,7 @@ class Worker(Thread):
self.req_log.addHandler(NullHandler())
# Error Log
self.err_log = logging.getLogger('Rocket.Errors.'+self.getName())
self.err_log = logging.getLogger('Rocket.Errors.' + self.getName())
self.err_log.addHandler(NullHandler())
def _handleError(self, typ, val, tb):
@@ -1301,11 +1316,11 @@ class Worker(Thread):
self.err_log.debug('Serving a request')
try:
self.run_app(conn)
log_info = dict(client_ip = conn.client_addr,
time = datetime.now().strftime('%c'),
status = self.status.split(' ')[0],
size = self.size,
request_line = self.request_line)
log_info = dict(client_ip=conn.client_addr,
time=datetime.now().strftime('%c'),
status=self.status.split(' ')[0],
size=self.size,
request_line=self.request_line)
self.req_log.info(LOG_LINE % log_info)
except:
exc = sys.exc_info()
@@ -1314,11 +1329,12 @@ class Worker(Thread):
break
else:
if self.request_line:
log_info = dict(client_ip = conn.client_addr,
time = datetime.now().strftime('%c'),
status = self.status.split(' ')[0],
size = self.size,
request_line = self.request_line + ' - not stopping')
log_info = dict(client_ip=conn.client_addr,
time=datetime.now(
).strftime('%c'),
status=self.status.split(' ')[0],
size=self.size,
request_line=self.request_line + ' - not stopping')
self.req_log.info(LOG_LINE % log_info)
if self.closeConnection:
@@ -1382,13 +1398,15 @@ class Worker(Thread):
except socket.timeout:
raise SocketTimeout("Socket timed out before request.")
except TypeError:
raise SocketClosed("ssl bug caused closer of socket, upgrade to python 2.7")
raise SocketClosed(
"ssl bug caused closer of socket, upgrade to python 2.7")
d = d.strip()
if not d:
if __debug__:
self.err_log.debug('Client did not send a recognizable request.')
self.err_log.debug(
'Client did not send a recognizable request.')
raise SocketClosed('Client closed socket.')
self.request_line = d
@@ -1408,11 +1426,12 @@ class Worker(Thread):
raise BadRequest
req = match.groupdict()
for k,v in req.iteritems():
for k, v in req.iteritems():
if not v:
req[k] = ""
if k == 'path':
req['path'] = r'%2F'.join([unquote(x) for x in re_SLASH.split(v)])
req['path'] = r'%2F'.join(
[unquote(x) for x in re_SLASH.split(v)])
return req
@@ -1421,15 +1440,15 @@ class Worker(Thread):
try:
method, uri, proto = d.split(' ')
if not proto.startswith('HTTP') or \
proto[-3:] not in ('1.0', '1.1') or \
method not in HTTP_METHODS:
proto[-3:] not in ('1.0', '1.1') or \
method not in HTTP_METHODS:
self.send_response('400 Bad Request')
raise BadRequest
except ValueError:
self.send_response('400 Bad Request')
raise BadRequest
req = dict(method=method, protocol = proto)
req = dict(method=method, protocol=proto)
scheme = ''
host = ''
if uri == '*' or uri.startswith('/'):
@@ -1454,7 +1473,6 @@ class Worker(Thread):
host=host)
return req
def read_headers(self, sock_file, environ):
try:
lname = None
@@ -1464,9 +1482,10 @@ class Worker(Thread):
try:
l = str(l, 'ISO-8859-1')
except UnicodeDecodeError:
self.err_log.warning('Invalid request header: '+repr(l))
self.err_log.warning(
'Invalid request header: ' + repr(l))
if l.strip().replace('\0','') == '':
if l.strip().replace('\0', '') == '':
break
elif l[0] in ' \t' and lname:
# Some headers take more than one line
@@ -1476,25 +1495,30 @@ class Worker(Thread):
l = l.split(':', 1)
# HTTP header names are us-ascii encoded
lname = str('HTTP_'+l[0].strip().upper().replace('-', '_'))
lname = str(
'HTTP_' + l[0].strip().upper().replace('-', '_'))
lval = str(l[-1].strip())
environ[lname] = lval
except socket.timeout:
raise SocketTimeout("Socket timed out before request.")
class SocketTimeout(Exception):
"Exception for when a socket times out between requests."
pass
class BadRequest(Exception):
"Exception for when a client sends an incomprehensible request."
pass
class SocketClosed(Exception):
"Exception for when a socket is closed by the client."
pass
class ChunkedReader(object):
def __init__(self, sock_file):
self.stream = sock_file
@@ -1542,6 +1566,7 @@ class ChunkedReader(object):
def readlines(self):
yield self.readline()
def get_method(method):
methods = dict(wsgi=WSGIWorker)
return methods[method.lower()]
@@ -1559,7 +1584,6 @@ from wsgiref.util import FileWrapper
# package imports removed in monolithic build
if PY3K:
from email.utils import formatdate
else:
@@ -1578,6 +1602,7 @@ BASE_ENV = {'SERVER_NAME': SERVER_NAME,
'wsgi.file_wrapper': FileWrapper
}
class WSGIWorker(Worker):
def __init__(self, *args, **kwargs):
"""Builds some instance variables that will last the life of the
@@ -1588,9 +1613,10 @@ class WSGIWorker(Worker):
multithreaded = self.app_info.get('max_threads') != 1
else:
multithreaded = False
self.base_environ = dict({'SERVER_SOFTWARE': self.app_info['server_software'],
'wsgi.multithread': multithreaded,
})
self.base_environ = dict(
{'SERVER_SOFTWARE': self.app_info['server_software'],
'wsgi.multithread': multithreaded,
})
self.base_environ.update(BASE_ENV)
# Grab our application
@@ -1614,7 +1640,7 @@ class WSGIWorker(Worker):
environ = self.base_environ.copy()
# Grab the headers
self.read_headers(sock_file,environ)
self.read_headers(sock_file, environ)
# Add CGI Variables
environ['SERVER_PORT'] = str(conn.server_port)
@@ -1644,7 +1670,7 @@ class WSGIWorker(Worker):
peercert = conn.socket.getpeercert(binary_form=True)
environ['SSL_CLIENT_RAW_CERT'] = \
peercert and ssl.DER_cert_to_PEM_cert(peercert)
except Exception,e:
except Exception, e:
print e
if environ.get('HTTP_TRANSFER_ENCODING', '') == 'chunked':
@@ -1822,7 +1848,7 @@ class WSGIWorker(Worker):
if __debug__:
self.err_log.debug('Finally closing output and sock_file')
if hasattr(output,'close'):
if hasattr(output, 'close'):
output.close()
sock_file.close()
@@ -1833,19 +1859,21 @@ class WSGIWorker(Worker):
# the following code is not part of Rocket but was added in web2py for testing purposes
#
def demo_app(environ, start_response):
global static_folder
import os
types = {'htm': 'text/html','html': 'text/html','gif': 'image/gif',
'jpg': 'image/jpeg','png': 'image/png','pdf': 'applications/pdf'}
types = {'htm': 'text/html', 'html': 'text/html', 'gif': 'image/gif',
'jpg': 'image/jpeg', 'png': 'image/png', 'pdf': 'applications/pdf'}
if static_folder:
if not static_folder.startswith('/'):
static_folder = os.path.join(os.getcwd(),static_folder)
path = os.path.join(static_folder, environ['PATH_INFO'][1:] or 'index.html')
type = types.get(path.split('.')[-1],'text')
static_folder = os.path.join(os.getcwd(), static_folder)
path = os.path.join(
static_folder, environ['PATH_INFO'][1:] or 'index.html')
type = types.get(path.split('.')[-1], 'text')
if os.path.exists(path):
try:
data = open(path,'rb').read()
data = open(path, 'rb').read()
start_response('200 OK', [('Content-Type', type)])
except IOError:
start_response('404 NOT FOUND', [])
@@ -1858,21 +1886,22 @@ def demo_app(environ, start_response):
data = '<html><body><h1>Hello from Rocket Web Server</h1></body></html>'
return [data]
def demo():
from optparse import OptionParser
parser = OptionParser()
parser.add_option("-i", "--ip", dest="ip",default="127.0.0.1",
parser.add_option("-i", "--ip", dest="ip", default="127.0.0.1",
help="ip address of the network interface")
parser.add_option("-p", "--port", dest="port",default="8000",
parser.add_option("-p", "--port", dest="port", default="8000",
help="post where to run web server")
parser.add_option("-s", "--static", dest="static",default=None,
parser.add_option("-s", "--static", dest="static", default=None,
help="folder containing static files")
(options, args) = parser.parse_args()
global static_folder
static_folder = options.static
print 'Rocket running on %s:%s' % (options.ip, options.port)
r=Rocket((options.ip,int(options.port)),'wsgi', {'wsgi_app':demo_app})
r = Rocket((options.ip, int(options.port)), 'wsgi', {'wsgi_app': demo_app})
r.start()
if __name__=='__main__':
if __name__ == '__main__':
demo()