This is a small helper library that adds some YAML capabilities to pydantic, namely dumping to yaml via the yaml_model.yaml()
function, and parsing from strings/files using YamlModel.parse_raw()
and YamlModel.parse_file()
. It also adds Enum
subclasses that get dumped to YAML as strings or integers, and fixes dumping of some typical types.
Documentation on ReadTheDocs.org
Typical usage is seen below. See the pydantic docs for more usage examples.
from pydantic import BaseModel, validator
from pydantic_yaml import YamlStrEnum, YamlModel
class MyEnum(YamlStrEnum):
"""This is a custom enumeration that is YAML-safe."""
a = "a"
b = "b"
class InnerModel(BaseModel):
"""This is a normal pydantic model that can be used as an inner class."""
fld: float = 1.0
class MyModel(YamlModel):
"""This is our custom class, with a `.yaml()` method.
The `parse_raw()` and `parse_file()` methods are also updated to be able to
handle `content_type='application/yaml'`, `protocol="yaml"` and file names
ending with `.yml`/`.yaml`
"""
x: int = 1
e: MyEnum = MyEnum.a
m: InnerModel = InnerModel()
@validator('x')
def _chk_x(cls, v: int) -> int: # noqa
"""You can add your normal pydantic validators, like this one."""
assert v > 0
return v
m1 = MyModel(x=2, e="b", m=InnerModel(fld=1.5))
# This dumps to YAML and JSON respectively
yml = m1.yaml()
jsn = m1.json()
m2 = MyModel.parse_raw(yml) # This automatically assumes YAML
assert m1 == m2
m3 = MyModel.parse_raw(jsn) # This will fallback to JSON
assert m1 == m3
m4 = MyModel.parse_raw(yml, proto="yaml")
assert m1 == m4
m5 = MyModel.parse_raw(yml, content_type="application/yaml")
assert m1 == m5
pip install pydantic_yaml
Make sure to install ruamel.yaml
or pyyaml
as well. These are optional dependencies:
pip install pydantic_yaml[ruamel]
pip install pydantic_yaml[pyyaml]
Version 0.5.0 adds a YamlModelMixin
which can be used to add YAML functionality on
top of, or alongside, other base classes:
from typing import List
from pydantic import BaseModel
from pydantic_yaml import YamlModelMixin
class MyBase(BaseModel):
"""This is a normal."""
x: str = "x"
class ExtModel(YamlModelMixin, MyBase):
"""This model can be sent to/read from YAML."""
y: List[int] = [1, 2, 3] # and you can define additional fields, if you want
Note that this YamlModelMixin
must be before any BaseModel
-derived classes.
This will hopefully be resolved in Pydantic 2.0
(see this discussion
for more details). If you know a better way of implementing this, please make raise
an issue or create a PR!
You can configure the function used to dump and load the YAML by using the Config
inner class, as in Pydantic:
class MyModel(YamlModel):
# ...
class Config:
# You can override these fields:
yaml_dumps = my_custom_dumper
yaml_loads = lambda x: MyModel()
# As well as other Pydantic configuration:
allow_mutation = False
Since YAML is often used for config files, there is also a SemVer
str-like class and VersionedYamlModel
base class.
The version
attribute is parsed according to the SemVer
(Semantic Versioning) specification.
It's constrained between the min_version
and max_version
specified by your models'
Config
inner class (similar to regular pydantic
models).
from pydantic import ValidationError
from pydantic_yaml import SemVer, VersionedYamlModel
class A(VersionedYamlModel):
"""Model with min, max constraints as None."""
foo: str = "bar"
class B(VersionedYamlModel):
"""Model with a maximum version set."""
foo: str = "bar"
class Config:
min_version = "2.0.0"
ex_yml = """
version: 1.0.0
foo: baz
"""
a = A.parse_raw(ex_yml)
assert a.version == SemVer("1.0.0")
assert a.foo == "baz"
try:
B.parse_raw(ex_yml)
except ValidationError as e:
print("Correctly got ValidationError:", e, sep="\n")