Coverage for src/griffe_pydantic/_internal/common.py: 100.00%

28 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-09-05 17:55 +0200

1from __future__ import annotations 

2 

3import json 

4from functools import partial 

5from typing import TYPE_CHECKING 

6 

7if TYPE_CHECKING: 

8 from collections.abc import Sequence 

9 

10 from griffe import Attribute, Class, Function 

11 from pydantic import BaseModel 

12 

13_self_namespace = "griffe_pydantic" 

14_mkdocstrings_namespace = "mkdocstrings" 

15 

16_field_constraints = { 

17 "gt", 

18 "ge", 

19 "lt", 

20 "le", 

21 "multiple_of", 

22 "min_length", 

23 "max_length", 

24 "pattern", 

25 "allow_inf_nan", 

26 "max_digits", 

27 "decimal_place", 

28} 

29 

30 

31def _model_fields(cls: Class) -> dict[str, Attribute]: 

32 return {name: attr for name, attr in cls.all_members.items() if "pydantic-field" in attr.labels} # type: ignore[misc] 

33 

34 

35def _model_validators(cls: Class) -> dict[str, Function]: 

36 return {name: func for name, func in cls.all_members.items() if "pydantic-validator" in func.labels} # type: ignore[misc] 

37 

38 

39def _json_schema(model: type[BaseModel]) -> str: 

40 """Produce a model schema as JSON. 

41 

42 Parameters: 

43 model: A Pydantic model. 

44 

45 Returns: 

46 A schema as JSON. 

47 """ 

48 return json.dumps(model.model_json_schema(), indent=2) 

49 

50 

51def _process_class(cls: Class) -> None: 

52 """Set metadata on a Pydantic model. 

53 

54 Parameters: 

55 cls: The Griffe class representing the Pydantic model. 

56 """ 

57 cls.labels.add("pydantic-model") 

58 cls.extra[_self_namespace]["fields"] = partial(_model_fields, cls) 

59 cls.extra[_self_namespace]["validators"] = partial(_model_validators, cls) 

60 cls.extra[_mkdocstrings_namespace]["template"] = "pydantic_model.html.jinja" 

61 

62 

63def _process_function(func: Function, cls: Class, fields: Sequence[str]) -> None: 

64 """Set metadata on a Pydantic validator. 

65 

66 Parameters: 

67 cls: A Griffe function representing the Pydantic validator. 

68 """ 

69 func.labels = {"pydantic-validator"} 

70 if fields and fields[0] == "*": 

71 targets = [member for member in cls.all_members.values() if "pydantic-field" in member.labels] 

72 else: 

73 targets = [cls.all_members[field] for field in fields] 

74 

75 func.extra[_self_namespace].setdefault("targets", []) 

76 func.extra[_self_namespace]["targets"].extend(targets) 

77 for target in targets: 

78 target.extra[_self_namespace].setdefault("validators", []) 

79 target.extra[_self_namespace]["validators"].append(func)