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 - # -*- 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. # See the NOTICE for more information.

View File

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

View File

@ -46,6 +46,7 @@ def make_wsgi_application():
return get_internal_wsgi_application() return get_internal_wsgi_application()
return WSGIHandler() return WSGIHandler()
def reload_django_settings(): def reload_django_settings():
mod = util.import_module(os.environ['DJANGO_SETTINGS_MODULE']) mod = util.import_module(os.environ['DJANGO_SETTINGS_MODULE'])
@ -63,7 +64,7 @@ def reload_django_settings():
if setting == setting.upper(): if setting == setting.upper():
setting_value = getattr(mod, setting) setting_value = getattr(mod, setting)
if setting in tuple_settings and type(setting_value) == str: 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) setattr(settings, setting, setting_value)
# Expand entries in INSTALLED_APPS like "django.contrib.*" to a list # 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.app.base import Application
from gunicorn import util from gunicorn import util
def is_setting_mod(path): def is_setting_mod(path):
return (os.path.isfile(os.path.join(path, "settings.py")) or return (os.path.isfile(os.path.join(path, "settings.py")) or
os.path.isfile(os.path.join(path, "settings.pyc"))) os.path.isfile(os.path.join(path, "settings.pyc")))
@ -34,7 +35,7 @@ def find_settings_module(path):
project_path = path project_path = path
elif os.path.isfile(path): elif os.path.isfile(path):
project_path = os.path.dirname(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 return project_path, settings_name
@ -91,7 +92,6 @@ class DjangoApplication(Application):
settings_name)) settings_name))
self.cfg.set("pythonpath", pythonpath) self.cfg.set("pythonpath", pythonpath)
def load(self): def load(self):
# set settings # set settings
make_default_env(self.cfg) make_default_env(self.cfg)
@ -114,7 +114,6 @@ class DjangoApplicationCommand(Application):
self.do_load_config() self.do_load_config()
def init(self, *args): def init(self, *args):
if 'settings' in self.options: if 'settings' in self.options:
self.options['django_settings'] = self.options.pop('settings') self.options['django_settings'] = self.options.pop('settings')
@ -133,6 +132,7 @@ class DjangoApplicationCommand(Application):
mod = util.import_module("gunicorn.app.django_wsgi") mod = util.import_module("gunicorn.app.django_wsgi")
return mod.make_command_wsgi_application(self.admin_media_path) return mod.make_command_wsgi_application(self.admin_media_path)
def run(): def run():
"""\ """\
The ``gunicorn_django`` command line runner for launching Django 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.app.base import Application
from gunicorn.config import Config from gunicorn.config import Config
class PasterBaseApplication(Application): class PasterBaseApplication(Application):
def app_config(self): def app_config(self):
@ -60,6 +61,7 @@ class PasterBaseApplication(Application):
fileConfig(config_file, dict(__file__=config_file, fileConfig(config_file, dict(__file__=config_file,
here=os.path.dirname(config_file))) here=os.path.dirname(config_file)))
class PasterApplication(PasterBaseApplication): class PasterApplication(PasterBaseApplication):
def init(self, parser, opts, args): def init(self, parser, opts, args):
@ -83,6 +85,7 @@ class PasterApplication(PasterBaseApplication):
def load(self): def load(self):
return loadapp(self.cfgurl, relative_to=self.relpath) return loadapp(self.cfgurl, relative_to=self.relpath)
class PasterServerApplication(PasterBaseApplication): class PasterServerApplication(PasterBaseApplication):
def __init__(self, app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs): 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.stderr.flush()
sys.exit(1) sys.exit(1)
def load_config(self): def load_config(self):
if not hasattr(self, "cfgfname"): if not hasattr(self, "cfgfname"):
return return
cfg = self.app_config() cfg = self.app_config()
for k,v in cfg.items(): for k, v in cfg.items():
try: try:
self.cfg.set(k.lower(), v) self.cfg.set(k.lower(), v)
except: except:
@ -147,6 +149,7 @@ def run():
from gunicorn.app.pasterapp import PasterApplication from gunicorn.app.pasterapp import PasterApplication
PasterApplication("%prog [OPTIONS] pasteconfig.ini").run() PasterApplication("%prog [OPTIONS] pasteconfig.ini").run()
def paste_server(app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs): def paste_server(app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs):
"""\ """\
A paster server. A paster server.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 - # -*- 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. # See the NOTICE for more information.
from gunicorn.http.message import Message, Request from gunicorn.http.message import Message, Request
from gunicorn.http.parser import RequestParser 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) _libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
_sendfile = _libc.sendfile _sendfile = _libc.sendfile
def sendfile(fdout, fdin, offset, nbytes): def sendfile(fdout, fdin, offset, nbytes):
if sys.platform == 'darwin': if sys.platform == 'darwin':
_sendfile.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_uint64, _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. # This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information. # See the NOTICE for more information.
import sys
from gunicorn.http.errors import (NoMoreData, ChunkMissingTerminator, from gunicorn.http.errors import (NoMoreData, ChunkMissingTerminator,
InvalidChunkSize) InvalidChunkSize)
from gunicorn import six from gunicorn import six
class ChunkedReader(object): class ChunkedReader(object):
def __init__(self, req, unreader): def __init__(self, req, unreader):
self.req = req self.req = req
@ -51,7 +50,7 @@ class ChunkedReader(object):
unreader.unread(buf.getvalue()[2:]) unreader.unread(buf.getvalue()[2:])
return b"" return b""
self.req.trailers = self.req.parse_headers(buf.getvalue()[:idx]) 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): def parse_chunked(self, unreader):
(size, rest) = self.parse_chunk_size(unreader) (size, rest) = self.parse_chunk_size(unreader)
@ -82,7 +81,7 @@ class ChunkedReader(object):
idx = buf.getvalue().find(b"\r\n") idx = buf.getvalue().find(b"\r\n")
data = buf.getvalue() 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() chunk_size = line.split(b";", 1)[0].strip()
try: try:
@ -104,6 +103,7 @@ class ChunkedReader(object):
raise NoMoreData() raise NoMoreData()
buf.write(data) buf.write(data)
class LengthReader(object): class LengthReader(object):
def __init__(self, unreader, length): def __init__(self, unreader, length):
self.unreader = unreader self.unreader = unreader
@ -119,7 +119,6 @@ class LengthReader(object):
if size == 0: if size == 0:
return b"" return b""
buf = six.BytesIO() buf = six.BytesIO()
data = self.unreader.read() data = self.unreader.read()
while data: while data:
@ -134,6 +133,7 @@ class LengthReader(object):
self.length -= size self.length -= size
return ret return ret
class EOFReader(object): class EOFReader(object):
def __init__(self, unreader): def __init__(self, unreader):
self.unreader = unreader self.unreader = unreader
@ -171,6 +171,7 @@ class EOFReader(object):
self.buf.write(rest) self.buf.write(rest)
return ret return ret
class Body(object): class Body(object):
def __init__(self, reader): def __init__(self, reader):
self.reader = reader self.reader = reader
@ -233,8 +234,8 @@ class Body(object):
idx = line.find(b"\n") idx = line.find(b"\n")
if idx >= 0: if idx >= 0:
ret = line[:idx+1] ret = line[:idx + 1]
self.buf.write(line[idx+1:]) self.buf.write(line[idx + 1:])
self.buf.write(extra_buf_data) self.buf.write(extra_buf_data)
return ret return ret
self.buf.write(extra_buf_data) self.buf.write(extra_buf_data)
@ -249,6 +250,6 @@ class Body(object):
ret.append(data) ret.append(data)
data = b"" data = b""
else: else:
line, data = data[:pos+1], data[pos+1:] line, data = data[:pos + 1], data[pos + 1:]
ret.append(line) ret.append(line)
return ret return ret

View File

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

View File

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

View File

@ -6,6 +6,7 @@
from gunicorn.http.message import Request from gunicorn.http.message import Request
from gunicorn.http.unreader import SocketUnreader, IterUnreader from gunicorn.http.unreader import SocketUnreader, IterUnreader
class Parser(object): class Parser(object):
def __init__(self, mesg_class, cfg, source): def __init__(self, mesg_class, cfg, source):
self.mesg_class = mesg_class self.mesg_class = mesg_class
@ -33,7 +34,6 @@ class Parser(object):
while data: while data:
data = self.mesg.body.read(8192) data = self.mesg.body.read(8192)
# Parse the next request # Parse the next request
self.req_count += 1 self.req_count += 1
self.mesg = self.mesg_class(self.cfg, self.unreader, self.req_count) self.mesg = self.mesg_class(self.cfg, self.unreader, self.req_count)
@ -43,7 +43,7 @@ class Parser(object):
next = __next__ next = __next__
class RequestParser(Parser): class RequestParser(Parser):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(RequestParser, self).__init__(Request, *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 # Classes that can undo reading data from
# a given type of data source. # a given type of data source.
class Unreader(object): class Unreader(object):
def __init__(self): def __init__(self):
self.buf = six.BytesIO() self.buf = six.BytesIO()
@ -34,7 +35,7 @@ class Unreader(object):
self.buf = six.BytesIO() self.buf = six.BytesIO()
return ret return ret
if size is None: if size is None:
d = self.chunk() d = self.chunk()
return d return d
while self.buf.tell() < size: while self.buf.tell() < size:
@ -53,6 +54,7 @@ class Unreader(object):
self.buf.seek(0, os.SEEK_END) self.buf.seek(0, os.SEEK_END)
self.buf.write(data) self.buf.write(data)
class SocketUnreader(Unreader): class SocketUnreader(Unreader):
def __init__(self, sock, max_chunk=8192): def __init__(self, sock, max_chunk=8192):
super(SocketUnreader, self).__init__() super(SocketUnreader, self).__init__()
@ -62,6 +64,7 @@ class SocketUnreader(Unreader):
def chunk(self): def chunk(self):
return self.sock.recv(self.mxchunk) return self.sock.recv(self.mxchunk)
class IterUnreader(Unreader): class IterUnreader(Unreader):
def __init__(self, iterable): def __init__(self, iterable):
super(IterUnreader, self).__init__() super(IterUnreader, self).__init__()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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