5.4. Combining Pydantic and semver¶
According to its homepage, Pydantic “enforces type hints at runtime, and provides user friendly errors when data is invalid.”
If you are working with Pydantic>2.0 and pydantic-extra-types>=2.10.5 use the built in SemanticVersion type, which wraps the Version class.
from pydantic import BaseModel from pydantic_extra_types.semantic_version import SemanticVersion class appVersion(BaseModel): version: SemanticVersion app_version = appVersion(version="1.2.3") print(app_version.version) # > 1.2.3
To work with Pydantic>2.0 and without pydantic-extra-types use the following example to define your own type:
Derive a new class from
Versionfirst and add the magic methods__get_pydantic_core_schema__()and__get_pydantic_json_schema__()like this:from typing import Annotated, Any, Callable from pydantic import GetJsonSchemaHandler from pydantic_core import core_schema from pydantic.json_schema import JsonSchemaValue from semver import Version class _VersionPydanticAnnotation: @classmethod def __get_pydantic_core_schema__( cls, _source_type: Any, _handler: Callable[[Any], core_schema.CoreSchema], ) -> core_schema.CoreSchema: def validate_from_str(value: str) -> Version: return Version.parse(value) from_str_schema = core_schema.chain_schema( [ core_schema.str_schema(), core_schema.no_info_plain_validator_function(validate_from_str), ] ) return core_schema.json_or_python_schema( json_schema=from_str_schema, python_schema=core_schema.union_schema( [ core_schema.is_instance_schema(Version), from_str_schema, ] ), serialization = core_schema.to_string_ser_schema(), ) @classmethod def __get_pydantic_json_schema__( cls, _core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler ) -> JsonSchemaValue: return handler(core_schema.str_schema()) ManifestVersion = Annotated[Version, _VersionPydanticAnnotation]
Create a new model (in this example
MyModel) and derive it frompydantic.BaseModel:import pydantic class MyModel(pydantic.BaseModel): version: _VersionPydanticAnnotation
Use your model like this:
model = MyModel.parse_obj({"version": "1.2.3"})
The attribute
model.versionwill be an instance ofVersion. If the version is invalid, the construction will raise apydantic_core.ValidationError.