mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
Create an application abstraction.
Groundwork for providing a post-fork app import option. Fixes paster's ini not being able to register changes.
This commit is contained in:
parent
63e39e1232
commit
5268b8fbbb
94
gunicorn/app.py
Normal file
94
gunicorn/app.py
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# -*- coding: utf-8 -
|
||||||
|
#
|
||||||
|
# This file is part of gunicorn released under the MIT license.
|
||||||
|
# See the NOTICE for more information.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from gunicorn import util
|
||||||
|
|
||||||
|
class Application(object):
|
||||||
|
"""\
|
||||||
|
An application interface for configuring and loading
|
||||||
|
the various necessities for any given web framework.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_config(self):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
class WSGIApplication(Application):
|
||||||
|
|
||||||
|
def __init__(self, app_uri):
|
||||||
|
self.app_uri = app_uri
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
return util.import_app(self.app_uri)
|
||||||
|
|
||||||
|
class DjangoApplication(Application):
|
||||||
|
|
||||||
|
def __init__(self, settings_modname, project_path):
|
||||||
|
self.project_path = project_path
|
||||||
|
self.settings_modname = settings_modname
|
||||||
|
|
||||||
|
# update sys.path
|
||||||
|
sys.path.insert(0, project_path)
|
||||||
|
sys.path.append(os.path.join(project_path, os.pardir))
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
import django.core.handlers.wsgi
|
||||||
|
os.environ['DJANGO_SETTINGS_MODULE'] = self.settings_modname
|
||||||
|
return django.core.handlers.wsgi.WSGIHandler()
|
||||||
|
|
||||||
|
class PasterApplication(Application):
|
||||||
|
|
||||||
|
def __init__(self, cfgurl, relpath, global_opts):
|
||||||
|
self.cfgurl = cfgurl
|
||||||
|
self.relpath = relpath
|
||||||
|
self.global_opts = global_opts
|
||||||
|
|
||||||
|
def local_conf(self):
|
||||||
|
from paste.deploy import loadwsgi
|
||||||
|
ctx = loadwsgi.loadcontext(loadwsgi.SERVER, self.cfgurl,
|
||||||
|
relative_to=self.relpath)
|
||||||
|
|
||||||
|
def mk_bind():
|
||||||
|
host = ctx.local_conf.get('host')
|
||||||
|
port = ctx.local_conf.get('port')
|
||||||
|
if host and port:
|
||||||
|
return '%s:%s' % (host, port)
|
||||||
|
elif host:
|
||||||
|
return host
|
||||||
|
|
||||||
|
ret = {}
|
||||||
|
vars = {
|
||||||
|
'bind': mk_bind,
|
||||||
|
'workers': lambda: ctx.local_conf.get('workers', 1),
|
||||||
|
'umask': lambda: int(ctx.local_conf.get('umask', UMASK)),
|
||||||
|
'group': lambda: ctx.local_conf.get('group'),
|
||||||
|
'user': lambda: ctx.local_conf.get('user')
|
||||||
|
}
|
||||||
|
for vn in vars:
|
||||||
|
if self.global_ops.get(vn):
|
||||||
|
val = vars[vn]()
|
||||||
|
if val:
|
||||||
|
ret[vn] = val
|
||||||
|
|
||||||
|
keys = ctx.local_conf.items()
|
||||||
|
keys = filter(self.global_opts.get, keys)
|
||||||
|
keys = filter(ret.has_key, keys)
|
||||||
|
ret.update((k, ctx.local_conf[k]) for k in keys)
|
||||||
|
|
||||||
|
if not self.global_opts.get("debug"):
|
||||||
|
ret['debug'] = (ctx.global_conf.get('debug') == "true")
|
||||||
|
|
||||||
|
ret['default_proc_name'] = ctx.global_conf.get('__file__')
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
from paste.deploy import loadapp
|
||||||
|
return loadapp(self.cfgurl, relative_to=self.relpath)
|
||||||
@ -44,19 +44,30 @@ class Config(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, opts, path=None):
|
def __init__(self, opts, path=None):
|
||||||
self.cfg = self.DEFAULTS.copy()
|
self.cfg = {}
|
||||||
|
self.opts = opts
|
||||||
if path is None:
|
if path is None:
|
||||||
path = os.path.join(os.getcwd(), self.DEFAULT_CONFIG_FILE)
|
path = os.path.join(os.getcwd(), self.DEFAULT_CONFIG_FILE)
|
||||||
if os.path.exists(path):
|
self.path = path
|
||||||
|
self.load()
|
||||||
|
|
||||||
|
def update(self, opts):
|
||||||
|
opts = dict((k, v) for (k, v) in opts.iteritems() if v is not None)
|
||||||
|
self.opts.update(opts)
|
||||||
|
self.cfg.update(opts)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self.cfg = self.DEFAULTS.copy()
|
||||||
|
|
||||||
|
if os.path.exists(self.path):
|
||||||
try:
|
try:
|
||||||
execfile(path, globals(), self.cfg)
|
execfile(self.path, globals(), self.cfg)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
sys.exit("Could not read config file: %r\n %s" % (path, e))
|
sys.exit("Could not read config file: %r\n %s" % (self.path, e))
|
||||||
self.cfg.pop("__builtins__", None)
|
self.cfg.pop("__builtins__", None)
|
||||||
|
|
||||||
opts = [(k, v) for (k, v) in opts.iteritems() if v is not None]
|
opts = dict((k, v) for (k, v) in opts.iteritems() if v is not None)
|
||||||
self.cfg.update(dict(opts))
|
self.cfg.update(opts)
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -69,6 +69,7 @@ def main(usage, get_app):
|
|||||||
|
|
||||||
cfg = Config(opts.__dict__, opts.config)
|
cfg = Config(opts.__dict__, opts.config)
|
||||||
app = get_app(parser, opts, args)
|
app = get_app(parser, opts, args)
|
||||||
|
cfg.update(app.get_config())
|
||||||
if cfg.spew:
|
if cfg.spew:
|
||||||
spew()
|
spew()
|
||||||
if cfg.daemon:
|
if cfg.daemon:
|
||||||
@ -77,7 +78,7 @@ def main(usage, get_app):
|
|||||||
os.setpgrp()
|
os.setpgrp()
|
||||||
configure_logging(cfg)
|
configure_logging(cfg)
|
||||||
|
|
||||||
Arbiter(cfg, app).run()
|
Arbiter(cfg, app.load()).run()
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
"""\
|
"""\
|
||||||
@ -90,10 +91,13 @@ def run():
|
|||||||
if len(args) != 1:
|
if len(args) != 1:
|
||||||
parser.error("No application module specified.")
|
parser.error("No application module specified.")
|
||||||
opts.default_proc_name = args[0]
|
opts.default_proc_name = args[0]
|
||||||
|
|
||||||
|
application = app.WSGIApplication(args[0])
|
||||||
try:
|
try:
|
||||||
return util.import_app(args[0])
|
application.load()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
parser.error("Failed to import application module:\n %s" % e)
|
parser.error("Failed to import application module:\n %s" % e)
|
||||||
|
return application
|
||||||
|
|
||||||
main("%prog [OPTIONS] APP_MODULE", get_app)
|
main("%prog [OPTIONS] APP_MODULE", get_app)
|
||||||
|
|
||||||
@ -124,22 +128,15 @@ def run_django():
|
|||||||
settings_path = os.path.join(project_path, "settings.py")
|
settings_path = os.path.join(project_path, "settings.py")
|
||||||
if not os.path.exists(settings_path):
|
if not os.path.exists(settings_path):
|
||||||
settings_notfound(settings_path)
|
settings_notfound(settings_path)
|
||||||
|
|
||||||
project_name = os.path.split(project_path)[-1]
|
|
||||||
|
|
||||||
sys.path.insert(0, project_path)
|
|
||||||
sys.path.append(os.path.join(project_path, os.pardir))
|
|
||||||
|
|
||||||
# set environ
|
# set environ
|
||||||
|
project_name = os.path.split(project_path)[-1]
|
||||||
settings_name, ext = os.path.splitext(os.path.basename(settings_path))
|
settings_name, ext = os.path.splitext(os.path.basename(settings_path))
|
||||||
|
settings_modname = "%s.%s" % (project_name, settings_name)
|
||||||
settings_modname = '%s.%s' % (project_name, settings_name)
|
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = settings_modname
|
|
||||||
|
|
||||||
opts.default_proc_name = settings_modname
|
opts.default_proc_name = settings_modname
|
||||||
|
|
||||||
# django wsgi app
|
# django wsgi app
|
||||||
return django.core.handlers.wsgi.WSGIHandler()
|
return app.DjangoApplication(settings_modname, project_path)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -150,7 +147,7 @@ def run_paster():
|
|||||||
The ``gunicorn_paster`` command for launcing Paster compatible
|
The ``gunicorn_paster`` command for launcing Paster compatible
|
||||||
apllications like Pylons or Turbogears2
|
apllications like Pylons or Turbogears2
|
||||||
"""
|
"""
|
||||||
from paste.deploy import loadapp, loadwsgi
|
from paste.deploy import loadwsgi
|
||||||
|
|
||||||
def get_app(parser, opts, args):
|
def get_app(parser, opts, args):
|
||||||
if len(args) != 1:
|
if len(args) != 1:
|
||||||
@ -169,43 +166,8 @@ def run_paster():
|
|||||||
|
|
||||||
# add to eggs
|
# add to eggs
|
||||||
pkg_resources.working_set.add_entry(relpath)
|
pkg_resources.working_set.add_entry(relpath)
|
||||||
ctx = loadwsgi.loadcontext(loadwsgi.SERVER, cfgurl, relative_to=relpath)
|
|
||||||
|
|
||||||
|
|
||||||
if not opts.workers:
|
return app.PasterApplication(cfgurl, relpath, opts.__dict__)
|
||||||
opts.workers = ctx.local_conf.get('workers', 1)
|
|
||||||
|
|
||||||
if not opts.umask:
|
|
||||||
opts.umask = int(ctx.local_conf.get('umask', UMASK))
|
|
||||||
|
|
||||||
if not opts.group:
|
|
||||||
opts.group = ctx.local_conf.get('group')
|
|
||||||
|
|
||||||
if not opts.user:
|
|
||||||
opts.user = ctx.local_conf.get('user')
|
|
||||||
|
|
||||||
if not opts.bind:
|
|
||||||
host = ctx.local_conf.get('host')
|
|
||||||
port = ctx.local_conf.get('port')
|
|
||||||
if host:
|
|
||||||
if port:
|
|
||||||
bind = "%s:%s" % (host, port)
|
|
||||||
else:
|
|
||||||
bind = host
|
|
||||||
opts.bind = bind
|
|
||||||
|
|
||||||
for k, v in ctx.local_conf.items():
|
|
||||||
if not hasattr(opts, k):
|
|
||||||
setattr(opts, k, v)
|
|
||||||
|
|
||||||
if not opts.debug:
|
|
||||||
opts.debug = (ctx.global_conf.get('debug') == "true")
|
|
||||||
|
|
||||||
|
|
||||||
opts.default_proc_name= ctx.global_conf.get('__file__')
|
|
||||||
|
|
||||||
app = loadapp(cfgurl, relative_to=relpath)
|
|
||||||
return app
|
|
||||||
|
|
||||||
main("%prog [OPTIONS] pasteconfig.ini", get_app)
|
main("%prog [OPTIONS] pasteconfig.ini", get_app)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user