Skip to content

Commit

Permalink
Type django.views (#1716)
Browse files Browse the repository at this point in the history
* fix: removed argument

* fix: missing constant ERROR_PAGE_TEMPLATE

* fix: missing Logger

* fix: missing view_is_async

We use _Getter | bool here, as users could use @Property, @cached_property or a direct assign (there is some usage on Github)

* fix: attributes can be None

E.g. for template_name, is we only set the type as str, users might wrongfully access it, and type checking would not warn them that it can be None.
paginate_by can be None per get_paginate_by() documentation
packages defaults to and supports None according to JavaScriptCatalog.get() implementation

* fi: misc django.views

* chore: allowlist
  • Loading branch information
GabDug authored Sep 17, 2023
1 parent 3147e39 commit 5514e37
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 38 deletions.
7 changes: 7 additions & 0 deletions django-stubs/views/debug.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ DEBUG_ENGINE: Engine
class CallableSettingWrapper:
def __init__(self, callable_setting: Callable | type[Any]) -> None: ...

class ExceptionCycleWarning(UserWarning): ...

def technical_500_response(
request: HttpRequest,
exc_type: type[BaseException] | None,
Expand All @@ -29,6 +31,8 @@ class SafeExceptionReporterFilter:
hidden_settings: re.Pattern[str]
def cleanse_setting(self, key: int | str, value: Any) -> Any: ...
def get_safe_settings(self) -> dict[str, Any]: ...
def get_safe_request_meta(self, request: HttpRequest) -> dict[str, Any]: ...
def get_safe_cookies(self, request: HttpRequest) -> dict[str, Any]: ...
def is_active(self, request: HttpRequest | None) -> bool: ...
def get_cleansed_multivaluedict(self, request: HttpRequest, multivaluedict: QueryDict) -> QueryDict: ...
def get_post_parameters(self, request: HttpRequest | None) -> dict[str, Any]: ...
Expand Down Expand Up @@ -67,3 +71,6 @@ class ExceptionReporter:

def technical_404_response(request: HttpRequest, exception: Http404) -> HttpResponse: ...
def default_urlconf(request: HttpResponse | None) -> HttpResponse: ...
def builtin_template_path(name: str) -> Path: ...
def get_caller(request: HttpRequest) -> str: ...
def get_exception_reporter_class(request: HttpRequest) -> ExceptionReporter: ...
1 change: 1 addition & 0 deletions django-stubs/views/defaults.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ERROR_404_TEMPLATE_NAME: str
ERROR_403_TEMPLATE_NAME: str
ERROR_400_TEMPLATE_NAME: str
ERROR_500_TEMPLATE_NAME: str
ERROR_PAGE_TEMPLATE: str

def page_not_found(
request: HttpRequest, exception: Exception | None, template_name: str = ...
Expand Down
7 changes: 6 additions & 1 deletion django-stubs/views/generic/base.pyi
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import logging
from collections.abc import Callable, Sequence
from typing import Any

from django.http.request import HttpRequest
from django.http.response import HttpResponse, HttpResponseBase
from django.utils.functional import _Getter

logger: logging.Logger

class ContextMixin:
extra_context: dict[str, Any] | None
Expand All @@ -14,6 +18,7 @@ class View:
args: Any
kwargs: Any
def __init__(self, **kwargs: Any) -> None: ...
view_is_async: _Getter[bool] | bool
@classmethod
def as_view(cls: Any, **initkwargs: Any) -> Callable[..., HttpResponseBase]: ...
def setup(self, request: HttpRequest, *args: Any, **kwargs: Any) -> None: ...
Expand All @@ -22,7 +27,7 @@ class View:
def options(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponseBase: ...

class TemplateResponseMixin:
template_name: str
template_name: str | None
template_engine: str | None
response_class: type[HttpResponse]
content_type: str | None
Expand Down
21 changes: 10 additions & 11 deletions django-stubs/views/generic/dates.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ from django.db import models
from django.db.models.query import QuerySet
from django.http import HttpRequest, HttpResponse
from django.utils.datastructures import _IndexableCollection
from django.utils.functional import _Getter
from django.views.generic.base import View
from django.views.generic.detail import BaseDetailView, SingleObjectTemplateResponseMixin
from django.views.generic.list import MultipleObjectMixin, MultipleObjectTemplateResponseMixin
from typing_extensions import TypeAlias

_M = TypeVar("_M", bound=models.Model)
_DatedItems: TypeAlias = tuple[_IndexableCollection[datetime.date] | None, _IndexableCollection[_M], dict[str, Any]]

class YearMixin:
year_format: str
Expand Down Expand Up @@ -50,15 +52,12 @@ class DateMixin:
allow_future: bool
def get_date_field(self) -> str: ...
def get_allow_future(self) -> bool: ...
@property
def uses_datetime_field(self) -> bool: ...

DatedItems: TypeAlias = tuple[_IndexableCollection[datetime.date] | None, _IndexableCollection[_M], dict[str, Any]]
uses_datetime_field: _Getter[bool] | bool

class BaseDateListView(MultipleObjectMixin[_M], DateMixin, View):
date_list_period: str
def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
def get_dated_items(self) -> DatedItems: ...
def get_dated_items(self) -> _DatedItems: ...
def get_ordering(self) -> str | Sequence[str]: ...
def get_dated_queryset(self, **lookup: Any) -> models.query.QuerySet[_M]: ...
def get_date_list_period(self) -> str: ...
Expand All @@ -68,41 +67,41 @@ class BaseDateListView(MultipleObjectMixin[_M], DateMixin, View):

class BaseArchiveIndexView(BaseDateListView[_M]):
context_object_name: str
def get_dated_items(self) -> DatedItems[_M]: ...
def get_dated_items(self) -> _DatedItems[_M]: ...

class ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView):
template_name_suffix: str

class BaseYearArchiveView(YearMixin, BaseDateListView[_M]):
date_list_period: str
make_object_list: bool
def get_dated_items(self) -> DatedItems[_M]: ...
def get_dated_items(self) -> _DatedItems[_M]: ...
def get_make_object_list(self) -> bool: ...

class YearArchiveView(MultipleObjectTemplateResponseMixin, BaseYearArchiveView):
template_name_suffix: str

class BaseMonthArchiveView(YearMixin, MonthMixin, BaseDateListView[_M]):
date_list_period: str
def get_dated_items(self) -> DatedItems[_M]: ...
def get_dated_items(self) -> _DatedItems[_M]: ...

class MonthArchiveView(MultipleObjectTemplateResponseMixin, BaseMonthArchiveView):
template_name_suffix: str

class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView[_M]):
def get_dated_items(self) -> DatedItems[_M]: ...
def get_dated_items(self) -> _DatedItems[_M]: ...

class WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView):
template_name_suffix: str

class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView[_M]):
def get_dated_items(self) -> DatedItems[_M]: ...
def get_dated_items(self) -> _DatedItems[_M]: ...

class DayArchiveView(MultipleObjectTemplateResponseMixin, BaseDayArchiveView):
template_name_suffix: str

class BaseTodayArchiveView(BaseDayArchiveView[_M]):
def get_dated_items(self) -> DatedItems[_M]: ...
def get_dated_items(self) -> _DatedItems[_M]: ...

class TodayArchiveView(MultipleObjectTemplateResponseMixin, BaseTodayArchiveView):
template_name_suffix: str
Expand Down
3 changes: 3 additions & 0 deletions django-stubs/views/generic/edit.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ class DeletionMixin(Generic[_M]):

class BaseDeleteView(Generic[_M, _ModelFormT], DeletionMixin[_M], FormMixin[_ModelFormT], BaseDetailView[_M]):
object: _M
def __init__(self, *args: Any, **kwargs: Any) -> None: ...

class DeleteView(Generic[_M, _ModelFormT], SingleObjectTemplateResponseMixin, BaseDeleteView[_M, _ModelFormT]):
object: _M
template_name_suffix: str

class DeleteViewCustomDeleteWarning(Warning): ...
5 changes: 4 additions & 1 deletion django-stubs/views/generic/list.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class MultipleObjectMixin(Generic[_M], ContextMixin):
allow_empty: bool
queryset: _SupportsPagination[_M] | None
model: type[_M] | None
paginate_by: int
paginate_by: int | None
paginate_orphans: int
context_object_name: str | None
paginator_class: type[Paginator]
Expand All @@ -35,6 +35,9 @@ class MultipleObjectMixin(Generic[_M], ContextMixin):
def get_paginate_orphans(self) -> int: ...
def get_allow_empty(self) -> bool: ...
def get_context_object_name(self, object_list: _SupportsPagination[_M]) -> str | None: ...
def get_context_data(
self, *, object_list: _SupportsPagination[_M] | None = ..., **kwargs: Any
) -> dict[str, Any]: ...

class BaseListView(MultipleObjectMixin[_M], View):
object_list: _SupportsPagination[_M]
Expand Down
2 changes: 1 addition & 1 deletion django-stubs/views/i18n.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ js_catalog_template: str
class JavaScriptCatalog(View):
head: Callable
domain: str
packages: list[str]
packages: list[str] | None
translation: DjangoTranslation
def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
def get_paths(self, packages: list[str]) -> list[str]: ...
Expand Down
2 changes: 1 addition & 1 deletion django-stubs/views/static.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ DEFAULT_DIRECTORY_INDEX_TEMPLATE: str
template_translatable: Any

def directory_index(path: Any, fullpath: Any) -> HttpResponse: ...
def was_modified_since(header: str | None = ..., mtime: float = ..., size: int = ...) -> bool: ...
def was_modified_since(header: str | None = ..., mtime: float = ...) -> bool: ...
5 changes: 5 additions & 0 deletions scripts/stubtest/allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ django.utils.translation.template.context_re
django.utils.translation.template.constant_re
django.utils.translation.template.block_re
django.utils.version.version_component_re
django.views.debug.SafeExceptionReporterFilter.hidden_settings

# AlterTogetherOptionsOperation.option_name is set as None,
# but is required in the init, so we type it as str
django.db.migrations.operations.models.AlterTogetherOptionOperation.option_name

# Attributes defaulting to None messing with mypy
django.views.generic.detail.SingleObjectMixin.model
django.views.generic.edit.BaseDeleteView.form_class
23 changes: 0 additions & 23 deletions scripts/stubtest/allowlist_todo.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2321,29 +2321,6 @@ django.urls.path
django.urls.re_path
django.urls.resolvers.LocaleRegexDescriptor.__get__
django.urls.resolvers.ResolverMatch.__iter__
django.views.View.view_is_async
django.views.debug.ExceptionCycleWarning
django.views.debug.SafeExceptionReporterFilter.get_safe_cookies
django.views.debug.SafeExceptionReporterFilter.get_safe_request_meta
django.views.debug.SafeExceptionReporterFilter.hidden_settings
django.views.debug.builtin_template_path
django.views.debug.get_caller
django.views.debug.get_exception_reporter_class
django.views.defaults.ERROR_PAGE_TEMPLATE
django.views.generic.View.view_is_async
django.views.generic.base.TemplateResponseMixin.template_name
django.views.generic.base.View.view_is_async
django.views.generic.base.logger
django.views.generic.dates.DateMixin.uses_datetime_field
django.views.generic.dates.DatedItems
django.views.generic.detail.SingleObjectMixin.model
django.views.generic.edit.BaseDeleteView.__init__
django.views.generic.edit.BaseDeleteView.form_class
django.views.generic.edit.DeleteViewCustomDeleteWarning
django.views.generic.list.MultipleObjectMixin.get_context_data
django.views.generic.list.MultipleObjectMixin.paginate_by
django.views.i18n.JavaScriptCatalog.packages
django.views.static.was_modified_since

# Jinja related:
django.template.backends.jinja2.Jinja2.template_context_processors

0 comments on commit 5514e37

Please sign in to comment.