dynamic.py
1 from __future__ import annotations 2 3 from typing import Any, Callable 4 5 from griffe import ( 6 Attribute, 7 Class, 8 Docstring, 9 Function, 10 Kind, 11 get_logger, 12 ) 13 14 from griffe_pydantic._internal import common 15 16 _logger = get_logger("griffe_pydantic") 17 18 19 def _process_attribute(obj: Any, attr: Attribute, cls: Class, *, processed: set[str]) -> None: 20 """Handle Pydantic fields.""" 21 from pydantic.fields import FieldInfo # noqa: PLC0415 22 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 29 30 if not isinstance(obj, FieldInfo): 31 return 32 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 40 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) 44 45 46 def _process_function(obj: Callable, func: Function, cls: Class, *, processed: set[str]) -> None: 47 """Handle Pydantic field validators.""" 48 if func.canonical_path in processed: 49 return 50 processed.add(func.canonical_path) 51 if dec_info := getattr(obj, "decorator_info", None): 52 common._process_function(func, cls, dec_info.fields) 53 54 55 def _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: 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: 65 _process_function(getattr(obj, member.name), member, cls, processed=processed) # type: ignore[arg-type]