from __future__ import annotations from dynaconf.loaders.base import SourceMetadata from dynaconf.utils import build_env_list from dynaconf.utils import upperfy from dynaconf.utils.parse_conf import parse_conf_data from dynaconf.utils.parse_conf import unparse_conf_data try: from redis import StrictRedis except ImportError: StrictRedis = None IDENTIFIER = "redis" def load(obj, env=None, silent=True, key=None, validate=False): """Reads and loads in to "settings" a single key or all keys from redis :param obj: the settings instance :param env: settings env default='DYNACONF' :param silent: if errors should raise :param key: if defined load a single key, else load all in env :return: None """ if StrictRedis is None: raise ImportError( "redis package is not installed in your environment. " "`pip install dynaconf[redis]` or disable the redis loader with " "export REDIS_ENABLED_FOR_DYNACONF=false" ) redis = StrictRedis(**obj.get("REDIS_FOR_DYNACONF")) prefix = obj.get("ENVVAR_PREFIX_FOR_DYNACONF") # prefix is added to env_list to keep backwards compatibility env_list = [prefix] + build_env_list(obj, env or obj.current_env) for env_name in env_list: holder = f"{prefix.upper()}_{env_name.upper()}" try: source_metadata = SourceMetadata(IDENTIFIER, "unique", env_name) if key: value = redis.hget(holder.upper(), key) if value: parsed_value = parse_conf_data( value, tomlfy=True, box_settings=obj ) if parsed_value: obj.set( key, parsed_value, validate=validate, loader_identifier=source_metadata, ) else: data = { key: parse_conf_data(value, tomlfy=True, box_settings=obj) for key, value in redis.hgetall(holder.upper()).items() } if data: obj.update( data, loader_identifier=source_metadata, validate=validate, ) except Exception: if silent: return False raise def write(obj, data=None, **kwargs): """Write a value in to loader source :param obj: settings object :param data: vars to be stored :param kwargs: vars to be stored :return: """ if obj.REDIS_ENABLED_FOR_DYNACONF is False: raise RuntimeError( "Redis is not configured \n" "export REDIS_ENABLED_FOR_DYNACONF=true\n" "and configure the REDIS_*_FOR_DYNACONF variables" ) client = StrictRedis(**obj.REDIS_FOR_DYNACONF) holder = obj.get("ENVVAR_PREFIX_FOR_DYNACONF").upper() # add env to holder holder = f"{holder}_{obj.current_env.upper()}" data = data or {} data.update(kwargs) if not data: raise AttributeError("Data must be provided") redis_data = { upperfy(key): unparse_conf_data(value) for key, value in data.items() } client.hset(holder.upper(), mapping=redis_data) load(obj) def delete(obj, key=None): """ Delete a single key if specified, or all env if key is none :param obj: settings object :param key: key to delete from store location :return: None """ client = StrictRedis(**obj.REDIS_FOR_DYNACONF) holder = obj.get("ENVVAR_PREFIX_FOR_DYNACONF").upper() # add env to holder holder = f"{holder}_{obj.current_env.upper()}" if key: client.hdel(holder.upper(), upperfy(key)) obj.unset(key) else: keys = client.hkeys(holder.upper()) client.delete(holder.upper()) obj.unset_all(keys)