Coverage for src/griffe_pydantic/_internal/dynamic.py: 65.62%
40 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-05 17:55 +0200
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-05 17:55 +0200
1from __future__ import annotations
3from typing import Any, Callable
5from griffe import (
6 Attribute,
7 Class,
8 Docstring,
9 Function,
10 Kind,
11 get_logger,
12)
14from griffe_pydantic._internal import common
16_logger = get_logger("griffe_pydantic")
19def _process_attribute(obj: Any, attr: Attribute, cls: Class, *, processed: set[str]) -> None:
20 """Handle Pydantic fields."""
21 from pydantic.fields import FieldInfo # noqa: PLC0415
23 if attr.canonical_path in processed:
24 return
25 processed.add(attr.canonical_path)
26 if attr.name == "model_config":
27 cls.extra[common._self_namespace]["config"] = obj
28 return
30 if not isinstance(obj, FieldInfo): 30 ↛ 33line 30 didn't jump to line 33 because the condition on line 30 was always true
31 return
33 attr.labels = {"pydantic-field"}
34 attr.value = obj.default
35 constraints = {}
36 for constraint in common._field_constraints:
37 if (value := getattr(obj, constraint, None)) is not None:
38 constraints[constraint] = value
39 attr.extra[common._self_namespace]["constraints"] = constraints
41 # Populate docstring from the field's `description` argument.
42 if not attr.docstring and (docstring := obj.description):
43 attr.docstring = Docstring(docstring, parent=attr)
46def _process_function(obj: Callable, func: Function, cls: Class, *, processed: set[str]) -> None:
47 """Handle Pydantic field validators."""
48 if func.canonical_path in processed: 48 ↛ 49line 48 didn't jump to line 49 because the condition on line 48 was never true
49 return
50 processed.add(func.canonical_path)
51 if dec_info := getattr(obj, "decorator_info", None): 51 ↛ 52line 51 didn't jump to line 52 because the condition on line 51 was never true
52 common._process_function(func, cls, dec_info.fields)
55def _process_class(obj: type, cls: Class, *, processed: set[str], schema: bool = False) -> None:
56 """Detect and prepare Pydantic models."""
57 common._process_class(cls)
58 if schema: 58 ↛ 60line 58 didn't jump to line 60 because the condition on line 58 was always true
59 cls.extra[common._self_namespace]["schema"] = common._json_schema(obj)
60 for member in cls.all_members.values():
61 kind = member.kind
62 if kind is Kind.ATTRIBUTE:
63 _process_attribute(getattr(obj, member.name), member, cls, processed=processed) # type: ignore[arg-type]
64 elif kind is Kind.FUNCTION: 64 ↛ 60line 64 didn't jump to line 60 because the condition on line 64 was always true
65 _process_function(getattr(obj, member.name), member, cls, processed=processed) # type: ignore[arg-type]