def test_returns_unmodified_if_no_variable_references(self): config = { collections.CompoundKey(["a", "b"]): "foo", collections.CompoundKey(["a"]): "bar", } replaced = replace_variable_references(config) assert config == replaced
def test_replaces_root_variable(self): config = { collections.CompoundKey(["a"]): "${b}", collections.CompoundKey(["b"]): "foo", } replaced = replace_variable_references(config) assert (replaced[collections.CompoundKey( ["a"])] == replaced[collections.CompoundKey(["b"])])
def test_chained_variables(self): config = { collections.CompoundKey(["a"]): "${b}", collections.CompoundKey(["b"]): "${c}", collections.CompoundKey(["c"]): "bar", } replaced = replace_variable_references(config) for value in replaced.values(): assert value == "bar"
def test_replaces_from_root_to_nested_keys(self): config = { collections.CompoundKey(["a"]): "${a.b}", collections.CompoundKey(["a", "b"]): "foo", } replaced = replace_variable_references(config) assert (replaced[collections.CompoundKey( ["a"])] == replaced[collections.CompoundKey(["a", "b"])])
def test_doesnt_modify_input(self): config = { collections.CompoundKey(["a", "b"]): "foo", collections.CompoundKey(["a"]): "${a.b}", } before_config = { collections.CompoundKey(["a", "b"]): "foo", collections.CompoundKey(["a"]): "${a.b}", } replaced = replace_variable_references(config) assert config == before_config assert config != replaced
def test_array_replacement_missing_variable(self): config = { collections.CompoundKey(["a"]): "foo", collections.CompoundKey(["b"]): ["${a}", "${a}", "${c}"], } replaced = replace_variable_references(config) assert replaced[collections.CompoundKey(["b"])] == [ replaced[collections.CompoundKey(["a"])], replaced[collections.CompoundKey(["a"])], "", ]
def check_and_replace(flat_config: dict, value: str) -> Optional[str]: match = INTERPOLATION_REGEX.search(value) if not match: return None # the matched_string includes "${}"; the matched_key is just the inner value matched_string = match.group(0) matched_key = match.group(1) # get the referenced key from the config value ref_key = collections.CompoundKey(matched_key.split(".")) # get the value corresponding to the referenced key ref_value = flat_config.get(ref_key, "") # The configuration's value was just a reference and nothing else if value == matched_string: return ref_value # The reference wasn't a valid reference, so to maintain consistency # with the rest of the config API, a missing reference returns an # empty string # The value could either have multiple references, or # be used to interpolate a larger string, such # as a database URI or API request header # Ex1) "postgresql+psycopg2://${username}:${password}@{host}:${port}/${dbname}" # Ex2) "Bearer ${api_token}" return value.replace(matched_string, str(ref_value), 1)
def load_environment_variables( env_var_prefix: str, ) -> Dict[collections.CompoundKey, Any]: flat_config = {} for env_var, env_var_value in os.environ.items(): if not env_var.startswith(env_var_prefix + "__"): continue # Strips the prefix off the environment variable env_var_option = env_var[len(env_var_prefix + "__") :] # Make sure the result has at least one delimited section # with a key if "__" not in env_var: continue # Env vars with escaped characters are interpreted as a # literal "\", which Python helpfuly escaped with a second "\". # This step makes sure that the escaped characters are properly # interpreted. value = cast(str, env_var_value.encode().decode("unicode_escape")) # Place the environment variable into the flat config # as the compound key config_option = collections.CompoundKey(env_var_option.lower().split("__")) flat_config[config_option] = string_to_type( cast(str, interpolate_env_vars(value)) ) return flat_config
def test_replaces_multiple_existing_variables(self): config = { collections.CompoundKey(["a"]): "${b}", collections.CompoundKey(["b"]): "foo", collections.CompoundKey(["c"]): "bar", collections.CompoundKey(["d"]): "${c}", } replaced = replace_variable_references(config) assert (replaced[collections.CompoundKey( ["a"])] == replaced[collections.CompoundKey(["b"])]) assert (replaced[collections.CompoundKey( ["c"])] == replaced[collections.CompoundKey(["d"])])
def test_single_key_multiple_variables(self): same_values = "${b}-${b}" different_values = "${b}-${c}" config = { collections.CompoundKey(["a"]): same_values, collections.CompoundKey(["d"]): different_values, collections.CompoundKey(["b"]): "foo", collections.CompoundKey(["c"]): "bar", } replaced = replace_variable_references(config) assert replaced[collections.CompoundKey( ["a"])] == "{val}-{val}".format( val=replaced[collections.CompoundKey(["b"])]) assert replaced[collections.CompoundKey(["d"])] == "{b}-{c}".format( b=replaced[collections.CompoundKey(["b"])], c=replaced[collections.CompoundKey(["c"])], )
def test_bad_reference_returns_empty_string(self): config = { collections.CompoundKey(["a"]): "${b}", collections.CompoundKey(["c"]): "bar", collections.CompoundKey(["d"]): "${c}", } replaced = replace_variable_references(config) assert replaced[collections.CompoundKey(["a"])] == "" # not modifying the other, valid entries assert replaced[collections.CompoundKey(["c"])] == "bar" assert (replaced[collections.CompoundKey( ["d"])] == replaced[collections.CompoundKey(["c"])])
def test_flatten_dict(nested_dict): flat = collections.dict_to_flatdict(nested_dict) assert flat == { collections.CompoundKey([1]): 2, collections.CompoundKey([2, 1]): 2, collections.CompoundKey([2, 3]): 4, collections.CompoundKey([3, 1]): 2, collections.CompoundKey([3, 3, 4]): 5, collections.CompoundKey([3, 3, 6, 7]): 8, }
def test_variable_reference_from_array(self): config = { collections.CompoundKey(["a"]): "foo", collections.CompoundKey(["b"]): ["${a}", "${a}", "${a}"], } replaced = replace_variable_references(config) assert replaced[collections.CompoundKey(["b"])] == [ replaced[collections.CompoundKey(["a"])], replaced[collections.CompoundKey(["a"])], replaced[collections.CompoundKey(["a"])], ]
def test_self_reference_doesnt_cause_recursion_error(self): config = { collections.CompoundKey(["a"]): "${a}", } replaced = replace_variable_references(config) assert config == replaced