Coverage for /pythoncovmergedfiles/medio/medio/src/pydantic/pydantic/fields.py: 40%

291 statements  

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

1""" 

2Defining fields on models. 

3""" 

4from __future__ import annotations as _annotations 

5 

6import dataclasses 

7import inspect 

8import sys 

9import typing 

10from copy import copy 

11from dataclasses import Field as DataclassField 

12from typing import Any 

13from warnings import warn 

14 

15import annotated_types 

16import typing_extensions 

17 

18from . import types 

19from ._internal import _decorators, _fields, _forward_ref, _internal_dataclass, _repr, _typing_extra, _utils 

20from ._internal._fields import Undefined 

21from ._internal._generics import replace_types 

22from .errors import PydanticUserError 

23 

24if typing.TYPE_CHECKING: 

25 from pydantic_core import core_schema as _core_schema 

26 

27 from ._internal._repr import ReprArgs 

28 

29 

30class FieldInfo(_repr.Representation): 

31 """ 

32 Hold information about a field. 

33 

34 FieldInfo is used for any field definition whether or not the `Field()` function is explicitly used. 

35 

36 Attributes: 

37 annotation (type): The type annotation of the field. 

38 default (Any): The default value of the field. 

39 default_factory (callable): The factory function used to construct the default value of the field. 

40 alias (str): The alias name of the field. 

41 alias_priority (int): The priority of the field's alias. 

42 validation_alias (str): The validation alias name of the field. 

43 serialization_alias (str): The serialization alias name of the field. 

44 title (str): The title of the field. 

45 description (str): The description of the field. 

46 examples (List[str]): List of examples of the field. 

47 exclude (bool): Whether or not to exclude the field from the model schema. 

48 include (bool): Whether or not to include the field in the model schema. 

49 metadata (Dict[str, Any]): Dictionary of metadata constraints. 

50 repr (bool): Whether or not to include the field in representation of the model. 

51 discriminator (bool): Whether or not to include the field in the "discriminator" schema property of the model. 

52 json_schema_extra (Dict[str, Any]): Dictionary of extra JSON schema properties. 

53 init_var (bool): Whether or not the field should be included in the constructor of the model. 

54 kw_only (bool): Whether or not the field should be a keyword-only argument in the constructor of the model. 

55 validate_default (bool): Whether or not to validate the default value of the field. 

56 frozen (bool): Whether or not the field is frozen. 

57 final (bool): Whether or not the field is final. 

58 """ 

59 

60 # TODO: Need to add attribute annotations 

61 

62 __slots__ = ( 

63 'annotation', 

64 'default', 

65 'default_factory', 

66 'alias', 

67 'alias_priority', 

68 'validation_alias', 

69 'serialization_alias', 

70 'title', 

71 'description', 

72 'examples', 

73 'exclude', 

74 'include', 

75 'metadata', 

76 'repr', 

77 'discriminator', 

78 'json_schema_extra', 

79 'init_var', 

80 'kw_only', 

81 'validate_default', 

82 'frozen', 

83 'final', 

84 ) 

85 

86 # used to convert kwargs to metadata/constraints, 

87 # None has a special meaning - these items are collected into a `PydanticGeneralMetadata` 

88 metadata_lookup: dict[str, typing.Callable[[Any], Any] | None] = { 

89 'gt': annotated_types.Gt, 

90 'ge': annotated_types.Ge, 

91 'lt': annotated_types.Lt, 

92 'le': annotated_types.Le, 

93 'multiple_of': annotated_types.MultipleOf, 

94 'strict': types.Strict, 

95 'min_length': annotated_types.MinLen, 

96 'max_length': annotated_types.MaxLen, 

97 'pattern': None, 

98 'allow_inf_nan': None, 

99 'max_digits': None, 

100 'decimal_places': None, 

101 } 

102 

103 def __init__(self, **kwargs: Any) -> None: 

104 # TODO: This is a good place to add migration warnings; we should use overload for type-hinting the signature 

105 self.annotation, annotation_metadata = self._extract_metadata(kwargs.get('annotation')) 

106 

107 default = kwargs.pop('default', Undefined) 

108 if default is Ellipsis: 

109 self.default = Undefined 

110 else: 

111 self.default = default 

112 

113 self.default_factory = kwargs.get('default_factory') 

114 

115 if self.default is not Undefined and self.default_factory is not None: 

116 raise TypeError('cannot specify both default and default_factory') 

117 

118 self.alias = kwargs.get('alias') 

119 self.alias_priority = kwargs.get('alias_priority') or 2 if self.alias is not None else None 

120 self.title = kwargs.get('title') 

121 self.validation_alias = kwargs.get('validation_alias', None) 

122 self.serialization_alias = kwargs.get('serialization_alias', None) 

123 self.description = kwargs.get('description') 

124 self.examples = kwargs.get('examples') 

125 self.exclude = kwargs.get('exclude') 

126 self.include = kwargs.get('include') 

127 self.metadata = self._collect_metadata(kwargs) + annotation_metadata 

128 self.discriminator = kwargs.get('discriminator') 

129 self.repr = kwargs.get('repr', True) 

130 self.json_schema_extra = kwargs.get('json_schema_extra') 

131 self.validate_default = kwargs.get('validate_default', None) 

132 self.frozen = kwargs.get('frozen', None) 

133 self.final = kwargs.get('final', None) 

134 # currently only used on dataclasses 

135 self.init_var = kwargs.get('init_var', None) 

136 self.kw_only = kwargs.get('kw_only', None) 

137 

138 @classmethod 

139 def from_field(cls, default: Any = Undefined, **kwargs: Any) -> FieldInfo: 

140 """ 

141 Create a new `FieldInfo` object with the `Field` function. 

142 

143 Args: 

144 default (Any): The default value for the field. Defaults to Undefined. 

145 **kwargs: Additional arguments dictionary. 

146 

147 Raises: 

148 TypeError: If 'annotation' is passed as a keyword argument. 

149 

150 Returns: 

151 FieldInfo: A new FieldInfo object with the given parameters. 

152 

153 Examples: 

154 This is how you can create a field with default value like this: 

155 

156 ```python 

157 import pydantic 

158 

159 class MyModel(pydantic.BaseModel): 

160 foo: int = pydantic.Field(4, ...) 

161 ``` 

162 """ 

163 # TODO: This is a good place to add migration warnings; should we use overload for type-hinting the signature? 

164 if 'annotation' in kwargs: 

165 raise TypeError('"annotation" is not permitted as a Field keyword argument') 

166 return cls(default=default, **kwargs) 

167 

168 @classmethod 

169 def from_annotation(cls, annotation: type[Any] | _forward_ref.PydanticForwardRef) -> FieldInfo: 

170 """ 

171 Creates a `FieldInfo` instance from a bare annotation. 

172 

173 Args: 

174 annotation (Union[type[Any], _forward_ref.PydanticForwardRef]): An annotation object. 

175 

176 Returns: 

177 FieldInfo: An instance of the field metadata. 

178 

179 Examples: 

180 This is how you can create a field from a bare annotation like this: 

181 

182 ```python 

183 import pydantic 

184 class MyModel(pydantic.BaseModel): 

185 foo: int # <-- like this 

186 ``` 

187 

188 We also account for the case where the annotation can be an instance of `Annotated` and where 

189 one of the (not first) arguments in `Annotated` are an instance of `FieldInfo`, e.g.: 

190 

191 ```python 

192 import pydantic, annotated_types, typing 

193 

194 class MyModel(pydantic.BaseModel): 

195 foo: typing.Annotated[int, annotated_types.Gt(42)] 

196 bar: typing.Annotated[int, Field(gt=42)] 

197 ``` 

198 

199 """ 

200 final = False 

201 if _typing_extra.is_finalvar(annotation): 

202 final = True 

203 if annotation is not typing_extensions.Final: 

204 annotation = typing_extensions.get_args(annotation)[0] 

205 

206 if _typing_extra.is_annotated(annotation): 

207 first_arg, *extra_args = typing_extensions.get_args(annotation) 

208 if _typing_extra.is_finalvar(first_arg): 

209 final = True 

210 field_info = cls._find_field_info_arg(extra_args) 

211 if field_info: 

212 new_field_info = copy(field_info) 

213 new_field_info.annotation = first_arg 

214 new_field_info.final = final 

215 new_field_info.metadata += [a for a in extra_args if not isinstance(a, FieldInfo)] 

216 return new_field_info 

217 

218 return cls(annotation=annotation, final=final) 

219 

220 @classmethod 

221 def from_annotated_attribute(cls, annotation: type[Any], default: Any) -> FieldInfo: 

222 """ 

223 Create `FieldInfo` from an annotation with a default value. 

224 

225 Args: 

226 annotation (type[Any]): The type annotation of the field. 

227 default (Any): The default value of the field. 

228 

229 Returns: 

230 FieldInfo: A field object with the passed values. 

231 

232 Examples: 

233 ```python 

234 import pydantic, annotated_types, typing 

235 

236 class MyModel(pydantic.BaseModel): 

237 foo: int = 4 # <-- like this 

238 bar: typing.Annotated[int, annotated_types.Gt(4)] = 4 # <-- or this 

239 spam: typing.Annotated[int, pydantic.Field(gt=4)] = 4 # <-- or this 

240 ``` 

241 """ 

242 final = False 

243 if _typing_extra.is_finalvar(annotation): 

244 final = True 

245 if annotation is not typing_extensions.Final: 

246 annotation = typing_extensions.get_args(annotation)[0] 

247 

248 if isinstance(default, cls): 

249 default.annotation, annotation_metadata = cls._extract_metadata(annotation) 

250 default.metadata += annotation_metadata 

251 default.final = final 

252 return default 

253 elif isinstance(default, dataclasses.Field): 

254 init_var = False 

255 if annotation is dataclasses.InitVar: 

256 if sys.version_info < (3, 8): 

257 raise RuntimeError('InitVar is not supported in Python 3.7 as type information is lost') 

258 

259 init_var = True 

260 annotation = Any 

261 elif isinstance(annotation, dataclasses.InitVar): 

262 init_var = True 

263 annotation = annotation.type 

264 pydantic_field = cls._from_dataclass_field(default) 

265 pydantic_field.annotation, annotation_metadata = cls._extract_metadata(annotation) 

266 pydantic_field.metadata += annotation_metadata 

267 pydantic_field.final = final 

268 pydantic_field.init_var = init_var 

269 pydantic_field.kw_only = getattr(default, 'kw_only', None) 

270 return pydantic_field 

271 else: 

272 if _typing_extra.is_annotated(annotation): 

273 first_arg, *extra_args = typing_extensions.get_args(annotation) 

274 field_info = cls._find_field_info_arg(extra_args) 

275 if field_info is not None: 

276 if not field_info.is_required(): 

277 raise TypeError('Default may not be specified twice on the same field') 

278 new_field_info = copy(field_info) 

279 new_field_info.default = default 

280 new_field_info.annotation = first_arg 

281 new_field_info.metadata += [a for a in extra_args if not isinstance(a, FieldInfo)] 

282 return new_field_info 

283 

284 return cls(annotation=annotation, default=default, final=final) 

285 

286 @classmethod 

287 def _from_dataclass_field(cls, dc_field: DataclassField[Any]) -> FieldInfo: 

288 """ 

289 Return a new `FieldInfo` instance from a `dataclasses.Field` instance. 

290 

291 Args: 

292 dc_field (dataclasses.Field): The `dataclasses.Field` instance to convert. 

293 

294 Returns: 

295 FieldInfo: The corresponding `FieldInfo` instance. 

296 

297 Raises: 

298 TypeError: If any of the `FieldInfo` kwargs does not match the `dataclass.Field` kwargs. 

299 """ 

300 default = dc_field.default 

301 if default is dataclasses.MISSING: 

302 default = Undefined 

303 

304 if dc_field.default_factory is dataclasses.MISSING: 

305 default_factory: typing.Callable[[], Any] | None = None 

306 else: 

307 default_factory = dc_field.default_factory 

308 

309 # use the `Field` function so in correct kwargs raise the correct `TypeError` 

310 field = Field(default=default, default_factory=default_factory, repr=dc_field.repr, **dc_field.metadata) 

311 

312 field.annotation, annotation_metadata = cls._extract_metadata(dc_field.type) 

313 field.metadata += annotation_metadata 

314 return field 

315 

316 @classmethod 

317 def _extract_metadata(cls, annotation: type[Any] | None) -> tuple[type[Any] | None, list[Any]]: 

318 """Tries to extract metadata/constraints from an annotation if it uses `Annotated`. 

319 

320 Args: 

321 annotation (type[Any] | None): The type hint annotation for which metadata has to be extracted. 

322 

323 Returns: 

324 tuple[type[Any] | None, list[Any]]: A tuple containing the extracted metadata type and the list 

325 of extra arguments. 

326 

327 Raises: 

328 TypeError: If a `Field` is used twice on the same field. 

329 """ 

330 if annotation is not None: 

331 if _typing_extra.is_annotated(annotation): 

332 first_arg, *extra_args = typing_extensions.get_args(annotation) 

333 if cls._find_field_info_arg(extra_args): 

334 raise TypeError('Field may not be used twice on the same field') 

335 return first_arg, list(extra_args) 

336 

337 return annotation, [] 

338 

339 @staticmethod 

340 def _find_field_info_arg(args: Any) -> FieldInfo | None: 

341 """ 

342 Find an instance of `FieldInfo` in the provided arguments. 

343 

344 Args: 

345 args (Any): The argument list to search for `FieldInfo`. 

346 

347 Returns: 

348 FieldInfo | None: An instance of `FieldInfo` if found, otherwise `None`. 

349 """ 

350 return next((a for a in args if isinstance(a, FieldInfo)), None) 

351 

352 @classmethod 

353 def _collect_metadata(cls, kwargs: dict[str, Any]) -> list[Any]: 

354 """ 

355 Collect annotations from kwargs. 

356 

357 The return type is actually `annotated_types.BaseMetadata | PydanticMetadata`, 

358 but it gets combined with `list[Any]` from `Annotated[T, ...]`, hence types. 

359 

360 Args: 

361 kwargs (dict[str, Any]): Keyword arguments passed to the function. 

362 

363 Returns: 

364 list[Any]: A list of metadata objects - a combination of `annotated_types.BaseMetadata` and 

365 `PydanticMetadata`. 

366 """ 

367 metadata: list[Any] = [] 

368 general_metadata = {} 

369 for key, value in list(kwargs.items()): 

370 try: 

371 marker = cls.metadata_lookup[key] 

372 except KeyError: 

373 continue 

374 

375 del kwargs[key] 

376 if value is not None: 

377 if marker is None: 

378 general_metadata[key] = value 

379 else: 

380 metadata.append(marker(value)) 

381 if general_metadata: 

382 metadata.append(_fields.PydanticGeneralMetadata(**general_metadata)) 

383 return metadata 

384 

385 def get_default(self, *, call_default_factory: bool = False) -> Any: 

386 """ 

387 Get the default value. 

388 

389 We expose an option for whether to call the default_factory (if present), as calling it may 

390 result in side effects that we want to avoid. However, there are times when it really should 

391 be called (namely, when instantiating a model via `model_construct`). 

392 

393 Args: 

394 call_default_factory (bool, optional): Whether to call the default_factory or not. Defaults to False. 

395 

396 Returns: 

397 Any: The default value, calling the default factory if requested or `None` if not set. 

398 """ 

399 if self.default_factory is None: 

400 return _utils.smart_deepcopy(self.default) 

401 elif call_default_factory: 

402 return self.default_factory() 

403 else: 

404 return None 

405 

406 def is_required(self) -> bool: 

407 """Check if the argument is required. 

408 

409 Returns: 

410 bool: `True` if the argument is required, `False` otherwise. 

411 """ 

412 return self.default is Undefined and self.default_factory is None 

413 

414 def rebuild_annotation(self) -> Any: 

415 """ 

416 Rebuild the original annotation for use in signatures. 

417 """ 

418 if not self.metadata: 

419 return self.annotation 

420 else: 

421 return typing_extensions._AnnotatedAlias(self.annotation, self.metadata) 

422 

423 def apply_typevars_map(self, typevars_map: dict[Any, Any] | None, types_namespace: dict[str, Any] | None) -> None: 

424 """ 

425 Apply a typevars_map to the annotation. 

426 

427 This is used when analyzing parametrized generic types to replace typevars with their concrete types. 

428 

429 See pydantic._internal._generics.replace_types for more details. 

430 """ 

431 annotation = _typing_extra.eval_type_lenient(self.annotation, types_namespace, None) 

432 self.annotation = replace_types(annotation, typevars_map) 

433 

434 def __repr_args__(self) -> ReprArgs: 

435 yield 'annotation', _repr.PlainRepr(_repr.display_as_type(self.annotation)) 

436 yield 'required', self.is_required() 

437 

438 for s in self.__slots__: 

439 if s == 'annotation': 

440 continue 

441 elif s == 'metadata' and not self.metadata: 

442 continue 

443 elif s == 'repr' and self.repr is True: 

444 continue 

445 elif s == 'final': 

446 continue 

447 if s == 'frozen' and self.frozen is False: 

448 continue 

449 if s == 'validation_alias' and self.validation_alias == self.alias: 

450 continue 

451 if s == 'serialization_alias' and self.serialization_alias == self.alias: 

452 continue 

453 if s == 'default_factory' and self.default_factory is not None: 

454 yield 'default_factory', _repr.PlainRepr(_repr.display_as_type(self.default_factory)) 

455 else: 

456 value = getattr(self, s) 

457 if value is not None and value is not Undefined: 

458 yield s, value 

459 

460 

461@_internal_dataclass.slots_dataclass 

462class AliasPath: 

463 path: list[int | str] 

464 

465 def __init__(self, first_arg: str, *args: str | int) -> None: 

466 self.path = [first_arg] + list(args) 

467 

468 def convert_to_aliases(self) -> list[str | int]: 

469 return self.path 

470 

471 

472@_internal_dataclass.slots_dataclass 

473class AliasChoices: 

474 choices: list[str | AliasPath] 

475 

476 def __init__(self, *args: str | AliasPath) -> None: 

477 self.choices = list(args) 

478 

479 def convert_to_aliases(self) -> list[list[str | int]]: 

480 aliases: list[list[str | int]] = [] 

481 for c in self.choices: 

482 if isinstance(c, AliasPath): 

483 aliases.append(c.convert_to_aliases()) 

484 else: 

485 aliases.append([c]) 

486 return aliases 

487 

488 

489def Field( # noqa C901 

490 default: Any = Undefined, 

491 *, 

492 default_factory: typing.Callable[[], Any] | None = None, 

493 alias: str | None = None, 

494 alias_priority: int | None = None, 

495 validation_alias: str | AliasPath | AliasChoices | None = None, 

496 serialization_alias: str | None = None, 

497 title: str | None = None, 

498 description: str | None = None, 

499 examples: list[Any] | None = None, 

500 exclude: typing.AbstractSet[int | str] | typing.Mapping[int | str, Any] | Any = None, 

501 include: typing.AbstractSet[int | str] | typing.Mapping[int | str, Any] | Any = None, 

502 gt: float | None = None, 

503 ge: float | None = None, 

504 lt: float | None = None, 

505 le: float | None = None, 

506 multiple_of: float | None = None, 

507 allow_inf_nan: bool | None = None, 

508 max_digits: int | None = None, 

509 decimal_places: int | None = None, 

510 min_items: int | None = None, 

511 max_items: int | None = None, 

512 min_length: int | None = None, 

513 max_length: int | None = None, 

514 frozen: bool = False, 

515 pattern: str | None = None, 

516 discriminator: str | None = None, 

517 repr: bool = True, 

518 strict: bool | None = None, 

519 json_schema_extra: dict[str, Any] | None = None, 

520 validate_default: bool | None = None, 

521 const: bool | None = None, 

522 unique_items: bool | None = None, 

523 allow_mutation: bool = True, 

524 regex: str | None = None, 

525 **extra: Any, 

526) -> Any: 

527 """ 

528 Create a field for objects that can be configured. 

529 

530 Used to provide extra information about a field, either for the model schema or complex validation. Some arguments 

531 apply only to number fields (`int`, `float`, `Decimal`) and some apply only to `str`. 

532 

533 Args: 

534 default (Any, optional): default value if the field is not set. 

535 default_factory (callable, optional): A callable to generate the default value like :func:`~datetime.utcnow`. 

536 alias (str, optional): an alternative name for the attribute. 

537 alias_priority (int, optional): priority of the alias. This defines which alias should be used in serialization. 

538 validation_alias (str, list of str, list of list of str, optional): 'whitelist' validation step. The field 

539 will be the single one allowed by the alias or set of aliases defined. 

540 serialization_alias (str, optional): 'blacklist' validation step. The vanilla field will be the single one of 

541 the alias' or set of aliases' fields and all the other fields will be ignored at serialization time. 

542 title (str, optional): human-readable title. 

543 description (str, optional): human-readable description. 

544 examples (list[Any], optional): An example value for this field. 

545 exclude (Union[AbstractSet[Union[str, int]], Mapping[Union[str, int], Any], Any]): 

546 Parameters that should be excluded from the field. If `None`, default 

547 Pydantic behaviors are used. 

548 include (Union[AbstractSet[Union[str, int]], Mapping[Union[str, int], Any], Any]): 

549 Parameters that should be included in the field. If `None`, default 

550 Pydantic behaviors are used. 

551 gt (float, optional): Greater than. If set, value must be greater than this. Only applicable to numbers. 

552 ge (float, optional): Greater than or equal. If set, value must be 

553 greater than or equal to this. Only applicable to numbers. 

554 lt (float, optional): Less than. If set, value must be 

555 less than this. Only applicable to numbers. 

556 le (float, optional): Less than or equal. If set, value must be 

557 less than or equal to this. Only applicable to numbers. 

558 multiple_of (float, optional): Value must be a multiple of this. Only applicable to numbers. 

559 allow_inf_nan (bool, optional): Allow `inf`, `-inf`, `nan`. Only applicable to numbers. 

560 max_digits (int, optional): Maximum number of allow digits for strings. 

561 decimal_places (int, optional): Maximum number decimal places allowed for numbers. 

562 min_items (int, optional): Minimum number of items in a collection. 

563 max_items (int, optional): Maximum number of items in a collection. 

564 min_length (int, optional): Minimum length for strings. 

565 max_length (int, optional): Maximum length for strings. 

566 frozen (bool, optional): Store the value as a frozen object if is mutable. 

567 pattern (str, optional): Pattern for strings. 

568 discriminator (str, optional): Codename for discriminating a field among others of the same type. 

569 repr (bool, optional): If `True` (the default), return a string representation of the field. 

570 strict (bool, optional): If `True` (the default is `None`), the field should be validated strictly. 

571 json_schema_extra (dict[str, Any]): Any other additional JSON schema data for the schema property. 

572 validate_default (bool, optional): Run validation that isn't only checking existence of defaults. This is 

573 `True` by default. 

574 const (bool, optional): Value is always the same literal object. This is typically a singleton object, 

575 such as `True` or `None`. 

576 unique_items (bool, optional): Require that collection items be unique. 

577 allow_mutation (bool, optional): If `False`, the dataclass will be frozen (made immutable). 

578 regex (str, optional): Regular expression pattern that the field must match against. 

579 

580 

581 Returns: 

582 Any: return the generated field object. 

583 """ 

584 # Check deprecated & removed params of V1. 

585 # This has to be removed deprecation period over. 

586 if const: 

587 raise PydanticUserError('`const` is removed. use `Literal` instead', code='deprecated_kwargs') 

588 if min_items: 

589 warn('`min_items` is deprecated and will be removed. use `min_length` instead', DeprecationWarning) 

590 if min_length is None: 

591 min_length = min_items 

592 if max_items: 

593 warn('`max_items` is deprecated and will be removed. use `max_length` instead', DeprecationWarning) 

594 if max_length is None: 

595 max_length = max_items 

596 if unique_items: 

597 raise PydanticUserError( 

598 ( 

599 '`unique_items` is removed, use `Set` instead' 

600 '(this feature is discussed in https://github.com/pydantic/pydantic-core/issues/296)' 

601 ), 

602 code='deprecated_kwargs', 

603 ) 

604 if allow_mutation is False: 

605 warn('`allow_mutation` is deprecated and will be removed. use `frozen` instead', DeprecationWarning) 

606 frozen = True 

607 if regex: 

608 raise PydanticUserError('`regex` is removed. use `Pattern` instead', code='deprecated_kwargs') 

609 if extra: 

610 warn( 

611 'Extra keyword arguments on `Field` is deprecated and will be removed. use `json_schema_extra` instead', 

612 DeprecationWarning, 

613 ) 

614 if not json_schema_extra: 

615 json_schema_extra = extra 

616 

617 converted_validation_alias: str | list[str | int] | list[list[str | int]] | None = None 

618 if validation_alias: 

619 if not isinstance(validation_alias, (str, AliasChoices, AliasPath)): 

620 raise TypeError('Invalid `validation_alias` type. it should be `str`, `AliasChoices`, or `AliasPath`') 

621 

622 if isinstance(validation_alias, (AliasChoices, AliasPath)): 

623 converted_validation_alias = validation_alias.convert_to_aliases() 

624 else: 

625 converted_validation_alias = validation_alias 

626 

627 if serialization_alias is None and isinstance(alias, str): 

628 serialization_alias = alias 

629 

630 return FieldInfo.from_field( 

631 default, 

632 default_factory=default_factory, 

633 alias=alias, 

634 alias_priority=alias_priority, 

635 validation_alias=converted_validation_alias or alias, 

636 serialization_alias=serialization_alias, 

637 title=title, 

638 description=description, 

639 examples=examples, 

640 exclude=exclude, 

641 include=include, 

642 gt=gt, 

643 ge=ge, 

644 lt=lt, 

645 le=le, 

646 multiple_of=multiple_of, 

647 allow_inf_nan=allow_inf_nan, 

648 max_digits=max_digits, 

649 decimal_places=decimal_places, 

650 min_items=min_items, 

651 max_items=max_items, 

652 min_length=min_length, 

653 max_length=max_length, 

654 frozen=frozen, 

655 pattern=pattern, 

656 discriminator=discriminator, 

657 repr=repr, 

658 json_schema_extra=json_schema_extra, 

659 strict=strict, 

660 validate_default=validate_default, 

661 ) 

662 

663 

664class ModelPrivateAttr(_repr.Representation): 

665 """A descriptor for private attributes in class models. 

666 

667 Attributes: 

668 default (Any): The default value of the attribute if not provided. 

669 default_factory (typing.Callable[[], Any]): A callable function that generates the default value of the 

670 attribute if not provided. 

671 """ 

672 

673 __slots__ = 'default', 'default_factory' 

674 

675 def __init__(self, default: Any = Undefined, *, default_factory: typing.Callable[[], Any] | None = None) -> None: 

676 self.default = default 

677 self.default_factory = default_factory 

678 

679 def __set_name__(self, cls: type[Any], name: str) -> None: 

680 """ 

681 preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487 

682 """ 

683 if self.default is not Undefined: 

684 try: 

685 set_name = getattr(self.default, '__set_name__') 

686 except AttributeError: 

687 pass 

688 else: 

689 if callable(set_name): 

690 set_name(cls, name) 

691 

692 def get_default(self) -> Any: 

693 """Returns the default value for the object. 

694 

695 If `self.default_factory` is `None`, the method will return a deep copy of the `self.default` object. 

696 If `self.default_factory` is not `None`, it will call `self.default_factory` and return the value returned. 

697 

698 Returns: 

699 Any: The default value of the object. 

700 """ 

701 return _utils.smart_deepcopy(self.default) if self.default_factory is None else self.default_factory() 

702 

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

704 return isinstance(other, self.__class__) and (self.default, self.default_factory) == ( 

705 other.default, 

706 other.default_factory, 

707 ) 

708 

709 

710def PrivateAttr( 

711 default: Any = Undefined, 

712 *, 

713 default_factory: typing.Callable[[], Any] | None = None, 

714) -> Any: 

715 """ 

716 Indicates that attribute is only used internally and never mixed with regular fields. 

717 

718 Private attributes are not checked by Pydantic, so it's up to you to maintain their accuracy. 

719 

720 Private attributes are stored in the model `__slots__`. 

721 

722 Args: 

723 default (Any): The attribute's default value. Defaults to Undefined. 

724 default_factory (typing.Callable[[], Any], optional): Callable that will be 

725 called when a default value is needed for this attribute. 

726 If both `default` and `default_factory` are set, an error will be raised. 

727 

728 Returns: 

729 Any: An instance of `ModelPrivateAttr` class. 

730 

731 Raises: 

732 ValueError: If both `default` and `default_factory` are set. 

733 """ 

734 if default is not Undefined and default_factory is not None: 

735 raise TypeError('cannot specify both default and default_factory') 

736 

737 return ModelPrivateAttr( 

738 default, 

739 default_factory=default_factory, 

740 ) 

741 

742 

743@_internal_dataclass.slots_dataclass 

744class ComputedFieldInfo: 

745 """ 

746 A container for data from `@computed_field` so that we can access it 

747 while building the pydantic-core schema. 

748 """ 

749 

750 decorator_repr: typing.ClassVar[str] = '@computed_field' 

751 wrapped_property: property 

752 json_return_type: _core_schema.JsonReturnTypes | None 

753 alias: str | None 

754 title: str | None 

755 description: str | None 

756 repr: bool 

757 

758 

759# this should really be `property[T], cached_proprety[T]` but property is not generic unlike cached_property 

760# See https://github.com/python/typing/issues/985 and linked issues 

761PropertyT = typing.TypeVar('PropertyT') 

762 

763 

764@typing.overload 

765def computed_field( 

766 *, 

767 json_return_type: _core_schema.JsonReturnTypes | None = None, 

768 alias: str | None = None, 

769 title: str | None = None, 

770 description: str | None = None, 

771 repr: bool = True, 

772) -> typing.Callable[[PropertyT], PropertyT]: 

773 ... 

774 

775 

776@typing.overload 

777def computed_field(__func: PropertyT) -> PropertyT: 

778 ... 

779 

780 

781def computed_field( 

782 __f: PropertyT | None = None, 

783 *, 

784 alias: str | None = None, 

785 title: str | None = None, 

786 description: str | None = None, 

787 repr: bool = True, 

788 json_return_type: _core_schema.JsonReturnTypes | None = None, 

789) -> PropertyT | typing.Callable[[PropertyT], PropertyT]: 

790 """ 

791 Decorate to include `property` and `cached_property` when serialising models. 

792 

793 If applied to functions not yet decorated with `@property` or `@cached_property`, the function is 

794 automatically wrapped with `property`. 

795 

796 Args: 

797 __f: the function to wrap. 

798 alias: alias to use when serializing this computed field, only used when `by_alias=True` 

799 title: Title to used when including this computed field in JSON Schema, currently unused waiting for #4697 

800 description: Description to used when including this computed field in JSON Schema, defaults to the functions 

801 docstring, currently unused waiting for #4697 

802 repr: whether to include this computed field in model repr 

803 json_return_type: optional return for serialization logic to expect when serialising to JSON, if included 

804 this must be correct, otherwise a `TypeError` is raised 

805 

806 Returns: 

807 A proxy wrapper for the property. 

808 """ 

809 

810 def dec(f: Any) -> Any: 

811 nonlocal description 

812 if description is None and f.__doc__: 

813 description = inspect.cleandoc(f.__doc__) 

814 

815 # if the function isn't already decorated with `@property` (or another descriptor), then we wrap it now 

816 f = _decorators.ensure_property(f) 

817 dec_info = ComputedFieldInfo(f, json_return_type, alias, title, description, repr) 

818 return _decorators.PydanticDescriptorProxy(f, dec_info) 

819 

820 if __f is None: 

821 return dec 

822 else: 

823 return dec(__f)