2019-04-23 22:44:42 +01:00
|
|
|
from contextlib import contextmanager
|
2016-12-16 17:46:07 +00:00
|
|
|
from os import environ
|
2018-09-29 18:54:47 +01:00
|
|
|
from pathlib import Path
|
|
|
|
from tempfile import TemporaryDirectory
|
|
|
|
from textwrap import dedent
|
2019-04-23 22:44:42 +01:00
|
|
|
|
2016-12-16 17:46:07 +00:00
|
|
|
import pytest
|
|
|
|
|
|
|
|
from sanic import Sanic
|
2019-04-23 22:44:42 +01:00
|
|
|
from sanic.config import DEFAULT_CONFIG, Config
|
2019-01-02 00:35:25 +00:00
|
|
|
from sanic.exceptions import PyFileError
|
2016-12-16 17:46:07 +00:00
|
|
|
|
|
|
|
|
2018-09-29 18:54:47 +01:00
|
|
|
@contextmanager
|
|
|
|
def temp_path():
|
2022-01-16 18:42:38 +00:00
|
|
|
"""a simple cross platform replacement for NamedTemporaryFile"""
|
2018-09-29 18:54:47 +01:00
|
|
|
with TemporaryDirectory() as td:
|
2018-12-30 11:18:06 +00:00
|
|
|
yield Path(td, "file")
|
2018-09-29 18:54:47 +01:00
|
|
|
|
|
|
|
|
2019-03-05 17:36:54 +00:00
|
|
|
class ConfigTest:
|
2019-06-24 20:49:11 +01:00
|
|
|
not_for_config = "should not be used"
|
|
|
|
CONFIG_VALUE = "should be used"
|
2016-12-16 17:46:07 +00:00
|
|
|
|
|
|
|
|
2018-12-26 20:27:02 +00:00
|
|
|
def test_load_from_object(app):
|
2019-03-05 17:36:54 +00:00
|
|
|
app.config.from_object(ConfigTest)
|
2018-12-30 11:18:06 +00:00
|
|
|
assert "CONFIG_VALUE" in app.config
|
|
|
|
assert app.config.CONFIG_VALUE == "should be used"
|
|
|
|
assert "not_for_config" not in app.config
|
2016-12-16 17:46:07 +00:00
|
|
|
|
2018-09-30 14:59:16 +01:00
|
|
|
|
2018-12-26 20:27:02 +00:00
|
|
|
def test_load_from_object_string(app):
|
2019-06-24 20:49:11 +01:00
|
|
|
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
|
2018-12-26 20:27:02 +00:00
|
|
|
|
|
|
|
|
2018-12-26 23:19:54 +00:00
|
|
|
def test_load_from_object_string_exception(app):
|
|
|
|
with pytest.raises(ImportError):
|
2019-06-24 20:49:11 +01:00
|
|
|
app.config.from_object("test_config.Config.test")
|
2018-12-26 23:19:54 +00:00
|
|
|
|
|
|
|
|
2017-03-22 01:37:46 +00:00
|
|
|
def test_auto_load_env():
|
|
|
|
environ["SANIC_TEST_ANSWER"] = "42"
|
2020-03-26 04:42:46 +00:00
|
|
|
app = Sanic(name=__name__)
|
2017-09-05 09:58:48 +01:00
|
|
|
assert app.config.TEST_ANSWER == 42
|
2017-03-22 01:37:46 +00:00
|
|
|
del environ["SANIC_TEST_ANSWER"]
|
|
|
|
|
2018-09-30 14:59:16 +01:00
|
|
|
|
2018-12-30 18:37:30 +00:00
|
|
|
def test_auto_load_bool_env():
|
|
|
|
environ["SANIC_TEST_ANSWER"] = "True"
|
2020-03-26 04:42:46 +00:00
|
|
|
app = Sanic(name=__name__)
|
2018-12-30 18:37:30 +00:00
|
|
|
assert app.config.TEST_ANSWER == True
|
|
|
|
del environ["SANIC_TEST_ANSWER"]
|
|
|
|
|
|
|
|
|
2017-09-05 09:58:48 +01:00
|
|
|
def test_dont_load_env():
|
2017-03-22 01:37:46 +00:00
|
|
|
environ["SANIC_TEST_ANSWER"] = "42"
|
2020-03-26 04:42:46 +00:00
|
|
|
app = Sanic(name=__name__, load_env=False)
|
2018-12-30 11:18:06 +00:00
|
|
|
assert getattr(app.config, "TEST_ANSWER", None) is None
|
2017-03-22 01:37:46 +00:00
|
|
|
del environ["SANIC_TEST_ANSWER"]
|
2016-12-16 17:46:07 +00:00
|
|
|
|
2018-09-30 14:59:16 +01:00
|
|
|
|
2017-09-05 09:58:48 +01:00
|
|
|
def test_load_env_prefix():
|
|
|
|
environ["MYAPP_TEST_ANSWER"] = "42"
|
2020-03-26 04:42:46 +00:00
|
|
|
app = Sanic(name=__name__, load_env="MYAPP_")
|
2017-09-05 09:58:48 +01:00
|
|
|
assert app.config.TEST_ANSWER == 42
|
|
|
|
del environ["MYAPP_TEST_ANSWER"]
|
|
|
|
|
2018-09-30 14:59:16 +01:00
|
|
|
|
2018-11-10 11:20:30 +00:00
|
|
|
def test_load_env_prefix_float_values():
|
|
|
|
environ["MYAPP_TEST_ROI"] = "2.3"
|
2020-03-26 04:42:46 +00:00
|
|
|
app = Sanic(name=__name__, load_env="MYAPP_")
|
2018-11-10 11:20:30 +00:00
|
|
|
assert app.config.TEST_ROI == 2.3
|
|
|
|
del environ["MYAPP_TEST_ROI"]
|
|
|
|
|
|
|
|
|
|
|
|
def test_load_env_prefix_string_value():
|
|
|
|
environ["MYAPP_TEST_TOKEN"] = "somerandomtesttoken"
|
2020-03-26 04:42:46 +00:00
|
|
|
app = Sanic(name=__name__, load_env="MYAPP_")
|
2018-11-10 11:20:30 +00:00
|
|
|
assert app.config.TEST_TOKEN == "somerandomtesttoken"
|
|
|
|
del environ["MYAPP_TEST_TOKEN"]
|
|
|
|
|
|
|
|
|
2018-08-26 15:43:14 +01:00
|
|
|
def test_load_from_file(app):
|
2018-12-30 11:18:06 +00:00
|
|
|
config = dedent(
|
|
|
|
"""
|
2018-09-29 18:54:47 +01:00
|
|
|
VALUE = 'some value'
|
|
|
|
condition = 1 == 1
|
|
|
|
if condition:
|
|
|
|
CONDITIONAL = 'should be set'
|
2018-12-30 11:18:06 +00:00
|
|
|
"""
|
|
|
|
)
|
2018-09-29 18:54:47 +01:00
|
|
|
with temp_path() as config_path:
|
|
|
|
config_path.write_text(config)
|
|
|
|
app.config.from_pyfile(str(config_path))
|
2018-12-30 11:18:06 +00:00
|
|
|
assert "VALUE" in app.config
|
|
|
|
assert app.config.VALUE == "some value"
|
|
|
|
assert "CONDITIONAL" in app.config
|
|
|
|
assert app.config.CONDITIONAL == "should be set"
|
|
|
|
assert "condition" not in app.config
|
2016-12-16 17:46:07 +00:00
|
|
|
|
|
|
|
|
2018-08-26 15:43:14 +01:00
|
|
|
def test_load_from_missing_file(app):
|
2016-12-16 17:46:07 +00:00
|
|
|
with pytest.raises(IOError):
|
2018-12-30 11:18:06 +00:00
|
|
|
app.config.from_pyfile("non-existent file")
|
2016-12-16 17:46:07 +00:00
|
|
|
|
|
|
|
|
2018-08-26 15:43:14 +01:00
|
|
|
def test_load_from_envvar(app):
|
2018-09-29 18:54:47 +01:00
|
|
|
config = "VALUE = 'some value'"
|
|
|
|
with temp_path() as config_path:
|
|
|
|
config_path.write_text(config)
|
2018-12-30 11:18:06 +00:00
|
|
|
environ["APP_CONFIG"] = str(config_path)
|
|
|
|
app.config.from_envvar("APP_CONFIG")
|
|
|
|
assert "VALUE" in app.config
|
|
|
|
assert app.config.VALUE == "some value"
|
2016-12-16 17:46:07 +00:00
|
|
|
|
|
|
|
|
2018-08-26 15:43:14 +01:00
|
|
|
def test_load_from_missing_envvar(app):
|
2018-09-30 14:59:16 +01:00
|
|
|
with pytest.raises(RuntimeError) as e:
|
2018-12-30 11:18:06 +00:00
|
|
|
app.config.from_envvar("non-existent variable")
|
|
|
|
assert str(e.value) == (
|
|
|
|
"The environment variable 'non-existent "
|
|
|
|
"variable' is not set and thus configuration "
|
|
|
|
"could not be loaded."
|
|
|
|
)
|
2016-12-16 17:46:07 +00:00
|
|
|
|
|
|
|
|
2018-10-03 13:27:59 +01:00
|
|
|
def test_load_config_from_file_invalid_syntax(app):
|
2018-10-11 16:34:46 +01:00
|
|
|
config = "VALUE = some value"
|
|
|
|
with temp_path() as config_path:
|
|
|
|
config_path.write_text(config)
|
2018-10-03 13:27:59 +01:00
|
|
|
|
|
|
|
with pytest.raises(PyFileError):
|
2018-10-11 16:34:46 +01:00
|
|
|
app.config.from_pyfile(config_path)
|
2018-10-03 13:27:59 +01:00
|
|
|
|
|
|
|
|
2018-08-26 15:43:14 +01:00
|
|
|
def test_overwrite_exisiting_config(app):
|
2016-12-16 17:46:07 +00:00
|
|
|
app.config.DEFAULT = 1
|
2018-09-30 14:59:16 +01:00
|
|
|
|
2016-12-16 17:46:07 +00:00
|
|
|
class Config:
|
|
|
|
DEFAULT = 2
|
|
|
|
|
|
|
|
app.config.from_object(Config)
|
|
|
|
assert app.config.DEFAULT == 2
|
|
|
|
|
|
|
|
|
2018-10-06 23:14:37 +01:00
|
|
|
def test_overwrite_exisiting_config_ignore_lowercase(app):
|
|
|
|
app.config.default = 1
|
|
|
|
|
|
|
|
class Config:
|
|
|
|
default = 2
|
|
|
|
|
|
|
|
app.config.from_object(Config)
|
|
|
|
assert app.config.default == 1
|
|
|
|
|
|
|
|
|
2018-08-26 15:43:14 +01:00
|
|
|
def test_missing_config(app):
|
2019-02-28 14:56:41 +00:00
|
|
|
with pytest.raises(
|
|
|
|
AttributeError, match="Config has no 'NON_EXISTENT'"
|
|
|
|
) as e:
|
|
|
|
_ = app.config.NON_EXISTENT
|
2018-12-30 18:37:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_config_defaults():
|
|
|
|
"""
|
|
|
|
load DEFAULT_CONFIG
|
|
|
|
"""
|
|
|
|
conf = Config()
|
|
|
|
for key, value in DEFAULT_CONFIG.items():
|
|
|
|
assert getattr(conf, key) == value
|
|
|
|
|
|
|
|
|
|
|
|
def test_config_custom_defaults():
|
|
|
|
"""
|
|
|
|
we should have all the variables from defaults rewriting them with custom defaults passed in
|
|
|
|
Config
|
|
|
|
"""
|
|
|
|
custom_defaults = {
|
|
|
|
"REQUEST_MAX_SIZE": 1,
|
|
|
|
"KEEP_ALIVE": False,
|
2019-02-06 18:29:33 +00:00
|
|
|
"ACCESS_LOG": False,
|
2018-12-30 18:37:30 +00:00
|
|
|
}
|
|
|
|
conf = Config(defaults=custom_defaults)
|
|
|
|
for key, value in DEFAULT_CONFIG.items():
|
|
|
|
if key in custom_defaults.keys():
|
|
|
|
value = custom_defaults[key]
|
|
|
|
assert getattr(conf, key) == value
|
|
|
|
|
|
|
|
|
|
|
|
def test_config_custom_defaults_with_env():
|
|
|
|
"""
|
|
|
|
test that environment variables has higher priority than DEFAULT_CONFIG and passed defaults dict
|
|
|
|
"""
|
|
|
|
custom_defaults = {
|
|
|
|
"REQUEST_MAX_SIZE123": 1,
|
|
|
|
"KEEP_ALIVE123": False,
|
2019-02-06 18:29:33 +00:00
|
|
|
"ACCESS_LOG123": False,
|
2018-12-30 18:37:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
environ_defaults = {
|
|
|
|
"SANIC_REQUEST_MAX_SIZE123": "2",
|
|
|
|
"SANIC_KEEP_ALIVE123": "True",
|
2019-02-06 18:29:33 +00:00
|
|
|
"SANIC_ACCESS_LOG123": "False",
|
2018-12-30 18:37:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for key, value in environ_defaults.items():
|
|
|
|
environ[key] = value
|
|
|
|
|
|
|
|
conf = Config(defaults=custom_defaults)
|
|
|
|
for key, value in DEFAULT_CONFIG.items():
|
|
|
|
if "SANIC_" + key in environ_defaults.keys():
|
|
|
|
value = environ_defaults["SANIC_" + key]
|
|
|
|
try:
|
|
|
|
value = int(value)
|
|
|
|
except ValueError:
|
2019-02-06 18:29:33 +00:00
|
|
|
if value in ["True", "False"]:
|
|
|
|
value = value == "True"
|
2018-12-30 18:37:30 +00:00
|
|
|
|
|
|
|
assert getattr(conf, key) == value
|
|
|
|
|
|
|
|
for key, value in environ_defaults.items():
|
|
|
|
del environ[key]
|
2018-12-30 20:27:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_config_access_log_passing_in_run(app):
|
|
|
|
assert app.config.ACCESS_LOG == True
|
|
|
|
|
2019-02-06 18:29:33 +00:00
|
|
|
@app.listener("after_server_start")
|
2018-12-30 20:27:20 +00:00
|
|
|
async def _request(sanic, loop):
|
|
|
|
app.stop()
|
|
|
|
|
|
|
|
app.run(port=1340, access_log=False)
|
|
|
|
assert app.config.ACCESS_LOG == False
|
|
|
|
|
|
|
|
app.run(port=1340, access_log=True)
|
|
|
|
assert app.config.ACCESS_LOG == True
|
|
|
|
|
|
|
|
|
2019-06-04 08:58:00 +01:00
|
|
|
@pytest.mark.asyncio
|
2018-12-30 21:14:10 +00:00
|
|
|
async def test_config_access_log_passing_in_create_server(app):
|
|
|
|
assert app.config.ACCESS_LOG == True
|
|
|
|
|
2019-02-06 18:29:33 +00:00
|
|
|
@app.listener("after_server_start")
|
2018-12-30 21:14:10 +00:00
|
|
|
async def _request(sanic, loop):
|
|
|
|
app.stop()
|
|
|
|
|
2019-02-06 18:29:33 +00:00
|
|
|
await app.create_server(
|
|
|
|
port=1341, access_log=False, return_asyncio_server=True
|
|
|
|
)
|
2018-12-30 21:14:10 +00:00
|
|
|
assert app.config.ACCESS_LOG == False
|
|
|
|
|
2019-02-06 18:29:33 +00:00
|
|
|
await app.create_server(
|
|
|
|
port=1342, access_log=True, return_asyncio_server=True
|
|
|
|
)
|
2018-12-30 21:14:10 +00:00
|
|
|
assert app.config.ACCESS_LOG == True
|
|
|
|
|
|
|
|
|
2018-12-30 20:27:20 +00:00
|
|
|
def test_config_rewrite_keep_alive():
|
|
|
|
config = Config()
|
|
|
|
assert config.KEEP_ALIVE == DEFAULT_CONFIG["KEEP_ALIVE"]
|
|
|
|
config = Config(keep_alive=True)
|
|
|
|
assert config.KEEP_ALIVE == True
|
|
|
|
config = Config(keep_alive=False)
|
|
|
|
assert config.KEEP_ALIVE == False
|
|
|
|
|
|
|
|
# use defaults
|
|
|
|
config = Config(defaults={"KEEP_ALIVE": False})
|
|
|
|
assert config.KEEP_ALIVE == False
|
|
|
|
config = Config(defaults={"KEEP_ALIVE": True})
|
|
|
|
assert config.KEEP_ALIVE == True
|