def test_empty_string_prefix(): environ["_VALUE"] = "underscored" load_from_env(identifier="env_global", key=None, env="", obj=settings, silent=True) assert settings.VALUE == "underscored"
def test_no_prefix(): environ["VALUE"] = "no_prefix" load_from_env(identifier="env_global", key=None, env=False, obj=settings, silent=True) assert settings.VALUE == "no_prefix"
def test_none_as_string_prefix(): environ["NONE_VALUE"] = "none as prefix" load_from_env( identifier="env_global", key=None, env="none", obj=settings, silent=True, ) assert settings.VALUE == "none as prefix"
def test_backwards_compat_using_env_argument(): environ["BLARG_VALUE"] = "BLARG as prefix" load_from_env( identifier="env_global", key=None, env="BLARG", # renamed to `prefix` on 3.0.0 obj=settings, silent=True, ) assert settings.VALUE == "BLARG as prefix"
def test_filtering_unknown_variables(): # Predefine some known variable. settings.MYCONFIG = "bar" # Enable environment filtering. settings.IGNORE_UNKNOWN_ENVVARS_FOR_DYNACONF = True # Pollute the environment. environ["IGNOREME"] = "foo" load_from_env( obj=settings, prefix=False, key=None, silent=True, identifier="env_global", env=False, ) # Verify the filter works. assert not settings.get("IGNOREME") # Smoke test. assert settings.get("MYCONFIG") == "bar"
def configure_dynaconf(app): # extra vars in .secrets.yml override values on quokka.yml # secrets file is a hidden file and must be excluded on .gitignore # all password, token and other sensitive must go there # or exported as env var ex: QUOKKA_SECRET_KEY=12345 settings_file = 'quokka.yml,.secrets.yml' initial_envmode = app.config.get('ENVMODE') # Extension is supposed to override envmode FlaskDynaconf( app, ENVVAR_FOR_DYNACONF="QUOKKA_SETTINGS_MODULE", DYNACONF_NAMESPACE='QUOKKA', SETTINGS_MODULE_FOR_DYNACONF=settings_file, DYNACONF_SILENT_ERRORS=True ) # Configure extra environment envmode = initial_envmode or app.config.get('ENVMODE') if envmode is not None: yaml_loader.load( obj=app.config, namespace=envmode, filename=settings_file ) # overload with envvars env_loader.load_from_env( identifier=envmode, key=None, namespace=f'quokka_{envmode}', obj=app.config, silent=True ) # configure theme options app.theme_context = { 'JINJA_ENVIRONMENT': app.jinja_env, 'DEFAULT_LANG': app.config.get('BABEL_DEFAULT_LOCALE'), 'default_locale': app.config.get('BABEL_DEFAULT_LOCALE'), 'PAGES': [], 'pages': [], 'tags': [], 'articles': [], 'categories': [], # https://github.com/getpelican/pelican-plugins/tree/master/tag_cloud 'tag_cloud': [], 'CATEGORIES_URL': 'categories/index.html', 'JINJA_EXTENSIONS': app.jinja_env.extensions, 'USE_LESS': False, # For some themes like bootstrap3 theme SITEURL must be '' 'SITEURL': 'http://localhost:5000', 'THEME_STATIC_DIR': 'theme', 'FAVICON': 'favicon.ico', 'FAVICON_IE': 'favicon.ico', 'FAVICON_FILENAME': 'favicon.ico', # 'AVATAR': 'LOAD FROM UPLOADS', 'NEWEST_FIRST_ARCHIVES': True } # load theme variables from YAML file yaml_loader.load( obj=app.theme_context, namespace='theme', filename=app.config.get('SETTINGS_MODULE') ) # overrride with QUOKKA_THEME_ prefixed env vars if exist env_loader.load_from_env( identifier='theme', key=None, namespace='quokka_theme', obj=app.theme_context, silent=True ) # remove prefix for pelican-themes active = app.theme_context.get('ACTIVE', 'default') if active.startswith('pelican'): active = active.lstrip('pelican-') app.theme_context['ACTIVE'] = active # load theme specific variables from YAML yaml_loader.load( obj=app.theme_context, namespace=f'theme_{app.theme_context.get("ACTIVE")}', filename=app.config.get('SETTINGS_MODULE') ) # overrride with QUOKKA_THEME_THEMENAME prefixed env vars if exist env_loader.load_from_env( identifier=f'theme_{app.theme_context.get("ACTIVE")}', key=None, namespace=f'quokka_theme_{app.theme_context.get("ACTIVE")}', obj=app.theme_context, silent=True ) # mark strings as safe Markup for k, v in app.theme_context.items(): if isinstance(v, str): app.theme_context[k] = Markup(v)
def test_load_dunder(clean_env): """Test load and merge with dunder settings""" clean_environ("DYNACONF_DATABASES") settings.set( "DATABASES", { "default": { "NAME": "db", "ENGINE": "module.foo.engine", "ARGS": { "timeout": 30 }, "PORTS": [123, 456], } }, ) # change engine clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__default__ENGINE"] = "other.module" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert settings.DATABASES.default.ENGINE == "other.module" # change timeout directly clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__default__ARGS__timeout"] = "99" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert settings.DATABASES.default.ARGS.timeout == 99 # add to ARGS clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__default__ARGS"] = "{retries=10}" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert settings.DATABASES.default.ARGS.retries == 10 assert settings.DATABASES.default.ARGS.timeout == 99 # Ensure dictionary keeps its format assert settings.DATABASES == { "default": { "NAME": "db", "ENGINE": "other.module", "ARGS": { "timeout": 99, "retries": 10 }, "PORTS": [123, 456], } } assert "default" in settings["DATABASES"].keys() assert "DEFAULT" not in settings["DATABASES"].keys() assert "NAME" in settings["DATABASES"]["default"].keys() assert "name" not in settings["DATABASES"]["default"].keys() # Clean args clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__default__ARGS"] = "@reset {timeout=8}" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert settings.DATABASES.default.ARGS == {"timeout": 8} # Make args empty clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__default__ARGS"] = "@reset {}" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert settings.DATABASES.default.ARGS == {} # Remove ARGS key clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__default__ARGS"] = "@del" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert "ARGS" not in settings.DATABASES.default.keys() # add to existing PORTS clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__default__PORTS"] = "[789, 101112]" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert "ARGS" not in settings.DATABASES.default.keys() assert settings.DATABASES.default.PORTS == [123, 456, 789, 101112] # reset PORTS clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__default__PORTS"] = "@reset [789, 101112]" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert "ARGS" not in settings.DATABASES.default.keys() assert settings.DATABASES.default.PORTS == [789, 101112] # delete PORTS clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__default__PORTS"] = "@del" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert "ARGS" not in settings.DATABASES.default.keys() assert "PORTS" not in settings.DATABASES.default.keys() # reset default key clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__default"] = "@reset {}" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert settings.DATABASES.default == {} # remove default clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__default"] = "@del" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert settings.DATABASES == {} # set value to databases clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES__foo"] = "bar" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert settings.DATABASES == {"foo": "bar"} # reset databases clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES"] = "{hello='world'}" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert settings.DATABASES == {"hello": "world"} # also reset databases clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES"] = "@reset {yes='no'}" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert settings.DATABASES == {"yes": "no"} # remove databases clean_environ("DYNACONF_DATABASES") environ["DYNACONF_DATABASES"] = "@del" load_from_env( identifier="env_global", key=None, env="dynaconf", obj=settings, silent=True, ) assert "DATABASES" not in settings
def test_can_load_in_to_dict(): os.environ["LOADTODICT"] = "true" sets = {} load_from_env(sets, prefix=False, key="LOADTODICT") assert sets["LOADTODICT"] is True
def test_env_is_not_str_raises(): with pytest.raises(TypeError): load_from_env(settings, prefix=int) with pytest.raises(TypeError): load_from_env(settings, prefix=True)
def configure_dynaconf(app): # extra vars in .secrets.yml override values on quokka.yml # secrets file is a hidden file and must be excluded on .gitignore # all password, token and other sensitive must go there # or exported as env var ex: QUOKKA_SECRET_KEY=12345 settings_file = 'quokka.yml,.secrets.yml' initial_envmode = app.config.get('ENVMODE') # Extension is supposed to override envmode FlaskDynaconf(app, ENVVAR_FOR_DYNACONF="QUOKKA_SETTINGS_MODULE", DYNACONF_NAMESPACE='QUOKKA', SETTINGS_MODULE_FOR_DYNACONF=settings_file, DYNACONF_SILENT_ERRORS=True) # Configure extra environment envmode = initial_envmode or app.config.get('ENVMODE') if envmode is not None: yaml_loader.load(obj=app.config, namespace=envmode, filename=settings_file) # overload with envvars env_loader.load_from_env(identifier=envmode, key=None, namespace=f'quokka_{envmode}', obj=app.config, silent=True) # configure theme options app.theme_context = { 'JINJA_ENVIRONMENT': app.jinja_env, 'DEFAULT_LANG': app.config.get('BABEL_DEFAULT_LOCALE'), 'default_locale': app.config.get('BABEL_DEFAULT_LOCALE'), 'PAGES': [], 'pages': [], 'tags': [], 'articles': [], 'categories': [], # https://github.com/getpelican/pelican-plugins/tree/master/tag_cloud 'tag_cloud': [], 'CATEGORIES_URL': 'categories/index.html', 'JINJA_EXTENSIONS': app.jinja_env.extensions, 'USE_LESS': False, # For some themes like bootstrap3 theme SITEURL must be '' 'SITEURL': 'http://localhost:5000', 'THEME_STATIC_DIR': 'theme', 'FAVICON': 'favicon.ico', 'FAVICON_IE': 'favicon.ico', 'FAVICON_FILENAME': 'favicon.ico', # 'AVATAR': 'LOAD FROM UPLOADS', 'NEWEST_FIRST_ARCHIVES': True } # load theme variables from YAML file yaml_loader.load(obj=app.theme_context, namespace='theme', filename=app.config.get('SETTINGS_MODULE')) # overrride with QUOKKA_THEME_ prefixed env vars if exist env_loader.load_from_env(identifier='theme', key=None, namespace='quokka_theme', obj=app.theme_context, silent=True) # remove prefix for pelican-themes active = app.theme_context.get('ACTIVE', 'default') if active.startswith('pelican'): active = active.lstrip('pelican-') app.theme_context['ACTIVE'] = active # load theme specific variables from YAML yaml_loader.load(obj=app.theme_context, namespace=f'theme_{app.theme_context.get("ACTIVE")}', filename=app.config.get('SETTINGS_MODULE')) # overrride with QUOKKA_THEME_THEMENAME prefixed env vars if exist env_loader.load_from_env( identifier=f'theme_{app.theme_context.get("ACTIVE")}', key=None, namespace=f'quokka_theme_{app.theme_context.get("ACTIVE")}', obj=app.theme_context, silent=True) # TODO: LOAD THEME VARS FROM MODEL # mark strings as safe Markup for k, v in app.theme_context.items(): if isinstance(v, str): app.theme_context[k] = Markup(v)