Coverage for src/config_utils.py: 100%
21 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-16 04:41 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-16 04:41 +0000
1"""Configuration utility functions for reusable config operations.
3This module provides low-level utilities for configuration traversal and retrieval,
4separated from business logic to follow Single Responsibility Principle.
5"""
7__author__ = "Mandar Patil (mandarons@pm.me)"
9from typing import Any
12def config_path_to_string(config_path: list[str]) -> str:
13 """Build config path as string for display purposes.
15 Args:
16 config_path: List of config keys forming a path (e.g., ["app", "credentials", "username"])
18 Returns:
19 String representation of the config path (e.g., "app > credentials > username")
20 """
21 return " > ".join(config_path)
24def traverse_config_path(config: dict, config_path: list[str]) -> bool:
25 """Traverse and validate existence of a config path.
27 Recursively checks if a path exists in the configuration dictionary.
28 Does not retrieve values, only validates path existence.
30 Args:
31 config: Configuration dictionary to traverse
32 config_path: List of keys forming the path to check
34 Returns:
35 True if path exists and is valid, False otherwise
36 """
37 if len(config_path) == 0:
38 return True
39 if not (config and config_path[0] in config):
40 return False
41 return traverse_config_path(config[config_path[0]], config_path=config_path[1:])
44def get_config_value(config: dict, config_path: list[str]) -> Any:
45 """Retrieve value from config using a path.
47 Recursively navigates the configuration dictionary to retrieve a value.
48 Should only be called after validating path existence with traverse_config_path().
50 Args:
51 config: Configuration dictionary
52 config_path: List of keys forming the path to the value
54 Returns:
55 The configuration value at the specified path
57 Raises:
58 KeyError: If the path doesn't exist (should be prevented by prior validation)
59 """
60 if len(config_path) == 1:
61 return config[config_path[0]]
62 return get_config_value(config=config[config_path[0]], config_path=config_path[1:])
65def get_config_value_or_none(config: dict, config_path: list[str]) -> Any | None:
66 """Safely retrieve config value or return None if path doesn't exist.
68 Combines path validation and value retrieval for cases where None is acceptable.
70 Args:
71 config: Configuration dictionary
72 config_path: List of keys forming the path to the value
74 Returns:
75 The configuration value if path exists, None otherwise
76 """
77 if not traverse_config_path(config=config, config_path=config_path):
78 return None
79 return get_config_value(config=config, config_path=config_path)
82def get_config_value_or_default(config: dict, config_path: list[str], default: Any) -> Any:
83 """Retrieve config value or return default if path doesn't exist.
85 Args:
86 config: Configuration dictionary
87 config_path: List of keys forming the path to the value
88 default: Default value to return if path doesn't exist
90 Returns:
91 The configuration value if path exists, default otherwise
92 """
93 value = get_config_value_or_none(config=config, config_path=config_path)
94 return value if value is not None else default