Coverage for /pythoncovmergedfiles/medio/medio/src/pydantic/pydantic/decorators.py: 36%

167 statements  

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

1""" 

2Public methods used as decorators within pydantic models and dataclasses. 

3""" 

4 

5from __future__ import annotations as _annotations 

6 

7from functools import partial, partialmethod 

8from types import FunctionType 

9from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union, overload 

10from warnings import warn 

11 

12from pydantic_core import core_schema as _core_schema 

13from typing_extensions import Literal, Protocol, TypeAlias 

14 

15from ._internal import _decorators, _decorators_v1 

16from .errors import PydanticUserError 

17 

18_ALLOW_REUSE_WARNING_MESSAGE = '`allow_reuse` is deprecated and will be ignored; it should no longer be necessary' 

19 

20 

21if TYPE_CHECKING: 

22 

23 class _OnlyValueValidatorClsMethod(Protocol): 

24 def __call__(self, __cls: Any, __value: Any) -> Any: 

25 ... 

26 

27 class _V1ValidatorWithValuesClsMethod(Protocol): 

28 def __call__(self, __cls: Any, __value: Any, values: dict[str, Any]) -> Any: 

29 ... 

30 

31 class _V1ValidatorWithValuesKwOnlyClsMethod(Protocol): 

32 def __call__(self, __cls: Any, __value: Any, *, values: dict[str, Any]) -> Any: 

33 ... 

34 

35 class _V1ValidatorWithKwargsClsMethod(Protocol): 

36 def __call__(self, __cls: Any, **kwargs: Any) -> Any: 

37 ... 

38 

39 class _V1ValidatorWithValuesAndKwargsClsMethod(Protocol): 

40 def __call__(self, __cls: Any, values: dict[str, Any], **kwargs: Any) -> Any: 

41 ... 

42 

43 class _V2ValidatorClsMethod(Protocol): 

44 def __call__(self, __cls: Any, __input_value: Any, __info: _core_schema.FieldValidationInfo) -> Any: 

45 ... 

46 

47 class _V2WrapValidatorClsMethod(Protocol): 

48 def __call__( 

49 self, 

50 __cls: Any, 

51 __input_value: Any, 

52 __validator: _core_schema.ValidatorFunctionWrapHandler, 

53 __info: _core_schema.ValidationInfo, 

54 ) -> Any: 

55 ... 

56 

57 class _V1RootValidatorClsMethod(Protocol): 

58 def __call__( 

59 self, __cls: Any, __values: _decorators_v1.RootValidatorValues 

60 ) -> _decorators_v1.RootValidatorValues: 

61 ... 

62 

63 V1Validator = Union[ 

64 _OnlyValueValidatorClsMethod, 

65 _V1ValidatorWithValuesClsMethod, 

66 _V1ValidatorWithValuesKwOnlyClsMethod, 

67 _V1ValidatorWithKwargsClsMethod, 

68 _V1ValidatorWithValuesAndKwargsClsMethod, 

69 _decorators_v1.V1ValidatorWithValues, 

70 _decorators_v1.V1ValidatorWithValuesKwOnly, 

71 _decorators_v1.V1ValidatorWithKwargs, 

72 _decorators_v1.V1ValidatorWithValuesAndKwargs, 

73 ] 

74 

75 V2Validator = Union[ 

76 _V2ValidatorClsMethod, 

77 _core_schema.FieldValidatorFunction, 

78 _OnlyValueValidatorClsMethod, 

79 _core_schema.NoInfoValidatorFunction, 

80 ] 

81 

82 V2WrapValidator = Union[ 

83 _V2WrapValidatorClsMethod, 

84 _core_schema.GeneralWrapValidatorFunction, 

85 _core_schema.FieldWrapValidatorFunction, 

86 ] 

87 

88 V1RootValidator = Union[ 

89 _V1RootValidatorClsMethod, 

90 _decorators_v1.V1RootValidatorFunction, 

91 ] 

92 

93 _PartialClsOrStaticMethod: TypeAlias = Union[classmethod[Any, Any, Any], staticmethod[Any, Any], partialmethod[Any]] 

94 

95 # Allow both a V1 (assumed pre=False) or V2 (assumed mode='after') validator 

96 # We lie to type checkers and say we return the same thing we get 

97 # but in reality we return a proxy object that _mostly_ behaves like the wrapped thing 

98 _V1ValidatorType = TypeVar('_V1ValidatorType', V1Validator, _PartialClsOrStaticMethod) 

99 _V2BeforeAfterOrPlainValidatorType = TypeVar( 

100 '_V2BeforeAfterOrPlainValidatorType', 

101 V2Validator, 

102 _PartialClsOrStaticMethod, 

103 ) 

104 _V2WrapValidatorType = TypeVar('_V2WrapValidatorType', V2WrapValidator, _PartialClsOrStaticMethod) 

105 _V1RootValidatorFunctionType = TypeVar( 

106 '_V1RootValidatorFunctionType', 

107 _decorators_v1.V1RootValidatorFunction, 

108 _V1RootValidatorClsMethod, 

109 _PartialClsOrStaticMethod, 

110 ) 

111 

112 

113def validator( 

114 __field: str, 

115 *fields: str, 

116 pre: bool = False, 

117 each_item: bool = False, 

118 always: bool = False, 

119 check_fields: bool | None = None, 

120 allow_reuse: bool = False, 

121) -> Callable[[_V1ValidatorType], _V1ValidatorType]: 

122 """ 

123 Decorate methods on the class indicating that they should be used to validate fields. 

124 

125 Args: 

126 __field (str): The first field the validator should be called on; this is separate 

127 from `fields` to ensure an error is raised if you don't pass at least one. 

128 *fields (str): Additional field(s) the validator should be called on. 

129 pre (bool, optional): Whether or not this validator should be called before the standard 

130 validators (else after). Defaults to False. 

131 each_item (bool, optional): For complex objects (sets, lists etc.) whether to validate 

132 individual elements rather than the whole object. Defaults to False. 

133 always (bool, optional): Whether this method and other validators should be called even if 

134 the value is missing. Defaults to False. 

135 check_fields (bool | None, optional): Whether to check that the fields actually exist on the model. 

136 Defaults to None. 

137 allow_reuse (bool, optional): Whether to track and raise an error if another validator refers to 

138 the decorated function. Defaults to False. 

139 

140 Returns: 

141 Callable: A decorator that can be used to decorate a 

142 function to be used as a validator. 

143 """ 

144 if allow_reuse is True: # pragma: no cover 

145 warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning) 

146 fields = tuple((__field, *fields)) 

147 if isinstance(fields[0], FunctionType): 

148 raise PydanticUserError( 

149 "validators should be used with fields and keyword arguments, not bare. " 

150 "E.g. usage should be `@validator('<field_name>', ...)`", 

151 code='validator-no-fields', 

152 ) 

153 elif not all(isinstance(field, str) for field in fields): 

154 raise PydanticUserError( 

155 "validator fields should be passed as separate string args. " 

156 "E.g. usage should be `@validator('<field_name_1>', '<field_name_2>', ...)`", 

157 code='validator-invalid-fields', 

158 ) 

159 

160 warn( 

161 'Pydantic V1 style `@validator` validators are deprecated.' 

162 ' You should migrate to Pydantic V2 style `@field_validator` validators,' 

163 ' see the migration guide for more details', 

164 DeprecationWarning, 

165 stacklevel=2, 

166 ) 

167 

168 mode: Literal['before', 'after'] = 'before' if pre is True else 'after' 

169 

170 def dec(f: Any) -> _decorators.PydanticDescriptorProxy[Any]: 

171 if _decorators.is_instance_method_from_sig(f): 

172 raise PydanticUserError( 

173 '`@validator` cannot be applied to instance methods', code='validator-instance-method' 

174 ) 

175 # auto apply the @classmethod decorator 

176 f = _decorators.ensure_classmethod_based_on_signature(f) 

177 wrap = _decorators_v1.make_generic_v1_field_validator 

178 validator_wrapper_info = _decorators.ValidatorDecoratorInfo( 

179 fields=fields, 

180 mode=mode, 

181 each_item=each_item, 

182 always=always, 

183 check_fields=check_fields, 

184 ) 

185 return _decorators.PydanticDescriptorProxy(f, validator_wrapper_info, shim=wrap) 

186 

187 return dec # type: ignore[return-value] 

188 

189 

190@overload 

191def field_validator( 

192 __field: str, 

193 *fields: str, 

194 mode: Literal['before', 'after', 'plain'] = ..., 

195 check_fields: bool | None = ..., 

196) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType]: 

197 ... 

198 

199 

200@overload 

201def field_validator( 

202 __field: str, 

203 *fields: str, 

204 mode: Literal['wrap'], 

205 check_fields: bool | None = ..., 

206) -> Callable[[_V2WrapValidatorType], _V2WrapValidatorType]: 

207 ... 

208 

209 

210FieldValidatorModes: TypeAlias = Literal['before', 'after', 'wrap', 'plain'] 

211 

212 

213def field_validator( 

214 __field: str, 

215 *fields: str, 

216 mode: FieldValidatorModes = 'after', 

217 check_fields: bool | None = None, 

218) -> Callable[[Any], Any]: 

219 """ 

220 Decorate methods on the class indicating that they should be used to validate fields. 

221 

222 Args: 

223 __field (str): The first field the field_validator should be called on; this is separate 

224 from `fields` to ensure an error is raised if you don't pass at least one. 

225 *fields (tuple): Additional field(s) the field_validator should be called on. 

226 mode (FieldValidatorModes): Specifies whether to validate the fields before or after validation. 

227 Defaults to 'after'. 

228 check_fields (bool | None): If set to True, checks that the fields actually exist on the model. 

229 Defaults to None. 

230 

231 Returns: 

232 Callable: A decorator that can be used to decorate a function to be used as a field_validator. 

233 """ 

234 if isinstance(__field, FunctionType): 

235 raise PydanticUserError( 

236 'field_validators should be used with fields and keyword arguments, not bare. ' 

237 "E.g. usage should be `@validator('<field_name>', ...)`", 

238 code='validator-no-fields', 

239 ) 

240 fields = __field, *fields 

241 if not all(isinstance(field, str) for field in fields): 

242 raise PydanticUserError( 

243 'field_validator fields should be passed as separate string args. ' 

244 "E.g. usage should be `@validator('<field_name_1>', '<field_name_2>', ...)`", 

245 code='validator-invalid-fields', 

246 ) 

247 

248 def dec( 

249 f: Callable[..., Any] | staticmethod[Any, Any] | classmethod[Any, Any, Any] 

250 ) -> _decorators.PydanticDescriptorProxy[Any]: 

251 if _decorators.is_instance_method_from_sig(f): 

252 raise PydanticUserError( 

253 '`@field_validator` cannot be applied to instance methods', code='validator-instance-method' 

254 ) 

255 

256 # auto apply the @classmethod decorator 

257 f = _decorators.ensure_classmethod_based_on_signature(f) 

258 

259 dec_info = _decorators.FieldValidatorDecoratorInfo(fields=fields, mode=mode, check_fields=check_fields) 

260 return _decorators.PydanticDescriptorProxy(f, dec_info) 

261 

262 return dec 

263 

264 

265@overload 

266def root_validator( 

267 *, 

268 # if you don't specify `pre` the default is `pre=False` 

269 # which means you need to specify `skip_on_failure=True` 

270 skip_on_failure: Literal[True], 

271 allow_reuse: bool = ..., 

272) -> Callable[[_V1RootValidatorFunctionType], _V1RootValidatorFunctionType,]: 

273 ... 

274 

275 

276@overload 

277def root_validator( 

278 *, 

279 # if you specify `pre=True` then you don't need to specify 

280 # `skip_on_failure`, in fact it is not allowed as an argument! 

281 pre: Literal[True], 

282 allow_reuse: bool = ..., 

283) -> Callable[[_V1RootValidatorFunctionType], _V1RootValidatorFunctionType,]: 

284 ... 

285 

286 

287@overload 

288def root_validator( 

289 *, 

290 # if you explicitly specify `pre=False` then you 

291 # MUST specify `skip_on_failure=True` 

292 pre: Literal[False], 

293 skip_on_failure: Literal[True], 

294 allow_reuse: bool = ..., 

295) -> Callable[[_V1RootValidatorFunctionType], _V1RootValidatorFunctionType,]: 

296 ... 

297 

298 

299def root_validator( 

300 *, 

301 pre: bool = False, 

302 skip_on_failure: bool = False, 

303 allow_reuse: bool = False, 

304) -> Any: 

305 """ 

306 Decorate methods on a model indicating that they should be used to validate (and perhaps 

307 modify) data either before or after standard model parsing/validation is performed. 

308 

309 Args: 

310 pre (bool, optional): Whether or not this validator should be called before the standard 

311 validators (else after). Defaults to False. 

312 skip_on_failure (bool, optional): Whether to stop validation and return as soon as a 

313 failure is encountered. Defaults to False. 

314 allow_reuse (bool, optional): Whether to track and raise an error if another validator 

315 refers to the decorated function. Defaults to False. 

316 

317 Returns: 

318 Any: A decorator that can be used to decorate a function to be used as a root_validator. 

319 """ 

320 if allow_reuse is True: # pragma: no cover 

321 warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning) 

322 mode: Literal['before', 'after'] = 'before' if pre is True else 'after' 

323 if pre is False and skip_on_failure is not True: 

324 raise PydanticUserError( 

325 'If you use `@root_validator` with pre=False (the default) you MUST specify `skip_on_failure=True`.', 

326 code='root-validator-pre-skip', 

327 ) 

328 

329 wrap = partial(_decorators_v1.make_v1_generic_root_validator, pre=pre) 

330 

331 def dec(f: Callable[..., Any] | classmethod[Any, Any, Any] | staticmethod[Any, Any]) -> Any: 

332 if _decorators.is_instance_method_from_sig(f): 

333 raise TypeError('`@root_validator` cannot be applied to instance methods') 

334 # auto apply the @classmethod decorator 

335 res = _decorators.ensure_classmethod_based_on_signature(f) 

336 dec_info = _decorators.RootValidatorDecoratorInfo(mode=mode) 

337 return _decorators.PydanticDescriptorProxy(res, dec_info, shim=wrap) 

338 

339 return dec 

340 

341 

342if TYPE_CHECKING: 

343 _PlainSerializationFunction = Union[_core_schema.SerializerFunction, _PartialClsOrStaticMethod] 

344 

345 _WrapSerializationFunction = Union[_core_schema.WrapSerializerFunction, _PartialClsOrStaticMethod] 

346 

347 _PlainSerializeMethodType = TypeVar('_PlainSerializeMethodType', bound=_PlainSerializationFunction) 

348 _WrapSerializeMethodType = TypeVar('_WrapSerializeMethodType', bound=_WrapSerializationFunction) 

349 

350 

351@overload 

352def field_serializer( 

353 __field: str, 

354 *fields: str, 

355 json_return_type: _core_schema.JsonReturnTypes | None = ..., 

356 when_used: Literal['always', 'unless-none', 'json', 'json-unless-none'] = ..., 

357 check_fields: bool | None = ..., 

358) -> Callable[[_PlainSerializeMethodType], _PlainSerializeMethodType]: 

359 ... 

360 

361 

362@overload 

363def field_serializer( 

364 __field: str, 

365 *fields: str, 

366 mode: Literal['plain'], 

367 json_return_type: _core_schema.JsonReturnTypes | None = ..., 

368 when_used: Literal['always', 'unless-none', 'json', 'json-unless-none'] = ..., 

369 check_fields: bool | None = ..., 

370) -> Callable[[_PlainSerializeMethodType], _PlainSerializeMethodType]: 

371 ... 

372 

373 

374@overload 

375def field_serializer( 

376 __field: str, 

377 *fields: str, 

378 mode: Literal['wrap'], 

379 json_return_type: _core_schema.JsonReturnTypes | None = ..., 

380 when_used: Literal['always', 'unless-none', 'json', 'json-unless-none'] = ..., 

381 check_fields: bool | None = ..., 

382) -> Callable[[_WrapSerializeMethodType], _WrapSerializeMethodType]: 

383 ... 

384 

385 

386def field_serializer( 

387 *fields: str, 

388 mode: Literal['plain', 'wrap'] = 'plain', 

389 json_return_type: _core_schema.JsonReturnTypes | None = None, 

390 when_used: Literal['always', 'unless-none', 'json', 'json-unless-none'] = 'always', 

391 check_fields: bool | None = None, 

392) -> Callable[[Any], Any]: 

393 """ 

394 Decorate methods on the class indicating that they should be used to serialize fields. 

395 

396 Four signatures are supported: 

397 

398 - `(self, value: Any, info: FieldSerializationInfo)` 

399 - `(self, value: Any, nxt: SerializerFunctionWrapHandler, info: FieldSerializationInfo)` 

400 - `(value: Any, info: SerializationInfo)` 

401 - `(value: Any, nxt: SerializerFunctionWrapHandler, info: SerializationInfo)` 

402 

403 Args: 

404 fields (str): Which field(s) the method should be called on. 

405 mode (str): `plain` means the function will be called instead of the default serialization logic, 

406 `wrap` means the function will be called with an argument to optionally call the 

407 default serialization logic. 

408 json_return_type (str): The type that the function returns if the serialization mode is JSON. 

409 when_used (str): When the function should be called. 

410 check_fields (bool): Whether to check that the fields actually exist on the model. 

411 

412 Returns: 

413 Callable: A decorator that can be used to decorate a function to be used as a field serializer. 

414 """ 

415 

416 def dec( 

417 f: Callable[..., Any] | staticmethod[Any, Any] | classmethod[Any, Any, Any] 

418 ) -> _decorators.PydanticDescriptorProxy[Any]: 

419 dec_info = _decorators.FieldSerializerDecoratorInfo( 

420 fields=fields, 

421 mode=mode, 

422 json_return_type=json_return_type, 

423 when_used=when_used, 

424 check_fields=check_fields, 

425 ) 

426 return _decorators.PydanticDescriptorProxy(f, dec_info) 

427 

428 return dec 

429 

430 

431def model_serializer( 

432 __f: Callable[..., Any] | None = None, 

433 *, 

434 mode: Literal['plain', 'wrap'] = 'plain', 

435 json_return_type: _core_schema.JsonReturnTypes | None = None, 

436) -> Callable[[Any], _decorators.PydanticDescriptorProxy[Any]] | _decorators.PydanticDescriptorProxy[Any]: 

437 """ 

438 Decorate a function which will be called to serialize the model. 

439 

440 (`when_used` is not permitted here since it makes no sense.) 

441 

442 Args: 

443 __f (Callable[..., Any] | None): The function to be decorated. 

444 mode (Literal['plain', 'wrap']): The serialization mode. `'plain'` means the function will be called 

445 instead of the default serialization logic, `'wrap'` means the function will be called with an argument 

446 to optionally call the default serialization logic. 

447 json_return_type (_core_schema.JsonReturnTypes | None): The type that the function returns if the 

448 serialization mode is JSON. 

449 

450 Returns: 

451 Callable: A decorator that can be used to decorate a function to be used as a model serializer. 

452 """ 

453 

454 def dec(f: Callable[..., Any]) -> _decorators.PydanticDescriptorProxy[Any]: 

455 dec_info = _decorators.ModelSerializerDecoratorInfo(mode=mode, json_return_type=json_return_type) 

456 return _decorators.PydanticDescriptorProxy(f, dec_info) 

457 

458 if __f is None: 

459 return dec 

460 else: 

461 return dec(__f) 

462 

463 

464ModelType = TypeVar('ModelType') 

465ModelWrapValidatorHandler = Callable[[Any], ModelType] 

466 

467 

468class ModelWrapValidatorWithoutInfo(Protocol): 

469 def __call__( 

470 self, 

471 cls: type[ModelType], 

472 # this can be a dict, a model instance 

473 # or anything else that gets passed to validate_python 

474 # thus validators _must_ handle all cases 

475 __value: Any, 

476 __handler: Callable[[Any], ModelType], 

477 ) -> ModelType: 

478 ... 

479 

480 

481class ModelWrapValidator(Protocol): 

482 def __call__( 

483 self, 

484 cls: type[ModelType], 

485 # this can be a dict, a model instance 

486 # or anything else that gets passed to validate_python 

487 # thus validators _must_ handle all cases 

488 __value: Any, 

489 __handler: Callable[[Any], ModelType], 

490 __info: _core_schema.ValidationInfo, 

491 ) -> ModelType: 

492 ... 

493 

494 

495class ModelBeforeValidatorWithoutInfo(Protocol): 

496 def __call__( 

497 self, 

498 cls: Any, 

499 # this can be a dict, a model instance 

500 # or anything else that gets passed to validate_python 

501 # thus validators _must_ handle all cases 

502 __value: Any, 

503 ) -> Any: 

504 ... 

505 

506 

507class ModelBeforeValidator(Protocol): 

508 def __call__( 

509 self, 

510 cls: Any, 

511 # this can be a dict, a model instance 

512 # or anything else that gets passed to validate_python 

513 # thus validators _must_ handle all cases 

514 __value: Any, 

515 __info: _core_schema.ValidationInfo, 

516 ) -> Any: 

517 ... 

518 

519 

520class ModelAfterValidatorWithoutInfo(Protocol): 

521 @staticmethod 

522 def __call__( 

523 self: ModelType, # type: ignore 

524 ) -> ModelType: 

525 ... 

526 

527 

528class ModelAfterValidator(Protocol): 

529 @staticmethod 

530 def __call__( 

531 self: ModelType, # type: ignore 

532 __info: _core_schema.ValidationInfo, 

533 ) -> ModelType: 

534 ... 

535 

536 

537AnyModelWrapValidator = Union[ModelWrapValidator, ModelWrapValidatorWithoutInfo] 

538AnyModeBeforeValidator = Union[ModelBeforeValidator, ModelBeforeValidatorWithoutInfo] 

539AnyModeAfterValidator = Union[ModelAfterValidator, ModelAfterValidatorWithoutInfo] 

540 

541 

542@overload 

543def model_validator( 

544 *, 

545 mode: Literal['wrap'], 

546) -> Callable[[AnyModelWrapValidator], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]]: 

547 ... 

548 

549 

550@overload 

551def model_validator( 

552 *, 

553 mode: Literal['before'], 

554) -> Callable[[AnyModeBeforeValidator], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]]: 

555 ... 

556 

557 

558@overload 

559def model_validator( 

560 *, 

561 mode: Literal['after'], 

562) -> Callable[[AnyModeAfterValidator], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]]: 

563 ... 

564 

565 

566def model_validator( 

567 *, 

568 mode: Literal['wrap', 'before', 'after'], 

569) -> Any: 

570 """ 

571 Decorate model methods for validation purposes. 

572 

573 Args: 

574 mode (Literal['wrap', 'before', 'after']): A required string literal that specifies the validation mode. 

575 It can be one of the following: 'wrap', 'before', or 'after'. 

576 

577 Returns: 

578 Any: A decorator that can be used to decorate a function to be used as a model validator. 

579 """ 

580 

581 def dec(f: Any) -> _decorators.PydanticDescriptorProxy[Any]: 

582 # auto apply the @classmethod decorator 

583 f = _decorators.ensure_classmethod_based_on_signature(f) 

584 dec_info = _decorators.ModelValidatorDecoratorInfo(mode=mode) 

585 return _decorators.PydanticDescriptorProxy(f, dec_info) 

586 

587 return dec