Coverage for /pythoncovmergedfiles/medio/medio/src/pydantic/pydantic/_internal/_forward_ref.py: 70%

43 statements  

« prev     ^ index     » next       coverage.py v7.2.3, created at 2023-04-27 07:38 +0000

1from __future__ import annotations as _annotations 

2 

3from dataclasses import dataclass, replace 

4from typing import Any, Union 

5 

6from pydantic_core import core_schema 

7from typing_extensions import Literal, TypedDict 

8 

9from ._typing_extra import TypeVarType 

10 

11 

12class DeferredClassGetitem(TypedDict): 

13 kind: Literal['class_getitem'] 

14 item: Any 

15 

16 

17class DeferredReplaceTypes(TypedDict): 

18 kind: Literal['replace_types'] 

19 typevars_map: dict[TypeVarType, Any] 

20 

21 

22DeferredAction = Union[DeferredClassGetitem, DeferredReplaceTypes] 

23 

24 

25@dataclass 

26class PydanticRecursiveRef: 

27 type_ref: str 

28 

29 __name__ = 'PydanticRecursiveRef' 

30 __hash__ = object.__hash__ 

31 

32 def __call__(self) -> None: 

33 """ 

34 Defining __call__ is necessary for the `typing` module to let you use an instance of 

35 this class as the result of resolving a standard ForwardRef 

36 """ 

37 

38 

39@dataclass 

40class PydanticForwardRef: 

41 """ 

42 No-op marker class for (recursive) type references. 

43 

44 Most of the logic here exists to handle recursive generics. 

45 """ 

46 

47 schema: core_schema.CoreSchema 

48 model: type[Any] 

49 deferred_actions: tuple[DeferredAction, ...] = () 

50 

51 __name__ = 'PydanticForwardRef' 

52 __hash__ = object.__hash__ 

53 

54 def __call__(self) -> None: 

55 """ 

56 Defining __call__ is necessary for the `typing` module to let you use an instance of 

57 this class as the result of resolving a standard ForwardRef 

58 """ 

59 

60 def __getitem__(self, item: Any) -> PydanticForwardRef: 

61 updated_actions = self.deferred_actions + ({'kind': 'class_getitem', 'item': item},) 

62 return replace(self, deferred_actions=updated_actions) 

63 

64 def replace_types(self, typevars_map: Any) -> PydanticForwardRef: 

65 updated_actions = self.deferred_actions + ({'kind': 'replace_types', 'typevars_map': typevars_map},) 

66 return replace(self, deferred_actions=updated_actions) 

67 

68 def resolve_model(self) -> type[Any] | PydanticForwardRef: 

69 from ._generics import replace_types 

70 

71 model: type[Any] | PydanticForwardRef = self.model 

72 for action in self.deferred_actions: 

73 if action['kind'] == 'replace_types': 

74 model = replace_types(model, action['typevars_map']) 

75 elif action['kind'] == 'class_getitem': 

76 model = model[action['item']] # type: ignore[index] 

77 else: 

78 raise ValueError(f'Unexpected action: {action}') 

79 return model