diff --git a/rest_framework-stubs/fields.pyi b/rest_framework-stubs/fields.pyi index d940c7195..fb6a2540c 100644 --- a/rest_framework-stubs/fields.pyi +++ b/rest_framework-stubs/fields.pyi @@ -89,6 +89,7 @@ class Field(Generic[_VT, _DT, _RP, _IN]): write_only: bool def __init__( self, + *, read_only: bool = ..., write_only: bool = ..., required: bool = ..., @@ -339,7 +340,6 @@ class DecimalField(Field[Decimal, int | float | str | Decimal, str, Any]): min_value: Decimal | int | float = ..., localize: bool = ..., rounding: str | None = ..., - normalize_output: bool = ..., *, read_only: bool = ..., write_only: bool = ..., @@ -367,6 +367,7 @@ class DateTimeField(Field[datetime.datetime, datetime.datetime | str, str, Any]) format: str | None = ..., input_formats: Sequence[str] = ..., default_timezone: datetime.tzinfo | None = ..., + *, read_only: bool = ..., write_only: bool = ..., required: bool = ..., @@ -391,6 +392,7 @@ class DateField(Field[datetime.date, datetime.date | str, str, Any]): self, format: str | None = ..., input_formats: Sequence[str] = ..., + *, read_only: bool = ..., write_only: bool = ..., required: bool = ..., @@ -413,6 +415,7 @@ class TimeField(Field[datetime.time, datetime.time | str, str, Any]): self, format: str | None = ..., input_formats: Sequence[str] = ..., + *, read_only: bool = ..., write_only: bool = ..., required: bool = ..., @@ -493,6 +496,7 @@ class MultipleChoiceField( allow_empty: bool def __init__( self, + *, choices: Iterable[Any], read_only: bool = ..., write_only: bool = ..., @@ -521,6 +525,7 @@ class FilePathField(ChoiceField): allow_files: bool = ..., allow_folders: bool = ..., required: bool = ..., + *, read_only: bool = ..., write_only: bool = ..., default: _DefaultInitial[str] = ..., @@ -593,6 +598,7 @@ class ListField(Field[list[Any], list[Any], list[Any], Any]): min_length: int | None def __init__( self, + *, read_only: bool = ..., write_only: bool = ..., required: bool = ..., @@ -605,7 +611,6 @@ class ListField(Field[list[Any], list[Any], list[Any], Any]): error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[list[Any]]] | None = ..., allow_null: bool = ..., - *, child: Field = ..., allow_empty: bool = ..., max_length: int = ..., @@ -618,6 +623,7 @@ class DictField(Field[dict[Any, Any], dict[Any, Any], dict[Any, Any], Any]): allow_empty: bool def __init__( self, + *, read_only: bool = ..., write_only: bool = ..., required: bool = ..., @@ -630,7 +636,6 @@ class DictField(Field[dict[Any, Any], dict[Any, Any], dict[Any, Any], Any]): error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[dict[Any, Any]]] | None = ..., allow_null: bool = ..., - *, child: Field = ..., allow_empty: bool = ..., ) -> None: ... @@ -645,6 +650,7 @@ class JSONField(Field[dict[str, Any] | list[dict[str, Any]], dict[str, Any] | li decoder: type[JSONDecoder] | None def __init__( self, + *, read_only: bool = ..., write_only: bool = ..., required: bool = ..., @@ -657,7 +663,6 @@ class JSONField(Field[dict[str, Any] | list[dict[str, Any]], dict[str, Any] | li error_messages: dict[str, StrOrPromise] = ..., validators: Sequence[Validator[Any]] | None = ..., allow_null: bool = ..., - *, binary: bool = ..., encoder: type[JSONEncoder] | None = ..., decoder: type[JSONDecoder] | None = ..., diff --git a/rest_framework-stubs/relations.pyi b/rest_framework-stubs/relations.pyi index 7f7e1a03c..5208b4177 100644 --- a/rest_framework-stubs/relations.pyi +++ b/rest_framework-stubs/relations.pyi @@ -37,6 +37,7 @@ class RelatedField(Generic[_MT, _DT, _PT], Field[_MT, _DT, _PT, Any]): html_cutoff_text: str | None def __init__( self, + *, many: bool = ..., allow_empty: bool = ..., queryset: QuerySet[_MT] | Manager[_MT] | None = ..., @@ -76,6 +77,7 @@ class PrimaryKeyRelatedField(RelatedField[_MT, _MT, Any]): pk_field: str | None def __init__( self, + *, many: bool = ..., allow_empty: bool = ..., queryset: QuerySet[_MT] | Manager[_MT] | None = ..., @@ -104,6 +106,8 @@ class HyperlinkedRelatedField(RelatedField[_MT, str, Hyperlink]): view_name: str | None def __init__( self, + view_name: str, + *, many: bool = ..., allow_empty: bool = ..., queryset: QuerySet[_MT] | Manager[_MT] | None = ..., @@ -121,7 +125,6 @@ class HyperlinkedRelatedField(RelatedField[_MT, str, Hyperlink]): validators: Sequence[Validator[_MT]] | None = ..., error_messages: dict[str, StrOrPromise] | None = ..., style: dict[str, str] | None = ..., - view_name: str | None = ..., lookup_field: str | None = ..., lookup_url_kwarg: str | None = ..., format: str | None = ..., @@ -135,6 +138,8 @@ class SlugRelatedField(RelatedField[_MT, str, str]): slug_field: str | None def __init__( self, + slug_field: str, + *, many: bool = ..., allow_empty: bool = ..., queryset: QuerySet[_MT] | Manager[_MT] | None = ..., @@ -152,7 +157,6 @@ class SlugRelatedField(RelatedField[_MT, str, str]): validators: Sequence[Validator[_MT]] | None = ..., error_messages: dict[str, StrOrPromise] | None = ..., style: dict[str, str] | None = ..., - slug_field: str | None = ..., ) -> None: ... def to_internal_value(self, data: Any) -> _MT: ... def to_representation(self, value: _MT) -> str: ... @@ -165,6 +169,8 @@ class ManyRelatedField(Field[Sequence[Any], Sequence[Any], list[Any], Any]): allow_empty: bool def __init__( self, + child_relation: RelatedField = ..., + *, read_only: bool = ..., write_only: bool = ..., required: bool = ..., @@ -178,7 +184,6 @@ class ManyRelatedField(Field[Sequence[Any], Sequence[Any], list[Any], Any]): validators: Sequence[Validator[Sequence[Any]]] | None = ..., allow_null: bool = ..., allow_empty: bool = ..., - child_relation: RelatedField = ..., ) -> None: ... def get_value(self, dictionary: Mapping[Any, Any]) -> list[Any]: ... def get_choices(self, cutoff: int | None = ...) -> dict: ... diff --git a/rest_framework-stubs/serializers.pyi b/rest_framework-stubs/serializers.pyi index d2bbf6764..7f51c268f 100644 --- a/rest_framework-stubs/serializers.pyi +++ b/rest_framework-stubs/serializers.pyi @@ -83,6 +83,7 @@ class BaseSerializer(Generic[_IN], Field[Any, Any, Any, _IN]): self, instance: _IN | None = ..., data: Any = ..., + *, partial: bool = ..., many: bool = ..., allow_empty: bool = ..., @@ -203,6 +204,7 @@ class ModelSerializer(Serializer, BaseSerializer[_MT]): self, instance: None | _MT | Sequence[_MT] | QuerySet[_MT] | Manager[_MT] = ..., data: Any = ..., + *, partial: bool = ..., many: bool = ..., context: dict[str, Any] = ..., diff --git a/scripts/stubtest/allowlist.txt b/scripts/stubtest/allowlist.txt index 3004daa55..22a9d7c4c 100644 --- a/scripts/stubtest/allowlist.txt +++ b/scripts/stubtest/allowlist.txt @@ -4,3 +4,13 @@ # # Please, move things here when you are sure that they really should be ignored. # Comments about why things are ignored are mandatory. + +# Constructor arguments *appear* optional but actually throw exception +rest_framework.relations.HyperlinkedIdentityField.__init__ +rest_framework.relations.HyperlinkedRelatedField.__init__ +rest_framework.relations.ManyRelatedField.__init__ +rest_framework.relations.SlugRelatedField.__init__ +rest_framework.serializers.HyperlinkedIdentityField.__init__ +rest_framework.serializers.HyperlinkedRelatedField.__init__ +rest_framework.serializers.ManyRelatedField.__init__ +rest_framework.serializers.SlugRelatedField.__init__ diff --git a/scripts/stubtest/allowlist_todo.txt b/scripts/stubtest/allowlist_todo.txt index fa3994a82..042b848b7 100644 --- a/scripts/stubtest/allowlist_todo.txt +++ b/scripts/stubtest/allowlist_todo.txt @@ -46,28 +46,20 @@ rest_framework.fields.DateField.to_internal_value rest_framework.fields.DateTimeField.__init__ rest_framework.fields.DateTimeField.to_internal_value rest_framework.fields.DecimalField.__init__ -rest_framework.fields.DictField.__init__ rest_framework.fields.DictField.initial rest_framework.fields.DurationField.to_internal_value rest_framework.fields.Field.__init__ rest_framework.fields.FilePathField.__init__ -rest_framework.fields.HStoreField.__init__ -rest_framework.fields.HiddenField.__init__ -rest_framework.fields.JSONField.__init__ -rest_framework.fields.ListField.__init__ rest_framework.fields.ListField.initial rest_framework.fields.ListField.to_representation rest_framework.fields.ModelField.get_attribute rest_framework.fields.ModelField.to_representation -rest_framework.fields.MultipleChoiceField.__init__ rest_framework.fields.NullBooleanField rest_framework.fields.Option rest_framework.fields.REGEX_TYPE -rest_framework.fields.ReadOnlyField.__init__ rest_framework.fields.SupportsToPython rest_framework.fields.TimeField.__init__ rest_framework.fields.TimeField.to_internal_value -rest_framework.fields._UnvalidatedField.__init__ rest_framework.fields.empty rest_framework.generics.BaseFilterProtocol rest_framework.generics.UsesQuerySet @@ -76,17 +68,10 @@ rest_framework.pagination.HtmlContext rest_framework.pagination.HtmlContextWithPageLinks rest_framework.parsers.BaseParser.media_type rest_framework.parsers.FileUploadParser.get_encoded_filename -rest_framework.relations.HyperlinkedIdentityField.__init__ -rest_framework.relations.HyperlinkedRelatedField.__init__ rest_framework.relations.HyperlinkedRelatedField.get_object -rest_framework.relations.ManyRelatedField.__init__ rest_framework.relations.ManyRelatedField.initial rest_framework.relations.ManyRelatedField.to_representation -rest_framework.relations.PrimaryKeyRelatedField.__init__ -rest_framework.relations.RelatedField.__init__ -rest_framework.relations.SlugRelatedField.__init__ rest_framework.relations.SlugRelatedField.to_representation -rest_framework.relations.StringRelatedField.__init__ rest_framework.renderers.BaseRenderer.format rest_framework.renderers.BaseRenderer.media_type rest_framework.renderers.BrowsableAPIRenderer.get_extra_actions @@ -124,7 +109,6 @@ rest_framework.schemas.views.SchemaView.get rest_framework.schemas.views.SchemaView.renderer_classes rest_framework.serializers.APIException rest_framework.serializers.AuthenticationFailed -rest_framework.serializers.BaseSerializer.__init__ rest_framework.serializers.BaseSerializer.is_valid rest_framework.serializers.BooleanField.initial rest_framework.serializers.CharField.initial @@ -133,43 +117,28 @@ rest_framework.serializers.DateField.to_internal_value rest_framework.serializers.DateTimeField.__init__ rest_framework.serializers.DateTimeField.to_internal_value rest_framework.serializers.DecimalField.__init__ -rest_framework.serializers.DictField.__init__ rest_framework.serializers.DictField.initial rest_framework.serializers.DurationField.to_internal_value rest_framework.serializers.Field.__init__ rest_framework.serializers.FilePathField.__init__ -rest_framework.serializers.HStoreField.__init__ -rest_framework.serializers.HiddenField.__init__ -rest_framework.serializers.HyperlinkedIdentityField.__init__ -rest_framework.serializers.HyperlinkedRelatedField.__init__ rest_framework.serializers.HyperlinkedRelatedField.get_object -rest_framework.serializers.JSONField.__init__ -rest_framework.serializers.ListField.__init__ rest_framework.serializers.ListField.initial rest_framework.serializers.ListField.to_representation rest_framework.serializers.ListSerializer.is_valid rest_framework.serializers.ListSerializer.to_representation -rest_framework.serializers.ManyRelatedField.__init__ rest_framework.serializers.ManyRelatedField.initial rest_framework.serializers.ManyRelatedField.to_representation rest_framework.serializers.MethodNotAllowed rest_framework.serializers.ModelField.get_attribute rest_framework.serializers.ModelField.to_representation rest_framework.serializers.ModelSerializer.Meta -rest_framework.serializers.ModelSerializer.__init__ -rest_framework.serializers.MultipleChoiceField.__init__ rest_framework.serializers.NotAcceptable rest_framework.serializers.NotAuthenticated rest_framework.serializers.NotFound rest_framework.serializers.NullBooleanField rest_framework.serializers.ParseError rest_framework.serializers.PermissionDenied -rest_framework.serializers.PrimaryKeyRelatedField.__init__ -rest_framework.serializers.ReadOnlyField.__init__ -rest_framework.serializers.RelatedField.__init__ -rest_framework.serializers.SlugRelatedField.__init__ rest_framework.serializers.SlugRelatedField.to_representation -rest_framework.serializers.StringRelatedField.__init__ rest_framework.serializers.Throttled rest_framework.serializers.TimeField.__init__ rest_framework.serializers.TimeField.to_internal_value diff --git a/tests/typecheck/test_fields.yml b/tests/typecheck/test_fields.yml index 1ae55ae57..eb3928c81 100644 --- a/tests/typecheck/test_fields.yml +++ b/tests/typecheck/test_fields.yml @@ -9,11 +9,12 @@ - case: some_positional_args_fields main: | + from datetime import datetime, time from django.db import models - from rest_framework.fields import DecimalField, IPAddressField, SlugField, RegexField, ModelField, SerializerMethodField, ChoiceField + from rest_framework.fields import DecimalField, IPAddressField, SlugField, RegexField, ModelField, SerializerMethodField, ChoiceField, DateTimeField, DateField, TimeField - DecimalField(1, 1, False, 1, 1, False, None, True) - DecimalField(1, 1, False, 1, 1, False, None, True, True) # E: Too many positional arguments for "DecimalField" + DecimalField(1, 1, False, 1, 1, False, None) + DecimalField(1, 1, False, 1, 1, False, None, True) # E: Too many positional arguments for "DecimalField" IPAddressField('both') IPAddressField('both', True) # E: Too many positional arguments for "IPAddressField" @@ -34,37 +35,15 @@ ChoiceField([]) ChoiceField([], False) # E: Too many positional arguments for "ChoiceField" -- case: most_positional_args_fields - main: | - from rest_framework.fields import Field, ListField, DictField, JSONField - f: Field = Field() - - ListField(True, True, True, [{"key": "value"}], [{"key": "value"}], 'src', 'l', 'ht', {"key": "value"}, {"key": "value"}, [lambda x: None], True) - ListField(True, True, True, [{"key": "value"}], [{"key": "value"}], 'src', 'l', 'ht', {"key": "value"}, {"key": "value"}, [lambda x: None], True, f) # E: Too many positional arguments for "ListField" - ListField(True, True, True, [{"key": "value"}], [{"key": "value"}], 'src', 'l', 'ht', {"key": "value"}, {"key": "value"}, [lambda x: None], True, child=f, allow_empty=True, max_length=1, min_length=1) - - DictField(True, True, True, {}, {}, 'src', 'l', 'ht', {}, {}, [], True) - DictField(True, True, True, {}, {}, 'src', 'l', 'ht', {}, {}, [], True, f) # E: Too many positional arguments for "DictField" - DictField(True, True, True, {}, {}, 'src', 'l', 'ht', {}, {}, [], True, child=f, allow_empty=True) - - JSONField(True, True, True, {}, {}, 'src', 'l', 'ht', {}, {}, [], True) - JSONField(True, True, True, {}, {}, 'src', 'l', 'ht', {}, {}, [], True, True) # E: Too many positional arguments for "JSONField" - JSONField(True, True, True, {}, {}, 'src', 'l', 'ht', {}, {}, [], True, binary=True, encoder=None, decoder=None) - -- case: all_positional_args_fields - main: | - from datetime import datetime, time - from rest_framework.fields import DateTimeField, DateField, TimeField - d: datetime = datetime.now() - DateTimeField('', [], None, True, True, True, d, d, 'src', 'l', 'ht', {}, {}, [], True) - DateTimeField('', [], None, True, True, True, d, d, 'src', 'l', 'ht', {}, {}, [], True, 1) # E: Too many arguments for "DateTimeField" + DateTimeField('', [], None, read_only=True, write_only=True, allow_null=True) + DateTimeField('', [], None, True) # E: Too many positional arguments for "DateTimeField" - DateField('', [], True, True, True, d, d, 'src', 'l', 'ht', {}, {}, [], True) - DateField('', [], True, True, True, d, d, 'src', 'l', 'ht', {}, {}, [], True, 1) # E: Too many arguments for "DateField" + DateField('', [], read_only=True, write_only=True, allow_null=True) + DateField('', [], True) # E: Too many positional arguments for "DateField" - TimeField('', [], True, True, True, time(hour=1), time(hour=1), 'src', 'l', 'ht', {}, {}, [], True) - TimeField('', [], True, True, True, time(hour=1), time(hour=1), 'src', 'l', 'ht', {}, {}, [], True, 1) # E: Too many arguments for "TimeField" + TimeField('', [], read_only=True, write_only=True, allow_null=True) + TimeField('', [], True) # E: Too many positional arguments for "TimeField" - case: default_and_inital_args_fields main: | @@ -107,11 +86,11 @@ def int_set_callback() -> Set[int]: ... def mixed_set_callback() -> Set[Union[int, str]]: ... - MultipleChoiceField([1], default={1}) - MultipleChoiceField(['test'], allow_null=True, default=None) - MultipleChoiceField([1], default=int_set_callback) - MultipleChoiceField([1, 'lulz'], default=mixed_set_callback) - MultipleChoiceField([1], default=lambda: [1]) # E: Argument "default" to "MultipleChoiceField" has incompatible type "Callable[[], List[int]]"; expected "Union[Set[Union[str, int]], Set[str], Set[int], Callable[[], Union[Set[Union[str, int]], Set[str], Set[int]]], None, _Empty]" # E: Incompatible return value type (got "List[int]", expected "Union[Set[Union[str, int]], Set[str], Set[int]]") + MultipleChoiceField(choices=[1], default={1}) + MultipleChoiceField(choices=['test'], allow_null=True, default=None) + MultipleChoiceField(choices=[1], default=int_set_callback) + MultipleChoiceField(choices=[1, 'lulz'], default=mixed_set_callback) + MultipleChoiceField(choices=[1], default=lambda: [1]) # E: Argument "default" to "MultipleChoiceField" has incompatible type "Callable[[], List[int]]"; expected "Union[Set[Union[str, int]], Set[str], Set[int], Callable[[], Union[Set[Union[str, int]], Set[str], Set[int]]], None, _Empty]" # E: Incompatible return value type (got "List[int]", expected "Union[Set[Union[str, int]], Set[str], Set[int]]") MultipleChoiceField(choices=[(1, "1"), (2, "2")], default={1}) 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]"