Skip to content

Commit

Permalink
feat: Also support pydantic.model_validator
Browse files Browse the repository at this point in the history
Issue-4: #4
  • Loading branch information
pawamoy committed Nov 3, 2024
1 parent 3e1020e commit c83074d
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 9 deletions.
11 changes: 10 additions & 1 deletion docs/examples/model_ext.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pydantic import field_validator, ConfigDict, BaseModel, Field
from typing import Any
from pydantic import field_validator, model_validator, ConfigDict, BaseModel, Field


class ExampleModel(BaseModel):
Expand Down Expand Up @@ -26,3 +27,11 @@ def check_max_length_ten(cls, v) -> str:
if len(v) >= 10:
raise ValueError("No more than 10 characters allowed")
return v

@model_validator(mode="before")
@classmethod
def lowercase_only(cls, data: dict[str, Any]) -> dict[str, Any]:
"""Ensure that the field without a default is lowercase."""
if isinstance(data.get("field_without_default"), str):
data["field_without_default"] = data["field_without_default"].lower()
return data
6 changes: 3 additions & 3 deletions src/griffe_pydantic/static.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def inherits_pydantic(cls: Class) -> bool:
return any(inherits_pydantic(parent_class) for parent_class in cls.mro())


def pydantic_field_validator(func: Function) -> ExprCall | None:
def pydantic_validator(func: Function) -> ExprCall | None:
"""Return a function's `pydantic.field_validator` decorator if it exists.
Parameters:
Expand All @@ -58,7 +58,7 @@ def pydantic_field_validator(func: Function) -> ExprCall | None:
A decorator value (Griffe expression).
"""
for decorator in func.decorators:
if isinstance(decorator.value, ExprCall) and decorator.callable_path == "pydantic.field_validator":
if isinstance(decorator.value, ExprCall) and decorator.callable_path in {"pydantic.field_validator", "pydantic.model_validator"}:
return decorator.value
return None

Expand Down Expand Up @@ -110,7 +110,7 @@ def process_function(func: Function, cls: Class, *, processed: set[str]) -> None
logger.warning(f"cannot yet process {func}")
return

if decorator := pydantic_field_validator(func):
if decorator := pydantic_validator(func):
fields = [ast.literal_eval(field) for field in decorator.arguments if isinstance(field, str)]
common.process_function(func, cls, fields)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,14 @@
<ul>
{% for name, validator in validators.items() %}
<li>
<code><autoref optional hover identifier="{{ validator.path }}">{{ name }}</autoref></code> &rarr;
{% for target in validator.extra.griffe_pydantic.targets %}
<code><autoref optional hover identifier="{{ target.path }}">{{ target.name }}</autoref></code>
{%- if not loop.last %}, {% endif %}
{% endfor %}
<code><autoref optional hover identifier="{{ validator.path }}">{{ name }}</autoref></code>
{% if validator.extra.griffe_pydantic.targets %}
&rarr;
{% for target in validator.extra.griffe_pydantic.targets %}
<code><autoref optional hover identifier="{{ target.path }}">{{ target.name }}</autoref></code>
{%- if not loop.last %}, {% endif %}
{% endfor %}
{% endif %}
</li>
{% endfor %}
</ul>
Expand Down

0 comments on commit c83074d

Please sign in to comment.