diff --git a/rest_framework-stubs/fields.pyi b/rest_framework-stubs/fields.pyi index 55a2b9a1e..2858e38a4 100644 --- a/rest_framework-stubs/fields.pyi +++ b/rest_framework-stubs/fields.pyi @@ -19,6 +19,8 @@ from typing_extensions import Self class _Empty(Enum): sentinel = 0 +# DISREPANCY: `empty` hinted as enum, to work correctly in unions: +# https://github.com/typeddjango/djangorestframework-stubs/issues/42 empty: Final = _Empty.sentinel class BuiltinSignatureError(Exception): ... diff --git a/rest_framework-stubs/relations.pyi b/rest_framework-stubs/relations.pyi index bf95a176f..01b23566c 100644 --- a/rest_framework-stubs/relations.pyi +++ b/rest_framework-stubs/relations.pyi @@ -138,6 +138,7 @@ class SlugRelatedField(RelatedField[_MT, str, str]): slug_field: str def __init__( self, + # DISCREPANCY: signature defaults `slug_field=None`, but actually crashes when `None` is provided. slug_field: str, *, many: bool = ..., @@ -169,7 +170,8 @@ class ManyRelatedField(Field[Sequence[Any], Sequence[Any], list[Any], Any]): allow_empty: bool def __init__( self, - child_relation: RelatedField = ..., + # DISCREPANCY: signature defaults `child_relation=None`, but actually crashes when `None` is provided. + child_relation: RelatedField, *, read_only: bool = ..., write_only: bool = ..., diff --git a/rest_framework-stubs/renderers.pyi b/rest_framework-stubs/renderers.pyi index 01de43daa..c5f23cdfc 100644 --- a/rest_framework-stubs/renderers.pyi +++ b/rest_framework-stubs/renderers.pyi @@ -13,6 +13,8 @@ from rest_framework.views import APIView def zero_as_none(value: Any) -> Any | None: ... class BaseRenderer: + # DISCREPANCY: `media_type`, `format` cannot be None. + # None is a placeholder, but all subclasses must override this to `str`. media_type: str format: str charset: str | None diff --git a/rest_framework-stubs/validators.pyi b/rest_framework-stubs/validators.pyi index cf6ec952a..f4392e931 100644 --- a/rest_framework-stubs/validators.pyi +++ b/rest_framework-stubs/validators.pyi @@ -59,6 +59,7 @@ class ProhibitSurrogateCharactersValidator: def __call__(self, value: Any) -> None: ... class BaseUniqueForValidator: + # DISCREPANCY: `message` cannot be None -- None is a placeholder, but subclasses must override this to StrOrPromise message: StrOrPromise missing_message: StrOrPromise requires_context: bool diff --git a/scripts/stubtest/allowlist.txt b/scripts/stubtest/allowlist.txt index 27dca2492..29d4d4147 100644 --- a/scripts/stubtest/allowlist.txt +++ b/scripts/stubtest/allowlist.txt @@ -11,6 +11,11 @@ rest_framework.relations.SlugRelatedField.__init__ rest_framework.serializers.ManyRelatedField.__init__ rest_framework.serializers.SlugRelatedField.__init__ +# None is used as a placeholder, but not valid in actual usage +rest_framework.renderers.BaseRenderer.format +rest_framework.renderers.BaseRenderer.media_type +rest_framework.validators.BaseUniqueForValidator.message + # Migrations are omitted rest_framework.authtoken.migrations rest_framework.authtoken.migrations.0001_initial @@ -18,6 +23,11 @@ rest_framework.authtoken.migrations.0002_auto_20160226_1747 rest_framework.authtoken.migrations.0003_tokenproxy rest_framework.authtoken.migrations.0004_alter_tokenproxy_options +# `empty` hinted as enum, to work correctly in unions: +# https://github.com/typeddjango/djangorestframework-stubs/issues/42 +rest_framework.fields.empty +rest_framework.serializers.empty + # Mypy doesn't like default value `empty` rest_framework.fields.DateField.__init__ rest_framework.fields.DateTimeField.__init__ diff --git a/scripts/stubtest/allowlist_todo.txt b/scripts/stubtest/allowlist_todo.txt index f112e4c33..eaa7133d1 100644 --- a/scripts/stubtest/allowlist_todo.txt +++ b/scripts/stubtest/allowlist_todo.txt @@ -41,7 +41,6 @@ rest_framework.fields.Option rest_framework.fields.REGEX_TYPE rest_framework.fields.SupportsToPython rest_framework.fields.TimeField.to_internal_value -rest_framework.fields.empty rest_framework.generics.BaseFilterProtocol rest_framework.generics.UsesQuerySet rest_framework.negotiation.DefaultContentNegotiation.settings @@ -51,8 +50,6 @@ rest_framework.parsers.BaseParser.media_type rest_framework.parsers.FileUploadParser.get_encoded_filename rest_framework.relations.ManyRelatedField.initial rest_framework.relations.ManyRelatedField.to_representation -rest_framework.renderers.BaseRenderer.format -rest_framework.renderers.BaseRenderer.media_type rest_framework.renderers.BrowsableAPIRenderer.get_extra_actions rest_framework.renderers.CoreJSONRenderer.render rest_framework.renderers._BaseOpenAPIRenderer.render @@ -91,7 +88,6 @@ rest_framework.serializers.PermissionDenied rest_framework.serializers.Throttled rest_framework.serializers.TimeField.to_internal_value rest_framework.serializers.UnsupportedMediaType -rest_framework.serializers.empty rest_framework.settings.DefaultsSettings rest_framework.settings.api_settings rest_framework.test.CoreAPIClient @@ -99,7 +95,6 @@ rest_framework.test.APIClient.options rest_framework.test.RequestsClient.__init__ rest_framework.throttling.SimpleRateThrottle.cache rest_framework.utils.encoders.JSONEncoder.default -rest_framework.validators.BaseUniqueForValidator.message rest_framework.validators.ContextValidator rest_framework.validators.Validator rest_framework.views.APIView.metadata_class