{"id":39909792,"url":"https://github.com/mwiatrzyk/modelity","last_synced_at":"2026-01-18T16:05:53.836Z","repository":{"id":258102129,"uuid":"854262451","full_name":"mwiatrzyk/modelity","owner":"mwiatrzyk","description":"Data parsing and validation library for Python","archived":false,"fork":false,"pushed_at":"2025-10-09T18:48:13.000Z","size":559,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-11T05:48:02.044Z","etag":null,"topics":["data","library","model","parsing","python","tool","validation"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mwiatrzyk.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-09-08T19:53:09.000Z","updated_at":"2025-10-09T18:48:16.000Z","dependencies_parsed_at":"2024-10-27T21:48:22.266Z","dependency_job_id":"092338b0-98ea-4398-b937-568f02eff8f9","html_url":"https://github.com/mwiatrzyk/modelity","commit_stats":null,"previous_names":["mwiatrzyk/modelity"],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/mwiatrzyk/modelity","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwiatrzyk%2Fmodelity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwiatrzyk%2Fmodelity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwiatrzyk%2Fmodelity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwiatrzyk%2Fmodelity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mwiatrzyk","download_url":"https://codeload.github.com/mwiatrzyk/modelity/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwiatrzyk%2Fmodelity/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28541068,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T14:59:57.589Z","status":"ssl_error","status_checked_at":"2026-01-18T14:59:46.540Z","response_time":98,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data","library","model","parsing","python","tool","validation"],"created_at":"2026-01-18T16:05:53.143Z","updated_at":"2026-01-18T16:05:53.828Z","avatar_url":"https://github.com/mwiatrzyk.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"![PyPI - Version](https://img.shields.io/pypi/v/modelity)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/modelity)\n![PyPI - License](https://img.shields.io/pypi/l/modelity)\n\n# 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’s input), while still being able to\nvalidate at any time (f.e. in reaction to button click).\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, or by\n  using `type_descriptor_factory` hook for registering 3rd party types.\n\n## Rationale\n\nWhy I have created this library?\n\nFirst reason is that I didn’t 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 successfully instantiated, with all fields parsed to their\nallowed types, therefore they can access all model’s fields without any extra\nchecks.\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’t 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\n**Formify** (the name is already in use, so I have chosen new name for new\nproject) which I was developing in free time at the beginning of my\nprofessional work as a Python developer. That project was originally made to\nhandle form parsing and validation to be used along with web framework.\nAlthough the project was never finished, I’ve resurrected some ideas from it,\nespecially parsing and validation separation. You can still find source code on\nmy GitHub profile: https://github.com/mwiatrzyk.\n\nAnd last but not least, I don’t intend to compete with any of the existing\nalternatives — and there are plenty of them. I simply created this project for\nfun and decided to release it once it became reasonably usable, hoping that\nmaybe someone else will find it helpful.😊\n\n## Example\n\nHere's a condensed example of how to use Modelity:\n\n```python\nimport json\nimport datetime\nimport typing\n\nfrom modelity.api import Model, ValidationError, ModelError, validate, dump, load\n\n# 1. Define models\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    address: Address\n\n\n# 2. Create instances (parsing runs automatically)\n\naddr = Address(\n    address_line1=\"221B Baker Street\",\n    address_line2=None,\n    city=\"London\",\n    state_province=None,\n    postal_code=\"NW1 6XE\",\n    country_code=\"GB\"\n)\n\nperson = Person(\n    name=\"Sherlock\",\n    second_name=None,\n    surname=\"Holmes\",\n    dob=datetime.date(1854, 1, 6),\n    address=addr\n)\n\n#: 3. Validate instances (on demand)\n\ntry:\n    validate(person)\nexcept ValidationError as e:\n    print(\"Model is not valid: \", e)\n    raise\n\n# 4. Dump to JSON-serializable dict\n\nperson_dict = dump(person)\nperson_json = json.dumps(person_dict)  # Dump to JSON; use any lib you like to do that\n\n# 5. Parse from dict\n\nperson_dict = json.loads(person_json)\ntry:\n    same_person = load(Person, person_dict)  # Parsing + validation made by helper\nexcept ModelError as e:  # Base for: ValidationError, ParsingError\n    print(\"Model parsing or validation failed: \", e)\n    raise\n\n# 6. Accessing fields (just like using normal dataclasses).\n\nprint(same_person.address.country_code)\n```\n\n## Documentation\n\nPlease visit project's ReadTheDocs site: https://modelity.readthedocs.io/en/latest/.\n\n## Disclaimer\n\n**Modelity** is an independent open-source project for the Python ecosystem. It\nis not affiliated with, sponsored by, or endorsed by any company, organization,\nor product of the same or similar name. Any similarity in names is purely\ncoincidental and does not imply any association.\n\n## License\n\nThis project is released under the terms of the MIT license.\n\n## Author\n\nMaciej Wiatrzyk \u003cmaciej.wiatrzyk@gmail.com\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmwiatrzyk%2Fmodelity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmwiatrzyk%2Fmodelity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmwiatrzyk%2Fmodelity/lists"}