mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
Specify wsgi_app in config #1359.
This commit is contained in:
parent
a232c270fd
commit
57a9e2eb7e
@ -21,12 +21,15 @@ gunicorn
|
|||||||
|
|
||||||
Basic usage::
|
Basic usage::
|
||||||
|
|
||||||
$ gunicorn [OPTIONS] APP_MODULE
|
$ gunicorn [OPTIONS] [WSGI_APP]
|
||||||
|
|
||||||
Where ``APP_MODULE`` is of the pattern ``$(MODULE_NAME):$(VARIABLE_NAME)``. The
|
Where ``WSGI_APP`` is of the pattern ``$(MODULE_NAME):$(VARIABLE_NAME)``. The
|
||||||
module name can be a full dotted path. The variable name refers to a WSGI
|
module name can be a full dotted path. The variable name refers to a WSGI
|
||||||
callable that should be found in the specified module.
|
callable that should be found in the specified module.
|
||||||
|
|
||||||
|
.. versionchanged:: 20.1.0
|
||||||
|
``WSGI_APP`` is optional if it is defined in a :ref:`config` file.
|
||||||
|
|
||||||
Example with the test app:
|
Example with the test app:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|||||||
@ -42,6 +42,17 @@ application specific configuration.
|
|||||||
Loading the config from a Python module requires the ``python:``
|
Loading the config from a Python module requires the ``python:``
|
||||||
prefix.
|
prefix.
|
||||||
|
|
||||||
|
.. _wsgi-app:
|
||||||
|
|
||||||
|
wsgi_app
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
* ``None``
|
||||||
|
|
||||||
|
A WSGI application path in pattern ``$(MODULE_NAME):$(VARIABLE_NAME)``.
|
||||||
|
|
||||||
|
.. versionadded:: 20.1.0
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,8 @@ from gunicorn import util
|
|||||||
|
|
||||||
class WSGIApplication(Application):
|
class WSGIApplication(Application):
|
||||||
def init(self, parser, opts, args):
|
def init(self, parser, opts, args):
|
||||||
|
self.app_uri = None
|
||||||
|
|
||||||
if opts.paste:
|
if opts.paste:
|
||||||
from .pasterapp import has_logging_config
|
from .pasterapp import has_logging_config
|
||||||
|
|
||||||
@ -29,11 +31,18 @@ class WSGIApplication(Application):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if not args:
|
if len(args) > 0:
|
||||||
parser.error("No application module specified.")
|
self.cfg.set("default_proc_name", args[0])
|
||||||
|
self.app_uri = args[0]
|
||||||
|
|
||||||
self.cfg.set("default_proc_name", args[0])
|
def load_config(self):
|
||||||
self.app_uri = args[0]
|
super().load_config()
|
||||||
|
|
||||||
|
if self.app_uri is None:
|
||||||
|
if self.cfg.wsgi_app is not None:
|
||||||
|
self.app_uri = self.cfg.wsgi_app
|
||||||
|
else:
|
||||||
|
raise ConfigError("No application module specified.")
|
||||||
|
|
||||||
def load_wsgiapp(self):
|
def load_wsgiapp(self):
|
||||||
return util.import_app(self.app_uri)
|
return util.import_app(self.app_uri)
|
||||||
|
|||||||
@ -560,6 +560,17 @@ class ConfigFile(Setting):
|
|||||||
prefix.
|
prefix.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
class WSGIApp(Setting):
|
||||||
|
name = "wsgi_app"
|
||||||
|
section = "Config File"
|
||||||
|
meta = "STRING"
|
||||||
|
validator = validate_string
|
||||||
|
default = None
|
||||||
|
desc = """\
|
||||||
|
A WSGI application path in pattern ``$(MODULE_NAME):$(VARIABLE_NAME)``.
|
||||||
|
|
||||||
|
.. versionadded:: 20.1.0
|
||||||
|
"""
|
||||||
|
|
||||||
class Bind(Setting):
|
class Bind(Setting):
|
||||||
name = "bind"
|
name = "bind"
|
||||||
|
|||||||
1
tests/config/test_cfg_with_wsgi_app.py
Normal file
1
tests/config/test_cfg_with_wsgi_app.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
wsgi_app = "app1:app1"
|
||||||
@ -11,6 +11,7 @@ import pytest
|
|||||||
|
|
||||||
from gunicorn import config
|
from gunicorn import config
|
||||||
from gunicorn.app.base import Application
|
from gunicorn.app.base import Application
|
||||||
|
from gunicorn.app.wsgiapp import WSGIApplication
|
||||||
from gunicorn.errors import ConfigError
|
from gunicorn.errors import ConfigError
|
||||||
from gunicorn.workers.sync import SyncWorker
|
from gunicorn.workers.sync import SyncWorker
|
||||||
from gunicorn import glogging
|
from gunicorn import glogging
|
||||||
@ -25,6 +26,8 @@ def cfg_file():
|
|||||||
return os.path.join(dirname, "config", "test_cfg.py")
|
return os.path.join(dirname, "config", "test_cfg.py")
|
||||||
def alt_cfg_file():
|
def alt_cfg_file():
|
||||||
return os.path.join(dirname, "config", "test_cfg_alt.py")
|
return os.path.join(dirname, "config", "test_cfg_alt.py")
|
||||||
|
def cfg_file_with_wsgi_app():
|
||||||
|
return os.path.join(dirname, "config", "test_cfg_with_wsgi_app.py")
|
||||||
def paster_ini():
|
def paster_ini():
|
||||||
return os.path.join(dirname, "..", "examples", "frameworks", "pylonstest", "nose.ini")
|
return os.path.join(dirname, "..", "examples", "frameworks", "pylonstest", "nose.ini")
|
||||||
|
|
||||||
@ -52,6 +55,14 @@ class NoConfigApp(Application):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class WSGIApp(WSGIApplication):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("no_usage", prog="gunicorn_test")
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_defaults():
|
def test_defaults():
|
||||||
c = config.Config()
|
c = config.Config()
|
||||||
for s in config.KNOWN_SETTINGS:
|
for s in config.KNOWN_SETTINGS:
|
||||||
@ -353,6 +364,7 @@ def test_invalid_enviroment_variables_config(monkeypatch, capsys):
|
|||||||
_, err = capsys.readouterr()
|
_, err = capsys.readouterr()
|
||||||
assert "error: unrecognized arguments: --foo" in err
|
assert "error: unrecognized arguments: --foo" in err
|
||||||
|
|
||||||
|
|
||||||
def test_cli_overrides_enviroment_variables_module(monkeypatch):
|
def test_cli_overrides_enviroment_variables_module(monkeypatch):
|
||||||
monkeypatch.setenv("GUNICORN_CMD_ARGS", "--workers=4")
|
monkeypatch.setenv("GUNICORN_CMD_ARGS", "--workers=4")
|
||||||
with AltArgs(["prog_name", "-c", cfg_file(), "--workers", "3"]):
|
with AltArgs(["prog_name", "-c", cfg_file(), "--workers", "3"]):
|
||||||
@ -360,6 +372,34 @@ def test_cli_overrides_enviroment_variables_module(monkeypatch):
|
|||||||
assert app.cfg.workers == 3
|
assert app.cfg.workers == 3
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("options, expected", [
|
||||||
|
(["app:app"], 'app:app'),
|
||||||
|
(["-c", cfg_file(), "app:app"], 'app:app'),
|
||||||
|
(["-c", cfg_file_with_wsgi_app(), "app:app"], 'app:app'),
|
||||||
|
(["-c", cfg_file_with_wsgi_app()], 'app1:app1'),
|
||||||
|
])
|
||||||
|
def test_wsgi_app_config(options, expected):
|
||||||
|
cmdline = ["prog_name"]
|
||||||
|
cmdline.extend(options)
|
||||||
|
with AltArgs(cmdline):
|
||||||
|
app = WSGIApp()
|
||||||
|
assert app.app_uri == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("options", [
|
||||||
|
([]),
|
||||||
|
(["-c", cfg_file()]),
|
||||||
|
])
|
||||||
|
def test_non_wsgi_app(options, capsys):
|
||||||
|
cmdline = ["prog_name"]
|
||||||
|
cmdline.extend(options)
|
||||||
|
with AltArgs(cmdline):
|
||||||
|
with pytest.raises(SystemExit):
|
||||||
|
WSGIApp()
|
||||||
|
_, err = capsys.readouterr()
|
||||||
|
assert "Error: No application module specified." in err
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("options, expected", [
|
@pytest.mark.parametrize("options, expected", [
|
||||||
(["myapp:app"], False),
|
(["myapp:app"], False),
|
||||||
(["--reload", "myapp:app"], True),
|
(["--reload", "myapp:app"], True),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user