Merge pull request #1436 from jotagesales/config_from_object_string
Config from object string
This commit is contained in:
commit
8fbbe94fe1
|
@ -53,6 +53,13 @@ import myapp.default_settings
|
||||||
app = Sanic('myapp')
|
app = Sanic('myapp')
|
||||||
app.config.from_object(myapp.default_settings)
|
app.config.from_object(myapp.default_settings)
|
||||||
```
|
```
|
||||||
|
or also by path to config:
|
||||||
|
|
||||||
|
```
|
||||||
|
app = Sanic('myapp')
|
||||||
|
app.config.from_object('config.path.config.Class')
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
You could use a class or any other object as well.
|
You could use a class or any other object as well.
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import os
|
||||||
import types
|
import types
|
||||||
|
|
||||||
from sanic.exceptions import PyFileError
|
from sanic.exceptions import PyFileError
|
||||||
|
from sanic.helpers import import_string
|
||||||
|
|
||||||
|
|
||||||
SANIC_PREFIX = "SANIC_"
|
SANIC_PREFIX = "SANIC_"
|
||||||
|
@ -102,6 +103,9 @@ class Config(dict):
|
||||||
from yourapplication import default_config
|
from yourapplication import default_config
|
||||||
app.config.from_object(default_config)
|
app.config.from_object(default_config)
|
||||||
|
|
||||||
|
or also:
|
||||||
|
app.config.from_object('myproject.config.MyConfigClass')
|
||||||
|
|
||||||
You should not use this function to load the actual configuration but
|
You should not use this function to load the actual configuration but
|
||||||
rather configuration defaults. The actual config should be loaded
|
rather configuration defaults. The actual config should be loaded
|
||||||
with :meth:`from_pyfile` and ideally from a location not within the
|
with :meth:`from_pyfile` and ideally from a location not within the
|
||||||
|
@ -109,6 +113,8 @@ class Config(dict):
|
||||||
|
|
||||||
:param obj: an object holding the configuration
|
:param obj: an object holding the configuration
|
||||||
"""
|
"""
|
||||||
|
if isinstance(obj, str):
|
||||||
|
obj = import_string(obj)
|
||||||
for key in dir(obj):
|
for key in dir(obj):
|
||||||
if key.isupper():
|
if key.isupper():
|
||||||
self[key] = getattr(obj, key)
|
self[key] = getattr(obj, key)
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
"""Defines basics of HTTP standard."""
|
"""Defines basics of HTTP standard."""
|
||||||
|
|
||||||
|
from importlib import import_module
|
||||||
|
from inspect import ismodule
|
||||||
|
|
||||||
|
|
||||||
STATUS_CODES = {
|
STATUS_CODES = {
|
||||||
100: b"Continue",
|
100: b"Continue",
|
||||||
101: b"Switching Protocols",
|
101: b"Switching Protocols",
|
||||||
|
@ -131,3 +135,21 @@ def remove_entity_headers(headers, allowed=("content-location", "expires")):
|
||||||
if not is_entity_header(header) or header.lower() in allowed
|
if not is_entity_header(header) or header.lower() in allowed
|
||||||
}
|
}
|
||||||
return headers
|
return headers
|
||||||
|
|
||||||
|
|
||||||
|
def import_string(module_name, package=None):
|
||||||
|
"""
|
||||||
|
import a module or class by string path.
|
||||||
|
|
||||||
|
:module_name: str with path of module or path to import and
|
||||||
|
instanciate a class
|
||||||
|
:returns: a module object or one instance from class if
|
||||||
|
module_name is a valid path to class
|
||||||
|
|
||||||
|
"""
|
||||||
|
module, klass = module_name.rsplit(".", 1)
|
||||||
|
module = import_module(module, package=package)
|
||||||
|
obj = getattr(module, klass)
|
||||||
|
if ismodule(obj):
|
||||||
|
return obj
|
||||||
|
return obj()
|
||||||
|
|
|
@ -18,17 +18,30 @@ def temp_path():
|
||||||
yield Path(td, "file")
|
yield Path(td, "file")
|
||||||
|
|
||||||
|
|
||||||
def test_load_from_object(app):
|
class ConfigTest:
|
||||||
class Config:
|
not_for_config = 'should not be used'
|
||||||
not_for_config = "should not be used"
|
CONFIG_VALUE = 'should be used'
|
||||||
CONFIG_VALUE = "should be used"
|
|
||||||
|
|
||||||
app.config.from_object(Config)
|
|
||||||
|
def test_load_from_object(app):
|
||||||
|
app.config.from_object(ConfigTest)
|
||||||
assert "CONFIG_VALUE" in app.config
|
assert "CONFIG_VALUE" in app.config
|
||||||
assert app.config.CONFIG_VALUE == "should be used"
|
assert app.config.CONFIG_VALUE == "should be used"
|
||||||
assert "not_for_config" not in app.config
|
assert "not_for_config" not in app.config
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_from_object_string(app):
|
||||||
|
app.config.from_object('test_config.ConfigTest')
|
||||||
|
assert 'CONFIG_VALUE' in app.config
|
||||||
|
assert app.config.CONFIG_VALUE == 'should be used'
|
||||||
|
assert 'not_for_config' not in app.config
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_from_object_string_exception(app):
|
||||||
|
with pytest.raises(ImportError):
|
||||||
|
app.config.from_object('test_config.Config.test')
|
||||||
|
|
||||||
|
|
||||||
def test_auto_load_env():
|
def test_auto_load_env():
|
||||||
environ["SANIC_TEST_ANSWER"] = "42"
|
environ["SANIC_TEST_ANSWER"] = "42"
|
||||||
app = Sanic()
|
app = Sanic()
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
import inspect
|
||||||
|
|
||||||
from sanic import helpers
|
from sanic import helpers
|
||||||
|
from sanic.config import Config
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test_has_message_body():
|
def test_has_message_body():
|
||||||
|
@ -56,3 +60,18 @@ def test_remove_entity_headers():
|
||||||
|
|
||||||
for header, expected in tests:
|
for header, expected in tests:
|
||||||
assert helpers.remove_entity_headers(header) == expected
|
assert helpers.remove_entity_headers(header) == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_import_string_class():
|
||||||
|
obj = helpers.import_string('sanic.config.Config')
|
||||||
|
assert isinstance(obj, Config)
|
||||||
|
|
||||||
|
|
||||||
|
def test_import_string_module():
|
||||||
|
module = helpers.import_string('sanic.config')
|
||||||
|
assert inspect.ismodule(module)
|
||||||
|
|
||||||
|
|
||||||
|
def test_import_string_exception():
|
||||||
|
with pytest.raises(ImportError):
|
||||||
|
helpers.import_string('test.test.test')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user