diff --git a/README.md b/README.md index dc359ff..0cc599c 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ When a schema is defined, the validator will also check if values are missing an ### Validator -The validator is the core of the package. It is used to validate a TOML file. A schema is optionally passed to the validator, and handlers are added using the `add_handler` method. Once you feel ready, you can call the `validate` method to get a dictionary of errors. +The validator is the core of the package. It is used to validate a TOML file. A schema is optionally passed to the validator, and handlers are added using the `add_handler` method. Once you feel ready, you can call the `validate` method with the data you want to validate as an argument to get a dictionary of errors. Currently, there are two type of error structures, for type errors and all other errors. @@ -133,7 +133,7 @@ structure = { schema = TOMLSchema(structure) # If the struture is invalid, a TOMLSchemaError is raised # Define validator -validator = TOMLValidator(data, schema) +validator = TOMLValidator(schema) # Add handlers validator.add_handler("*_name", lambda key: None if key in ["first_name", "last_name"] else "invalid-key") @@ -141,7 +141,7 @@ validator.add_handler("age", lambda value: None if 18 < value < 100 else "invali validator.add_handler("*", lambda: "invalid-key") # Validate the data -errors = validator.validate() +errors = validator.validate(data) ``` ## Future Plans diff --git a/tomlval/toml_validator.py b/tomlval/toml_validator.py index c62a171..ab2e0f2 100644 --- a/tomlval/toml_validator.py +++ b/tomlval/toml_validator.py @@ -19,34 +19,27 @@ class TOMLValidator: """Class to validate TOML data.""" - def __init__(self, data: dict, schema: TOMLSchema = None): + def __init__(self, schema: TOMLSchema = None): """ Initialize the TOML validator. Args: - data: dict - The TOML data to validate. - schema: dict - The TOML schema to validate against. + schema: TOMLSchema - The TOML schema to validate against. Returns: None Raises: - TypeError - If data is not a dictionary or - schema is not a TOMLSchema. + TypeError - If the schema is not a TOMLSchema. """ - # Data - if not isinstance(data, dict): - raise TypeError("Data must be a dictionary.") - # Schema if schema is not None: if not isinstance(schema, TOMLSchema): raise TypeError("Schema must be a TOMLSchema.") - self._data = flatten(data) self._schema = schema self._handlers = {} - def _map_handlers(self) -> dict[str, Handler]: + def _map_handlers(self, data: dict) -> dict[str, Handler]: """A method to map each key to a handler.""" def _match_key(key: str) -> Handler: @@ -75,7 +68,7 @@ def _match_key(key: str) -> Handler: return matched_handler - return {k: _match_key(k) for k in flatten(self._data)} + return {k: _match_key(k) for k in data} def _inspect_function(self, fn: Callable) -> List[str]: """ @@ -93,20 +86,17 @@ def _inspect_function(self, fn: Callable) -> List[str]: return list(inspect.signature(fn).parameters.keys()) - def _get_missing_keys(self) -> list[str]: + def _get_missing_keys(self, data: dict) -> list[str]: """Get a list of keys missing in the data.""" - # return [k for k in self._schema if k not in self._data] if not isinstance(self._schema, TOMLSchema): return [] return [ - k - for k in self._schema - if k not in self._data and not k.endswith("?") + k for k in self._schema if k not in data and not k.endswith("?") ] def _get_invalid_types( - self, + self, data: dict ) -> dict[str, Tuple[str, Tuple[Any, TypeList, TypeList]]]: """Get a list of keys with invalid types.""" invalid_types = {} @@ -115,19 +105,19 @@ def _get_invalid_types( return invalid_types for k, h in self._schema.items(): - if k not in self._data: + if k not in data: continue # Built in type if isinstance(h, type): - value = self._data[k] + value = data[k] if not isinstance(value, h): invalid_types[k] = ("invalid-type", (value, h, type(value))) continue # List of build in types if isinstance(h, (list, tuple)): - _value = self._data[k] + _value = data[k] _type = type(_value) if not any(isinstance(_value, t) for t in h): @@ -137,24 +127,24 @@ def _get_invalid_types( return invalid_types - def _get_handler_results(self) -> dict[str, Any]: + def _get_handler_results(self, data: dict) -> dict[str, Any]: """Runs the handlers and gets the results.""" results = {} - for k, h in self._map_handlers().items(): + for k, h in self._map_handlers(data).items(): if h is None: continue # Built in type if isinstance(h, type): - value = self._data[k] + value = data[k] if not isinstance(value, h): results[k] = ("invalid-type", (value, h, type(value))) continue # List of build in types if isinstance(h, (list, tuple)): - _value = self._data[k] + _value = data[k] _type = type(_value) if not any(isinstance(_value, t) for t in h): @@ -172,9 +162,9 @@ def _get_handler_results(self) -> dict[str, Any]: if fn_args[0] == "key": results[k] = h(k) elif fn_args[0] == "value": - results[k] = h(self._data[k]) + results[k] = h(data[k]) elif len(fn_args) == 2: - results[k] = h(k, self._data[k]) + results[k] = h(k, data[k]) return results @@ -258,11 +248,25 @@ def add_handler(self, key: str, handler: Handler): else: raise TOMLHandlerError("Handler must accept 0, 1, or 2 arguments.") - def validate(self) -> ValidatedSchema: - """Validates the TOML data.""" - handler_results = self._get_handler_results() - missing_keys = self._get_missing_keys() - invalid_types = self._get_invalid_types() + def validate(self, data: dict) -> ValidatedSchema: + """ + Validates the TOML data. + + Args: + data: dict - The TOML data to validate. + Returns: + dict - The errors in the data. + Raises: + TypeError - If data is not a dictionary. + """ + if not isinstance(data, dict): + raise TypeError("Data must be a dictionary.") + + data = flatten(data) + + handler_results = self._get_handler_results(data) + missing_keys = self._get_missing_keys(data) + invalid_types = self._get_invalid_types(data) errors = { **{k: ("missing", None) for k in missing_keys}, @@ -278,8 +282,8 @@ def validate(self) -> ValidatedSchema: if __name__ == "__main__": - val = TOMLValidator({"a_1_b": "1"}) + val = TOMLValidator() # val.add_handler("a_*_b", int) val.add_handler("a_*_b", (int, float)) - print(val.validate()) + print(val.validate({"a_1_b": "1"}))