Skip to content

Commit

Permalink
Validator no longer accepts the data as an initial parameter and inst…
Browse files Browse the repository at this point in the history
…ead is passed to the 'validate' method so the validator can be reused
  • Loading branch information
marcusfrdk committed Feb 4, 2025
1 parent 1a5f3d3 commit 02eb548
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 37 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -133,15 +133,15 @@ 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")
validator.add_handler("age", lambda value: None if 18 < value < 100 else "invalid-age")
validator.add_handler("*", lambda: "invalid-key")

# Validate the data
errors = validator.validate()
errors = validator.validate(data)
```

## Future Plans
Expand Down
72 changes: 38 additions & 34 deletions tomlval/toml_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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]:
"""
Expand All @@ -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 = {}
Expand All @@ -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):
Expand All @@ -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):
Expand All @@ -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

Expand Down Expand Up @@ -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},
Expand All @@ -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"}))

0 comments on commit 02eb548

Please sign in to comment.