# modelity
Data parsing and validation library for Python.
## About
Modelity is a data parsing and validation library, written purely in Python,
and based on the idea that data parsing and validation should be separated from
each other, but being a part of single toolkit for ease of use.
In Modelity, **data parsing** is executed **automatically** once data model is
**instantiated or modified**, while model **validation** needs to be explicitly
called by the user. Thanks to this approach, models can be feed with data
progressively (f.e. in response to user’s input), while still being able to
validate at any time.
## Features
* Declare models using type annotations
* Uses slots, not descriptors, making reading from a model as fast as possible
* Clean separation between **data parsing** stage (executed when model is
created or modified) and **model validation** stage (executed on demand)
* Clean differentiation between unset fields (via special `Unset` sentinel) and
optional fields set to `None`
* Easily customizable via pre- and postprocessors (executed during data
parsing), model-level validators, and field-level validators (both executed
during model validation)
* Ability do access any field via **root model** (the one for each validation is
executed) from any custom validator, allowing to implement complex
cross-field validation logic
* Ability to add custom **validation context** for even more complex validation
strategies (like having different validators when model is created, when
model is updated or when model is fetched over the API).
* Use of predefined error codes instead of error messages for easier
customization of error reporting (if needed)
* Ease of providing custom types simply by defining
`__modelity_type_descriptor__` static method in user-defined type.
## Rationale
Why I have created this library?
First reason is that I didn’t find such clean separation in known data parsing
tools, and found myself needing such freedom in several projects - both
private, and commercial ones. Separation between parsing and validation steps
simplifies validators, as validators in models can assume that they are called
when model is instantiated, therefore they can access all model’s fields
without any extra checks.
Second reason is that I often found myself writing validation logic from the
scratch for various reasons, especially for large models with lots of
dependencies. Each time I had to validate some complex logic manually I was
asking myself, why don’t merge all these ideas and make a library that already
has these kind of helpers? For example, I sometimes needed to access parent
model when validating field that itself is another, nested model. With
Modelity, it is easy, as root model (the one that is validated) is
populated to all nested models' validators recursively.
Third reason is that I wanted to finish my over 10 years old, abandoned project
Formify (the name is already in use, so I have chosen new name for new project)
which I was developing in free time at the beginning of my professional work
during learning of Python. That project was originally made to handle form
parsing and validation to be used along with web framework. Although the
project was never finished, I’ve resurrected some ideas from it, especially
parsing and validation separation. You can still find source code on my GH
profile.
And last, but not least… I made this project for fun with a hope that maybe
someone will find it useful :-)
## Example
Here's an example data model created with Modelity:
```python
import datetime
import typing
from modelity.model import Model
class Address(Model):
address_line1: str
address_line2: typing.Optional[str]
city: str
state_province: typing.Optional[str]
postal_code: str
country_code: str
class Person(Model):
name: str
second_name: typing.Optional[str]
surname: str
dob: datetime.date
```
## Documentation
Please visit project's ReadTheDocs site: https://modelity.readthedocs.io/en/latest/.
## License
This project is released under the terms of the MIT license.
## Author
Maciej Wiatrzyk <maciej.wiatrzyk@gmail.com>
Raw data
{
"_id": null,
"home_page": "https://github.com/mwiatrzyk/modelity",
"name": "modelity",
"maintainer": null,
"docs_url": null,
"requires_python": "<4,>=3.9",
"maintainer_email": null,
"keywords": "parsing, validation, modelling, parser, validator, model, library, toolkit",
"author": "Maciej Wiatrzyk",
"author_email": "maciej.wiatrzyk@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/c7/5d/230d6bb4e37e7cc31c0cddaa7fe220ebc0683f9ea119171ba925505570e4/modelity-0.18.0.tar.gz",
"platform": null,
"description": "# modelity\n\nData parsing and validation library for Python.\n\n## About\n\nModelity is a data parsing and validation library, written purely in Python,\nand based on the idea that data parsing and validation should be separated from\neach other, but being a part of single toolkit for ease of use.\n\nIn Modelity, **data parsing** is executed **automatically** once data model is\n**instantiated or modified**, while model **validation** needs to be explicitly\ncalled by the user. Thanks to this approach, models can be feed with data\nprogressively (f.e. in response to user\u2019s input), while still being able to\nvalidate at any time.\n\n## Features\n\n* Declare models using type annotations\n* Uses slots, not descriptors, making reading from a model as fast as possible\n* Clean separation between **data parsing** stage (executed when model is\n created or modified) and **model validation** stage (executed on demand)\n* Clean differentiation between unset fields (via special `Unset` sentinel) and\n optional fields set to `None`\n* Easily customizable via pre- and postprocessors (executed during data\n parsing), model-level validators, and field-level validators (both executed\n during model validation)\n* Ability do access any field via **root model** (the one for each validation is\n executed) from any custom validator, allowing to implement complex\n cross-field validation logic\n* Ability to add custom **validation context** for even more complex validation\n strategies (like having different validators when model is created, when\n model is updated or when model is fetched over the API).\n* Use of predefined error codes instead of error messages for easier\n customization of error reporting (if needed)\n* Ease of providing custom types simply by defining\n `__modelity_type_descriptor__` static method in user-defined type.\n\n## Rationale\n\nWhy I have created this library?\n\nFirst reason is that I didn\u2019t find such clean separation in known data parsing\ntools, and found myself needing such freedom in several projects - both\nprivate, and commercial ones. Separation between parsing and validation steps\nsimplifies validators, as validators in models can assume that they are called\nwhen model is instantiated, therefore they can access all model\u2019s fields\nwithout any extra checks.\n\nSecond reason is that I often found myself writing validation logic from the\nscratch for various reasons, especially for large models with lots of\ndependencies. Each time I had to validate some complex logic manually I was\nasking myself, why don\u2019t merge all these ideas and make a library that already\nhas these kind of helpers? For example, I sometimes needed to access parent\nmodel when validating field that itself is another, nested model. With\nModelity, it is easy, as root model (the one that is validated) is\npopulated to all nested models' validators recursively.\n\nThird reason is that I wanted to finish my over 10 years old, abandoned project\nFormify (the name is already in use, so I have chosen new name for new project)\nwhich I was developing in free time at the beginning of my professional work\nduring learning of Python. That project was originally made to handle form\nparsing and validation to be used along with web framework. Although the\nproject was never finished, I\u2019ve resurrected some ideas from it, especially\nparsing and validation separation. You can still find source code on my GH\nprofile.\n\nAnd last, but not least\u2026 I made this project for fun with a hope that maybe\nsomeone will find it useful :-)\n\n## Example\n\nHere's an example data model created with Modelity:\n\n```python\nimport datetime\nimport typing\n\nfrom modelity.model import Model\n\nclass Address(Model):\n address_line1: str\n address_line2: typing.Optional[str]\n city: str\n state_province: typing.Optional[str]\n postal_code: str\n country_code: str\n\nclass Person(Model):\n name: str\n second_name: typing.Optional[str]\n surname: str\n dob: datetime.date\n```\n\n## Documentation\n\nPlease visit project's ReadTheDocs site: https://modelity.readthedocs.io/en/latest/.\n\n## License\n\nThis project is released under the terms of the MIT license.\n\n## Author\n\nMaciej Wiatrzyk <maciej.wiatrzyk@gmail.com>\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Data parsing and validation library for Python",
"version": "0.18.0",
"project_urls": {
"Homepage": "https://github.com/mwiatrzyk/modelity",
"Repository": "https://github.com/mwiatrzyk/modelity"
},
"split_keywords": [
"parsing",
" validation",
" modelling",
" parser",
" validator",
" model",
" library",
" toolkit"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d8192a14282416c855fc3ff4f46eeebabdae0dbd9681668137219436c5e22433",
"md5": "fe58c370df531ca590e20625770b7139",
"sha256": "e9400d88cb659245c32492d1d7ccb591fede2e89a208990f616b88e8bac3a9a8"
},
"downloads": -1,
"filename": "modelity-0.18.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "fe58c370df531ca590e20625770b7139",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4,>=3.9",
"size": 36723,
"upload_time": "2025-07-28T20:26:52",
"upload_time_iso_8601": "2025-07-28T20:26:52.124959Z",
"url": "https://files.pythonhosted.org/packages/d8/19/2a14282416c855fc3ff4f46eeebabdae0dbd9681668137219436c5e22433/modelity-0.18.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "c75d230d6bb4e37e7cc31c0cddaa7fe220ebc0683f9ea119171ba925505570e4",
"md5": "0a4a7351176e3d602205de016aeba480",
"sha256": "9928c62a72caf992f4d7672dd09ce82c73c89cfac947964ff7cf86696df47c2a"
},
"downloads": -1,
"filename": "modelity-0.18.0.tar.gz",
"has_sig": false,
"md5_digest": "0a4a7351176e3d602205de016aeba480",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4,>=3.9",
"size": 28750,
"upload_time": "2025-07-28T20:26:53",
"upload_time_iso_8601": "2025-07-28T20:26:53.278367Z",
"url": "https://files.pythonhosted.org/packages/c7/5d/230d6bb4e37e7cc31c0cddaa7fe220ebc0683f9ea119171ba925505570e4/modelity-0.18.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-28 20:26:53",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mwiatrzyk",
"github_project": "modelity",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"circle": true,
"lcname": "modelity"
}