Coverage for pydantic/_internal/_core_metadata.py: 87.04%

34 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-02-13 19:35 +0000

1from __future__ import annotations as _annotations 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

2 

3from typing import TYPE_CHECKING, Any, TypedDict, cast 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

4from warnings import warn 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

5 

6if TYPE_CHECKING: 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

7 from ..config import JsonDict, JsonSchemaExtraCallable 

8 from ._schema_generation_shared import ( 

9 GetJsonSchemaFunction, 

10 ) 

11 

12 

13class CoreMetadata(TypedDict, total=False): 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

14 """A `TypedDict` for holding the metadata dict of the schema. 

15 

16 Attributes: 

17 pydantic_js_functions: List of JSON schema functions that resolve refs during application. 

18 pydantic_js_annotation_functions: List of JSON schema functions that don't resolve refs during application. 

19 pydantic_js_prefer_positional_arguments: Whether JSON schema generator will 

20 prefer positional over keyword arguments for an 'arguments' schema. 

21 custom validation function. Only applies to before, plain, and wrap validators. 

22 pydantic_js_updates: key / value pair updates to apply to the JSON schema for a type. 

23 pydantic_js_extra: WIP, either key/value pair updates to apply to the JSON schema, or a custom callable. 

24 pydantic_internal_union_tag_key: Used internally by the `Tag` metadata to specify the tag used for a discriminated union. 

25 pydantic_internal_union_discriminator: Used internally to specify the discriminator value for a discriminated union 

26 when the discriminator was applied to a `'definition-ref'` schema, and that reference was missing at the time 

27 of the annotation application. 

28 

29 TODO: Perhaps we should move this structure to pydantic-core. At the moment, though, 

30 it's easier to iterate on if we leave it in pydantic until we feel there is a semi-stable API. 

31 

32 TODO: It's unfortunate how functionally oriented JSON schema generation is, especially that which occurs during 

33 the core schema generation process. It's inevitable that we need to store some json schema related information 

34 on core schemas, given that we generate JSON schemas directly from core schemas. That being said, debugging related 

35 issues is quite difficult when JSON schema information is disguised via dynamically defined functions. 

36 """ 

37 

38 pydantic_js_functions: list[GetJsonSchemaFunction] 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

39 pydantic_js_annotation_functions: list[GetJsonSchemaFunction] 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

40 pydantic_js_prefer_positional_arguments: bool 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

41 pydantic_js_updates: JsonDict 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

42 pydantic_js_extra: JsonDict | JsonSchemaExtraCallable 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

43 pydantic_internal_union_tag_key: str 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

44 pydantic_internal_union_discriminator: str 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

45 

46 

47def update_core_metadata( 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

48 core_metadata: Any, 

49 /, 

50 *, 

51 pydantic_js_functions: list[GetJsonSchemaFunction] | None = None, 

52 pydantic_js_annotation_functions: list[GetJsonSchemaFunction] | None = None, 

53 pydantic_js_updates: JsonDict | None = None, 

54 pydantic_js_extra: JsonDict | JsonSchemaExtraCallable | None = None, 

55) -> None: 

56 from ..json_schema import PydanticJsonSchemaWarning 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

57 

58 """Update CoreMetadata instance in place. When we make modifications in this function, they 1abcdefghijklmnopqGHIJKLrstuvwxy

59 take effect on the `core_metadata` reference passed in as the first (and only) positional argument. 

60 

61 First, cast to `CoreMetadata`, then finish with a cast to `dict[str, Any]` for core schema compatibility. 

62 We do this here, instead of before / after each call to this function so that this typing hack 

63 can be easily removed if/when we move `CoreMetadata` to `pydantic-core`. 

64 

65 For parameter descriptions, see `CoreMetadata` above. 

66 """ 

67 core_metadata = cast(CoreMetadata, core_metadata) 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

68 

69 if pydantic_js_functions: 69 ↛ 70line 69 didn't jump to line 70 because the condition on line 69 was never true1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

70 core_metadata.setdefault('pydantic_js_functions', []).extend(pydantic_js_functions) 

71 

72 if pydantic_js_annotation_functions: 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

73 core_metadata.setdefault('pydantic_js_annotation_functions', []).extend(pydantic_js_annotation_functions) 1zAabcdefghBiCDjklmnopqEFrstuvwxy

74 

75 if pydantic_js_updates: 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

76 if (existing_updates := core_metadata.get('pydantic_js_updates')) is not None: 1zAabcdefghBiCDjklmnopqEFrstuvwxy

77 core_metadata['pydantic_js_updates'] = {**existing_updates, **pydantic_js_updates} 1zAabcdefghBiCDjklmnopqEFrstuvwxy

78 else: 

79 core_metadata['pydantic_js_updates'] = pydantic_js_updates 1zAabcdefghBiCDjklmnopqEFrstuvwxy

80 

81 if pydantic_js_extra is not None: 1zAabcdefghBiCDjklmnopqMGHIJKLEFrstuvwxy

82 existing_pydantic_js_extra = core_metadata.get('pydantic_js_extra') 1zAabcdefghBiCDjklmnopqEFrstuvwxy

83 if existing_pydantic_js_extra is None: 1zAabcdefghBiCDjklmnopqEFrstuvwxy

84 core_metadata['pydantic_js_extra'] = pydantic_js_extra 1zAabcdefghBiCDjklmnopqEFrstuvwxy

85 if isinstance(existing_pydantic_js_extra, dict): 1zAabcdefghBiCDjklmnopqEFrstuvwxy

86 if isinstance(pydantic_js_extra, dict): 86 ↛ 88line 86 didn't jump to line 88 because the condition on line 86 was always true1zAabcdefghBiCDjklmnopqEFrstuvwxy

87 core_metadata['pydantic_js_extra'] = {**existing_pydantic_js_extra, **pydantic_js_extra} 1zAabcdefghBiCDjklmnopqEFrstuvwxy

88 if callable(pydantic_js_extra): 88 ↛ 89line 88 didn't jump to line 89 because the condition on line 88 was never true1zAabcdefghBiCDjklmnopqEFrstuvwxy

89 warn( 

90 'Composing `dict` and `callable` type `json_schema_extra` is not supported.' 

91 'The `callable` type is being ignored.' 

92 "If you'd like support for this behavior, please open an issue on pydantic.", 

93 PydanticJsonSchemaWarning, 

94 ) 

95 if callable(existing_pydantic_js_extra): 95 ↛ 97line 95 didn't jump to line 97 because the condition on line 95 was never true1zAabcdefghBiCDjklmnopqEFrstuvwxy

96 # if ever there's a case of a callable, we'll just keep the last json schema extra spec 

97 core_metadata['pydantic_js_extra'] = pydantic_js_extra