Skip to main content

TOML Validator

top language code size last commit issues contributors PyPI License Downloads Monthly Downloads

A simple and easy to use TOML validator for Python.

Installation

You can install the package from PyPI:

pip install tomlval

The package is available for Python 3.11 and newer.

Usage

TLDR

import re
from datetime import datetime
from tomlval import TOMLSchema, TOMLValidator

# Regex pattern
username_pattern = re.compile(r"^[a-zA-Z0-9_]+$")

# Load data
data = {...}

# Define schema
schema = TOMLSchema({
    "*_name": str, # Wildcard key
    "last_name": lambda value: "invalid-last-name" if age <= 0 else None, # Specific key with custom handler
    "age": (int, float), # Multiple types
    "birthday": datetime, # Specific key with type handler
    "username": username_pattern, # Regex pattern
    "*": lambda: "invalid-key" # Catch-all handler
})

# Define validator
validator = TOMLValidator(schema)

# Validate data
errors = validator.validate(data)

Handlers

Handlers are the validation functions used to validate the value of keys in the input data.

Types

A handler must be one of type, Callable or re.Pattern. This means any object of type type or re.Pattern is valid, and and Callable, such as lambda functions as well as named functions are valid.

Parameters

The handler will dynamically be passed either the key and/or value argument based of what parameters are defined.

Examples of valid handlers are:

  • Types: str, int, ...
  • Objects: datetime.datetime, re.Pattern, ...
  • Anonymous functions: lambda: ..., lambda key: ..., lambda value: ..., lambda key, value: ...
  • Named functions: def my_fn(), def my_fn(key), def my_fn(value), def my_fn(key, value)

If a handler accepts any parameters which are not key or value, a TOMLHandlerError will be raised.

Return Types

A handler returns an error, meaning nullish values tell the validator that the test passes. The reason for this design is that the handler may return error messages or any value your program needs.

Schema

A schema is an optional structure used to add functionality to the validator, this includes validation for missing keys and default handlers.

Keys

Keys follow the TOML specification, meaning keys must be in either snake_case or SCREAMING_SNAKE_CASE. This project adds some special notation in the form of suffixing a key with ? to make it optional, adding [] to the end to make the key a nested array as well as wildcard regex pattern support. The importance of keys are based of specificity, so my.key would dominate both my.* and *.

This means the following keys are examples of valid keys:

  • name, user.name: Specific key
  • *_name, user.*, *name*, user.*.name: Wildcard keys
  • last_name?, user.name?, array?[].key: Optional keys
  • array[], array?[], array[].key: Nested arrays

All keys can be written in dot-notation, meaning a deeply nested object/array can be written in a simpler form. For example:

{
    "very": {
        "deeply": {
            "nested": {
                "object": {
                    "key": str
                }
            }
        }
    }
}

can be written as "very.deeply.nested.object.key": str. This notation also supports optionality and arrays. This would work by just suffixing the word with ? and if an array, suffix the ? with [].

Defining a Schema

In order to define a new schema, you can use the following code as reference:

from tomlval import TOMLSchema

def my_fn(key, value):
    return "some-error"

def default_handler() -> str:
    """ Default handler for all keys """
    return "invalid-key"

schema = TOMLSchema({
    "single_type": str,
    "multiple_types": (int, float),
    "single_handler": lambda: "error-message",
    "multiple_handlers": (lambda: "error-message", str, my_fn),
    "optional?": str
    "list_of_strings": [str],
    "nested_dictionary": {
        "key": str,
        ...
    },
    "nested_array": [
        {
            "key": str,
            ...
        },
        ...
    ],
})

Note: When a nested array includes dictionaries with different structures, they will be merged. If the merge fails, a TOMLSchemaMergeError will be raised.

Validator

The validator defines the blueprint for how data should be validated. This is defined in the optional schema, or handlers can be manually added using the add_handler(key, fn) method. Handlers, like keys, are prioritized based of the key priority.

Examples

Basic

This examples includes the most basic use case, where a default handler is defined manually:

from tomlval import TOMLValidator

validator = TOMLValidator()
validator.add_handler("*", lambda: "invalid-key")
With a Schema

This example includes a schema, assume the schema is populated with the structure and handlers you require.

from tomlval import TOMLValidator, TOMLSchema

schema = TOMLSchema({...})
validator = TOMLValidator(schema)
Customizing a Defined Schema

This example includes a case where you might have defined a shared schema somewhere in your code but you need to customize specific keys:

from tomlval import TOMLValidator
from .schema import schema

def validate_age(value):
    if value <= 0:
        return "value-to-low"
    return None

validator = TOMLValidator(schema)
validator.add_handler("user.age", validate_age)
Customizing The Default Callbacks

For some people, it might not be the best option to return an error message, and instead some other value might be preferred or you might want a more verbose error message. In this case, the on_missing and on_type_mismatch callbacks can be changed changed:

import re
from typing import Any
from tomlval import TOMLValidator
from .schema import schema

def on_missing(key: str):
    return f"'{key}' is missing"

def on_type_mismatch(key: str, expected: type, got: type):
    return f"The argument '{key}' expected type '{expected.__name__}', got '{got.__name__}'"

def on_pattern_mismatch(key: str, value: Any, pattern: re.Pattern):
    return f"The argument '{key}' with value '{value}' does not match the pattern '{pattern.pattern}'"

validator = TOMLValidator(
    schema,
    on_missing=on_missing,
    on_type_mismatch=on_type_mismatch,
    on_pattern_mismatch=on_pattern_mismatch
)

Validation

Now that you have defined your schema and validator, the validator is now ready to be used on TOML data.

In order to use the validator, the validate(data) method is used. It accepts any dictionary as an argument and outputs a flat dictionary of all keys in dot-notation with each key's respective error value.

Examples

Validate File

This example shows a use-case where a TOML file is validated.

import tomllib
from datetime import datetime
from pathlib import Path
from tomlval import TOMLSchema, TOMLValidator

# Read file
file_path = Path("example.toml")
with file_path.open("rb") as file:
    data = tomllib.load(file)

# Define schema
schema = TOMLSchema({
    "*_name": str,
    "age": lambda value: "invalid-age" if age <= 0 else None,
    "birthday": datetime,
    "*": lambda: "invalid-key"
})

# Define validator
validator = TOMLValidator(schema)

# Validate data
errors = validator.validate(data)
Validate Dictionary

Instead of loading a file, you might have pre-loaded TOML-data in the form of a dictionary.

import tomllib
from datetime import datetime
from pathlib import Path
from tomlval import TOMLSchema, TOMLValidator
from .data import data

# Define schema
schema = TOMLSchema({
    "*_name": str,
    "age": lambda value: "invalid-age" if age <= 0 else None,
    "birthday": datetime,
    "*": lambda: "invalid-key"
})

# Define validator
validator = TOMLValidator(schema)

# Validate data
errors = validator.validate(data)

License

This project is licensed under the MIT License - seea the LICENSE file for details.

Metadata

Release files for tomlval 1.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tomlval 1.1.5
File Size Uploaded Provenance
tomlval-1.1.5.tar.gz 20.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for tomlval 1.1.5
File Interpreter ABI Platform
tomlval-1.1.5-py3-none-any.whl Python 3 none any Details

Total release size: 41.6 kB

Release files / tomlval-1.1.5.tar.gz

Download URL tomlval-1.1.5.tar.gz
Size 20.9 kB
Tags Source
SHA-256 checksum
How to use checksums
5eb728a943d8be679aa1671b31dbc3884a13056e2ef548123327364ebe94f8e8
BLAKE2b-256 checksum
How to use checksums
51d63ae04bf372eecbf14a2edeb0556f5d676fa4a35d7c1837db08df1919f581
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.9

Release files / tomlval-1.1.5-py3-none-any.whl

Download URL tomlval-1.1.5-py3-none-any.whl
Size 20.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5fbb386cc4d7d70aa3d2c06f5059cfd3d5317b58a83187640e47bac0c4d5e02f
BLAKE2b-256 checksum
How to use checksums
8cd08035234bce5b6514bf6d32f052b6e62480fde49ef957fd57704df206722d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.9

Security for tomlval 1.1.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page