erdantic.pydantic¶
Classes¶
PydanticField (Field)
¶
Concrete field adapter class for Pydantic fields.
Attributes:
Name | Type | Description |
---|---|---|
field |
pydantic.fields.ModelField |
The Pydantic field object that is associated with this adapter instance. |
Source code in erdantic/pydantic.py
class PydanticField(Field[pydantic.fields.FieldInfo]):
"""Concrete field adapter class for Pydantic fields.
Attributes:
field (pydantic.fields.ModelField): The Pydantic field object that is associated with this
adapter instance.
"""
def __init__(self, name: str, field_info: pydantic.fields.FieldInfo):
self._name = name
if not isinstance(field_info, pydantic.fields.FieldInfo):
raise InvalidFieldError(
f"field_info must be of type pydantic.fields.FieldInfo. Got: {type(field_info)}"
)
super().__init__(field=field_info)
@property
def name(self) -> str:
return self._name
@property
def type_obj(self) -> Union[type, GenericAlias]:
return self.field.annotation
def is_many(self) -> bool:
return is_many(self.type_obj)
def is_nullable(self) -> bool:
return is_nullable(self.type_obj)
Attributes¶
name: str
property
readonly
¶
Name of this field on the parent data model.
type_obj: Union[type, _GenericAlias]
property
readonly
¶
Python type object for this field.
Methods¶
__init__(self, name: str, field_info: FieldInfo)
special
¶
Source code in erdantic/pydantic.py
def __init__(self, name: str, field_info: pydantic.fields.FieldInfo):
self._name = name
if not isinstance(field_info, pydantic.fields.FieldInfo):
raise InvalidFieldError(
f"field_info must be of type pydantic.fields.FieldInfo. Got: {type(field_info)}"
)
super().__init__(field=field_info)
is_many(self) -> bool
¶
Check whether this field represents a one-to-one or one-to-many relationship.
Returns:
Type | Description |
---|---|
bool |
True if one-to-many relationship, else False. |
Source code in erdantic/pydantic.py
def is_many(self) -> bool:
return is_many(self.type_obj)
is_nullable(self) -> bool
¶
Check whether this field is nullable, i.e., can be None
.
Returns:
Type | Description |
---|---|
bool |
True if nullable, else False. |
Source code in erdantic/pydantic.py
def is_nullable(self) -> bool:
return is_nullable(self.type_obj)
PydanticModel (Model)
¶
Concrete model adapter class for a Pydantic
BaseModel
.
Attributes:
Name | Type | Description |
---|---|---|
model |
Type[pydantic.BaseModel] |
The Pydantic model class that is associated with this adapter instance. |
forward_ref_help |
Optional[str] |
Instructions for how to resolve an unevaluated forward reference in a field's type declaration. |
Source code in erdantic/pydantic.py
@register_model_adapter("pydantic")
class PydanticModel(Model[Type[pydantic.BaseModel]]):
"""Concrete model adapter class for a Pydantic
[`BaseModel`](https://pydantic-docs.helpmanual.io/usage/models/).
Attributes:
model (Type[pydantic.BaseModel]): The Pydantic model class that is associated with this
adapter instance.
forward_ref_help (Optional[str]): Instructions for how to resolve an unevaluated forward
reference in a field's type declaration.
"""
forward_ref_help = (
"Call 'update_forward_refs' after model is created to resolve. "
"See: https://pydantic-docs.helpmanual.io/usage/postponed_annotations/"
)
def __init__(self, model: Type[pydantic.BaseModel]):
if not self.is_model_type(model):
raise InvalidModelError(
"Argument model must be a subclass of pydantic.BaseModel. "
f"Got {repr_type_with_mro(model)}"
)
super().__init__(model=model)
@staticmethod
def is_model_type(obj: Any) -> bool:
return isinstance(obj, type) and issubclass(obj, pydantic.BaseModel)
@property
def fields(self) -> List[Field]:
return [
PydanticField(name=name, field_info=field_info)
for name, field_info in self.model.model_fields.items()
]
@property
def docstring(self) -> str:
out = super().docstring
field_descriptions = [field.field.description for field in self.fields]
if any(descr is not None for descr in field_descriptions):
# Sometimes Pydantic models have field documentation as descriptions as metadata on the
# field instead of in the docstring. If detected, construct docstring and add.
out += "\nAttributes:\n"
field_defaults = [field.field.default for field in self.fields]
for field, descr, default in zip(self.fields, field_descriptions, field_defaults):
if descr is not None:
line = f"{field.name} ({field.type_name}): {descr}"
if (
not isinstance(default, pydantic_core.PydanticUndefinedType)
and default is not ...
):
if not line.strip().endswith("."):
line = line.rstrip() + ". "
else:
line = line.rstrip() + " "
if isinstance(default, str):
line += f"Default is '{default}'."
else:
line += f"Default is {default}."
out += " " + line.strip() + "\n"
return out
Attributes¶
docstring: str
property
readonly
¶
Docstring for this data model.
fields: List[erdantic.base.Field]
property
readonly
¶
List of fields defined on this data model.
forward_ref_help: Optional[str]
¶
Methods¶
__init__(self, model: Type[pydantic.main.BaseModel])
special
¶
Source code in erdantic/pydantic.py
def __init__(self, model: Type[pydantic.BaseModel]):
if not self.is_model_type(model):
raise InvalidModelError(
"Argument model must be a subclass of pydantic.BaseModel. "
f"Got {repr_type_with_mro(model)}"
)
super().__init__(model=model)
is_model_type(obj: Any) -> bool
staticmethod
¶
Check if object is the type of data model class that this model adapter works with.
Source code in erdantic/pydantic.py
@staticmethod
def is_model_type(obj: Any) -> bool:
return isinstance(obj, type) and issubclass(obj, pydantic.BaseModel)