1import json 2import os 3import textwrap 4from datetime import timedelta 5 6import pytest 7 8import flask 9 10 11# config keys used for the TestConfig 12TEST_KEY = "foo" 13SECRET_KEY = "config" 14 15 16def common_object_test(app): 17 assert app.secret_key == "config" 18 assert app.config["TEST_KEY"] == "foo" 19 assert "TestConfig" not in app.config 20 21 22def test_config_from_pyfile(): 23 app = flask.Flask(__name__) 24 app.config.from_pyfile(f"{__file__.rsplit('.', 1)[0]}.py") 25 common_object_test(app) 26 27 28def test_config_from_object(): 29 app = flask.Flask(__name__) 30 app.config.from_object(__name__) 31 common_object_test(app) 32 33 34def test_config_from_file(): 35 app = flask.Flask(__name__) 36 current_dir = os.path.dirname(os.path.abspath(__file__)) 37 app.config.from_file(os.path.join(current_dir, "static", "config.json"), json.load) 38 common_object_test(app) 39 40 41def test_config_from_mapping(): 42 app = flask.Flask(__name__) 43 app.config.from_mapping({"SECRET_KEY": "config", "TEST_KEY": "foo"}) 44 common_object_test(app) 45 46 app = flask.Flask(__name__) 47 app.config.from_mapping([("SECRET_KEY", "config"), ("TEST_KEY", "foo")]) 48 common_object_test(app) 49 50 app = flask.Flask(__name__) 51 app.config.from_mapping(SECRET_KEY="config", TEST_KEY="foo") 52 common_object_test(app) 53 54 app = flask.Flask(__name__) 55 with pytest.raises(TypeError): 56 app.config.from_mapping({}, {}) 57 58 59def test_config_from_class(): 60 class Base: 61 TEST_KEY = "foo" 62 63 class Test(Base): 64 SECRET_KEY = "config" 65 66 app = flask.Flask(__name__) 67 app.config.from_object(Test) 68 common_object_test(app) 69 70 71def test_config_from_envvar(monkeypatch): 72 monkeypatch.setattr("os.environ", {}) 73 app = flask.Flask(__name__) 74 with pytest.raises(RuntimeError) as e: 75 app.config.from_envvar("FOO_SETTINGS") 76 assert "'FOO_SETTINGS' is not set" in str(e.value) 77 assert not app.config.from_envvar("FOO_SETTINGS", silent=True) 78 79 monkeypatch.setattr( 80 "os.environ", {"FOO_SETTINGS": f"{__file__.rsplit('.', 1)[0]}.py"} 81 ) 82 assert app.config.from_envvar("FOO_SETTINGS") 83 common_object_test(app) 84 85 86def test_config_from_envvar_missing(monkeypatch): 87 monkeypatch.setattr("os.environ", {"FOO_SETTINGS": "missing.cfg"}) 88 with pytest.raises(IOError) as e: 89 app = flask.Flask(__name__) 90 app.config.from_envvar("FOO_SETTINGS") 91 msg = str(e.value) 92 assert msg.startswith( 93 "[Errno 2] Unable to load configuration file (No such file or directory):" 94 ) 95 assert msg.endswith("missing.cfg'") 96 assert not app.config.from_envvar("FOO_SETTINGS", silent=True) 97 98 99def test_config_missing(): 100 app = flask.Flask(__name__) 101 with pytest.raises(IOError) as e: 102 app.config.from_pyfile("missing.cfg") 103 msg = str(e.value) 104 assert msg.startswith( 105 "[Errno 2] Unable to load configuration file (No such file or directory):" 106 ) 107 assert msg.endswith("missing.cfg'") 108 assert not app.config.from_pyfile("missing.cfg", silent=True) 109 110 111def test_config_missing_file(): 112 app = flask.Flask(__name__) 113 with pytest.raises(IOError) as e: 114 app.config.from_file("missing.json", load=json.load) 115 msg = str(e.value) 116 assert msg.startswith( 117 "[Errno 2] Unable to load configuration file (No such file or directory):" 118 ) 119 assert msg.endswith("missing.json'") 120 assert not app.config.from_file("missing.json", load=json.load, silent=True) 121 122 123def test_custom_config_class(): 124 class Config(flask.Config): 125 pass 126 127 class Flask(flask.Flask): 128 config_class = Config 129 130 app = Flask(__name__) 131 assert isinstance(app.config, Config) 132 app.config.from_object(__name__) 133 common_object_test(app) 134 135 136def test_session_lifetime(): 137 app = flask.Flask(__name__) 138 app.config["PERMANENT_SESSION_LIFETIME"] = 42 139 assert app.permanent_session_lifetime.seconds == 42 140 141 142def test_send_file_max_age(): 143 app = flask.Flask(__name__) 144 app.config["SEND_FILE_MAX_AGE_DEFAULT"] = 3600 145 assert app.send_file_max_age_default.seconds == 3600 146 app.config["SEND_FILE_MAX_AGE_DEFAULT"] = timedelta(hours=2) 147 assert app.send_file_max_age_default.seconds == 7200 148 149 150def test_get_namespace(): 151 app = flask.Flask(__name__) 152 app.config["FOO_OPTION_1"] = "foo option 1" 153 app.config["FOO_OPTION_2"] = "foo option 2" 154 app.config["BAR_STUFF_1"] = "bar stuff 1" 155 app.config["BAR_STUFF_2"] = "bar stuff 2" 156 foo_options = app.config.get_namespace("FOO_") 157 assert 2 == len(foo_options) 158 assert "foo option 1" == foo_options["option_1"] 159 assert "foo option 2" == foo_options["option_2"] 160 bar_options = app.config.get_namespace("BAR_", lowercase=False) 161 assert 2 == len(bar_options) 162 assert "bar stuff 1" == bar_options["STUFF_1"] 163 assert "bar stuff 2" == bar_options["STUFF_2"] 164 foo_options = app.config.get_namespace("FOO_", trim_namespace=False) 165 assert 2 == len(foo_options) 166 assert "foo option 1" == foo_options["foo_option_1"] 167 assert "foo option 2" == foo_options["foo_option_2"] 168 bar_options = app.config.get_namespace( 169 "BAR_", lowercase=False, trim_namespace=False 170 ) 171 assert 2 == len(bar_options) 172 assert "bar stuff 1" == bar_options["BAR_STUFF_1"] 173 assert "bar stuff 2" == bar_options["BAR_STUFF_2"] 174 175 176@pytest.mark.parametrize("encoding", ["utf-8", "iso-8859-15", "latin-1"]) 177def test_from_pyfile_weird_encoding(tmpdir, encoding): 178 f = tmpdir.join("my_config.py") 179 f.write_binary( 180 textwrap.dedent( 181 f""" 182 # -*- coding: {encoding} -*- 183 TEST_VALUE = "föö" 184 """ 185 ).encode(encoding) 186 ) 187 app = flask.Flask(__name__) 188 app.config.from_pyfile(str(f)) 189 value = app.config["TEST_VALUE"] 190 assert value == "föö" 191