# pydantic-strict-partial
[![PyPI version](https://badge.fury.io/py/pydantic-strict-partial.svg)](https://badge.fury.io/py/pydantic-strict-partial)
[![PyPI Supported Python Versions](https://img.shields.io/pypi/pyversions/pydantic-strict-partial.svg)](https://pypi.python.org/pypi/pydantic-strict-partial/)
[![CI](https://github.com/ADR-007/pydantic-strict-partial/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/ADR-007/pydantic-strict-partial/actions/workflows/ci.yaml)
![badge](https://raw.githubusercontent.com/ADR-007/pydantic-strict-partial/_xml_coverage_reports/data/main/./badge.svg)
## About
Create partial models based on the original Pydantic models.
This makes all the fields optional.
This **doesn't** make them nullable and **doesn't** disable validation.
The only thing it does is provide default values for those fields (`None` by default),
so you can use `model.model_dump(exclude_unset=True)` command to receive specified values only.
The most common use case is a `PATCH` request on **FastAPI** endpoints where you want to allow partial updates.
## Installation
`pydantic-strict-partial` compatible with Python 3.10+ and Pydantic 2.1+.
### Using pip
```bash
pip install pydantic-strict-partial
```
### Using poetry
```bash
poetry add pydantic-strict-partial
```
## Usage
```python
from typing import Annotated
from annotated_types import Ge
from pydantic import BaseModel
from pydantic_strict_partial import create_partial_model
class UserSchema(BaseModel):
name: str
nickname: str | None
age: Annotated[int, Ge(18)]
UserPartialUpdateSchema = create_partial_model(UserSchema)
assert UserPartialUpdateSchema(age=20).model_dump(exclude_unset=True) == {
'age': 20
}
UserPartialUpdateSchema(name=None) # raises ValidationError
UserPartialUpdateSchema(age=17) # raises ValidationError
```
There is also possible to specify a limited list of fields to be partial:
```python
UserPartialUpdateSchema = create_partial_model(UserSchema, 'name', 'nickname')
```
Or to make all fields partial except for the specified ones:
```python
UserPartialCreateSchema = create_partial_model(UserSchema, required_fields=['age'])
```
## Known limitations
#### MyPy: "is not valid as a type" error
You may be faced with `Variable "UserPartialUpdateSchema" is not valid as a type` error.
There is no good solution for that. But the next approach can be used as a workaround:
```py
class UserPartialUpdateSchema(create_partial_model(UserSchema)): # type: ignore[misc]
pass
```
## Alternatives
[pydantic-partial](https://github.com/team23/pydantic-partial) - it makes all fields nullable and disables all validators, which is not suitable for payload validation on `PATCH` endpoints.
Raw data
{
"_id": null,
"home_page": "https://github.com/ADR-007/pydantic-strict-partial",
"name": "pydantic-strict-partial",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": "pydantic, partial, fastapi",
"author": "Adrian Dankiv",
"author_email": "adr-007@ukr.net",
"download_url": "https://files.pythonhosted.org/packages/94/12/c74e192acaa2a019180803c7555bdd568d81e774d4dfe57be4b0fe2753e9/pydantic_strict_partial-0.6.1.tar.gz",
"platform": null,
"description": "# pydantic-strict-partial\n\n[![PyPI version](https://badge.fury.io/py/pydantic-strict-partial.svg)](https://badge.fury.io/py/pydantic-strict-partial)\n[![PyPI Supported Python Versions](https://img.shields.io/pypi/pyversions/pydantic-strict-partial.svg)](https://pypi.python.org/pypi/pydantic-strict-partial/)\n[![CI](https://github.com/ADR-007/pydantic-strict-partial/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/ADR-007/pydantic-strict-partial/actions/workflows/ci.yaml)\n![badge](https://raw.githubusercontent.com/ADR-007/pydantic-strict-partial/_xml_coverage_reports/data/main/./badge.svg)\n\n## About\n\nCreate partial models based on the original Pydantic models. \n\nThis makes all the fields optional. \nThis **doesn't** make them nullable and **doesn't** disable validation.\nThe only thing it does is provide default values for those fields (`None` by default), \nso you can use `model.model_dump(exclude_unset=True)` command to receive specified values only.\n\nThe most common use case is a `PATCH` request on **FastAPI** endpoints where you want to allow partial updates.\n\n## Installation\n\n`pydantic-strict-partial` compatible with Python 3.10+ and Pydantic 2.1+.\n\n### Using pip\n```bash\npip install pydantic-strict-partial\n```\n\n### Using poetry\n```bash\npoetry add pydantic-strict-partial\n```\n\n## Usage\n\n```python\nfrom typing import Annotated\n\nfrom annotated_types import Ge\nfrom pydantic import BaseModel\n\nfrom pydantic_strict_partial import create_partial_model\n\n\nclass UserSchema(BaseModel):\n name: str\n nickname: str | None\n age: Annotated[int, Ge(18)]\n\n\nUserPartialUpdateSchema = create_partial_model(UserSchema)\n\nassert UserPartialUpdateSchema(age=20).model_dump(exclude_unset=True) == {\n 'age': 20\n}\n\nUserPartialUpdateSchema(name=None) # raises ValidationError\nUserPartialUpdateSchema(age=17) # raises ValidationError\n\n```\n\nThere is also possible to specify a limited list of fields to be partial:\n\n```python\nUserPartialUpdateSchema = create_partial_model(UserSchema, 'name', 'nickname')\n```\n\nOr to make all fields partial except for the specified ones:\n\n```python\nUserPartialCreateSchema = create_partial_model(UserSchema, required_fields=['age'])\n```\n\n## Known limitations\n\n#### MyPy: \"is not valid as a type\" error\n\nYou may be faced with `Variable \"UserPartialUpdateSchema\" is not valid as a type` error.\nThere is no good solution for that. But the next approach can be used as a workaround: \n\n```py\nclass UserPartialUpdateSchema(create_partial_model(UserSchema)): # type: ignore[misc]\n pass\n```\n\n## Alternatives\n\n[pydantic-partial](https://github.com/team23/pydantic-partial) - it makes all fields nullable and disables all validators, which is not suitable for payload validation on `PATCH` endpoints.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Makes partial Pydantic models without making fields nullable.",
"version": "0.6.1",
"project_urls": {
"Homepage": "https://github.com/ADR-007/pydantic-strict-partial"
},
"split_keywords": [
"pydantic",
" partial",
" fastapi"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "c7c59af4783ba1d07f982a4571acddc34cb4151a5d88b03cba807919015877a4",
"md5": "d91295316f8c13846debd961f6828b9e",
"sha256": "57ad2f787cecdc5ed233dd31590badcb92aac0678103395a45bd32a2cadf9544"
},
"downloads": -1,
"filename": "pydantic_strict_partial-0.6.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d91295316f8c13846debd961f6828b9e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 4092,
"upload_time": "2024-12-10T01:15:00",
"upload_time_iso_8601": "2024-12-10T01:15:00.524317Z",
"url": "https://files.pythonhosted.org/packages/c7/c5/9af4783ba1d07f982a4571acddc34cb4151a5d88b03cba807919015877a4/pydantic_strict_partial-0.6.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9412c74e192acaa2a019180803c7555bdd568d81e774d4dfe57be4b0fe2753e9",
"md5": "f49022e2853ceafcd95aa56398001a4d",
"sha256": "22c41a460a76da281bc8e9473f93b8d9461b932bd3501a3d5901c02d11b9437c"
},
"downloads": -1,
"filename": "pydantic_strict_partial-0.6.1.tar.gz",
"has_sig": false,
"md5_digest": "f49022e2853ceafcd95aa56398001a4d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 5000,
"upload_time": "2024-12-10T01:15:01",
"upload_time_iso_8601": "2024-12-10T01:15:01.805843Z",
"url": "https://files.pythonhosted.org/packages/94/12/c74e192acaa2a019180803c7555bdd568d81e774d4dfe57be4b0fe2753e9/pydantic_strict_partial-0.6.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-10 01:15:01",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ADR-007",
"github_project": "pydantic-strict-partial",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pydantic-strict-partial"
}