Source code for hammurabi.rules.mixins

from typing import Any, Dict, List, Union


[docs]class SelectorMixin: # pylint: disable=too-few-public-methods """ This mixin contains the helper function to get a value from dict by a css selector like selector path. (``.example.path.to.key``) """ @staticmethod def __normalize_key_path(key_path: Union[str, List[str]]) -> List[str]: """ Normalize the key_path and make sure we return the list representation of it. :param key_path: Path to the key in a selector format (``.path.to.the.key`` or ``["path", "to", "the", "key"]``) :type key_path: Union[str, List[str]] :return: List representation of key type :rtype: List[str] """ if isinstance(key_path, str): key_path = key_path.split(".") return list(filter(lambda key: key, key_path))
[docs] def get_by_selector( self, data: Any, key_path: Union[str, List[str]] ) -> Dict[str, Any]: """ Get a key's value by a selector and traverse the path. :param data: The loaded YAML data into dict :type data: :class:`hammurabi.rules.mixins.Any` :param key_path: Path to the key in a selector format (``.path.to.the.key`` or ``["path", "to", "the", "key"]``) :type key_path: Union[str, List[str]] :return: Return the value belonging to the selector :rtype: :class:`hammurabi.rules.mixins.Any` """ if not data: return dict() key_path = self.__normalize_key_path(key_path) entry = data or dict() for item in key_path: entry = entry.get(item, None) if not entry: return dict() return entry
[docs] def set_by_selector( self, loaded_data: Any, key_path: Union[str, List[str]], value: Union[None, list, dict, str, int, float], delete: bool = False, ) -> Any: """ Set a value by the key selector and traverse the path. :param loaded_data: The loaded YAML data into dict :type loaded_data: :class:`hammurabi.rules.mixins.Any` :param key_path: Path to the key in a selector format (``.path.to.the.key`` or ``["path", "to", "the", "key"]``) :type key_path: Union[str, List[str]] :param value: The value set for the key :type value: Union[None, list, dict, str, int, float] :param delete: Indicate if the key should be deleted :type delete: bool :return: The modified YAML data :rtype: :class:`hammurabi.rules.mixins.Any` """ key_path = self.__normalize_key_path(key_path) data: Dict[str, Any] = loaded_data or dict() entry = data for item in key_path[:-1]: current = entry.get(item) if current and not isinstance(current, dict): entry[item] = {} entry = entry.setdefault(item, {}) if not delete: entry[key_path[-1]] = value return data