From 971b8d8bca1cabdebe346d157717004bdb973912 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 12 Dec 2023 11:36:54 -0600 Subject: [PATCH 01/11] Add more explicit typing to avoid pyright unknown errors --- django-stubs/apps/registry.pyi | 2 +- django-stubs/contrib/admin/options.pyi | 6 +++--- django-stubs/contrib/admin/sites.pyi | 4 ++-- django-stubs/core/cache/__init__.pyi | 8 +++++--- django-stubs/db/models/manager.pyi | 3 ++- django-stubs/shortcuts.pyi | 6 +++--- django-stubs/urls/base.pyi | 3 ++- django-stubs/utils/decorators.pyi | 10 ++++++---- 8 files changed, 24 insertions(+), 18 deletions(-) diff --git a/django-stubs/apps/registry.pyi b/django-stubs/apps/registry.pyi index 528704e31..d7a3963e4 100644 --- a/django-stubs/apps/registry.pyi +++ b/django-stubs/apps/registry.pyi @@ -24,7 +24,7 @@ class Apps: def get_app_config(self, app_label: str) -> AppConfig: ... # it's not possible to support it in plugin properly now def get_models(self, include_auto_created: bool = ..., include_swapped: bool = ...) -> list[type[Model]]: ... - def get_model(self, app_label: str, model_name: str | None = ..., require_ready: bool = ...) -> type[Any]: ... + def get_model(self, app_label: str, model_name: str | None = ..., require_ready: bool = ...) -> type[Model]: ... def register_model(self, app_label: str, model: type[Model]) -> None: ... def is_installed(self, app_name: str) -> bool: ... def get_containing_app_config(self, object_name: str) -> AppConfig | None: ... diff --git a/django-stubs/contrib/admin/options.pyi b/django-stubs/contrib/admin/options.pyi index 64cfb44a0..cfc6cbdca 100644 --- a/django-stubs/contrib/admin/options.pyi +++ b/django-stubs/contrib/admin/options.pyi @@ -65,10 +65,10 @@ class _FieldOpts(_OptionalFieldOpts, total=True): _FieldsetSpec: TypeAlias = _ListOrTuple[tuple[_StrOrPromise | None, _FieldOpts]] _ListFilterT: TypeAlias = ( type[ListFilter] - | Field + | Field[Any, Any] | str - | tuple[Field | str, type[FieldListFilter]] - | list[Field | str | type[FieldListFilter]] + | tuple[Field[Any, Any] | str, type[FieldListFilter]] + | list[Field[Any, Any] | str | type[FieldListFilter]] ) # Generic type specifically for models, for use in BaseModelAdmin and subclasses diff --git a/django-stubs/contrib/admin/sites.pyi b/django-stubs/contrib/admin/sites.pyi index 12cf76526..fbfe25281 100644 --- a/django-stubs/contrib/admin/sites.pyi +++ b/django-stubs/contrib/admin/sites.pyi @@ -61,11 +61,11 @@ class AdminSite: def is_registered(self, model: type[Model]) -> bool: ... def add_action(self, action: _ActionCallback, name: str | None = ...) -> None: ... def disable_action(self, name: str) -> None: ... - def get_action(self, name: str) -> Callable: ... + def get_action(self, name: str) -> _ActionCallback: ... @property def actions(self) -> Iterable[tuple[str, _ActionCallback]]: ... def has_permission(self, request: HttpRequest) -> bool: ... - def admin_view(self, view: Callable, cacheable: bool = ...) -> Callable: ... + def admin_view(self, view: Callable[..., HttpResponse], cacheable: bool = ...) -> Callable[..., HttpResponse]: ... def get_urls(self) -> list[URLResolver | URLPattern]: ... @property def urls(self) -> tuple[list[URLResolver | URLPattern], str, str]: ... diff --git a/django-stubs/core/cache/__init__.pyi b/django-stubs/core/cache/__init__.pyi index ed6f98eca..c093c29d0 100644 --- a/django-stubs/core/cache/__init__.pyi +++ b/django-stubs/core/cache/__init__.pyi @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, TypeVar from django.utils.connection import BaseConnectionHandler @@ -9,7 +9,9 @@ from .backends.base import InvalidCacheKey as InvalidCacheKey DEFAULT_CACHE_ALIAS: str -class CacheHandler(BaseConnectionHandler): +_T = TypeVar("_T") + +class CacheHandler(BaseConnectionHandler[_T]): settings_name: str exception_class: type[Exception] def create_connection(self, alias: str) -> BaseCache: ... @@ -18,4 +20,4 @@ class CacheHandler(BaseConnectionHandler): def close_caches(**kwargs: Any) -> None: ... cache: BaseCache -caches: CacheHandler +caches: CacheHandler[Any] diff --git a/django-stubs/db/models/manager.pyi b/django-stubs/db/models/manager.pyi index 63dbc52f7..d6a58029b 100644 --- a/django-stubs/db/models/manager.pyi +++ b/django-stubs/db/models/manager.pyi @@ -1,5 +1,5 @@ import datetime -from collections.abc import AsyncIterator, Collection, Iterable, Iterator, MutableMapping, Sequence +from collections.abc import AsyncIterator, Callable, Collection, Iterable, Iterator, MutableMapping, Sequence from typing import Any, Generic, NoReturn, TypeVar, overload from django.db.models.base import Model @@ -12,6 +12,7 @@ from django_stubs_ext import ValuesQuerySet _T = TypeVar("_T", bound=Model, covariant=True) class BaseManager(Generic[_T]): + cache: Callable[[], Self] # django-cacheops creation_counter: int auto_created: bool use_in_migrations: bool diff --git a/django-stubs/shortcuts.pyi b/django-stubs/shortcuts.pyi index 1e352e86b..4c4fbe4c9 100644 --- a/django-stubs/shortcuts.pyi +++ b/django-stubs/shortcuts.pyi @@ -20,15 +20,15 @@ class SupportsGetAbsoluteUrl(Protocol): @overload def redirect( - to: Callable | str | SupportsGetAbsoluteUrl, *args: Any, permanent: Literal[True], **kwargs: Any + to: Callable[..., Any] | str | SupportsGetAbsoluteUrl, *args: Any, permanent: Literal[True], **kwargs: Any ) -> HttpResponsePermanentRedirect: ... @overload def redirect( - to: Callable | str | SupportsGetAbsoluteUrl, *args: Any, permanent: Literal[False] = ..., **kwargs: Any + to: Callable[..., Any] | str | SupportsGetAbsoluteUrl, *args: Any, permanent: Literal[False] = ..., **kwargs: Any ) -> HttpResponseRedirect: ... @overload def redirect( - to: Callable | str | SupportsGetAbsoluteUrl, *args: Any, permanent: bool, **kwargs: Any + to: Callable[..., Any] | str | SupportsGetAbsoluteUrl, *args: Any, permanent: bool, **kwargs: Any ) -> HttpResponseRedirect | HttpResponsePermanentRedirect: ... _T = TypeVar("_T", bound=Model) diff --git a/django-stubs/urls/base.pyi b/django-stubs/urls/base.pyi index 2dd53f88b..e2b8dd904 100644 --- a/django-stubs/urls/base.pyi +++ b/django-stubs/urls/base.pyi @@ -1,11 +1,12 @@ from collections.abc import Callable, Sequence from typing import Any, Literal +from django.http.response import HttpResponse from django.urls.resolvers import ResolverMatch def resolve(path: str, urlconf: str | None = ...) -> ResolverMatch: ... def reverse( - viewname: Callable | str | None, + viewname: Callable[..., HttpResponse] | str | None, urlconf: str | None = ..., args: Sequence[Any] | None = ..., kwargs: dict[str, Any] | None = ..., diff --git a/django-stubs/utils/decorators.pyi b/django-stubs/utils/decorators.pyi index 40c1d8252..133002cbe 100644 --- a/django-stubs/utils/decorators.pyi +++ b/django-stubs/utils/decorators.pyi @@ -9,10 +9,12 @@ _CallableType = TypeVar("_CallableType", bound=Callable) classonlymethod = classmethod -def method_decorator(decorator: Callable | Iterable[Callable], name: str = ...) -> Callable[[_T], _T]: ... -def decorator_from_middleware_with_args(middleware_class: type) -> Callable: ... -def decorator_from_middleware(middleware_class: type) -> Callable: ... -def make_middleware_decorator(middleware_class: type[MiddlewareMixin]) -> Callable: ... +def method_decorator( + decorator: Callable[[_T], _T] | Iterable[Callable[[_T], _T]], name: str = ... +) -> Callable[[_T], _T]: ... +def decorator_from_middleware_with_args(middleware_class: type) -> Callable[[_T], _T]: ... +def decorator_from_middleware(middleware_class: type) -> Callable[[_T], _T]: ... +def make_middleware_decorator(middleware_class: type[MiddlewareMixin]) -> Callable[[_T], _T]: ... def sync_and_async_middleware(func: _CallableType) -> _CallableType: ... def sync_only_middleware(func: _CallableType) -> _CallableType: ... def async_only_middleware(func: _CallableType) -> _CallableType: ... From dbff96a5c419053b006e4736fd7aefcdc0773b40 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 12 Dec 2023 11:37:47 -0600 Subject: [PATCH 02/11] forward generic params to JSONField --- django-stubs/db/models/fields/json.pyi | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/django-stubs/db/models/fields/json.pyi b/django-stubs/db/models/fields/json.pyi index 544fb03ea..805f8d7af 100644 --- a/django-stubs/db/models/fields/json.pyi +++ b/django-stubs/db/models/fields/json.pyi @@ -1,6 +1,6 @@ import json from collections.abc import Callable -from typing import Any, ClassVar +from typing import Any, ClassVar, TypeVar from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models import lookups @@ -13,7 +13,12 @@ from typing_extensions import Self from . import Field from .mixins import CheckFieldDefaultMixin -class JSONField(CheckFieldDefaultMixin, Field): +# __set__ value type +_ST = TypeVar("_ST", contravariant=True) +# __get__ return type +_GT = TypeVar("_GT", covariant=True) + +class JSONField(CheckFieldDefaultMixin, Field[_ST, _GT]): encoder: type[json.JSONEncoder] | None decoder: type[json.JSONDecoder] | None def __init__( From d8d5467ac2cf9e3e04d8fb2621f2ef85be9aa253 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 12 Dec 2023 11:42:35 -0600 Subject: [PATCH 03/11] Forward generic type to alias for _DisplayT Per https://github.com/microsoft/pyright/issues/6715 --- django-stubs/contrib/admin/options.pyi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/django-stubs/contrib/admin/options.pyi b/django-stubs/contrib/admin/options.pyi index cfc6cbdca..3434fe3fe 100644 --- a/django-stubs/contrib/admin/options.pyi +++ b/django-stubs/contrib/admin/options.pyi @@ -119,7 +119,7 @@ class BaseModelAdmin(Generic[_ModelT]): def get_readonly_fields(self, request: HttpRequest, obj: _ModelT | None = ...) -> _ListOrTuple[str]: ... def get_prepopulated_fields(self, request: HttpRequest, obj: _ModelT | None = ...) -> dict[str, Sequence[str]]: ... def get_queryset(self, request: HttpRequest) -> QuerySet[_ModelT]: ... - def get_sortable_by(self, request: HttpRequest) -> _DisplayT: ... + def get_sortable_by(self, request: HttpRequest) -> _DisplayT[_ModelT]: ... def lookup_allowed(self, lookup: str, value: str) -> bool: ... def to_field_allowed(self, request: HttpRequest, to_field: str) -> bool: ... def has_add_permission(self, request: HttpRequest) -> bool: ... @@ -133,8 +133,8 @@ _ModelAdmin = TypeVar("_ModelAdmin", bound=ModelAdmin) _ActionCallable: TypeAlias = Callable[[_ModelAdmin, HttpRequest, QuerySet[_ModelT]], HttpResponseBase | None] class ModelAdmin(BaseModelAdmin[_ModelT]): - list_display: _DisplayT - list_display_links: _DisplayT | None + list_display: _DisplayT[_ModelT] + list_display_links: _DisplayT[_ModelT] | None list_filter: _ListOrTuple[_ListFilterT] list_select_related: bool | _ListOrTuple[str] list_per_page: int @@ -200,8 +200,8 @@ class ModelAdmin(BaseModelAdmin[_ModelT]): self, request: HttpRequest, default_choices: list[tuple[str, str]] = ... ) -> list[tuple[str, str]]: ... def get_action(self, action: Callable | str) -> tuple[Callable[..., str], str, str] | None: ... - def get_list_display(self, request: HttpRequest) -> _DisplayT: ... - def get_list_display_links(self, request: HttpRequest, list_display: _DisplayT) -> _DisplayT: ... + def get_list_display(self, request: HttpRequest) -> _DisplayT[_ModelT]: ... + def get_list_display_links(self, request: HttpRequest, list_display: _DisplayT[_ModelT]) -> _DisplayT[_ModelT]: ... def get_list_filter(self, request: HttpRequest) -> _ListOrTuple[_ListFilterT]: ... def get_list_select_related(self, request: HttpRequest) -> bool | _ListOrTuple[str]: ... def get_search_fields(self, request: HttpRequest) -> _ListOrTuple[str]: ... From 832e52aec7b1476c7f93c3d4ffd1e806a0709cf6 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 12 Dec 2023 12:22:31 -0600 Subject: [PATCH 04/11] update method_decorator#decorator to the correct type --- django-stubs/utils/decorators.pyi | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/django-stubs/utils/decorators.pyi b/django-stubs/utils/decorators.pyi index 133002cbe..5ca9fc570 100644 --- a/django-stubs/utils/decorators.pyi +++ b/django-stubs/utils/decorators.pyi @@ -1,20 +1,21 @@ from collections.abc import Callable, Iterable -from typing import TypeVar +from typing import TypeAlias, TypeVar +from django.http.response import HttpResponseBase from django.utils.deprecation import MiddlewareMixin from django.views.generic.base import View _T = TypeVar("_T", bound=View | Callable) # Any callable _CallableType = TypeVar("_CallableType", bound=Callable) +_VIEW = TypeVar("_VIEW", bound=Callable[..., HttpResponseBase]) +_DECORATOR: TypeAlias = Callable[..., _VIEW | Callable[..., _VIEW]] classonlymethod = classmethod -def method_decorator( - decorator: Callable[[_T], _T] | Iterable[Callable[[_T], _T]], name: str = ... -) -> Callable[[_T], _T]: ... -def decorator_from_middleware_with_args(middleware_class: type) -> Callable[[_T], _T]: ... -def decorator_from_middleware(middleware_class: type) -> Callable[[_T], _T]: ... -def make_middleware_decorator(middleware_class: type[MiddlewareMixin]) -> Callable[[_T], _T]: ... +def method_decorator(decorator: _DECORATOR | Iterable[_DECORATOR], name: str = ...) -> Callable[[_T], _T]: ... +def decorator_from_middleware_with_args(middleware_class: type) -> Callable: ... +def decorator_from_middleware(middleware_class: type) -> Callable: ... +def make_middleware_decorator(middleware_class: type[MiddlewareMixin]) -> Callable: ... def sync_and_async_middleware(func: _CallableType) -> _CallableType: ... def sync_only_middleware(func: _CallableType) -> _CallableType: ... def async_only_middleware(func: _CallableType) -> _CallableType: ... From ff0f4f828439cc4d5659c00cf0d7fe1b6224eafe Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 12 Dec 2023 12:28:32 -0600 Subject: [PATCH 05/11] correctly pass typevar for CacheHandler --- django-stubs/core/cache/__init__.pyi | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/django-stubs/core/cache/__init__.pyi b/django-stubs/core/cache/__init__.pyi index c093c29d0..e1a5a8fd1 100644 --- a/django-stubs/core/cache/__init__.pyi +++ b/django-stubs/core/cache/__init__.pyi @@ -1,4 +1,4 @@ -from typing import Any, TypeVar +from typing import Any from django.utils.connection import BaseConnectionHandler @@ -9,9 +9,7 @@ from .backends.base import InvalidCacheKey as InvalidCacheKey DEFAULT_CACHE_ALIAS: str -_T = TypeVar("_T") - -class CacheHandler(BaseConnectionHandler[_T]): +class CacheHandler(BaseConnectionHandler[BaseCache]): settings_name: str exception_class: type[Exception] def create_connection(self, alias: str) -> BaseCache: ... @@ -20,4 +18,4 @@ class CacheHandler(BaseConnectionHandler[_T]): def close_caches(**kwargs: Any) -> None: ... cache: BaseCache -caches: CacheHandler[Any] +caches: CacheHandler From faa4866a1566e6470edf5b666f04a9b093114eaa Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 12 Dec 2023 12:30:36 -0600 Subject: [PATCH 06/11] Add default type for JSONField --- django-stubs/db/models/fields/json.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/django-stubs/db/models/fields/json.pyi b/django-stubs/db/models/fields/json.pyi index 805f8d7af..6780dce96 100644 --- a/django-stubs/db/models/fields/json.pyi +++ b/django-stubs/db/models/fields/json.pyi @@ -14,9 +14,9 @@ from . import Field from .mixins import CheckFieldDefaultMixin # __set__ value type -_ST = TypeVar("_ST", contravariant=True) +_ST = TypeVar("_ST", contravariant=True, default=Any) # __get__ return type -_GT = TypeVar("_GT", covariant=True) +_GT = TypeVar("_GT", covariant=True, default=Any) class JSONField(CheckFieldDefaultMixin, Field[_ST, _GT]): encoder: type[json.JSONEncoder] | None From 072433bd1a77a9aa29a12638b95eb48f96f4c440 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 12 Dec 2023 14:34:45 -0600 Subject: [PATCH 07/11] fix type_extension import --- django-stubs/utils/decorators.pyi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/django-stubs/utils/decorators.pyi b/django-stubs/utils/decorators.pyi index 5ca9fc570..0bd62ab2e 100644 --- a/django-stubs/utils/decorators.pyi +++ b/django-stubs/utils/decorators.pyi @@ -1,9 +1,10 @@ from collections.abc import Callable, Iterable -from typing import TypeAlias, TypeVar +from typing import TypeVar from django.http.response import HttpResponseBase from django.utils.deprecation import MiddlewareMixin from django.views.generic.base import View +from typing_extensions import TypeAlias _T = TypeVar("_T", bound=View | Callable) # Any callable _CallableType = TypeVar("_CallableType", bound=Callable) From 10de6196297f42d04559a91764cf882845e4107b Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 12 Dec 2023 16:09:14 -0600 Subject: [PATCH 08/11] Address comment about not able to use generic type alias --- django-stubs/utils/decorators.pyi | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/django-stubs/utils/decorators.pyi b/django-stubs/utils/decorators.pyi index 0bd62ab2e..d7f2d9fad 100644 --- a/django-stubs/utils/decorators.pyi +++ b/django-stubs/utils/decorators.pyi @@ -1,5 +1,5 @@ from collections.abc import Callable, Iterable -from typing import TypeVar +from typing import Any, TypeVar from django.http.response import HttpResponseBase from django.utils.deprecation import MiddlewareMixin @@ -7,9 +7,8 @@ from django.views.generic.base import View from typing_extensions import TypeAlias _T = TypeVar("_T", bound=View | Callable) # Any callable -_CallableType = TypeVar("_CallableType", bound=Callable) -_VIEW = TypeVar("_VIEW", bound=Callable[..., HttpResponseBase]) -_DECORATOR: TypeAlias = Callable[..., _VIEW | Callable[..., _VIEW]] +_CallableType = TypeVar("_CallableType", bound=Callable[..., Any]) +_DECORATOR: TypeAlias = Callable[..., Callable[..., HttpResponseBase] | Callable[..., Callable[..., HttpResponseBase]]] classonlymethod = classmethod From 1d5e94ad1db82a37aa0e862f24749e7b5ef3bfd3 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Wed, 13 Dec 2023 06:16:07 -0600 Subject: [PATCH 09/11] address comment about generic _T(_ViewType) --- django-stubs/utils/decorators.pyi | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/django-stubs/utils/decorators.pyi b/django-stubs/utils/decorators.pyi index d7f2d9fad..42177efab 100644 --- a/django-stubs/utils/decorators.pyi +++ b/django-stubs/utils/decorators.pyi @@ -6,16 +6,18 @@ from django.utils.deprecation import MiddlewareMixin from django.views.generic.base import View from typing_extensions import TypeAlias -_T = TypeVar("_T", bound=View | Callable) # Any callable +_ViewType = TypeVar("_ViewType", bound=View | Callable[..., Any]) # Any callable _CallableType = TypeVar("_CallableType", bound=Callable[..., Any]) _DECORATOR: TypeAlias = Callable[..., Callable[..., HttpResponseBase] | Callable[..., Callable[..., HttpResponseBase]]] classonlymethod = classmethod -def method_decorator(decorator: _DECORATOR | Iterable[_DECORATOR], name: str = ...) -> Callable[[_T], _T]: ... -def decorator_from_middleware_with_args(middleware_class: type) -> Callable: ... -def decorator_from_middleware(middleware_class: type) -> Callable: ... -def make_middleware_decorator(middleware_class: type[MiddlewareMixin]) -> Callable: ... +def method_decorator( + decorator: _DECORATOR | Iterable[_DECORATOR], name: str = ... +) -> Callable[[_ViewType], _ViewType]: ... +def decorator_from_middleware_with_args(middleware_class: type) -> _DECORATOR: ... +def decorator_from_middleware(middleware_class: type) -> _DECORATOR: ... +def make_middleware_decorator(middleware_class: type[MiddlewareMixin]) -> _DECORATOR: ... def sync_and_async_middleware(func: _CallableType) -> _CallableType: ... def sync_only_middleware(func: _CallableType) -> _CallableType: ... def async_only_middleware(func: _CallableType) -> _CallableType: ... From 415d22bc6759cc88afa9d077bf2cc463918555ad Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Wed, 13 Dec 2023 06:17:11 -0600 Subject: [PATCH 10/11] change get_model back to return Type[Any] --- django-stubs/apps/registry.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django-stubs/apps/registry.pyi b/django-stubs/apps/registry.pyi index d7a3963e4..528704e31 100644 --- a/django-stubs/apps/registry.pyi +++ b/django-stubs/apps/registry.pyi @@ -24,7 +24,7 @@ class Apps: def get_app_config(self, app_label: str) -> AppConfig: ... # it's not possible to support it in plugin properly now def get_models(self, include_auto_created: bool = ..., include_swapped: bool = ...) -> list[type[Model]]: ... - def get_model(self, app_label: str, model_name: str | None = ..., require_ready: bool = ...) -> type[Model]: ... + def get_model(self, app_label: str, model_name: str | None = ..., require_ready: bool = ...) -> type[Any]: ... def register_model(self, app_label: str, model: type[Model]) -> None: ... def is_installed(self, app_name: str) -> bool: ... def get_containing_app_config(self, object_name: str) -> AppConfig | None: ... From 248eb88d2f3b5e2a0b53c77de349ecedd21553d3 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Tue, 19 Dec 2023 06:40:23 -0600 Subject: [PATCH 11/11] Address feedback to use Typevar for admin_view --- django-stubs/contrib/admin/sites.pyi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/django-stubs/contrib/admin/sites.pyi b/django-stubs/contrib/admin/sites.pyi index fbfe25281..b4138e99b 100644 --- a/django-stubs/contrib/admin/sites.pyi +++ b/django-stubs/contrib/admin/sites.pyi @@ -1,6 +1,6 @@ import sys from collections.abc import Callable, Iterable -from typing import Any +from typing import Any, TypeVar from django.apps.config import AppConfig from django.contrib.admin.options import ModelAdmin @@ -24,6 +24,7 @@ else: all_sites: MutableSet[AdminSite] +_ViewType = TypeVar("_ViewType", bound=Callable[..., HttpResponse]) _ActionCallback: TypeAlias = Callable[[ModelAdmin, HttpRequest, QuerySet], TemplateResponse | None] class AlreadyRegistered(Exception): ... @@ -65,7 +66,7 @@ class AdminSite: @property def actions(self) -> Iterable[tuple[str, _ActionCallback]]: ... def has_permission(self, request: HttpRequest) -> bool: ... - def admin_view(self, view: Callable[..., HttpResponse], cacheable: bool = ...) -> Callable[..., HttpResponse]: ... + def admin_view(self, view: _ViewType, cacheable: bool = ...) -> _ViewType: ... def get_urls(self) -> list[URLResolver | URLPattern]: ... @property def urls(self) -> tuple[list[URLResolver | URLPattern], str, str]: ...