def _target(path: List[Any], dictionary: Dict[str, Any]) -> Any: """Target a value following the path 'self.path' inside the dictionary. :Example: path = ["a", 0, "b"] obj = {"a": [{"b": 1}]} assert DictRule(path).target(obj) == 1 # True :param path: The tpath to target inside the dictionary. :type path: List[Any] :param dictionary: The targeting dictionary. :type dictionary: Dict[str, Any] :raises (TypeError, ValueError, KeyError): if the path doesn't exist. :return: The value of the path. :rtype: Any """ if not path: return dictionary current = dictionary for key in path: try: current = current[key] except KeyError as error: path = " -> ".join(path) raise CertumException( f"The path '{path}' doesn't exist") from error return current
def _using(*args, validator: "DictValidator") -> "DictValidator": """Setup strategies to use by the validator. These strategies can be provided using :class:`certum.strategy.abstract.Strategy` or lists of :class:`certum.strategy.abstract.Strategy`. :raises CertumException: If the argument provided is not a available strategy. :return: Itself. :rtype: DictValidator """ def setup_strategy(validator, strategy) -> "DictValidator": if isinstance(strategy, SortingStrategy): validator.sorting = strategy elif isinstance(strategy, FilteringStrategy): validator.filtering = strategy elif isinstance(strategy, PrintingStrategy): validator.printing = strategy else: raise CertumException( "The strategy provided for the validator is unknown.") return validator for arg in args: if isinstance(arg, list): for strategy in arg: validator = setup_strategy(validator, strategy) elif isinstance(arg, Strategy): validator = setup_strategy(validator, arg) else: raise CertumException( "The strategy provided for the validator is unknown.") return validator
def setup_strategy(validator, strategy) -> "DictValidator": if isinstance(strategy, SortingStrategy): validator.sorting = strategy elif isinstance(strategy, FilteringStrategy): validator.filtering = strategy elif isinstance(strategy, PrintingStrategy): validator.printing = strategy else: raise CertumException( "The strategy provided for the validator is unknown.") return validator
def ensure(dictionary: Dict[str, Any]) -> DictValidator: """Entry point to analyse a dictionary object and ensure that is respects certain rules generate from the "that" function. :param dictionary: The dictionary to analyse. :type dictionary: Dict[str, Any] :return: The validator instance. :rtype: DictValidator """ if not isinstance(dictionary, dict): raise CertumException("DictValidator need a dictionary of type dict.") return DictValidator(dictionary)
def args_to_rule_decipher(*args) -> List[DictRule]: """Decipher that figures out what are the type of arguments and try to convert them as a list of DictRule. :raises CertumException: if one argument is not a DictRule complient argument. :return: The list of dictionary rules. :rtype: List[DictRule] """ rules = [] for arg in args: if isinstance(arg, list): for rule in arg: if not isinstance(rule, DictRule): raise CertumException(f"{rule} is not a dictionary rule") rules.append(rule) elif not isinstance(arg, DictRule): raise CertumException(f"{arg} is not a dictionary rule") else: rules.append(arg) return rules
def forsome(self, *args, **kwargs) -> DictRuleForsome: """Check if the current path respect a list of rules for elements corresponding to some keys. .. note:: Forsome needs a parameter 'keys' that contains the keys to analyse. :return: The DictRule related with this rule. :rtype: DictRuleForsome """ try: keys = kwargs["keys"] if not isinstance(keys, list): raise CertumException("Forsome needs a 'keys' argument of type list") except KeyError as error: raise CertumException( "Forsome needs a 'keys' argument of type list" ) from error rules = args_to_rule_decipher(*args) return DictRuleForsome(self.path, keys, rules)
def on( # pylint: disable=C0103 self, dictionary: Dict[str, Any]) -> "DictValidator": """Attribute a new dictionary to analyse by the validator. :param dictionary: The dictionary to analyse. :type dictionary: Dict[str, Any] :return: Itself. :rtype: DictValidator """ if not isinstance(dictionary, dict): raise CertumException( "DictValidator need a dictionary of type dict.") return DictValidator(dictionary, self.rules, self.sorting, self.filtering, self.printing)
def check(self): """Check all provided rules and throw an error if at least one of them is not respected. :param sorting: The sorting strategy used to sort errors, defaults to NoSorting() :type sorting: SortingStrategy, optional :param filtering: The sorting strategy used to sort errors, defaults to NoSorting() :type filtering: FilteringStrategy, optional :param printing: The filtering strategy used to filter errors, defaults to NoFiltering() :type printing: FilteringStrategy, optional :raises CertumException: if at least one rule is not respected. """ errors = [ err for rule in self.rules for err in rule.check(self.dictionary) ] errors = list(set(errors)) errors = self.sorting.sort(errors) errors = self.filtering.filter(errors) if errors: raise CertumException(f"\n\n{self.printing.print(errors)}")