Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/pyright unknown #1873

Merged
merged 12 commits into from
Dec 21, 2023
16 changes: 8 additions & 8 deletions django-stubs/contrib/admin/options.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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: ...
Expand All @@ -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
Expand Down Expand Up @@ -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]: ...
Expand Down
4 changes: 2 additions & 2 deletions django-stubs/contrib/admin/sites.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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]: ...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, admin_view looks like a decorator. I think we want to use a TypeVar to not ruin any function signature using it. e.g.

Suggested change
def admin_view(self, view: Callable[..., HttpResponse], cacheable: bool = ...) -> Callable[..., HttpResponse]: ...
def admin_view(self, view: F, cacheable: bool = ...) -> F: ...

Where F could be a variable bound to a callable returning a HttpResponse

F = TypeVar("F", bound=Callable[..., HttpResponse])

def get_urls(self) -> list[URLResolver | URLPattern]: ...
@property
def urls(self) -> tuple[list[URLResolver | URLPattern], str, str]: ...
Expand Down
2 changes: 1 addition & 1 deletion django-stubs/core/cache/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ from .backends.base import InvalidCacheKey as InvalidCacheKey

DEFAULT_CACHE_ALIAS: str

class CacheHandler(BaseConnectionHandler):
class CacheHandler(BaseConnectionHandler[BaseCache]):
settings_name: str
exception_class: type[Exception]
def create_connection(self, alias: str) -> BaseCache: ...
Expand Down
9 changes: 7 additions & 2 deletions django-stubs/db/models/fields/json.pyi
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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, default=Any)
# __get__ return type
_GT = TypeVar("_GT", covariant=True, default=Any)
flaeppe marked this conversation as resolved.
Show resolved Hide resolved

class JSONField(CheckFieldDefaultMixin, Field[_ST, _GT]):
encoder: type[json.JSONEncoder] | None
decoder: type[json.JSONDecoder] | None
def __init__(
Expand Down
3 changes: 2 additions & 1 deletion django-stubs/db/models/manager.pyi
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions django-stubs/shortcuts.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion django-stubs/urls/base.pyi
Original file line number Diff line number Diff line change
@@ -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 = ...,
Expand Down
19 changes: 12 additions & 7 deletions django-stubs/utils/decorators.pyi
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
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
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)
_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: 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: _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: ...