https://github.com/marcusfrdk/tomlval
A flexible, easy-to-use, and dependency-free Python library for validating TOML data against custom schemas.
https://github.com/marcusfrdk/tomlval
python schema toml validation
Last synced: 6 months ago
JSON representation
A flexible, easy-to-use, and dependency-free Python library for validating TOML data against custom schemas.
- Host: GitHub
- URL: https://github.com/marcusfrdk/tomlval
- Owner: marcusfrdk
- License: mit
- Created: 2025-02-04T11:04:04.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-07-27T01:47:25.000Z (12 months ago)
- Last Synced: 2025-08-27T21:41:10.926Z (11 months ago)
- Topics: python, schema, toml, validation
- Language: Python
- Homepage: https://pypi.org/project/tomlval/
- Size: 204 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# TOML Validator









A package used for validating TOML data against a schema and manually added handlers. It is designed to be flexible and easy to use, allowing you to customize the validation process to fit your needs.
## Installation
You can install the package from [PyPI](https://pypi.org/project/tomlval/):
```bash
pip install tomlval
```
The package is available for Python 3.11 and newer.
## Concepts
### Handlers
A handler is a validation function used by the validator to validate the value of a key. Handlers can be defined in a [schema](docs/SCHEMA.md) or added directly to the [validator](docs/VALIDATOR.md) using the `add_handler(key, fn) method.
You can read more about handlers in the [handler documentation](docs/HANDLER.md).
### Schema
A schema is a collection of keys and their associated handlers. It is defined as a dictionary where the keys are specific- or wildcard keys and the values are the functions ([handlers](docs/HANDLER.md)).
You can read more about schemas in the [schema documentation](docs/SCHEMA.md).
### Validator
The validator is the object that performs the actual validation on the data. It uses the optionally defined schema alongside manually added [handlers](docs/HANDLER.md) to validate the data and returns a dictionary of errors.
You can read more about the validator in the [validator documentation](docs/VALIDATOR.md).
## Examples
```python
from tomlval import TOMLSchema, TOMLValidator
# Define a schema
schema = TOMLSchema({
"name": str,
"age": int,
})
# Sample TOML data
data = {
"name": "Alice",
"age": 30,
}
# Create a validator
validator = TOMLValidator(schema=schema)
# Validate the data
errors = validator.validate(data)
```
```python
from tomlval import TOMLSchema, TOMLValidator
# Define a schema
schema = TOMLSchema({
"email?": str, # Optional email
"username": lambda value: "invalid-username" if len(value) < 3 else None, # Custom handler
})
# Sample TOML data
data = {
"username": "ab",
}
# Create a validator
validator = TOMLValidator(schema=schema)
# Validate the data
errors = validator.validate(data)
print(errors)
```
```python
import re
from datetime import datetime
from tomlval import TOMLSchema, TOMLValidator
# Regex patterns
username_pattern = re.compile(r"^[a-zA-Z0-9_]+$")
email_pattern = re.compile(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")
# Sample TOML data
data = {
"first_name": "John",
"last_name": "Doe",
"age": 25,
"email": "john.doe@example.com",
"username": "john_doe",
"birthday": datetime(1999, 1, 1),
"is_active": True,
"scores": [85, 92, 78],
"preferences": {
"theme": "dark",
"notifications": True,
"language": "en"
},
"social_profiles": [
{"platform": "twitter", "handle": "@johndoe"},
{"platform": "github", "handle": "johndoe"}
],
"work_history": [
{
"company": "TechCorp",
"position": "Developer",
"skills": [{"name": "Python", "level": 8}, {"name": "JavaScript", "level": 7}]
}
],
"metadata": {
"created_at": datetime.now(),
"tags": ["user", "premium"]
}
}
# Define a schema
schema = TOMLSchema({
# Basic type validation
"first_name": str,
"age": (int, float), # Multiple types
"birthday": datetime,
"is_active": bool,
# Optional keys
"middle_name?": str,
"phone?": str,
# Regex pattern validation
"username": username_pattern,
"email": email_pattern,
# Custom handlers
"last_name": lambda value: "too-short" if len(value) < 2 else None,
"age": lambda value: "invalid-age" if not (0 < value < 150) else None,
"email": lambda key: f"missing-{key}" if not key else None,
"username": lambda key, value: f"invalid-{key}" if len(value) < 3 else None,
# List validation
"scores": [int], # List of integers
"tags?": [str], # Optional List of strings
# Nested object validation
"preferences": {
"theme": str,
"notifications": bool,
"language?": str # Optional nested key
},
# List of objects
"social_profiles": [
{
"platform": str,
"handle": lambda value: "invalid-handle" if not value.startswith("@") else None
}
],
# Deeply nested list of objects
"work_history": [
{
"company": str,
"position": str,
"skills": [
{
"name": str,
"level": lambda value: "invalid-level" if not (1 <= value <= 10) else None
}
]
}
],
# Optional nested object
"metadata?": {
"created_at": datetime,
"tags": [str],
"version?": float
},
# Wildcard patterns
"*_name": str, # Matches first_name, last_name, etc.
"preferences.*": lambda: None, # Matches any key in preferences
"*_profiles": [dict], # Matches social_profiles, etc.
# Keys within lists
"scores[]": int, # Individual List elements
"work_history[].company": str, # Nested List element validation
"social_profiles[].platform": lambda value: "unsupported" if value not in ["twitter", "github", "linkedin"] else None,
# Optional List elements
"work_history[]?": dict, # Optional List elements
"preferences?.*": str, # Optional wildcard in optional object
# Catch-all handler
"*": lambda: "invalid-key"
})
# Custom callback functions
def on_missing_key(key: str) -> str:
return f"Missing key '{key}'"
def on_type_mismatch(key: str, expected, got) -> str:
return f"Key '{key}' expected {expected.__name__} but got {got.__name__}"
def on_pattern_mismatch(key: str, pattern) -> str:
return f"Key '{key}' does not match pattern {pattern.pattern}"
# Override default handlers
validator = TOMLValidator(
schema=schema,
on_missing=on_missing_key,
on_type_mismatch=on_type_mismatch,
on_pattern_mismatch=on_pattern_mismatch
)
# Manual handlers
validator.add_handler("some.key", lambda value: "custom-error" if value == "invalid" else None)
# Validate
errors = validator.validate(data)
```
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.