Metadata-Version: 2.1
Name: pydantic-partials
Version: 1.0.4
Summary: Pydantic partial model class, with ability to easily dynamically omit fields when serializing a model.
Home-page: https://github.com/joshorr/pydantic-partials
Author: Josh Orr
Author-email: josh@orr.blue
Requires-Python: >=3.10,<4.0
Classifier: License :: OSI Approved :: The Unlicense (Unlicense)
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Dist: pydantic (>=2.7.3,<3.0.0)
Requires-Dist: xsentinels (>=1.2.1,<2.0.0)
Project-URL: Repository, https://github.com/joshorr/pydantic-partials
Description-Content-Type: text/markdown

# Pydantic Partials

An easy way to add or create partials for Pydantic models.

![PythonSupport](https://img.shields.io/static/v1?label=python&message=%203.10|%203.11|%203.12&color=blue?style=flat-square&logo=python)
![PyPI version](https://badge.fury.io/py/xmodel.svg?)

## Documentation

**[📄 Detailed Documentation](https://joshorr.github.io/pydantic-partials/latest/)** | **[🐍 PyPi](https://pypi.org/project/pydantic-partials/)**

## Quick Start

```shell
poetry install pydantic-partials
```

or

```shell
pip install pydantic-partials
```

By default, all fields without a default value will have the ability to be partial,
and can be missing from both validation and serialization.

Very basic example is below:

```python
from pydantic_partials import PartialModel, Missing


class MyModel(PartialModel):
    some_attr: str
    another_field: str

# By default, Partial fields without any value will get set to a special `Missing` type.
# Any field that is set to Missing is excluded from the model_dump/model_dump_json
obj = MyModel()
assert obj.some_attr is Missing
assert obj.model_dump() == {}

# You can set the real value at any time, and it will behave like expected.
obj.some_attr = 'hello'
assert obj.some_attr is 'hello'
assert obj.model_dump() == {'some_attr': 'hello'}

# You can always manually set a field to `Missing` directly.
obj.some_attr = Missing

# And now it's removed from the model-dump.
assert obj.model_dump() == {}

# The json dump is also affected in the same way.
assert obj.model_dump_json() == '{}'

# Any non-missing fields will be included when dumping/serializing model.
obj.another_field = 'assigned-value'

# And now it's removed from the model-dump.
assert obj.model_dump() == {'another_field': 'assigned-value'}
```

You can turn off this default behavior by via `auto_partials` class argument or modeL_config option:

```python
from pydantic_partials import PartialModel, PartialConfigDict

class TestModel1(PartialModel, auto_partials=False):
    ...

class TestModel2(PartialModel):
    model_config = PartialConfigDict(auto_partials=False)
    ...
```

You can disable this automatic function. This means you have complete control of exactly which field 
can be partial or not.  You can use either the generic `Partial[...]` generic or a union with `MissingType`
to mark a field as a partial field.  The generic simple makes the union to MissingType for you.

Example of disabling auto_partials:

```python
from pydantic_partials import PartialModel, Missing, MissingType, Partial
from decimal import Decimal
from pydantic import ValidationError

class TestModel(PartialModel, auto_partials=False):
    # Can use `Partial` generic type
    partial_int: Partial[int] = Missing
    
    # Or union with `MissingType`
    partial_str: str | MissingType
    
    required_decimal: Decimal
    
try:
    TestModel()
except ValidationError as e:
    print(f'Pydantic will state `required_decimal` is required: {e}')
else:
    raise Exception('Pydantic should have required `required_decimal`.')
    
obj = TestModel(required_decimal='1.34')

# You can find out at any time if a field is missing or not:
assert obj.partial_int is Missing
assert obj.partial_str is Missing

assert obj.required_decimal == Decimal('1.34')
```



You can inherit from a model to make a partial-version of the inherited fields:

```python
from pydantic_partials import PartialModel, Missing
from pydantic import ValidationError, BaseModel


class TestModel(BaseModel):
    name: str
    value: str
    some_null_by_default_field: str | None = None


try:
    TestModel()
except ValidationError as e:
    print(f'Pydantic will state `name` + `value` are required: {e}')
else:
    raise Exception('Pydantic should have required `required_decimal`.')    

    
class PartialTestModel(PartialModel, TestModel):
    pass

    
obj = PartialTestModel(name='a-name')

assert obj.name == 'a-name'
assert obj.value is Missing
assert obj.some_null_by_default_field is None
```

Notice that if a field has a default value, it's used instead of marking it as `Missing`.

Also, the `Missing` sentinel value is a separate value vs `None`, allowing one to easily
know if a value is truly just missing or is `None`/`Null`.

