From 35815ce5aadd7601be05c05de9b346360924e653 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Fri, 10 Jan 2025 02:23:31 +0100 Subject: [PATCH] Optimized comments --- app/utils/configuration_resolver.py | 74 +++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/app/utils/configuration_resolver.py b/app/utils/configuration_resolver.py index 2b81c75..0e97abd 100644 --- a/app/utils/configuration_resolver.py +++ b/app/utils/configuration_resolver.py @@ -1,54 +1,87 @@ class ConfigurationResolver: def __init__(self, config): + """ + Initializes the ConfigurationResolver with a configuration dictionary. + + Args: + config (dict): The configuration to resolve links in. + """ self.config = config def resolve_links(self): """ - Resolves all `link` entries in the configuration. + Resolves all `link` entries in the configuration by replacing them with + the referenced configuration entry. """ self._recursive_resolve(self.config, self.config) def _recursive_resolve(self, current_config, root_config, path=""): """ - Recursively resolves `link` entries in the configuration. + Recursively traverses the configuration to resolve all `link` entries. + + Args: + current_config (dict or list): The current section of the configuration being processed. + root_config (dict): The root of the configuration to resolve links against. + path (str): The current path in the configuration for debugging purposes. """ if isinstance(current_config, dict): + # Traverse all key-value pairs in the dictionary for key, value in list(current_config.items()): if key == "link": + # Found a `link` entry, attempt to resolve it try: print(f"Resolving link '{value}' at path '{path}'") # Debugging target = self._find_entry(root_config, value.lower().replace(" ", "_")) + if isinstance(target, dict): + # Replace the current dictionary with the resolved dictionary current_config.clear() current_config.update(target) elif isinstance(target, str): + # Replace the `link` entry with the resolved string current_config[key] = target else: - raise ValueError(f"Expected a dictionary or string for link '{value}', got {type(target)}") + raise ValueError( + f"Expected a dictionary or string for link '{value}', got {type(target)}" + ) except KeyError as e: + # Handle unresolved links raise ValueError( - f"Key error while resolving link '{value}': {str(e)}. Current path: {key}, Current config: {current_config}" + f"Key error while resolving link '{value}': {str(e)}. " + f"Current path: {path}, Current config: {current_config}" ) else: + # Recursively resolve non-`link` entries self._recursive_resolve(value, root_config, path=f"{path}.{key}") + elif isinstance(current_config, list): + # Traverse all items in the list for index, item in enumerate(current_config): self._recursive_resolve(item, root_config, path=f"{path}[{index}]") def _find_entry(self, config, path): """ - Finds an entry in the configuration by a dot-separated path. - Supports both dictionaries and lists, but does not navigate into `subitems` - unless explicitly required by the path. + Finds an entry in the configuration by navigating a dot-separated path. + + Args: + config (dict or list): The configuration to search within. + path (str): The dot-separated path to the desired entry. + + Returns: + dict or str: The resolved entry. + + Raises: + KeyError: If the path cannot be resolved. + ValueError: If the resolved entry is not of the expected type. """ - parts = path.split('.') + parts = path.split('.') # Split the path into segments current = config for part in parts: - part = part.replace(" ", "_") # Normalize the part name + part = part.replace(" ", "_") # Normalize part name if isinstance(current, list): - # Look for a matching entry in the list + # Search for a matching entry in a list found = next( ( item @@ -65,7 +98,7 @@ class ConfigurationResolver: current = found elif isinstance(current, dict): - # Look for a key match in the dictionary + # Search for a key match in a dictionary key = next((k for k in current if k.lower().replace(" ", "_") == part), None) if key is None: raise KeyError( @@ -75,27 +108,30 @@ class ConfigurationResolver: current = current[key] else: + # Invalid path segment raise ValueError( f"Invalid path segment '{part}'. Current type: {type(current)}. " f"Path so far: {' > '.join(parts[:parts.index(part)+1])}" ) - # Stop navigating into `subitems` if the path doesn't explicitly require it + # Stop navigating into `subitems` unless explicitly required by the path if isinstance(current, dict) and "subitems" in current and isinstance(current["subitems"], list): - if part == "subitems": - current = current["subitems"] - else: - break # Do not navigate further unless explicitly in the path + if part != "subitems": + break # Stop navigation if `subitems` is not explicitly in the path # Ensure the resolved target is a dictionary or string if not isinstance(current, (dict, str)): - raise ValueError(f"Expected a dictionary or string for path '{path}', got {type(current)}. Current value: {current}") + raise ValueError( + f"Expected a dictionary or string for path '{path}', got {type(current)}. Current value: {current}" + ) return current - def get_config(self): """ - Returns the resolved configuration. + Returns the fully resolved configuration. + + Returns: + dict: The resolved configuration. """ return self.config