Skip to content

Commit

Permalink
Add support for deprecated fields
Browse files Browse the repository at this point in the history
  • Loading branch information
Viicos committed Nov 27, 2023
1 parent 7f03cfc commit edca0e1
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 1 deletion.
1 change: 1 addition & 0 deletions pydantic/_internal/_generate_schema.py
Expand Up @@ -982,6 +982,7 @@ def set_discriminator(schema: CoreSchema) -> CoreSchema:
json_schema_updates = {
'title': field_info.title,
'description': field_info.description,
'deprecated': field_info.deprecated,
'examples': to_jsonable_python(field_info.examples),
}
json_schema_updates = {k: v for k, v in json_schema_updates.items() if v is not None}
Expand Down
11 changes: 10 additions & 1 deletion pydantic/_internal/_typing_extra.py
Expand Up @@ -5,12 +5,13 @@
import sys
import types
import typing
import warnings
from collections.abc import Callable
from functools import partial
from types import GetSetDescriptorType
from typing import TYPE_CHECKING, Any, Final, ForwardRef

from typing_extensions import Annotated, Literal, TypeAliasType, TypeGuard, get_args, get_origin
from typing_extensions import Annotated, Literal, TypeAliasType, TypeGuard, deprecated, get_args, get_origin

if TYPE_CHECKING:
from ._dataclasses import StandardDataclass
Expand Down Expand Up @@ -62,6 +63,10 @@ def origin_is_union(tp: type[Any] | None) -> bool:
if hasattr(typing, 'Literal'):
LITERAL_TYPES.add(typing.Literal) # type: ignore

DEPRECATED_TYPES: set[Any] = {deprecated}
if hasattr(warnings, 'deprecated'):
DEPRECATED_TYPES.add(warnings.deprecated) # type: ignore

NONE_TYPES: tuple[Any, ...] = (None, NoneType, *(tp[None] for tp in LITERAL_TYPES))


Expand All @@ -80,6 +85,10 @@ def is_literal_type(type_: type[Any]) -> bool:
return Literal is not None and get_origin(type_) in LITERAL_TYPES


def is_deprecated_instance(instance: Any) -> bool:
return isinstance(instance, tuple(DEPRECATED_TYPES))


def literal_values(type_: type[Any]) -> tuple[Any, ...]:
return get_args(type_)

Expand Down
12 changes: 12 additions & 0 deletions pydantic/fields.py
Expand Up @@ -59,6 +59,7 @@ class _FromFieldInfoInputs(typing_extensions.TypedDict, total=False):
decimal_places: int | None
union_mode: Literal['smart', 'left_to_right'] | None
discriminator: str | types.Discriminator | None
deprecated: bool | None
json_schema_extra: JsonDict | typing.Callable[[JsonDict], None] | None
frozen: bool | None
validate_default: bool | None
Expand Down Expand Up @@ -96,6 +97,7 @@ class FieldInfo(_repr.Representation):
examples: List of examples of the field.
exclude: Whether to exclude the field from the model serialization.
discriminator: Field name or Discriminator for discriminating the type in a tagged union.
deprecated: Whether the field is marked as deprecated.
json_schema_extra: Dictionary of extra JSON schema properties.
frozen: Whether the field is frozen.
validate_default: Whether to validate the default value of the field.
Expand All @@ -117,6 +119,7 @@ class FieldInfo(_repr.Representation):
examples: list[Any] | None
exclude: bool | None
discriminator: str | types.Discriminator | None
deprecated: bool | None
json_schema_extra: JsonDict | typing.Callable[[JsonDict], None] | None
frozen: bool | None
validate_default: bool | None
Expand All @@ -138,6 +141,7 @@ class FieldInfo(_repr.Representation):
'examples',
'exclude',
'discriminator',
'deprecated',
'json_schema_extra',
'frozen',
'validate_default',
Expand Down Expand Up @@ -197,6 +201,7 @@ def __init__(self, **kwargs: Unpack[_FieldInfoInputs]) -> None:
self.examples = kwargs.pop('examples', None)
self.exclude = kwargs.pop('exclude', None)
self.discriminator = kwargs.pop('discriminator', None)
self.deprecated = kwargs.pop('deprecated', None)
self.repr = kwargs.pop('repr', True)
self.json_schema_extra = kwargs.pop('json_schema_extra', None)
self.validate_default = kwargs.pop('validate_default', None)
Expand Down Expand Up @@ -292,6 +297,8 @@ class MyModel(pydantic.BaseModel):
for a in extra_args:
if not isinstance(a, FieldInfo):
metadata.append(a)
elif _typing_extra.is_deprecated_instance(a):
new_field_info.deprecated = True
else:
metadata.extend(a.metadata)
new_field_info.metadata = metadata
Expand Down Expand Up @@ -366,6 +373,8 @@ class MyModel(pydantic.BaseModel):
for a in extra_args:
if not isinstance(a, FieldInfo):
metadata.append(a)
elif _typing_extra.is_deprecated_instance(a):
field_info.deprecated = True
else:
metadata.extend(a.metadata)
field_info.metadata = metadata
Expand Down Expand Up @@ -674,6 +683,7 @@ def Field( # noqa: C901
examples: list[Any] | None = _Unset,
exclude: bool | None = _Unset,
discriminator: str | types.Discriminator | None = _Unset,
deprecated: bool | None = _Unset,
json_schema_extra: JsonDict | typing.Callable[[JsonDict], None] | None = _Unset,
frozen: bool | None = _Unset,
validate_default: bool | None = _Unset,
Expand Down Expand Up @@ -719,6 +729,7 @@ def Field( # noqa: C901
examples: Example values for this field.
exclude: Whether to exclude the field from the model serialization.
discriminator: Field name or Discriminator for discriminating the type in a tagged union.
deprecated: Whether the field is marked as deprecated.
json_schema_extra: Any additional JSON schema data for the schema property.
frozen: Whether the field is frozen.
validate_default: Run validation that isn't only checking existence of defaults. This can be set to `True` or `False`. If not set, it defaults to `None`.
Expand Down Expand Up @@ -825,6 +836,7 @@ def Field( # noqa: C901
examples=examples,
exclude=exclude,
discriminator=discriminator,
deprecated=deprecated,
json_schema_extra=json_schema_extra,
frozen=frozen,
pattern=pattern,
Expand Down

0 comments on commit edca0e1

Please sign in to comment.