Skip to content

Commit feddfd4

Browse files
committed
docs: add documentation for FlatInitModel
1 parent 0313263 commit feddfd4

1 file changed

Lines changed: 60 additions & 22 deletions

File tree

README.md

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -112,38 +112,76 @@ model_instance_3 = curried_model_3(x="1", y=2)(z=("3", 4))
112112
print(model_instance_3)
113113
```
114114

115-
#### init_model_from_kwargs
115+
#### FlatInitModel
116116

117-
The `init_model_from_kwargs` constructor allows to initialize (potentially nested) models from (flat) kwargs.
117+
The `FlatInitModel` constructor allows to instantiate a potentially deeply nested Pydantic model from flat kwargs.
118118

119119
```python
120-
class SimpleModel(BaseModel):
121-
x: int
122-
y: int = 3
120+
from lupl import FlatInitModel
121+
from pydantic import BaseModel
123122

123+
class DeeplyNestedModel(BaseModel):
124+
z: int
124125

125126
class NestedModel(BaseModel):
126-
a: str
127-
b: SimpleModel
127+
y: int
128+
deeply_nested: DeeplyNestedModel
129+
130+
class Model(BaseModel):
131+
x: int
132+
nested: NestedModel
133+
134+
constructor = FlatInitModel(model=Model)
135+
136+
instance: Model = constructor(x=1, y=2, z=3)
137+
print(instance.model_dump()) # {'x': 1, 'nested': {'y': 2, 'deeply_nested': {'z': 3}}}
138+
```
139+
140+
141+
`FlatInitModel` also handles model union types by processing the first model type of the union.
142+
143+
A common use case for model union types is e.g. to assign a default value to a model union typed field in case a nested model instance does not meet certain criteria, i.e. fails a predicate.
144+
145+
The `model_bool` parameter in `lupl.ConfigDict` allows to specify the condition for *model truthiness* - if the existential condition of a model is met, the model instance gets assigned to the model field, else the constructor falls back to the default value.
146+
147+
148+
The default condition for model truthiness is that *any* model field must be truthy for the model to be considered truthy.
128149

150+
The `model_bool` parameter takes either
129151

130-
class ComplexModel(BaseModel):
131-
p: str
132-
q: NestedModel
152+
- a callable object of arity 1 that receives the model instance at runtime,
153+
- a `str` denoting a field of the model that must be truthy in order for the model to be truthy
154+
- a `set[str]` denoting fields of the model, all of which must be truthy for the model to be truthy.
133155

134156

135-
# p='p value' q=NestedModel(a='a value', b=SimpleModel(x=1, y=2))
136-
model_instance_1 = init_model_from_kwargs(
137-
ComplexModel, x=1, y=2, a="a value", p="p value"
138-
)
157+
The following example defines the truth condition for `DeeplyNestedModel` to be `gt3`. `NestedModel` defines a model union type with a default value - if the `model_bool` predicate fails, the constructor falls back to the default:
139158

140-
# p='p value' q=NestedModel(a='a value', b=SimpleModel(x=1, y=3))
141-
model_instance_2 = init_model_from_kwargs(
142-
ComplexModel, p="p value", q=NestedModel(a="a value", b=SimpleModel(x=1))
143-
)
159+
```python
160+
from lupl import ConfigDict, FlatInitModel
161+
from pydantic import BaseModel
162+
163+
class DeeplyNestedModel(BaseModel):
164+
model_config = ConfigDict(model_bool=lambda model: model.z > 3)
144165

145-
# p='p value' q=NestedModel(a='a value', b=SimpleModel(x=1, y=3))
146-
model_instance_3 = init_model_from_kwargs(
147-
ComplexModel, p="p value", q=init_model_from_kwargs(NestedModel, a="a value", x=1)
148-
)
166+
z: int
167+
168+
class NestedModel(BaseModel):
169+
y: int
170+
deeply_nested: DeeplyNestedModel | str = "default"
171+
172+
class Model(BaseModel):
173+
x: int
174+
nested: NestedModel
175+
176+
constructor = FlatInitModel(model=Model)
177+
178+
instance: Model = constructor(x=1, y=2, z=3)
179+
instance.model_dump() # {'x': 1, 'nested': {'y': 2, 'deeply_nested': 'default'}}
180+
```
181+
182+
If the existential condition of the model is met, the model instance gets assigned:
183+
184+
```python
185+
instance: Model = constructor(x=1, y=2, z=4)
186+
instance.model_dump() # {'x': 1, 'nested': {'y': 2, 'deeply_nested': {'z': 4}}}
149187
```

0 commit comments

Comments
 (0)