PEP8 fixes

This commit is contained in:
Adnane Belmadiaf 2012-12-23 22:14:36 +00:00 committed by benoitc
parent 1c9b8460b1
commit 20cd49595a
29 changed files with 207 additions and 84 deletions

View File

@ -1,4 +1,4 @@
# -*- coding: utf-8 -
#
# This file is part of gunicorn released under the MIT license.
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.

View File

@ -13,6 +13,7 @@ from gunicorn.config import Config
from gunicorn import debug
from gunicorn.six import execfile_
class Application(object):
"""\
An application interface for configuring and loading
@ -129,4 +130,3 @@ class Application(object):
sys.stderr.write("\nError: %s\n\n" % e)
sys.stderr.flush()
sys.exit(1)

View File

@ -46,6 +46,7 @@ def make_wsgi_application():
return get_internal_wsgi_application()
return WSGIHandler()
def reload_django_settings():
mod = util.import_module(os.environ['DJANGO_SETTINGS_MODULE'])
@ -63,7 +64,7 @@ def reload_django_settings():
if setting == setting.upper():
setting_value = getattr(mod, setting)
if setting in tuple_settings and type(setting_value) == str:
setting_value = (setting_value,) # In case the user forgot the comma.
setting_value = (setting_value,) # In case the user forgot the comma.
setattr(settings, setting, setting_value)
# Expand entries in INSTALLED_APPS like "django.contrib.*" to a list

View File

@ -9,6 +9,7 @@ import sys
from gunicorn.app.base import Application
from gunicorn import util
def is_setting_mod(path):
return (os.path.isfile(os.path.join(path, "settings.py")) or
os.path.isfile(os.path.join(path, "settings.pyc")))
@ -34,7 +35,7 @@ def find_settings_module(path):
project_path = path
elif os.path.isfile(path):
project_path = os.path.dirname(path)
settings_name, _ = os.path.splitext(os.path.basename(path))
settings_name, _ = os.path.splitext(os.path.basename(path))
return project_path, settings_name
@ -91,7 +92,6 @@ class DjangoApplication(Application):
settings_name))
self.cfg.set("pythonpath", pythonpath)
def load(self):
# set settings
make_default_env(self.cfg)
@ -114,7 +114,6 @@ class DjangoApplicationCommand(Application):
self.do_load_config()
def init(self, *args):
if 'settings' in self.options:
self.options['django_settings'] = self.options.pop('settings')
@ -133,6 +132,7 @@ class DjangoApplicationCommand(Application):
mod = util.import_module("gunicorn.app.django_wsgi")
return mod.make_command_wsgi_application(self.admin_media_path)
def run():
"""\
The ``gunicorn_django`` command line runner for launching Django

View File

@ -18,6 +18,7 @@ SERVER = loadwsgi.SERVER
from gunicorn.app.base import Application
from gunicorn.config import Config
class PasterBaseApplication(Application):
def app_config(self):
@ -60,6 +61,7 @@ class PasterBaseApplication(Application):
fileConfig(config_file, dict(__file__=config_file,
here=os.path.dirname(config_file)))
class PasterApplication(PasterBaseApplication):
def init(self, parser, opts, args):
@ -83,6 +85,7 @@ class PasterApplication(PasterBaseApplication):
def load(self):
return loadapp(self.cfgurl, relative_to=self.relpath)
class PasterServerApplication(PasterBaseApplication):
def __init__(self, app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs):
@ -119,13 +122,12 @@ class PasterServerApplication(PasterBaseApplication):
sys.stderr.flush()
sys.exit(1)
def load_config(self):
if not hasattr(self, "cfgfname"):
return
cfg = self.app_config()
for k,v in cfg.items():
for k, v in cfg.items():
try:
self.cfg.set(k.lower(), v)
except:
@ -147,6 +149,7 @@ def run():
from gunicorn.app.pasterapp import PasterApplication
PasterApplication("%prog [OPTIONS] pasteconfig.ini").run()
def paste_server(app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs):
"""\
A paster server.

View File

@ -9,6 +9,7 @@ import sys
from gunicorn import util
from gunicorn.app.base import Application
class WSGIApplication(Application):
def init(self, parser, opts, args):
@ -23,6 +24,7 @@ class WSGIApplication(Application):
def load(self):
return util.import_app(self.app_uri)
def run():
"""\
The ``gunicorn`` command line runner for launcing Gunicorn with

View File

@ -13,7 +13,6 @@ import sys
import time
import traceback
from gunicorn.errors import HaltServer
from gunicorn.pidfile import Pidfile
from gunicorn.sock import create_sockets
@ -21,6 +20,7 @@ from gunicorn import util
from gunicorn import __version__, SERVER_SOFTWARE
class Arbiter(object):
"""
Arbiter maintain the workers processes alive. It launches or
@ -82,6 +82,7 @@ class Arbiter(object):
def _get_num_workers(self):
return self._num_workers
def _set_num_workers(self, value):
old_value = self._num_workers
self._num_workers = value
@ -106,8 +107,6 @@ class Arbiter(object):
if self.cfg.debug:
self.log.debug("Current configuration:")
for config, value in sorted(self.cfg.settings.items(),
key=lambda setting: setting[1]):
self.log.debug(" %s: %s", config, value.value)
@ -322,7 +321,6 @@ class Arbiter(object):
except KeyboardInterrupt:
sys.exit()
def stop(self, graceful=True):
"""\
Stop workers
@ -367,7 +365,7 @@ class Arbiter(object):
# close all file descriptors except bound sockets
util.closerange(3, fds[0])
util.closerange(fds[-1]+1, util.get_maxfd())
util.closerange(fds[-1] + 1, util.get_maxfd())
os.execvpe(self.START_CTX[0], self.START_CTX['args'], os.environ)
@ -470,7 +468,7 @@ class Arbiter(object):
def spawn_worker(self):
self.worker_age += 1
worker = self.worker_class(self.worker_age, self.pid, self.LISTENERS,
self.app, self.timeout/2.0,
self.app, self.timeout / 2.0,
self.cfg, self.log)
self.cfg.pre_fork(self, worker)
pid = os.fork()

View File

@ -19,11 +19,13 @@ from gunicorn.six import string_types, integer_types, bytes_to_str
KNOWN_SETTINGS = []
def wrap_method(func):
def _wrapped(instance, *args, **kwargs):
return func(*args, **kwargs)
return _wrapped
def make_settings(ignore=None):
settings = {}
ignore = ignore or ()
@ -34,6 +36,7 @@ def make_settings(ignore=None):
settings[setting.name] = setting.copy()
return settings
class Config(object):
def __init__(self, usage=None):
@ -63,10 +66,10 @@ class Config(object):
parser = optparse.OptionParser(**kwargs)
keys = list(self.settings)
def sorter(k):
return (self.settings[k].section, self.settings[k].order)
keys = sorted(self.settings, key=self.settings.__getitem__)
for k in keys:
self.settings[k].add_option(parser)
@ -151,6 +154,7 @@ class SettingMeta(type):
setattr(cls, "desc", desc)
setattr(cls, "short", desc.splitlines()[0])
class Setting(object):
name = None
value = None
@ -201,6 +205,7 @@ class Setting(object):
Setting = SettingMeta('Setting', (Setting,), {})
def validate_bool(val):
if isinstance(val, bool):
return val
@ -213,11 +218,13 @@ def validate_bool(val):
else:
raise ValueError("Invalid boolean: %s" % val)
def validate_dict(val):
if not isinstance(val, dict):
raise TypeError("Value is not a dictionary: %s " % val)
return val
def validate_pos_int(val):
if not isinstance(val, integer_types):
val = int(val, 0)
@ -228,6 +235,7 @@ def validate_pos_int(val):
raise ValueError("Value must be positive: %s" % val)
return val
def validate_string(val):
if val is None:
return None
@ -235,6 +243,7 @@ def validate_string(val):
raise TypeError("Not a string: %s" % val)
return val.strip()
def validate_list_string(val):
if not val:
return []
@ -245,6 +254,7 @@ def validate_list_string(val):
return [validate_string(v) for v in val]
def validate_string_to_list(val):
val = validate_string(val)
@ -253,6 +263,7 @@ def validate_string_to_list(val):
return [v.strip() for v in val.split(",") if v]
def validate_class(val):
if inspect.isfunction(val) or inspect.ismethod(val):
val = val()
@ -260,6 +271,7 @@ def validate_class(val):
return val
return validate_string(val)
def validate_callable(arity):
def _validate_callable(val):
if isinstance(val, string_types):
@ -297,6 +309,7 @@ def validate_user(val):
except KeyError:
raise ConfigError("No such user: '%s'" % val)
def validate_group(val):
if val is None:
return os.getegid()
@ -311,6 +324,7 @@ def validate_group(val):
except KeyError:
raise ConfigError("No such group: '%s'" % val)
def validate_post_request(val):
val = validate_callable(-1)(val)
@ -325,7 +339,6 @@ def validate_post_request(val):
raise TypeError("Value must have an arity of: 4")
class ConfigFile(Setting):
name = "config"
section = "Config File"
@ -340,6 +353,7 @@ class ConfigFile(Setting):
application specific configuration.
"""
class Bind(Setting):
name = "bind"
action = "append"
@ -367,6 +381,7 @@ class Bind(Setting):
and ipv4 interfaces.
"""
class Backlog(Setting):
name = "backlog"
section = "Server Socket"
@ -386,6 +401,7 @@ class Backlog(Setting):
Must be a positive integer. Generally set in the 64-2048 range.
"""
class Workers(Setting):
name = "workers"
section = "Worker Processes"
@ -402,6 +418,7 @@ class Workers(Setting):
application's work load.
"""
class WorkerClass(Setting):
name = "worker_class"
section = "Worker Processes"
@ -430,6 +447,7 @@ class WorkerClass(Setting):
can also load the gevent class with ``egg:gunicorn#gevent``
"""
class WorkerConnections(Setting):
name = "worker_connections"
section = "Worker Processes"
@ -444,6 +462,7 @@ class WorkerConnections(Setting):
This setting only affects the Eventlet and Gevent worker types.
"""
class MaxRequests(Setting):
name = "max_requests"
section = "Worker Processes"
@ -463,6 +482,7 @@ class MaxRequests(Setting):
restarts are disabled.
"""
class Timeout(Setting):
name = "timeout"
section = "Worker Processes"
@ -480,6 +500,7 @@ class Timeout(Setting):
is not tied to the length of time required to handle a single request.
"""
class GracefulTimeout(Setting):
name = "graceful_timeout"
section = "Worker Processes"
@ -496,6 +517,7 @@ class GracefulTimeout(Setting):
be force killed.
"""
class Keepalive(Setting):
name = "keepalive"
section = "Worker Processes"
@ -510,6 +532,7 @@ class Keepalive(Setting):
Generally set in the 1-5 seconds range.
"""
class LimitRequestLine(Setting):
name = "limit_request_line"
section = "Security"
@ -533,6 +556,7 @@ class LimitRequestLine(Setting):
This parameter can be used to prevent any DDOS attack.
"""
class LimitRequestFields(Setting):
name = "limit_request_fields"
section = "Security"
@ -541,7 +565,7 @@ class LimitRequestFields(Setting):
validator = validate_pos_int
type = "int"
default = 100
desc= """\
desc = """\
Limit the number of HTTP headers fields in a request.
This parameter is used to limit the number of headers in a request to
@ -550,6 +574,7 @@ class LimitRequestFields(Setting):
32768.
"""
class LimitRequestFieldSize(Setting):
name = "limit_request_field_size"
section = "Security"
@ -558,13 +583,14 @@ class LimitRequestFieldSize(Setting):
validator = validate_pos_int
type = "int"
default = 8190
desc= """\
desc = """\
Limit the allowed size of an HTTP request header field.
Value is a number from 0 (unlimited) to 8190. to set the limit
on the allowed size of an HTTP request header field.
"""
class Debug(Setting):
name = "debug"
section = "Debugging"
@ -579,6 +605,7 @@ class Debug(Setting):
handling that's sent to clients.
"""
class Spew(Setting):
name = "spew"
section = "Debugging"
@ -592,10 +619,11 @@ class Spew(Setting):
This is the nuclear option.
"""
class ConfigCheck(Setting):
name = "check_config"
section = "Debugging"
cli = ["--check-config",]
cli = ["--check-config", ]
validator = validate_bool
action = "store_true"
default = False
@ -603,6 +631,7 @@ class ConfigCheck(Setting):
Check the configuration..
"""
class PreloadApp(Setting):
name = "preload_app"
section = "Server Mechanics"
@ -619,6 +648,7 @@ class PreloadApp(Setting):
restarting workers.
"""
class Daemon(Setting):
name = "daemon"
section = "Server Mechanics"
@ -633,6 +663,7 @@ class Daemon(Setting):
background.
"""
class Pidfile(Setting):
name = "pidfile"
section = "Server Mechanics"
@ -646,6 +677,7 @@ class Pidfile(Setting):
If not set, no PID file will be written.
"""
class User(Setting):
name = "user"
section = "Server Mechanics"
@ -661,6 +693,7 @@ class User(Setting):
the worker process user.
"""
class Group(Setting):
name = "group"
section = "Server Mechanics"
@ -676,6 +709,7 @@ class Group(Setting):
the worker processes group.
"""
class Umask(Setting):
name = "umask"
section = "Server Mechanics"
@ -694,6 +728,7 @@ class Umask(Setting):
"0xFF", "0022" are valid for decimal, hex, and octal representations)
"""
class TmpUploadDir(Setting):
name = "tmp_upload_dir"
section = "Server Mechanics"
@ -710,6 +745,7 @@ class TmpUploadDir(Setting):
temporary directory.
"""
class SecureSchemeHeader(Setting):
name = "secure_scheme_headers"
section = "Server Mechanics"
@ -734,6 +770,8 @@ class SecureSchemeHeader(Setting):
It is important that your front-end proxy configuration ensures that
the headers defined here can not be passed directly from the client.
"""
class XForwardedFor(Setting):
name = "x_forwarded_for_header"
section = "Server Mechanics"
@ -745,6 +783,7 @@ class XForwardedFor(Setting):
address of the client connection to gunicorn via a proxy.
"""
class ForwardedAllowIPS(Setting):
name = "forwarded_allow_ips"
section = "Server Mechanics"
@ -760,6 +799,7 @@ class ForwardedAllowIPS(Setting):
you still trust the environment)
"""
class AccessLog(Setting):
name = "accesslog"
section = "Logging"
@ -773,6 +813,7 @@ class AccessLog(Setting):
"-" means log to stderr.
"""
class AccessLogFormat(Setting):
name = "access_log_format"
section = "Logging"
@ -804,6 +845,7 @@ class AccessLogFormat(Setting):
{Header}o: response header
"""
class ErrorLog(Setting):
name = "errorlog"
section = "Logging"
@ -817,6 +859,7 @@ class ErrorLog(Setting):
"-" means log to stderr.
"""
class Loglevel(Setting):
name = "loglevel"
section = "Logging"
@ -836,6 +879,7 @@ class Loglevel(Setting):
* critical
"""
class LoggerClass(Setting):
name = "logger_class"
section = "Logging"
@ -869,6 +913,7 @@ Gunicorn uses the standard Python logging module's Configuration
file format.
"""
class Procname(Setting):
name = "proc_name"
section = "Process Naming"
@ -887,6 +932,7 @@ class Procname(Setting):
It defaults to 'gunicorn'.
"""
class DefaultProcName(Setting):
name = "default_proc_name"
section = "Process Naming"
@ -911,6 +957,7 @@ class DjangoSettings(Setting):
DJANGO_SETTINGS_MODULE environment variable will be used.
"""
class PythonPath(Setting):
name = "pythonpath"
section = "Server Mechanics"
@ -925,11 +972,13 @@ class PythonPath(Setting):
'/home/djangoprojects/myproject'.
"""
class OnStarting(Setting):
name = "on_starting"
section = "Server Hooks"
validator = validate_callable(1)
type = "callable"
def on_starting(server):
pass
default = staticmethod(on_starting)
@ -939,11 +988,13 @@ class OnStarting(Setting):
The callable needs to accept a single instance variable for the Arbiter.
"""
class OnReload(Setting):
name = "on_reload"
section = "Server Hooks"
validator = validate_callable(1)
type = "callable"
def on_reload(server):
pass
default = staticmethod(on_reload)
@ -953,11 +1004,13 @@ class OnReload(Setting):
The callable needs to accept a single instance variable for the Arbiter.
"""
class WhenReady(Setting):
name = "when_ready"
section = "Server Hooks"
validator = validate_callable(1)
type = "callable"
def when_ready(server):
pass
default = staticmethod(when_ready)
@ -967,11 +1020,13 @@ class WhenReady(Setting):
The callable needs to accept a single instance variable for the Arbiter.
"""
class Prefork(Setting):
name = "pre_fork"
section = "Server Hooks"
validator = validate_callable(2)
type = "callable"
def pre_fork(server, worker):
pass
default = staticmethod(pre_fork)
@ -982,11 +1037,13 @@ class Prefork(Setting):
new Worker.
"""
class Postfork(Setting):
name = "post_fork"
section = "Server Hooks"
validator = validate_callable(2)
type = "callable"
def post_fork(server, worker):
pass
default = staticmethod(post_fork)
@ -997,11 +1054,13 @@ class Postfork(Setting):
new Worker.
"""
class PreExec(Setting):
name = "pre_exec"
section = "Server Hooks"
validator = validate_callable(1)
type = "callable"
def pre_exec(server):
pass
default = staticmethod(pre_exec)
@ -1011,11 +1070,13 @@ class PreExec(Setting):
The callable needs to accept a single instance variable for the Arbiter.
"""
class PreRequest(Setting):
name = "pre_request"
section = "Server Hooks"
validator = validate_callable(2)
type = "callable"
def pre_request(worker, req):
worker.log.debug("%s %s" % (req.method, req.path))
default = staticmethod(pre_request)
@ -1026,11 +1087,13 @@ class PreRequest(Setting):
the Request.
"""
class PostRequest(Setting):
name = "post_request"
section = "Server Hooks"
validator = validate_post_request
type = "callable"
def post_request(worker, req, environ, resp):
pass
default = staticmethod(post_request)
@ -1041,11 +1104,13 @@ class PostRequest(Setting):
the Request.
"""
class WorkerExit(Setting):
name = "worker_exit"
section = "Server Hooks"
validator = validate_callable(2)
type = "callable"
def worker_exit(server, worker):
pass
default = staticmethod(worker_exit)
@ -1056,11 +1121,13 @@ class WorkerExit(Setting):
the just-exited Worker.
"""
class NumWorkersChanged(Setting):
name = "nworkers_changed"
section = "Server Hooks"
validator = validate_callable(3)
type = "callable"
def nworkers_changed(server, new_value, old_value):
pass
default = staticmethod(nworkers_changed)
@ -1074,6 +1141,7 @@ class NumWorkersChanged(Setting):
None.
"""
class ProxyProtocol(Setting):
name = "proxy_protocol"
section = "Server Mechanics"
@ -1099,6 +1167,7 @@ class ProxyProtocol(Setting):
key = /etc/ssl/certs/stunnel.key
"""
class ProxyAllowFrom(Setting):
name = "proxy_allow_ips"
section = "Server Mechanics"
@ -1109,6 +1178,7 @@ class ProxyAllowFrom(Setting):
Front-end's IPs from which allowed accept proxy requests (comma separate).
"""
class KeyFile(Setting):
name = "keyfile"
section = "Ssl"
@ -1120,6 +1190,7 @@ class KeyFile(Setting):
SSL key file
"""
class CertFile(Setting):
name = "certfile"
section = "Ssl"

View File

@ -16,7 +16,6 @@ __all__ = ['spew', 'unspew']
_token_spliter = re.compile('\W+')
class Spew(object):
"""
"""
@ -69,5 +68,3 @@ def unspew():
"""Remove the trace hook installed by spew.
"""
sys.settrace(None)

View File

@ -12,5 +12,6 @@ class HaltServer(BaseException):
def __str__(self):
return "<HaltServer %r %d>" % (self.reason, self.exit_status)
class ConfigError(BaseException):
""" Exception raised on config error """

View File

@ -17,11 +17,11 @@ from gunicorn import util
from gunicorn.six import string_types
CONFIG_DEFAULTS = dict(
version = 1,
disable_existing_loggers = False,
version=1,
disable_existing_loggers=False,
loggers = {
"root": { "level": "INFO", "handlers": ["console"] },
loggers={
"root": {"level": "INFO", "handlers": ["console"]},
"gunicorn.error": {
"level": "INFO",
"handlers": ["console"],
@ -29,14 +29,14 @@ CONFIG_DEFAULTS = dict(
"qualname": "gunicorn.error"
}
},
handlers = {
handlers={
"console": {
"class": "logging.StreamHandler",
"formatter": "generic",
"stream": "sys.stdout"
}
},
formatters = {
formatters={
"generic": {
"format": "%(asctime)s [%(process)d] [%(levelname)s] %(message)s",
"datefmt": "%Y-%m-%d %H:%M:%S",
@ -45,12 +45,14 @@ CONFIG_DEFAULTS = dict(
}
)
def loggers():
""" get list of all loggers """
root = logging.root
existing = root.manager.loggerDict.keys()
return [logging.getLogger(name) for name in existing]
class LazyWriter(object):
"""
@ -100,6 +102,7 @@ class LazyWriter(object):
def isatty(self):
return bool(self.fileobj and self.fileobj.isatty())
class SafeAtoms(dict):
def __init__(self, atoms):
@ -149,7 +152,6 @@ class Logger(object):
self.error_log.setLevel(loglevel)
self.access_log.setLevel(logging.INFO)
if cfg.errorlog != "-":
# if an error log file is set redirect stdout & stderr to
# this log file.
@ -170,7 +172,6 @@ class Logger(object):
else:
raise RuntimeError("Error: log config '%s' not found" % cfg.logconfig)
def critical(self, msg, *args, **kwargs):
self.error_log.critical(msg, *args, **kwargs)
@ -206,7 +207,7 @@ class Logger(object):
atoms = {
'h': environ.get('REMOTE_ADDR', '-'),
'l': '-',
'u': '-', # would be cool to get username from basic auth header
'u': '-', # would be cool to get username from basic auth header
't': self.now(),
'r': "%s %s %s" % (environ['REQUEST_METHOD'],
environ['RAW_URI'], environ["SERVER_PROTOCOL"]),
@ -225,10 +226,10 @@ class Logger(object):
else:
req_headers = req
atoms.update(dict([("{%s}i" % k.lower(),v) for k, v in req_headers]))
atoms.update(dict([("{%s}i" % k.lower(), v) for k, v in req_headers]))
# add response headers
atoms.update(dict([("{%s}o" % k.lower(),v) for k, v in resp.headers]))
atoms.update(dict([("{%s}o" % k.lower(), v) for k, v in resp.headers]))
# wrap atoms:
# - make sure atoms will be test case insensitively
@ -247,7 +248,6 @@ class Logger(object):
return '[%02d/%s/%04d:%02d:%02d:%02d]' % (now.day, month,
now.year, now.hour, now.minute, now.second)
def reopen_files(self):
if self.cfg.errorlog != "-":
# Close stderr & stdout if they are redirected to error log file
@ -276,7 +276,6 @@ class Logger(object):
finally:
handler.release()
def _get_gunicorn_handler(self, log):
for h in log.handlers:
if getattr(h, "_gunicorn", False) == True:
@ -297,4 +296,3 @@ class Logger(object):
h.setFormatter(fmt)
h._gunicorn = True
log.addHandler(h)

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -
#
# This file is part of gunicorn released under the MIT license.
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.
from gunicorn.http.message import Message, Request
from gunicorn.http.parser import RequestParser
__all__ = [Message, Request, RequestParser]
__all__ = [Message, Request, RequestParser]

View File

@ -28,6 +28,7 @@ if sys.version_info < (2, 6) or \
_libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
_sendfile = _libc.sendfile
def sendfile(fdout, fdin, offset, nbytes):
if sys.platform == 'darwin':
_sendfile.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_uint64,

View File

@ -3,12 +3,11 @@
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.
import sys
from gunicorn.http.errors import (NoMoreData, ChunkMissingTerminator,
InvalidChunkSize)
from gunicorn import six
class ChunkedReader(object):
def __init__(self, req, unreader):
self.req = req
@ -51,7 +50,7 @@ class ChunkedReader(object):
unreader.unread(buf.getvalue()[2:])
return b""
self.req.trailers = self.req.parse_headers(buf.getvalue()[:idx])
unreader.unread(buf.getvalue()[idx+4:])
unreader.unread(buf.getvalue()[idx + 4:])
def parse_chunked(self, unreader):
(size, rest) = self.parse_chunk_size(unreader)
@ -82,7 +81,7 @@ class ChunkedReader(object):
idx = buf.getvalue().find(b"\r\n")
data = buf.getvalue()
line, rest_chunk = data[:idx], data[idx+2:]
line, rest_chunk = data[:idx], data[idx + 2:]
chunk_size = line.split(b";", 1)[0].strip()
try:
@ -104,6 +103,7 @@ class ChunkedReader(object):
raise NoMoreData()
buf.write(data)
class LengthReader(object):
def __init__(self, unreader, length):
self.unreader = unreader
@ -119,7 +119,6 @@ class LengthReader(object):
if size == 0:
return b""
buf = six.BytesIO()
data = self.unreader.read()
while data:
@ -134,6 +133,7 @@ class LengthReader(object):
self.length -= size
return ret
class EOFReader(object):
def __init__(self, unreader):
self.unreader = unreader
@ -171,6 +171,7 @@ class EOFReader(object):
self.buf.write(rest)
return ret
class Body(object):
def __init__(self, reader):
self.reader = reader
@ -233,8 +234,8 @@ class Body(object):
idx = line.find(b"\n")
if idx >= 0:
ret = line[:idx+1]
self.buf.write(line[idx+1:])
ret = line[:idx + 1]
self.buf.write(line[idx + 1:])
self.buf.write(extra_buf_data)
return ret
self.buf.write(extra_buf_data)
@ -249,6 +250,6 @@ class Body(object):
ret.append(data)
data = b""
else:
line, data = data[:pos+1], data[pos+1:]
line, data = data[:pos + 1], data[pos + 1:]
ret.append(line)
return ret

View File

@ -3,9 +3,11 @@
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.
class ParseException(Exception):
pass
class NoMoreData(IOError):
def __init__(self, buf=None):
self.buf = buf
@ -13,6 +15,7 @@ class NoMoreData(IOError):
def __str__(self):
return "No more data after: %r" % self.buf
class InvalidRequestLine(ParseException):
def __init__(self, req):
self.req = req
@ -21,6 +24,7 @@ class InvalidRequestLine(ParseException):
def __str__(self):
return "Invalid HTTP request line: %r" % self.req
class InvalidRequestMethod(ParseException):
def __init__(self, method):
self.method = method
@ -28,6 +32,7 @@ class InvalidRequestMethod(ParseException):
def __str__(self):
return "Invalid HTTP method: %r" % self.method
class InvalidHTTPVersion(ParseException):
def __init__(self, version):
self.version = version
@ -35,6 +40,7 @@ class InvalidHTTPVersion(ParseException):
def __str__(self):
return "Invalid HTTP Version: %s" % self.version
class InvalidHeader(ParseException):
def __init__(self, hdr, req=None):
self.hdr = hdr
@ -43,6 +49,7 @@ class InvalidHeader(ParseException):
def __str__(self):
return "Invalid HTTP Header: %s" % self.hdr
class InvalidHeaderName(ParseException):
def __init__(self, hdr):
self.hdr = hdr
@ -50,6 +57,7 @@ class InvalidHeaderName(ParseException):
def __str__(self):
return "Invalid HTTP header name: %s" % self.hdr
class InvalidChunkSize(IOError):
def __init__(self, data):
self.data = data
@ -57,6 +65,7 @@ class InvalidChunkSize(IOError):
def __str__(self):
return "Invalid chunk size: %r" % self.data
class ChunkMissingTerminator(IOError):
def __init__(self, term):
self.term = term
@ -73,6 +82,7 @@ class LimitRequestLine(ParseException):
def __str__(self):
return "Request Line is too large (%s > %s)" % (self.size, self.max_size)
class LimitRequestHeaders(ParseException):
def __init__(self, msg):
self.msg = msg

View File

@ -19,6 +19,7 @@ MAX_REQUEST_LINE = 8190
MAX_HEADERS = 32768
MAX_HEADERFIELD_SIZE = 8190
class Message(object):
def __init__(self, cfg, unreader):
self.cfg = cfg
@ -150,7 +151,6 @@ class Request(Message):
self.proxy_protocol_info = None
super(Request, self).__init__(cfg, unreader)
def get_data(self, unreader, buf, stop=False):
data = unreader.read()
if not data:
@ -200,7 +200,7 @@ class Request(Message):
self.headers = self.parse_headers(data[:idx])
ret = data[idx+4:]
ret = data[idx + 4:]
buf = BytesIO()
return ret
@ -220,8 +220,8 @@ class Request(Message):
if len(data) - 2 > limit > 0:
raise LimitRequestLine(len(data), limit)
return (data[:idx], # request line,
data[idx + 2:]) # residue in the buffer, skip \r\n
return (data[:idx], # request line,
data[idx + 2:]) # residue in the buffer, skip \r\n
def proxy_protocol(self, line):
"""\
@ -337,5 +337,3 @@ class Request(Message):
super(Request, self).set_body_reader()
if isinstance(self.body.reader, EOFReader):
self.body = Body(LengthReader(self.unreader, 0))

View File

@ -6,6 +6,7 @@
from gunicorn.http.message import Request
from gunicorn.http.unreader import SocketUnreader, IterUnreader
class Parser(object):
def __init__(self, mesg_class, cfg, source):
self.mesg_class = mesg_class
@ -33,7 +34,6 @@ class Parser(object):
while data:
data = self.mesg.body.read(8192)
# Parse the next request
self.req_count += 1
self.mesg = self.mesg_class(self.cfg, self.unreader, self.req_count)
@ -43,7 +43,7 @@ class Parser(object):
next = __next__
class RequestParser(Parser):
def __init__(self, *args, **kwargs):
super(RequestParser, self).__init__(Request, *args, **kwargs)

View File

@ -10,6 +10,7 @@ from gunicorn import six
# Classes that can undo reading data from
# a given type of data source.
class Unreader(object):
def __init__(self):
self.buf = six.BytesIO()
@ -34,7 +35,7 @@ class Unreader(object):
self.buf = six.BytesIO()
return ret
if size is None:
d = self.chunk()
d = self.chunk()
return d
while self.buf.tell() < size:
@ -53,6 +54,7 @@ class Unreader(object):
self.buf.seek(0, os.SEEK_END)
self.buf.write(data)
class SocketUnreader(Unreader):
def __init__(self, sock, max_chunk=8192):
super(SocketUnreader, self).__init__()
@ -62,6 +64,7 @@ class SocketUnreader(Unreader):
def chunk(self):
return self.sock.recv(self.mxchunk)
class IterUnreader(Unreader):
def __init__(self, iterable):
super(IterUnreader, self).__init__()

View File

@ -26,6 +26,7 @@ NORMALIZE_SPACE = re.compile(r'(?:\r\n)?[ \t]+')
log = logging.getLogger(__name__)
class FileWrapper:
def __init__(self, filelike, blksize=8192):
@ -58,6 +59,7 @@ def default_environ(req, sock, cfg):
"SERVER_PROTOCOL": "HTTP/%s" % ".".join([str(v) for v in req.version])
}
def proxy_environ(req):
info = req.proxy_protocol_info
@ -72,6 +74,7 @@ def proxy_environ(req):
"PROXY_PORT": str(info["proxy_port"]),
}
def create(req, sock, client, server, cfg):
resp = Response(req, sock)
@ -127,7 +130,7 @@ def create(req, sock, client, server, cfg):
# find host and port on ipv6 address
if '[' in forward and ']' in forward:
host = forward.split(']')[0][1:].lower()
host = forward.split(']')[0][1:].lower()
elif ":" in forward and forward.count(":") == 1:
host = forward.split(":")[0].lower()
else:
@ -147,7 +150,7 @@ def create(req, sock, client, server, cfg):
environ['REMOTE_PORT'] = str(remote[1])
if isinstance(server, string_types):
server = server.split(":")
server = server.split(":")
if len(server) == 1:
if url_scheme == "http":
server.append("80")
@ -168,6 +171,7 @@ def create(req, sock, client, server, cfg):
return resp, environ
class Response(object):
def __init__(self, req, sock):
@ -229,14 +233,13 @@ class Response(object):
continue
self.headers.append((name.strip(), value))
def is_chunked(self):
# Only use chunked responses when the client is
# speaking HTTP/1.1 or newer and there was
# no Content-Length header set.
if self.response_length is not None:
return False
elif self.req.version <= (1,0):
elif self.req.version <= (1, 0):
return False
elif self.status.startswith("304") or self.status.startswith("204"):
# Do not use chunked responses when the response is guaranteed to
@ -268,7 +271,7 @@ class Response(object):
if self.headers_sent:
return
tosend = self.default_headers()
tosend.extend(["%s: %s\r\n" % (k,v) for k, v in self.headers])
tosend.extend(["%s: %s\r\n" % (k, v) for k, v in self.headers])
header_str = "%s\r\n" % "".join(tosend)
util.write(self.sock, util.to_bytestring(header_str))
@ -315,9 +318,9 @@ class Response(object):
nbytes -= BLKSIZE
else:
sent = 0
sent += sendfile(sockno, fileno, offset+sent, nbytes-sent)
sent += sendfile(sockno, fileno, offset + sent, nbytes - sent)
while sent != nbytes:
sent += sendfile(sockno, fileno, offset+sent, nbytes-sent)
sent += sendfile(sockno, fileno, offset + sent, nbytes - sent)
def write_file(self, respiter):
if sendfile is not None and \

View File

@ -45,6 +45,7 @@ def make_options():
g_settings = make_settings(ignore=("version"))
keys = g_settings.keys()
def sorter(k):
return (g_settings[k].section, g_settings[k].order)

View File

@ -55,7 +55,7 @@ class Pidfile(object):
""" delete pidfile"""
try:
with open(self.fname, "r") as f:
pid1 = int(f.read() or 0)
pid1 = int(f.read() or 0)
if pid1 == self.pid:
os.unlink(self.fname)

View File

@ -12,6 +12,7 @@ import time
from gunicorn import util
from gunicorn.six import string_types
class BaseSocket(object):
def __init__(self, address, conf, log, fd=None):
@ -50,6 +51,7 @@ class BaseSocket(object):
time.sleep(0.3)
del self.sock
class TCPSocket(BaseSocket):
FAMILY = socket.AF_INET
@ -60,13 +62,14 @@ class TCPSocket(BaseSocket):
else:
scheme = "http"
addr = self.sock.getsockname()
addr = self.sock.getsockname()
return "%s://%s:%d" % (scheme, addr[0], addr[1])
def set_options(self, sock, bound=False):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
return super(TCPSocket, self).set_options(sock, bound=bound)
class TCP6Socket(TCPSocket):
FAMILY = socket.AF_INET6
@ -75,6 +78,7 @@ class TCP6Socket(TCPSocket):
(host, port, fl, sc) = self.sock.getsockname()
return "http://[%s]:%d" % (host, port)
class UnixSocket(BaseSocket):
FAMILY = socket.AF_UNIX
@ -100,6 +104,7 @@ class UnixSocket(BaseSocket):
super(UnixSocket, self).close()
os.unlink(self.cfg_addr)
def _sock_type(addr):
if isinstance(addr, tuple):
if util.is_ipv6(addr[0]):
@ -112,6 +117,7 @@ def _sock_type(addr):
raise TypeError("Unable to create socket from: %r" % addr)
return sock_type
def create_sockets(conf, log):
"""
Create a new socket for the given address. If the
@ -158,7 +164,7 @@ def create_sockets(conf, log):
sock = None
for i in range(5):
try:
sock = sock_type(addr, conf, log)
sock = sock_type(addr, conf, log)
except socket.error as e:
if e.args[0] == errno.EADDRINUSE:
log.error("Connection in use: %s", str(addr))

View File

@ -24,14 +24,16 @@ import sys
import textwrap
import time
import inspect
import errno
import warnings
from gunicorn.six import text_type, string_types
MAXFD = 1024
if (hasattr(os, "devnull")):
REDIRECT_TO = os.devnull
REDIRECT_TO = os.devnull
else:
REDIRECT_TO = "/dev/null"
REDIRECT_TO = "/dev/null"
timeout_default = object()
@ -83,7 +85,6 @@ except ImportError:
"package")
return "%s.%s" % (package[:dot], name)
def import_module(name, package=None):
"""Import a module.
@ -104,6 +105,7 @@ relative import to an absolute import.
__import__(name)
return sys.modules[name]
def load_class(uri, default="sync", section="gunicorn.workers"):
if inspect.isclass(uri):
return uri
@ -111,7 +113,7 @@ def load_class(uri, default="sync", section="gunicorn.workers"):
# uses entry points
entry_str = uri.split("egg:")[1]
try:
dist, name = entry_str.rsplit("#",1)
dist, name = entry_str.rsplit("#", 1)
except ValueError:
dist = entry_str
name = default
@ -135,7 +137,8 @@ def load_class(uri, default="sync", section="gunicorn.workers"):
mod = getattr(mod, comp)
return getattr(mod, klass)
def set_owner_process(uid,gid):
def set_owner_process(uid, gid):
""" set user and group of workers processes """
if gid:
try:
@ -150,6 +153,7 @@ def set_owner_process(uid,gid):
if uid:
os.setuid(uid)
def chown(path, uid, gid):
try:
os.chown(path, uid, gid)
@ -198,6 +202,7 @@ if sys.platform.startswith("win"):
else:
_unlink = os.unlink
def unlink(filename):
try:
_unlink(filename)
@ -210,10 +215,11 @@ def unlink(filename):
def is_ipv6(addr):
try:
socket.inet_pton(socket.AF_INET6, addr)
except socket.error: # not a valid address
except socket.error: # not a valid address
return False
return True
def parse_address(netloc, default_port=8000):
if netloc.startswith("unix:"):
return netloc.split("unix:")[1]
@ -239,21 +245,25 @@ def parse_address(netloc, default_port=8000):
port = default_port
return (host, port)
def get_maxfd():
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
if (maxfd == resource.RLIM_INFINITY):
maxfd = MAXFD
return maxfd
def close_on_exec(fd):
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
flags |= fcntl.FD_CLOEXEC
fcntl.fcntl(fd, fcntl.F_SETFD, flags)
def set_non_blocking(fd):
flags = fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK
fcntl.fcntl(fd, fcntl.F_SETFL, flags)
def close(sock):
try:
sock.close()
@ -268,9 +278,10 @@ except ImportError:
for fd in range(fd_low, fd_high):
try:
os.close(fd)
except OSError: # ERROR, fd wasn't open to begin with (ignored)
except OSError: # ERROR, fd wasn't open to begin with (ignored)
pass
def write_chunk(sock, data):
if isinstance(data, text_type):
data = data.encode('utf-8')
@ -278,11 +289,13 @@ def write_chunk(sock, data):
chunk = b"".join([chunk_size.encode('utf-8'), data, b"\r\n"])
sock.sendall(chunk)
def write(sock, data, chunked=False):
if chunked:
return write_chunk(sock, data)
sock.sendall(data)
def write_nonblock(sock, data, chunked=False):
timeout = sock.gettimeout()
if timeout != 0.0:
@ -294,10 +307,12 @@ def write_nonblock(sock, data, chunked=False):
else:
return write(sock, data, chunked)
def writelines(sock, lines, chunked=False):
for line in list(lines):
write(sock, line, chunked)
def write_error(sock, status_int, reason, mesg):
html = textwrap.dedent("""\
<html>
@ -321,8 +336,10 @@ def write_error(sock, status_int, reason, mesg):
""") % (str(status_int), reason, len(html), html)
write_nonblock(sock, http.encode('latin1'))
def normalize_name(name):
return "-".join([w.lower().capitalize() for w in name.split("-")])
return "-".join([w.lower().capitalize() for w in name.split("-")])
def import_app(module):
parts = module.split(":", 1)
@ -336,7 +353,7 @@ def import_app(module):
except ImportError:
if module.endswith(".py") and os.path.exists(module):
raise ImportError("Failed to find application, did "
"you mean '%s:%s'?" % (module.rsplit(".",1)[0], obj))
"you mean '%s:%s'?" % (module.rsplit(".", 1)[0], obj))
else:
raise
@ -348,6 +365,7 @@ def import_app(module):
raise TypeError("Application object must be callable.")
return app
def http_date(timestamp=None):
"""Return the current date and time formatted for a message header."""
if timestamp is None:
@ -359,9 +377,11 @@ def http_date(timestamp=None):
hh, mm, ss)
return s
def is_hoppish(header):
return header.lower().strip() in hop_headers
def daemonize():
"""\
Standard daemonization of a process.
@ -383,6 +403,7 @@ def daemonize():
os.dup2(0, 1)
os.dup2(0, 2)
def seed():
try:
random.seed(os.urandom(64))
@ -397,6 +418,7 @@ def check_is_writeable(path):
raise RuntimeError("Error: '%s' isn't writable [%r]" % (path, e))
f.close()
def to_bytestring(value):
"""Converts a string argument to a byte string"""
if isinstance(value, bytes):

View File

@ -16,6 +16,7 @@ from gunicorn import six
ALREADY_HANDLED = object()
class AsyncWorker(base.Worker):
def __init__(self, *args, **kwargs):
@ -47,9 +48,9 @@ class AsyncWorker(base.Worker):
except StopIteration as e:
self.log.debug("Closing connection. %s", e)
except ssl.SSLError:
raise # pass to next try-except level
raise # pass to next try-except level
except socket.error:
raise # pass to next try-except level
raise # pass to next try-except level
except Exception as e:
self.handle_error(req, client, addr, e)
except ssl.SSLError as e:
@ -100,7 +101,7 @@ class AsyncWorker(base.Worker):
self.log.access(resp, req, environ, request_time)
finally:
if hasattr(respiter, "close"):
respiter.close()
respiter.close()
if resp.should_close():
raise StopIteration()
finally:

View File

@ -19,6 +19,7 @@ from gunicorn.http.errors import InvalidProxyLine, ForbiddenProxyRequest
from gunicorn.http.wsgi import default_environ, Response
from gunicorn.six import MAXSIZE
class Worker(object):
SIGNALS = [getattr(signal, "SIG%s" % x) \
@ -129,7 +130,7 @@ class Worker(object):
def handle_error(self, req, client, addr, exc):
request_start = datetime.now()
addr = addr or ('', -1) # unix socket case
addr = addr or ('', -1) # unix socket case
if isinstance(exc, (InvalidRequestLine, InvalidRequestMethod,
InvalidHTTPVersion, InvalidHeader, InvalidHeaderName,
LimitRequestLine, LimitRequestHeaders,
@ -147,7 +148,7 @@ class Worker(object):
elif isinstance(exc, (InvalidHeaderName, InvalidHeader,)):
mesg = "<p>%s</p>" % str(exc)
if not req and hasattr(exc, "req"):
req = exc.req # for access log
req = exc.req # for access log
elif isinstance(exc, LimitRequestLine):
mesg = "<p>%s</p>" % str(exc)
elif isinstance(exc, LimitRequestHeaders):

View File

@ -15,12 +15,13 @@ from eventlet.greenio import GreenSocket
from gunicorn.workers.async import AsyncWorker
class EventletWorker(AsyncWorker):
@classmethod
def setup(cls):
import eventlet
if eventlet.version_info < (0,9,7):
if eventlet.version_info < (0, 9, 7):
raise RuntimeError("You need eventlet >= 0.9.7")
eventlet.monkey_patch(os=False)

View File

@ -38,6 +38,7 @@ BASE_WSGI_ENV = {
'wsgi.run_once': False
}
class GeventWorker(AsyncWorker):
server_class = None
@ -52,7 +53,6 @@ class GeventWorker(AsyncWorker):
def timeout_ctx(self):
return gevent.Timeout(self.cfg.keepalive, False)
def run(self):
servers = []
ssl_args = {}
@ -80,7 +80,7 @@ class GeventWorker(AsyncWorker):
while self.alive:
self.notify()
if pid == os.getpid() and self.ppid != os.getppid():
if pid == os.getpid() and self.ppid != os.getppid():
self.log.info("Parent changed, shutting down: %s", self)
break
@ -137,12 +137,12 @@ class GeventResponse(object):
headers = None
response_length = None
def __init__(self, status, headers, clength):
self.status = status
self.headers = headers
self.response_length = clength
class PyWSGIHandler(pywsgi.WSGIHandler):
def log_request(self):
@ -160,9 +160,11 @@ class PyWSGIHandler(pywsgi.WSGIHandler):
env['RAW_URI'] = self.path
return env
class PyWSGIServer(pywsgi.WSGIServer):
base_env = BASE_WSGI_ENV
class GeventPyWSGIWorker(GeventWorker):
"The Gevent StreamServer based workers."
server_class = PyWSGIServer

View File

@ -17,6 +17,7 @@ import gunicorn.util as util
import gunicorn.workers.base as base
from gunicorn import six
class SyncWorker(base.Worker):
def run(self):

View File

@ -8,6 +8,7 @@ import tempfile
from gunicorn import util
class WorkerTmp(object):
def __init__(self, cfg):
@ -30,7 +31,7 @@ class WorkerTmp(object):
def notify(self):
try:
self.spinner = (self.spinner+1) % 2
self.spinner = (self.spinner + 1) % 2
os.fchmod(self._tmp.fileno(), self.spinner)
except AttributeError:
# python < 2.6