mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
The Arbiter is smart about getting the CWD; first it checks the CWD environment (which doesn't resolve symlinks), then it falls back to the python os.getcwd() (which does resolve symlinks). However, the Arbiter is the only place that does this, which will then do the right thing when we reexec. However, when reloading the Arbiter, it won't pick up changes if the symlink has changed. By changing the *app.py entry points to also use the same method for determining the CWD, we'll insert a symlink path into the first location in sys.path. Then our reloaded app will correctly pull in any new changes.
144 lines
4.4 KiB
Python
144 lines
4.4 KiB
Python
# -*- 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.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")))
|
|
|
|
|
|
def find_settings_module(path):
|
|
path = os.path.abspath(path)
|
|
project_path = None
|
|
settings_name = "settings"
|
|
|
|
if os.path.isdir(path):
|
|
project_path = None
|
|
if not is_setting_mod(path):
|
|
for d in os.listdir(path):
|
|
if d in ('..', '.'):
|
|
continue
|
|
|
|
root = os.path.join(path, d)
|
|
if is_setting_mod(root):
|
|
project_path = root
|
|
break
|
|
else:
|
|
project_path = path
|
|
elif os.path.isfile(path):
|
|
project_path = os.path.dirname(path)
|
|
settings_name, _ = os.path.splitext(os.path.basename(path))
|
|
|
|
return project_path, settings_name
|
|
|
|
|
|
def make_default_env(cfg):
|
|
if cfg.django_settings:
|
|
os.environ['DJANGO_SETTINGS_MODULE'] = cfg.django_settings
|
|
|
|
if cfg.pythonpath and cfg.pythonpath is not None:
|
|
paths = cfg.pythonpath.split(",")
|
|
for path in paths:
|
|
pythonpath = os.path.abspath(cfg.pythonpath)
|
|
if pythonpath not in sys.path:
|
|
sys.path.insert(0, pythonpath)
|
|
|
|
try:
|
|
os.environ['DJANGO_SETTINGS_MODULE']
|
|
except KeyError:
|
|
# not settings env set, try to build one.
|
|
cwd = util.getcwd()
|
|
project_path, settings_name = find_settings_module(cwd)
|
|
|
|
if not project_path:
|
|
raise RuntimeError("django project not found")
|
|
|
|
pythonpath, project_name = os.path.split(project_path)
|
|
os.environ['DJANGO_SETTINGS_MODULE'] = "%s.%s" % (project_name,
|
|
settings_name)
|
|
if pythonpath not in sys.path:
|
|
sys.path.insert(0, pythonpath)
|
|
|
|
if project_path not in sys.path:
|
|
sys.path.insert(0, project_path)
|
|
|
|
|
|
class DjangoApplication(Application):
|
|
|
|
def init(self, parser, opts, args):
|
|
if args:
|
|
if ("." in args[0] and not (os.path.isfile(args[0])
|
|
or os.path.isdir(args[0]))):
|
|
self.cfg.set("django_settings", args[0])
|
|
else:
|
|
# not settings env set, try to build one.
|
|
project_path, settings_name = find_settings_module(
|
|
os.path.abspath(args[0]))
|
|
if project_path not in sys.path:
|
|
sys.path.insert(0, project_path)
|
|
|
|
if not project_path:
|
|
raise RuntimeError("django project not found")
|
|
|
|
pythonpath, project_name = os.path.split(project_path)
|
|
self.cfg.set("django_settings", "%s.%s" % (project_name,
|
|
settings_name))
|
|
self.cfg.set("pythonpath", pythonpath)
|
|
|
|
def load(self):
|
|
# set settings
|
|
make_default_env(self.cfg)
|
|
|
|
# load wsgi application and return it.
|
|
mod = util.import_module("gunicorn.app.django_wsgi")
|
|
return mod.make_wsgi_application()
|
|
|
|
|
|
class DjangoApplicationCommand(Application):
|
|
|
|
def __init__(self, options, admin_media_path):
|
|
self.usage = None
|
|
self.prog = None
|
|
self.cfg = None
|
|
self.config_file = options.get("config") or ""
|
|
self.options = options
|
|
self.admin_media_path = admin_media_path
|
|
self.callable = None
|
|
self.project_path = None
|
|
self.do_load_config()
|
|
|
|
def init(self, *args):
|
|
if 'settings' in self.options:
|
|
self.options['django_settings'] = self.options.pop('settings')
|
|
|
|
cfg = {}
|
|
for k, v in self.options.items():
|
|
if k.lower() in self.cfg.settings and v is not None:
|
|
cfg[k.lower()] = v
|
|
return cfg
|
|
|
|
def load(self):
|
|
# set settings
|
|
make_default_env(self.cfg)
|
|
|
|
# load wsgi application and return it.
|
|
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
|
|
applications.
|
|
"""
|
|
from gunicorn.app.djangoapp import DjangoApplication
|
|
DjangoApplication("%(prog)s [OPTIONS] [SETTINGS_PATH]").run()
|