A lightweight extension of Pydantic's BaseModel that adds generic type introspection and retrieval of fields annotated with typing.Annotated.
Install with pip
pip install pydantic-super-model- Generic support
- Able to retrieve field(s) with a specific Annotation
from pydantic_super_model import SuperModel
class UserWithType[T](SuperModel):
"""User model with a generic type."""
id: T
name: str
user = UserWithType[int](id=1, name="John Doe")
user_type = user.get_type() # intfrom typing import Annotated
from pydantic_super_model import SuperModel
class _PrimaryKeyAnnotation:
pass
PrimaryKey = Annotated[int, _PrimaryKeyAnnotation]
class UserWithAnnotation(SuperModel):
"""User model with an Annotation for a field."""
id: PrimaryKey
name: str
user = UserWithAnnotation(id=1, name="John Doe")
annotations = user.get_annotated_fields(PrimaryKey)
# {"id": 1}SuperModel.get_annotated_fields(*annotations) returns a dict of field names to values for fields whose type hints carry any of the provided annotations (either the Annotated[...] alias or the meta annotation type).
It includes falsy values (like 0 or an empty string) and includes None only when the field was explicitly provided. Unset default None values are omitted.
from typing import Annotated
from pydantic_super_model import SuperModel
class _PrimaryKey:
pass
PrimaryKey = Annotated[int, _PrimaryKey]
class User(SuperModel):
id: PrimaryKey
name: str
u = User(id=1, name="Jane")
assert u.get_annotated_fields(PrimaryKey) == {"id": 1}Explicit None vs. unset default:
class UserOptional(SuperModel):
id: PrimaryKey | None = None
name: str
# Unset default None is omitted
assert not UserOptional(name="A").get_annotated_fields(PrimaryKey)
# Explicit None is included
assert UserOptional(id=None, name="B").get_annotated_fields(PrimaryKey) == {"id": None}You can use the FieldNotImplemented annotation to mark fields that should not be set. An example
use case are experimental fields that you intend on implementing later.
from typing import Annotated
from pydantic_super_model import SuperModel, FieldNotImplemented
class Experimental(SuperModel):
test_field: Annotated[int, FieldNotImplemented]
name: str
# Raises NotImplementedError because the field is provided
Experimental(test_field=1, name="x")
# Optional + unset default is allowed
class ExperimentalOptional(SuperModel):
test_field: Annotated[int | None, FieldNotImplemented] = None
name: str
ExperimentalOptional(name="ok") # ok (field is unset)Use get_type() to retrieve the concrete generic type parameter supplied at instantiation time.
from pydantic_super_model import SuperModel
class UserWithType[T](SuperModel):
id: T
name: str
u = UserWithType[int](id=1, name="Charlie")
assert u.get_type() is int- Install with the
devextra:pip install pydantic-super-model[dev] - Run tests with
pytest .