From ebdf4c941bfd4967f2b313b20f50fb60f5561d17 Mon Sep 17 00:00:00 2001 From: Xavier Francisco Date: Fri, 18 Nov 2022 20:36:32 -0100 Subject: [PATCH 1/5] Add failing test --- tests/typecheck/test_exceptions.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/typecheck/test_exceptions.yml b/tests/typecheck/test_exceptions.yml index 0c1a4704e..c17849318 100644 --- a/tests/typecheck/test_exceptions.yml +++ b/tests/typecheck/test_exceptions.yml @@ -15,3 +15,12 @@ status_code = 200 default_detail = {"ok": "everything"} default_code = "ok" +- case: test_exception_declaration_lazystr + main: | + from django.utils.translation import gettext_lazy as _ + from rest_framework import exceptions + + class MyException(exceptions.APIException): + status_code = 200 + default_detail = _("Está tudo bem") + default_code = "ok" From 8f1c2a5f43a9590be2c72fd8e9715a7637b63237 Mon Sep 17 00:00:00 2001 From: Xavier Francisco Date: Fri, 18 Nov 2022 20:50:02 -0100 Subject: [PATCH 2/5] Support _StrPromise --- rest_framework-stubs/exceptions.pyi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rest_framework-stubs/exceptions.pyi b/rest_framework-stubs/exceptions.pyi index 7dcaf8f57..7bf23f51c 100644 --- a/rest_framework-stubs/exceptions.pyi +++ b/rest_framework-stubs/exceptions.pyi @@ -4,6 +4,7 @@ from typing import Any from typing_extensions import TypeAlias from django.http import HttpRequest, JsonResponse +from django.utils.functional import _StrPromise from rest_framework.renderers import BaseRenderer from rest_framework.request import Request @@ -15,7 +16,7 @@ class ErrorDetail(str): code: str | None def __new__(cls, string: str, code: str | None = ...): ... -_Detail: TypeAlias = str | list[Any] | dict[str, Any] +_Detail: TypeAlias = str | _StrPromise | list[Any] | dict[str, Any] class APIException(Exception): status_code: int From 40c8e5ac899401968885ba1657794c144541ddc6 Mon Sep 17 00:00:00 2001 From: Xavier Francisco Date: Thu, 24 Nov 2022 01:06:08 -0100 Subject: [PATCH 3/5] Update ignores --- scripts/typecheck_tests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/typecheck_tests.py b/scripts/typecheck_tests.py index 2daefe099..9481ca84f 100644 --- a/scripts/typecheck_tests.py +++ b/scripts/typecheck_tests.py @@ -106,7 +106,7 @@ "Dict entry", '"FieldValues"', 'base class "Field" defined the type as "bool"', - 'Invalid index type "int" for "Union[str, List[Any], Dict[str, Any]]"; expected type "str"', + 'Invalid index type "int" for "Union[str, _StrPromise, List[Any], Dict[str, Any]]"; expected type "str"', 'Item "str" of "Union[str, Any]" has no attribute "code"', 'Argument "default" to "CharField" has incompatible type', '"MultipleChoiceField" has no attribute "partial"', @@ -152,7 +152,7 @@ 'Cannot assign multiple types to name "composed_perm" without an explicit "Type[...]" annotation', ], "test_relations.py": [ - 'Invalid index type "int" for "Union[str, List[Any], Dict[str, Any]]"; expected type "str"', + 'Invalid index type "int" for "Union[str, _StrPromise, List[Any], Dict[str, Any]]"; expected type "str"', 'Argument "queryset" to "HyperlinkedRelatedField" has incompatible type', 'Incompatible return value type (got "None", expected "HttpResponseBase', 'Argument 2 to "re_path" has incompatible type "Callable[[], None]"; expected "Callable[..., HttpResponseBase]"', # noqa: E501 @@ -216,7 +216,7 @@ 'Argument 1 to "to_internal_value" of "Field" has incompatible type "object"', ], "test_validation_error.py": [ - 'Argument "detail" to "ValidationError" has incompatible type "Tuple[str, str]"; expected "Optional[Union[str, List[Any], Dict[str, Any]]]"', # noqa: E501 + 'Argument "detail" to "ValidationError" has incompatible type "Tuple[str, str]"; expected "Optional[Union[str, _StrPromise, List[Any], Dict[str, Any]]]"', # noqa: E501 ], "test_validators.py": [ 'Argument "queryset" to "BaseUniqueForValidator" has incompatible type "object";' From 14332bc896034ccda677138b8ee36532309bfb80 Mon Sep 17 00:00:00 2001 From: Xavier Francisco Date: Thu, 22 Dec 2022 07:28:58 -0100 Subject: [PATCH 4/5] Use StrOrPromise --- rest_framework-stubs/exceptions.pyi | 4 ++-- scripts/typecheck_tests.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rest_framework-stubs/exceptions.pyi b/rest_framework-stubs/exceptions.pyi index 7bf23f51c..9af1352f3 100644 --- a/rest_framework-stubs/exceptions.pyi +++ b/rest_framework-stubs/exceptions.pyi @@ -4,7 +4,7 @@ from typing import Any from typing_extensions import TypeAlias from django.http import HttpRequest, JsonResponse -from django.utils.functional import _StrPromise +from django_stubs_ext import StrOrPromise from rest_framework.renderers import BaseRenderer from rest_framework.request import Request @@ -16,7 +16,7 @@ class ErrorDetail(str): code: str | None def __new__(cls, string: str, code: str | None = ...): ... -_Detail: TypeAlias = str | _StrPromise | list[Any] | dict[str, Any] +_Detail: TypeAlias = StrOrPromise | list[Any] | dict[str, Any] class APIException(Exception): status_code: int diff --git a/scripts/typecheck_tests.py b/scripts/typecheck_tests.py index 9481ca84f..528101f21 100644 --- a/scripts/typecheck_tests.py +++ b/scripts/typecheck_tests.py @@ -106,7 +106,7 @@ "Dict entry", '"FieldValues"', 'base class "Field" defined the type as "bool"', - 'Invalid index type "int" for "Union[str, _StrPromise, List[Any], Dict[str, Any]]"; expected type "str"', + 'Invalid index type "int" for "Union[StrOrPromise, List[Any], Dict[str, Any]]"; expected type "str"', 'Item "str" of "Union[str, Any]" has no attribute "code"', 'Argument "default" to "CharField" has incompatible type', '"MultipleChoiceField" has no attribute "partial"', @@ -152,7 +152,7 @@ 'Cannot assign multiple types to name "composed_perm" without an explicit "Type[...]" annotation', ], "test_relations.py": [ - 'Invalid index type "int" for "Union[str, _StrPromise, List[Any], Dict[str, Any]]"; expected type "str"', + 'Invalid index type "int" for "Union[StrOrPromise, List[Any], Dict[str, Any]]"; expected type "str"', 'Argument "queryset" to "HyperlinkedRelatedField" has incompatible type', 'Incompatible return value type (got "None", expected "HttpResponseBase', 'Argument 2 to "re_path" has incompatible type "Callable[[], None]"; expected "Callable[..., HttpResponseBase]"', # noqa: E501 @@ -216,7 +216,7 @@ 'Argument 1 to "to_internal_value" of "Field" has incompatible type "object"', ], "test_validation_error.py": [ - 'Argument "detail" to "ValidationError" has incompatible type "Tuple[str, str]"; expected "Optional[Union[str, _StrPromise, List[Any], Dict[str, Any]]]"', # noqa: E501 + 'Argument "detail" to "ValidationError" has incompatible type "Tuple[str, str]"; expected "Optional[Union[Union[str, _StrPromise], List[Any], Dict[str, Any]]]"', # noqa: E501 ], "test_validators.py": [ 'Argument "queryset" to "BaseUniqueForValidator" has incompatible type "object";' From c9bfc728250c24c0db4c68f99ecee4a0a8ecae59 Mon Sep 17 00:00:00 2001 From: Xavier Francisco Date: Thu, 22 Dec 2022 07:34:03 -0100 Subject: [PATCH 5/5] Fix --- scripts/typecheck_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/typecheck_tests.py b/scripts/typecheck_tests.py index 528101f21..69138134e 100644 --- a/scripts/typecheck_tests.py +++ b/scripts/typecheck_tests.py @@ -106,7 +106,7 @@ "Dict entry", '"FieldValues"', 'base class "Field" defined the type as "bool"', - 'Invalid index type "int" for "Union[StrOrPromise, List[Any], Dict[str, Any]]"; expected type "str"', + 'Invalid index type "int" for "Union[str, _StrPromise, List[Any], Dict[str, Any]]"; expected type "str"', 'Item "str" of "Union[str, Any]" has no attribute "code"', 'Argument "default" to "CharField" has incompatible type', '"MultipleChoiceField" has no attribute "partial"', @@ -152,7 +152,7 @@ 'Cannot assign multiple types to name "composed_perm" without an explicit "Type[...]" annotation', ], "test_relations.py": [ - 'Invalid index type "int" for "Union[StrOrPromise, List[Any], Dict[str, Any]]"; expected type "str"', + 'Invalid index type "int" for "Union[str, _StrPromise, List[Any], Dict[str, Any]]"; expected type "str"', 'Argument "queryset" to "HyperlinkedRelatedField" has incompatible type', 'Incompatible return value type (got "None", expected "HttpResponseBase', 'Argument 2 to "re_path" has incompatible type "Callable[[], None]"; expected "Callable[..., HttpResponseBase]"', # noqa: E501