diff --git a/README.rst b/README.rst index 1df658e1..1de439cf 100644 --- a/README.rst +++ b/README.rst @@ -52,7 +52,8 @@ After installing Gunicorn you will have access to the command line script Commonly Used Arguments +++++++++++++++++++++++ - * ``-c CONFIG, --config=CONFIG`` - Specify the path to a `config file`_ + * ``-c CONFIG, --config=CONFIG`` - Specify the path to a `config file`_ or + python module. * ``-b BIND, --bind=BIND`` - Specify a server socket to bind. Server sockets can be any of ``$(HOST)``, ``$(HOST):$(PORT)``, or ``unix:$(PATH)``. An IP is a valid ``$(HOST)``. diff --git a/docs/source/settings.rst b/docs/source/settings.rst index 9eee8b2e..6996db0c 100644 --- a/docs/source/settings.rst +++ b/docs/source/settings.rst @@ -18,7 +18,7 @@ config * ``-c FILE, --config FILE`` * ``None`` -The path to a Gunicorn config file. +The path to a Gunicorn config file, or python module. Only has an effect when specified on the command line or as part of an application specific configuration. diff --git a/gunicorn/app/base.py b/gunicorn/app/base.py index b23b6b35..bc6ea188 100644 --- a/gunicorn/app/base.py +++ b/gunicorn/app/base.py @@ -75,11 +75,9 @@ class BaseApplication(object): sys.exit(1) class Application(BaseApplication): - def load_config_from_file(self, filename): - """ - Loads the configuration file: the file is a python file, otherwise raise an RuntimeError - Exception or stop the process if the configuration file contains a syntax error. - """ + + def get_config_from_filename(self, filename): + if not os.path.exists(filename): raise RuntimeError("%r doesn't exist" % filename) @@ -97,6 +95,22 @@ class Application(BaseApplication): traceback.print_exc() sys.exit(1) + return cfg + + def get_config_from_module_name(self, module_name): + return util.import_module(module_name).__dict__ + + def load_config_from_module_name_or_filename(self, location): + """ + Loads the configuration file: the file is a python file, otherwise raise an RuntimeError + Exception or stop the process if the configuration file contains a syntax error. + """ + + try: + cfg = self.get_config_from_module_name(module_name=location) + except ImportError: + cfg = self.get_config_from_filename(filename=location) + for k, v in cfg.items(): # Ignore unknown names if k not in self.cfg.settings: @@ -109,6 +123,11 @@ class Application(BaseApplication): return cfg + def load_config_from_file(self, filename): + return self.load_config_from_module_name_or_filename( + location=filename + ) + def load_config(self): # parse console args parser = self.cfg.parser() diff --git a/gunicorn/config.py b/gunicorn/config.py index d940fa19..ca5c3d4d 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -454,7 +454,7 @@ class ConfigFile(Setting): validator = validate_string default = None desc = """\ - The path to a Gunicorn config file. + The path to a Gunicorn config file, or python module. Only has an effect when specified on the command line or as part of an application specific configuration. diff --git a/tests/config/__init__.py b/tests/config/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_003-config.py b/tests/test_003-config.py index c35feb79..bbf03521 100644 --- a/tests/test_003-config.py +++ b/tests/test_003-config.py @@ -14,6 +14,8 @@ from gunicorn.app.base import Application from gunicorn.workers.sync import SyncWorker dirname = os.path.dirname(__file__) +def cfg_module(): + return 'config.test_cfg' def cfg_file(): return os.path.join(dirname, "config", "test_cfg.py") def paster_ini(): @@ -185,12 +187,25 @@ def test_load_config(): t.eq(app.cfg.workers, 3) t.eq(app.cfg.proc_name, "fooey") +def test_load_config_module(): + with AltArgs(["prog_name", "-c", cfg_module()]): + app = NoConfigApp() + t.eq(app.cfg.bind, ["unix:/tmp/bar/baz"]) + t.eq(app.cfg.workers, 3) + t.eq(app.cfg.proc_name, "fooey") + def test_cli_overrides_config(): with AltArgs(["prog_name", "-c", cfg_file(), "-b", "blarney"]): app = NoConfigApp() t.eq(app.cfg.bind, ["blarney"]) t.eq(app.cfg.proc_name, "fooey") +def test_cli_overrides_config_module(): + with AltArgs(["prog_name", "-c", cfg_module(), "-b", "blarney"]): + app = NoConfigApp() + t.eq(app.cfg.bind, ["blarney"]) + t.eq(app.cfg.proc_name, "fooey") + def test_default_config_file(): default_config = os.path.join(os.path.abspath(os.getcwd()), 'gunicorn.conf.py')