mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-08 21:14:49 +08:00
split error suppression for tests typechecking, fix ci, bunch of fixes
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
from django.contrib.admin.decorators import register as register
|
from .decorators import register as register
|
||||||
from django.contrib.admin.filters import (
|
from .filters import (
|
||||||
AllValuesFieldListFilter as AllValuesFieldListFilter,
|
AllValuesFieldListFilter as AllValuesFieldListFilter,
|
||||||
BooleanFieldListFilter as BooleanFieldListFilter,
|
BooleanFieldListFilter as BooleanFieldListFilter,
|
||||||
ChoicesFieldListFilter as ChoicesFieldListFilter,
|
ChoicesFieldListFilter as ChoicesFieldListFilter,
|
||||||
@@ -10,14 +10,15 @@ from django.contrib.admin.filters import (
|
|||||||
RelatedOnlyFieldListFilter as RelatedOnlyFieldListFilter,
|
RelatedOnlyFieldListFilter as RelatedOnlyFieldListFilter,
|
||||||
SimpleListFilter as SimpleListFilter,
|
SimpleListFilter as SimpleListFilter,
|
||||||
)
|
)
|
||||||
from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME as ACTION_CHECKBOX_NAME
|
from .helpers import ACTION_CHECKBOX_NAME as ACTION_CHECKBOX_NAME
|
||||||
from django.contrib.admin.options import (
|
from .options import (
|
||||||
HORIZONTAL as HORIZONTAL,
|
HORIZONTAL as HORIZONTAL,
|
||||||
VERTICAL as VERTICAL,
|
VERTICAL as VERTICAL,
|
||||||
ModelAdmin as ModelAdmin,
|
ModelAdmin as ModelAdmin,
|
||||||
StackedInline as StackedInline,
|
StackedInline as StackedInline,
|
||||||
TabularInline as TabularInline,
|
TabularInline as TabularInline,
|
||||||
)
|
)
|
||||||
from django.contrib.admin.sites import AdminSite as AdminSite, site as site
|
from .sites import AdminSite as AdminSite, site as site
|
||||||
|
from . import checks as checks
|
||||||
|
|
||||||
def autodiscover() -> None: ...
|
def autodiscover() -> None: ...
|
||||||
|
|||||||
@@ -11,11 +11,8 @@ def check_dependencies(**kwargs: Any) -> List[_CheckError]: ...
|
|||||||
class BaseModelAdminChecks:
|
class BaseModelAdminChecks:
|
||||||
def check(self, admin_obj: BaseModelAdmin, **kwargs: Any) -> List[_CheckError]: ...
|
def check(self, admin_obj: BaseModelAdmin, **kwargs: Any) -> List[_CheckError]: ...
|
||||||
|
|
||||||
class ModelAdminChecks(BaseModelAdminChecks):
|
class ModelAdminChecks(BaseModelAdminChecks): ...
|
||||||
def check(self, admin_obj: ModelAdmin, **kwargs: Any) -> List[_CheckError]: ...
|
class InlineModelAdminChecks(BaseModelAdminChecks): ...
|
||||||
|
|
||||||
class InlineModelAdminChecks(BaseModelAdminChecks):
|
|
||||||
def check(self, inline_obj: InlineModelAdmin, **kwargs: Any) -> List[_CheckError]: ...
|
|
||||||
|
|
||||||
def must_be(type: Any, option: Any, obj: Any, id: Any): ...
|
def must_be(type: Any, option: Any, obj: Any, id: Any): ...
|
||||||
def must_inherit_from(parent: Any, option: Any, obj: Any, id: Any): ...
|
def must_inherit_from(parent: Any, option: Any, obj: Any, id: Any): ...
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from django.urls.resolvers import URLPattern
|
|||||||
from django.utils.safestring import SafeText
|
from django.utils.safestring import SafeText
|
||||||
|
|
||||||
from django.db.models.fields import Field
|
from django.db.models.fields import Field
|
||||||
|
from django.template.response import TemplateResponse
|
||||||
|
|
||||||
IS_POPUP_VAR: str
|
IS_POPUP_VAR: str
|
||||||
TO_FIELD_VAR: str
|
TO_FIELD_VAR: str
|
||||||
@@ -229,7 +230,7 @@ class ModelAdmin(BaseModelAdmin):
|
|||||||
) -> HttpResponse: ...
|
) -> HttpResponse: ...
|
||||||
def changelist_view(
|
def changelist_view(
|
||||||
self, request: WSGIRequest, extra_context: Optional[Dict[str, str]] = ...
|
self, request: WSGIRequest, extra_context: Optional[Dict[str, str]] = ...
|
||||||
) -> HttpResponseBase: ...
|
) -> TemplateResponse: ...
|
||||||
def get_deleted_objects(
|
def get_deleted_objects(
|
||||||
self, objs: QuerySet, request: WSGIRequest
|
self, objs: QuerySet, request: WSGIRequest
|
||||||
) -> Tuple[List[Any], Dict[Any, Any], Set[Any], List[Any]]: ...
|
) -> Tuple[List[Any], Dict[Any, Any], Set[Any], List[Any]]: ...
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ from datetime import datetime
|
|||||||
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
|
from django.forms.models import ModelChoiceIterator
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.admin.sites import AdminSite
|
from django.contrib.admin.sites import AdminSite
|
||||||
from django.db.models.fields.reverse_related import ForeignObjectRel
|
from django.db.models.fields.reverse_related import ForeignObjectRel, ManyToOneRel, ManyToManyRel
|
||||||
from django.db.models.query_utils import Q
|
from django.db.models.query_utils import Q
|
||||||
from django.forms.fields import Field
|
from django.forms.fields import Field
|
||||||
from django.forms.widgets import ChoiceWidget, Media, Widget
|
from django.forms.widgets import ChoiceWidget, Media, Widget, DateTimeBaseInput
|
||||||
from django.http.request import QueryDict
|
from django.http.request import QueryDict
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
|
|
||||||
@@ -92,7 +94,7 @@ def url_params_from_lookup_dict(
|
|||||||
class ForeignKeyRawIdWidget(forms.TextInput):
|
class ForeignKeyRawIdWidget(forms.TextInput):
|
||||||
attrs: Dict[Any, Any]
|
attrs: Dict[Any, Any]
|
||||||
template_name: str = ...
|
template_name: str = ...
|
||||||
rel: django.db.models.fields.reverse_related.ManyToOneRel = ...
|
rel: ManyToOneRel = ...
|
||||||
admin_site: AdminSite = ...
|
admin_site: AdminSite = ...
|
||||||
db: None = ...
|
db: None = ...
|
||||||
def __init__(self, rel: ForeignObjectRel, admin_site: AdminSite, attrs: None = ..., using: None = ...) -> None: ...
|
def __init__(self, rel: ForeignObjectRel, admin_site: AdminSite, attrs: None = ..., using: None = ...) -> None: ...
|
||||||
@@ -107,7 +109,7 @@ class ManyToManyRawIdWidget(ForeignKeyRawIdWidget):
|
|||||||
admin_site: AdminSite
|
admin_site: AdminSite
|
||||||
attrs: Dict[Any, Any]
|
attrs: Dict[Any, Any]
|
||||||
db: None
|
db: None
|
||||||
rel: django.db.models.fields.reverse_related.ManyToManyRel
|
rel: ManyToManyRel
|
||||||
template_name: str = ...
|
template_name: str = ...
|
||||||
def get_context(
|
def get_context(
|
||||||
self, name: str, value: Optional[List[int]], attrs: Optional[Dict[str, str]]
|
self, name: str, value: Optional[List[int]], attrs: Optional[Dict[str, str]]
|
||||||
@@ -122,8 +124,8 @@ class RelatedFieldWidgetWrapper(forms.Widget):
|
|||||||
needs_multipart_form: bool = ...
|
needs_multipart_form: bool = ...
|
||||||
attrs: Dict[Any, Any] = ...
|
attrs: Dict[Any, Any] = ...
|
||||||
choices: ModelChoiceIterator = ...
|
choices: ModelChoiceIterator = ...
|
||||||
widget: django.contrib.admin.widgets.AutocompleteSelect = ...
|
widget: AutocompleteSelect = ...
|
||||||
rel: django.db.models.fields.reverse_related.ManyToOneRel = ...
|
rel: ManyToOneRel = ...
|
||||||
can_add_related: bool = ...
|
can_add_related: bool = ...
|
||||||
can_change_related: bool = ...
|
can_change_related: bool = ...
|
||||||
can_delete_related: bool = ...
|
can_delete_related: bool = ...
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ class SupportsLen(Protocol):
|
|||||||
class SupportsCount(Protocol):
|
class SupportsCount(Protocol):
|
||||||
def count(self) -> int: ...
|
def count(self) -> int: ...
|
||||||
|
|
||||||
|
class SupportsOrdered(Protocol):
|
||||||
|
ordered: bool = ...
|
||||||
|
|
||||||
class Paginator:
|
class Paginator:
|
||||||
object_list: QuerySet = ...
|
object_list: QuerySet = ...
|
||||||
per_page: int = ...
|
per_page: int = ...
|
||||||
@@ -21,7 +24,7 @@ class Paginator:
|
|||||||
allow_empty_first_page: bool = ...
|
allow_empty_first_page: bool = ...
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
object_list: Union[SupportsLen, SupportsCount],
|
object_list: Union[SupportsLen, SupportsCount, SupportsOrdered],
|
||||||
per_page: Union[int, str],
|
per_page: Union[int, str],
|
||||||
orphans: int = ...,
|
orphans: int = ...,
|
||||||
allow_empty_first_page: bool = ...,
|
allow_empty_first_page: bool = ...,
|
||||||
|
|||||||
6
django-stubs/core/signals.pyi
Normal file
6
django-stubs/core/signals.pyi
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.dispatch import Signal
|
||||||
|
|
||||||
|
request_started: Signal = ...
|
||||||
|
request_finished: Signal = ...
|
||||||
|
got_request_exception: Signal = ...
|
||||||
|
setting_changed: Signal = ...
|
||||||
@@ -47,6 +47,7 @@ from .fields.related import (
|
|||||||
ForeignObject as ForeignObject,
|
ForeignObject as ForeignObject,
|
||||||
)
|
)
|
||||||
from .fields.files import ImageField as ImageField, FileField as FileField
|
from .fields.files import ImageField as ImageField, FileField as FileField
|
||||||
|
from .fields.proxy import OrderWrt as OrderWrt
|
||||||
|
|
||||||
from .deletion import (
|
from .deletion import (
|
||||||
CASCADE as CASCADE,
|
CASCADE as CASCADE,
|
||||||
@@ -54,6 +55,7 @@ from .deletion import (
|
|||||||
SET_NULL as SET_NULL,
|
SET_NULL as SET_NULL,
|
||||||
DO_NOTHING as DO_NOTHING,
|
DO_NOTHING as DO_NOTHING,
|
||||||
PROTECT as PROTECT,
|
PROTECT as PROTECT,
|
||||||
|
SET as SET,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .query import (
|
from .query import (
|
||||||
@@ -97,3 +99,5 @@ from .aggregates import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from .indexes import Index as Index
|
from .indexes import Index as Index
|
||||||
|
|
||||||
|
from . import signals as signals
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
|
|
||||||
def CASCADE(collector, field, sub_objs, using): ...
|
def CASCADE(collector, field, sub_objs, using): ...
|
||||||
@@ -5,5 +7,6 @@ def SET_NULL(collector, field, sub_objs, using): ...
|
|||||||
def SET_DEFAULT(collector, field, sub_objs, using): ...
|
def SET_DEFAULT(collector, field, sub_objs, using): ...
|
||||||
def DO_NOTHING(collector, field, sub_objs, using): ...
|
def DO_NOTHING(collector, field, sub_objs, using): ...
|
||||||
def PROTECT(collector, field, sub_objs, using): ...
|
def PROTECT(collector, field, sub_objs, using): ...
|
||||||
|
def SET(value: Any) -> Callable: ...
|
||||||
|
|
||||||
class ProtectedError(IntegrityError): ...
|
class ProtectedError(IntegrityError): ...
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import Any, Optional
|
from typing import Any
|
||||||
|
|
||||||
from django.db.models import fields
|
from django.db.models import fields
|
||||||
|
|
||||||
|
|||||||
@@ -152,8 +152,10 @@ class Prefetch(object):
|
|||||||
def get_current_queryset(self, level) -> Optional[QuerySet]: ...
|
def get_current_queryset(self, level) -> Optional[QuerySet]: ...
|
||||||
|
|
||||||
def prefetch_related_objects(model_instances: Iterable[_T], *related_lookups: Union[str, Prefetch]) -> None: ...
|
def prefetch_related_objects(model_instances: Iterable[_T], *related_lookups: Union[str, Prefetch]) -> None: ...
|
||||||
def get_prefetcher(instance: _T, through_attr: str, to_attr: str) -> Tuple[Any, Any, bool, bool]: ...
|
def get_prefetcher(instance: Model, through_attr: str, to_attr: str) -> Tuple[Any, Any, bool, bool]: ...
|
||||||
|
|
||||||
|
class ModelIterable(Iterable[_T]):
|
||||||
|
def __iter__(self) -> Iterator[_T]: ...
|
||||||
|
|
||||||
class ModelIterable(Iterable[_T]): ...
|
|
||||||
class InstanceCheckMeta(type): ...
|
class InstanceCheckMeta(type): ...
|
||||||
class EmptyQuerySet(metaclass=InstanceCheckMeta): ...
|
class EmptyQuerySet(metaclass=InstanceCheckMeta): ...
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from django.dispatch import Signal
|
|||||||
class_prepared: Any
|
class_prepared: Any
|
||||||
|
|
||||||
class ModelSignal(Signal):
|
class ModelSignal(Signal):
|
||||||
def connect(
|
def connect( # type: ignore
|
||||||
self,
|
self,
|
||||||
receiver: Callable,
|
receiver: Callable,
|
||||||
sender: Optional[Union[Type[Model], str]] = ...,
|
sender: Optional[Union[Type[Model], str]] = ...,
|
||||||
@@ -15,7 +15,7 @@ class ModelSignal(Signal):
|
|||||||
dispatch_uid: None = ...,
|
dispatch_uid: None = ...,
|
||||||
apps: Optional[Apps] = ...,
|
apps: Optional[Apps] = ...,
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def disconnect(
|
def disconnect( # type: ignore
|
||||||
self,
|
self,
|
||||||
receiver: Callable = ...,
|
receiver: Callable = ...,
|
||||||
sender: Optional[Union[Type[Model], str]] = ...,
|
sender: Optional[Union[Type[Model], str]] = ...,
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ class Signal:
|
|||||||
def __init__(self, providing_args: List[str] = ..., use_caching: bool = ...) -> None: ...
|
def __init__(self, providing_args: List[str] = ..., use_caching: bool = ...) -> None: ...
|
||||||
def connect(
|
def connect(
|
||||||
self,
|
self,
|
||||||
receiver: Any,
|
receiver: Callable,
|
||||||
sender: Optional[Union[Type[Model], AppConfig]] = ...,
|
sender: Optional[Union[Type[Model], AppConfig, str]] = ...,
|
||||||
weak: bool = ...,
|
weak: bool = ...,
|
||||||
dispatch_uid: Optional[str] = ...,
|
dispatch_uid: Optional[str] = ...,
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def disconnect(
|
def disconnect(
|
||||||
self,
|
self,
|
||||||
receiver: Optional[Callable] = ...,
|
receiver: Optional[Callable] = ...,
|
||||||
sender: Optional[Union[Type[Model], AppConfig]] = ...,
|
sender: Optional[Union[Type[Model], AppConfig, str]] = ...,
|
||||||
dispatch_uid: Optional[str] = ...,
|
dispatch_uid: Optional[str] = ...,
|
||||||
) -> bool: ...
|
) -> bool: ...
|
||||||
def has_listeners(self, sender: Any = ...) -> bool: ...
|
def has_listeners(self, sender: Any = ...) -> bool: ...
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ from .widgets import (
|
|||||||
SelectMultiple as SelectMultiple,
|
SelectMultiple as SelectMultiple,
|
||||||
TimeInput as TimeInput,
|
TimeInput as TimeInput,
|
||||||
URLInput as URLInput,
|
URLInput as URLInput,
|
||||||
|
SelectDateWidget as SelectDateWidget,
|
||||||
|
SplitHiddenDateTimeWidget as SplitHiddenDateTimeWidget,
|
||||||
|
SplitDateTimeWidget as SplitDateTimeWidget,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .fields import (
|
from .fields import (
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ class SelectMultiple(Select):
|
|||||||
allow_multiple_selected: bool = ...
|
allow_multiple_selected: bool = ...
|
||||||
|
|
||||||
class RadioSelect(ChoiceWidget):
|
class RadioSelect(ChoiceWidget):
|
||||||
|
can_add_related: bool
|
||||||
option_template_name: str = ...
|
option_template_name: str = ...
|
||||||
|
|
||||||
class CheckboxSelectMultiple(ChoiceWidget):
|
class CheckboxSelectMultiple(ChoiceWidget):
|
||||||
|
|||||||
@@ -12,3 +12,5 @@ from .base import Node as Node, NodeList as NodeList, Origin as Origin, Template
|
|||||||
from .context import Context as Context, RequestContext as RequestContext
|
from .context import Context as Context, RequestContext as RequestContext
|
||||||
|
|
||||||
from .library import Library as Library
|
from .library import Library as Library
|
||||||
|
|
||||||
|
from . import defaultfilters as defaultfilters
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from datetime import date, datetime, timedelta
|
from datetime import _date, datetime, timedelta
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, Union
|
from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, Union
|
||||||
|
|
||||||
@@ -72,14 +72,14 @@ def unordered_list(
|
|||||||
value: Union[Iterator[Any], List[Union[List[Union[List[Union[List[str], str]], str]], str]]], autoescape: bool = ...
|
value: Union[Iterator[Any], List[Union[List[Union[List[Union[List[str], str]], str]], str]]], autoescape: bool = ...
|
||||||
) -> SafeText: ...
|
) -> SafeText: ...
|
||||||
def add(
|
def add(
|
||||||
value: Union[List[int], Tuple[int, int], date, int, str],
|
value: Union[List[int], Tuple[int, int], _date, int, str],
|
||||||
arg: Union[List[int], Tuple[int, int], timedelta, int, str],
|
arg: Union[List[int], Tuple[int, int], timedelta, int, str],
|
||||||
) -> Union[List[int], Tuple[int, int, int, int], date, int, str]: ...
|
) -> Union[List[int], Tuple[int, int, int, int], _date, int, str]: ...
|
||||||
def get_digit(value: Union[int, str], arg: int) -> Union[int, str]: ...
|
def get_digit(value: Union[int, str], arg: int) -> Union[int, str]: ...
|
||||||
def date(value: Optional[Union[datetime, str]], arg: Optional[str] = ...) -> str: ...
|
def date(value: Optional[Union[_date, datetime, str]], arg: Optional[str] = ...) -> str: ...
|
||||||
def time(value: Optional[Union[datetime, str]], arg: Optional[str] = ...) -> str: ...
|
def time(value: Optional[Union[datetime, str]], arg: Optional[str] = ...) -> str: ...
|
||||||
def timesince_filter(value: Optional[date], arg: Optional[date] = ...) -> str: ...
|
def timesince_filter(value: Optional[_date], arg: Optional[_date] = ...) -> str: ...
|
||||||
def timeuntil_filter(value: Optional[date], arg: Optional[date] = ...) -> str: ...
|
def timeuntil_filter(value: Optional[_date], arg: Optional[_date] = ...) -> str: ...
|
||||||
def default(value: Optional[Union[int, str]], arg: Union[int, str]) -> Union[int, str]: ...
|
def default(value: Optional[Union[int, str]], arg: Union[int, str]) -> Union[int, str]: ...
|
||||||
def default_if_none(value: Optional[str], arg: Union[int, str]) -> Union[int, str]: ...
|
def default_if_none(value: Optional[str], arg: Union[int, str]) -> Union[int, str]: ...
|
||||||
def divisibleby(value: int, arg: int) -> bool: ...
|
def divisibleby(value: int, arg: int) -> bool: ...
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
from django.core.signals import setting_changed as setting_changed
|
||||||
|
|
||||||
template_rendered: Any
|
template_rendered: Any
|
||||||
COMPLEX_OVERRIDE_SETTINGS: Any
|
COMPLEX_OVERRIDE_SETTINGS: Any
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import decimal
|
import decimal
|
||||||
import warnings
|
import warnings
|
||||||
|
from io import StringIO
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Type, Union, IO
|
from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Type, Union, IO
|
||||||
@@ -107,13 +108,13 @@ class isolate_apps(TestContextDecorator):
|
|||||||
@contextmanager
|
@contextmanager
|
||||||
def extend_sys_path(*paths: str) -> Iterator[None]: ...
|
def extend_sys_path(*paths: str) -> Iterator[None]: ...
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def captured_output(stream_name) -> Iterator[IO[str]]: ...
|
def captured_output(stream_name) -> Iterator[StringIO]: ...
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def captured_stdin() -> Iterator[IO[str]]: ...
|
def captured_stdin() -> Iterator[StringIO]: ...
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def captured_stdout() -> Iterator[IO[str]]: ...
|
def captured_stdout() -> Iterator[StringIO]: ...
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def captured_stderr() -> Iterator[IO[str]]: ...
|
def captured_stderr() -> Iterator[StringIO]: ...
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def freeze_time(t: float) -> Iterator[None]: ...
|
def freeze_time(t: float) -> Iterator[None]: ...
|
||||||
def tag(*tags: str): ...
|
def tag(*tags: str): ...
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ from git import Repo
|
|||||||
from mypy import build
|
from mypy import build
|
||||||
from mypy.main import process_options
|
from mypy.main import process_options
|
||||||
|
|
||||||
|
PROJECT_DIRECTORY = Path(__file__).parent.parent
|
||||||
|
|
||||||
# Django branch to typecheck against
|
# Django branch to typecheck against
|
||||||
DJANGO_BRANCH = 'stable/2.1.x'
|
DJANGO_BRANCH = 'stable/2.1.x'
|
||||||
|
|
||||||
@@ -17,64 +19,114 @@ DJANGO_COMMIT_SHA = '03219b5f709dcd5b0bfacd963508625557ec1ef0'
|
|||||||
|
|
||||||
# Some errors occur for the test suite itself, and cannot be addressed via django-stubs. They should be ignored
|
# Some errors occur for the test suite itself, and cannot be addressed via django-stubs. They should be ignored
|
||||||
# using this constant.
|
# using this constant.
|
||||||
IGNORED_ERROR_PATTERNS = [
|
MOCK_OBJECTS = ['MockRequest', 'MockCompiler', 'modelz']
|
||||||
'Need type annotation for',
|
IGNORED_ERRORS = {
|
||||||
'already defined on',
|
'__common__': [
|
||||||
'Cannot assign to a',
|
*MOCK_OBJECTS,
|
||||||
'cannot perform relative import',
|
|
||||||
'broken_app',
|
|
||||||
'cache_clear',
|
|
||||||
'call_count',
|
|
||||||
'call_args_list',
|
|
||||||
'call_args',
|
|
||||||
'"password_changed" does not return a value',
|
|
||||||
'"validate_password" does not return a value',
|
|
||||||
'LazySettings',
|
'LazySettings',
|
||||||
'Cannot infer type of lambda',
|
'NullTranslations',
|
||||||
'"refresh_from_db" of "Model"',
|
'Need type annotation for',
|
||||||
'"as_sql" undefined in superclass',
|
|
||||||
'Incompatible types in assignment (expression has type "str", target has type "type")',
|
|
||||||
'Incompatible types in assignment (expression has type "Callable[',
|
|
||||||
'Invalid value for a to= parameter',
|
'Invalid value for a to= parameter',
|
||||||
'Incompatible types in assignment (expression has type "FilteredChildAdmin", variable has type "ChildAdmin")',
|
'already defined (possibly by an import)',
|
||||||
'Incompatible types in assignment (expression has type "RelatedFieldWidgetWrapper", variable has type "AdminRadioSelect")',
|
'Cannot assign to a type',
|
||||||
'has incompatible type "MockRequest"; expected "WSGIRequest"',
|
# forms <-> models plugin support
|
||||||
'"NullTranslations" has no attribute "_catalog"',
|
'"Model" has no attribute',
|
||||||
'Definition of "as_sql" in base class',
|
re.compile(r'Cannot determine type of \'(objects|stuff)\''),
|
||||||
'expression has type "property"',
|
# settings
|
||||||
'"object" has no attribute "__iter__"',
|
re.compile(r'Module has no attribute "[A-Z_]+"'),
|
||||||
'Too few arguments for "dates" of "QuerySet"',
|
# attributes assigned to test functions
|
||||||
'has no attribute "vendor"',
|
|
||||||
'Argument 1 to "get_list_or_404" has incompatible type "List',
|
|
||||||
'error: "AdminRadioSelect" has no attribute "can_add_related"',
|
|
||||||
'MockCompiler',
|
|
||||||
'SessionTestsMixin',
|
|
||||||
'Argument 1 to "Paginator" has incompatible type "ObjectList"',
|
|
||||||
'"Type[Morsel[Any]]" has no attribute "_reserved"',
|
|
||||||
'Argument 1 to "append" of "list"',
|
|
||||||
'Argument 1 to "bytes"',
|
|
||||||
'"full_clean" of "Model" does not return a value',
|
|
||||||
'"object" not callable',
|
|
||||||
'Item "GenericForeignKey" of "Union[GenericForeignKey, Model, None]" has no attribute "read_by"',
|
|
||||||
'Item "Model" of "Union[GenericForeignKey, Model, None]" has no attribute "read_by"',
|
|
||||||
re.compile('Cannot determine type of \'(objects|stuff|specimens|normal_manager)\''),
|
|
||||||
re.compile(r'"Callable\[\[(Any(, )?)+\], Any\]" has no attribute'),
|
re.compile(r'"Callable\[\[(Any(, )?)+\], Any\]" has no attribute'),
|
||||||
re.compile(r'"HttpResponseBase" has no attribute "[A-Za-z_]+"'),
|
# assign empty tuple
|
||||||
re.compile(r'Incompatible types in assignment \(expression has type "Tuple\[\]", '
|
re.compile(r'Incompatible types in assignment \(expression has type "Tuple\[\]", '
|
||||||
r'variable has type "Tuple\[[A-Za-z, ]+\]"'),
|
r'variable has type "Tuple\[[A-Za-z, ]+\]"'),
|
||||||
re.compile(r'"validate" of "[A-Za-z]+" does not return a value'),
|
# assign method to a method
|
||||||
re.compile(r'Module has no attribute "[A-Za-z_]+"'),
|
'Cannot assign to a method',
|
||||||
re.compile(r'"[A-Za-z\[\]]+" has no attribute "getvalue"'),
|
'Cannot infer type of lambda',
|
||||||
# TODO: remove when reassignment will be possible (in 0.670? )
|
re.compile(r'Incompatible types in assignment \(expression has type "Callable\[\[(Any(, )?)+\], Any\]", '
|
||||||
re.compile(r'Incompatible types in assignment \(expression has type "(QuerySet|List)\[[A-Za-z, ]+\]", '
|
r'variable has type "Callable\['),
|
||||||
r'variable has type "(QuerySet|List)\[[A-Za-z, ]+\]"\)'),
|
],
|
||||||
re.compile(r'"(MockRequest|DummyRequest|DummyUser)" has no attribute "[a-zA-Z_]+"'),
|
'admin_changelist': [
|
||||||
# TODO: remove when form <-> model plugin support is added
|
'Incompatible types in assignment (expression has type "FilteredChildAdmin", variable has type "ChildAdmin")'
|
||||||
re.compile(r'"Model" has no attribute "[A-Za-z_]+"'),
|
],
|
||||||
re.compile(r'Argument 1 to "get_object_or_404" has incompatible type "(str|Type\[CustomClass\])"'),
|
'admin_scripts': [
|
||||||
re.compile(r'"None" has no attribute "[a-zA-Z_0-9]+"'),
|
'Incompatible types in assignment (expression has type "Callable['
|
||||||
|
],
|
||||||
|
'admin_widgets': [
|
||||||
|
'Incompatible types in assignment (expression has type "RelatedFieldWidgetWrapper", '
|
||||||
|
'variable has type "AdminRadioSelect")',
|
||||||
|
'Incompatible types in assignment (expression has type "Widget", variable has type "AutocompleteSelect")'
|
||||||
|
],
|
||||||
|
'aggregation': [
|
||||||
|
'Incompatible types in assignment (expression has type "QuerySet[Any]", variable has type "List[Any]")',
|
||||||
|
'"as_sql" undefined in superclass'
|
||||||
|
],
|
||||||
|
'aggregation_regress': [
|
||||||
|
'Incompatible types in assignment (expression has type "List[str]", variable has type "QuerySet[Author]")'
|
||||||
|
],
|
||||||
|
'basic': [
|
||||||
|
'Unexpected keyword argument "unknown_kwarg" for "refresh_from_db" of "Model"',
|
||||||
|
'"refresh_from_db" of "Model" defined here'
|
||||||
|
],
|
||||||
|
'builtin_server': [
|
||||||
|
'has no attribute "getvalue"'
|
||||||
|
],
|
||||||
|
'csrf_tests': [
|
||||||
|
'Incompatible types in assignment (expression has type "property", ' +
|
||||||
|
'base class "HttpRequest" defined the type as "QueryDict")'
|
||||||
|
],
|
||||||
|
'dates': [
|
||||||
|
'Too few arguments for "dates" of "QuerySet"',
|
||||||
|
],
|
||||||
|
'defer': [
|
||||||
|
'Too many arguments for "refresh_from_db" of "Model"'
|
||||||
|
],
|
||||||
|
'db_typecasts': [
|
||||||
|
'"object" has no attribute "__iter__"; maybe "__str__" or "__dir__"? (not iterable)'
|
||||||
|
],
|
||||||
|
'from_db_value': [
|
||||||
|
'has no attribute "vendor"'
|
||||||
|
],
|
||||||
|
'get_object_or_404': [
|
||||||
|
'Argument 1 to "get_object_or_404" has incompatible type "str"; '
|
||||||
|
+ 'expected "Union[Type[Model], Manager[Any], QuerySet[Any]]"',
|
||||||
|
'Argument 1 to "get_object_or_404" has incompatible type "Type[CustomClass]"; '
|
||||||
|
+ 'expected "Union[Type[Model], Manager[Any], QuerySet[Any]]"',
|
||||||
|
'Argument 1 to "get_list_or_404" has incompatible type "List[Type[Article]]"; '
|
||||||
|
+ 'expected "Union[Type[Model], Manager[Any], QuerySet[Any]]"'
|
||||||
|
],
|
||||||
|
'model_inheritance_regress': [
|
||||||
|
'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"'
|
||||||
|
],
|
||||||
|
'migrate_signals': [
|
||||||
|
'Value of type "None" is not indexable',
|
||||||
|
],
|
||||||
|
'queryset_pickle': [
|
||||||
|
'"None" has no attribute "somefield"'
|
||||||
|
],
|
||||||
|
'prefetch_related': [
|
||||||
|
'Incompatible types in assignment (expression has type "List[Room]", variable has type "QuerySet[Room]")',
|
||||||
|
'"None" has no attribute "__iter__"',
|
||||||
|
'has no attribute "read_by"'
|
||||||
|
],
|
||||||
|
'urlpatterns': [
|
||||||
|
'"object" has no attribute "__iter__"; maybe "__str__" or "__dir__"? (not iterable)',
|
||||||
|
'"object" not callable'
|
||||||
|
],
|
||||||
|
'user_commands': [
|
||||||
|
'Incompatible types in assignment (expression has type "Callable[[Any, KwArg(Any)], Any]", variable has type'
|
||||||
|
],
|
||||||
|
'sessions_tests': [
|
||||||
|
'base class "SessionTestsMixin" defined the type as "None")',
|
||||||
|
'has no attribute "_reserved"'
|
||||||
|
],
|
||||||
|
'select_related_onetoone': [
|
||||||
|
'"None" has no attribute'
|
||||||
]
|
]
|
||||||
|
}
|
||||||
# Test folders to typecheck
|
# Test folders to typecheck
|
||||||
TESTS_DIRS = [
|
TESTS_DIRS = [
|
||||||
'absolute_url_overrides',
|
'absolute_url_overrides',
|
||||||
@@ -190,7 +242,7 @@ TESTS_DIRS = [
|
|||||||
# TODO: 'messages_tests',
|
# TODO: 'messages_tests',
|
||||||
# TODO: 'middleware',
|
# TODO: 'middleware',
|
||||||
# TODO: 'middleware_exceptions',
|
# TODO: 'middleware_exceptions',
|
||||||
# SKIPPED (all errors are false positives) 'migrate_signals',
|
'migrate_signals',
|
||||||
'migration_test_data_persistence',
|
'migration_test_data_persistence',
|
||||||
# TODO: 'migrations',
|
# TODO: 'migrations',
|
||||||
'migrations2',
|
'migrations2',
|
||||||
@@ -201,7 +253,7 @@ TESTS_DIRS = [
|
|||||||
'model_indexes',
|
'model_indexes',
|
||||||
# TODO: 'model_inheritance',
|
# TODO: 'model_inheritance',
|
||||||
'model_inheritance_regress',
|
'model_inheritance_regress',
|
||||||
# SKIPPED (all errors are false positives) 'model_meta',
|
'model_meta',
|
||||||
'model_options',
|
'model_options',
|
||||||
'model_package',
|
'model_package',
|
||||||
'model_regress',
|
'model_regress',
|
||||||
@@ -298,8 +350,8 @@ def cd(path):
|
|||||||
os.chdir(prev_cwd)
|
os.chdir(prev_cwd)
|
||||||
|
|
||||||
|
|
||||||
def is_ignored(line: str) -> bool:
|
def is_ignored(line: str, test_folder_name: str) -> bool:
|
||||||
for pattern in IGNORED_ERROR_PATTERNS:
|
for pattern in IGNORED_ERRORS['__common__'] + IGNORED_ERRORS.get(test_folder_name, []):
|
||||||
if isinstance(pattern, Pattern):
|
if isinstance(pattern, Pattern):
|
||||||
if pattern.search(line):
|
if pattern.search(line):
|
||||||
return True
|
return True
|
||||||
@@ -309,22 +361,29 @@ def is_ignored(line: str) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def replace_with_clickable_location(error: str, abs_test_folder: Path) -> str:
|
||||||
|
raw_path, _, error_line = error.partition(': ')
|
||||||
|
fname, line_number = raw_path.split(':')
|
||||||
|
path = abs_test_folder.joinpath(fname).relative_to(PROJECT_DIRECTORY)
|
||||||
|
clickable_location = f'./{path}:{line_number}'
|
||||||
|
return error.replace(raw_path, clickable_location)
|
||||||
|
|
||||||
|
|
||||||
def check_with_mypy(abs_path: Path, config_file_path: Path) -> int:
|
def check_with_mypy(abs_path: Path, config_file_path: Path) -> int:
|
||||||
error_happened = False
|
error_happened = False
|
||||||
with cd(abs_path):
|
with cd(abs_path):
|
||||||
sources, options = process_options(['--config-file', str(config_file_path), str(abs_path)])
|
sources, options = process_options(['--config-file', str(config_file_path), str(abs_path)])
|
||||||
res = build.build(sources, options)
|
res = build.build(sources, options)
|
||||||
for error_line in res.errors:
|
for error_line in res.errors:
|
||||||
if not is_ignored(error_line):
|
if not is_ignored(error_line, abs_path.name):
|
||||||
error_happened = True
|
error_happened = True
|
||||||
print(error_line)
|
print(replace_with_clickable_location(error_line, abs_test_folder=abs_path))
|
||||||
return int(error_happened)
|
return int(error_happened)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
project_directory = Path(__file__).parent.parent
|
mypy_config_file = (PROJECT_DIRECTORY / 'scripts' / 'mypy.ini').absolute()
|
||||||
mypy_config_file = (project_directory / 'scripts' / 'mypy.ini').absolute()
|
repo_directory = PROJECT_DIRECTORY / 'django-sources'
|
||||||
repo_directory = project_directory / 'django-sources'
|
|
||||||
tests_root = repo_directory / 'tests'
|
tests_root = repo_directory / 'tests'
|
||||||
global_rc = 0
|
global_rc = 0
|
||||||
|
|
||||||
@@ -337,8 +396,8 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
repo.git.checkout(DJANGO_COMMIT_SHA)
|
repo.git.checkout(DJANGO_COMMIT_SHA)
|
||||||
for dirname in TESTS_DIRS:
|
for dirname in TESTS_DIRS:
|
||||||
abs_path = (project_directory / tests_root / dirname).absolute()
|
abs_path = (PROJECT_DIRECTORY / tests_root / dirname).absolute()
|
||||||
print(f'Checking {abs_path.as_uri()}')
|
print(f'Checking {abs_path}')
|
||||||
|
|
||||||
rc = check_with_mypy(abs_path, mypy_config_file)
|
rc = check_with_mypy(abs_path, mypy_config_file)
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
|
|||||||
Reference in New Issue
Block a user