Name | tomlval JSON |
Version |
1.1.1
JSON |
| download |
home_page | None |
Summary | A simple and easy to use TOML validator for Python. |
upload_time | 2025-02-07 13:26:38 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.11 |
license | MIT License
Copyright (c) 2025 Marcus Fredriksson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
|
keywords |
toml
validator
validation
parser
python
|
VCS |
![](/static/img/github-24-000000.png) |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# TOML Validator
![top language](https://img.shields.io/github/languages/top/marcusfrdk/tomlval)
![code size](https://img.shields.io/github/languages/code-size/marcusfrdk/tomlval)
![last commit](https://img.shields.io/github/last-commit/marcusfrdk/tomlval)
![issues](https://img.shields.io/github/issues/marcusfrdk/tomlval)
![contributors](https://img.shields.io/github/contributors/marcusfrdk/tomlval)
![PyPI](https://img.shields.io/pypi/v/tomlval)
![License](https://img.shields.io/github/license/marcusfrdk/tomlval)
A simple and easy to use TOML validator for Python.
## 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.
## Usage
### 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`. This means any object of type `type` 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. No parameters are also okay.
Examples of valid handlers are:
- **Types:** `str`, `int`, `datetime.datetime`, ...
- **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 for keys.
#### 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 an array and 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:
```py
{
"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:
```py
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:
```py
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.
```py
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:
```py
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 even a more verbose error message. In this case, the `on_missing` and `on_type_mismatch` callbacks are changed:
```py
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__}'"
validator = TOMLValidator(
schema,
on_missing=on_missing,
on_type_mismatch=on_type_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.
```py
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.
```py
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](LICENSE) file for details.
Raw data
{
"_id": null,
"home_page": null,
"name": "tomlval",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "toml, validator, validation, parser, python",
"author": null,
"author_email": "Marcus Fredriksson <marcus@marcusfredriksson.com>",
"download_url": "https://files.pythonhosted.org/packages/e2/e1/eacbb89e5e1a6ceaadb5ac009c4825f839fb6e87b2b61efce808c1cc9bd0/tomlval-1.1.1.tar.gz",
"platform": null,
"description": "# TOML Validator\n\n![top language](https://img.shields.io/github/languages/top/marcusfrdk/tomlval)\n![code size](https://img.shields.io/github/languages/code-size/marcusfrdk/tomlval)\n![last commit](https://img.shields.io/github/last-commit/marcusfrdk/tomlval)\n![issues](https://img.shields.io/github/issues/marcusfrdk/tomlval)\n![contributors](https://img.shields.io/github/contributors/marcusfrdk/tomlval)\n![PyPI](https://img.shields.io/pypi/v/tomlval)\n![License](https://img.shields.io/github/license/marcusfrdk/tomlval)\n\nA simple and easy to use TOML validator for Python.\n\n## Installation\n\nYou can install the package from [PyPI](https://pypi.org/project/tomlval/):\n\n```bash\npip install tomlval\n```\n\nThe package is available for Python 3.11 and newer.\n\n## Usage\n\n### Handlers\n\nHandlers are the validation functions used to validate the value of keys in the input data.\n\n#### Types\n\nA handler must be one of `type`, `Callable`. This means any object of type `type` is valid, and and `Callable`, such as `lambda` functions as well as named functions are valid.\n\n#### Parameters\n\nThe handler will dynamically be passed either the `key` and/or `value` argument based of what parameters are defined. No parameters are also okay.\n\nExamples of valid handlers are:\n\n- **Types:** `str`, `int`, `datetime.datetime`, ...\n- **Anonymous functions:** `lambda: ...`, `lambda key: ...`, `lambda value: ...`, `lambda key, value: ...`\n- **Named functions:** `def my_fn()`, `def my_fn(key)`, `def my_fn(value)`, `def my_fn(key, value)`\n\nIf a handler accepts any parameters which are not `key` or `value`, a `TOMLHandlerError` will be raised.\n\n#### Return Types\n\nA 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.\n\n### Schema\n\nA schema is an _optional_ structure used to add functionality to the validator, this includes validation for missing keys and default handlers for keys.\n\n#### Keys\n\nKeys 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 an array and wildcard regex pattern support. The importance of keys are based of specificity, so `my.key` would dominate both `my.*` and `*`.\n\nThis means the following keys are examples of valid keys:\n\n- `name`, `user.name`: Specific key\n- `*_name`, `user.*`, `*name*`, `user.*.name`: Wildcard keys\n- `last_name?`, `user.name?`, `array?[].key`: Optional keys\n- `array[]`, `array?[]`, `array[].key`: Nested arrays\n\nAll keys can be written in dot-notation, meaning a deeply nested object/array can be written in a simpler form. For example:\n\n```py\n{\n \"very\": {\n \"deeply\": {\n \"nested\": {\n \"object\": {\n \"key\": str\n }\n }\n }\n }\n}\n```\n\ncan 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 `[]`.\n\n#### Defining a Schema\n\nIn order to define a new schema, you can use the following code as reference:\n\n```py\nfrom tomlval import TOMLSchema\n\ndef my_fn(key, value):\n return \"some-error\"\n\ndef default_handler() -> str:\n \"\"\" Default handler for all keys \"\"\"\n return \"invalid-key\"\n\nschema = TOMLSchema({\n \"single_type\": str,\n \"multiple_types\": (int, float),\n \"single_handler\": lambda: \"error-message\",\n \"multiple_handlers\": (lambda: \"error-message\", str, my_fn),\n \"optional?\": str\n \"list_of_strings\": [str],\n \"nested_dictionary\": {\n \"key\": str,\n ...\n },\n \"nested_array\": [\n {\n \"key\": str,\n ...\n },\n ...\n ],\n})\n```\n\n_Note: When a nested array includes dictionaries with different structures, they will be merged. If the merge fails, a `TOMLSchemaMergeError` will be raised._\n\n### Validator\n\nThe 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.\n\n#### Examples\n\n##### Basic\n\nThis examples includes the most basic use case, where a default handler is defined manually:\n\n```py\nfrom tomlval import TOMLValidator\n\nvalidator = TOMLValidator()\nvalidator.add_handler(\"*\", lambda: \"invalid-key\")\n```\n\n##### With a Schema\n\nThis example includes a schema, assume the schema is populated with the structure and handlers you require.\n\n```py\nfrom tomlval import TOMLValidator, TOMLSchema\n\nschema = TOMLSchema({...})\nvalidator = TOMLValidator(schema)\n```\n\n##### Customizing a Defined Schema\n\nThis example includes a case where you might have defined a _shared_ schema somewhere in your code but you need to customize specific keys:\n\n```py\nfrom tomlval import TOMLValidator\nfrom .schema import schema\n\ndef validate_age(value):\n if value <= 0:\n return \"value-to-low\"\n return None\n\nvalidator = TOMLValidator(schema)\nvalidator.add_handler(\"user.age\", validate_age)\n```\n\n##### Customizing The Default Callbacks\n\nFor some people, it might not be the best option to return an error message, and instead some other value might be preferred or even a more verbose error message. In this case, the `on_missing` and `on_type_mismatch` callbacks are changed:\n\n```py\nfrom tomlval import TOMLValidator\nfrom .schema import schema\n\ndef on_missing(key: str):\n return f\"'{key}' is missing\"\n\ndef on_type_mismatch(key: str, expected: type, got: type)\n return f\"The argument '{key}' expected type '{expected.__name__}', got '{got.__name__}'\"\n\nvalidator = TOMLValidator(\n schema,\n on_missing=on_missing,\n on_type_mismatch=on_type_mismatch\n)\n```\n\n### Validation\n\nNow that you have defined your schema and validator, the validator is now ready to be used on TOML data.\n\nIn 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.\n\n#### Examples\n\n##### Validate File\n\nThis example shows a use-case where a TOML file is validated.\n\n```py\nimport tomllib\nfrom datetime import datetime\nfrom pathlib import Path\nfrom tomlval import TOMLSchema, TOMLValidator\n\n# Read file\nfile_path = Path(\"example.toml\")\nwith file_path.open(\"rb\") as file:\n data = tomllib.load(file)\n\n# Define schema\nschema = TOMLSchema({\n \"*_name\": str,\n \"age\": lambda value: \"invalid-age\" if age <= 0 else None,\n \"birthday\": datetime,\n \"*\": lambda: \"invalid-key\"\n})\n\n# Define validator\nvalidator = TOMLValidator(schema)\n\n# Validate data\nerrors = validator.validate(data)\n```\n\n##### Validate Dictionary\n\nInstead of loading a file, you might have pre-loaded TOML-data in the form of a dictionary.\n\n```py\nimport tomllib\nfrom datetime import datetime\nfrom pathlib import Path\nfrom tomlval import TOMLSchema, TOMLValidator\nfrom .data import data\n\n# Define schema\nschema = TOMLSchema({\n \"*_name\": str,\n \"age\": lambda value: \"invalid-age\" if age <= 0 else None,\n \"birthday\": datetime,\n \"*\": lambda: \"invalid-key\"\n})\n\n# Define validator\nvalidator = TOMLValidator(schema)\n\n# Validate data\nerrors = validator.validate(data)\n```\n\n## License\n\nThis project is licensed under the MIT License - seea the [LICENSE](LICENSE) file for details.\n",
"bugtrack_url": null,
"license": "MIT License\n \n Copyright (c) 2025 Marcus Fredriksson\n \n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n \n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n \n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n ",
"summary": "A simple and easy to use TOML validator for Python.",
"version": "1.1.1",
"project_urls": {
"Homepage": "https://github.com/marcusfrdk/tomlval",
"Issues": "https://github.com/marcusfrdk/tomlval/issues",
"Repository": "https://github.com/marcusfrdk/tomlval"
},
"split_keywords": [
"toml",
" validator",
" validation",
" parser",
" python"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "7019a2d810288e862f48e23e5fb9da1e6eda7da997f3b615a01ee6de727be91b",
"md5": "044b85a5f4315da4ef65b3f8ae206c5e",
"sha256": "721e24fd76d0f15bab24c444805b377a9f4d82f87b8b70df5a6aa87fb60cedf5"
},
"downloads": -1,
"filename": "tomlval-1.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "044b85a5f4315da4ef65b3f8ae206c5e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 19834,
"upload_time": "2025-02-07T13:26:37",
"upload_time_iso_8601": "2025-02-07T13:26:37.730510Z",
"url": "https://files.pythonhosted.org/packages/70/19/a2d810288e862f48e23e5fb9da1e6eda7da997f3b615a01ee6de727be91b/tomlval-1.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "e2e1eacbb89e5e1a6ceaadb5ac009c4825f839fb6e87b2b61efce808c1cc9bd0",
"md5": "503fceb4a83773b2e5d66f2541e0cab1",
"sha256": "36bc075afde61fbff4a3df1388586bc533ef860ca2ffcc62a7cca489170e62b7"
},
"downloads": -1,
"filename": "tomlval-1.1.1.tar.gz",
"has_sig": false,
"md5_digest": "503fceb4a83773b2e5d66f2541e0cab1",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 19972,
"upload_time": "2025-02-07T13:26:38",
"upload_time_iso_8601": "2025-02-07T13:26:38.804845Z",
"url": "https://files.pythonhosted.org/packages/e2/e1/eacbb89e5e1a6ceaadb5ac009c4825f839fb6e87b2b61efce808c1cc9bd0/tomlval-1.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-02-07 13:26:38",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "marcusfrdk",
"github_project": "tomlval",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "tomlval"
}