Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pydantic/root_model.py: 48%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

71 statements  

1"""RootModel class and type definitions.""" 

2 

3from __future__ import annotations as _annotations 

4 

5from collections.abc import Callable 

6from copy import copy, deepcopy 

7from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar 

8 

9from pydantic_core import PydanticUndefined 

10from typing_extensions import Self, dataclass_transform 

11 

12from . import PydanticUserError 

13from ._internal import _model_construction, _repr 

14from .main import BaseModel, _object_setattr 

15 

16if TYPE_CHECKING: 

17 from .fields import Field as PydanticModelField 

18 from .fields import PrivateAttr as PydanticModelPrivateAttr 

19 from .main import IncEx 

20 

21 # dataclass_transform could be applied to RootModel directly, but `ModelMetaclass`'s dataclass_transform 

22 # takes priority (at least with pyright). We trick type checkers into thinking we apply dataclass_transform 

23 # on a new metaclass. 

24 @dataclass_transform(kw_only_default=False, field_specifiers=(PydanticModelField, PydanticModelPrivateAttr)) 

25 class _RootModelMetaclass(_model_construction.ModelMetaclass): ... 

26else: 

27 _RootModelMetaclass = _model_construction.ModelMetaclass 

28 

29__all__ = ('RootModel',) 

30 

31RootModelRootType = TypeVar('RootModelRootType') 

32 

33 

34class RootModel(BaseModel, Generic[RootModelRootType], metaclass=_RootModelMetaclass): 

35 """!!! abstract "Usage Documentation" 

36 [`RootModel` and Custom Root Types](../concepts/models.md#rootmodel-and-custom-root-types) 

37 

38 A Pydantic `BaseModel` for the root object of the model. 

39 

40 Attributes: 

41 root: The root object of the model. 

42 __pydantic_root_model__: Whether the model is a RootModel. 

43 __pydantic_private__: Private fields in the model. 

44 __pydantic_extra__: Extra fields in the model. 

45 

46 """ 

47 

48 __pydantic_root_model__ = True 

49 __pydantic_private__ = None 

50 __pydantic_extra__ = None 

51 

52 root: RootModelRootType 

53 

54 def __init_subclass__(cls, **kwargs): 

55 extra = cls.model_config.get('extra') 

56 if extra is not None: 

57 raise PydanticUserError( 

58 "`RootModel` does not support setting `model_config['extra']`", code='root-model-extra' 

59 ) 

60 super().__init_subclass__(**kwargs) 

61 

62 def __init__(self, /, root: RootModelRootType = PydanticUndefined, **data) -> None: # type: ignore 

63 __tracebackhide__ = True 

64 if data: 

65 if root is not PydanticUndefined: 

66 raise ValueError( 

67 '"RootModel.__init__" accepts either a single positional argument or arbitrary keyword arguments' 

68 ) 

69 root = data # type: ignore 

70 self.__pydantic_validator__.validate_python(root, self_instance=self) 

71 

72 __init__.__pydantic_base_init__ = True # pyright: ignore[reportFunctionMemberAccess] 

73 

74 @classmethod 

75 def model_construct(cls, root: RootModelRootType, _fields_set: set[str] | None = None) -> Self: # type: ignore 

76 """Create a new model using the provided root object and update fields set. 

77 

78 Args: 

79 root: The root object of the model. 

80 _fields_set: The set of fields to be updated. 

81 

82 Returns: 

83 The new model. 

84 

85 Raises: 

86 NotImplemented: If the model is not a subclass of `RootModel`. 

87 """ 

88 return super().model_construct(root=root, _fields_set=_fields_set) 

89 

90 def __getstate__(self) -> dict[Any, Any]: 

91 return { 

92 '__dict__': self.__dict__, 

93 '__pydantic_fields_set__': self.__pydantic_fields_set__, 

94 } 

95 

96 def __setstate__(self, state: dict[Any, Any]) -> None: 

97 _object_setattr(self, '__pydantic_fields_set__', state['__pydantic_fields_set__']) 

98 _object_setattr(self, '__dict__', state['__dict__']) 

99 

100 def __copy__(self) -> Self: 

101 """Returns a shallow copy of the model.""" 

102 cls = type(self) 

103 m = cls.__new__(cls) 

104 new_dict = copy(self.__dict__) 

105 new_dict['root'] = copy(self.__dict__['root']) # pyright: ignore[reportIndexIssue] (https://github.com/microsoft/pyright/issues/11548) 

106 _object_setattr(m, '__dict__', new_dict) 

107 _object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__)) 

108 return m 

109 

110 def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self: 

111 """Returns a deep copy of the model.""" 

112 if memo is None: 

113 memo = {} 

114 cls = type(self) 

115 m = cls.__new__(cls) 

116 memo[id(self)] = m 

117 _object_setattr(m, '__dict__', deepcopy(self.__dict__, memo=memo)) 

118 # This next line doesn't need a deepcopy because __pydantic_fields_set__ is a set[str], 

119 # and attempting a deepcopy would be marginally slower. 

120 _object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__)) 

121 return m 

122 

123 if TYPE_CHECKING: 

124 # This `model_dump()` definition is only provided to get a more accurate return type for type checkers 

125 # (no override is actually necessary at runtime). Generally, the return type will be `RootModelRootType`, 

126 # assuming that `RootModelRootType` is not a `BaseModel` subclass. If `RootModelRootType` is a `BaseModel` 

127 # subclass, then the return type will likely be `dict[str, Any]`, as `model_dump()` calls are recursive. 

128 # The return type could even be something different, in the case of a custom serializer. Thus, `Any` is 

129 # used here to catch all of these cases. 

130 

131 def model_dump( # type: ignore 

132 self, 

133 *, 

134 mode: Literal['json', 'python'] | str = 'python', 

135 include: IncEx | None = None, 

136 exclude: IncEx | None = None, 

137 context: Any | None = None, 

138 by_alias: bool | None = None, 

139 exclude_unset: bool = False, 

140 exclude_defaults: bool = False, 

141 exclude_none: bool = False, 

142 exclude_computed_fields: bool = False, 

143 round_trip: bool = False, 

144 warnings: bool | Literal['none', 'warn', 'error'] = True, 

145 fallback: Callable[[Any], Any] | None = None, 

146 serialize_as_any: bool = False, 

147 polymorphic_serialization: bool | None = None, 

148 ) -> Any: 

149 """!!! abstract "Usage Documentation" 

150 [`model_dump`](../concepts/serialization.md#python-mode) 

151 

152 Generate a dictionary representation of the model, optionally specifying which fields to include or exclude. 

153 

154 Args: 

155 mode: The mode in which `to_python` should run. 

156 If mode is 'json', the output will only contain JSON serializable types. 

157 If mode is 'python', the output may contain non-JSON-serializable Python objects. 

158 include: A set of fields to include in the output. 

159 exclude: A set of fields to exclude from the output. 

160 context: Additional context to pass to the serializer. 

161 by_alias: Whether to use the field's alias in the dictionary key if defined. 

162 exclude_unset: Whether to exclude fields that have not been explicitly set. 

163 exclude_defaults: Whether to exclude fields that are set to their default value. 

164 exclude_none: Whether to exclude fields that have a value of `None`. 

165 exclude_computed_fields: Whether to exclude computed fields. 

166 While this can be useful for round-tripping, it is usually recommended to use the dedicated 

167 `round_trip` parameter instead. 

168 round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T]. 

169 warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, 

170 "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError]. 

171 fallback: A function to call when an unknown value is encountered. If not provided, 

172 a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised. 

173 serialize_as_any: Whether to serialize fields with duck-typing serialization behavior. 

174 polymorphic_serialization: Whether to use model and dataclass polymorphic serialization for this call. 

175 

176 Returns: 

177 A dictionary representation of the model. 

178 """ 

179 ... 

180 

181 def __eq__(self, other: Any) -> bool: 

182 if not isinstance(other, RootModel): 

183 return NotImplemented 

184 return self.__pydantic_fields__['root'].annotation == other.__pydantic_fields__[ 

185 'root' 

186 ].annotation and super().__eq__(other) 

187 

188 def __repr_args__(self) -> _repr.ReprArgs: 

189 yield 'root', self.root