Coverage for fast_depends/pydantic/schema.py: 100%

38 statements  

« prev     ^ index     » next       coverage.py v7.17.3, created at 2026-11-13 05:19 +0000

1from collections.abc import Iterable 1abcdefghijklmno

2from typing import Any 1abcdefghijklmno

3 

4from fast_depends.core import CallModel 1abcdefghijklmno

5from fast_depends.pydantic._compat import PYDANTIC_V2, create_model, model_schema 1abcdefghijklmno

6 

7 

8def get_schema( 1abcdefghijklmno

9 call: CallModel, 

10 *, 

11 embed: bool = False, 

12 resolve_refs: bool = False, 

13 exclude: Iterable[str] = (), 

14) -> dict[str, Any]: 

15 class_options: dict[str, Any] = { 1abcdefghijklmno

16 i.field_name: (i.field_type, i.default_value) 

17 for i in call.flat_params 

18 if i.field_name not in exclude 

19 } 

20 

21 name = getattr(call.serializer, "name", "Undefined") 1abcdefghijklmno

22 

23 if not class_options: 1abcdefghijklmno

24 return {"title": name, "type": "null"} 1abcdefghijklmno

25 

26 params_model = create_model(name, **class_options) 1abcdefghijklmno

27 

28 body = model_schema(params_model) 1abcdefghijklmno

29 

30 if resolve_refs: 1abcdefghijklmno

31 pydantic_key = "$defs" if PYDANTIC_V2 else "definitions" 1abcdefghijklmno

32 body = _move_pydantic_refs(body, pydantic_key) 1abcdefghijklmno

33 body.pop(pydantic_key, None) 1abcdefghijklmno

34 

35 if embed and len(body["properties"]) == 1: 1abcdefghijklmno

36 body = list(body["properties"].values())[0] 1abcdefghijklmno

37 

38 return body 1abcdefghijklmno

39 

40 

41def _move_pydantic_refs( 1abcdefghijklmno

42 original: Any, key: str, refs: dict[str, Any] | None = None 

43) -> Any: 

44 if not isinstance(original, dict): 1abcdefghijklmno

45 return original 1abcdefghijklmno

46 

47 data = original.copy() 1abcdefghijklmno

48 

49 if refs is None: 1abcdefghijklmno

50 raw_refs = data.get(key, {}) 1abcdefghijklmno

51 refs = _move_pydantic_refs(raw_refs, key, raw_refs) 1abcdefghijklmno

52 

53 name: str | None = None 1abcdefghijklmno

54 for k in data: 1abcdefghijklmno

55 if k == "$ref": 1abcdefghijklmno

56 name = data[k].replace(f"#/{key}/", "") 1abcdefghijklmno

57 

58 elif isinstance(data[k], dict): 1abcdefghijklmno

59 data[k] = _move_pydantic_refs(data[k], key, refs) 1abcdefghijklmno

60 

61 elif isinstance(data[k], list): 1abcdefghijklmno

62 for i in range(len(data[k])): 1abcdefghijklmno

63 data[k][i] = _move_pydantic_refs(data[k][i], key, refs) 1abcdefghijklmno

64 

65 if name: 1abcdefghijklmno

66 assert refs, "Smth wrong" 1abcdefghijklmno

67 data = refs[name] 1abcdefghijklmno

68 

69 return data 1abcdefghijklmno