Skip to content

Commit 3189ac7

Browse files
authored
Merge pull request #2 from joshorr/josho/adjust-docs
Josho/adjust docs
2 parents 8e0a357 + a0eb544 commit 3189ac7

File tree

7 files changed

+115
-33
lines changed

7 files changed

+115
-33
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Custom Ones
22

33
/scripts
4-
4+
/api
55

66
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
77
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

README.md

Lines changed: 85 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,110 @@
22

33
Provides easy way to map dict to/from Full-Fledged 'JsonModel' object.
44

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

88
## Documentation
99

10-
**[📄 Detailed Documentation](https://xyngular.github.io/py-xmodel/latest/)** | **[🐍 PyPi](https://pypi.org/project/xmodel/)**
11-
12-
## Getting Started
13-
14-
???+ warning "Alpha Software!"
15-
This is pre-release Alpha software, based on another code base and
16-
the needed changes to make a final release version are not yet
17-
completed. Everything is subject to change!
10+
**[📄 Detailed Documentation](https://joshorr.github.io/pydantic-partials/latest/)** | **[🐍 PyPi](https://pypi.org/project/pydantic-partials/)**
1811

12+
## Quick Start
1913

2014
```shell
21-
poetry install xmodel
15+
poetry install pydantic-partials
2216
```
2317

2418
or
2519

2620
```shell
27-
pip install xmodel
21+
pip install pydantic-partials
2822
```
2923

30-
Very basic example:
24+
By default, all fields without a default value will have the ability to be partial,
25+
and can be missing from both validation and serialization.
26+
27+
Very basic example is below:
3128

3229
```python
33-
from xmodel import JsonModel
30+
from pydantic_partials import PartialModel, Missing, Partial
3431

35-
class MyModel(JsonModel):
32+
33+
class MyModel(PartialModel):
3634
some_attr: str
3735

38-
json_dict_input = {'some_attr': 'a-value'}
3936

40-
obj = MyModel(json_dict_input)
41-
assert obj.some_attr == 'a-value'
37+
# By default, Partial fields without any value will get set to a special `Missing` type.
38+
# Any field that is set to Missing is excluded from the model_dump/model_dump_json
39+
obj = MyModel()
40+
assert obj.some_attr is Missing
41+
assert obj.model_dump() == {}
42+
43+
# You can set the real value at any time, and it will behave like expected.
44+
obj.some_attr = 'hello'
45+
assert obj.some_attr is 'hello'
46+
assert obj.model_dump() == {'some_attr': 'hello'}
47+
48+
# You can always manually set a field to `Missing` directly.
49+
obj.some_attr = Missing
50+
51+
# And now it's removed from the model-dump.
52+
assert obj.model_dump() == {}
53+
54+
# The json dump is also affected in the same way.
55+
assert obj.model_dump_json() == '{}'
56+
```
57+
58+
59+
You can turn off this default behavior by via `auto_partials` class argument or modeL_config option:
60+
61+
```python
62+
from pydantic_partials import PartialModel, PartialConfigDict
63+
64+
class TestModel1(PartialModel, auto_partials=False):
65+
...
66+
67+
class TestModel2(PartialModel):
68+
model_config = PartialConfigDict(auto_partials=False)
69+
...
70+
71+
```
72+
73+
You can disable this automatic function. This means you have complete control of exactly which field
74+
can be partial or not. You can use either the generic `Partial[...]` generic or a union with `MissingType`
75+
to mark a field as a partial field. The generic simple makes the union to MissingType for you.
76+
77+
Example of disabling auto_partials:
78+
79+
```python
80+
from pydantic_partials import PartialModel, Missing, MissingType, Partial, PartialConfigDict
81+
from decimal import Decimal
82+
from pydantic import ValidationError
83+
84+
class TestModel(PartialModel, auto_partials=False):
85+
# Can use `Partial` generic type
86+
partial_int: Partial[int] = Missing
87+
88+
# Or union with `MissingType`
89+
partial_str: str | MissingType
90+
91+
required_decimal: Decimal
92+
93+
try:
94+
TestModel()
95+
except ValidationError as e:
96+
print(f'Pydantic will state `required_decimal` is required: {e}')
97+
else:
98+
raise Exception('Pydantic should have required `required_decimal`.')
99+
100+
obj = TestModel(required_decimal='1.34')
101+
102+
# You can find out at any time if a field is missing or not:
103+
assert obj.partial_int is Missing
104+
assert obj.partial_str is Missing
105+
106+
assert obj.required_decimal == Decimal('1.34')
42107

43-
json_dict = obj.api.json()
44-
assert json_dict == json_dict_input
45108
```
109+
110+
111+

pydantic_partials/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class PartialConfigDict(ConfigDict):
99
"""
1010
Defaults to `True`.
1111
12-
If `True` (default): When class is created, all required attributes will be made `Partial`,
12+
- If `True` (default): When class is created, all required attributes will be made `Partial`,
1313
and their default set to `Missing`. This means that all attributes that don't have any
1414
default or default_factory defined will automatically have `MissingType`/`LazyType` added
1515
to their annotation and field default set to `Missing`/`Lazy`.
@@ -19,7 +19,7 @@ class PartialConfigDict(ConfigDict):
1919
This allows Pydantic to create an instance of the model without a value defined
2020
for partial fields.
2121
22-
If `False`: Class won't automatically add `Partial` fields.
22+
- If `False`: Class won't automatically add `Partial` fields.
2323
Instead adding them to individual fields will be up to the user.
2424
2525
The default value of any fields set by user to be `Partial` will still be adjusted

pydantic_partials/meta.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515

1616

1717
# metaclass to make all fields in a model optional, useful for PATCH requests
18-
class _PartialMeta(ModelMetaclass):
18+
class PartialMeta(ModelMetaclass):
19+
""" Metaclass of `pydantic_partials.partial.PartialModel`, used to support partial fields,
20+
including the ability ot automatically apply `pydantic_partials.partial.Partial`[...] to fields
21+
via `pydantic_partials.config.PartialConfigDict.auto_partials` configuration option.
22+
"""
1923
model_partial_fields: typing.ClassVar[set[str]]
2024
""" Set of strings representing field names that can be missing from validation/serialization.
2125
If they are missing, they will return the `Missing` sentinel value and the field will be entirely
@@ -53,7 +57,7 @@ def __new__(
5357
"""
5458
5559
Args:
56-
auto_partials: For more details see `pydantic_partials.config.PartialConfigDict.auto_partial`.
60+
auto_partials: For more details see `pydantic_partials.config.PartialConfigDict.auto_partials`.
5761
If `Default`: Inherit behavior from parent/model_config; otherwise defaults to `True`.
5862
If `True` (default): Will automatically make all fields on the model `Partial`.
5963
If `False`: User needs to mark individual fields as `Partial` where they want.

pydantic_partials/partial.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from pydantic import BaseModel, model_serializer, JsonValue
55

6-
from .meta import _PartialMeta
6+
from .meta import PartialMeta
77
from .sentinels import Missing, MissingType
88

99
from logging import getLogger
@@ -23,18 +23,25 @@ class PartialModel(
2323

2424
# Need metaclass to examine fields for missing type
2525
# and also to auto-add missing type if desired.
26-
metaclass=_PartialMeta,
26+
metaclass=PartialMeta,
2727

2828
# Needed so `Missing` default values will be validated and therefore the `PydanticOmit` will be
2929
# raised and inform Pydantic to ignore/omit the field value.
3030
validate_default=True
3131
):
32-
""" Class Args:
33-
auto_partial: For more details see `pydantic_partials.config.PartialConfigDict.auto_partial`.
34-
If `Default`: Inherit behavior from parent/model_config; otherwise defaults to `True`.
35-
If `True` (default): Will automatically make all fields on the model `Partial`.
36-
If `False`: User needs to mark individual fields as `Partial` where they want.
3732
"""
33+
Class Args:
34+
35+
- auto_partial: For more details see `pydantic_partials.config.PartialConfigDict.auto_partials`.
36+
- If `Default`: Inherit behavior from parent/model_config; otherwise defaults to `True`.
37+
- If `True` (default): Will automatically make all fields on the model `Partial`.
38+
- If `False`: User needs to mark individual fields as `Partial` where they want.
39+
"""
40+
41+
def __init__(self, *args, **kwargs):
42+
""" Pydantic partial model class, with ability to easily dynamically omit fields when serializing a model.
43+
"""
44+
super().__init__(*args, **kwargs)
3845

3946
if not typing.TYPE_CHECKING:
4047

pydantic_partials/sentinels.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66

77

88
class MissingType(Sentinel):
9-
# See (https://docs.pydantic.dev/latest/concepts/json_schema/#modifying-the-schema).
9+
""" Class/Type of `Missing`, a sentinel that is used to indicate if a field is missing its value
10+
in a `pydantic_partials.partial.PartialModel` subclass.
11+
"""
12+
# Notes/See (https://docs.pydantic.dev/latest/concepts/json_schema/#modifying-the-schema).
1013

1114
@classmethod
1215
def __get_pydantic_core_schema__(
@@ -41,6 +44,8 @@ def _serialize(value: Any) -> 'MissingType':
4144

4245

4346
Missing = MissingType()
47+
""" Returned as attribute value when attribute value is missing. Can also be set on attribute to indicate it's missing.
48+
"""
4449

4550
T = TypeVar('T')
4651

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tool.poetry]
22
name = "pydantic-partials"
33
version = "1.0.0"
4-
description = "Pydantic partial model class, with ability to easily dynamically omit fields when seralizing a model."
4+
description = "Pydantic partial model class, with ability to easily dynamically omit fields when serializing a model."
55

66
authors = ["Josh Orr <[email protected]>"]
77
packages = [{include = "pydantic_partials"}]

0 commit comments

Comments
 (0)