{"id":19921485,"url":"https://github.com/pyapp-kit/pydantic-compat","last_synced_at":"2025-05-03T06:31:24.941Z","repository":{"id":185312442,"uuid":"624075612","full_name":"pyapp-kit/pydantic-compat","owner":"pyapp-kit","description":"Compatibility layer for pydantic v1/v2","archived":false,"fork":false,"pushed_at":"2025-04-07T21:19:01.000Z","size":58,"stargazers_count":12,"open_issues_count":2,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-26T12:02:34.213Z","etag":null,"topics":["compatibility","pydantic","pydantic-v2"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pyapp-kit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2023-04-05T17:36:31.000Z","updated_at":"2025-01-13T10:11:47.000Z","dependencies_parsed_at":"2024-02-05T22:24:56.641Z","dependency_job_id":"51e9c8ae-eb89-4b1d-98b4-cdf47abac0ca","html_url":"https://github.com/pyapp-kit/pydantic-compat","commit_stats":null,"previous_names":["tlambert03/pydantic-compat"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyapp-kit%2Fpydantic-compat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyapp-kit%2Fpydantic-compat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyapp-kit%2Fpydantic-compat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyapp-kit%2Fpydantic-compat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pyapp-kit","download_url":"https://codeload.github.com/pyapp-kit/pydantic-compat/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252154738,"owners_count":21702983,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["compatibility","pydantic","pydantic-v2"],"created_at":"2024-11-12T22:07:44.584Z","updated_at":"2025-05-03T06:31:19.932Z","avatar_url":"https://github.com/pyapp-kit.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pydantic-compat\n\n[![GitHub](https://img.shields.io/github/license/pyapp-kit/pydantic-compat)\n](https://github.com/pyapp-kit/pydantic-compat/raw/main/LICENSE)\n[![PyPI](https://img.shields.io/pypi/v/pydantic-compat.svg?color=green)](https://pypi.org/project/pydantic-compat)\n[![Python Version](https://img.shields.io/pypi/pyversions/pydantic-compat.svg?color=green)](https://python.org)\n[![CI](https://github.com/pyapp-kit/pydantic-compat/actions/workflows/ci.yml/badge.svg)](https://github.com/pyapp-kit/pydantic-compat/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/pyapp-kit/pydantic-compat/branch/main/graph/badge.svg)](https://codecov.io/gh/pyapp-kit/pydantic-compat)\n\n## Motivation\n\nPydantic 2 was a major release that completely changed the pydantic API.\n\nFor applications, this is not a big deal, as they can pin to whatever version of\npydantic they need. But for libraries that want to exist in a broader\nenvironment, pinning to a specific version of pydantic is not always an option\n(as it limits the ability to co-exist with other libraries).\n\nThis package provides (unofficial) compatibility mixins and function adaptors for pydantic\nv1-v2 cross compatibility. It allows you to use either v1 or v2 API names,\nregardless of the pydantic version installed. (Prefer using v2 names when possible).\n\nTests are run on Pydantic v1.8 and up\n\nThe API conversion is not exhaustive, but suffices for many of the use cases\nI have come across. It is in use by the following libraries:\n\n- [ome-types](https://github.com/tlambert03/ome-types)\n- [psygnal](https://github.com/pyapp-kit/psygnal)\n- [app-model](https://github.com/pyapp-kit/app-model)\n- [useq-schema](https://github.com/pymmcore-plus/useq-schema)\n\nFeel free to open an issue or PR if you find it useful, but lacking features\nyou need.\n\n## What does it do?\n\nNot much! :joy:\n\nMostly it serves to translate names from one API to another. It backports\nthe v2 API to v1 (so you can v2 names in a pydantic1 runtime),\nand forwards the v1 API to v2 (so you can use v1 names in a v2 runtime\nwithout deprecation warnings).\n\n\u003e While pydantic2 does offer deprecated access to the v1 API, if you explicitly\n\u003e wish to support pydantic1 without your users seeing deprecation warnings,\n\u003e then you need to do a lot of name adaptation depending on the runtime\n\u003e pydantic version. This package does that for you.\n\nIt does _not_ do any significantly complex translation of API logic.\nFor custom types, you will still likely need to add class methods to\nsupport both versions of pydantic.\n\nIt also does not prevent you from needing to know a what's changing\nunder the hood in pydantic 2. You should be running tests on both\nversions of pydantic to ensure your library works as expected. This\nlibrary just makes it much easier to support both versions in a single\ncodebase without a lot of ugly conditionals and boilerplate.\n\n## Usage\n\n```py\nfrom pydantic import BaseModel\nfrom pydantic_compat import PydanticCompatMixin\nfrom pydantic_compat import field_validator  # or 'validator'\nfrom pydantic_compat import model_validator  # or 'root_validator'\n\nclass MyModel(PydanticCompatMixin, BaseModel):\n    x: int\n    y: int = 2\n\n    # prefer v2 dict, but v1 class Config is supported\n    model_config = {'frozen': True}\n\n    @field_validator('x', mode='after')\n    def _check_x(cls, v):\n        if v != 42:\n            raise ValueError(\"That's not the answer!\")\n        return v\n\n    @model_validator('x', mode='after')\n    def _check_x(cls, v: MyModel):\n        # ...\n        return v\n```\n\nYou can now use the following attributes and methods regardless of the\npydantic version installed (without deprecation warnings):\n\n| v1 name                     | v2 name                     |\n| --------------------------- | --------------------------- |\n| `obj.dict()`                | `obj.model_dump()`          |\n| `obj.json()`                | `obj.model_dump_json()`     |\n| `obj.copy()`                | `obj.model_copy()`          |\n| `Model.construct`           | `Model.model_construct`     |\n| `Model.schema`              | `Model.model_json_schema`   |\n| `Model.validate`            | `Model.model_validate`      |\n| `Model.parse_obj`           | `Model.model_validate`      |\n| `Model.parse_raw`           | `Model.model_validate_json` |\n| `Model.update_forward_refs` | `Model.model_rebuild`       |\n| `Model.__fields__`          | `Model.model_fields`        |\n| `Model.__fields_set__`      | `Model.model_fields_set`    |\n\n\n## `Field` notes\n\n- `pydantic_compat.Field` will remove outdated fields (`const`) and translate\n  fields with new names:\n  | v1 name          | v2 name             |\n  | ---------------- | ------------------- |\n  | `min_items`      | `min_length`        |\n  | `max_items`      | `max_length`        |\n  | `regex`          | `pattern`           |\n  | `allow_mutation` | `not frozen`        |\n  | `\u003cextra_key\u003e`       | `json_schema_extra['\u003cextra_key\u003e']` |\n- Don't use `var = Field(..., const='val')`, use `var: Literal['val'] = 'val'`\n  it works in both v1 and v2\n- No attempt is made to convert between v1's `unique_items` and v2's `Set[]`\n  semantics. See \u003chttps://github.com/pydantic/pydantic-core/issues/296\u003e for\n  discussion.\n\n## API rules\n\n- both V1 and V2 names may be used (regardless of pydantic version), but\n  usage of V2 names are strongly recommended.\n- But the API must match the pydantic version matching the name you are using.\n  For example, if you are using `pydantic_compat.field_validator` then the\n  signature must match the pydantic (v2) `field_validator` signature (regardless)\n  of the pydantic version installed. Similarly, if you choose to use\n  `pydantic_compat.validator` then the signature must match the pydantic\n  (v1) `validator` signature.\n\n## Notable differences\n\n- `BaseModel.__fields__` in v1 is a dict of `{'field_name' -\u003e ModelField}`\n  whereas in v2 `BaseModel.model_fields` is a dict of `{'field_name' -\u003e\nFieldInfo}`. `FieldInfo` is a much simpler object that ModelField, so it is\n  difficult to directly support complicated v1 usage of `__fields__`.\n  `pydantic-compat` simply provides a name addaptor that lets you access many of\n  the attributes you may have accessed on `ModelField` in v1 while operating in\n  a v2 world, but `ModelField` methods will not be made available. You'll need\n  to update your usage accordingly.\n\n- in V2, `pydantic.model_validator(..., mode='after')` passes a model _instance_\n  to the validator function, whereas `pydantic.v1.root_validator(...,\npre=False)` passes a dict of `{'field_name' -\u003e validated_value}` to the\n  validator function. In pydantic-compat, both decorators follow the semantics\n  of their corresponding pydantic versions, _but_ `root_validator` gains\n  parameter `construct_object: bool=False` that matches the `model_validator`\n  behavior (only when `mode=='after'`). If you want that behavior though, prefer\n  using `model_validator` directly.\n\n## TODO:\n\n- Serialization decorators\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpyapp-kit%2Fpydantic-compat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpyapp-kit%2Fpydantic-compat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpyapp-kit%2Fpydantic-compat/lists"}