From c7cb58def2278e6ba1329ceb467643c6c018b578 Mon Sep 17 00:00:00 2001 From: Piotr Szyma Date: Fri, 27 Jan 2023 20:50:48 +0100 Subject: [PATCH] feat: update for StrOrPromise in typeddjango/django-stubs --- rest_framework-stubs/fields.pyi | 171 ++++++++++++++------------- rest_framework-stubs/serializers.pyi | 23 ++-- tests/typecheck/test_fields.yml | 6 +- 3 files changed, 101 insertions(+), 99 deletions(-) diff --git a/rest_framework-stubs/fields.pyi b/rest_framework-stubs/fields.pyi index 0bc5bdf97..886960f55 100644 --- a/rest_framework-stubs/fields.pyi +++ b/rest_framework-stubs/fields.pyi @@ -12,6 +12,7 @@ from _typeshed import Self from django.core.files.base import File from django.db import models from django.forms import ImageField as DjangoImageField # noqa: F401 +from django_stubs_ext import StrOrPromise from rest_framework.serializers import BaseSerializer from rest_framework.validators import Validator from typing_extensions import Final, TypeAlias @@ -38,9 +39,9 @@ class SkipField(Exception): ... class Option(Protocol): start_option_group: bool end_option_group: bool - label: str + label: StrOrPromise value: str - display_text: str + display_text: StrOrPromise def is_simple_callable(obj: Callable) -> bool: ... def get_attribute(instance: Any, attrs: list[str] | None) -> Any: ... @@ -48,7 +49,7 @@ def set_value(dictionary: MutableMapping[str, Any], keys: Sequence[str], value: def to_choices_dict(choices: Iterable[Any]) -> OrderedDict: ... def flatten_choices_dict(choices: dict[Any, Any]) -> OrderedDict: ... def iter_options( - grouped_choices: OrderedDict, cutoff: int | None = ..., cutoff_text: str | None = ... + grouped_choices: OrderedDict, cutoff: int | None = ..., cutoff_text: StrOrPromise | None = ... ) -> Generator[Option, None, None]: ... def get_error_detail(exc_info: Any) -> Any: ... @@ -73,13 +74,13 @@ class Field(Generic[_VT, _DT, _RP, _IN]): allow_null: bool default: _VT | None default_empty_html: Any - default_error_messages: dict[str, str] + default_error_messages: dict[str, StrOrPromise] default_validators: list[Validator[_VT]] - error_messages: dict[str, str] + error_messages: dict[str, StrOrPromise] field_name: str | None - help_text: str | None + help_text: StrOrPromise | None initial: _VT | Callable[[], _VT] | None - label: str | None + label: StrOrPromise | None parent: BaseSerializer read_only: bool required: bool @@ -95,10 +96,10 @@ class Field(Generic[_VT, _DT, _RP, _IN]): default: _DefaultInitial[_VT] = ..., initial: _DefaultInitial[_VT] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[_VT]] | None = ..., allow_null: bool = ..., ): ... @@ -160,13 +161,13 @@ class CharField(Field[str, str, str, Any]): read_only: bool = ..., write_only: bool = ..., required: bool = ..., - default: _DefaultInitial[str] = ..., + default: _DefaultInitial[StrOrPromise] = ..., initial: _DefaultInitial[str] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[str]] | None = ..., allow_null: bool = ..., allow_blank: bool = ..., @@ -185,13 +186,13 @@ class RegexField(CharField): read_only: bool = ..., write_only: bool = ..., required: bool = ..., - default: _DefaultInitial[str] = ..., + default: _DefaultInitial[StrOrPromise] = ..., initial: _DefaultInitial[str] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[str]] | None = ..., allow_null: bool = ..., allow_blank: bool = ..., @@ -209,13 +210,13 @@ class SlugField(CharField): read_only: bool = ..., write_only: bool = ..., required: bool = ..., - default: _DefaultInitial[str] = ..., + default: _DefaultInitial[StrOrPromise] = ..., initial: _DefaultInitial[str] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[str]] | None = ..., allow_null: bool = ..., allow_blank: bool = ..., @@ -239,10 +240,10 @@ class UUIDField(Field[uuid.UUID, uuid.UUID | str | int, str, Any]): default: _DefaultInitial[uuid.UUID] = ..., initial: _DefaultInitial[uuid.UUID] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[uuid.UUID]] | None = ..., allow_null: bool = ..., ): ... @@ -260,10 +261,10 @@ class IPAddressField(CharField): default: _DefaultInitial[str] = ..., initial: _DefaultInitial[str] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[str]] | None = ..., allow_null: bool = ..., allow_blank: bool = ..., @@ -288,10 +289,10 @@ class IntegerField(Field[int, float | int | str, int, Any]): default: _DefaultInitial[int] = ..., initial: _DefaultInitial[int] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[int]] | None = ..., allow_null: bool = ..., ): ... @@ -312,10 +313,10 @@ class FloatField(Field[float, float | int | str, str, Any]): default: _DefaultInitial[float] = ..., initial: _DefaultInitial[float] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[float]] | None = ..., allow_null: bool = ..., ): ... @@ -347,10 +348,10 @@ class DecimalField(Field[Decimal, int | float | str | Decimal, str, Any]): default: _DefaultInitial[Decimal] = ..., initial: _DefaultInitial[Decimal] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[Decimal]] | None = ..., allow_null: bool = ..., ): ... @@ -373,10 +374,10 @@ class DateTimeField(Field[datetime.datetime, datetime.datetime | str, str, Any]) default: _DefaultInitial[datetime.datetime] = ..., initial: _DefaultInitial[datetime.datetime] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[datetime.datetime]] | None = ..., allow_null: bool = ..., ): ... @@ -397,10 +398,10 @@ class DateField(Field[datetime.date, datetime.date | str, str, Any]): default: _DefaultInitial[datetime.date] = ..., initial: _DefaultInitial[datetime.date] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[datetime.date]] | None = ..., allow_null: bool = ..., ): ... @@ -419,10 +420,10 @@ class TimeField(Field[datetime.time, datetime.time | str, str, Any]): default: _DefaultInitial[datetime.time] = ..., initial: _DefaultInitial[datetime.time] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[datetime.time]] | None = ..., allow_null: bool = ..., ): ... @@ -441,17 +442,17 @@ class DurationField(Field[datetime.timedelta, datetime.timedelta | str, str, Any default: _DefaultInitial[datetime.timedelta] = ..., initial: _DefaultInitial[datetime.timedelta] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[datetime.timedelta]] | None = ..., allow_null: bool = ..., ): ... class ChoiceField(Field[str, str | int | tuple[str | int, str | int | tuple], str, Any]): html_cutoff: int | None - html_cutoff_text: str | None + html_cutoff_text: StrOrPromise | None allow_blank: bool grouped_choices: OrderedDict choice_strings_to_values: dict[str, Any] @@ -463,17 +464,17 @@ class ChoiceField(Field[str, str | int | tuple[str | int, str | int | tuple], st read_only: bool = ..., write_only: bool = ..., required: bool = ..., - default: _DefaultInitial[str | int] = ..., + default: _DefaultInitial[StrOrPromise | int] = ..., initial: _DefaultInitial[str | int] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[Any]] | None = ..., allow_null: bool = ..., html_cutoff: int = ..., - html_cutoff_text: str = ..., + html_cutoff_text: StrOrPromise = ..., allow_blank: bool = ..., ): ... def iter_options(self) -> Iterable[Option]: ... @@ -498,16 +499,16 @@ class MultipleChoiceField( write_only: bool = ..., required: bool = ..., default: _DefaultInitial[set[str | int] | set[str] | set[int]] = ..., - initial: _DefaultInitial[set[str | int] | set[str] | set[int]] = ..., + initial: _DefaultInitial[set[StrOrPromise | int] | set[StrOrPromise] | set[int]] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[Any]] | None = ..., allow_null: bool = ..., html_cutoff: int = ..., - html_cutoff_text: str = ..., + html_cutoff_text: StrOrPromise = ..., allow_blank: bool = ..., allow_empty: bool = ..., ): ... @@ -526,14 +527,14 @@ class FilePathField(ChoiceField): default: _DefaultInitial[str] = ..., initial: _DefaultInitial[str] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[Any]] | None = ..., allow_null: bool = ..., html_cutoff: int = ..., - html_cutoff_text: str = ..., + html_cutoff_text: StrOrPromise = ..., allow_blank: bool = ..., ): ... @@ -550,10 +551,10 @@ class FileField(Field[File, File, str | None, Any]): # this field can return No default: _DefaultInitial[File] = ..., initial: _DefaultInitial[File] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[File]] | None = ..., allow_null: bool = ..., max_length: int = ..., @@ -572,10 +573,10 @@ class ImageField(FileField): default: _DefaultInitial[File] = ..., initial: _DefaultInitial[File] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[File]] | None = ..., allow_null: bool = ..., max_length: int = ..., @@ -599,10 +600,10 @@ class ListField(Field[list[Any], list[Any], list[Any], Any]): default: _DefaultInitial[list[Any]] = ..., initial: _DefaultInitial[list[Any]] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[list[Any]]] | None = ..., allow_null: bool = ..., *, @@ -624,10 +625,10 @@ class DictField(Field[dict[Any, Any], dict[Any, Any], dict[Any, Any], Any]): default: _DefaultInitial[dict[Any, Any]] = ..., initial: _DefaultInitial[dict[Any, Any]] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[dict[Any, Any]]] | None = ..., allow_null: bool = ..., *, @@ -651,10 +652,10 @@ class JSONField(Field[dict[str, Any] | list[dict[str, Any]], dict[str, Any] | li default: _DefaultInitial[Mapping[Any, Any]] = ..., initial: _DefaultInitial[Mapping[Any, Any]] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[Any]] | None = ..., allow_null: bool = ..., *, @@ -678,10 +679,10 @@ class SerializerMethodField(Field): default: Any = ..., initial: Any = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[Any]] | None = ..., allow_null: bool = ..., ): ... @@ -699,10 +700,10 @@ class ModelField(Field): default: Any = ..., initial: Any = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[Any]] | None = ..., allow_null: bool = ..., max_length: int = ..., diff --git a/rest_framework-stubs/serializers.pyi b/rest_framework-stubs/serializers.pyi index b486dd156..03c0201f5 100644 --- a/rest_framework-stubs/serializers.pyi +++ b/rest_framework-stubs/serializers.pyi @@ -9,6 +9,7 @@ from django.db.models import Manager, Model, QuerySet from django.db.models.fields import Field as DjangoModelField from django.utils.functional import cached_property from django.utils.translation import ugettext_lazy as _ +from django_stubs_ext import StrOrPromise from rest_framework.exceptions import APIException as APIException from rest_framework.exceptions import AuthenticationFailed as AuthenticationFailed from rest_framework.exceptions import ErrorDetail as ErrorDetail @@ -96,10 +97,10 @@ class BaseSerializer(Generic[_IN], Field[Any, Any, Any, _IN]): default: Any = ..., initial: Any = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[Any]] | None = ..., allow_null: bool = ..., ): ... @@ -129,7 +130,7 @@ class Serializer( metaclass=SerializerMetaclass, ): _declared_fields: dict[str, Field] - default_error_messages: dict[str, Any] + default_error_messages: dict[str, StrOrPromise] def get_initial(self) -> Any: ... @cached_property def fields(self) -> BindingDict: ... @@ -152,7 +153,7 @@ class ListSerializer( ): child: Field | BaseSerializer | None many: bool - default_error_messages: dict[str, Any] + default_error_messages: dict[str, StrOrPromise] allow_empty: bool | None def __init__( self, @@ -168,10 +169,10 @@ class ListSerializer( default: Any = ..., initial: Any = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[list[Any]]] | None = ..., allow_null: bool = ..., min_length: int | None = ..., @@ -215,10 +216,10 @@ class ModelSerializer(Serializer, BaseSerializer[_MT]): default: _MT | Sequence[_MT] | Callable[[], _MT | Sequence[_MT]] = ..., initial: _MT | Sequence[_MT] | Callable[[], _MT | Sequence[_MT]] = ..., source: str = ..., - label: str = ..., - help_text: str = ..., + label: StrOrPromise = ..., + help_text: StrOrPromise = ..., style: dict[str, Any] = ..., - error_messages: dict[str, str] = ..., + error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[_MT]] | None = ..., allow_null: bool = ..., allow_empty: bool = ..., diff --git a/tests/typecheck/test_fields.yml b/tests/typecheck/test_fields.yml index 3f542a3a2..1ae55ae57 100644 --- a/tests/typecheck/test_fields.yml +++ b/tests/typecheck/test_fields.yml @@ -72,7 +72,7 @@ from typing import Optional, Dict, Any CharField(initial='', default=lambda: '') - CharField(initial=None, default=4) # E: Argument "default" to "CharField" has incompatible type "int"; expected "Union[str, Callable[[], str], None, _Empty]" + CharField(initial=None, default=4) # E: Argument "default" to "CharField" has incompatible type "int"; expected "Union[Union[str, _StrPromise], Callable[[], Union[str, _StrPromise]], None, _Empty]" CharField(initial={}, default=empty) # E: Argument "initial" to "CharField" has incompatible type "Dict[, ]"; expected "Union[str, Callable[[], str], None, _Empty]" x: Optional[str] = CharField().get_initial() @@ -97,7 +97,7 @@ ChoiceField(['test'], allow_null=True, default=None) ChoiceField([1], default=int_callback) ChoiceField([1, 'lulz'], default=mixed_callback) - ChoiceField([1], default=lambda: None) # E: Argument "default" to "ChoiceField" has incompatible type "Callable[[], None]"; expected "Union[str, int, Callable[[], Union[str, int]], None, _Empty]" # E: Incompatible return value type (got "None", expected "Union[str, int]") + ChoiceField([1], default=lambda: None) # E: Argument "default" to "ChoiceField" has incompatible type "Callable[[], None]"; expected "Union[Union[str, _StrPromise], int, Callable[[], Union[Union[str, _StrPromise], int]], None, _Empty]" # E: Incompatible return value type (got "None", expected "Union[Union[str, _StrPromise], int]") - case: MultipleChoiceField_default main: | @@ -117,7 +117,7 @@ MultipleChoiceField(choices=[(1, "1"), (2, "2")], default=[1]) # E: Argument "default" to "MultipleChoiceField" has incompatible type "List[int]"; expected "Union[Set[Union[str, int]], Set[str], Set[int], Callable[[], Union[Set[Union[str, int]], Set[str], Set[int]]], None, _Empty]" MultipleChoiceField(choices=[(1, "1"), (2, "2")], initial={1}) - MultipleChoiceField(choices=[(1, "1"), (2, "2")], initial=[1]) # E: Argument "initial" to "MultipleChoiceField" has incompatible type "List[int]"; expected "Union[Set[Union[str, int]], Set[str], Set[int], Callable[[], Union[Set[Union[str, int]], Set[str], Set[int]]], None, _Empty]" + MultipleChoiceField(choices=[(1, "1"), (2, "2")], initial=[1]) # E: Argument "initial" to "MultipleChoiceField" has incompatible type "List[int]"; expected "Union[Set[Union[Union[str, _StrPromise], int]], Set[Union[str, _StrPromise]], Set[int], Callable[[], Union[Set[Union[Union[str, _StrPromise], int]], Set[Union[str, _StrPromise]], Set[int]]], None, _Empty]" - case: FileField_default main: |