mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-10 14:01:56 +08:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8978ad471f | ||
|
|
f7dfbefbd6 | ||
|
|
627daa55f5 | ||
|
|
194489ee8d | ||
|
|
1d2c7fb805 | ||
|
|
18c908bf98 | ||
|
|
e0e8814804 | ||
|
|
53f5d2214b | ||
|
|
9e4ed70fc5 | ||
|
|
18445f686f | ||
|
|
c962b8ac68 | ||
|
|
70c3126348 | ||
|
|
af8ecc5520 | ||
|
|
64f8870d0b | ||
|
|
df5c70c703 | ||
|
|
c09a97e005 | ||
|
|
0e30821ad3 | ||
|
|
2dadd681ff | ||
|
|
2dec3b4325 | ||
|
|
3b8c5d08e8 | ||
|
|
eaee3d390f | ||
|
|
b686751f19 | ||
|
|
73ea682356 | ||
|
|
9ea25f3e56 | ||
|
|
dacf88c692 | ||
|
|
3d14d07e4e | ||
|
|
6e6d1645d3 | ||
|
|
cda703a94b | ||
|
|
2bd018951b | ||
|
|
14ea848dd7 | ||
|
|
2d3b5492f0 | ||
|
|
194258ab8e | ||
|
|
116aa2c539 | ||
|
|
67c99434e5 | ||
|
|
5d8cdbcf29 | ||
|
|
78810f55b6 | ||
|
|
36662896bc | ||
|
|
e54dbb79c9 | ||
|
|
41f283552a | ||
|
|
ab73d53ae5 | ||
|
|
d24be4b35f | ||
|
|
9d60b472df | ||
|
|
632e063e22 | ||
|
|
66224416b5 |
22
.travis.yml
22
.travis.yml
@@ -4,20 +4,34 @@ dist: xenial
|
||||
sudo: required
|
||||
jobs:
|
||||
include:
|
||||
- name: Typecheck Django test suite
|
||||
python: 3.7
|
||||
script: 'python ./scripts/typecheck_tests.py'
|
||||
|
||||
- name: Run plugin test suite with python 3.7
|
||||
python: 3.7
|
||||
script: |
|
||||
set -e
|
||||
pytest
|
||||
|
||||
- name: Run plugin test suite with python 3.6
|
||||
python: 3.6
|
||||
script: |
|
||||
set -e
|
||||
pytest
|
||||
|
||||
- name: Typecheck Django test suite
|
||||
python: 3.7
|
||||
script: 'python ./scripts/typecheck_tests.py'
|
||||
|
||||
- name: Lint with black
|
||||
python: 3.7
|
||||
script: 'black --check --line-length=120 django-stubs/'
|
||||
|
||||
- name: Lint plugin code with flake8
|
||||
python: 3.7
|
||||
script: 'flake8'
|
||||
|
||||
- name: Lint plugin code with isort
|
||||
python: 3.7
|
||||
script: 'isort --check'
|
||||
|
||||
before_install: |
|
||||
# Upgrade pip, setuptools, and wheel
|
||||
pip install -U pip setuptools wheel
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
|
||||
This package contains type stubs and mypy plugin to provide more precise static types and type inference for Django framework. Django uses some Python "magic" that makes having precise types for some code patterns problematic. This is why we need to accompany the stubs with mypy plugins. The final goal is to be able to get precise types for most common patterns.
|
||||
|
||||
Supports Python 3.6/3.7, and Django 2.1.x series.
|
||||
|
||||
Could be run on earlier versions of Django, but expect some missing imports warnings.
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
black
|
||||
pytest-mypy-plugins
|
||||
flake8
|
||||
isort==4.3.4
|
||||
-e .
|
||||
|
||||
@@ -5,7 +5,7 @@ by the DJANGO_SETTINGS_MODULE environment variable.
|
||||
|
||||
# This is defined here as a do-nothing function because we can't import
|
||||
# django.utils.translation -- that module depends on the settings.
|
||||
from typing import Any, Dict, List, Optional, Pattern, Tuple, Protocol, Union, Callable, TYPE_CHECKING
|
||||
from typing import Any, Dict, List, Optional, Pattern, Tuple, Protocol, Union, Callable, TYPE_CHECKING, Sequence
|
||||
|
||||
####################
|
||||
# CORE #
|
||||
@@ -377,7 +377,7 @@ CACHE_MIDDLEWARE_ALIAS = "default"
|
||||
|
||||
AUTH_USER_MODEL: str = ...
|
||||
|
||||
AUTHENTICATION_BACKENDS: List[str] = ...
|
||||
AUTHENTICATION_BACKENDS: Sequence[str] = ...
|
||||
|
||||
LOGIN_URL = "/accounts/login/"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from collections import OrderedDict
|
||||
from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, Iterator
|
||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, Union
|
||||
|
||||
from django.contrib.admin.filters import ListFilter
|
||||
from django.contrib.admin.models import LogEntry
|
||||
@@ -8,7 +8,6 @@ from django.contrib.admin.views.main import ChangeList
|
||||
from django.contrib.auth.forms import AdminPasswordChangeForm
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.checks.messages import Error
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models.base import Model
|
||||
from django.db.models.fields.related import ForeignKey, ManyToManyField, RelatedField
|
||||
@@ -17,12 +16,13 @@ from django.db.models.query import QuerySet
|
||||
from django.forms.fields import TypedChoiceField
|
||||
from django.forms.models import ModelChoiceField, ModelMultipleChoiceField
|
||||
from django.forms.widgets import Media
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponse, HttpResponseBase, HttpResponseRedirect, JsonResponse
|
||||
from django.template.response import TemplateResponse
|
||||
from django.urls.resolvers import URLPattern
|
||||
from django.utils.safestring import SafeText
|
||||
|
||||
from django.db.models.fields import Field
|
||||
from django.template.response import TemplateResponse
|
||||
|
||||
IS_POPUP_VAR: str
|
||||
TO_FIELD_VAR: str
|
||||
@@ -58,40 +58,40 @@ class BaseModelAdmin:
|
||||
def check(self, **kwargs: Any) -> List[Union[str, Error]]: ...
|
||||
def __init__(self) -> None: ...
|
||||
def formfield_for_dbfield(
|
||||
self, db_field: Field, request: Optional[WSGIRequest], **kwargs: Any
|
||||
self, db_field: Field, request: Optional[HttpRequest], **kwargs: Any
|
||||
) -> Optional[Field]: ...
|
||||
def formfield_for_choice_field(
|
||||
self, db_field: Field, request: Optional[WSGIRequest], **kwargs: Any
|
||||
self, db_field: Field, request: Optional[HttpRequest], **kwargs: Any
|
||||
) -> TypedChoiceField: ...
|
||||
def get_field_queryset(
|
||||
self, db: None, db_field: RelatedField, request: Optional[WSGIRequest]
|
||||
self, db: None, db_field: RelatedField, request: Optional[HttpRequest]
|
||||
) -> Optional[QuerySet]: ...
|
||||
def formfield_for_foreignkey(
|
||||
self, db_field: ForeignKey, request: Optional[WSGIRequest], **kwargs: Any
|
||||
self, db_field: ForeignKey, request: Optional[HttpRequest], **kwargs: Any
|
||||
) -> Optional[ModelChoiceField]: ...
|
||||
def formfield_for_manytomany(
|
||||
self, db_field: ManyToManyField, request: Optional[WSGIRequest], **kwargs: Any
|
||||
self, db_field: ManyToManyField, request: Optional[HttpRequest], **kwargs: Any
|
||||
) -> ModelMultipleChoiceField: ...
|
||||
def get_autocomplete_fields(self, request: WSGIRequest) -> Tuple: ...
|
||||
def get_autocomplete_fields(self, request: HttpRequest) -> Tuple: ...
|
||||
def get_view_on_site_url(self, obj: Optional[Model] = ...) -> Optional[str]: ...
|
||||
def get_empty_value_display(self) -> SafeText: ...
|
||||
def get_exclude(self, request: WSGIRequest, obj: Optional[Model] = ...) -> Any: ...
|
||||
def get_fields(self, request: WSGIRequest, obj: Optional[Model] = ...) -> Sequence[Union[Callable, str]]: ...
|
||||
def get_exclude(self, request: HttpRequest, obj: Optional[Model] = ...) -> Any: ...
|
||||
def get_fields(self, request: HttpRequest, obj: Optional[Model] = ...) -> Sequence[Union[Callable, str]]: ...
|
||||
def get_fieldsets(
|
||||
self, request: WSGIRequest, obj: Optional[Model] = ...
|
||||
self, request: HttpRequest, obj: Optional[Model] = ...
|
||||
) -> List[Tuple[Optional[str], Dict[str, Any]]]: ...
|
||||
def get_ordering(self, request: WSGIRequest) -> Union[List[str], Tuple]: ...
|
||||
def get_readonly_fields(self, request: WSGIRequest, obj: Optional[Model] = ...) -> Union[List[str], Tuple]: ...
|
||||
def get_prepopulated_fields(self, request: WSGIRequest, obj: Optional[Model] = ...) -> Dict[str, Tuple[str]]: ...
|
||||
def get_queryset(self, request: WSGIRequest) -> QuerySet: ...
|
||||
def get_sortable_by(self, request: WSGIRequest) -> Union[List[Callable], List[str], Tuple]: ...
|
||||
def get_ordering(self, request: HttpRequest) -> Union[List[str], Tuple]: ...
|
||||
def get_readonly_fields(self, request: HttpRequest, obj: Optional[Model] = ...) -> Union[List[str], Tuple]: ...
|
||||
def get_prepopulated_fields(self, request: HttpRequest, obj: Optional[Model] = ...) -> Dict[str, Tuple[str]]: ...
|
||||
def get_queryset(self, request: HttpRequest) -> QuerySet: ...
|
||||
def get_sortable_by(self, request: HttpRequest) -> Union[List[Callable], List[str], Tuple]: ...
|
||||
def lookup_allowed(self, lookup: str, value: str) -> bool: ...
|
||||
def to_field_allowed(self, request: WSGIRequest, to_field: str) -> bool: ...
|
||||
def has_add_permission(self, request: WSGIRequest, obj: Optional[Model] = ...) -> bool: ...
|
||||
def has_change_permission(self, request: WSGIRequest, obj: Optional[Model] = ...) -> bool: ...
|
||||
def has_delete_permission(self, request: WSGIRequest, obj: Optional[Model] = ...) -> bool: ...
|
||||
def has_view_permission(self, request: WSGIRequest, obj: Optional[Model] = ...) -> bool: ...
|
||||
def has_module_permission(self, request: WSGIRequest) -> bool: ...
|
||||
def to_field_allowed(self, request: HttpRequest, to_field: str) -> bool: ...
|
||||
def has_add_permission(self, request: HttpRequest, obj: Optional[Model] = ...) -> bool: ...
|
||||
def has_change_permission(self, request: HttpRequest, obj: Optional[Model] = ...) -> bool: ...
|
||||
def has_delete_permission(self, request: HttpRequest, obj: Optional[Model] = ...) -> bool: ...
|
||||
def has_view_permission(self, request: HttpRequest, obj: Optional[Model] = ...) -> bool: ...
|
||||
def has_module_permission(self, request: HttpRequest) -> bool: ...
|
||||
|
||||
class ModelAdmin(BaseModelAdmin):
|
||||
formfield_overrides: Any
|
||||
@@ -127,54 +127,54 @@ class ModelAdmin(BaseModelAdmin):
|
||||
opts: Options = ...
|
||||
admin_site: AdminSite = ...
|
||||
def __init__(self, model: Type[Model], admin_site: Optional[AdminSite]) -> None: ...
|
||||
def get_inline_instances(self, request: WSGIRequest, obj: Optional[Model] = ...) -> List[InlineModelAdmin]: ...
|
||||
def get_inline_instances(self, request: HttpRequest, obj: Optional[Model] = ...) -> List[InlineModelAdmin]: ...
|
||||
def get_urls(self) -> List[URLPattern]: ...
|
||||
@property
|
||||
def urls(self) -> List[URLPattern]: ...
|
||||
@property
|
||||
def media(self) -> Media: ...
|
||||
def get_model_perms(self, request: WSGIRequest) -> Dict[str, bool]: ...
|
||||
def get_model_perms(self, request: HttpRequest) -> Dict[str, bool]: ...
|
||||
def get_form(self, request: Any, obj: Optional[Any] = ..., change: bool = ..., **kwargs: Any): ...
|
||||
def get_changelist(self, request: WSGIRequest, **kwargs: Any) -> Type[ChangeList]: ...
|
||||
def get_changelist_instance(self, request: WSGIRequest) -> ChangeList: ...
|
||||
def get_object(self, request: WSGIRequest, object_id: str, from_field: None = ...) -> Optional[Model]: ...
|
||||
def get_changelist(self, request: HttpRequest, **kwargs: Any) -> Type[ChangeList]: ...
|
||||
def get_changelist_instance(self, request: HttpRequest) -> ChangeList: ...
|
||||
def get_object(self, request: HttpRequest, object_id: str, from_field: None = ...) -> Optional[Model]: ...
|
||||
def get_changelist_form(self, request: Any, **kwargs: Any): ...
|
||||
def get_changelist_formset(self, request: Any, **kwargs: Any): ...
|
||||
def get_formsets_with_inlines(self, request: WSGIRequest, obj: Optional[Model] = ...) -> Iterator[Any]: ...
|
||||
def get_formsets_with_inlines(self, request: HttpRequest, obj: Optional[Model] = ...) -> Iterator[Any]: ...
|
||||
def get_paginator(
|
||||
self,
|
||||
request: WSGIRequest,
|
||||
request: HttpRequest,
|
||||
queryset: QuerySet,
|
||||
per_page: int,
|
||||
orphans: int = ...,
|
||||
allow_empty_first_page: bool = ...,
|
||||
) -> Paginator: ...
|
||||
def log_addition(self, request: WSGIRequest, object: Model, message: Any) -> LogEntry: ...
|
||||
def log_change(self, request: WSGIRequest, object: Model, message: Any) -> LogEntry: ...
|
||||
def log_deletion(self, request: WSGIRequest, object: Model, object_repr: str) -> LogEntry: ...
|
||||
def log_addition(self, request: HttpRequest, object: Model, message: Any) -> LogEntry: ...
|
||||
def log_change(self, request: HttpRequest, object: Model, message: Any) -> LogEntry: ...
|
||||
def log_deletion(self, request: HttpRequest, object: Model, object_repr: str) -> LogEntry: ...
|
||||
def action_checkbox(self, obj: Model) -> SafeText: ...
|
||||
def get_actions(self, request: WSGIRequest) -> OrderedDict: ...
|
||||
def get_actions(self, request: HttpRequest) -> OrderedDict: ...
|
||||
def get_action_choices(
|
||||
self, request: WSGIRequest, default_choices: List[Tuple[str, str]] = ...
|
||||
self, request: HttpRequest, default_choices: List[Tuple[str, str]] = ...
|
||||
) -> List[Tuple[str, str]]: ...
|
||||
def get_action(self, action: Union[Callable, str]) -> Tuple[Callable, str, str]: ...
|
||||
def get_list_display(self, request: WSGIRequest) -> Sequence[str]: ...
|
||||
def get_list_display_links(self, request: WSGIRequest, list_display: Sequence[str]) -> Optional[Sequence[str]]: ...
|
||||
def get_list_filter(self, request: WSGIRequest) -> Sequence[str]: ...
|
||||
def get_list_select_related(self, request: WSGIRequest) -> Sequence[str]: ...
|
||||
def get_search_fields(self, request: WSGIRequest) -> List[str]: ...
|
||||
def get_list_display(self, request: HttpRequest) -> Sequence[str]: ...
|
||||
def get_list_display_links(self, request: HttpRequest, list_display: Sequence[str]) -> Optional[Sequence[str]]: ...
|
||||
def get_list_filter(self, request: HttpRequest) -> Sequence[str]: ...
|
||||
def get_list_select_related(self, request: HttpRequest) -> Sequence[str]: ...
|
||||
def get_search_fields(self, request: HttpRequest) -> List[str]: ...
|
||||
def get_search_results(
|
||||
self, request: WSGIRequest, queryset: QuerySet, search_term: str
|
||||
self, request: HttpRequest, queryset: QuerySet, search_term: str
|
||||
) -> Tuple[QuerySet, bool]: ...
|
||||
def get_preserved_filters(self, request: WSGIRequest) -> str: ...
|
||||
def _get_edited_object_pks(self, request: WSGIRequest, prefix: str) -> List[str]: ...
|
||||
def _get_list_editable_queryset(self, request: WSGIRequest, prefix: str) -> QuerySet: ...
|
||||
def get_preserved_filters(self, request: HttpRequest) -> str: ...
|
||||
def _get_edited_object_pks(self, request: HttpRequest, prefix: str) -> List[str]: ...
|
||||
def _get_list_editable_queryset(self, request: HttpRequest, prefix: str) -> QuerySet: ...
|
||||
def construct_change_message(
|
||||
self, request: WSGIRequest, form: AdminPasswordChangeForm, formsets: None, add: bool = ...
|
||||
self, request: HttpRequest, form: AdminPasswordChangeForm, formsets: None, add: bool = ...
|
||||
) -> List[Dict[str, Dict[str, List[str]]]]: ...
|
||||
def message_user(
|
||||
self,
|
||||
request: WSGIRequest,
|
||||
request: HttpRequest,
|
||||
message: str,
|
||||
level: Union[int, str] = ...,
|
||||
extra_tags: str = ...,
|
||||
@@ -182,8 +182,8 @@ class ModelAdmin(BaseModelAdmin):
|
||||
) -> None: ...
|
||||
def save_form(self, request: Any, form: Any, change: Any): ...
|
||||
def save_model(self, request: Any, obj: Any, form: Any, change: Any) -> None: ...
|
||||
def delete_model(self, request: WSGIRequest, obj: Model) -> None: ...
|
||||
def delete_queryset(self, request: WSGIRequest, queryset: QuerySet) -> None: ...
|
||||
def delete_model(self, request: HttpRequest, obj: Model) -> None: ...
|
||||
def delete_queryset(self, request: HttpRequest, queryset: QuerySet) -> None: ...
|
||||
def save_formset(self, request: Any, form: Any, formset: Any, change: Any) -> None: ...
|
||||
def save_related(self, request: Any, form: Any, formsets: Any, change: Any) -> None: ...
|
||||
def render_change_form(
|
||||
@@ -196,52 +196,51 @@ class ModelAdmin(BaseModelAdmin):
|
||||
obj: Optional[Any] = ...,
|
||||
): ...
|
||||
def response_add(
|
||||
self, request: WSGIRequest, obj: Model, post_url_continue: Optional[str] = ...
|
||||
self, request: HttpRequest, obj: Model, post_url_continue: Optional[str] = ...
|
||||
) -> HttpResponse: ...
|
||||
def response_change(self, request: WSGIRequest, obj: Model) -> HttpResponse: ...
|
||||
def response_post_save_add(self, request: WSGIRequest, obj: Model) -> HttpResponseRedirect: ...
|
||||
def response_post_save_change(self, request: WSGIRequest, obj: Model) -> HttpResponseRedirect: ...
|
||||
def response_action(self, request: WSGIRequest, queryset: QuerySet) -> Optional[HttpResponseBase]: ...
|
||||
def response_delete(self, request: WSGIRequest, obj_display: str, obj_id: int) -> HttpResponse: ...
|
||||
def response_change(self, request: HttpRequest, obj: Model) -> HttpResponse: ...
|
||||
def response_post_save_add(self, request: HttpRequest, obj: Model) -> HttpResponseRedirect: ...
|
||||
def response_post_save_change(self, request: HttpRequest, obj: Model) -> HttpResponseRedirect: ...
|
||||
def response_action(self, request: HttpRequest, queryset: QuerySet) -> Optional[HttpResponseBase]: ...
|
||||
def response_delete(self, request: HttpRequest, obj_display: str, obj_id: int) -> HttpResponse: ...
|
||||
def render_delete_form(self, request: Any, context: Any): ...
|
||||
def get_inline_formsets(
|
||||
self, request: WSGIRequest, formsets: List[Any], inline_instances: List[Any], obj: Optional[Model] = ...
|
||||
self, request: HttpRequest, formsets: List[Any], inline_instances: List[Any], obj: Optional[Model] = ...
|
||||
) -> List[Any]: ...
|
||||
def get_changeform_initial_data(self, request: WSGIRequest) -> Dict[str, str]: ...
|
||||
def get_changeform_initial_data(self, request: HttpRequest) -> Dict[str, str]: ...
|
||||
def changeform_view(
|
||||
self,
|
||||
request: WSGIRequest,
|
||||
request: HttpRequest,
|
||||
object_id: Optional[str] = ...,
|
||||
form_url: str = ...,
|
||||
extra_context: Optional[Dict[str, bool]] = ...,
|
||||
) -> Any: ...
|
||||
def autocomplete_view(self, request: WSGIRequest) -> JsonResponse: ...
|
||||
def add_view(self, request: WSGIRequest, form_url: str = ..., extra_context: None = ...) -> HttpResponse: ...
|
||||
def autocomplete_view(self, request: HttpRequest) -> JsonResponse: ...
|
||||
def add_view(self, request: HttpRequest, form_url: str = ..., extra_context: None = ...) -> HttpResponse: ...
|
||||
def change_view(
|
||||
self, request: WSGIRequest, object_id: str, form_url: str = ..., extra_context: Optional[Dict[str, bool]] = ...
|
||||
self, request: HttpRequest, object_id: str, form_url: str = ..., extra_context: Optional[Dict[str, bool]] = ...
|
||||
) -> HttpResponse: ...
|
||||
def changelist_view(
|
||||
self, request: WSGIRequest, extra_context: Optional[Dict[str, str]] = ...
|
||||
self, request: HttpRequest, extra_context: Optional[Dict[str, str]] = ...
|
||||
) -> TemplateResponse: ...
|
||||
def get_deleted_objects(
|
||||
self, objs: QuerySet, request: WSGIRequest
|
||||
self, objs: QuerySet, request: HttpRequest
|
||||
) -> Tuple[List[Any], Dict[Any, Any], Set[Any], List[Any]]: ...
|
||||
def delete_view(self, request: WSGIRequest, object_id: str, extra_context: None = ...) -> Any: ...
|
||||
def history_view(self, request: WSGIRequest, object_id: str, extra_context: None = ...) -> HttpResponse: ...
|
||||
def delete_view(self, request: HttpRequest, object_id: str, extra_context: None = ...) -> Any: ...
|
||||
def history_view(self, request: HttpRequest, object_id: str, extra_context: None = ...) -> HttpResponse: ...
|
||||
|
||||
class InlineModelAdmin(BaseModelAdmin):
|
||||
model: Any = ...
|
||||
fk_name: Any = ...
|
||||
formset: Any = ...
|
||||
extra: int = ...
|
||||
min_num: Any = ...
|
||||
max_num: Any = ...
|
||||
template: Any = ...
|
||||
verbose_name: Any = ...
|
||||
verbose_name_plural: Any = ...
|
||||
min_num: Optional[int] = ...
|
||||
max_num: Optional[int] = ...
|
||||
template: str = ...
|
||||
verbose_name: Optional[str] = ...
|
||||
verbose_name_plural: Optional[str] = ...
|
||||
can_delete: bool = ...
|
||||
show_change_link: bool = ...
|
||||
checks_class: Any = ...
|
||||
classes: Any = ...
|
||||
admin_site: Any = ...
|
||||
parent_model: Any = ...
|
||||
@@ -250,18 +249,10 @@ class InlineModelAdmin(BaseModelAdmin):
|
||||
def __init__(self, parent_model: Union[Type[Model], Model], admin_site: AdminSite) -> None: ...
|
||||
@property
|
||||
def media(self) -> Media: ...
|
||||
def get_extra(self, request: WSGIRequest, obj: Optional[Model] = ..., **kwargs: Any) -> int: ...
|
||||
def get_min_num(self, request: WSGIRequest, obj: Optional[Model] = ..., **kwargs: Any) -> None: ...
|
||||
def get_max_num(self, request: WSGIRequest, obj: Optional[Model] = ..., **kwargs: Any) -> Optional[int]: ...
|
||||
fields: Any = ...
|
||||
def get_extra(self, request: HttpRequest, obj: Optional[Model] = ..., **kwargs: Any) -> int: ...
|
||||
def get_min_num(self, request: HttpRequest, obj: Optional[Model] = ..., **kwargs: Any) -> Optional[int]: ...
|
||||
def get_max_num(self, request: HttpRequest, obj: Optional[Model] = ..., **kwargs: Any) -> Optional[int]: ...
|
||||
def get_formset(self, request: Any, obj: Optional[Any] = ..., **kwargs: Any): ...
|
||||
def get_queryset(self, request: WSGIRequest) -> QuerySet: ...
|
||||
def has_change_permission(self, request: WSGIRequest, obj: Optional[Model] = ...) -> bool: ...
|
||||
def has_delete_permission(self, request: WSGIRequest, obj: Optional[Model] = ...) -> bool: ...
|
||||
def has_view_permission(self, request: WSGIRequest, obj: Optional[Model] = ...) -> bool: ...
|
||||
|
||||
class StackedInline(InlineModelAdmin):
|
||||
template: str = ...
|
||||
|
||||
class TabularInline(InlineModelAdmin):
|
||||
template: str = ...
|
||||
class StackedInline(InlineModelAdmin): ...
|
||||
class TabularInline(InlineModelAdmin): ...
|
||||
|
||||
@@ -44,7 +44,6 @@ class UserCreationForm(forms.ModelForm):
|
||||
password2: Any = ...
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
||||
def clean_password2(self) -> str: ...
|
||||
def save(self, commit: bool = ...) -> User: ...
|
||||
|
||||
class UserChangeForm(forms.ModelForm):
|
||||
auto_id: str
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from typing import Any, Callable, List, Optional
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django import http
|
||||
from django.http.response import HttpResponse, HttpResponseRedirect
|
||||
|
||||
class AccessMixin:
|
||||
@@ -14,15 +14,15 @@ class AccessMixin:
|
||||
def handle_no_permission(self) -> HttpResponseRedirect: ...
|
||||
|
||||
class LoginRequiredMixin(AccessMixin):
|
||||
def dispatch(self, request: WSGIRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
def dispatch(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
|
||||
class PermissionRequiredMixin(AccessMixin):
|
||||
permission_required: Any = ...
|
||||
def get_permission_required(self) -> List[str]: ...
|
||||
def has_permission(self) -> bool: ...
|
||||
def dispatch(self, request: WSGIRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
def dispatch(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
|
||||
class UserPassesTestMixin(AccessMixin):
|
||||
def test_func(self) -> None: ...
|
||||
def get_test_func(self) -> Callable: ...
|
||||
def dispatch(self, request: WSGIRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
def dispatch(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from typing import Any
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponse
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
||||
class RedirectFallbackMiddleware(MiddlewareMixin):
|
||||
response_gone_class: Any = ...
|
||||
response_redirect_class: Any = ...
|
||||
def process_response(self, request: WSGIRequest, response: HttpResponse) -> HttpResponse: ...
|
||||
def process_response(self, request: HttpRequest, response: HttpResponse) -> HttpResponse: ...
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Any, Dict, Optional, Type
|
||||
|
||||
from django.contrib.sessions.backends.base import SessionBase
|
||||
|
||||
from django.db import models
|
||||
|
||||
class BaseSessionManager(models.Manager):
|
||||
creation_counter: int
|
||||
model: None
|
||||
name: None
|
||||
def encode(self, session_dict: Dict[str, int]) -> str: ...
|
||||
def save(self, session_key: str, session_dict: Dict[str, int], expire_date: datetime) -> AbstractBaseSession: ...
|
||||
|
||||
class AbstractBaseSession(models.Model):
|
||||
session_key: Any = ...
|
||||
session_data: Any = ...
|
||||
expire_date: Any = ...
|
||||
expire_date: datetime
|
||||
session_data: str
|
||||
session_key: str
|
||||
objects: Any = ...
|
||||
@classmethod
|
||||
def get_session_store_class(cls) -> None: ...
|
||||
def get_session_store_class(cls) -> Optional[Type[SessionBase]]: ...
|
||||
def get_decoded(self) -> Dict[str, int]: ...
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
from typing import Any, Optional, Type
|
||||
|
||||
from django.contrib.sessions.backends.db import SessionStore
|
||||
from django.contrib.sessions.base_session import AbstractBaseSession, BaseSessionManager
|
||||
|
||||
class SessionManager(BaseSessionManager):
|
||||
creation_counter: int
|
||||
model: None
|
||||
name: None
|
||||
use_in_migrations: bool = ...
|
||||
|
||||
class Session(AbstractBaseSession):
|
||||
expire_date: datetime.datetime
|
||||
session_data: str
|
||||
session_key: str
|
||||
objects: Any = ...
|
||||
@classmethod
|
||||
def get_session_store_class(cls) -> Type[SessionStore]: ...
|
||||
class SessionManager(BaseSessionManager): ...
|
||||
class Session(AbstractBaseSession): ...
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Dict
|
||||
|
||||
from django.core.signing import JSONSerializer as BaseJSONSerializer
|
||||
from django.db.models.base import Model
|
||||
|
||||
@@ -11,7 +11,7 @@ PING_URL: str
|
||||
|
||||
class SitemapNotFound(Exception): ...
|
||||
|
||||
def ping_google(sitemap_url: None = ..., ping_url: str = ...) -> None: ...
|
||||
def ping_google(sitemap_url: Optional[str] = ..., ping_url: str = ...) -> None: ...
|
||||
|
||||
class Sitemap:
|
||||
limit: int = ...
|
||||
@@ -22,14 +22,14 @@ class Sitemap:
|
||||
def paginator(self) -> Paginator: ...
|
||||
def get_urls(
|
||||
self, page: Union[int, str] = ..., site: Optional[Union[Site, RequestSite]] = ..., protocol: Optional[str] = ...
|
||||
) -> List[Dict[str, Optional[Union[datetime, Model, str]]]]: ...
|
||||
) -> List[Dict[str, Any]]: ...
|
||||
|
||||
class GenericSitemap(Sitemap):
|
||||
priority: None = ...
|
||||
changefreq: None = ...
|
||||
priority: Optional[float] = ...
|
||||
changefreq: Optional[str] = ...
|
||||
queryset: QuerySet = ...
|
||||
date_field: None = ...
|
||||
protocol: None = ...
|
||||
protocol: Optional[str] = ...
|
||||
def __init__(
|
||||
self,
|
||||
info_dict: Dict[str, Union[datetime, QuerySet, str]],
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
from collections import OrderedDict
|
||||
from typing import Any, Callable, Dict, Optional, Type, Union
|
||||
from typing import Callable, Dict, Optional, Type, Union
|
||||
|
||||
from django.http.request import HttpRequest
|
||||
from django.template.response import TemplateResponse
|
||||
|
||||
from django.contrib.sitemaps import GenericSitemap, Sitemap
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.template.response import TemplateResponse
|
||||
|
||||
def x_robots_tag(func: Callable) -> Callable: ...
|
||||
def index(
|
||||
request: WSGIRequest,
|
||||
request: HttpRequest,
|
||||
sitemaps: Dict[str, Union[Type[Sitemap], Sitemap]],
|
||||
template_name: str = ...,
|
||||
content_type: str = ...,
|
||||
sitemap_url_name: str = ...,
|
||||
) -> TemplateResponse: ...
|
||||
def sitemap(
|
||||
request: WSGIRequest,
|
||||
request: HttpRequest,
|
||||
sitemaps: Union[Dict[str, Type[Sitemap]], Dict[str, GenericSitemap], OrderedDict],
|
||||
section: Optional[str] = ...,
|
||||
template_name: str = ...,
|
||||
|
||||
2
django-stubs/core/cache/__init__.pyi
vendored
2
django-stubs/core/cache/__init__.pyi
vendored
@@ -1,7 +1,7 @@
|
||||
from collections import OrderedDict
|
||||
from typing import Any, Callable, Dict, Union
|
||||
|
||||
from django.core.cache.backends.base import BaseCache as BaseCache
|
||||
from .backends.base import BaseCache as BaseCache
|
||||
|
||||
DEFAULT_CACHE_ALIAS: str
|
||||
|
||||
|
||||
4
django-stubs/core/cache/utils.pyi
vendored
4
django-stubs/core/cache/utils.pyi
vendored
@@ -1,5 +1,5 @@
|
||||
from typing import Any, List, Optional, Union
|
||||
from typing import Any, Iterable, Optional
|
||||
|
||||
TEMPLATE_FRAGMENT_KEY_TEMPLATE: str
|
||||
|
||||
def make_template_fragment_key(fragment_name: str, vary_on: Optional[Union[List[int], List[str]]] = ...) -> str: ...
|
||||
def make_template_fragment_key(fragment_name: str, vary_on: Optional[Iterable[Any]] = ...) -> str: ...
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Any, Dict, Iterator, List, Optional, Tuple, Type, Union
|
||||
from typing import Any, Dict, Iterator, List, Mapping, Optional, Tuple, Union
|
||||
|
||||
from django.db.models.base import Model
|
||||
from django.forms.utils import ErrorDict
|
||||
|
||||
class FieldDoesNotExist(Exception): ...
|
||||
@@ -31,20 +30,13 @@ class ValidationError(Exception):
|
||||
message: Any = ...
|
||||
code: Any = ...
|
||||
params: Any = ...
|
||||
def __init__(
|
||||
self,
|
||||
message: Any,
|
||||
code: Optional[str] = ...,
|
||||
params: Optional[
|
||||
Union[Dict[str, Union[Tuple[str], Type[Model], Model, str]], Dict[str, Union[int, str]]]
|
||||
] = ...,
|
||||
) -> None: ...
|
||||
def __init__(self, message: Any, code: Optional[str] = ..., params: Optional[Mapping[str, Any]] = ...) -> None: ...
|
||||
@property
|
||||
def message_dict(self) -> Dict[str, List[str]]: ...
|
||||
@property
|
||||
def messages(self) -> List[str]: ...
|
||||
def update_error_dict(
|
||||
self, error_dict: Union[Dict[str, List[ValidationError]], ErrorDict]
|
||||
self, error_dict: Mapping[str, Any]
|
||||
) -> Union[Dict[str, List[ValidationError]], ErrorDict]: ...
|
||||
def __iter__(self) -> Iterator[Union[Tuple[str, List[str]], str]]: ...
|
||||
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
from datetime import datetime
|
||||
from io import StringIO, TextIOWrapper
|
||||
from typing import Any, List, Optional, Tuple, Union
|
||||
from typing import Any, IO, List, Optional, Tuple
|
||||
|
||||
from django.core.files.base import File
|
||||
from django.utils.functional import LazyObject
|
||||
|
||||
class Storage:
|
||||
def open(self, name: str, mode: str = ...) -> File: ...
|
||||
def save(
|
||||
self, name: Optional[str], content: Union[StringIO, TextIOWrapper, File], max_length: Optional[int] = ...
|
||||
) -> str: ...
|
||||
def save(self, name: Optional[str], content: IO[Any], max_length: Optional[int] = ...) -> str: ...
|
||||
def get_valid_name(self, name: str) -> str: ...
|
||||
def get_available_name(self, name: str, max_length: Optional[int] = ...) -> str: ...
|
||||
def generate_filename(self, filename: str) -> str: ...
|
||||
|
||||
@@ -39,10 +39,10 @@ class InMemoryUploadedFile(UploadedFile):
|
||||
charset: Optional[str],
|
||||
content_type_extra: Dict[str, str] = ...,
|
||||
) -> None: ...
|
||||
def chunks(self, chunk_size: int = None) -> Iterator[bytes]: ...
|
||||
def multiple_chunks(self, chunk_size: int = None) -> bool: ...
|
||||
def chunks(self, chunk_size: Optional[int] = ...) -> Iterator[bytes]: ...
|
||||
def multiple_chunks(self, chunk_size: Optional[int] = ...) -> bool: ...
|
||||
|
||||
class SimpleUploadedFile(InMemoryUploadedFile):
|
||||
def __init__(self, name: str, content: bytes, content_type: str = "") -> None: ...
|
||||
def __init__(self, name: str, content: Optional[Union[bytes, str]], content_type: str = ...) -> None: ...
|
||||
@classmethod
|
||||
def from_dict(cls: Any, file_dict: Dict[str, Union[str, bytes]]) -> None: ...
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from typing import Any, Callable
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponse, HttpResponseBase
|
||||
|
||||
logger: Any
|
||||
@@ -13,5 +13,5 @@ class BaseHandler:
|
||||
def load_middleware(self) -> None: ...
|
||||
def make_view_atomic(self, view: Callable) -> Callable: ...
|
||||
def get_exception_response(self, request: Any, resolver: Any, status_code: Any, exception: Any): ...
|
||||
def get_response(self, request: WSGIRequest) -> HttpResponseBase: ...
|
||||
def process_exception_by_middleware(self, exception: Exception, request: WSGIRequest) -> HttpResponse: ...
|
||||
def get_response(self, request: HttpRequest) -> HttpResponseBase: ...
|
||||
def process_exception_by_middleware(self, exception: Exception, request: HttpRequest) -> HttpResponse: ...
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
from typing import Any, Callable
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponse
|
||||
from django.urls.resolvers import URLResolver
|
||||
|
||||
def convert_exception_to_response(get_response: Callable) -> Callable: ...
|
||||
def response_for_exception(request: WSGIRequest, exc: Exception) -> HttpResponse: ...
|
||||
def response_for_exception(request: HttpRequest, exc: Exception) -> HttpResponse: ...
|
||||
def get_exception_response(
|
||||
request: WSGIRequest, resolver: URLResolver, status_code: int, exception: Exception, sender: None = ...
|
||||
request: HttpRequest, resolver: URLResolver, status_code: int, exception: Exception, sender: None = ...
|
||||
) -> HttpResponse: ...
|
||||
def handle_uncaught_exception(request: Any, resolver: Any, exc_info: Any): ...
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
from typing import Any, List, Optional, Tuple
|
||||
|
||||
from django.core.mail.backends.base import BaseEmailBackend
|
||||
from django.core.mail.message import DEFAULT_ATTACHMENT_MIME_TYPE as DEFAULT_ATTACHMENT_MIME_TYPE
|
||||
from django.core.mail.message import BadHeaderError as BadHeaderError
|
||||
from django.core.mail.message import EmailMessage as EmailMessage
|
||||
from django.core.mail.message import EmailMultiAlternatives as EmailMultiAlternatives
|
||||
from django.core.mail.message import SafeMIMEMultipart as SafeMIMEMultipart
|
||||
from django.core.mail.message import SafeMIMEText as SafeMIMEText
|
||||
from django.core.mail.message import forbid_multi_line_headers as forbid_multi_line_headers
|
||||
from django.core.mail.utils import DNS_NAME as DNS_NAME
|
||||
from django.core.mail.utils import CachedDnsName as CachedDnsName
|
||||
from .backends.base import BaseEmailBackend
|
||||
from .message import (
|
||||
BadHeaderError as BadHeaderError,
|
||||
DEFAULT_ATTACHMENT_MIME_TYPE as DEFAULT_ATTACHMENT_MIME_TYPE,
|
||||
EmailMessage as EmailMessage,
|
||||
EmailMultiAlternatives as EmailMultiAlternatives,
|
||||
SafeMIMEMultipart as SafeMIMEMultipart,
|
||||
SafeMIMEText as SafeMIMEText,
|
||||
forbid_multi_line_headers as forbid_multi_line_headers,
|
||||
)
|
||||
from .utils import CachedDnsName as CachedDnsName, DNS_NAME as DNS_NAME
|
||||
|
||||
def get_connection(backend: Optional[str] = ..., fail_silently: bool = ..., **kwds: Any) -> BaseEmailBackend: ...
|
||||
def send_mail(
|
||||
@@ -18,17 +19,17 @@ def send_mail(
|
||||
from_email: Optional[str],
|
||||
recipient_list: List[str],
|
||||
fail_silently: bool = ...,
|
||||
auth_user: None = ...,
|
||||
auth_password: None = ...,
|
||||
auth_user: Optional[str] = ...,
|
||||
auth_password: Optional[str] = ...,
|
||||
connection: Optional[BaseEmailBackend] = ...,
|
||||
html_message: Optional[str] = ...,
|
||||
) -> int: ...
|
||||
def send_mass_mail(
|
||||
datatuple: List[Tuple[str, str, str, List[str]]],
|
||||
fail_silently: bool = ...,
|
||||
auth_user: None = ...,
|
||||
auth_password: None = ...,
|
||||
connection: BaseEmailBackend = ...,
|
||||
auth_user: Optional[str] = ...,
|
||||
auth_password: Optional[str] = ...,
|
||||
connection: Optional[BaseEmailBackend] = ...,
|
||||
) -> int: ...
|
||||
def mail_admins(
|
||||
subject: str,
|
||||
@@ -45,4 +46,4 @@ def mail_managers(
|
||||
html_message: Optional[str] = ...,
|
||||
) -> None: ...
|
||||
|
||||
outbox = [EmailMessage()]
|
||||
outbox: List[EmailMessage] = ...
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import email
|
||||
from email._policybase import Policy
|
||||
from email.mime.message import MIMEMessage
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union, Sequence
|
||||
|
||||
from django.core.mail.backends.base import BaseEmailBackend
|
||||
from django.utils.safestring import SafeText
|
||||
@@ -27,14 +27,14 @@ class MIMEMixin:
|
||||
class SafeMIMEMessage(MIMEMixin, MIMEMessage):
|
||||
defects: List[Any]
|
||||
epilogue: None
|
||||
policy: email._policybase.Compat32
|
||||
policy: Policy
|
||||
preamble: None
|
||||
def __setitem__(self, name: str, val: str) -> None: ...
|
||||
|
||||
class SafeMIMEText(MIMEMixin, MIMEText):
|
||||
defects: List[Any]
|
||||
epilogue: None
|
||||
policy: email._policybase.Compat32
|
||||
policy: Policy
|
||||
preamble: None
|
||||
encoding: str = ...
|
||||
def __init__(self, _text: str, _subtype: str = ..., _charset: str = ...) -> None: ...
|
||||
@@ -44,7 +44,7 @@ class SafeMIMEText(MIMEMixin, MIMEText):
|
||||
class SafeMIMEMultipart(MIMEMixin, MIMEMultipart):
|
||||
defects: List[Any]
|
||||
epilogue: None
|
||||
policy: email._policybase.Compat32
|
||||
policy: Policy
|
||||
preamble: None
|
||||
encoding: str = ...
|
||||
def __init__(
|
||||
@@ -71,12 +71,12 @@ class EmailMessage:
|
||||
subject: str = ...,
|
||||
body: Optional[str] = ...,
|
||||
from_email: Optional[str] = ...,
|
||||
to: Optional[Union[List[str], Tuple[str, str], str]] = ...,
|
||||
bcc: Optional[Union[List[str], Tuple[str], str]] = ...,
|
||||
to: Optional[Union[Sequence[str], str]] = ...,
|
||||
bcc: Optional[Union[Sequence[str], str]] = ...,
|
||||
connection: Optional[BaseEmailBackend] = ...,
|
||||
attachments: Optional[Union[List[Tuple[str, str]], List[MIMEText]]] = ...,
|
||||
headers: Optional[Dict[str, str]] = ...,
|
||||
cc: Optional[Union[List[str], Tuple[str, str], str]] = ...,
|
||||
cc: Optional[Union[Sequence[str], str]] = ...,
|
||||
reply_to: Optional[Union[List[Optional[str]], str]] = ...,
|
||||
) -> None: ...
|
||||
def get_connection(self, fail_silently: bool = ...) -> BaseEmailBackend: ...
|
||||
|
||||
@@ -11,7 +11,6 @@ class Node:
|
||||
parents: Set[Any] = ...
|
||||
def __init__(self, key: Tuple[str, str]) -> None: ...
|
||||
def __lt__(self, other: Union[Tuple[str, str], Node]) -> bool: ...
|
||||
def __hash__(self) -> int: ...
|
||||
def __getitem__(self, item: int) -> str: ...
|
||||
def add_child(self, child: Node) -> None: ...
|
||||
def add_parent(self, parent: Node) -> None: ...
|
||||
@@ -19,13 +18,9 @@ class Node:
|
||||
def descendants(self) -> List[Tuple[str, str]]: ...
|
||||
|
||||
class DummyNode(Node):
|
||||
children: Set[Any]
|
||||
key: Tuple[str, str]
|
||||
parents: Set[Any]
|
||||
origin: Any = ...
|
||||
error_message: Any = ...
|
||||
def __init__(self, key: Tuple[str, str], origin: Union[Migration, str], error_message: str) -> None: ...
|
||||
__class__: Any = ...
|
||||
def promote(self) -> None: ...
|
||||
def raise_error(self) -> None: ...
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from typing import Any, Dict, Optional, Set, Tuple, Union, Sequence
|
||||
from typing import Any, Dict, Optional, Sequence, Set, Tuple, Union
|
||||
|
||||
from django.db import DefaultConnectionProxy
|
||||
from django.db.backends.base.base import BaseDatabaseWrapper
|
||||
from django.db.backends.sqlite3.base import DatabaseWrapper
|
||||
from django.db.migrations.migration import Migration, SwappableTuple
|
||||
from django.db.migrations.state import ProjectState
|
||||
|
||||
from django.db import DefaultConnectionProxy
|
||||
|
||||
MIGRATIONS_MODULE_NAME: str
|
||||
|
||||
class MigrationLoader:
|
||||
|
||||
@@ -13,7 +13,6 @@ class Migration:
|
||||
name: str = ...
|
||||
app_label: str = ...
|
||||
def __init__(self, name: str, app_label: str) -> None: ...
|
||||
def __hash__(self) -> int: ...
|
||||
def mutate_state(self, project_state: ProjectState, preserve: bool = ...) -> ProjectState: ...
|
||||
def apply(
|
||||
self, project_state: ProjectState, schema_editor: BaseDatabaseSchemaEditor, collect_sql: bool = ...
|
||||
@@ -24,6 +23,6 @@ class Migration:
|
||||
|
||||
class SwappableTuple(tuple):
|
||||
setting: str = ...
|
||||
def __new__(cls: Type[SwappableTuple], value: Tuple[str, str], setting: str) -> SwappableTuple: ...
|
||||
def __new__(cls, value: Tuple[str, str], setting: str) -> SwappableTuple: ...
|
||||
|
||||
def swappable_dependency(value: str) -> SwappableTuple: ...
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
# Stubs for django.db.migrations.operations (Python 3.6)
|
||||
#
|
||||
# NOTE: This dynamically typed stub was automatically generated by stubgen.
|
||||
|
||||
from .fields import (
|
||||
AddField as AddField,
|
||||
AlterField as AlterField,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, List, Optional, Type
|
||||
from typing import Any, List
|
||||
|
||||
class Operation:
|
||||
reversible: bool = ...
|
||||
@@ -6,7 +6,6 @@ class Operation:
|
||||
atomic: bool = ...
|
||||
elidable: bool = ...
|
||||
serialization_expand_args: Any = ...
|
||||
def __new__(cls: Type[Operation], *args: Any, **kwargs: Any) -> Operation: ...
|
||||
def deconstruct(self): ...
|
||||
def state_forwards(self, app_label: Any, state: Any) -> None: ...
|
||||
def database_forwards(self, app_label: Any, schema_editor: Any, from_state: Any, to_state: Any) -> None: ...
|
||||
|
||||
@@ -12,7 +12,6 @@ class ModelOperation(Operation):
|
||||
def name_lower(self) -> str: ...
|
||||
|
||||
class CreateModel(ModelOperation):
|
||||
serialization_expand_args: Any = ...
|
||||
fields: Sequence[Tuple[str, Field]] = ...
|
||||
options: Any = ...
|
||||
bases: Optional[Sequence[Union[type, str]]] = ...
|
||||
@@ -63,7 +62,6 @@ class AlterModelOptions(ModelOptionOperation):
|
||||
def __init__(self, name: str, options: Dict[str, Any]) -> None: ...
|
||||
|
||||
class AlterModelManagers(ModelOptionOperation):
|
||||
serialization_expand_args: Any = ...
|
||||
managers: Any = ...
|
||||
def __init__(self, name: Any, managers: Any) -> None: ...
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Callable, Optional, Sequence, Dict
|
||||
from typing import Any, Callable, Dict, Optional, Sequence
|
||||
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
from django.db.migrations.state import StateApps
|
||||
@@ -6,7 +6,6 @@ from django.db.migrations.state import StateApps
|
||||
from .base import Operation
|
||||
|
||||
class SeparateDatabaseAndState(Operation):
|
||||
serialization_expand_args: Any = ...
|
||||
database_operations: Sequence[Operation] = ...
|
||||
state_operations: Sequence[Operation] = ...
|
||||
def __init__(
|
||||
@@ -19,7 +18,6 @@ class RunSQL(Operation):
|
||||
reverse_sql: Any = ...
|
||||
state_operations: Any = ...
|
||||
hints: Any = ...
|
||||
elidable: Any = ...
|
||||
def __init__(
|
||||
self,
|
||||
sql: Any,
|
||||
@@ -30,12 +28,9 @@ class RunSQL(Operation):
|
||||
) -> None: ...
|
||||
|
||||
class RunPython(Operation):
|
||||
reduces_to_sql: bool = ...
|
||||
atomic: bool = ...
|
||||
code: Callable = ...
|
||||
reverse_code: Optional[Callable] = ...
|
||||
hints: Optional[Dict[str, Any]] = ...
|
||||
elidable: bool = ...
|
||||
def __init__(
|
||||
self,
|
||||
code: Callable,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Any, Optional
|
||||
|
||||
from django.db.migrations.state import ProjectState
|
||||
|
||||
from django.db.models.fields import Field
|
||||
|
||||
def is_referenced_by_foreign_key(state: ProjectState, model_name_lower: str, field: Field, field_name: str) -> bool: ...
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Any, List, Optional
|
||||
from typing import List, Optional
|
||||
|
||||
from django.db.migrations.operations.base import Operation
|
||||
|
||||
class MigrationOptimizer:
|
||||
def optimize(self, operations: List[Operation], app_label: str = ...) -> List[Operation]: ...
|
||||
def optimize_inner(self, operations: List[Operation], app_label: str = ...) -> List[Operation]: ...
|
||||
def optimize(self, operations: List[Operation], app_label: Optional[str] = ...) -> List[Operation]: ...
|
||||
def optimize_inner(self, operations: List[Operation], app_label: Optional[str] = ...) -> List[Operation]: ...
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
from typing import Any, Dict, Optional, Set
|
||||
|
||||
from django.db.migrations.state import ModelState
|
||||
|
||||
from django.db.models.fields import Field
|
||||
|
||||
from .loader import MigrationLoader
|
||||
|
||||
class MigrationQuestioner:
|
||||
defaults: Dict[Any, Any] = ...
|
||||
specified_apps: Set[Any] = ...
|
||||
dry_run: None = ...
|
||||
defaults: Dict[str, Any] = ...
|
||||
specified_apps: Set[str] = ...
|
||||
dry_run: Optional[bool] = ...
|
||||
def __init__(
|
||||
self,
|
||||
defaults: Optional[Dict[str, bool]] = ...,
|
||||
@@ -23,21 +22,5 @@ class MigrationQuestioner:
|
||||
def ask_merge(self, app_label: str) -> bool: ...
|
||||
def ask_auto_now_add_addition(self, field_name: str, model_name: str) -> None: ...
|
||||
|
||||
class InteractiveMigrationQuestioner(MigrationQuestioner):
|
||||
defaults: Dict[Any, Any]
|
||||
dry_run: bool
|
||||
specified_apps: Set[str]
|
||||
def ask_not_null_addition(self, field_name: str, model_name: str) -> None: ...
|
||||
def ask_not_null_alteration(self, field_name: Any, model_name: Any): ...
|
||||
def ask_rename(self, model_name: Any, old_name: Any, new_name: Any, field_instance: Any): ...
|
||||
def ask_rename_model(self, old_model_state: Any, new_model_state: Any): ...
|
||||
def ask_merge(self, app_label: str) -> bool: ...
|
||||
def ask_auto_now_add_addition(self, field_name: str, model_name: str) -> int: ...
|
||||
|
||||
class NonInteractiveMigrationQuestioner(MigrationQuestioner):
|
||||
defaults: Dict[Any, Any]
|
||||
dry_run: bool
|
||||
specified_apps: Set[str]
|
||||
def ask_not_null_addition(self, field_name: Any, model_name: Any) -> None: ...
|
||||
def ask_not_null_alteration(self, field_name: Any, model_name: Any): ...
|
||||
def ask_auto_now_add_addition(self, field_name: Any, model_name: Any) -> None: ...
|
||||
class InteractiveMigrationQuestioner(MigrationQuestioner): ...
|
||||
class NonInteractiveMigrationQuestioner(MigrationQuestioner): ...
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
from typing import Any, Optional, Set, Tuple, Union
|
||||
from typing import Any, Optional, Set, Tuple
|
||||
|
||||
from django.db import models
|
||||
from django.db.backends.base.base import BaseDatabaseWrapper
|
||||
from django.db.models.query import QuerySet
|
||||
|
||||
from django.db import models
|
||||
|
||||
class MigrationRecorder:
|
||||
class Migration(models.Model):
|
||||
app: Any = ...
|
||||
|
||||
@@ -1,88 +1,40 @@
|
||||
from typing import Any, Callable, Dict, List, Set, Tuple, Union
|
||||
|
||||
from django.db.models.fields import Field
|
||||
|
||||
class BaseSerializer:
|
||||
value: Any = ...
|
||||
def __init__(self, value: Any) -> None: ...
|
||||
def serialize(self) -> None: ...
|
||||
def serialize(self) -> Any: ...
|
||||
|
||||
class BaseSequenceSerializer(BaseSerializer):
|
||||
def serialize(self) -> Tuple[str, Set[str]]: ...
|
||||
|
||||
class BaseSimpleSerializer(BaseSerializer):
|
||||
value: str
|
||||
def serialize(self) -> Tuple[str, Set[Any]]: ...
|
||||
|
||||
class DatetimeSerializer(BaseSerializer):
|
||||
value: Any = ...
|
||||
def serialize(self): ...
|
||||
|
||||
class DateSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class DecimalSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
class BaseSequenceSerializer(BaseSerializer): ...
|
||||
class BaseSimpleSerializer(BaseSerializer): ...
|
||||
class DatetimeSerializer(BaseSerializer): ...
|
||||
class DateSerializer(BaseSerializer): ...
|
||||
class DecimalSerializer(BaseSerializer): ...
|
||||
|
||||
class DeconstructableSerializer(BaseSerializer):
|
||||
@staticmethod
|
||||
def serialize_deconstructed(
|
||||
path: str, args: List[Any], kwargs: Dict[str, Union[Callable, int, str]]
|
||||
) -> Tuple[str, Set[str]]: ...
|
||||
def serialize(self): ...
|
||||
|
||||
class DictionarySerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class EnumSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class FloatSerializer(BaseSimpleSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class DictionarySerializer(BaseSerializer): ...
|
||||
class EnumSerializer(BaseSerializer): ...
|
||||
class FloatSerializer(BaseSimpleSerializer): ...
|
||||
class FrozensetSerializer(BaseSequenceSerializer): ...
|
||||
|
||||
class FunctionTypeSerializer(BaseSerializer):
|
||||
value: Callable
|
||||
def serialize(self) -> Tuple[str, Set[str]]: ...
|
||||
|
||||
class FunctoolsPartialSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class IterableSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class ModelFieldSerializer(DeconstructableSerializer):
|
||||
value: Field
|
||||
def serialize(self) -> Tuple[str, Set[str]]: ...
|
||||
|
||||
class ModelManagerSerializer(DeconstructableSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class OperationSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class RegexSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class FunctionTypeSerializer(BaseSerializer): ...
|
||||
class FunctoolsPartialSerializer(BaseSerializer): ...
|
||||
class IterableSerializer(BaseSerializer): ...
|
||||
class ModelFieldSerializer(DeconstructableSerializer): ...
|
||||
class ModelManagerSerializer(DeconstructableSerializer): ...
|
||||
class OperationSerializer(BaseSerializer): ...
|
||||
class RegexSerializer(BaseSerializer): ...
|
||||
class SequenceSerializer(BaseSequenceSerializer): ...
|
||||
class SetSerializer(BaseSequenceSerializer): ...
|
||||
|
||||
class SettingsReferenceSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class TimedeltaSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class TimeSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class SettingsReferenceSerializer(BaseSerializer): ...
|
||||
class TimedeltaSerializer(BaseSerializer): ...
|
||||
class TimeSerializer(BaseSerializer): ...
|
||||
class TupleSerializer(BaseSequenceSerializer): ...
|
||||
|
||||
class TypeSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
|
||||
class UUIDSerializer(BaseSerializer):
|
||||
def serialize(self): ...
|
||||
class TypeSerializer(BaseSerializer): ...
|
||||
class UUIDSerializer(BaseSerializer): ...
|
||||
|
||||
def serializer_factory(value: Any) -> BaseSerializer: ...
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
from typing import Any, Dict, Iterator, List, Optional, Tuple, Type, DefaultDict, Union, Sequence
|
||||
from typing import Any, DefaultDict, Dict, Iterator, List, Optional, Sequence, Tuple, Type, Union
|
||||
|
||||
from django.apps.registry import Apps
|
||||
from django.db.models.base import Model
|
||||
from django.db.models.manager import Manager
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
from django.db.models.fields import Field
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Dict, Iterator, List, Optional, Set
|
||||
from typing import Dict, Iterator, List, Set
|
||||
|
||||
from django.db.migrations.operations.base import Operation
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
from typing import Any, Optional
|
||||
|
||||
from django.utils.functional import SimpleLazyObject
|
||||
from typing import Any
|
||||
|
||||
COMPILED_REGEX_TYPE: Any
|
||||
|
||||
class RegexObject:
|
||||
pattern: str = ...
|
||||
flags: int = ...
|
||||
def __init__(self, obj: SimpleLazyObject) -> None: ...
|
||||
def __init__(self, obj: Any) -> None: ...
|
||||
|
||||
def get_migration_name_timestamp() -> str: ...
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
from typing import Any, Optional, Set, Tuple, Type, List, Union
|
||||
from typing import Any, List, Set, Tuple, Union
|
||||
|
||||
from django.db.migrations.migration import Migration
|
||||
from django.db.migrations.operations.base import Operation
|
||||
|
||||
from django.db.migrations.operations.models import CreateModel
|
||||
|
||||
class SettingsReference(str):
|
||||
def __new__(self: Type[SettingsReference], value: str, setting_name: str) -> SettingsReference: ...
|
||||
setting_name: str = ...
|
||||
def __init__(self, value: str, setting_name: str) -> None: ...
|
||||
|
||||
class OperationWriter:
|
||||
|
||||
@@ -8,7 +8,6 @@ from django.core.exceptions import FieldDoesNotExist as FieldDoesNotExist
|
||||
from django.db.models.expressions import Combinable
|
||||
from django.db.models.query_utils import RegisterLookupMixin
|
||||
from django.forms import Field as FormField, Widget
|
||||
from typing_extensions import Literal
|
||||
|
||||
from .mixins import NOT_PROVIDED as NOT_PROVIDED
|
||||
|
||||
@@ -72,7 +71,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
|
||||
def to_python(self, value: Any) -> Any: ...
|
||||
|
||||
class IntegerField(Field[_ST, _GT]):
|
||||
_pyi_private_set_type: Union[int, Combinable, Literal[""]]
|
||||
_pyi_private_set_type: Union[float, int, str, Combinable]
|
||||
_pyi_private_get_type: int
|
||||
|
||||
class PositiveIntegerRelDbTypeMixin:
|
||||
|
||||
@@ -84,9 +84,7 @@ class QuerySet(Iterable[_T], Sized):
|
||||
def latest(self, *fields: Any, field_name: Optional[Any] = ...) -> _T: ...
|
||||
def first(self) -> Optional[_T]: ...
|
||||
def last(self) -> Optional[_T]: ...
|
||||
def in_bulk(
|
||||
self, id_list: Any = ..., *, field_name: str = ..., **kwargs: Any
|
||||
) -> Dict[Union[int, str], models.Model]: ...
|
||||
def in_bulk(self, id_list: Iterable[Any] = ..., *, field_name: str = ...) -> Dict[Any, _T]: ...
|
||||
def delete(self) -> Tuple[int, Dict[str, int]]: ...
|
||||
def update(self, **kwargs: Any) -> int: ...
|
||||
def _update(self, values: Any) -> Optional[Any]: ...
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from contextlib import ContextDecorator
|
||||
from typing import Any, Callable, Optional, Union, Iterator, overload, ContextManager
|
||||
from typing import Any, Callable, Optional, overload, TypeVar
|
||||
|
||||
from django.db import ProgrammingError
|
||||
|
||||
@@ -18,19 +17,23 @@ def get_rollback(using: None = ...) -> bool: ...
|
||||
def set_rollback(rollback: bool, using: Optional[str] = ...) -> None: ...
|
||||
def on_commit(func: Callable, using: None = ...) -> None: ...
|
||||
|
||||
class Atomic(ContextDecorator):
|
||||
_C = TypeVar("_C", bound=Callable) # Any callable
|
||||
|
||||
# Don't inherit from ContextDecorator, so we can provide a more specific signature for __call__
|
||||
class Atomic:
|
||||
using: Optional[str] = ...
|
||||
savepoint: bool = ...
|
||||
def __init__(self, using: Optional[str], savepoint: bool) -> None: ...
|
||||
# When decorating, return the decorated function as-is, rather than clobbering it as ContextDecorator does.
|
||||
def __call__(self, func: _C) -> _C: ...
|
||||
def __enter__(self) -> None: ...
|
||||
def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None: ...
|
||||
|
||||
# Bare decorator
|
||||
@overload
|
||||
def atomic() -> Atomic: ...
|
||||
def atomic(using: _C) -> _C: ...
|
||||
|
||||
# Decorator or context-manager with parameters
|
||||
@overload
|
||||
def atomic(using: Optional[str] = ...,) -> ContextManager[Atomic]: ...
|
||||
@overload
|
||||
def atomic(using: Callable = ...) -> Callable: ...
|
||||
@overload
|
||||
def atomic(using: Optional[str] = ..., savepoint: bool = ...) -> ContextManager[Atomic]: ...
|
||||
def atomic(using: Optional[str] = None, savepoint: bool = True) -> Atomic: ...
|
||||
def non_atomic_requests(using: Callable = ...) -> Callable: ...
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import decimal
|
||||
from datetime import date, datetime, time, timedelta
|
||||
from datetime import datetime, timedelta
|
||||
from decimal import Decimal
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Union, Type
|
||||
from uuid import UUID
|
||||
from typing import Any, Callable, List, Optional, Pattern, Sequence, Type, Union
|
||||
|
||||
from django.core.files.base import File
|
||||
from django.core.validators import BaseValidator
|
||||
from django.db.models.fields.files import FieldFile
|
||||
from django.forms.boundfield import BoundField
|
||||
from django.forms.forms import BaseForm
|
||||
from django.forms.widgets import Widget
|
||||
@@ -31,16 +27,16 @@ class Field:
|
||||
self,
|
||||
*,
|
||||
required: bool = ...,
|
||||
widget: Optional[Any] = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Any = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
def prepare_value(self, value: Any) -> Any: ...
|
||||
def to_python(self, value: Optional[Any]) -> Optional[Any]: ...
|
||||
@@ -49,60 +45,60 @@ class Field:
|
||||
def clean(self, value: Any) -> Any: ...
|
||||
def bound_data(self, data: Any, initial: Any) -> Any: ...
|
||||
def widget_attrs(self, widget: Widget) -> Any: ...
|
||||
def has_changed(self, initial: Any, data: Optional[str]) -> bool: ...
|
||||
def has_changed(self, initial: Any, data: Any) -> bool: ...
|
||||
def get_bound_field(self, form: BaseForm, field_name: str) -> BoundField: ...
|
||||
def __deepcopy__(self, memo: Dict[Any, Any]) -> Field: ...
|
||||
|
||||
class CharField(Field):
|
||||
disabled: bool
|
||||
error_messages: Dict[str, str]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
max_length: Optional[Union[int, str]] = ...
|
||||
min_length: Optional[Union[int, str]] = ...
|
||||
strip: bool = ...
|
||||
empty_value: Optional[str] = ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
max_length: Optional[Any] = ...,
|
||||
min_length: Optional[Any] = ...,
|
||||
strip: bool = ...,
|
||||
empty_value: str = ...,
|
||||
**kwargs: Any
|
||||
empty_value: Optional[str] = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
|
||||
class IntegerField(Field):
|
||||
disabled: bool
|
||||
error_messages: Dict[str, str]
|
||||
max_value: Optional[Any]
|
||||
min_value: Optional[Any]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
default_error_messages: Any = ...
|
||||
re_decimal: Any = ...
|
||||
def __init__(self, *, max_value: Optional[Any] = ..., min_value: Optional[Any] = ..., **kwargs: Any) -> None: ...
|
||||
def __init__(
|
||||
self,
|
||||
max_value: Optional[Any] = ...,
|
||||
min_value: Optional[Any] = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
|
||||
class FloatField(IntegerField):
|
||||
disabled: bool
|
||||
error_messages: Dict[str, str]
|
||||
max_value: Optional[float]
|
||||
min_value: Optional[float]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
default_error_messages: Any = ...
|
||||
def validate(self, value: Optional[float]) -> None: ...
|
||||
|
||||
class DecimalField(IntegerField):
|
||||
decimal_places: Optional[int]
|
||||
disabled: bool
|
||||
error_messages: Dict[str, str]
|
||||
max_digits: Optional[int]
|
||||
max_value: Optional[Union[decimal.Decimal, int]]
|
||||
min_value: Optional[Union[decimal.Decimal, int]]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
default_error_messages: Any = ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -110,118 +106,95 @@ class DecimalField(IntegerField):
|
||||
min_value: Optional[Any] = ...,
|
||||
max_digits: Optional[Any] = ...,
|
||||
decimal_places: Optional[Any] = ...,
|
||||
**kwargs: Any
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
def validate(self, value: Optional[Decimal]) -> None: ...
|
||||
|
||||
class BaseTemporalField(Field):
|
||||
input_formats: Any = ...
|
||||
def __init__(self, *, input_formats: Optional[Any] = ..., **kwargs: Any) -> None: ...
|
||||
def strptime(self, value: Any, format: Any) -> Any: ...
|
||||
def __init__(
|
||||
self,
|
||||
input_formats: Optional[Any] = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
def strptime(self, value: Any, format: str) -> Any: ...
|
||||
|
||||
class DateField(BaseTemporalField):
|
||||
disabled: bool
|
||||
error_messages: Dict[str, str]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
input_formats: Any = ...
|
||||
default_error_messages: Any = ...
|
||||
def strptime(self, value: str, format: str) -> date: ...
|
||||
|
||||
class TimeField(BaseTemporalField):
|
||||
disabled: bool
|
||||
error_messages: Dict[str, str]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
input_formats: Any = ...
|
||||
default_error_messages: Any = ...
|
||||
def strptime(self, value: str, format: str) -> time: ...
|
||||
|
||||
class DateTimeField(BaseTemporalField):
|
||||
disabled: bool
|
||||
error_messages: Dict[str, str]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
input_formats: Any = ...
|
||||
default_error_messages: Any = ...
|
||||
def prepare_value(self, value: Optional[datetime]) -> Optional[datetime]: ...
|
||||
def strptime(self, value: str, format: str) -> datetime: ...
|
||||
class DateField(BaseTemporalField): ...
|
||||
class TimeField(BaseTemporalField): ...
|
||||
class DateTimeField(BaseTemporalField): ...
|
||||
|
||||
class DurationField(Field):
|
||||
disabled: bool
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
default_error_messages: Any = ...
|
||||
def prepare_value(self, value: Optional[Union[timedelta, str]]) -> Optional[str]: ...
|
||||
|
||||
class RegexField(CharField):
|
||||
disabled: bool
|
||||
empty_value: str
|
||||
error_messages: Dict[str, str]
|
||||
max_length: Optional[int]
|
||||
min_length: Optional[int]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
strip: bool
|
||||
def __init__(self, regex: str, **kwargs: Any) -> None: ...
|
||||
regex: Any = ...
|
||||
regex: str = ...
|
||||
def __init__(
|
||||
self,
|
||||
regex: Union[str, Pattern],
|
||||
max_length: Optional[Any] = ...,
|
||||
min_length: Optional[Any] = ...,
|
||||
strip: bool = ...,
|
||||
empty_value: Optional[str] = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
|
||||
class EmailField(CharField):
|
||||
disabled: bool
|
||||
empty_value: Optional[str]
|
||||
error_messages: Dict[str, str]
|
||||
max_length: Optional[int]
|
||||
min_length: Optional[int]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
strip: bool
|
||||
default_validators: Any = ...
|
||||
def __init__(self, **kwargs: Any) -> None: ...
|
||||
class EmailField(CharField): ...
|
||||
|
||||
class FileField(Field):
|
||||
disabled: bool
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
default_error_messages: Any = ...
|
||||
max_length: Optional[int] = ...
|
||||
allow_empty_file: bool = ...
|
||||
def __init__(self, *, max_length: Optional[Any] = ..., allow_empty_file: bool = ..., **kwargs: Any) -> None: ...
|
||||
def bound_data(self, data: Any, initial: Optional[FieldFile]) -> Optional[Union[File, str]]: ...
|
||||
def __init__(
|
||||
self,
|
||||
max_length: Optional[Any] = ...,
|
||||
allow_empty_file: bool = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
def clean(self, data: Any, initial: Optional[Any] = ...): ...
|
||||
|
||||
class ImageField(FileField):
|
||||
allow_empty_file: bool
|
||||
disabled: bool
|
||||
max_length: Optional[int]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
default_validators: Any = ...
|
||||
default_error_messages: Any = ...
|
||||
|
||||
class URLField(CharField):
|
||||
disabled: bool
|
||||
empty_value: Optional[str]
|
||||
error_messages: Dict[str, str]
|
||||
max_length: Optional[int]
|
||||
min_length: Optional[int]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
strip: bool
|
||||
default_error_messages: Any = ...
|
||||
default_validators: Any = ...
|
||||
def __init__(self, **kwargs: Any) -> None: ...
|
||||
|
||||
class BooleanField(Field):
|
||||
disabled: bool
|
||||
error_messages: Dict[str, str]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
def validate(self, value: bool) -> None: ...
|
||||
|
||||
class NullBooleanField(BooleanField):
|
||||
disabled: bool
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
def validate(self, value: Optional[bool]) -> None: ...
|
||||
class ImageField(FileField): ...
|
||||
class URLField(CharField): ...
|
||||
class BooleanField(Field): ...
|
||||
class NullBooleanField(BooleanField): ...
|
||||
|
||||
class CallableChoiceIterator:
|
||||
choices_func: Callable = ...
|
||||
@@ -229,125 +202,191 @@ class CallableChoiceIterator:
|
||||
def __iter__(self) -> None: ...
|
||||
|
||||
class ChoiceField(Field):
|
||||
disabled: bool
|
||||
error_messages: Dict[str, str]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
default_error_messages: Any = ...
|
||||
choices: Any = ...
|
||||
def __init__(self, *, choices: Any = ..., **kwargs: Any) -> None: ...
|
||||
def validate(self, value: Any) -> None: ...
|
||||
def __init__(
|
||||
self,
|
||||
choices: Any = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
def valid_value(self, value: str) -> bool: ...
|
||||
|
||||
class TypedChoiceField(ChoiceField):
|
||||
disabled: bool
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
coerce: Union[Callable, Type[Union[bool, float, str]]] = ...
|
||||
coerce: Union[Callable, Type[Any]] = ...
|
||||
empty_value: Optional[str] = ...
|
||||
def __init__(self, *, coerce: Any = ..., empty_value: str = ..., **kwargs: Any) -> None: ...
|
||||
def __init__(
|
||||
self,
|
||||
coerce: Any = ...,
|
||||
empty_value: Optional[str] = ...,
|
||||
choices: Any = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
|
||||
class MultipleChoiceField(ChoiceField):
|
||||
disabled: bool
|
||||
error_messages: Dict[str, str]
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
hidden_widget: Any = ...
|
||||
default_error_messages: Any = ...
|
||||
def validate(self, value: List[str]) -> None: ...
|
||||
class MultipleChoiceField(ChoiceField): ...
|
||||
|
||||
class TypedMultipleChoiceField(MultipleChoiceField):
|
||||
disabled: bool
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
coerce: Union[Callable, Type[float]] = ...
|
||||
empty_value: Optional[List[Any]] = ...
|
||||
def __init__(self, *, coerce: Any = ..., **kwargs: Any) -> None: ...
|
||||
def validate(self, value: List[str]) -> None: ...
|
||||
def __init__(
|
||||
self,
|
||||
coerce: Any = ...,
|
||||
empty_value: Optional[str] = ...,
|
||||
choices: Any = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
|
||||
class ComboField(Field):
|
||||
disabled: bool
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
fields: Any = ...
|
||||
def __init__(self, fields: List[CharField], **kwargs: Any) -> None: ...
|
||||
def __init__(
|
||||
self,
|
||||
fields: Sequence[Field],
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
|
||||
class MultiValueField(Field):
|
||||
disabled: bool
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
default_error_messages: Any = ...
|
||||
require_all_fields: bool = ...
|
||||
fields: Any = ...
|
||||
def __init__(self, fields: Tuple[Field, Field], *, require_all_fields: bool = ..., **kwargs: Any) -> None: ...
|
||||
def validate(self, value: Union[datetime, str]) -> None: ...
|
||||
def __init__(
|
||||
self,
|
||||
fields: Sequence[Field],
|
||||
require_all_fields: bool = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
def compress(self, data_list: Any) -> Any: ...
|
||||
|
||||
class FilePathField(ChoiceField):
|
||||
allow_files: bool
|
||||
allow_folders: bool
|
||||
disabled: bool
|
||||
match: Optional[str]
|
||||
path: str
|
||||
recursive: bool
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
choices: Any = ...
|
||||
match_re: Any = ...
|
||||
def __init__(
|
||||
self,
|
||||
path: str,
|
||||
*,
|
||||
match: Optional[Any] = ...,
|
||||
recursive: bool = ...,
|
||||
allow_files: bool = ...,
|
||||
allow_folders: bool = ...,
|
||||
**kwargs: Any
|
||||
choices: Any = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
|
||||
class SplitDateTimeField(MultiValueField):
|
||||
disabled: bool
|
||||
require_all_fields: bool
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
hidden_widget: Any = ...
|
||||
default_error_messages: Any = ...
|
||||
def __init__(
|
||||
self, *, input_date_formats: Optional[Any] = ..., input_time_formats: Optional[Any] = ..., **kwargs: Any
|
||||
self,
|
||||
input_date_formats: Optional[Any] = ...,
|
||||
input_time_formats: Optional[Any] = ...,
|
||||
fields: Sequence[Field] = ...,
|
||||
require_all_fields: bool = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
def compress(self, data_list: List[Optional[datetime]]) -> Optional[datetime]: ...
|
||||
|
||||
class GenericIPAddressField(CharField):
|
||||
disabled: bool
|
||||
empty_value: str
|
||||
error_messages: Dict[str, str]
|
||||
max_length: None
|
||||
min_length: None
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
strip: bool
|
||||
unpack_ipv4: bool = ...
|
||||
default_validators: List[Callable] = ...
|
||||
def __init__(self, *, protocol: str = ..., unpack_ipv4: bool = ..., **kwargs: Any) -> None: ...
|
||||
def __init__(
|
||||
self,
|
||||
protocol: str = ...,
|
||||
unpack_ipv4: bool = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
|
||||
class SlugField(CharField):
|
||||
disabled: bool
|
||||
empty_value: str
|
||||
max_length: Optional[int]
|
||||
min_length: None
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
strip: bool
|
||||
allow_unicode: bool = ...
|
||||
def __init__(self, *, allow_unicode: bool = ..., **kwargs: Any) -> None: ...
|
||||
def __init__(
|
||||
self,
|
||||
allow_unicode: bool = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
initial: Optional[Any] = ...,
|
||||
help_text: str = ...,
|
||||
error_messages: Optional[Any] = ...,
|
||||
show_hidden_initial: bool = ...,
|
||||
validators: Sequence[Any] = ...,
|
||||
localize: bool = ...,
|
||||
disabled: bool = ...,
|
||||
label_suffix: Optional[Any] = ...,
|
||||
) -> None: ...
|
||||
|
||||
class UUIDField(CharField):
|
||||
disabled: bool
|
||||
empty_value: str
|
||||
max_length: None
|
||||
min_length: None
|
||||
required: bool
|
||||
show_hidden_initial: bool
|
||||
strip: bool
|
||||
default_error_messages: Any = ...
|
||||
def prepare_value(self, value: UUID) -> str: ...
|
||||
class UUIDField(CharField): ...
|
||||
|
||||
@@ -1,48 +1,46 @@
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, Iterator, List, Mapping, Optional, Tuple, Type, Union
|
||||
from typing import Any, Dict, Iterator, List, Mapping, Optional, Sequence, Type, Union
|
||||
|
||||
from django.core.exceptions import ValidationError as ValidationError
|
||||
from django.core.files.base import File
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.db.models.query import QuerySet
|
||||
from django.forms.boundfield import BoundField
|
||||
from django.forms.fields import Field
|
||||
from django.forms.renderers import BaseRenderer
|
||||
from django.forms.utils import ErrorDict, ErrorList
|
||||
from django.forms.widgets import Media, MediaDefiningClass
|
||||
from django.utils.safestring import SafeText
|
||||
|
||||
class DeclarativeFieldsMetaclass(MediaDefiningClass):
|
||||
def __new__(
|
||||
mcs: Type[DeclarativeFieldsMetaclass], name: str, bases: Tuple[Type[BaseForm]], attrs: OrderedDict
|
||||
) -> Type[BaseForm]: ...
|
||||
def __new__(mcs, name: str, bases: Sequence[Type[BaseForm]], attrs: Dict[str, Any]) -> Type[BaseForm]: ...
|
||||
|
||||
class BaseForm:
|
||||
default_renderer: Any = ...
|
||||
field_order: Any = ...
|
||||
prefix: Any = ...
|
||||
use_required_attribute: bool = ...
|
||||
is_bound: Any = ...
|
||||
data: Any = ...
|
||||
files: Any = ...
|
||||
is_bound: bool = ...
|
||||
data: Dict[str, Any] = ...
|
||||
files: Optional[Dict[str, Any]] = ...
|
||||
auto_id: Any = ...
|
||||
initial: Any = ...
|
||||
error_class: Any = ...
|
||||
label_suffix: Any = ...
|
||||
empty_permitted: Any = ...
|
||||
fields: Any = ...
|
||||
renderer: Any = ...
|
||||
initial: Dict[str, Any] = ...
|
||||
error_class: Type[ErrorList] = ...
|
||||
prefix: str = ...
|
||||
label_suffix: str = ...
|
||||
empty_permitted: bool = ...
|
||||
fields: Dict[str, Any] = ...
|
||||
renderer: BaseRenderer = ...
|
||||
cleaned_data: Any = ...
|
||||
def __init__(
|
||||
self,
|
||||
data: Optional[Mapping[str, Any]] = ...,
|
||||
files: Optional[Mapping[str, File]] = ...,
|
||||
files: Optional[Mapping[str, Any]] = ...,
|
||||
auto_id: Optional[Union[bool, str]] = ...,
|
||||
prefix: Optional[str] = ...,
|
||||
initial: Optional[Mapping[str, Any]] = ...,
|
||||
error_class: Type[ErrorList] = ...,
|
||||
label_suffix: None = ...,
|
||||
label_suffix: Optional[str] = ...,
|
||||
empty_permitted: bool = ...,
|
||||
field_order: None = ...,
|
||||
field_order: Optional[Any] = ...,
|
||||
use_required_attribute: Optional[bool] = ...,
|
||||
renderer: Any = ...,
|
||||
) -> None: ...
|
||||
@@ -60,7 +58,6 @@ class BaseForm:
|
||||
def non_field_errors(self) -> ErrorList: ...
|
||||
def add_error(self, field: Optional[str], error: Union[ValidationError, str]) -> None: ...
|
||||
def has_error(self, field: Any, code: Optional[Any] = ...): ...
|
||||
cleaned_data: Any = ...
|
||||
def full_clean(self) -> None: ...
|
||||
def clean(self) -> Dict[str, Optional[Union[datetime, SimpleUploadedFile, QuerySet, str]]]: ...
|
||||
def has_changed(self) -> bool: ...
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import collections
|
||||
from typing import Any, List, Optional, Union, Dict, Type
|
||||
|
||||
from django.forms.renderers import BaseRenderer
|
||||
from django.forms.utils import ErrorList
|
||||
from typing import Any, Dict, Mapping, Optional, Sequence, Sized
|
||||
|
||||
from django.forms import Form
|
||||
|
||||
@@ -17,21 +13,9 @@ DEFAULT_MIN_NUM: int = ...
|
||||
DEFAULT_MAX_NUM: int = ...
|
||||
|
||||
class ManagementForm(Form):
|
||||
auto_id: Union[bool, str]
|
||||
cleaned_data: Dict[str, Optional[int]]
|
||||
data: Dict[str, Union[List[int], int, str]]
|
||||
empty_permitted: bool
|
||||
error_class: Type[ErrorList]
|
||||
fields: collections.OrderedDict
|
||||
files: Dict[Any, Any]
|
||||
initial: Dict[str, int]
|
||||
is_bound: bool
|
||||
label_suffix: str
|
||||
prefix: str
|
||||
renderer: BaseRenderer
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
||||
|
||||
class BaseFormSet:
|
||||
class BaseFormSet(Sized, Mapping[str, Any]):
|
||||
is_bound: Any = ...
|
||||
prefix: Any = ...
|
||||
auto_id: Any = ...
|
||||
@@ -57,6 +41,7 @@ class BaseFormSet:
|
||||
def management_form(self): ...
|
||||
def total_form_count(self): ...
|
||||
def initial_form_count(self): ...
|
||||
@property
|
||||
def forms(self): ...
|
||||
def get_form_kwargs(self, index: Any): ...
|
||||
@property
|
||||
@@ -101,4 +86,4 @@ def formset_factory(
|
||||
min_num: Optional[Any] = ...,
|
||||
validate_min: bool = ...,
|
||||
): ...
|
||||
def all_valid(formsets: List[Any]) -> bool: ...
|
||||
def all_valid(formsets: Sequence[Any]) -> bool: ...
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from collections import OrderedDict
|
||||
from datetime import date, datetime
|
||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, Type, Union, Sequence
|
||||
from typing import Any, Callable, Dict, Iterator, List, MutableMapping, Optional, Sequence, Tuple, Type, Union, Mapping
|
||||
from unittest.mock import MagicMock
|
||||
from uuid import UUID
|
||||
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.core.files.base import File
|
||||
from django.db import models
|
||||
from django.db.models import ForeignKey
|
||||
from django.db.models.base import Model
|
||||
from django.db.models.manager import Manager
|
||||
@@ -14,25 +15,22 @@ from django.forms.fields import CharField, ChoiceField, Field
|
||||
from django.forms.forms import BaseForm, DeclarativeFieldsMetaclass
|
||||
from django.forms.formsets import BaseFormSet
|
||||
from django.forms.utils import ErrorList
|
||||
from django.forms.widgets import Input, Widget, Select
|
||||
from django.http.request import QueryDict
|
||||
from django.utils.datastructures import MultiValueDict
|
||||
from django.forms.widgets import Input, Widget
|
||||
from typing_extensions import Literal
|
||||
|
||||
ALL_FIELDS: str
|
||||
|
||||
_Fields = Union[List[Union[Callable, str]], Tuple[str]]
|
||||
_Fields = Union[List[Union[Callable, str]], Sequence[str], Literal["__all__"]]
|
||||
_Labels = Dict[str, str]
|
||||
_ErrorMessages = Dict[str, Dict[str, str]]
|
||||
|
||||
def model_to_dict(
|
||||
instance: Model,
|
||||
fields: Optional[_Fields] = ...,
|
||||
exclude: Optional[Union[List[Union[Callable, str]], Tuple[str]]] = ...,
|
||||
) -> Dict[str, Optional[Union[bool, date, float]]]: ...
|
||||
instance: Model, fields: Optional[_Fields] = ..., exclude: Optional[_Fields] = ...
|
||||
) -> Dict[str, Any]: ...
|
||||
def fields_for_model(
|
||||
model: Type[Model],
|
||||
fields: Optional[_Fields] = ...,
|
||||
exclude: Optional[Union[List[Union[Callable, str]], Tuple]] = ...,
|
||||
exclude: Optional[_Fields] = ...,
|
||||
widgets: Optional[Union[Dict[str, Type[Input]], Dict[str, Widget]]] = ...,
|
||||
formfield_callback: Optional[Union[Callable, str]] = ...,
|
||||
localized_fields: Optional[Union[Tuple[str], str]] = ...,
|
||||
@@ -42,12 +40,12 @@ def fields_for_model(
|
||||
field_classes: Optional[Dict[str, Type[CharField]]] = ...,
|
||||
*,
|
||||
apply_limit_choices_to: bool = ...
|
||||
) -> OrderedDict: ...
|
||||
) -> Dict[str, Any]: ...
|
||||
|
||||
class ModelFormOptions:
|
||||
model: Optional[Type[Model]] = ...
|
||||
fields: Optional[_Fields] = ...
|
||||
exclude: Optional[Union[List[Union[Callable, str]], Tuple, str]] = ...
|
||||
exclude: Optional[_Fields] = ...
|
||||
widgets: Optional[Dict[str, Union[Widget, Input]]] = ...
|
||||
localized_fields: Optional[Union[Tuple[str], str]] = ...
|
||||
labels: Optional[_Labels] = ...
|
||||
@@ -57,46 +55,44 @@ class ModelFormOptions:
|
||||
def __init__(self, options: Optional[type] = ...) -> None: ...
|
||||
|
||||
class ModelFormMetaclass(DeclarativeFieldsMetaclass):
|
||||
def __new__(
|
||||
mcs: Type[ModelFormMetaclass], name: str, bases: Tuple[Type[ModelForm]], attrs: OrderedDict
|
||||
) -> Type[ModelForm]: ...
|
||||
def __new__(mcs, name: str, bases: Sequence[Type[Any]], attrs: Dict[str, Any]) -> Type[ModelForm]: ...
|
||||
|
||||
class BaseModelForm(BaseForm):
|
||||
instance: Any = ...
|
||||
def __init__(
|
||||
self,
|
||||
data: Optional[Union[Dict[str, Any], QueryDict]] = ...,
|
||||
files: Optional[Union[Dict[str, SimpleUploadedFile], MultiValueDict]] = ...,
|
||||
data: Optional[Mapping[str, Any]] = ...,
|
||||
files: Optional[Mapping[str, File]] = ...,
|
||||
auto_id: Union[bool, str] = ...,
|
||||
prefix: None = ...,
|
||||
initial: Optional[Union[Dict[str, List[int]], Dict[str, int]]] = ...,
|
||||
prefix: Optional[str] = ...,
|
||||
initial: Optional[Dict[str, Any]] = ...,
|
||||
error_class: Type[ErrorList] = ...,
|
||||
label_suffix: None = ...,
|
||||
label_suffix: Optional[str] = ...,
|
||||
empty_permitted: bool = ...,
|
||||
instance: Optional[Model] = ...,
|
||||
use_required_attribute: None = ...,
|
||||
use_required_attribute: Optional[bool] = ...,
|
||||
renderer: Any = ...,
|
||||
) -> None: ...
|
||||
def clean(self) -> Dict[str, Any]: ...
|
||||
def validate_unique(self) -> None: ...
|
||||
save_m2m: Any = ...
|
||||
def save(self, commit: bool = ...) -> Model: ...
|
||||
def save(self, commit: bool = ...) -> Any: ...
|
||||
|
||||
class ModelForm(BaseModelForm): ...
|
||||
|
||||
def modelform_factory(
|
||||
model: Type[Model],
|
||||
form: Type[ModelForm] = ...,
|
||||
fields: Optional[Union[List[str], str]] = ...,
|
||||
exclude: None = ...,
|
||||
formfield_callback: Optional[str] = ...,
|
||||
widgets: None = ...,
|
||||
localized_fields: None = ...,
|
||||
labels: None = ...,
|
||||
help_texts: None = ...,
|
||||
error_messages: None = ...,
|
||||
field_classes: None = ...,
|
||||
) -> Any: ...
|
||||
fields: Optional[_Fields] = ...,
|
||||
exclude: Optional[_Fields] = ...,
|
||||
formfield_callback: Optional[Union[str, Callable[[models.Field], Field]]] = ...,
|
||||
widgets: Optional[MutableMapping[str, Widget]] = ...,
|
||||
localized_fields: Optional[Sequence[str]] = ...,
|
||||
labels: Optional[MutableMapping[str, str]] = ...,
|
||||
help_texts: Optional[MutableMapping[str, str]] = ...,
|
||||
error_messages: Optional[MutableMapping[str, Dict[str, Any]]] = ...,
|
||||
field_classes: Optional[MutableMapping[str, Type[Field]]] = ...,
|
||||
) -> Type[ModelForm]: ...
|
||||
|
||||
class BaseModelFormSet(BaseFormSet):
|
||||
model: Any = ...
|
||||
@@ -144,17 +140,17 @@ def modelformset_factory(
|
||||
can_order: bool = ...,
|
||||
min_num: Optional[int] = ...,
|
||||
max_num: Optional[int] = ...,
|
||||
fields: Optional[Union[str, Sequence[str]]] = ...,
|
||||
exclude: Optional[Sequence[str]] = ...,
|
||||
fields: Optional[_Fields] = ...,
|
||||
exclude: Optional[_Fields] = ...,
|
||||
widgets: Optional[Dict[str, Any]] = ...,
|
||||
validate_max: bool = ...,
|
||||
localized_fields: None = ...,
|
||||
localized_fields: Optional[Sequence[str]] = ...,
|
||||
labels: Optional[Dict[str, str]] = ...,
|
||||
help_texts: Optional[Dict[str, str]] = ...,
|
||||
error_messages: Optional[Dict[str, Dict[str, str]]] = ...,
|
||||
validate_min: bool = ...,
|
||||
field_classes: Optional[Dict[str, Any]] = ...,
|
||||
) -> Any: ...
|
||||
field_classes: Optional[Dict[str, Type[Field]]] = ...,
|
||||
) -> Type[BaseModelFormSet]: ...
|
||||
|
||||
class BaseInlineFormSet(BaseModelFormSet):
|
||||
instance: Any = ...
|
||||
@@ -183,8 +179,8 @@ def inlineformset_factory(
|
||||
form: Type[ModelForm] = ...,
|
||||
formset: Type[BaseInlineFormSet] = ...,
|
||||
fk_name: Optional[str] = ...,
|
||||
fields: Optional[Union[str, Sequence[str]]] = ...,
|
||||
exclude: Optional[Sequence[str]] = ...,
|
||||
fields: Optional[_Fields] = ...,
|
||||
exclude: Optional[_Fields] = ...,
|
||||
extra: int = ...,
|
||||
can_order: bool = ...,
|
||||
can_delete: bool = ...,
|
||||
@@ -192,14 +188,14 @@ def inlineformset_factory(
|
||||
formfield_callback: Optional[Callable] = ...,
|
||||
widgets: Optional[Dict[str, Any]] = ...,
|
||||
validate_max: bool = ...,
|
||||
localized_fields: None = ...,
|
||||
localized_fields: Optional[Sequence[str]] = ...,
|
||||
labels: Optional[Dict[str, str]] = ...,
|
||||
help_texts: Optional[Dict[str, str]] = ...,
|
||||
error_messages: Optional[Dict[str, Dict[str, str]]] = ...,
|
||||
min_num: Optional[int] = ...,
|
||||
validate_min: bool = ...,
|
||||
field_classes: Optional[Dict[str, Any]] = ...,
|
||||
) -> Any: ...
|
||||
) -> Type[BaseInlineFormSet]: ...
|
||||
|
||||
class InlineForeignKeyField(Field):
|
||||
disabled: bool
|
||||
@@ -241,7 +237,7 @@ class ModelChoiceField(ChoiceField):
|
||||
self,
|
||||
queryset: Optional[Union[Manager, QuerySet]],
|
||||
*,
|
||||
empty_label: str = ...,
|
||||
empty_label: Optional[str] = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Any] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
from collections import UserList
|
||||
from datetime import datetime
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union, Sequence
|
||||
from typing import Any, Dict, List, Optional, Sequence, Union
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.safestring import SafeText
|
||||
|
||||
def pretty_name(name: str) -> str: ...
|
||||
def flatatt(attrs: Dict[str, Optional[str]]) -> SafeText: ...
|
||||
def flatatt(attrs: Dict[str, Any]) -> SafeText: ...
|
||||
|
||||
class ErrorDict(dict):
|
||||
def as_data(self) -> Dict[str, List[ValidationError]]: ...
|
||||
def get_json_data(self, escape_html: bool = ...) -> Dict[str, List[Dict[str, str]]]: ...
|
||||
def get_json_data(self, escape_html: bool = ...) -> Dict[str, Any]: ...
|
||||
def as_json(self, escape_html: bool = ...) -> str: ...
|
||||
def as_ul(self) -> str: ...
|
||||
def as_text(self) -> str: ...
|
||||
@@ -19,16 +19,15 @@ class ErrorList(UserList):
|
||||
data: List[Union[ValidationError, str]]
|
||||
error_class: str = ...
|
||||
def __init__(
|
||||
self, initlist: Optional[Union[ErrorList, Sequence[str]]] = ..., error_class: Optional[str] = ...
|
||||
self,
|
||||
initlist: Optional[Union[ErrorList, Sequence[Union[str, Exception]]]] = ...,
|
||||
error_class: Optional[str] = ...,
|
||||
) -> None: ...
|
||||
def as_data(self) -> List[ValidationError]: ...
|
||||
def get_json_data(self, escape_html: bool = ...) -> List[Dict[str, str]]: ...
|
||||
def as_json(self, escape_html: bool = ...) -> str: ...
|
||||
def as_ul(self) -> str: ...
|
||||
def as_text(self) -> str: ...
|
||||
def __reduce_ex__(
|
||||
self, *args: Any, **kwargs: Any
|
||||
) -> Tuple[Callable, Tuple[Type[ErrorList]], Dict[str, Union[List[ValidationError], str]], None, None]: ...
|
||||
|
||||
def from_current_timezone(value: datetime) -> datetime: ...
|
||||
def to_current_timezone(value: datetime) -> datetime: ...
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
from datetime import time
|
||||
from decimal import Decimal
|
||||
from itertools import chain
|
||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Type, Union, Iterable, Sequence
|
||||
from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Sequence, Set, Tuple, Type, Union
|
||||
|
||||
from django.contrib.admin.options import BaseModelAdmin
|
||||
from django.core.files.base import File
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.db.models.fields.files import FieldFile
|
||||
from django.forms.forms import BaseForm
|
||||
from django.forms.renderers import EngineMixin
|
||||
from django.utils.datastructures import MultiValueDict
|
||||
from django.utils.safestring import SafeText
|
||||
|
||||
_OptAttrs = Dict[str, str]
|
||||
|
||||
class MediaOrderConflictWarning(RuntimeWarning): ...
|
||||
|
||||
class Media:
|
||||
@@ -32,9 +31,7 @@ class Media:
|
||||
def __add__(self, other: Media) -> Media: ...
|
||||
|
||||
class MediaDefiningClass(type):
|
||||
def __new__(
|
||||
mcs: Type[MediaDefiningClass], name: str, bases: Tuple, attrs: Any
|
||||
) -> Type[Union[BaseModelAdmin, BaseForm, Widget]]: ...
|
||||
def __new__(mcs, name: str, bases: Sequence[Any], attrs: Dict[str, Any]) -> type: ...
|
||||
|
||||
class Widget:
|
||||
needs_multipart_form: bool = ...
|
||||
@@ -61,10 +58,10 @@ class Widget:
|
||||
self, base_attrs: Dict[str, Union[float, str]], extra_attrs: Optional[Dict[str, Union[bool, str]]] = ...
|
||||
) -> Dict[str, Union[Decimal, float, str]]: ...
|
||||
def value_from_datadict(
|
||||
self, data: dict, files: Union[Dict[str, SimpleUploadedFile], MultiValueDict], name: str
|
||||
self, data: dict, files: Union[Dict[str, Iterable[Any]], MultiValueDict], name: str
|
||||
) -> Any: ...
|
||||
def value_omitted_from_data(
|
||||
self, data: Dict[str, Any], files: Union[Dict[str, SimpleUploadedFile], MultiValueDict], name: str
|
||||
self, data: Dict[str, Any], files: Union[Dict[str, Iterable[Any]], MultiValueDict], name: str
|
||||
) -> bool: ...
|
||||
def id_for_label(self, id_: str) -> str: ...
|
||||
def use_required_attribute(self, initial: Any) -> bool: ...
|
||||
@@ -80,6 +77,7 @@ class URLInput(Input): ...
|
||||
|
||||
class PasswordInput(Input):
|
||||
render_value: bool = ...
|
||||
def __init__(self, attrs: Optional[_OptAttrs] = ..., render_value: bool = ...): ...
|
||||
|
||||
class HiddenInput(Input):
|
||||
choices: Iterable[Tuple[str, str]]
|
||||
@@ -105,6 +103,7 @@ class DateTimeBaseInput(TextInput):
|
||||
format_key: str = ...
|
||||
supports_microseconds: bool = ...
|
||||
format: Optional[str] = ...
|
||||
def __init__(self, attrs: Optional[_OptAttrs] = ..., format: Optional[str] = ...): ...
|
||||
|
||||
class DateInput(DateTimeBaseInput): ...
|
||||
class DateTimeInput(DateTimeBaseInput): ...
|
||||
@@ -112,9 +111,7 @@ class TimeInput(DateTimeBaseInput): ...
|
||||
|
||||
class CheckboxInput(Input):
|
||||
check_test: Callable = ...
|
||||
def __init__(self, attrs: Optional[Dict[str, str]] = ..., check_test: Optional[Callable] = ...) -> None: ...
|
||||
|
||||
_OptAttrs = Dict[str, Any]
|
||||
def __init__(self, attrs: Optional[_OptAttrs] = ..., check_test: Optional[Callable] = ...) -> None: ...
|
||||
|
||||
class ChoiceWidget(Widget):
|
||||
allow_multiple_selected: bool = ...
|
||||
@@ -165,7 +162,7 @@ class CheckboxSelectMultiple(ChoiceWidget):
|
||||
class MultiWidget(Widget):
|
||||
template_name: str = ...
|
||||
widgets: List[Widget] = ...
|
||||
def __init__(self, widgets: Sequence[Widget], attrs: Optional[_OptAttrs] = ...) -> None: ...
|
||||
def __init__(self, widgets: Sequence[Union[Widget, Type[Widget]]], attrs: Optional[_OptAttrs] = ...) -> None: ...
|
||||
@property
|
||||
def is_hidden(self) -> bool: ...
|
||||
def decompress(self, value: Any) -> Optional[Any]: ...
|
||||
@@ -209,7 +206,7 @@ class SelectDateWidget(Widget):
|
||||
def __init__(
|
||||
self,
|
||||
attrs: Optional[_OptAttrs] = ...,
|
||||
years: Optional[Union[Tuple[Union[int, str]], range]] = ...,
|
||||
months: None = ...,
|
||||
empty_label: Optional[Union[Tuple[str, str], str]] = ...,
|
||||
years: Optional[Iterable[Union[int, str]]] = ...,
|
||||
months: Optional[Dict[int, str]] = ...,
|
||||
empty_label: Optional[Union[str, Sequence[str]]] = ...,
|
||||
) -> None: ...
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import datetime
|
||||
from io import BytesIO
|
||||
from json import JSONEncoder
|
||||
from typing import Any, Dict, Iterable, Iterator, List, Optional, Tuple, Type, Union, overload, AnyStr, IO
|
||||
from typing import Any, Dict, Iterable, Iterator, List, Optional, Tuple, Type, Union, overload
|
||||
|
||||
import six
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http.cookie import SimpleCookie
|
||||
from django.test.client import Client
|
||||
@@ -13,7 +12,7 @@ from django.urls import ResolverMatch
|
||||
|
||||
class BadHeaderError(ValueError): ...
|
||||
|
||||
class HttpResponseBase(Iterable[AnyStr]):
|
||||
class HttpResponseBase(Iterable[Any]):
|
||||
status_code: int = ...
|
||||
cookies: SimpleCookie = ...
|
||||
reason_phrase: str = ...
|
||||
@@ -60,7 +59,7 @@ class HttpResponseBase(Iterable[AnyStr]):
|
||||
def seekable(self) -> bool: ...
|
||||
def writable(self) -> bool: ...
|
||||
def writelines(self, lines: Iterable[object]): ...
|
||||
def __iter__(self) -> Iterator[AnyStr]: ...
|
||||
def __iter__(self) -> Iterator[Any]: ...
|
||||
|
||||
class HttpResponse(HttpResponseBase):
|
||||
client: Client
|
||||
@@ -70,7 +69,6 @@ class HttpResponse(HttpResponseBase):
|
||||
request: Dict[str, Any]
|
||||
resolver_match: ResolverMatch
|
||||
sameorigin: bool
|
||||
status_code: int
|
||||
templates: List[Template]
|
||||
test_server_port: str
|
||||
test_was_secure_request: bool
|
||||
@@ -88,21 +86,13 @@ class HttpResponse(HttpResponseBase):
|
||||
def json(self) -> Dict[str, Any]: ...
|
||||
|
||||
class StreamingHttpResponse(HttpResponseBase):
|
||||
def __init__(self, streaming_content: Iterable[AnyStr] = ..., *args: Any, **kwargs: Any) -> None: ...
|
||||
@property
|
||||
def content(self) -> AnyStr: ...
|
||||
@content.setter
|
||||
def content(self, value: AnyStr) -> None: ...
|
||||
@property
|
||||
def streaming_content(self) -> Iterator[AnyStr]: ...
|
||||
@streaming_content.setter
|
||||
def streaming_content(self, value: Iterable[AnyStr]) -> None: ...
|
||||
def __iter__(self) -> Iterator[AnyStr]: ...
|
||||
def getvalue(self) -> AnyStr: ...
|
||||
content: Any
|
||||
streaming_content: Iterator[Any]
|
||||
def __init__(self, streaming_content: Iterable[Any] = ..., *args: Any, **kwargs: Any) -> None: ...
|
||||
def getvalue(self) -> Any: ...
|
||||
|
||||
class FileResponse(StreamingHttpResponse):
|
||||
client: Client
|
||||
closed: bool
|
||||
context: None
|
||||
file_to_stream: Optional[BytesIO]
|
||||
request: Dict[str, str]
|
||||
@@ -119,8 +109,6 @@ class FileResponse(StreamingHttpResponse):
|
||||
class HttpResponseRedirectBase(HttpResponse):
|
||||
allowed_schemes = ... # type: List[str]
|
||||
def __init__(self, redirect_to: str, *args: Any, **kwargs: Any) -> None: ...
|
||||
@property
|
||||
def url(self) -> str: ...
|
||||
|
||||
class HttpResponseRedirect(HttpResponseRedirectBase): ...
|
||||
class HttpResponsePermanentRedirect(HttpResponseRedirectBase): ...
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any, Optional, Union, Callable
|
||||
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponse, HttpResponseBase
|
||||
@@ -26,4 +26,6 @@ class CacheMiddleware(UpdateCacheMiddleware, FetchFromCacheMiddleware):
|
||||
cache_alias: str = ...
|
||||
cache_timeout: float = ...
|
||||
cache: BaseCache = ...
|
||||
def __init__(self, get_response: None = ..., cache_timeout: Optional[float] = ..., **kwargs: Any) -> None: ...
|
||||
def __init__(
|
||||
self, get_response: Optional[Callable] = ..., cache_timeout: Optional[float] = ..., **kwargs: Any
|
||||
) -> None: ...
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from typing import Any
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponseBase
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
||||
re_accepts_gzip: Any
|
||||
|
||||
class GZipMiddleware(MiddlewareMixin):
|
||||
def process_response(self, request: WSGIRequest, response: HttpResponseBase) -> HttpResponseBase: ...
|
||||
def process_response(self, request: HttpRequest, response: HttpResponseBase) -> HttpResponseBase: ...
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponseBase
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
||||
class ConditionalGetMiddleware(MiddlewareMixin):
|
||||
def process_response(self, request: WSGIRequest, response: HttpResponseBase) -> HttpResponseBase: ...
|
||||
def process_response(self, request: HttpRequest, response: HttpResponseBase) -> HttpResponseBase: ...
|
||||
def needs_etag(self, response: HttpResponseBase) -> bool: ...
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from typing import Any
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponseBase
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
||||
class LocaleMiddleware(MiddlewareMixin):
|
||||
response_redirect_class: Any = ...
|
||||
def process_request(self, request: WSGIRequest) -> None: ...
|
||||
def process_response(self, request: WSGIRequest, response: HttpResponseBase) -> HttpResponseBase: ...
|
||||
def process_request(self, request: HttpRequest) -> None: ...
|
||||
def process_response(self, request: HttpRequest, response: HttpResponseBase) -> HttpResponseBase: ...
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from typing import Any, Optional, List
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponse, HttpResponsePermanentRedirect
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
||||
@@ -13,5 +13,5 @@ class SecurityMiddleware(MiddlewareMixin):
|
||||
redirect: bool = ...
|
||||
redirect_host: Optional[str] = ...
|
||||
redirect_exempt: List[Any] = ...
|
||||
def process_request(self, request: WSGIRequest) -> Optional[HttpResponsePermanentRedirect]: ...
|
||||
def process_response(self, request: WSGIRequest, response: HttpResponse) -> HttpResponse: ...
|
||||
def process_request(self, request: HttpRequest) -> Optional[HttpResponsePermanentRedirect]: ...
|
||||
def process_response(self, request: HttpRequest, response: HttpResponse) -> HttpResponse: ...
|
||||
|
||||
@@ -9,8 +9,6 @@ from django.http.cookie import SimpleCookie
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponse, HttpResponseBase
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
|
||||
BOUNDARY: str = ...
|
||||
MULTIPART_CONTENT: str = ...
|
||||
CONTENT_TYPE_RE: Pattern = ...
|
||||
@@ -42,13 +40,13 @@ class RequestFactory:
|
||||
cookies: SimpleCookie = ...
|
||||
errors: BytesIO = ...
|
||||
def __init__(self, *, json_encoder: Any = ..., **defaults: Any) -> None: ...
|
||||
def request(self, **request: Any) -> WSGIRequest: ...
|
||||
def get(self, path: str, data: Any = ..., secure: bool = ..., **extra: Any) -> WSGIRequest: ...
|
||||
def request(self, **request: Any) -> HttpRequest: ...
|
||||
def get(self, path: str, data: Any = ..., secure: bool = ..., **extra: Any) -> HttpRequest: ...
|
||||
def post(
|
||||
self, path: str, data: Any = ..., content_type: str = ..., secure: bool = ..., **extra: Any
|
||||
) -> WSGIRequest: ...
|
||||
def head(self, path: str, data: Any = ..., secure: bool = ..., **extra: Any) -> WSGIRequest: ...
|
||||
def trace(self, path: str, secure: bool = ..., **extra: Any) -> WSGIRequest: ...
|
||||
) -> HttpRequest: ...
|
||||
def head(self, path: str, data: Any = ..., secure: bool = ..., **extra: Any) -> HttpRequest: ...
|
||||
def trace(self, path: str, secure: bool = ..., **extra: Any) -> HttpRequest: ...
|
||||
def options(
|
||||
self,
|
||||
path: str,
|
||||
@@ -56,16 +54,16 @@ class RequestFactory:
|
||||
content_type: str = ...,
|
||||
secure: bool = ...,
|
||||
**extra: Any
|
||||
) -> WSGIRequest: ...
|
||||
) -> HttpRequest: ...
|
||||
def put(
|
||||
self, path: str, data: Any = ..., content_type: str = ..., secure: bool = ..., **extra: Any
|
||||
) -> WSGIRequest: ...
|
||||
) -> HttpRequest: ...
|
||||
def patch(
|
||||
self, path: str, data: Any = ..., content_type: str = ..., secure: bool = ..., **extra: Any
|
||||
) -> WSGIRequest: ...
|
||||
) -> HttpRequest: ...
|
||||
def delete(
|
||||
self, path: str, data: Any = ..., content_type: str = ..., secure: bool = ..., **extra: Any
|
||||
) -> WSGIRequest: ...
|
||||
) -> HttpRequest: ...
|
||||
def generic(
|
||||
self,
|
||||
method: str,
|
||||
@@ -74,7 +72,7 @@ class RequestFactory:
|
||||
content_type: Optional[str] = ...,
|
||||
secure: bool = ...,
|
||||
**extra: Any
|
||||
) -> WSGIRequest: ...
|
||||
) -> HttpRequest: ...
|
||||
|
||||
class Client:
|
||||
json_encoder: Type[DjangoJSONEncoder] = ...
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from html.parser import HTMLParser
|
||||
from typing import Any, List, Optional, Tuple, Union, TypeVar, Iterable, Sequence
|
||||
from typing import Any, List, Optional, Sequence, Tuple, TypeVar, Union
|
||||
|
||||
_Self = TypeVar("_Self")
|
||||
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
from typing import Any, Callable, Dict, List, Tuple, Type, Union
|
||||
from typing import Any
|
||||
|
||||
from django.test import LiveServerTestCase
|
||||
|
||||
class SeleniumTestCaseBase:
|
||||
browsers: Any = ...
|
||||
browser: Any = ...
|
||||
def __new__(
|
||||
cls: Type[SeleniumTestCaseBase],
|
||||
name: str,
|
||||
bases: Tuple[Type[SeleniumTestCase]],
|
||||
attrs: Dict[str, Union[Callable, List[str], str]],
|
||||
) -> Type[SeleniumTestCase]: ...
|
||||
@classmethod
|
||||
def import_webdriver(cls, browser: Any): ...
|
||||
def create_webdriver(self): ...
|
||||
|
||||
class SeleniumTestCase(LiveServerTestCase):
|
||||
implicit_wait: int = ...
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None: ...
|
||||
def disable_implicit_wait(self) -> None: ...
|
||||
|
||||
@@ -18,14 +18,9 @@ from django.utils.safestring import SafeText
|
||||
from django.db import connections as connections
|
||||
|
||||
class _AssertNumQueriesContext(CaptureQueriesContext):
|
||||
connection: Any
|
||||
final_queries: Optional[int]
|
||||
force_debug_cursor: bool
|
||||
initial_queries: int
|
||||
test_case: SimpleTestCase = ...
|
||||
num: int = ...
|
||||
def __init__(self, test_case: Any, num: Any, connection: Any) -> None: ...
|
||||
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any): ...
|
||||
|
||||
class _AssertTemplateUsedContext:
|
||||
test_case: SimpleTestCase = ...
|
||||
@@ -40,14 +35,7 @@ class _AssertTemplateUsedContext:
|
||||
def __enter__(self): ...
|
||||
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any): ...
|
||||
|
||||
class _AssertTemplateNotUsedContext(_AssertTemplateUsedContext):
|
||||
context: ContextList
|
||||
rendered_template_names: List[str]
|
||||
rendered_templates: List[Template]
|
||||
template_name: str
|
||||
test_case: SimpleTestCase
|
||||
def test(self): ...
|
||||
def message(self): ...
|
||||
class _AssertTemplateNotUsedContext(_AssertTemplateUsedContext): ...
|
||||
|
||||
class _CursorFailure:
|
||||
cls_name: str = ...
|
||||
@@ -59,10 +47,6 @@ class SimpleTestCase(unittest.TestCase):
|
||||
client_class: Any = ...
|
||||
client: Client
|
||||
allow_database_queries: bool = ...
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None: ...
|
||||
@classmethod
|
||||
def tearDownClass(cls) -> None: ...
|
||||
def __call__(self, result: unittest.TestResult = ...) -> None: ...
|
||||
def settings(self, **kwargs: Any) -> Any: ...
|
||||
def modify_settings(self, **kwargs: Any) -> Any: ...
|
||||
@@ -150,7 +134,6 @@ class TransactionTestCase(SimpleTestCase):
|
||||
fixtures: Any = ...
|
||||
multi_db: bool = ...
|
||||
serialized_rollback: bool = ...
|
||||
allow_database_queries: bool = ...
|
||||
def assertQuerysetEqual(
|
||||
self,
|
||||
qs: Union[Iterator[Any], List[Model], QuerySet, RawQuerySet],
|
||||
@@ -164,10 +147,6 @@ class TransactionTestCase(SimpleTestCase):
|
||||
) -> Optional[_AssertNumQueriesContext]: ...
|
||||
|
||||
class TestCase(TransactionTestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None: ...
|
||||
@classmethod
|
||||
def tearDownClass(cls) -> None: ...
|
||||
@classmethod
|
||||
def setUpTestData(cls) -> None: ...
|
||||
|
||||
@@ -181,17 +160,14 @@ def skipIfDBFeature(*features: Any) -> Callable: ...
|
||||
def skipUnlessDBFeature(*features: Any) -> Callable: ...
|
||||
def skipUnlessAnyDBFeature(*features: Any) -> Callable: ...
|
||||
|
||||
class QuietWSGIRequestHandler(WSGIRequestHandler):
|
||||
def log_message(*args: Any) -> None: ...
|
||||
class QuietWSGIRequestHandler(WSGIRequestHandler): ...
|
||||
|
||||
class FSFilesHandler(WSGIHandler):
|
||||
application: Any = ...
|
||||
base_url: Any = ...
|
||||
def __init__(self, application: Any) -> None: ...
|
||||
def file_path(self, url: Any): ...
|
||||
def get_response(self, request: Any): ...
|
||||
def serve(self, request: Any): ...
|
||||
def __call__(self, environ: Any, start_response: Any): ...
|
||||
|
||||
class _StaticFilesHandler(FSFilesHandler):
|
||||
def get_base_dir(self): ...
|
||||
@@ -216,7 +192,6 @@ class LiveServerThread(threading.Thread):
|
||||
port: int = ...,
|
||||
) -> None: ...
|
||||
httpd: ThreadedWSGIServer = ...
|
||||
def run(self) -> None: ...
|
||||
def terminate(self) -> None: ...
|
||||
|
||||
class LiveServerTestCase(TransactionTestCase):
|
||||
@@ -225,10 +200,6 @@ class LiveServerTestCase(TransactionTestCase):
|
||||
server_thread_class: Any = ...
|
||||
static_handler: Any = ...
|
||||
def live_server_url(cls): ...
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None: ...
|
||||
@classmethod
|
||||
def tearDownClass(cls) -> None: ...
|
||||
|
||||
class SerializeMixin:
|
||||
lockfile: Any = ...
|
||||
|
||||
@@ -66,15 +66,15 @@ class override_system_checks(TestContextDecorator):
|
||||
|
||||
class CaptureQueriesContext:
|
||||
connection: Any = ...
|
||||
force_debug_cursor: bool = ...
|
||||
initial_queries: int = ...
|
||||
final_queries: Optional[int] = ...
|
||||
def __init__(self, connection: Any) -> None: ...
|
||||
def __iter__(self): ...
|
||||
def __getitem__(self, index: int) -> Dict[str, str]: ...
|
||||
def __len__(self) -> int: ...
|
||||
@property
|
||||
def captured_queries(self) -> List[Dict[str, str]]: ...
|
||||
force_debug_cursor: bool = ...
|
||||
initial_queries: int = ...
|
||||
final_queries: Optional[int] = ...
|
||||
def __enter__(self) -> CaptureQueriesContext: ...
|
||||
def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None: ...
|
||||
|
||||
|
||||
@@ -12,8 +12,11 @@ from typing import (
|
||||
Union,
|
||||
overload,
|
||||
Iterator,
|
||||
Optional,
|
||||
)
|
||||
|
||||
from typing_extensions import Literal
|
||||
|
||||
_K = TypeVar("_K")
|
||||
_V = TypeVar("_V")
|
||||
|
||||
@@ -27,24 +30,22 @@ class OrderedSet(MutableSet[_K]):
|
||||
|
||||
class MultiValueDictKeyError(KeyError): ...
|
||||
|
||||
_Val = Union[_V, List[_V]]
|
||||
|
||||
class MultiValueDict(MutableMapping[_K, _V]):
|
||||
@overload
|
||||
def __init__(self, key_to_list_mapping: Iterable[Tuple[_K, _Val]] = ...) -> None: ...
|
||||
def __init__(self, key_to_list_mapping: Mapping[_K, Optional[List[_V]]] = ...) -> None: ...
|
||||
@overload
|
||||
def __init__(self, key_to_list_mapping: Mapping[_K, _Val] = ...) -> None: ...
|
||||
def __init__(self, key_to_list_mapping: Iterable[Tuple[_K, List[_V]]] = ...) -> None: ...
|
||||
def getlist(self, key: _K, default: List[_V] = None) -> List[_V]: ...
|
||||
def setlist(self, key: _K, list_: List[_V]) -> None: ...
|
||||
def setlistdefault(self, key: _K, default_list: List[_V] = None) -> List[_V]: ...
|
||||
def appendlist(self, key: _K, value: _V) -> None: ...
|
||||
def lists(self) -> Iterable[Tuple[_K, List[_V]]]: ...
|
||||
def dict(self) -> Dict[_K, _Val]: ...
|
||||
def dict(self) -> Dict[_K, Union[_V, List[_V]]]: ...
|
||||
def copy(self) -> MultiValueDict[_K, _V]: ...
|
||||
# These overrides are needed to convince mypy that this isn't an abstract class
|
||||
def __delitem__(self, item: _K) -> None: ...
|
||||
def __getitem__(self, item: _K) -> _Val: ... # type: ignore
|
||||
def __setitem__(self, k: _K, v: _Val) -> None: ...
|
||||
def __getitem__(self, item: _K) -> Union[_V, Literal[[]]]: ... # type: ignore
|
||||
def __setitem__(self, k: _K, v: Union[_V, List[_V]]) -> None: ...
|
||||
def __len__(self) -> int: ...
|
||||
def __iter__(self) -> Iterator[_K]: ...
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
from django.views.generic.base import View
|
||||
|
||||
__all__ = ["View"]
|
||||
1
django-stubs/views/__init__.pyi
Normal file
1
django-stubs/views/__init__.pyi
Normal file
@@ -0,0 +1 @@
|
||||
from .generic.base import View as View
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Any, Optional
|
||||
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponseForbidden
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ class SafeExceptionReporterFilter(ExceptionReporterFilter):
|
||||
class ExceptionReporter:
|
||||
request: Optional[HttpRequest] = ...
|
||||
filter: ExceptionReporterFilter = ...
|
||||
exc_type: None = ...
|
||||
exc_type: Optional[Type[BaseException]] = ...
|
||||
exc_value: Optional[str] = ...
|
||||
tb: None = ...
|
||||
tb: Optional[TracebackType] = ...
|
||||
is_email: bool = ...
|
||||
template_info: None = ...
|
||||
template_does_not_exist: bool = ...
|
||||
@@ -59,7 +59,7 @@ class ExceptionReporter:
|
||||
lineno: int,
|
||||
context_lines: int,
|
||||
loader: Optional[SourceLoader] = ...,
|
||||
module_name: Optional[str] = None,
|
||||
module_name: Optional[str] = ...,
|
||||
): ...
|
||||
|
||||
def technical_404_response(request: HttpRequest, exception: Http404) -> HttpResponse: ...
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Callable, Optional
|
||||
from typing import Callable
|
||||
|
||||
def xframe_options_deny(view_func: Callable) -> Callable: ...
|
||||
def xframe_options_sameorigin(view_func: Callable) -> Callable: ...
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Callable, Optional
|
||||
from typing import Any, Callable
|
||||
|
||||
from django.middleware.csrf import CsrfViewMiddleware
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Callable, Optional
|
||||
from typing import Any, Callable
|
||||
|
||||
def sensitive_variables(*variables: Any) -> Callable: ...
|
||||
def sensitive_post_parameters(*parameters: Any) -> Callable: ...
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Callable, Optional
|
||||
from typing import Any, Callable
|
||||
|
||||
def vary_on_headers(*headers: Any) -> Callable: ...
|
||||
def vary_on_cookie(func: Callable) -> Callable: ...
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
from typing import Any, Optional
|
||||
from typing import Optional
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import (
|
||||
Http404,
|
||||
HttpResponseBadRequest,
|
||||
HttpResponseForbidden,
|
||||
HttpResponseNotFound,
|
||||
@@ -15,10 +14,10 @@ ERROR_400_TEMPLATE_NAME: str
|
||||
ERROR_500_TEMPLATE_NAME: str
|
||||
|
||||
def page_not_found(
|
||||
request: WSGIRequest, exception: Optional[Http404], template_name: str = ...
|
||||
request: HttpRequest, exception: Optional[Exception], template_name: str = ...
|
||||
) -> HttpResponseNotFound: ...
|
||||
def server_error(request: WSGIRequest, template_name: str = ...) -> HttpResponseServerError: ...
|
||||
def bad_request(request: WSGIRequest, exception: Exception, template_name: str = ...) -> HttpResponseBadRequest: ...
|
||||
def server_error(request: HttpRequest, template_name: str = ...) -> HttpResponseServerError: ...
|
||||
def bad_request(request: HttpRequest, exception: Exception, template_name: str = ...) -> HttpResponseBadRequest: ...
|
||||
def permission_denied(
|
||||
request: WSGIRequest, exception: Exception, template_name: str = ...
|
||||
request: HttpRequest, exception: Exception, template_name: str = ...
|
||||
) -> HttpResponseForbidden: ...
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from django.views.generic.base import RedirectView as RedirectView, TemplateView as TemplateView, View as View
|
||||
from django.views.generic.dates import (
|
||||
from .base import RedirectView as RedirectView, TemplateView as TemplateView, View as View
|
||||
from .dates import (
|
||||
ArchiveIndexView as ArchiveIndexView,
|
||||
DateDetailView as DateDetailView,
|
||||
DayArchiveView as DayArchiveView,
|
||||
@@ -8,13 +8,8 @@ from django.views.generic.dates import (
|
||||
WeekArchiveView as WeekArchiveView,
|
||||
YearArchiveView as YearArchiveView,
|
||||
)
|
||||
from django.views.generic.detail import DetailView as DetailView
|
||||
from django.views.generic.edit import (
|
||||
CreateView as CreateView,
|
||||
DeleteView as DeleteView,
|
||||
FormView as FormView,
|
||||
UpdateView as UpdateView,
|
||||
)
|
||||
from django.views.generic.list import ListView as ListView
|
||||
from .detail import DetailView as DetailView
|
||||
from .edit import CreateView as CreateView, DeleteView as DeleteView, FormView as FormView, UpdateView as UpdateView
|
||||
from .list import ListView as ListView
|
||||
|
||||
class GenericViewError(Exception): ...
|
||||
|
||||
@@ -1,48 +1,43 @@
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Type
|
||||
from typing import Any, Callable, Dict, List, Optional, Type
|
||||
|
||||
from django import http
|
||||
|
||||
logger = ... # type: Any
|
||||
|
||||
class ContextMixin:
|
||||
def get_context_data(self, **kwargs: object) -> Dict[str, Any]: ...
|
||||
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]: ...
|
||||
|
||||
class View:
|
||||
http_method_names = ... # type: List[str]
|
||||
request = ... # type: http.HttpRequest
|
||||
args = ... # type: Tuple[object, ...]
|
||||
kwargs = ... # type: Dict[str, object]
|
||||
def __init__(self, **kwargs: object) -> None: ...
|
||||
http_method_names: List[str] = ...
|
||||
request: http.HttpRequest = ...
|
||||
args: Any = ...
|
||||
kwargs: Any = ...
|
||||
def __init__(self, **kwargs: Any) -> None: ...
|
||||
@classmethod
|
||||
def as_view(cls: Any, **initkwargs: object) -> Callable[..., http.HttpResponse]: ...
|
||||
def dispatch(self, request: http.HttpRequest, *args: object, **kwargs: object) -> http.HttpResponse: ...
|
||||
def http_method_not_allowed(
|
||||
self, request: http.HttpRequest, *args: object, **kwargs: object
|
||||
) -> http.HttpResponse: ...
|
||||
def options(self, request: http.HttpRequest, *args: object, **kwargs: object) -> http.HttpResponse: ...
|
||||
def as_view(cls: Any, **initkwargs: Any) -> Callable[..., http.HttpResponse]: ...
|
||||
def dispatch(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> http.HttpResponse: ...
|
||||
def http_method_not_allowed(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> http.HttpResponse: ...
|
||||
def options(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> http.HttpResponse: ...
|
||||
|
||||
class TemplateResponseMixin:
|
||||
template_name = ... # type: str
|
||||
template_engine = ... # type: Optional[str]
|
||||
response_class = ... # type: Type[http.HttpResponse]
|
||||
content_type = ... # type: Optional[str]
|
||||
request = ... # type: http.HttpRequest
|
||||
def render_to_response(self, context: Dict[str, object], **response_kwargs: object) -> http.HttpResponse: ...
|
||||
template_name: str = ...
|
||||
template_engine: Optional[str] = ...
|
||||
response_class: Type[http.HttpResponse] = ...
|
||||
content_type: Optional[str] = ...
|
||||
request: http.HttpRequest = ...
|
||||
def render_to_response(self, context: Dict[str, Any], **response_kwargs: Any) -> http.HttpResponse: ...
|
||||
def get_template_names(self) -> List[str]: ...
|
||||
|
||||
class TemplateView(TemplateResponseMixin, ContextMixin, View):
|
||||
def get(self, request: http.HttpRequest, *args: object, **kwargs: object) -> http.HttpResponse: ...
|
||||
def get(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> http.HttpResponse: ...
|
||||
|
||||
class RedirectView(View):
|
||||
permanent = ... # type: bool
|
||||
url = ... # type: Optional[str]
|
||||
pattern_name = ... # type: Optional[str]
|
||||
query_string = ... # type: bool
|
||||
def get_redirect_url(self, *args: object, **kwargs: object) -> Optional[str]: ...
|
||||
def get(self, request: http.HttpRequest, *args: object, **kwargs: object) -> http.HttpResponse: ...
|
||||
def head(self, request: http.HttpRequest, *args: object, **kwargs: object) -> http.HttpResponse: ...
|
||||
def post(self, request: http.HttpRequest, *args: object, **kwargs: object) -> http.HttpResponse: ...
|
||||
def options(self, request: http.HttpRequest, *args: object, **kwargs: object) -> http.HttpResponse: ...
|
||||
def delete(self, request: http.HttpRequest, *args: object, **kwargs: object) -> http.HttpResponse: ...
|
||||
def put(self, request: http.HttpRequest, *args: object, **kwargs: object) -> http.HttpResponse: ...
|
||||
def patch(self, request: http.HttpRequest, *args: object, **kwargs: object) -> http.HttpResponse: ...
|
||||
permanent: bool = ...
|
||||
url: Optional[str] = ...
|
||||
pattern_name: Optional[str] = ...
|
||||
query_string: bool = ...
|
||||
def get_redirect_url(self, *args: Any, **kwargs: Any) -> Optional[str]: ...
|
||||
def get(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> http.HttpResponse: ...
|
||||
def head(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> http.HttpResponse: ...
|
||||
def post(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> http.HttpResponse: ...
|
||||
def delete(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> http.HttpResponse: ...
|
||||
def put(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> http.HttpResponse: ...
|
||||
def patch(self, request: http.HttpRequest, *args: Any, **kwargs: Any) -> http.HttpResponse: ...
|
||||
|
||||
@@ -8,49 +8,49 @@ from django.views.generic.detail import BaseDetailView, SingleObjectTemplateResp
|
||||
from django.views.generic.list import MultipleObjectMixin, MultipleObjectTemplateResponseMixin
|
||||
|
||||
class YearMixin:
|
||||
year_format = ... # type: str
|
||||
year = ... # type: Optional[str]
|
||||
kwargs = ... # type: Dict[str, object]
|
||||
request = ... # type: HttpRequest
|
||||
year_format: str = ...
|
||||
year: Optional[str] = ...
|
||||
kwargs: Dict[str, Any] = ...
|
||||
request: HttpRequest = ...
|
||||
def get_year_format(self) -> str: ...
|
||||
def get_year(self) -> str: ...
|
||||
def get_next_year(self, date: datetime.date) -> Optional[datetime.date]: ...
|
||||
def get_previous_year(self, date: datetime.date) -> Optional[datetime.date]: ...
|
||||
|
||||
class MonthMixin:
|
||||
month_format = ... # type: str
|
||||
month = ... # type: Optional[str]
|
||||
request = ... # type: HttpRequest
|
||||
kwargs = ... # type: Dict[str, object]
|
||||
month_format: str = ...
|
||||
month: Optional[str] = ...
|
||||
request: HttpRequest = ...
|
||||
kwargs: Dict[str, Any] = ...
|
||||
def get_month_format(self) -> str: ...
|
||||
def get_month(self) -> str: ...
|
||||
def get_next_month(self, date: datetime.date) -> Optional[datetime.date]: ...
|
||||
def get_previous_month(self, date: datetime.date) -> Optional[datetime.date]: ...
|
||||
|
||||
class DayMixin:
|
||||
day_format = ... # type: str
|
||||
day = ... # type: Optional[str]
|
||||
request = ... # type: HttpRequest
|
||||
kwargs = ... # type: Dict[str, object]
|
||||
day_format: str = ...
|
||||
day: Optional[str] = ...
|
||||
request: HttpRequest = ...
|
||||
kwargs: Dict[str, Any] = ...
|
||||
def get_day_format(self) -> str: ...
|
||||
def get_day(self) -> str: ...
|
||||
def get_next_day(self, date: datetime.date) -> Optional[datetime.date]: ...
|
||||
def get_previous_day(self, date: datetime.date) -> Optional[datetime.date]: ...
|
||||
|
||||
class WeekMixin:
|
||||
week_format = ... # type: str
|
||||
week = ... # type: Optional[str]
|
||||
request = ... # type: HttpRequest
|
||||
kwargs = ... # type: Dict[str, object]
|
||||
week_format: str = ...
|
||||
week: Optional[str] = ...
|
||||
request: HttpRequest = ...
|
||||
kwargs: Dict[str, Any] = ...
|
||||
def get_week_format(self) -> str: ...
|
||||
def get_week(self) -> str: ...
|
||||
def get_next_week(self, date: datetime.date) -> Optional[datetime.date]: ...
|
||||
def get_previous_week(self, date: datetime.date) -> Optional[datetime.date]: ...
|
||||
|
||||
class DateMixin:
|
||||
date_field = ... # type: Optional[str]
|
||||
allow_future = ... # type: bool
|
||||
model = ... # type: Optional[Type[models.Model]]
|
||||
date_field: Optional[str] = ...
|
||||
allow_future: bool = ...
|
||||
model: Optional[Type[models.Model]] = ...
|
||||
def get_date_field(self) -> str: ...
|
||||
def get_allow_future(self) -> bool: ...
|
||||
def uses_datetime_field(self) -> bool: ...
|
||||
@@ -58,63 +58,33 @@ class DateMixin:
|
||||
DatedItems = Tuple[Optional[Sequence[datetime.date]], Sequence[object], Dict[str, Any]]
|
||||
|
||||
class BaseDateListView(MultipleObjectMixin, DateMixin, View):
|
||||
allow_empty = ... # type: bool
|
||||
date_list_period = ... # type: str
|
||||
def render_to_response(self, context: Dict[str, object], **response_kwargs: object) -> HttpResponse: ...
|
||||
def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
|
||||
date_list_period: str = ...
|
||||
def render_to_response(self, context: Dict[str, Any], **response_kwargs: Any) -> HttpResponse: ...
|
||||
def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
def get_dated_items(self) -> DatedItems: ...
|
||||
def get_ordering(self) -> Sequence[str]: ...
|
||||
def get_dated_queryset(self, **lookup: object) -> models.query.QuerySet: ...
|
||||
def get_dated_queryset(self, **lookup: Any) -> models.query.QuerySet: ...
|
||||
def get_date_list_period(self) -> str: ...
|
||||
def get_date_list(
|
||||
self, queryset: models.query.QuerySet, date_type: str = None, ordering: str = ...
|
||||
self, queryset: models.query.QuerySet, date_type: Optional[str] = ..., ordering: str = ...
|
||||
) -> models.query.QuerySet: ...
|
||||
|
||||
class BaseArchiveIndexView(BaseDateListView):
|
||||
context_object_name = ... # type: str
|
||||
def get_dated_items(self) -> DatedItems: ...
|
||||
|
||||
class ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView):
|
||||
template_name_suffix = ... # type: str
|
||||
class BaseArchiveIndexView(BaseDateListView): ...
|
||||
class ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView): ...
|
||||
|
||||
class BaseYearArchiveView(YearMixin, BaseDateListView):
|
||||
date_list_period = ... # type: str
|
||||
make_object_list = ... # type: bool
|
||||
def get_dated_items(self) -> DatedItems: ...
|
||||
make_object_list: bool = ...
|
||||
def get_make_object_list(self) -> bool: ...
|
||||
|
||||
class YearArchiveView(MultipleObjectTemplateResponseMixin, BaseYearArchiveView):
|
||||
template_name_suffix = ... # type: str
|
||||
|
||||
class BaseMonthArchiveView(YearMixin, MonthMixin, BaseDateListView):
|
||||
date_list_period = ... # type: str
|
||||
def get_dated_items(self) -> DatedItems: ...
|
||||
|
||||
class MonthArchiveView(MultipleObjectTemplateResponseMixin, BaseMonthArchiveView):
|
||||
template_name_suffix = ... # type: str
|
||||
|
||||
class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView):
|
||||
def get_dated_items(self) -> DatedItems: ...
|
||||
|
||||
class WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView):
|
||||
template_name_suffix = ... # type: str
|
||||
|
||||
class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView):
|
||||
def get_dated_items(self) -> DatedItems: ...
|
||||
|
||||
class DayArchiveView(MultipleObjectTemplateResponseMixin, BaseDayArchiveView):
|
||||
template_name_suffix = ... # type: str
|
||||
|
||||
class BaseTodayArchiveView(BaseDayArchiveView):
|
||||
def get_dated_items(self) -> DatedItems: ...
|
||||
|
||||
class TodayArchiveView(MultipleObjectTemplateResponseMixin, BaseTodayArchiveView):
|
||||
template_name_suffix = ... # type: str
|
||||
|
||||
class BaseDateDetailView(YearMixin, MonthMixin, DayMixin, DateMixin, BaseDetailView):
|
||||
def get_object(self, queryset: models.query.QuerySet = None) -> models.Model: ...
|
||||
|
||||
class DateDetailView(SingleObjectTemplateResponseMixin, BaseDateDetailView):
|
||||
template_name_suffix = ... # type: str
|
||||
class YearArchiveView(MultipleObjectTemplateResponseMixin, BaseYearArchiveView): ...
|
||||
class BaseMonthArchiveView(YearMixin, MonthMixin, BaseDateListView): ...
|
||||
class MonthArchiveView(MultipleObjectTemplateResponseMixin, BaseMonthArchiveView): ...
|
||||
class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView): ...
|
||||
class WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView): ...
|
||||
class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView): ...
|
||||
class DayArchiveView(MultipleObjectTemplateResponseMixin, BaseDayArchiveView): ...
|
||||
class BaseTodayArchiveView(BaseDayArchiveView): ...
|
||||
class TodayArchiveView(MultipleObjectTemplateResponseMixin, BaseTodayArchiveView): ...
|
||||
class BaseDateDetailView(YearMixin, MonthMixin, DayMixin, DateMixin, BaseDetailView): ...
|
||||
class DateDetailView(SingleObjectTemplateResponseMixin, BaseDateDetailView): ...
|
||||
|
||||
def timezone_today() -> datetime.date: ...
|
||||
|
||||
@@ -1,35 +1,33 @@
|
||||
from typing import Any, Dict, List, Optional, Type
|
||||
from typing import Any, Dict, Optional, Type
|
||||
|
||||
from django.db import models
|
||||
from django.http import HttpResponse, HttpRequest
|
||||
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
|
||||
|
||||
from django.db import models
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
|
||||
class SingleObjectMixin(ContextMixin):
|
||||
model = ... # type: Optional[Type[models.Model]]
|
||||
queryset = ... # type: Optional[models.query.QuerySet]
|
||||
slug_field = ... # type: str
|
||||
context_object_name = ... # type: Optional[str]
|
||||
slug_url_kwarg = ... # type: str
|
||||
pk_url_kwarg = ... # type: str
|
||||
query_pk_and_slug = ... # type: bool
|
||||
object = ... # type: models.Model
|
||||
kwargs = ... # type: Dict[str, object]
|
||||
def get_object(self, queryset: models.query.QuerySet = None) -> models.Model: ...
|
||||
model: Optional[Type[models.Model]] = ...
|
||||
queryset: Optional[models.query.QuerySet] = ...
|
||||
slug_field: str = ...
|
||||
context_object_name: Optional[str] = ...
|
||||
slug_url_kwarg: str = ...
|
||||
pk_url_kwarg: str = ...
|
||||
query_pk_and_slug: bool = ...
|
||||
object: models.Model = ...
|
||||
kwargs: Dict[str, Any] = ...
|
||||
def get_object(self, queryset: Optional[models.query.QuerySet] = ...) -> models.Model: ...
|
||||
def get_queryset(self) -> models.query.QuerySet: ...
|
||||
def get_slug_field(self) -> str: ...
|
||||
def get_context_object_name(self, obj: Any) -> Optional[str]: ...
|
||||
def get_context_data(self, **kwargs: object) -> Dict[str, Any]: ...
|
||||
|
||||
class BaseDetailView(SingleObjectMixin, View):
|
||||
def render_to_response(self, context: Dict[str, object], **response_kwargs: object) -> HttpResponse: ...
|
||||
object = ... # type: models.Model
|
||||
def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
|
||||
def render_to_response(self, context: Dict[str, Any], **response_kwargs: Any) -> HttpResponse: ...
|
||||
def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
|
||||
class SingleObjectTemplateResponseMixin(TemplateResponseMixin):
|
||||
template_name_field = ... # type: Optional[str]
|
||||
template_name_suffix = ... # type: str
|
||||
model = ... # type: Optional[Type[models.Model]]
|
||||
object = ... # type: models.Model
|
||||
def get_template_names(self) -> List[str]: ...
|
||||
template_name_field: Optional[str] = ...
|
||||
template_name_suffix: str = ...
|
||||
model: Optional[Type[models.Model]] = ...
|
||||
object: models.Model = ...
|
||||
|
||||
class DetailView(SingleObjectTemplateResponseMixin, BaseDetailView): ...
|
||||
|
||||
@@ -1,77 +1,53 @@
|
||||
from typing import Any, Callable, Dict, Optional, Sequence, Type, Union
|
||||
|
||||
from django.db import models
|
||||
from django.forms.forms import BaseForm
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
|
||||
from django.views.generic.detail import BaseDetailView, SingleObjectMixin, SingleObjectTemplateResponseMixin
|
||||
from typing_extensions import Literal
|
||||
|
||||
from django.db import models
|
||||
from django.forms import Form
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
|
||||
class FormMixin(ContextMixin):
|
||||
initial: Dict[str, Any] = ...
|
||||
form_class: Optional[Type[Form]] = ...
|
||||
form_class: Optional[Type[BaseForm]] = ...
|
||||
success_url: Optional[Union[str, Callable[..., Any]]] = ...
|
||||
prefix: Optional[str] = ...
|
||||
request: HttpRequest = ...
|
||||
def render_to_response(self, context: Dict[str, Any], **response_kwargs: object) -> HttpResponse: ...
|
||||
def get_initial(self) -> Dict[str, Any]: ...
|
||||
def get_prefix(self) -> Optional[str]: ...
|
||||
def get_form_class(self) -> Type[Form]: ...
|
||||
def get_form(self, form_class: Type[Form] = None) -> Form: ...
|
||||
def get_form_class(self) -> Type[BaseForm]: ...
|
||||
def get_form(self, form_class: Optional[Type[BaseForm]] = None) -> BaseForm: ...
|
||||
def get_form_kwargs(self) -> Dict[str, Any]: ...
|
||||
def get_success_url(self) -> str: ...
|
||||
def form_valid(self, form: Form) -> HttpResponse: ...
|
||||
def form_invalid(self, form: Form) -> HttpResponse: ...
|
||||
def get_context_data(self, **kwargs: object) -> Dict[str, Any]: ...
|
||||
def form_valid(self, form: BaseForm) -> HttpResponse: ...
|
||||
def form_invalid(self, form: BaseForm) -> HttpResponse: ...
|
||||
|
||||
class ModelFormMixin(FormMixin, SingleObjectMixin):
|
||||
fields: Optional[Union[Sequence[str], Literal["__all__"]]] = ...
|
||||
object: models.Model = ...
|
||||
def get_form_class(self) -> Type[Form]: ...
|
||||
def get_form_kwargs(self) -> Dict[str, object]: ...
|
||||
def get_success_url(self) -> str: ...
|
||||
def form_valid(self, form: Form) -> HttpResponse: ...
|
||||
|
||||
class ProcessFormView(View):
|
||||
def render_to_response(self, context: Dict[str, object], **response_kwargs: object) -> HttpResponse: ...
|
||||
def get_context_data(self, **kwargs: object) -> Dict[str, Any]: ...
|
||||
def get_form(self, form_class: Type[Form] = None) -> Form: ...
|
||||
def form_valid(self, form: Form) -> HttpResponse: ...
|
||||
def form_invalid(self, form: Form) -> HttpResponse: ...
|
||||
def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
|
||||
def post(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
|
||||
def put(self, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
def render_to_response(self, context: Dict[str, Any], **response_kwargs: Any) -> HttpResponse: ...
|
||||
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]: ...
|
||||
def get(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: ...
|
||||
def post(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: ...
|
||||
def put(self, *args: str, **kwargs: Any) -> HttpResponse: ...
|
||||
|
||||
class BaseFormView(FormMixin, ProcessFormView): ...
|
||||
class FormView(TemplateResponseMixin, BaseFormView): ...
|
||||
|
||||
class BaseCreateView(ModelFormMixin, ProcessFormView):
|
||||
object = ... # type: models.Model
|
||||
def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
|
||||
def post(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
|
||||
|
||||
class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):
|
||||
template_name_suffix = ... # type: str
|
||||
|
||||
class BaseUpdateView(ModelFormMixin, ProcessFormView):
|
||||
object = ... # type: models.Model
|
||||
def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
|
||||
def post(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
|
||||
|
||||
class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView):
|
||||
template_name_suffix = ... # type: str
|
||||
class BaseCreateView(ModelFormMixin, ProcessFormView): ...
|
||||
class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView): ...
|
||||
class BaseUpdateView(ModelFormMixin, ProcessFormView): ...
|
||||
class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView): ...
|
||||
|
||||
_object = object
|
||||
|
||||
class DeletionMixin:
|
||||
success_url = ... # type: Optional[str]
|
||||
object = ... # type: models.Model
|
||||
def delete(self, request: HttpRequest, *args: _object, **kwargs: _object) -> HttpResponse: ...
|
||||
def post(self, request: HttpRequest, *args: _object, **kwargs: _object) -> HttpResponse: ...
|
||||
success_url: Optional[str] = ...
|
||||
object: models.Model = ...
|
||||
def post(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: ...
|
||||
def delete(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: ...
|
||||
def get_success_url(self) -> str: ...
|
||||
|
||||
class BaseDeleteView(DeletionMixin, BaseDetailView): ...
|
||||
|
||||
class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView):
|
||||
template_name_suffix = ... # type: str
|
||||
class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView): ...
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
from typing import Any, Dict, List, Optional, Sequence, Tuple, Type
|
||||
from typing import Any, Dict, Optional, Sequence, Tuple, Type
|
||||
|
||||
from django.db.models import Model
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models.query import QuerySet
|
||||
from django.core.paginator import Paginator # type: ignore # This will be fixed when adding the paginator module
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
|
||||
|
||||
from django.db.models import Model
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
|
||||
class MultipleObjectMixin(ContextMixin):
|
||||
allow_empty = ... # type: bool
|
||||
queryset = ... # type: Optional[QuerySet]
|
||||
model = ... # type: Optional[Type[Model]]
|
||||
paginate_by = ... # type: Optional[int]
|
||||
paginate_orphans = ... # type: int
|
||||
context_object_name = ... # type: Optional[str]
|
||||
paginator_class = ... # type: Type[Paginator]
|
||||
page_kwarg = ... # type: str
|
||||
ordering = ... # type: Sequence[str]
|
||||
request = ... # type: HttpRequest
|
||||
kwargs = ... # type: Dict[str, object]
|
||||
object_list = ... # type: QuerySet
|
||||
allow_empty: bool = ...
|
||||
queryset: Optional[QuerySet] = ...
|
||||
model: Optional[Type[Model]] = ...
|
||||
paginate_by: Optional[int] = ...
|
||||
paginate_orphans: int = ...
|
||||
context_object_name: Optional[str] = ...
|
||||
paginator_class: Type[Paginator] = ...
|
||||
page_kwarg: str = ...
|
||||
ordering: Sequence[str] = ...
|
||||
request: HttpRequest = ...
|
||||
kwargs: Dict[str, Any] = ...
|
||||
object_list: QuerySet = ...
|
||||
def get_queryset(self) -> QuerySet: ...
|
||||
def get_ordering(self) -> Sequence[str]: ...
|
||||
def paginate_queryset(self, queryset: QuerySet, page_size: int) -> Tuple[Paginator, int, QuerySet, bool]: ...
|
||||
@@ -29,16 +30,13 @@ class MultipleObjectMixin(ContextMixin):
|
||||
def get_paginate_orphans(self) -> int: ...
|
||||
def get_allow_empty(self) -> bool: ...
|
||||
def get_context_object_name(self, object_list: QuerySet) -> Optional[str]: ...
|
||||
def get_context_data(self, **kwargs: object) -> Dict[str, Any]: ...
|
||||
|
||||
class BaseListView(MultipleObjectMixin, View):
|
||||
object_list = ... # type: QuerySet
|
||||
def render_to_response(self, context: Dict[str, object], **response_kwargs: object) -> HttpResponse: ...
|
||||
def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
|
||||
def render_to_response(self, context: Dict[str, Any], **response_kwargs: Any) -> HttpResponse: ...
|
||||
def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
|
||||
class MultipleObjectTemplateResponseMixin(TemplateResponseMixin):
|
||||
template_name_suffix = ... # type: str
|
||||
object_list = ... # type: QuerySet
|
||||
def get_template_names(self) -> List[str]: ...
|
||||
template_name_suffix: str = ...
|
||||
object_list: QuerySet = ...
|
||||
|
||||
class ListView(MultipleObjectTemplateResponseMixin, BaseListView): ...
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
from typing import Any, Callable, Dict, List, Optional, Union
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import HttpResponse
|
||||
from django.utils.translation.trans_real import DjangoTranslation
|
||||
|
||||
from django.views.generic import View
|
||||
|
||||
LANGUAGE_QUERY_PARAMETER: str
|
||||
|
||||
def set_language(request: WSGIRequest) -> HttpResponse: ...
|
||||
def set_language(request: HttpRequest) -> HttpResponse: ...
|
||||
def get_formats() -> Dict[str, Union[List[str], int, str]]: ...
|
||||
|
||||
js_catalog_template: str
|
||||
@@ -15,21 +17,15 @@ def render_javascript_catalog(catalog: Optional[Any] = ..., plural: Optional[Any
|
||||
def null_javascript_catalog(request: Any, domain: Optional[Any] = ..., packages: Optional[Any] = ...): ...
|
||||
|
||||
class JavaScriptCatalog(View):
|
||||
args: Tuple
|
||||
head: Callable
|
||||
kwargs: Dict[Any, Any]
|
||||
request: WSGIRequest
|
||||
domain: str = ...
|
||||
packages: List[str] = ...
|
||||
translation: django.utils.translation.trans_real.DjangoTranslation = ...
|
||||
def get(self, request: WSGIRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
translation: DjangoTranslation = ...
|
||||
def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
|
||||
def get_paths(self, packages: List[str]) -> List[str]: ...
|
||||
def get_plural(self) -> None: ...
|
||||
def get_catalog(self) -> Dict[str, Union[List[str], str]]: ...
|
||||
def get_context_data(self, **kwargs: Any) -> Dict[str, Optional[Dict[str, Union[List[str], int, str]]]]: ...
|
||||
def render_to_response(
|
||||
self, context: Dict[str, Optional[Dict[str, Union[List[str], int, str]]]], **response_kwargs: Any
|
||||
) -> HttpResponse: ...
|
||||
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]: ...
|
||||
def render_to_response(self, context: Dict[str, Any], **response_kwargs: Any) -> HttpResponse: ...
|
||||
|
||||
class JSONCatalog(JavaScriptCatalog):
|
||||
def render_to_response(self, context: Any, **response_kwargs: Any): ...
|
||||
class JSONCatalog(JavaScriptCatalog): ...
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from typing import Any, Optional
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http.request import HttpRequest
|
||||
from django.http.response import FileResponse
|
||||
|
||||
def serve(request: WSGIRequest, path: str, document_root: str = ..., show_indexes: bool = ...) -> FileResponse: ...
|
||||
def serve(request: HttpRequest, path: str, document_root: str = ..., show_indexes: bool = ...) -> FileResponse: ...
|
||||
|
||||
DEFAULT_DIRECTORY_INDEX_TEMPLATE: str
|
||||
template_translatable: Any
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from configparser import ConfigParser
|
||||
from typing import List, Optional
|
||||
from typing import Optional
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
@@ -20,6 +20,7 @@ class Config:
|
||||
fallback=None)
|
||||
if django_settings:
|
||||
django_settings = django_settings.strip()
|
||||
|
||||
return Config(django_settings_module=django_settings,
|
||||
ignore_missing_settings=ini_config.get('mypy_django_plugin', 'ignore_missing_settings',
|
||||
fallback=False))
|
||||
ignore_missing_settings=bool(ini_config.get('mypy_django_plugin', 'ignore_missing_settings',
|
||||
fallback=False)))
|
||||
|
||||
@@ -2,10 +2,13 @@ import typing
|
||||
from typing import Dict, Optional
|
||||
|
||||
from mypy.checker import TypeChecker
|
||||
from mypy.nodes import AssignmentStmt, ClassDef, Expression, ImportedName, Lvalue, MypyFile, NameExpr, SymbolNode, \
|
||||
TypeInfo
|
||||
from mypy.plugin import FunctionContext
|
||||
from mypy.types import AnyType, Instance, NoneTyp, Type, TypeOfAny, TypeVarType, UnionType
|
||||
from mypy.nodes import (
|
||||
AssignmentStmt, ClassDef, Expression, ImportedName, Lvalue, MypyFile, NameExpr, SymbolNode, TypeInfo,
|
||||
)
|
||||
from mypy.plugin import FunctionContext, MethodContext
|
||||
from mypy.types import (
|
||||
AnyType, Instance, NoneTyp, Type, TypeOfAny, TypeVarType, UnionType,
|
||||
)
|
||||
|
||||
MODEL_CLASS_FULLNAME = 'django.db.models.base.Model'
|
||||
FIELD_FULLNAME = 'django.db.models.fields.Field'
|
||||
@@ -23,6 +26,12 @@ BASE_MANAGER_CLASS_FULLNAME = 'django.db.models.manager.BaseManager'
|
||||
MANAGER_CLASS_FULLNAME = 'django.db.models.manager.Manager'
|
||||
RELATED_MANAGER_CLASS_FULLNAME = 'django.db.models.manager.RelatedManager'
|
||||
|
||||
BASEFORM_CLASS_FULLNAME = 'django.forms.forms.BaseForm'
|
||||
FORM_CLASS_FULLNAME = 'django.forms.forms.Form'
|
||||
MODELFORM_CLASS_FULLNAME = 'django.forms.models.ModelForm'
|
||||
|
||||
FORM_MIXIN_CLASS_FULLNAME = 'django.views.generic.edit.FormMixin'
|
||||
|
||||
MANAGER_CLASSES = {
|
||||
MANAGER_CLASS_FULLNAME,
|
||||
RELATED_MANAGER_CLASS_FULLNAME,
|
||||
@@ -54,9 +63,9 @@ def get_model_fullname(app_name: str, model_name: str,
|
||||
return None
|
||||
|
||||
|
||||
class InvalidModelString(ValueError):
|
||||
def __init__(self, model_string: str):
|
||||
self.model_string = model_string
|
||||
class SameFileModel(Exception):
|
||||
def __init__(self, model_cls_name: str):
|
||||
self.model_cls_name = model_cls_name
|
||||
|
||||
|
||||
class SelfReference(ValueError):
|
||||
@@ -69,7 +78,7 @@ def get_model_fullname_from_string(model_string: str,
|
||||
raise SelfReference()
|
||||
|
||||
if '.' not in model_string:
|
||||
raise InvalidModelString(model_string)
|
||||
raise SameFileModel(model_string)
|
||||
|
||||
app_name, model_name = model_string.split('.')
|
||||
return get_model_fullname(app_name, model_name, all_modules)
|
||||
@@ -124,7 +133,7 @@ def fill_typevars(tp: Instance, type_to_fill: Instance) -> Instance:
|
||||
return Instance(type_to_fill.type, typevar_values)
|
||||
|
||||
|
||||
def get_argument_by_name(ctx: FunctionContext, name: str) -> Optional[Expression]:
|
||||
def get_argument_by_name(ctx: typing.Union[FunctionContext, MethodContext], name: str) -> Optional[Expression]:
|
||||
"""Return the expression for the specific argument.
|
||||
|
||||
This helper should only be used with non-star arguments.
|
||||
@@ -139,7 +148,7 @@ def get_argument_by_name(ctx: FunctionContext, name: str) -> Optional[Expression
|
||||
return args[0]
|
||||
|
||||
|
||||
def get_argument_type_by_name(ctx: FunctionContext, name: str) -> Optional[Type]:
|
||||
def get_argument_type_by_name(ctx: typing.Union[FunctionContext, MethodContext], name: str) -> Optional[Type]:
|
||||
"""Return the type for the specific argument.
|
||||
|
||||
This helper should only be used with non-star arguments.
|
||||
@@ -176,8 +185,8 @@ def get_setting_expr(api: TypeChecker, setting_name: str) -> Optional[Expression
|
||||
return None
|
||||
|
||||
|
||||
def iter_over_assignments(
|
||||
class_or_module: typing.Union[ClassDef, MypyFile]) -> typing.Iterator[typing.Tuple[Lvalue, Expression]]:
|
||||
def iter_over_assignments(class_or_module: typing.Union[ClassDef, MypyFile]
|
||||
) -> typing.Iterator[typing.Tuple[Lvalue, Expression]]:
|
||||
if isinstance(class_or_module, ClassDef):
|
||||
statements = class_or_module.defs.body
|
||||
else:
|
||||
@@ -246,7 +255,7 @@ def extract_primary_key_type_for_get(model: TypeInfo) -> Optional[Type]:
|
||||
|
||||
|
||||
def make_optional(typ: Type):
|
||||
return UnionType.make_simplified_union([typ, NoneTyp()])
|
||||
return UnionType.make_union([typ, NoneTyp()])
|
||||
|
||||
|
||||
def make_required(typ: Type) -> Type:
|
||||
@@ -273,3 +282,17 @@ def has_any_of_bases(info: TypeInfo, bases: typing.Sequence[str]) -> bool:
|
||||
|
||||
def is_none_expr(expr: Expression) -> bool:
|
||||
return isinstance(expr, NameExpr) and expr.fullname == 'builtins.None'
|
||||
|
||||
|
||||
def get_nested_meta_node_for_current_class(info: TypeInfo) -> Optional[TypeInfo]:
|
||||
metaclass_sym = info.names.get('Meta')
|
||||
if metaclass_sym is not None and isinstance(metaclass_sym.node, TypeInfo):
|
||||
return metaclass_sym.node
|
||||
return None
|
||||
|
||||
|
||||
def get_assigned_value_for_class(type_info: TypeInfo, name: str) -> Optional[Expression]:
|
||||
for lvalue, rvalue in iter_over_assignments(type_info.defn):
|
||||
if isinstance(lvalue, NameExpr) and lvalue.name == name:
|
||||
return rvalue
|
||||
return None
|
||||
|
||||
@@ -2,17 +2,28 @@ import os
|
||||
from typing import Callable, Dict, Optional, Union, cast
|
||||
|
||||
from mypy.checker import TypeChecker
|
||||
from mypy.nodes import MemberExpr, TypeInfo
|
||||
from mypy.nodes import MemberExpr, NameExpr, TypeInfo
|
||||
from mypy.options import Options
|
||||
from mypy.plugin import AttributeContext, ClassDefContext, FunctionContext, MethodContext, Plugin
|
||||
from mypy.types import AnyType, Instance, Type, TypeOfAny, TypeType, UnionType
|
||||
from mypy.plugin import (
|
||||
AttributeContext, ClassDefContext, FunctionContext, MethodContext, Plugin,
|
||||
)
|
||||
from mypy.types import (
|
||||
AnyType, CallableType, Instance, NoneTyp, Type, TypeOfAny, TypeType, UnionType,
|
||||
)
|
||||
|
||||
from mypy_django_plugin import helpers, monkeypatch
|
||||
from mypy_django_plugin.config import Config
|
||||
from mypy_django_plugin.transformers import fields, init_create
|
||||
from mypy_django_plugin.transformers.migrations import determine_model_cls_from_string_for_migrations, \
|
||||
get_string_value_from_expr
|
||||
from mypy_django_plugin.transformers.forms import (
|
||||
make_meta_nested_class_inherit_from_any,
|
||||
)
|
||||
from mypy_django_plugin.transformers.migrations import (
|
||||
determine_model_cls_from_string_for_migrations, get_string_value_from_expr,
|
||||
)
|
||||
from mypy_django_plugin.transformers.models import process_model_class
|
||||
from mypy_django_plugin.transformers.settings import AddSettingValuesToDjangoConfObject, get_settings_metadata
|
||||
from mypy_django_plugin.transformers.settings import (
|
||||
AddSettingValuesToDjangoConfObject, get_settings_metadata,
|
||||
)
|
||||
|
||||
|
||||
def transform_model_class(ctx: ClassDefContext) -> None:
|
||||
@@ -33,6 +44,14 @@ def transform_manager_class(ctx: ClassDefContext) -> None:
|
||||
sym.node.metadata['django']['manager_bases'][ctx.cls.fullname] = 1
|
||||
|
||||
|
||||
def transform_form_class(ctx: ClassDefContext) -> None:
|
||||
sym = ctx.api.lookup_fully_qualified_or_none(helpers.BASEFORM_CLASS_FULLNAME)
|
||||
if sym is not None and isinstance(sym.node, TypeInfo):
|
||||
sym.node.metadata['django']['baseform_bases'][ctx.cls.fullname] = 1
|
||||
|
||||
make_meta_nested_class_inherit_from_any(ctx)
|
||||
|
||||
|
||||
def determine_proper_manager_type(ctx: FunctionContext) -> Type:
|
||||
api = cast(TypeChecker, ctx.api)
|
||||
ret = ctx.default_return_type
|
||||
@@ -148,6 +167,47 @@ class ExtractSettingType:
|
||||
return ctx.default_attr_type
|
||||
|
||||
|
||||
def transform_form_view(ctx: ClassDefContext) -> None:
|
||||
form_class_value = helpers.get_assigned_value_for_class(ctx.cls.info, 'form_class')
|
||||
if isinstance(form_class_value, NameExpr):
|
||||
helpers.get_django_metadata(ctx.cls.info)['form_class'] = form_class_value.fullname
|
||||
|
||||
|
||||
def extract_proper_type_for_get_form_class(ctx: MethodContext) -> Type:
|
||||
object_type = ctx.type
|
||||
if not isinstance(object_type, Instance):
|
||||
return ctx.default_return_type
|
||||
|
||||
form_class_fullname = helpers.get_django_metadata(object_type.type).get('form_class', None)
|
||||
if not form_class_fullname:
|
||||
return ctx.default_return_type
|
||||
|
||||
return TypeType(ctx.api.named_generic_type(form_class_fullname, []))
|
||||
|
||||
|
||||
def extract_proper_type_for_get_form(ctx: MethodContext) -> Type:
|
||||
object_type = ctx.type
|
||||
if not isinstance(object_type, Instance):
|
||||
return ctx.default_return_type
|
||||
|
||||
form_class_type = helpers.get_argument_type_by_name(ctx, 'form_class')
|
||||
if form_class_type is None or isinstance(form_class_type, NoneTyp):
|
||||
# extract from specified form_class in metadata
|
||||
form_class_fullname = helpers.get_django_metadata(object_type.type).get('form_class', None)
|
||||
if not form_class_fullname:
|
||||
return ctx.default_return_type
|
||||
|
||||
return ctx.api.named_generic_type(form_class_fullname, [])
|
||||
|
||||
if isinstance(form_class_type, TypeType) and isinstance(form_class_type.item, Instance):
|
||||
return form_class_type.item
|
||||
|
||||
if isinstance(form_class_type, CallableType) and isinstance(form_class_type.ret_type, Instance):
|
||||
return form_class_type.ret_type
|
||||
|
||||
return ctx.default_return_type
|
||||
|
||||
|
||||
class DjangoPlugin(Plugin):
|
||||
def __init__(self, options: Options) -> None:
|
||||
super().__init__(options)
|
||||
@@ -176,31 +236,31 @@ class DjangoPlugin(Plugin):
|
||||
def _get_current_model_bases(self) -> Dict[str, int]:
|
||||
model_sym = self.lookup_fully_qualified(helpers.MODEL_CLASS_FULLNAME)
|
||||
if model_sym is not None and isinstance(model_sym.node, TypeInfo):
|
||||
if 'django' not in model_sym.node.metadata:
|
||||
model_sym.node.metadata['django'] = {
|
||||
'model_bases': {helpers.MODEL_CLASS_FULLNAME: 1}
|
||||
}
|
||||
return model_sym.node.metadata['django']['model_bases']
|
||||
return (helpers.get_django_metadata(model_sym.node)
|
||||
.setdefault('model_bases', {helpers.MODEL_CLASS_FULLNAME: 1}))
|
||||
else:
|
||||
return {}
|
||||
|
||||
def _get_current_manager_bases(self) -> Dict[str, int]:
|
||||
manager_sym = self.lookup_fully_qualified(helpers.MANAGER_CLASS_FULLNAME)
|
||||
if manager_sym is not None and isinstance(manager_sym.node, TypeInfo):
|
||||
if 'django' not in manager_sym.node.metadata:
|
||||
manager_sym.node.metadata['django'] = {
|
||||
'manager_bases': {helpers.MANAGER_CLASS_FULLNAME: 1}
|
||||
}
|
||||
return manager_sym.node.metadata['django']['manager_bases']
|
||||
model_sym = self.lookup_fully_qualified(helpers.MANAGER_CLASS_FULLNAME)
|
||||
if model_sym is not None and isinstance(model_sym.node, TypeInfo):
|
||||
return (helpers.get_django_metadata(model_sym.node)
|
||||
.setdefault('manager_bases', {helpers.MANAGER_CLASS_FULLNAME: 1}))
|
||||
else:
|
||||
return {}
|
||||
|
||||
def _get_current_form_bases(self) -> Dict[str, int]:
|
||||
model_sym = self.lookup_fully_qualified(helpers.BASEFORM_CLASS_FULLNAME)
|
||||
if model_sym is not None and isinstance(model_sym.node, TypeInfo):
|
||||
return (helpers.get_django_metadata(model_sym.node)
|
||||
.setdefault('baseform_bases', {helpers.BASEFORM_CLASS_FULLNAME: 1,
|
||||
helpers.FORM_CLASS_FULLNAME: 1,
|
||||
helpers.MODELFORM_CLASS_FULLNAME: 1}))
|
||||
else:
|
||||
return {}
|
||||
|
||||
def get_function_hook(self, fullname: str
|
||||
) -> Optional[Callable[[FunctionContext], Type]]:
|
||||
sym = self.lookup_fully_qualified(fullname)
|
||||
if sym and isinstance(sym.node, TypeInfo) and sym.node.has_base(helpers.FIELD_FULLNAME):
|
||||
return fields.adjust_return_type_of_field_instantiation
|
||||
|
||||
if fullname == 'django.contrib.auth.get_user_model':
|
||||
return return_user_model_hook
|
||||
|
||||
@@ -209,27 +269,38 @@ class DjangoPlugin(Plugin):
|
||||
return determine_proper_manager_type
|
||||
|
||||
sym = self.lookup_fully_qualified(fullname)
|
||||
if sym and isinstance(sym.node, TypeInfo):
|
||||
if sym is not None and isinstance(sym.node, TypeInfo):
|
||||
if sym.node.has_base(helpers.FIELD_FULLNAME):
|
||||
return fields.adjust_return_type_of_field_instantiation
|
||||
|
||||
if sym.node.metadata.get('django', {}).get('generated_init'):
|
||||
return init_create.redefine_and_typecheck_model_init
|
||||
|
||||
def get_method_hook(self, fullname: str
|
||||
) -> Optional[Callable[[MethodContext], Type]]:
|
||||
manager_classes = self._get_current_manager_bases()
|
||||
class_fullname, _, method_name = fullname.rpartition('.')
|
||||
if class_fullname in manager_classes and method_name == 'create':
|
||||
return init_create.redefine_and_typecheck_model_create
|
||||
class_name, _, method_name = fullname.rpartition('.')
|
||||
if method_name == 'get_form_class':
|
||||
sym = self.lookup_fully_qualified(class_name)
|
||||
if sym and isinstance(sym.node, TypeInfo) and sym.node.has_base(helpers.FORM_MIXIN_CLASS_FULLNAME):
|
||||
return extract_proper_type_for_get_form_class
|
||||
|
||||
if method_name == 'get_form':
|
||||
sym = self.lookup_fully_qualified(class_name)
|
||||
if sym and isinstance(sym.node, TypeInfo) and sym.node.has_base(helpers.FORM_MIXIN_CLASS_FULLNAME):
|
||||
return extract_proper_type_for_get_form
|
||||
|
||||
if fullname in {'django.apps.registry.Apps.get_model',
|
||||
'django.db.migrations.state.StateApps.get_model'}:
|
||||
return determine_model_cls_from_string_for_migrations
|
||||
|
||||
manager_classes = self._get_current_manager_bases()
|
||||
class_fullname, _, method_name = fullname.rpartition('.')
|
||||
if class_fullname in manager_classes and method_name == 'create':
|
||||
return init_create.redefine_and_typecheck_model_create
|
||||
return None
|
||||
|
||||
def get_base_class_hook(self, fullname: str
|
||||
) -> Optional[Callable[[ClassDefContext], None]]:
|
||||
if fullname in self._get_current_model_bases():
|
||||
return transform_model_class
|
||||
|
||||
if fullname == helpers.DUMMY_SETTINGS_BASE_CLASS:
|
||||
settings_modules = ['django.conf.global_settings']
|
||||
if self.django_settings_module:
|
||||
@@ -237,13 +308,26 @@ class DjangoPlugin(Plugin):
|
||||
return AddSettingValuesToDjangoConfObject(settings_modules,
|
||||
self.config.ignore_missing_settings)
|
||||
|
||||
if fullname in self._get_current_model_bases():
|
||||
return transform_model_class
|
||||
|
||||
if fullname in self._get_current_manager_bases():
|
||||
return transform_manager_class
|
||||
|
||||
if fullname in self._get_current_form_bases():
|
||||
return transform_form_class
|
||||
|
||||
sym = self.lookup_fully_qualified(fullname)
|
||||
if sym and isinstance(sym.node, TypeInfo) and sym.node.has_base(helpers.FORM_MIXIN_CLASS_FULLNAME):
|
||||
return transform_form_view
|
||||
|
||||
return None
|
||||
|
||||
def get_attribute_hook(self, fullname: str
|
||||
) -> Optional[Callable[[AttributeContext], Type]]:
|
||||
if fullname == 'builtins.object.id':
|
||||
return return_integer_type_for_id_for_non_defined_primary_key_in_models
|
||||
|
||||
module, _, name = fullname.rpartition('.')
|
||||
sym = self.lookup_fully_qualified('django.conf.LazySettings')
|
||||
if sym and isinstance(sym.node, TypeInfo):
|
||||
@@ -251,9 +335,6 @@ class DjangoPlugin(Plugin):
|
||||
if module == 'builtins.object' and name in metadata:
|
||||
return ExtractSettingType(module_fullname=metadata[name])
|
||||
|
||||
if fullname == 'builtins.object.id':
|
||||
return return_integer_type_for_id_for_non_defined_primary_key_in_models
|
||||
|
||||
return extract_and_return_primary_key_of_bound_related_field_parameter
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
from .dependencies import (add_modules_as_a_source_seed_files,
|
||||
inject_modules_as_dependencies_for_django_conf_settings,
|
||||
restore_original_load_graph,
|
||||
restore_original_dependencies_handling)
|
||||
@@ -3,12 +3,14 @@ from typing import Optional, cast
|
||||
from mypy.checker import TypeChecker
|
||||
from mypy.nodes import ListExpr, NameExpr, StrExpr, TupleExpr, TypeInfo, Var
|
||||
from mypy.plugin import FunctionContext
|
||||
from mypy.types import AnyType, CallableType, Instance, TupleType, Type, TypeOfAny, UnionType
|
||||
from mypy.types import (
|
||||
AnyType, CallableType, Instance, TupleType, Type, TypeOfAny, UnionType,
|
||||
)
|
||||
|
||||
from mypy_django_plugin import helpers
|
||||
from mypy_django_plugin.transformers.models import iter_over_assignments
|
||||
|
||||
|
||||
def get_valid_to_value_or_none(ctx: FunctionContext) -> Optional[Instance]:
|
||||
def extract_referred_to_type(ctx: FunctionContext) -> Optional[Instance]:
|
||||
api = cast(TypeChecker, ctx.api)
|
||||
if 'to' not in ctx.callee_arg_names:
|
||||
api.msg.fail(f'to= parameter must be set for {ctx.context.callee.fullname}',
|
||||
@@ -27,6 +29,9 @@ def get_valid_to_value_or_none(ctx: FunctionContext) -> Optional[Instance]:
|
||||
except helpers.SelfReference:
|
||||
model_fullname = api.tscope.classes[-1].fullname()
|
||||
|
||||
except helpers.SameFileModel as exc:
|
||||
model_fullname = api.tscope.classes[-1].module_name + '.' + exc.model_cls_name
|
||||
|
||||
if model_fullname is None:
|
||||
return None
|
||||
model_info = helpers.lookup_fully_qualified_generic(model_fullname,
|
||||
@@ -52,8 +57,8 @@ def convert_any_to_type(typ: Type, referred_to_type: Type) -> Type:
|
||||
converted_items = []
|
||||
for item in typ.items:
|
||||
converted_items.append(convert_any_to_type(item, referred_to_type))
|
||||
return UnionType.make_simplified_union(converted_items,
|
||||
line=typ.line, column=typ.column)
|
||||
return UnionType.make_union(converted_items,
|
||||
line=typ.line, column=typ.column)
|
||||
if isinstance(typ, Instance):
|
||||
args = []
|
||||
for default_arg in typ.args:
|
||||
@@ -69,19 +74,9 @@ def convert_any_to_type(typ: Type, referred_to_type: Type) -> Type:
|
||||
return typ
|
||||
|
||||
|
||||
def _extract_referred_to_type(ctx: FunctionContext) -> Optional[Type]:
|
||||
try:
|
||||
referred_to_type = get_valid_to_value_or_none(ctx)
|
||||
except helpers.InvalidModelString as exc:
|
||||
ctx.api.fail(f'Invalid value for a to= parameter: {exc.model_string!r}', ctx.context)
|
||||
return None
|
||||
|
||||
return referred_to_type
|
||||
|
||||
|
||||
def fill_descriptor_types_for_related_field(ctx: FunctionContext) -> Type:
|
||||
default_return_type = set_descriptor_types_for_field(ctx)
|
||||
referred_to_type = _extract_referred_to_type(ctx)
|
||||
referred_to_type = extract_referred_to_type(ctx)
|
||||
if referred_to_type is None:
|
||||
return default_return_type
|
||||
|
||||
@@ -106,10 +101,6 @@ def get_private_descriptor_type(type_info: TypeInfo, private_field_name: str, is
|
||||
def set_descriptor_types_for_field(ctx: FunctionContext) -> Instance:
|
||||
default_return_type = cast(Instance, ctx.default_return_type)
|
||||
is_nullable = helpers.parse_bool(helpers.get_argument_by_name(ctx, 'null'))
|
||||
if not is_nullable and default_return_type.type.has_base(helpers.CHAR_FIELD_FULLNAME):
|
||||
# blank=True for CharField can be interpreted as null=True
|
||||
is_nullable = helpers.parse_bool(helpers.get_argument_by_name(ctx, 'blank'))
|
||||
|
||||
set_type = get_private_descriptor_type(default_return_type.type, '_pyi_private_set_type',
|
||||
is_nullable=is_nullable)
|
||||
get_type = get_private_descriptor_type(default_return_type.type, '_pyi_private_get_type',
|
||||
@@ -161,7 +152,7 @@ def record_field_properties_into_outer_model_class(ctx: FunctionContext) -> None
|
||||
return
|
||||
|
||||
field_name = None
|
||||
for name_expr, stmt in iter_over_assignments(outer_model.defn):
|
||||
for name_expr, stmt in helpers.iter_over_assignments(outer_model.defn):
|
||||
if stmt == ctx.context and isinstance(name_expr, NameExpr):
|
||||
field_name = name_expr.name
|
||||
break
|
||||
|
||||
10
mypy_django_plugin/transformers/forms.py
Normal file
10
mypy_django_plugin/transformers/forms.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from mypy.plugin import ClassDefContext
|
||||
|
||||
from mypy_django_plugin import helpers
|
||||
|
||||
|
||||
def make_meta_nested_class_inherit_from_any(ctx: ClassDefContext) -> None:
|
||||
meta_node = helpers.get_nested_meta_node_for_current_class(ctx.cls.info)
|
||||
if meta_node is None:
|
||||
return None
|
||||
meta_node.fallback_to_any = True
|
||||
@@ -4,8 +4,8 @@ from mypy.checker import TypeChecker
|
||||
from mypy.nodes import TypeInfo, Var
|
||||
from mypy.plugin import FunctionContext, MethodContext
|
||||
from mypy.types import AnyType, Instance, Type, TypeOfAny
|
||||
|
||||
from mypy_django_plugin import helpers
|
||||
from mypy_django_plugin.helpers import extract_field_setter_type, extract_explicit_set_type_of_model_primary_key, get_fields_metadata
|
||||
from mypy_django_plugin.transformers.fields import get_private_descriptor_type
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ def redefine_and_typecheck_model_create(ctx: MethodContext) -> Type:
|
||||
|
||||
|
||||
def extract_choices_type(model: TypeInfo, field_name: str) -> Optional[str]:
|
||||
field_metadata = get_fields_metadata(model).get(field_name, {})
|
||||
field_metadata = helpers.get_fields_metadata(model).get(field_name, {})
|
||||
if 'choices' in field_metadata:
|
||||
return field_metadata['choices']
|
||||
return None
|
||||
@@ -117,7 +117,7 @@ def extract_expected_types(ctx: FunctionContext, model: TypeInfo,
|
||||
api = cast(TypeChecker, ctx.api)
|
||||
|
||||
expected_types: Dict[str, Type] = {}
|
||||
primary_key_type = extract_explicit_set_type_of_model_primary_key(model)
|
||||
primary_key_type = helpers.extract_explicit_set_type_of_model_primary_key(model)
|
||||
if not primary_key_type:
|
||||
# no explicit primary key, set pk to Any and add id
|
||||
primary_key_type = AnyType(TypeOfAny.special_form)
|
||||
@@ -143,7 +143,7 @@ def extract_expected_types(ctx: FunctionContext, model: TypeInfo,
|
||||
expected_types[name + '_id'] = AnyType(TypeOfAny.from_unimported_type)
|
||||
|
||||
elif isinstance(typ, Instance):
|
||||
field_type = extract_field_setter_type(typ)
|
||||
field_type = helpers.extract_field_setter_type(typ)
|
||||
if field_type is None:
|
||||
continue
|
||||
|
||||
@@ -156,8 +156,9 @@ def extract_expected_types(ctx: FunctionContext, model: TypeInfo,
|
||||
if is_nullable:
|
||||
referred_to_model = helpers.make_required(typ.args[1])
|
||||
|
||||
if isinstance(referred_to_model, Instance) and referred_to_model.type.has_base(helpers.MODEL_CLASS_FULLNAME):
|
||||
pk_type = extract_explicit_set_type_of_model_primary_key(referred_to_model.type)
|
||||
if isinstance(referred_to_model, Instance) and referred_to_model.type.has_base(
|
||||
helpers.MODEL_CLASS_FULLNAME):
|
||||
pk_type = helpers.extract_explicit_set_type_of_model_primary_key(referred_to_model.type)
|
||||
if not pk_type:
|
||||
# extract set type of AutoField
|
||||
autofield_info = api.lookup_typeinfo('django.db.models.fields.AutoField')
|
||||
@@ -170,7 +171,7 @@ def extract_expected_types(ctx: FunctionContext, model: TypeInfo,
|
||||
|
||||
expected_types[name + '_id'] = related_primary_key_type
|
||||
|
||||
field_metadata = get_fields_metadata(model).get(name, {})
|
||||
field_metadata = helpers.get_fields_metadata(model).get(name, {})
|
||||
if field_type:
|
||||
# related fields could be None in __init__ (but should be specified before save())
|
||||
if helpers.has_any_of_bases(typ.type, (helpers.FOREIGN_KEY_FULLNAME,
|
||||
@@ -178,7 +179,15 @@ def extract_expected_types(ctx: FunctionContext, model: TypeInfo,
|
||||
field_type = helpers.make_optional(field_type)
|
||||
|
||||
# if primary_key=True and default specified
|
||||
elif field_metadata.get('primary_key', False) and field_metadata.get('default_specified', False):
|
||||
elif field_metadata.get('primary_key', False) and field_metadata.get('default_specified',
|
||||
False):
|
||||
field_type = helpers.make_optional(field_type)
|
||||
|
||||
# if CharField(blank=True,...) and not nullable, then field can be None in __init__
|
||||
elif (
|
||||
helpers.has_any_of_bases(typ.type, (helpers.CHAR_FIELD_FULLNAME,)) and is_init and
|
||||
field_metadata.get('blank', False) and not field_metadata.get('null', False)
|
||||
):
|
||||
field_type = helpers.make_optional(field_type)
|
||||
|
||||
expected_types[name] = field_type
|
||||
|
||||
@@ -4,6 +4,7 @@ from mypy.checker import TypeChecker
|
||||
from mypy.nodes import Expression, StrExpr, TypeInfo
|
||||
from mypy.plugin import MethodContext
|
||||
from mypy.types import Instance, Type, TypeType
|
||||
|
||||
from mypy_django_plugin import helpers
|
||||
|
||||
|
||||
|
||||
@@ -2,14 +2,16 @@ from abc import ABCMeta, abstractmethod
|
||||
from typing import Dict, Iterator, List, Optional, Tuple, cast
|
||||
|
||||
import dataclasses
|
||||
from mypy.nodes import ARG_STAR, ARG_STAR2, Argument, CallExpr, ClassDef, Context, Expression, IndexExpr, \
|
||||
Lvalue, MDEF, MemberExpr, MypyFile, NameExpr, StrExpr, SymbolTableNode, TypeInfo, Var
|
||||
from mypy.nodes import (
|
||||
ARG_STAR, ARG_STAR2, MDEF, Argument, CallExpr, ClassDef, Expression, IndexExpr, Lvalue, MemberExpr, MypyFile,
|
||||
NameExpr, StrExpr, SymbolTableNode, TypeInfo, Var,
|
||||
)
|
||||
from mypy.plugin import ClassDefContext
|
||||
from mypy.plugins.common import add_method
|
||||
from mypy.semanal import SemanticAnalyzerPass2
|
||||
from mypy.types import AnyType, Instance, NoneTyp, TypeOfAny
|
||||
|
||||
from mypy_django_plugin import helpers
|
||||
from mypy_django_plugin.helpers import iter_over_assignments
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
@@ -21,20 +23,12 @@ class ModelClassInitializer(metaclass=ABCMeta):
|
||||
def from_ctx(cls, ctx: ClassDefContext):
|
||||
return cls(api=cast(SemanticAnalyzerPass2, ctx.api), model_classdef=ctx.cls)
|
||||
|
||||
def get_nested_meta_node(self) -> Optional[TypeInfo]:
|
||||
metaclass_sym = self.model_classdef.info.names.get('Meta')
|
||||
if metaclass_sym is not None and isinstance(metaclass_sym.node, TypeInfo):
|
||||
return metaclass_sym.node
|
||||
return None
|
||||
|
||||
def get_meta_attribute(self, name: str) -> Optional[Expression]:
|
||||
meta_node = self.get_nested_meta_node()
|
||||
meta_node = helpers.get_nested_meta_node_for_current_class(self.model_classdef.info)
|
||||
if meta_node is None:
|
||||
return None
|
||||
|
||||
for lvalue, rvalue in iter_over_assignments(meta_node.defn):
|
||||
if isinstance(lvalue, NameExpr) and lvalue.name == name:
|
||||
return rvalue
|
||||
return helpers.get_assigned_value_for_class(meta_node, name)
|
||||
|
||||
def is_abstract_model(self) -> bool:
|
||||
is_abstract_expr = self.get_meta_attribute('abstract')
|
||||
@@ -48,7 +42,7 @@ class ModelClassInitializer(metaclass=ABCMeta):
|
||||
var._fullname = self.model_classdef.info.fullname() + '.' + name
|
||||
var.is_inferred = True
|
||||
var.is_initialized_in_class = True
|
||||
self.model_classdef.info.names[name] = SymbolTableNode(MDEF, var)
|
||||
self.model_classdef.info.names[name] = SymbolTableNode(MDEF, var, plugin_generated=True)
|
||||
|
||||
@abstractmethod
|
||||
def run(self) -> None:
|
||||
@@ -56,7 +50,7 @@ class ModelClassInitializer(metaclass=ABCMeta):
|
||||
|
||||
|
||||
def iter_call_assignments(klass: ClassDef) -> Iterator[Tuple[Lvalue, CallExpr]]:
|
||||
for lvalue, rvalue in iter_over_assignments(klass):
|
||||
for lvalue, rvalue in helpers.iter_over_assignments(klass):
|
||||
if isinstance(rvalue, CallExpr):
|
||||
yield lvalue, rvalue
|
||||
|
||||
@@ -64,7 +58,7 @@ def iter_call_assignments(klass: ClassDef) -> Iterator[Tuple[Lvalue, CallExpr]]:
|
||||
def iter_over_one_to_n_related_fields(klass: ClassDef) -> Iterator[Tuple[NameExpr, CallExpr]]:
|
||||
for lvalue, rvalue in iter_call_assignments(klass):
|
||||
if (isinstance(lvalue, NameExpr)
|
||||
and isinstance(rvalue.callee, MemberExpr)):
|
||||
and isinstance(rvalue.callee, MemberExpr)):
|
||||
if rvalue.callee.fullname in {helpers.FOREIGN_KEY_FULLNAME,
|
||||
helpers.ONETOONE_FIELD_FULLNAME}:
|
||||
yield lvalue, rvalue
|
||||
@@ -80,7 +74,7 @@ class SetIdAttrsForRelatedFields(ModelClassInitializer):
|
||||
|
||||
class InjectAnyAsBaseForNestedMeta(ModelClassInitializer):
|
||||
def run(self) -> None:
|
||||
meta_node = self.get_nested_meta_node()
|
||||
meta_node = helpers.get_nested_meta_node_for_current_class(self.model_classdef.info)
|
||||
if meta_node is None:
|
||||
return None
|
||||
meta_node.fallback_to_any = True
|
||||
@@ -115,8 +109,8 @@ class AddDefaultObjectsManager(ModelClassInitializer):
|
||||
if isinstance(callee_expr, IndexExpr):
|
||||
callee_expr = callee_expr.analyzed.expr
|
||||
if isinstance(callee_expr, (MemberExpr, NameExpr)) \
|
||||
and isinstance(callee_expr.node, TypeInfo) \
|
||||
and callee_expr.node.has_base(helpers.BASE_MANAGER_CLASS_FULLNAME):
|
||||
and isinstance(callee_expr.node, TypeInfo) \
|
||||
and callee_expr.node.has_base(helpers.BASE_MANAGER_CLASS_FULLNAME):
|
||||
managers.append((manager_name, callee_expr.node))
|
||||
return managers
|
||||
|
||||
@@ -155,7 +149,7 @@ class AddIdAttributeIfPrimaryKeyTrueIsNotSet(ModelClassInitializer):
|
||||
|
||||
for _, rvalue in iter_call_assignments(self.model_classdef):
|
||||
if ('primary_key' in rvalue.arg_names
|
||||
and self.api.parse_bool(rvalue.args[rvalue.arg_names.index('primary_key')])):
|
||||
and self.api.parse_bool(rvalue.args[rvalue.arg_names.index('primary_key')])):
|
||||
break
|
||||
else:
|
||||
self.add_new_node_to_model_class('id', self.api.builtin_type('builtins.object'))
|
||||
@@ -173,10 +167,9 @@ class AddRelatedManagers(ModelClassInitializer):
|
||||
all_modules=self.api.modules)
|
||||
except helpers.SelfReference:
|
||||
ref_to_fullname = defn.fullname
|
||||
except helpers.InvalidModelString as exc:
|
||||
self.api.fail(f'Invalid value for a to= parameter: {exc.model_string!r}',
|
||||
Context(line=rvalue.line))
|
||||
return None
|
||||
|
||||
except helpers.SameFileModel as exc:
|
||||
ref_to_fullname = module_name + '.' + exc.model_cls_name
|
||||
|
||||
if self.model_classdef.fullname == ref_to_fullname:
|
||||
related_manager_name = defn.name.lower() + '_set'
|
||||
@@ -211,10 +204,10 @@ def is_related_field(expr: CallExpr, module_file: MypyFile) -> bool:
|
||||
if isinstance(expr.callee, MemberExpr) and isinstance(expr.callee.expr, NameExpr):
|
||||
module = module_file.names.get(expr.callee.expr.name)
|
||||
if module \
|
||||
and module.fullname == 'django.db.models' \
|
||||
and expr.callee.name in {'ForeignKey',
|
||||
'OneToOneField',
|
||||
'ManyToManyField'}:
|
||||
and module.fullname == 'django.db.models' \
|
||||
and expr.callee.name in {'ForeignKey',
|
||||
'OneToOneField',
|
||||
'ManyToManyField'}:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from typing import Iterable, List, Optional, cast
|
||||
|
||||
from mypy.nodes import ClassDef, Context, ImportAll, MypyFile, SymbolNode, SymbolTableNode, TypeInfo, Var
|
||||
from mypy.nodes import (
|
||||
ClassDef, Context, ImportAll, MypyFile, SymbolNode, SymbolTableNode, TypeInfo, Var,
|
||||
)
|
||||
from mypy.plugin import ClassDefContext
|
||||
from mypy.semanal import SemanticAnalyzerPass2
|
||||
from mypy.types import AnyType, Instance, NoneTyp, Type, TypeOfAny, UnionType
|
||||
@@ -56,8 +58,8 @@ def load_settings_from_names(settings_classdef: ClassDef,
|
||||
settings_classdef.info.names[name] = copied
|
||||
else:
|
||||
var = Var(name, AnyType(TypeOfAny.unannotated))
|
||||
var.info = api.named_type('__builtins__.object').type
|
||||
settings_classdef.info.names[name] = SymbolTableNode(sym.kind, var)
|
||||
var.info = api.named_type('__builtins__.object').type # outer class type
|
||||
settings_classdef.info.names[name] = SymbolTableNode(sym.kind, var, plugin_generated=True)
|
||||
|
||||
settings_metadata[name] = module.fullname()
|
||||
|
||||
@@ -67,11 +69,12 @@ def get_import_star_modules(api: SemanticAnalyzerPass2, module: MypyFile) -> Lis
|
||||
for module_import in module.imports:
|
||||
# relative import * are not resolved by mypy
|
||||
if isinstance(module_import, ImportAll) and module_import.relative:
|
||||
absolute_import_path, correct = correct_relative_import(module.fullname(), module_import.relative, module_import.id,
|
||||
is_cur_package_init_file=False)
|
||||
absolute_import_path, correct = correct_relative_import(module.fullname(), module_import.relative,
|
||||
module_import.id, is_cur_package_init_file=False)
|
||||
if not correct:
|
||||
return []
|
||||
for path in [absolute_import_path] + get_import_star_modules(api, module=api.modules.get(absolute_import_path)):
|
||||
for path in [absolute_import_path] + get_import_star_modules(api,
|
||||
module=api.modules.get(absolute_import_path)):
|
||||
if path not in import_star_modules:
|
||||
import_star_modules.append(path)
|
||||
return import_star_modules
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
[pytest]
|
||||
|
||||
testpaths = ./test-data
|
||||
addopts =
|
||||
--tb=native
|
||||
--mypy-ini-file=./test-data/plugins.ini
|
||||
--mypy-no-cache
|
||||
-s
|
||||
-v
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/local/bin/xonsh
|
||||
|
||||
try:
|
||||
pip install wheel
|
||||
pip install wheel twine
|
||||
python setup.py sdist bdist_wheel --universal
|
||||
twine upload dist/*
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ ignore_missing_imports = True
|
||||
check_untyped_defs = True
|
||||
warn_no_return = False
|
||||
show_traceback = True
|
||||
warn_redundant_casts = True
|
||||
allow_redefinition = True
|
||||
incremental = False
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
@@ -32,12 +33,13 @@ IGNORED_ERRORS = {
|
||||
'Cannot assign to a type',
|
||||
re.compile(r'Cannot assign to class variable "[a-z_]+" via instance'),
|
||||
# forms <-> models plugin support
|
||||
'"Model" has no attribute',
|
||||
# '"Model" has no attribute',
|
||||
re.compile(r'Cannot determine type of \'(objects|stuff)\''),
|
||||
# settings
|
||||
re.compile(r'Module has no attribute "[A-Z_]+"'),
|
||||
# attributes assigned to test functions
|
||||
re.compile(r'"Callable\[(\[(Any(, )?)*((, )?VarArg\(Any\))?((, )?KwArg\(Any\))?\]|\.\.\.), Any\]" has no attribute'),
|
||||
re.compile(
|
||||
r'"Callable\[(\[(Any(, )?)*((, )?VarArg\(Any\))?((, )?KwArg\(Any\))?\]|\.\.\.), Any\]" has no attribute'),
|
||||
# assign empty tuple
|
||||
re.compile(r'Incompatible types in assignment \(expression has type "Tuple\[\]", '
|
||||
r'variable has type "Tuple\[[A-Za-z, ]+\]"'),
|
||||
@@ -54,7 +56,10 @@ IGNORED_ERRORS = {
|
||||
'ValuesIterable',
|
||||
'Value of type "Optional[Dict[str, Any]]" is not indexable',
|
||||
'Argument 1 to "len" has incompatible type "Optional[List[_Record]]"; expected "Sized"',
|
||||
'Argument 1 to "loads" has incompatible type "Union[bytes, str, None]"; expected "Union[str, bytes, bytearray]"'
|
||||
'Argument 1 to "loads" has incompatible type "Union[bytes, str, None]"; '
|
||||
+ 'expected "Union[str, bytes, bytearray]"',
|
||||
'Incompatible types in assignment (expression has type "None", variable has type Module)',
|
||||
'note:'
|
||||
],
|
||||
'admin_changelist': [
|
||||
'Incompatible types in assignment (expression has type "FilteredChildAdmin", variable has type "ChildAdmin")'
|
||||
@@ -64,8 +69,9 @@ IGNORED_ERRORS = {
|
||||
],
|
||||
'admin_widgets': [
|
||||
'Incompatible types in assignment (expression has type "RelatedFieldWidgetWrapper", '
|
||||
'variable has type "AdminRadioSelect")',
|
||||
'Incompatible types in assignment (expression has type "Union[Widget, Any]", variable has type "AutocompleteSelect")'
|
||||
+ 'variable has type "AdminRadioSelect")',
|
||||
'Incompatible types in assignment (expression has type "Union[Widget, Any]", '
|
||||
+ 'variable has type "AutocompleteSelect")'
|
||||
],
|
||||
'admin_utils': [
|
||||
re.compile(r'Argument [0-9] to "lookup_field" has incompatible type'),
|
||||
@@ -90,11 +96,13 @@ IGNORED_ERRORS = {
|
||||
'Incompatible types in assignment (expression has type "FlatValuesListIterable", '
|
||||
+ 'variable has type "ValuesListIterable")',
|
||||
'Incompatible type for "contact" of "Book" (got "Optional[Author]", expected "Union[Author, Combinable]")',
|
||||
'Incompatible type for "publisher" of "Book" (got "Optional[Publisher]", expected "Union[Publisher, Combinable]")'
|
||||
'Incompatible type for "publisher" of "Book" (got "Optional[Publisher]", '
|
||||
+ 'expected "Union[Publisher, Combinable]")'
|
||||
],
|
||||
'aggregation_regress': [
|
||||
'Incompatible types in assignment (expression has type "List[str]", variable has type "QuerySet[Author]")',
|
||||
'Incompatible types in assignment (expression has type "FlatValuesListIterable", variable has type "QuerySet[Any]")',
|
||||
'Incompatible types in assignment (expression has type "FlatValuesListIterable", '
|
||||
+ 'variable has type "QuerySet[Any]")',
|
||||
'Too few arguments for "count" of "Sequence"'
|
||||
],
|
||||
'apps': [
|
||||
@@ -166,6 +174,29 @@ IGNORED_ERRORS = {
|
||||
'fixtures': [
|
||||
'Incompatible types in assignment (expression has type "int", target has type "Iterable[str]")'
|
||||
],
|
||||
'forms_tests': [
|
||||
'List item 0 has incompatible type "Jinja2"; expected "DjangoTemplates"',
|
||||
'Not enough arguments for format string',
|
||||
'Argument after ** must be a mapping, not "object"',
|
||||
'"media" undefined in superclass',
|
||||
'expression has type "None", base class "TestFormParent"',
|
||||
'variable has type "SongForm"',
|
||||
'"full_clean" of "BaseForm" does not return a value',
|
||||
'No overload variant of "zip" matches argument types "Tuple[str, str, str]", "object"',
|
||||
'Incompatible types in assignment (expression has type "GetDateShowHiddenInitial", '
|
||||
+ 'variable has type "GetDate")',
|
||||
re.compile(r'Incompatible types in assignment \(expression has type "[a-zA-Z]+Field", '
|
||||
r'base class "BaseForm" defined the type as "Dict\[str, Any\]"\)'),
|
||||
'List or tuple expected as variable arguments',
|
||||
'Argument 1 to "__init__" of "MultiWidget" has incompatible type "List[object]"; '
|
||||
+ 'expected "Sequence[Union[Widget, Type[Widget]]]"',
|
||||
'Argument 1 to "issubclass" has incompatible type "ModelFormMetaclass"; expected "type"',
|
||||
'Incompatible types in assignment (expression has type "List[str]", target has type "str")',
|
||||
'Incompatible types in assignment (expression has type "TestForm", variable has type "Person")',
|
||||
'Incompatible types in assignment (expression has type "Type[Textarea]", '
|
||||
+ 'base class "Field" defined the type as "Widget")',
|
||||
'Incompatible types in assignment (expression has type "SimpleUploadedFile", variable has type "BinaryIO")',
|
||||
],
|
||||
'get_object_or_404': [
|
||||
'Argument 1 to "get_object_or_404" has incompatible type "str"; '
|
||||
+ 'expected "Union[Type[<nothing>], Manager[<nothing>], QuerySet[<nothing>]]"',
|
||||
@@ -190,23 +221,37 @@ IGNORED_ERRORS = {
|
||||
'logging_tests': [
|
||||
re.compile('"(setUpClass|tearDownClass)" undefined in superclass')
|
||||
],
|
||||
'lookup': [
|
||||
'Unexpected keyword argument "headline__startswith" for "in_bulk" of "QuerySet"',
|
||||
],
|
||||
'many_to_one': [
|
||||
'Incompatible type for "parent" of "Child" (got "None", expected "Union[Parent, Combinable]")'
|
||||
],
|
||||
'model_inheritance_regress': [
|
||||
'Incompatible types in assignment (expression has type "List[Supplier]", variable has type "QuerySet[Supplier]")'
|
||||
'Incompatible types in assignment (expression has type "List[Supplier]", '
|
||||
+ 'variable has type "QuerySet[Supplier]")'
|
||||
],
|
||||
'model_meta': [
|
||||
'"object" has no attribute "items"',
|
||||
'"Field" has no attribute "many_to_many"'
|
||||
],
|
||||
'model_forms': [
|
||||
'Argument "instance" to "InvalidModelForm" has incompatible type "Type[Category]"; expected "Optional[Model]"',
|
||||
'Invalid type "NewForm"'
|
||||
],
|
||||
'model_fields': [
|
||||
'Incompatible types in assignment (expression has type "Type[Person]", variable has type',
|
||||
'Unexpected keyword argument "name" for "Person"',
|
||||
'Cannot assign multiple types to name "PersonTwoImages" without an explicit "Type[...]" annotation',
|
||||
'Incompatible types in assignment (expression has type "Type[Person]", '
|
||||
+ 'base class "ImageFieldTestMixin" defined the type as "Type[PersonWithHeightAndWidth]")',
|
||||
'note: "Person" defined here'
|
||||
],
|
||||
'model_formsets': [
|
||||
'Incompatible types in string interpolation (expression has type "object", '
|
||||
+ 'placeholder has type "Union[int, float]")'
|
||||
],
|
||||
'model_formsets_regress': [
|
||||
'Incompatible types in assignment (expression has type "Model", variable has type "User")'
|
||||
],
|
||||
'model_regress': [
|
||||
'Too many arguments for "Worker"',
|
||||
@@ -249,9 +294,11 @@ IGNORED_ERRORS = {
|
||||
'Incompatible types in assignment (expression has type "Type[Field[Any, Any]]',
|
||||
'DummyArrayField',
|
||||
'DummyJSONField',
|
||||
'Argument "encoder" to "JSONField" has incompatible type "DjangoJSONEncoder"; expected "Optional[Type[JSONEncoder]]"',
|
||||
'Argument "encoder" to "JSONField" has incompatible type "DjangoJSONEncoder"; '
|
||||
+ 'expected "Optional[Type[JSONEncoder]]"',
|
||||
'for model "CITestModel"',
|
||||
'Incompatible type for "field" of "IntegerArrayModel" (got "None", expected "Union[Sequence[int], Combinable]")'
|
||||
'Incompatible type for "field" of "IntegerArrayModel" (got "None", '
|
||||
+ 'expected "Union[Sequence[int], Combinable]")'
|
||||
],
|
||||
'properties': [
|
||||
re.compile('Unexpected attribute "(full_name|full_name_2)" for model "Person"')
|
||||
@@ -286,7 +333,8 @@ IGNORED_ERRORS = {
|
||||
],
|
||||
'schema': [
|
||||
'Incompatible type for "info" of "Note" (got "None", expected "Union[str, Combinable]")',
|
||||
'Incompatible type for "detail_info" of "NoteRename" (got "None", expected "Union[str, Combinable]")'
|
||||
'Incompatible type for "detail_info" of "NoteRename" (got "None", expected "Union[str, Combinable]")',
|
||||
'Incompatible type for "year" of "UniqueTest" (got "None", expected "Union[float, int, str, Combinable]")'
|
||||
],
|
||||
'settings_tests': [
|
||||
'Argument 1 to "Settings" has incompatible type "Optional[str]"; expected "str"'
|
||||
@@ -295,11 +343,14 @@ IGNORED_ERRORS = {
|
||||
'Incompatible types in assignment (expression has type "Thread", variable has type "Callable[[], Any]")'
|
||||
],
|
||||
'test_client': [
|
||||
'Incompatible types in assignment (expression has type "StreamingHttpResponse", variable has type "HttpResponse")',
|
||||
'Incompatible types in assignment (expression has type "HttpResponse", variable has type "StreamingHttpResponse")'
|
||||
'Incompatible types in assignment (expression has type "StreamingHttpResponse", '
|
||||
+ 'variable has type "HttpResponse")',
|
||||
'Incompatible types in assignment (expression has type "HttpResponse", '
|
||||
+ 'variable has type "StreamingHttpResponse")'
|
||||
],
|
||||
'test_client_regress': [
|
||||
'Incompatible types in assignment (expression has type "Dict[<nothing>, <nothing>]", variable has type "SessionBase")',
|
||||
'Incompatible types in assignment (expression has type "Dict[<nothing>, <nothing>]", '
|
||||
+ 'variable has type "SessionBase")',
|
||||
'Unsupported left operand type for + ("None")',
|
||||
'Both left and right operands are unions'
|
||||
],
|
||||
@@ -309,7 +360,8 @@ IGNORED_ERRORS = {
|
||||
'test_runner': [
|
||||
'Value of type "TestSuite" is not indexable',
|
||||
'"TestSuite" has no attribute "_tests"',
|
||||
'Argument "result" to "run" of "TestCase" has incompatible type "RemoteTestResult"; expected "Optional[TestResult]"',
|
||||
'Argument "result" to "run" of "TestCase" has incompatible type "RemoteTestResult"; '
|
||||
+ 'expected "Optional[TestResult]"',
|
||||
'Item "TestSuite" of "Union[TestCase, TestSuite]" has no attribute "id"',
|
||||
'MockTestRunner',
|
||||
'Incompatible types in assignment (expression has type "Tuple[Union[TestCase, TestSuite], ...]", '
|
||||
@@ -329,7 +381,6 @@ IGNORED_ERRORS = {
|
||||
'template_backends': [
|
||||
'Incompatible import of "Jinja2" (imported name has type "Type[Jinja2]", local name has type "object")',
|
||||
'TemplateStringsTests',
|
||||
'Incompatible types in assignment (expression has type "None", variable has type Module)'
|
||||
],
|
||||
'urlpatterns': [
|
||||
'"object" has no attribute "__iter__"; maybe "__str__" or "__dir__"? (not iterable)',
|
||||
@@ -348,7 +399,7 @@ IGNORED_ERRORS = {
|
||||
],
|
||||
'sessions_tests': [
|
||||
'base class "SessionTestsMixin" defined the type as "None")',
|
||||
'Incompatible types in assignment (expression has type "None", variable has type "int")'
|
||||
'Incompatible types in assignment (expression has type "None", variable has type "int")',
|
||||
],
|
||||
'select_related_onetoone': [
|
||||
'"None" has no attribute'
|
||||
@@ -439,7 +490,7 @@ TESTS_DIRS = [
|
||||
'flatpages_tests',
|
||||
'force_insert_update',
|
||||
'foreign_object',
|
||||
# TODO: 'forms_tests',
|
||||
'forms_tests',
|
||||
'from_db_value',
|
||||
'generic_inline_admin',
|
||||
'generic_relations',
|
||||
@@ -593,7 +644,8 @@ def cd(path):
|
||||
|
||||
|
||||
def is_ignored(line: str, test_folder_name: str) -> bool:
|
||||
for pattern in IGNORED_ERRORS['__common__'] + IGNORED_ERRORS.get(test_folder_name, []):
|
||||
for pattern in itertools.chain(IGNORED_ERRORS['__common__'],
|
||||
IGNORED_ERRORS.get(test_folder_name, [])):
|
||||
if isinstance(pattern, Pattern):
|
||||
if pattern.search(line):
|
||||
return True
|
||||
@@ -631,6 +683,10 @@ def check_with_mypy(abs_path: Path, config_file_path: Path) -> int:
|
||||
return int(error_happened)
|
||||
|
||||
|
||||
def get_absolute_path_for_test(test_dirname: str):
|
||||
return (PROJECT_DIRECTORY / tests_root / test_dirname).absolute()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
mypy_config_file = (PROJECT_DIRECTORY / 'scripts' / 'mypy.ini').absolute()
|
||||
repo_directory = PROJECT_DIRECTORY / 'django-sources'
|
||||
@@ -645,8 +701,14 @@ if __name__ == '__main__':
|
||||
repo.remotes['origin'].pull(DJANGO_BRANCH)
|
||||
|
||||
repo.git.checkout(DJANGO_COMMIT_SHA)
|
||||
for dirname in TESTS_DIRS:
|
||||
abs_path = (PROJECT_DIRECTORY / tests_root / dirname).absolute()
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
tests_to_run = sys.argv[1:]
|
||||
else:
|
||||
tests_to_run = TESTS_DIRS
|
||||
|
||||
for dirname in tests_to_run:
|
||||
abs_path = get_absolute_path_for_test(dirname)
|
||||
print(f'Checking {abs_path}')
|
||||
|
||||
rc = check_with_mypy(abs_path, mypy_config_file)
|
||||
|
||||
29
setup.cfg
Normal file
29
setup.cfg
Normal file
@@ -0,0 +1,29 @@
|
||||
[isort]
|
||||
skip =
|
||||
django-sources,
|
||||
django-stubs,
|
||||
test-data
|
||||
include_trailing_comma = true
|
||||
multi_line_output = 5
|
||||
wrap_length = 120
|
||||
|
||||
[flake8]
|
||||
exclude =
|
||||
django-sources,
|
||||
django-stubs,
|
||||
test-data
|
||||
max_line_length = 120
|
||||
|
||||
[tool:pytest]
|
||||
testpaths = ./test-data
|
||||
addopts =
|
||||
--tb=native
|
||||
--mypy-ini-file=./test-data/plugins.ini
|
||||
-s
|
||||
-v
|
||||
|
||||
[bdist_wheel]
|
||||
universal = 1
|
||||
|
||||
[metadata]
|
||||
license_file = LICENSE.txt
|
||||
3
setup.py
3
setup.py
@@ -21,7 +21,6 @@ with open('README.md', 'r') as f:
|
||||
readme = f.read()
|
||||
|
||||
dependencies = [
|
||||
'Django',
|
||||
'mypy>=0.670',
|
||||
'typing-extensions'
|
||||
]
|
||||
@@ -31,7 +30,7 @@ if sys.version_info[:2] < (3, 7):
|
||||
|
||||
setup(
|
||||
name="django-stubs",
|
||||
version="0.5.1",
|
||||
version="0.8.2",
|
||||
description='Django mypy stubs',
|
||||
long_description=readme,
|
||||
long_description_content_type='text/markdown',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[mypy]
|
||||
incremental = False
|
||||
incremental = True
|
||||
strict_optional = True
|
||||
plugins =
|
||||
mypy_django_plugin.main
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
[CASE missing_settings_ignored_flag]
|
||||
[env MYPY_DJANGO_CONFIG=${MYPY_CWD}/mypy_django.ini]
|
||||
[disable_cache]
|
||||
from django.conf import settings
|
||||
reveal_type(settings.NO_SUCH_SETTING) # E: Revealed type is 'Any'
|
||||
|
||||
[env MYPY_DJANGO_CONFIG=${MYPY_CWD}/mypy_django.ini]
|
||||
|
||||
[file mypy_django.ini]
|
||||
[[mypy_django_plugin]
|
||||
ignore_missing_settings = True
|
||||
[out]
|
||||
[/CASE]
|
||||
|
||||
[CASE django_settings_via_config_file]
|
||||
[env MYPY_DJANGO_CONFIG=${MYPY_CWD}/mypy_django.ini]
|
||||
[disable_cache]
|
||||
from django.conf import settings
|
||||
reveal_type(settings.MY_SETTING) # E: Revealed type is 'builtins.int'
|
||||
|
||||
[env MYPY_DJANGO_CONFIG=${MYPY_CWD}/mypy_django.ini]
|
||||
[file mypy_django.ini]
|
||||
[[mypy_django_plugin]
|
||||
django_settings = mysettings
|
||||
|
||||
[file mysettings.py]
|
||||
MY_SETTING: int = 1
|
||||
[out]
|
||||
[/CASE]
|
||||
|
||||
[CASE mypy_django_ini_in_current_directory_is_a_default]
|
||||
[disable_cache]
|
||||
from django.conf import settings
|
||||
reveal_type(settings.MY_SETTING) # E: Revealed type is 'builtins.int'
|
||||
|
||||
@@ -32,4 +34,4 @@ django_settings = mysettings
|
||||
|
||||
[file mysettings.py]
|
||||
MY_SETTING: int = 1
|
||||
[out]
|
||||
[/CASE]
|
||||
|
||||
@@ -7,6 +7,7 @@ class User(models.Model):
|
||||
|
||||
user = User()
|
||||
reveal_type(user.array) # E: Revealed type is 'builtins.list*[Any]'
|
||||
[/CASE]
|
||||
|
||||
[CASE array_field_base_field_parsed_into_generic_typevar]
|
||||
from django.db import models
|
||||
@@ -19,6 +20,7 @@ class User(models.Model):
|
||||
user = User()
|
||||
reveal_type(user.members) # E: Revealed type is 'builtins.list*[builtins.int]'
|
||||
reveal_type(user.members_as_text) # E: Revealed type is 'builtins.list*[builtins.str]'
|
||||
[/CASE]
|
||||
|
||||
[CASE test_model_fields_classes_present_as_primitives]
|
||||
from django.db import models
|
||||
@@ -36,6 +38,7 @@ reveal_type(user.small_int) # E: Revealed type is 'builtins.int*'
|
||||
reveal_type(user.name) # E: Revealed type is 'builtins.str*'
|
||||
reveal_type(user.slug) # E: Revealed type is 'builtins.str*'
|
||||
reveal_type(user.text) # E: Revealed type is 'builtins.str*'
|
||||
[/CASE]
|
||||
|
||||
[CASE test_model_field_classes_from_existing_locations]
|
||||
from django.db import models
|
||||
@@ -51,6 +54,7 @@ booking = Booking()
|
||||
reveal_type(booking.id) # E: Revealed type is 'builtins.int*'
|
||||
reveal_type(booking.time_range) # E: Revealed type is 'Any'
|
||||
reveal_type(booking.some_decimal) # E: Revealed type is 'decimal.Decimal*'
|
||||
[/CASE]
|
||||
|
||||
[CASE test_add_id_field_if_no_primary_key_defined]
|
||||
from django.db import models
|
||||
@@ -59,6 +63,7 @@ class User(models.Model):
|
||||
pass
|
||||
|
||||
reveal_type(User().id) # E: Revealed type is 'builtins.int'
|
||||
[/CASE]
|
||||
|
||||
[CASE test_do_not_add_id_if_field_with_primary_key_True_defined]
|
||||
from django.db import models
|
||||
@@ -68,7 +73,7 @@ class User(models.Model):
|
||||
|
||||
reveal_type(User().my_pk) # E: Revealed type is 'builtins.int*'
|
||||
reveal_type(User().id) # E: Revealed type is 'Any'
|
||||
[out]
|
||||
[/CASE]
|
||||
|
||||
[CASE test_meta_nested_class_allows_subclassing_in_multiple_inheritance]
|
||||
from typing import Any
|
||||
@@ -84,7 +89,7 @@ class Mixin2(models.Model):
|
||||
|
||||
class User(Mixin1, Mixin2):
|
||||
pass
|
||||
[out]
|
||||
[/CASE]
|
||||
|
||||
[CASE test_inheritance_from_abstract_model_does_not_fail_if_field_with_id_exists]
|
||||
from django.db import models
|
||||
@@ -93,7 +98,7 @@ class Abstract(models.Model):
|
||||
abstract = True
|
||||
class User(Abstract):
|
||||
id = models.AutoField(primary_key=True)
|
||||
[out]
|
||||
[/CASE]
|
||||
|
||||
[CASE standard_it_from_parent_model_could_be_overridden_with_non_integer_field_in_child_model]
|
||||
from django.db import models
|
||||
@@ -103,11 +108,24 @@ class ParentModel(models.Model):
|
||||
class MyModel(ParentModel):
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
reveal_type(MyModel().id) # E: Revealed type is 'uuid.UUID*'
|
||||
[out]
|
||||
[/CASE]
|
||||
|
||||
[CASE blank_for_charfield_is_the_same_as_null]
|
||||
[CASE blank_and_null_char_field_allows_none]
|
||||
from django.db import models
|
||||
class MyModel(models.Model):
|
||||
text = models.CharField(max_length=30, blank=True)
|
||||
MyModel(text=None)
|
||||
[out]
|
||||
nulltext=models.CharField(max_length=1, blank=True, null=True)
|
||||
MyModel(nulltext="")
|
||||
MyModel(nulltext=None)
|
||||
MyModel().nulltext=None
|
||||
reveal_type(MyModel().nulltext) # E: Revealed type is 'Union[builtins.str, None]'
|
||||
[/CASE]
|
||||
|
||||
[CASE blank_and_not_null_charfield_does_not_allow_none]
|
||||
from django.db import models
|
||||
class MyModel(models.Model):
|
||||
notnulltext=models.CharField(max_length=1, blank=True, null=False)
|
||||
MyModel(notnulltext=None) # Should allow None in constructor
|
||||
MyModel(notnulltext="")
|
||||
MyModel().notnulltext = None # E: Incompatible types in assignment (expression has type "None", variable has type "Union[str, int, Combinable]")
|
||||
reveal_type(MyModel().notnulltext) # E: Revealed type is 'builtins.str*'
|
||||
[/CASE]
|
||||
|
||||
41
test-data/typecheck/forms.test
Normal file
41
test-data/typecheck/forms.test
Normal file
@@ -0,0 +1,41 @@
|
||||
[CASE no_incompatible_meta_nested_class_false_positive]
|
||||
from django.db import models
|
||||
from django import forms
|
||||
|
||||
class Article(models.Model):
|
||||
pass
|
||||
class Category(models.Model):
|
||||
pass
|
||||
class ArticleForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Article
|
||||
fields = '__all__'
|
||||
class CategoryForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Category
|
||||
fields = '__all__'
|
||||
class CompositeForm(ArticleForm, CategoryForm):
|
||||
pass
|
||||
[/CASE]
|
||||
|
||||
[CASE formview_methods_on_forms_return_proper_types]
|
||||
from typing import Any
|
||||
from django import forms
|
||||
from django.views.generic.edit import FormView
|
||||
|
||||
class MyForm(forms.ModelForm):
|
||||
pass
|
||||
class MyForm2(forms.ModelForm):
|
||||
pass
|
||||
|
||||
class MyView(FormView):
|
||||
form_class = MyForm
|
||||
|
||||
def post(self, request, *args: Any, **kwds: Any):
|
||||
form_class = self.get_form_class()
|
||||
reveal_type(form_class) # E: Revealed type is 'Type[main.MyForm]'
|
||||
reveal_type(self.get_form(None)) # E: Revealed type is 'main.MyForm'
|
||||
reveal_type(self.get_form()) # E: Revealed type is 'main.MyForm'
|
||||
reveal_type(self.get_form(form_class)) # E: Revealed type is 'main.MyForm'
|
||||
reveal_type(self.get_form(MyForm2)) # E: Revealed type is 'main.MyForm2'
|
||||
[/CASE]
|
||||
@@ -6,7 +6,7 @@ class User(models.Model):
|
||||
age = models.IntegerField()
|
||||
|
||||
User.objects.create(name='Max', age=10)
|
||||
User.objects.create(age='hello') # E: Incompatible type for "age" of "User" (got "str", expected "Union[int, Combinable, Literal['']]")
|
||||
User.objects.create(age=[]) # E: Incompatible type for "age" of "User" (got "List[Any]", expected "Union[float, int, str, Combinable]")
|
||||
[out]
|
||||
|
||||
[CASE model_recognises_parent_attributes]
|
||||
@@ -59,6 +59,6 @@ MyModel.objects.create(id=None)
|
||||
|
||||
class MyModel2(models.Model):
|
||||
id = models.IntegerField(primary_key=True, default=None)
|
||||
MyModel2(id=None) # E: Incompatible type for "id" of "MyModel2" (got "None", expected "Union[int, Combinable, Literal['']]")
|
||||
MyModel2.objects.create(id=None) # E: Incompatible type for "id" of "MyModel2" (got "None", expected "Union[int, Combinable, Literal['']]")
|
||||
MyModel2(id=None) # E: Incompatible type for "id" of "MyModel2" (got "None", expected "Union[float, int, str, Combinable]")
|
||||
MyModel2.objects.create(id=None) # E: Incompatible type for "id" of "MyModel2" (got "None", expected "Union[float, int, str, Combinable]")
|
||||
[out]
|
||||
@@ -14,9 +14,9 @@ from django.db import models
|
||||
class MyUser(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
age = models.IntegerField()
|
||||
user = MyUser(name='hello', age='world')
|
||||
user = MyUser(name='hello', age=[])
|
||||
[out]
|
||||
main:6: error: Incompatible type for "age" of "MyUser" (got "str", expected "Union[int, Combinable, Literal['']]")
|
||||
main:6: error: Incompatible type for "age" of "MyUser" (got "List[Any]", expected "Union[float, int, str, Combinable]")
|
||||
|
||||
[CASE arguments_to_init_combined_from_base_classes]
|
||||
from django.db import models
|
||||
@@ -63,7 +63,7 @@ from django.db import models
|
||||
|
||||
class MyUser1(models.Model):
|
||||
mypk = models.IntegerField(primary_key=True)
|
||||
user = MyUser1(pk='hello') # E: Incompatible type for "pk" of "MyUser1" (got "str", expected "Union[int, Combinable, Literal['']]")
|
||||
user = MyUser1(pk=[]) # E: Incompatible type for "pk" of "MyUser1" (got "List[Any]", expected "Union[float, int, str, Combinable]")
|
||||
[out]
|
||||
|
||||
[CASE can_set_foreign_key_by_its_primary_key]
|
||||
@@ -115,7 +115,7 @@ MyModel(1)
|
||||
class MyModel2(models.Model):
|
||||
name = models.IntegerField()
|
||||
MyModel2(1, 12)
|
||||
MyModel2(1, 'Maxim') # E: Incompatible type for "name" of "MyModel2" (got "str", expected "Union[int, Combinable, Literal['']]")
|
||||
MyModel2(1, []) # E: Incompatible type for "name" of "MyModel2" (got "List[Any]", expected "Union[float, int, str, Combinable]")
|
||||
[out]
|
||||
|
||||
[CASE arguments_passed_as_dictionary_unpacking_are_not_supported]
|
||||
|
||||
10
test-data/typecheck/queryset.test
Normal file
10
test-data/typecheck/queryset.test
Normal file
@@ -0,0 +1,10 @@
|
||||
[CASE test_queryset]
|
||||
from django.db import models
|
||||
|
||||
class Blog(models.Model):
|
||||
slug = models.CharField(max_length=100)
|
||||
reveal_type(Blog.objects.in_bulk([1])) # E: Revealed type is 'builtins.dict[Any, main.Blog*]'
|
||||
reveal_type(Blog.objects.in_bulk()) # E: Revealed type is 'builtins.dict[Any, main.Blog*]'
|
||||
reveal_type(Blog.objects.in_bulk(['beatles_blog'], field_name='slug')) # E: Revealed type is 'builtins.dict[Any, main.Blog*]'
|
||||
|
||||
[out]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user