mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-10 22:11:54 +08:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de4fa92441 | ||
|
|
dce0c0e930 | ||
|
|
fc9a335dfd | ||
|
|
5fc39ff110 | ||
|
|
e95b40ef52 | ||
|
|
c91a6d1d5b | ||
|
|
d7e8222163 | ||
|
|
09767210ec | ||
|
|
656105bab2 | ||
|
|
ff7bf33e9c | ||
|
|
d94b7b0c6a | ||
|
|
7bf1664307 | ||
|
|
0545c2d3ea | ||
|
|
825931da9f | ||
|
|
737fd239b6 | ||
|
|
7f476057b0 | ||
|
|
d31512854a | ||
|
|
552de422dc | ||
|
|
a9978cc021 | ||
|
|
bb08212b20 | ||
|
|
5d2efdb80b | ||
|
|
27793ecd32 | ||
|
|
dddcb20fe4 |
10
.editorconfig
Normal file
10
.editorconfig
Normal file
@@ -0,0 +1,10 @@
|
||||
# Check http://editorconfig.org for more information
|
||||
# This is the main config file for this project:
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
trim_trailing_whitespace = true
|
||||
@@ -24,7 +24,7 @@ class Apps:
|
||||
def get_app_configs(self) -> Iterable[AppConfig]: ...
|
||||
def get_app_config(self, app_label: str) -> AppConfig: ...
|
||||
# it's not possible to support it in plugin properly now
|
||||
def get_models(self, include_auto_created: bool = ..., include_swapped: bool = ...) -> List[Type[Any]]: ...
|
||||
def get_models(self, include_auto_created: bool = ..., include_swapped: bool = ...) -> List[Type[Model]]: ...
|
||||
def get_model(self, app_label: str, model_name: Optional[str] = ..., require_ready: bool = ...) -> Type[Any]: ...
|
||||
def register_model(self, app_label: str, model: Type[Model]) -> None: ...
|
||||
def is_installed(self, app_name: str) -> bool: ...
|
||||
|
||||
3
django-stubs/contrib/admindocs/urls.pyi
Normal file
3
django-stubs/contrib/admindocs/urls.pyi
Normal file
@@ -0,0 +1,3 @@
|
||||
from typing import Any, List
|
||||
|
||||
urlpatterns: List[Any] = ...
|
||||
3
django-stubs/contrib/flatpages/urls.pyi
Normal file
3
django-stubs/contrib/flatpages/urls.pyi
Normal file
@@ -0,0 +1,3 @@
|
||||
from typing import Any, List
|
||||
|
||||
urlpatterns: List[Any] = ...
|
||||
@@ -13,7 +13,7 @@ class SearchVectorCombinable:
|
||||
ADD: str = ...
|
||||
|
||||
class SearchVector(SearchVectorCombinable, Func):
|
||||
config: Optional[Any] = None
|
||||
config: Optional[Any] = ...
|
||||
def __init__(self, *expressions: Union[str, Combinable], **extra: Any): ...
|
||||
|
||||
class CombinedSearchVector(SearchVectorCombinable, CombinedExpression):
|
||||
@@ -31,11 +31,11 @@ class SearchQueryCombinable:
|
||||
|
||||
class SearchQuery(SearchQueryCombinable, Value):
|
||||
SEARCH_TYPES: Dict[str, str] = {"plain": "plainto_tsquery", "phrase": "phraseto_tsquery", "raw": "to_tsquery"}
|
||||
def __init__(self, value, output_field=None, *, config=None, invert=False, search_type="plain"): ...
|
||||
def __init__(self, value, output_field=..., *, config=..., invert=False, search_type="plain"): ...
|
||||
def __invert__(self: _T) -> _T: ...
|
||||
|
||||
class CombinedSearchQuery(SearchQueryCombinable, CombinedExpression):
|
||||
def __init__(self, lhs, connector, rhs, config, output_field=None) -> None: ...
|
||||
def __init__(self, lhs, connector, rhs, config, output_field=...) -> None: ...
|
||||
|
||||
class SearchRank(Func):
|
||||
def __init__(self, vector, query, **extra: Any) -> None: ...
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from django.core.files.storage import FileSystemStorage
|
||||
from django.core.files.storage import Storage
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
class Command(BaseCommand):
|
||||
@@ -23,6 +23,6 @@ class Command(BaseCommand):
|
||||
def log(self, msg: str, level: int = ...) -> None: ...
|
||||
def is_local_storage(self) -> bool: ...
|
||||
def clear_dir(self, path: str) -> None: ...
|
||||
def delete_file(self, path: str, prefixed_path: str, source_storage: FileSystemStorage) -> bool: ...
|
||||
def link_file(self, path: str, prefixed_path: str, source_storage: FileSystemStorage) -> None: ...
|
||||
def copy_file(self, path: str, prefixed_path: str, source_storage: FileSystemStorage) -> None: ...
|
||||
def delete_file(self, path: str, prefixed_path: str, source_storage: Storage) -> bool: ...
|
||||
def link_file(self, path: str, prefixed_path: str, source_storage: Storage) -> None: ...
|
||||
def copy_file(self, path: str, prefixed_path: str, source_storage: Storage) -> None: ...
|
||||
|
||||
@@ -2,6 +2,6 @@ from typing import Any, List, Optional
|
||||
|
||||
from django.urls.resolvers import URLPattern
|
||||
|
||||
urlpatterns: Any
|
||||
urlpatterns: List[Any] = ...
|
||||
|
||||
def staticfiles_urlpatterns(prefix: Optional[str] = ...) -> List[URLPattern]: ...
|
||||
|
||||
24
django-stubs/core/cache/backends/locmem.pyi
vendored
24
django-stubs/core/cache/backends/locmem.pyi
vendored
@@ -1,26 +1,6 @@
|
||||
from typing import Any, Callable, Dict, Optional, Union
|
||||
from typing import Any, Dict
|
||||
|
||||
from django.core.cache.backends.base import BaseCache
|
||||
|
||||
class LocMemCache(BaseCache):
|
||||
default_timeout: int
|
||||
key_func: Callable
|
||||
key_prefix: str
|
||||
version: int
|
||||
def __init__(self, name: str, params: Dict[str, Optional[Union[Callable, Dict[str, int], int, str]]]) -> None: ...
|
||||
def add(
|
||||
self,
|
||||
key: str,
|
||||
value: Union[Dict[str, int], Dict[str, str], bytes, int, str],
|
||||
timeout: Any = ...,
|
||||
version: Optional[int] = ...,
|
||||
) -> Any: ...
|
||||
def get(
|
||||
self, key: Union[int, str], default: Optional[Union[int, str]] = ..., version: Optional[int] = ...
|
||||
) -> Any: ...
|
||||
def set(self, key: Union[int, str], value: Any, timeout: Any = ..., version: Optional[int] = ...) -> None: ...
|
||||
def touch(self, key: str, timeout: Any = ..., version: None = ...) -> Any: ...
|
||||
def incr(self, key: Union[int, str], delta: int = ..., version: Optional[int] = ...) -> int: ...
|
||||
def has_key(self, key: str, version: Optional[int] = ...) -> Any: ...
|
||||
def delete(self, key: str, version: Optional[int] = ...) -> None: ...
|
||||
def clear(self) -> None: ...
|
||||
def __init__(self, name: str, params: Dict[str, Any]) -> None: ...
|
||||
|
||||
10
django-stubs/core/cache/backends/memcached.pyi
vendored
Normal file
10
django-stubs/core/cache/backends/memcached.pyi
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
from django.core.cache.backends.base import BaseCache
|
||||
|
||||
class BaseMemcachedCache(BaseCache):
|
||||
def __init__(self, server, params, library, value_not_found_exception) -> None: ...
|
||||
|
||||
class MemcachedCache(BaseMemcachedCache):
|
||||
def __init__(self, server, params): ...
|
||||
|
||||
class PyLibMCCache(BaseMemcachedCache):
|
||||
def __init__(self, server, params): ...
|
||||
@@ -23,9 +23,14 @@ class FileUploadHandler:
|
||||
content_type_extra = ... # type: Optional[Dict[str, str]]
|
||||
request = ... # type: Optional[HttpRequest]
|
||||
field_name = ... # type: str
|
||||
def __init__(self, request: HttpRequest = None) -> None: ...
|
||||
def __init__(self, request: Optional[HttpRequest] = ...) -> None: ...
|
||||
def handle_raw_input(
|
||||
self, input_data: IO[bytes], META: Dict[str, str], content_length: int, boundary: str, encoding: str = None
|
||||
self,
|
||||
input_data: IO[bytes],
|
||||
META: Dict[str, str],
|
||||
content_length: int,
|
||||
boundary: str,
|
||||
encoding: Optional[str] = ...,
|
||||
) -> Optional[Tuple[QueryDict, MultiValueDict[str, UploadedFile]]]: ...
|
||||
def new_file(
|
||||
self,
|
||||
@@ -33,15 +38,15 @@ class FileUploadHandler:
|
||||
file_name: str,
|
||||
content_type: str,
|
||||
content_length: Optional[int],
|
||||
charset: str = None,
|
||||
content_type_extra: Dict[str, str] = None,
|
||||
charset: Optional[str] = ...,
|
||||
content_type_extra: Optional[Dict[str, str]] = ...,
|
||||
) -> None: ...
|
||||
def receive_data_chunk(self, raw_data: bytes, start: int) -> Optional[bytes]: ...
|
||||
def file_complete(self, file_size: int) -> Optional[UploadedFile]: ...
|
||||
def upload_complete(self) -> None: ...
|
||||
|
||||
class TemporaryFileUploadHandler(FileUploadHandler):
|
||||
def __init__(self, request: HttpRequest = None) -> None: ...
|
||||
def __init__(self, request: Optional[HttpRequest] = ...) -> None: ...
|
||||
file = ... # type: TemporaryUploadedFile
|
||||
def new_file(
|
||||
self,
|
||||
@@ -49,8 +54,8 @@ class TemporaryFileUploadHandler(FileUploadHandler):
|
||||
file_name: str,
|
||||
content_type: str,
|
||||
content_length: Optional[int],
|
||||
charset: str = None,
|
||||
content_type_extra: Dict[str, str] = None,
|
||||
charset: Optional[str] = ...,
|
||||
content_type_extra: Optional[Dict[str, str]] = ...,
|
||||
) -> None: ...
|
||||
def receive_data_chunk(self, raw_data: bytes, start: int) -> Optional[bytes]: ...
|
||||
def file_complete(self, file_size: int) -> Optional[UploadedFile]: ...
|
||||
@@ -59,7 +64,12 @@ class MemoryFileUploadHandler(FileUploadHandler):
|
||||
activated = ... # type: bool
|
||||
file = ... # type: IO[bytes]
|
||||
def handle_raw_input(
|
||||
self, input_data: IO[bytes], META: Dict[str, str], content_length: int, boundary: str, encoding: str = None
|
||||
self,
|
||||
input_data: IO[bytes],
|
||||
META: Dict[str, str],
|
||||
content_length: int,
|
||||
boundary: str,
|
||||
encoding: Optional[str] = ...,
|
||||
) -> Optional[Tuple[QueryDict, MultiValueDict[str, UploadedFile]]]: ...
|
||||
def new_file(
|
||||
self,
|
||||
@@ -67,8 +77,8 @@ class MemoryFileUploadHandler(FileUploadHandler):
|
||||
file_name: str,
|
||||
content_type: str,
|
||||
content_length: Optional[int],
|
||||
charset: str = None,
|
||||
content_type_extra: Dict[str, str] = None,
|
||||
charset: Optional[str] = ...,
|
||||
content_type_extra: Optional[Dict[str, str]] = ...,
|
||||
) -> None: ...
|
||||
def receive_data_chunk(self, raw_data: bytes, start: int) -> Optional[bytes]: ...
|
||||
def file_complete(self, file_size: int) -> Optional[UploadedFile]: ...
|
||||
|
||||
@@ -6,10 +6,6 @@ from django.http.response import HttpResponse, HttpResponseBase
|
||||
logger: Any
|
||||
|
||||
class BaseHandler:
|
||||
_view_middleware: None = ...
|
||||
_template_response_middleware: None = ...
|
||||
_exception_middleware: None = ...
|
||||
_middleware_chain: None = ...
|
||||
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): ...
|
||||
|
||||
@@ -65,7 +65,7 @@ class EmailMessage:
|
||||
to: Optional[Union[Sequence[str], str]] = ...,
|
||||
bcc: Optional[Union[Sequence[str], str]] = ...,
|
||||
connection: Optional[Any] = ...,
|
||||
attachments: Optional[Union[List[Tuple[str, str]], List[MIMEText]]] = ...,
|
||||
attachments: Optional[Union[List[Tuple[str, Union[str, bytes], str]], List[MIMEText]]] = ...,
|
||||
headers: Optional[Dict[str, str]] = ...,
|
||||
cc: Optional[Union[Sequence[str], str]] = ...,
|
||||
reply_to: Optional[Union[List[Optional[str]], str]] = ...,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from argparse import ArgumentParser, HelpFormatter, Namespace
|
||||
from io import StringIO, TextIOBase, TextIOWrapper
|
||||
from typing import Any, Callable, List, Optional, Union
|
||||
from typing import Any, Callable, List, Optional, Union, Tuple
|
||||
|
||||
from django.apps.config import AppConfig
|
||||
from django.core.management.color import Style
|
||||
@@ -36,8 +36,8 @@ class BaseCommand:
|
||||
output_transaction: bool = ...
|
||||
requires_migrations_checks: bool = ...
|
||||
requires_system_checks: bool = ...
|
||||
base_stealth_options: Any = ...
|
||||
stealth_options: Any = ...
|
||||
base_stealth_options: Tuple[str, ...] = ...
|
||||
stealth_options: Tuple[str, ...] = ...
|
||||
stdout: OutputWrapper = ...
|
||||
stderr: OutputWrapper = ...
|
||||
style: Style = ...
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
class Command(BaseCommand): ...
|
||||
class Command(BaseCommand):
|
||||
default_addr: str = ...
|
||||
default_addr_ipv6: str = ...
|
||||
default_port: int = ...
|
||||
protocol: str = ...
|
||||
|
||||
@@ -5,6 +5,6 @@ from django.db.models.base import Model
|
||||
|
||||
def popen_wrapper(args: List[str], stdout_encoding: str = ...) -> Tuple[str, str, int]: ...
|
||||
def handle_extensions(extensions: List[str]) -> Set[str]: ...
|
||||
def find_command(cmd: str, path: None = ..., pathext: None = ...) -> Optional[str]: ...
|
||||
def find_command(cmd: str, path: Optional[str] = ..., pathext: Optional[str] = ...) -> Optional[str]: ...
|
||||
def get_random_secret_key(): ...
|
||||
def parse_apps_and_model_labels(labels: List[str]) -> Tuple[Set[Type[Model]], Set[AppConfig]]: ...
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import types
|
||||
from datetime import date, datetime, time
|
||||
from decimal import Decimal
|
||||
from typing import Any, Dict, Iterator, List, Mapping, Optional, Sequence, Tuple, Union
|
||||
from typing import Any, Dict, Iterator, List, Mapping, Optional, Sequence, Tuple, Union, Type
|
||||
from uuid import UUID
|
||||
|
||||
logger: Any
|
||||
@@ -16,7 +17,12 @@ class CursorWrapper:
|
||||
def __getattr__(self, attr: str) -> Any: ...
|
||||
def __iter__(self) -> None: ...
|
||||
def __enter__(self) -> CursorWrapper: ...
|
||||
def __exit__(self, type: None, value: None, traceback: None) -> None: ...
|
||||
def __exit__(
|
||||
self,
|
||||
exc_type: Optional[Type[BaseException]],
|
||||
exc_value: Optional[BaseException],
|
||||
tb: Optional[types.TracebackType],
|
||||
) -> None: ...
|
||||
def callproc(self, procname: str, params: List[Any] = ..., kparams: Dict[str, int] = ...) -> Any: ...
|
||||
def execute(
|
||||
self, sql: str, params: Optional[Union[Sequence[_SQLType], Mapping[str, _SQLType]]] = ...
|
||||
|
||||
@@ -6,6 +6,7 @@ from django.db.models.sql.compiler import SQLCompiler
|
||||
|
||||
from django.db.models import Q, QuerySet
|
||||
from django.db.models.fields import Field
|
||||
from django.db.models.query import _BaseQuerySet
|
||||
|
||||
_OutputField = Union[Field, str]
|
||||
|
||||
@@ -125,7 +126,7 @@ class Subquery(Expression):
|
||||
template: str = ...
|
||||
queryset: QuerySet = ...
|
||||
extra: Dict[Any, Any] = ...
|
||||
def __init__(self, queryset: QuerySet, output_field: Optional[_OutputField] = ..., **extra: Any) -> None: ...
|
||||
def __init__(self, queryset: _BaseQuerySet, output_field: Optional[_OutputField] = ..., **extra: Any) -> None: ...
|
||||
|
||||
class Exists(Subquery):
|
||||
negated: bool = ...
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Any, Callable, List, Optional, Type, Union, Tuple, Iterable
|
||||
from typing import Any, Callable, List, Optional, Type, Union, Tuple, Iterable, overload, TypeVar
|
||||
|
||||
from django.core.checks.messages import Error
|
||||
from django.core.files.base import File
|
||||
from django.core.files.images import ImageFile
|
||||
from django.core.files.storage import FileSystemStorage, Storage
|
||||
@@ -34,6 +33,8 @@ class FileDescriptor:
|
||||
def __set__(self, instance: Model, value: Optional[Any]) -> None: ...
|
||||
def __get__(self, instance: Optional[Model], cls: Type[Model] = ...) -> Union[FieldFile, FileDescriptor]: ...
|
||||
|
||||
_T = TypeVar("_T", bound="Field")
|
||||
|
||||
class FileField(Field):
|
||||
storage: Any = ...
|
||||
upload_to: Union[str, Callable] = ...
|
||||
@@ -63,6 +64,15 @@ class FileField(Field):
|
||||
validators: Iterable[_ValidatorCallable] = ...,
|
||||
error_messages: Optional[_ErrorMessagesToOverride] = ...,
|
||||
): ...
|
||||
# class access
|
||||
@overload # type: ignore
|
||||
def __get__(self, instance: None, owner) -> FileDescriptor: ...
|
||||
# Model instance access
|
||||
@overload
|
||||
def __get__(self, instance: Model, owner) -> Any: ...
|
||||
# non-Model instances
|
||||
@overload
|
||||
def __get__(self: _T, instance, owner) -> _T: ...
|
||||
def generate_filename(self, instance: Optional[Model], filename: str) -> str: ...
|
||||
|
||||
class ImageFileDescriptor(FileDescriptor):
|
||||
@@ -82,4 +92,13 @@ class ImageField(FileField):
|
||||
height_field: Optional[str] = ...,
|
||||
**kwargs: Any
|
||||
) -> None: ...
|
||||
# class access
|
||||
@overload # type: ignore
|
||||
def __get__(self, instance: None, owner) -> ImageFileDescriptor: ...
|
||||
# Model instance access
|
||||
@overload
|
||||
def __get__(self, instance: Model, owner) -> Any: ...
|
||||
# non-Model instances
|
||||
@overload
|
||||
def __get__(self: _T, instance, owner) -> _T: ...
|
||||
def update_dimension_fields(self, instance: Model, force: bool = ..., *args: Any, **kwargs: Any) -> None: ...
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, TYPE_CHECKING, Tuple, Type, TypeVar, Union
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
Iterable,
|
||||
List,
|
||||
Optional,
|
||||
Sequence,
|
||||
TYPE_CHECKING,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
overload,
|
||||
)
|
||||
from uuid import UUID
|
||||
|
||||
from django.db.models.expressions import Combinable
|
||||
@@ -25,7 +39,7 @@ if TYPE_CHECKING:
|
||||
from django.db.models.manager import RelatedManager
|
||||
|
||||
_T = TypeVar("_T", bound=models.Model)
|
||||
|
||||
_F = TypeVar("_F", bound=models.Field)
|
||||
_Choice = Tuple[Any, str]
|
||||
_ChoiceNamedGroup = Tuple[str, Iterable[_Choice]]
|
||||
_FieldChoices = Iterable[Union[_Choice, _ChoiceNamedGroup]]
|
||||
@@ -66,9 +80,9 @@ class ForeignObject(RelatedField[_ST, _GT]):
|
||||
on_delete: Callable[..., None],
|
||||
from_fields: Sequence[str],
|
||||
to_fields: Sequence[str],
|
||||
rel: None = ...,
|
||||
rel: Optional[ForeignObjectRel] = ...,
|
||||
related_name: Optional[str] = ...,
|
||||
related_query_name: None = ...,
|
||||
related_query_name: Optional[str] = ...,
|
||||
limit_choices_to: Optional[Union[Dict[str, Any], Callable[[], Any]]] = ...,
|
||||
parent_link: bool = ...,
|
||||
db_constraint: bool = ...,
|
||||
@@ -127,6 +141,15 @@ class ForeignKey(ForeignObject[_ST, _GT]):
|
||||
validators: Iterable[_ValidatorCallable] = ...,
|
||||
error_messages: Optional[_ErrorMessagesToOverride] = ...,
|
||||
): ...
|
||||
# class access
|
||||
@overload # type: ignore
|
||||
def __get__(self, instance: None, owner) -> ForwardManyToOneDescriptor: ...
|
||||
# Model instance access
|
||||
@overload
|
||||
def __get__(self, instance: Model, owner) -> _GT: ...
|
||||
# non-Model instances
|
||||
@overload
|
||||
def __get__(self: _F, instance, owner) -> _F: ...
|
||||
|
||||
class OneToOneField(RelatedField[_ST, _GT]):
|
||||
_pyi_private_set_type: Union[Any, Combinable]
|
||||
@@ -163,6 +186,15 @@ class OneToOneField(RelatedField[_ST, _GT]):
|
||||
validators: Iterable[_ValidatorCallable] = ...,
|
||||
error_messages: Optional[_ErrorMessagesToOverride] = ...,
|
||||
): ...
|
||||
# class access
|
||||
@overload # type: ignore
|
||||
def __get__(self, instance: None, owner) -> ForwardOneToOneDescriptor: ...
|
||||
# Model instance access
|
||||
@overload
|
||||
def __get__(self, instance: Model, owner) -> _GT: ...
|
||||
# non-Model instances
|
||||
@overload
|
||||
def __get__(self: _F, instance, owner) -> _F: ...
|
||||
|
||||
class ManyToManyField(RelatedField[_ST, _GT]):
|
||||
_pyi_private_set_type: Sequence[Any]
|
||||
@@ -206,7 +238,15 @@ class ManyToManyField(RelatedField[_ST, _GT]):
|
||||
validators: Iterable[_ValidatorCallable] = ...,
|
||||
error_messages: Optional[_ErrorMessagesToOverride] = ...,
|
||||
) -> None: ...
|
||||
def __get__(self, instance, owner) -> _GT: ... # type: ignore
|
||||
# class access
|
||||
@overload # type: ignore
|
||||
def __get__(self, instance: None, owner) -> ManyToManyDescriptor: ...
|
||||
# Model instance access
|
||||
@overload
|
||||
def __get__(self, instance: Model, owner) -> _GT: ...
|
||||
# non-Model instances
|
||||
@overload
|
||||
def __get__(self: _F, instance, owner) -> _F: ...
|
||||
def get_path_info(self, filtered_relation: None = ...) -> List[PathInfo]: ...
|
||||
def get_reverse_path_info(self, filtered_relation: None = ...) -> List[PathInfo]: ...
|
||||
def contribute_to_related_class(self, cls: Type[Model], related: RelatedField) -> None: ...
|
||||
|
||||
@@ -5,7 +5,7 @@ from django.db.models.query import QuerySet
|
||||
|
||||
_T = TypeVar("_T", bound=Model, covariant=True)
|
||||
|
||||
class BaseManager(QuerySet[_T, _T]):
|
||||
class BaseManager(QuerySet[_T]):
|
||||
creation_counter: int = ...
|
||||
auto_created: bool = ...
|
||||
use_in_migrations: bool = ...
|
||||
@@ -21,7 +21,7 @@ class BaseManager(QuerySet[_T, _T]):
|
||||
def _get_queryset_methods(cls, queryset_class: type) -> Dict[str, Any]: ...
|
||||
def contribute_to_class(self, model: Type[Model], name: str) -> None: ...
|
||||
def db_manager(self, using: Optional[str] = ..., hints: Optional[Dict[str, Model]] = ...) -> Manager: ...
|
||||
def get_queryset(self) -> QuerySet[_T, _T]: ...
|
||||
def get_queryset(self) -> QuerySet[_T]: ...
|
||||
|
||||
class Manager(BaseManager[_T]): ...
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ class Options(Generic[_M]):
|
||||
abstract: bool = ...
|
||||
managed: bool = ...
|
||||
proxy: bool = ...
|
||||
proxy_for_model: None = ...
|
||||
proxy_for_model: Optional[Type[Model]] = ...
|
||||
concrete_model: Optional[Type[Model]] = ...
|
||||
swappable: None = ...
|
||||
parents: collections.OrderedDict = ...
|
||||
|
||||
@@ -27,10 +27,115 @@ from django.db import models
|
||||
from django.db.models import Manager
|
||||
from django.db.models.query_utils import Q as Q
|
||||
|
||||
_T = TypeVar("_T", bound=models.Model, covariant=True)
|
||||
_QS = TypeVar("_QS", bound="_BaseQuerySet")
|
||||
|
||||
class _BaseQuerySet(Generic[_T], Sized):
|
||||
query: Query
|
||||
def __init__(
|
||||
self,
|
||||
model: Optional[Type[models.Model]] = ...,
|
||||
query: Optional[Query] = ...,
|
||||
using: Optional[str] = ...,
|
||||
hints: Optional[Dict[str, models.Model]] = ...,
|
||||
) -> None: ...
|
||||
@classmethod
|
||||
def as_manager(cls) -> Manager[Any]: ...
|
||||
def __len__(self) -> int: ...
|
||||
def __bool__(self) -> bool: ...
|
||||
def __class_getitem__(cls, item: Type[_T]):
|
||||
pass
|
||||
def __getstate__(self) -> Dict[str, Any]: ...
|
||||
# Technically, the other QuerySet must be of the same type _T, but _T is covariant
|
||||
def __and__(self: _QS, other: _BaseQuerySet[_T]) -> _QS: ...
|
||||
def __or__(self: _QS, other: _BaseQuerySet[_T]) -> _QS: ...
|
||||
def iterator(self, chunk_size: int = ...) -> Iterator[_T]: ...
|
||||
def aggregate(self, *args: Any, **kwargs: Any) -> Dict[str, Any]: ...
|
||||
def get(self, *args: Any, **kwargs: Any) -> _T: ...
|
||||
def create(self, *args: Any, **kwargs: Any) -> _T: ...
|
||||
def bulk_create(
|
||||
self, objs: Iterable[Model], batch_size: Optional[int] = ..., ignore_conflicts: bool = ...
|
||||
) -> List[_T]: ...
|
||||
def get_or_create(self, defaults: Optional[MutableMapping[str, Any]] = ..., **kwargs: Any) -> Tuple[_T, bool]: ...
|
||||
def update_or_create(
|
||||
self, defaults: Optional[MutableMapping[str, Any]] = ..., **kwargs: Any
|
||||
) -> Tuple[_T, bool]: ...
|
||||
def earliest(self, *fields: Any, field_name: Optional[Any] = ...) -> _T: ...
|
||||
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: Iterable[Any] = ..., *, field_name: str = ...) -> Dict[Any, _T]: ...
|
||||
def delete(self) -> Tuple[int, Dict[str, int]]: ...
|
||||
def update(self, **kwargs: Any) -> int: ...
|
||||
def exists(self) -> bool: ...
|
||||
def explain(self, *, format: Optional[Any] = ..., **options: Any) -> str: ...
|
||||
def raw(
|
||||
self,
|
||||
raw_query: str,
|
||||
params: Any = ...,
|
||||
translations: Optional[Dict[str, str]] = ...,
|
||||
using: Optional[str] = ...,
|
||||
) -> RawQuerySet: ...
|
||||
# The type of values may be overridden to be more specific in the mypy plugin, depending on the fields param
|
||||
def values(self, *fields: Union[str, Combinable], **expressions: Any) -> ValuesQuerySet[_T, Dict[str, Any]]: ...
|
||||
# The type of values_list may be overridden to be more specific in the mypy plugin, depending on the fields param
|
||||
def values_list(
|
||||
self, *fields: Union[str, Combinable], flat: bool = ..., named: bool = ...
|
||||
) -> ValuesQuerySet[_T, Any]: ...
|
||||
def dates(self, field_name: str, kind: str, order: str = ...) -> ValuesQuerySet[_T, datetime.date]: ...
|
||||
def datetimes(
|
||||
self, field_name: str, kind: str, order: str = ..., tzinfo: Optional[datetime.tzinfo] = ...
|
||||
) -> ValuesQuerySet[_T, datetime.datetime]: ...
|
||||
def none(self: _QS) -> _QS: ...
|
||||
def all(self: _QS) -> _QS: ...
|
||||
def filter(self: _QS, *args: Any, **kwargs: Any) -> _QS: ...
|
||||
def exclude(self: _QS, *args: Any, **kwargs: Any) -> _QS: ...
|
||||
def complex_filter(self, filter_obj: Any) -> _QS: ...
|
||||
def count(self) -> int: ...
|
||||
def union(self: _QS, *other_qs: Any, all: bool = ...) -> _QS: ...
|
||||
def intersection(self: _QS, *other_qs: Any) -> _QS: ...
|
||||
def difference(self: _QS, *other_qs: Any) -> _QS: ...
|
||||
def select_for_update(self: _QS, nowait: bool = ..., skip_locked: bool = ..., of: Tuple = ...) -> _QS: ...
|
||||
def select_related(self: _QS, *fields: Any) -> _QS: ...
|
||||
def prefetch_related(self: _QS, *lookups: Any) -> _QS: ...
|
||||
# TODO: return type
|
||||
def annotate(self, *args: Any, **kwargs: Any) -> QuerySet[Any]: ...
|
||||
def order_by(self: _QS, *field_names: Any) -> _QS: ...
|
||||
def distinct(self: _QS, *field_names: Any) -> _QS: ...
|
||||
# extra() return type won't be supported any time soon
|
||||
def extra(
|
||||
self,
|
||||
select: Optional[Dict[str, Any]] = ...,
|
||||
where: Optional[List[str]] = ...,
|
||||
params: Optional[List[Any]] = ...,
|
||||
tables: Optional[List[str]] = ...,
|
||||
order_by: Optional[Sequence[str]] = ...,
|
||||
select_params: Optional[Sequence[Any]] = ...,
|
||||
) -> QuerySet[Any]: ...
|
||||
def reverse(self: _QS) -> _QS: ...
|
||||
def defer(self: _QS, *fields: Any) -> _QS: ...
|
||||
def only(self: _QS, *fields: Any) -> _QS: ...
|
||||
def using(self: _QS, alias: Optional[str]) -> _QS: ...
|
||||
@property
|
||||
def ordered(self) -> bool: ...
|
||||
@property
|
||||
def db(self) -> str: ...
|
||||
def resolve_expression(self, *args: Any, **kwargs: Any) -> Any: ...
|
||||
# TODO: remove when django adds __class_getitem__ methods
|
||||
def __getattr__(self, item: str) -> Any: ...
|
||||
|
||||
class QuerySet(_BaseQuerySet[_T], Collection[_T], Sized):
|
||||
def __iter__(self) -> Iterator[_T]: ...
|
||||
def __contains__(self, x: object) -> bool: ...
|
||||
@overload
|
||||
def __getitem__(self, i: int) -> _T: ...
|
||||
@overload
|
||||
def __getitem__(self: _QS, s: slice) -> _QS: ...
|
||||
|
||||
_Row = TypeVar("_Row", covariant=True)
|
||||
|
||||
class BaseIterable(Sequence[_Row]):
|
||||
def __init__(self, queryset: QuerySet, chunked_fetch: bool = ..., chunk_size: int = ...): ...
|
||||
def __init__(self, queryset: _BaseQuerySet, chunked_fetch: bool = ..., chunk_size: int = ...): ...
|
||||
def __iter__(self) -> Iterator[_Row]: ...
|
||||
def __contains__(self, x: object) -> bool: ...
|
||||
def __len__(self) -> int: ...
|
||||
@@ -47,109 +152,19 @@ class NamedValuesListIterable(ValuesListIterable): ...
|
||||
class FlatValuesListIterable(BaseIterable):
|
||||
def __iter__(self) -> Iterator[Any]: ...
|
||||
|
||||
_T = TypeVar("_T", bound=models.Model, covariant=True)
|
||||
|
||||
class QuerySet(Generic[_T, _Row], Collection[_Row], Sized):
|
||||
query: Query
|
||||
def __init__(
|
||||
self,
|
||||
model: Optional[Type[models.Model]] = ...,
|
||||
query: Optional[Query] = ...,
|
||||
using: Optional[str] = ...,
|
||||
hints: Optional[Dict[str, models.Model]] = ...,
|
||||
) -> None: ...
|
||||
@classmethod
|
||||
def as_manager(cls) -> Manager[Any]: ...
|
||||
def __len__(self) -> int: ...
|
||||
def __iter__(self) -> Iterator[_Row]: ...
|
||||
class ValuesQuerySet(_BaseQuerySet[_T], Collection[_Row], Sized):
|
||||
def __contains__(self, x: object) -> bool: ...
|
||||
@overload
|
||||
def __iter__(self) -> Iterator[_Row]: ... # type: ignore
|
||||
@overload # type: ignore
|
||||
def __getitem__(self, i: int) -> _Row: ...
|
||||
@overload
|
||||
def __getitem__(self, s: slice) -> QuerySet[_T, _Row]: ...
|
||||
def __bool__(self) -> bool: ...
|
||||
def __class_getitem__(cls, item: Type[_T]):
|
||||
pass
|
||||
def __getstate__(self) -> Dict[str, Any]: ...
|
||||
# __and__ and __or__ ignore the other QuerySet's _Row type parameter because they use the same row type as the self QuerySet.
|
||||
# Technically, the other QuerySet must be of the same type _T, but _T is covariant
|
||||
def __and__(self, other: QuerySet[_T, Any]) -> QuerySet[_T, _Row]: ...
|
||||
def __or__(self, other: QuerySet[_T, Any]) -> QuerySet[_T, _Row]: ...
|
||||
def iterator(self, chunk_size: int = ...) -> Iterator[_Row]: ...
|
||||
def aggregate(self, *args: Any, **kwargs: Any) -> Dict[str, Any]: ...
|
||||
def get(self, *args: Any, **kwargs: Any) -> _Row: ...
|
||||
def create(self, *args: Any, **kwargs: Any) -> _T: ...
|
||||
def bulk_create(
|
||||
self, objs: Iterable[Model], batch_size: Optional[int] = ..., ignore_conflicts: bool = ...
|
||||
) -> List[_T]: ...
|
||||
def get_or_create(self, defaults: Optional[MutableMapping[str, Any]] = ..., **kwargs: Any) -> Tuple[_T, bool]: ...
|
||||
def update_or_create(
|
||||
self, defaults: Optional[MutableMapping[str, Any]] = ..., **kwargs: Any
|
||||
) -> Tuple[_T, bool]: ...
|
||||
def earliest(self, *fields: Any, field_name: Optional[Any] = ...) -> _Row: ...
|
||||
def latest(self, *fields: Any, field_name: Optional[Any] = ...) -> _Row: ...
|
||||
# technically it's Optional[_Row], but it creates a lot of false-positives (same for last())
|
||||
def first(self) -> _Row: ...
|
||||
def last(self) -> _Row: ...
|
||||
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 exists(self) -> bool: ...
|
||||
def explain(self, *, format: Optional[Any] = ..., **options: Any) -> str: ...
|
||||
def raw(
|
||||
self,
|
||||
raw_query: str,
|
||||
params: Any = ...,
|
||||
translations: Optional[Dict[str, str]] = ...,
|
||||
using: Optional[str] = ...,
|
||||
) -> RawQuerySet: ...
|
||||
# The type of values may be overridden to be more specific in the mypy plugin, depending on the fields param
|
||||
def values(self, *fields: Union[str, Combinable], **expressions: Any) -> QuerySet[_T, Dict[str, Any]]: ...
|
||||
# The type of values_list may be overridden to be more specific in the mypy plugin, depending on the fields param
|
||||
def values_list(
|
||||
self, *fields: Union[str, Combinable], flat: bool = ..., named: bool = ...
|
||||
) -> QuerySet[_T, Any]: ...
|
||||
def dates(self, field_name: str, kind: str, order: str = ...) -> QuerySet[_T, datetime.date]: ...
|
||||
def datetimes(
|
||||
self, field_name: str, kind: str, order: str = ..., tzinfo: None = ...
|
||||
) -> QuerySet[_T, datetime.datetime]: ...
|
||||
def none(self) -> QuerySet[_T, _Row]: ...
|
||||
def all(self) -> QuerySet[_T, _Row]: ...
|
||||
def filter(self, *args: Any, **kwargs: Any) -> QuerySet[_T, _Row]: ...
|
||||
def exclude(self, *args: Any, **kwargs: Any) -> QuerySet[_T, _Row]: ...
|
||||
def complex_filter(self, filter_obj: Any) -> QuerySet[_T, _Row]: ...
|
||||
def count(self) -> int: ...
|
||||
def union(self, *other_qs: Any, all: bool = ...) -> QuerySet[_T, _Row]: ...
|
||||
def intersection(self, *other_qs: Any) -> QuerySet[_T, _Row]: ...
|
||||
def difference(self, *other_qs: Any) -> QuerySet[_T, _Row]: ...
|
||||
def select_for_update(self, nowait: bool = ..., skip_locked: bool = ..., of: Tuple = ...) -> QuerySet[_T, _Row]: ...
|
||||
def select_related(self, *fields: Any) -> QuerySet[_T, _Row]: ...
|
||||
def prefetch_related(self, *lookups: Any) -> QuerySet[_T, _Row]: ...
|
||||
# TODO: return type
|
||||
def annotate(self, *args: Any, **kwargs: Any) -> QuerySet[Any, Any]: ...
|
||||
def order_by(self, *field_names: Any) -> QuerySet[_T, _Row]: ...
|
||||
def distinct(self, *field_names: Any) -> QuerySet[_T, _Row]: ...
|
||||
# extra() return type won't be supported any time soon
|
||||
def extra(
|
||||
self,
|
||||
select: Optional[Dict[str, Any]] = ...,
|
||||
where: Optional[List[str]] = ...,
|
||||
params: Optional[List[Any]] = ...,
|
||||
tables: Optional[List[str]] = ...,
|
||||
order_by: Optional[Sequence[str]] = ...,
|
||||
select_params: Optional[Sequence[Any]] = ...,
|
||||
) -> QuerySet[Any, Any]: ...
|
||||
def reverse(self) -> QuerySet[_T, _Row]: ...
|
||||
def defer(self, *fields: Any) -> QuerySet[_T, _Row]: ...
|
||||
def only(self, *fields: Any) -> QuerySet[_T, _Row]: ...
|
||||
def using(self, alias: Optional[str]) -> QuerySet[_T, _Row]: ...
|
||||
@property
|
||||
def ordered(self) -> bool: ...
|
||||
@property
|
||||
def db(self) -> str: ...
|
||||
def resolve_expression(self, *args: Any, **kwargs: Any) -> Any: ...
|
||||
# TODO: remove when django adds __class_getitem__ methods
|
||||
def __getattr__(self, item: str) -> Any: ...
|
||||
def __getitem__(self: _QS, s: slice) -> _QS: ...
|
||||
def iterator(self, chunk_size: int = ...) -> Iterator[_Row]: ... # type: ignore
|
||||
def get(self, *args: Any, **kwargs: Any) -> _Row: ... # type: ignore
|
||||
def earliest(self, *fields: Any, field_name: Optional[Any] = ...) -> _Row: ... # type: ignore
|
||||
def latest(self, *fields: Any, field_name: Optional[Any] = ...) -> _Row: ... # type: ignore
|
||||
def first(self) -> Optional[_Row]: ... # type: ignore
|
||||
def last(self) -> Optional[_Row]: ... # type: ignore
|
||||
|
||||
class RawQuerySet(Iterable[_T], Sized):
|
||||
query: RawQuery
|
||||
@@ -184,7 +199,7 @@ class RawQuerySet(Iterable[_T], Sized):
|
||||
def using(self, alias: Optional[str]) -> RawQuerySet[_T]: ...
|
||||
|
||||
class Prefetch(object):
|
||||
def __init__(self, lookup: str, queryset: Optional[QuerySet] = None, to_attr: Optional[str] = None) -> None: ...
|
||||
def __init__(self, lookup: str, queryset: Optional[QuerySet] = ..., to_attr: Optional[str] = ...) -> None: ...
|
||||
def __getstate__(self) -> Dict[str, Any]: ...
|
||||
def add_prefix(self, prefix: str) -> None: ...
|
||||
def get_current_prefetch_to(self, level: int) -> str: ...
|
||||
|
||||
@@ -38,5 +38,5 @@ def atomic(using: _C) -> _C: ...
|
||||
|
||||
# Decorator or context-manager with parameters
|
||||
@overload
|
||||
def atomic(using: Optional[str] = None, savepoint: bool = True) -> Atomic: ...
|
||||
def atomic(using: Optional[str] = ..., savepoint: bool = True) -> Atomic: ...
|
||||
def non_atomic_requests(using: Callable = ...) -> Callable: ...
|
||||
|
||||
@@ -6,7 +6,7 @@ from uuid import UUID
|
||||
from django.core.files.base import File
|
||||
from django.db.models.base import Model
|
||||
from django.db.models.manager import Manager
|
||||
from django.db.models.query import QuerySet
|
||||
from django.db.models.query import QuerySet, _BaseQuerySet
|
||||
from django.db.models.query_utils import Q
|
||||
from django.forms.fields import CharField, ChoiceField, Field
|
||||
from django.forms.forms import BaseForm, DeclarativeFieldsMetaclass
|
||||
@@ -262,7 +262,7 @@ class ModelMultipleChoiceField(ModelChoiceField):
|
||||
widget: Any = ...
|
||||
hidden_widget: Any = ...
|
||||
default_error_messages: Any = ...
|
||||
def __init__(self, queryset: QuerySet, **kwargs: Any) -> None: ...
|
||||
def __init__(self, queryset: _BaseQuerySet, **kwargs: Any) -> None: ...
|
||||
|
||||
def _get_foreign_key(
|
||||
parent_model: Type[Model], model: Type[Model], fk_name: Optional[str] = ..., can_fail: bool = ...
|
||||
|
||||
@@ -49,7 +49,7 @@ class HttpResponseBase(Iterable[Any]):
|
||||
) -> None: ...
|
||||
def setdefault(self, key: str, value: str) -> None: ...
|
||||
def set_signed_cookie(self, key: str, value: str, salt: str = "", **kwargs: Any) -> None: ...
|
||||
def delete_cookie(self, key: str, path: str = "", domain: str = None) -> None: ...
|
||||
def delete_cookie(self, key: str, path: str = "", domain: Optional[str] = ...) -> None: ...
|
||||
def make_bytes(self, value: object) -> bytes: ...
|
||||
def close(self) -> None: ...
|
||||
def write(self, content: Union[str, bytes]) -> None: ...
|
||||
|
||||
@@ -31,6 +31,6 @@ def redirect(
|
||||
|
||||
_T = TypeVar("_T", bound=Model)
|
||||
|
||||
def get_object_or_404(klass: Union[Type[_T], Manager[_T], QuerySet[_T, _T]], *args: Any, **kwargs: Any) -> _T: ...
|
||||
def get_list_or_404(klass: Union[Type[_T], Manager[_T], QuerySet[_T, _T]], *args: Any, **kwargs: Any) -> List[_T]: ...
|
||||
def get_object_or_404(klass: Union[Type[_T], Manager[_T], QuerySet[_T]], *args: Any, **kwargs: Any) -> _T: ...
|
||||
def get_list_or_404(klass: Union[Type[_T], Manager[_T], QuerySet[_T]], *args: Any, **kwargs: Any) -> List[_T]: ...
|
||||
def resolve_url(to: Union[Callable, Model, str], *args: Any, **kwargs: Any) -> str: ...
|
||||
|
||||
@@ -119,15 +119,17 @@ class SimpleTestCase(unittest.TestCase):
|
||||
field_kwargs: None = ...,
|
||||
empty_value: str = ...,
|
||||
) -> Any: ...
|
||||
def assertHTMLEqual(self, html1: str, html2: str, msg: None = ...) -> None: ...
|
||||
def assertHTMLNotEqual(self, html1: str, html2: str, msg: None = ...) -> None: ...
|
||||
def assertHTMLEqual(self, html1: str, html2: str, msg: Optional[str] = ...) -> None: ...
|
||||
def assertHTMLNotEqual(self, html1: str, html2: str, msg: Optional[str] = ...) -> None: ...
|
||||
def assertInHTML(
|
||||
self, needle: str, haystack: SafeText, count: Optional[int] = ..., msg_prefix: str = ...
|
||||
) -> None: ...
|
||||
def assertJSONEqual(self, raw: str, expected_data: Union[Dict[str, str], bool, str], msg: None = ...) -> None: ...
|
||||
def assertJSONNotEqual(self, raw: str, expected_data: str, msg: None = ...) -> None: ...
|
||||
def assertXMLEqual(self, xml1: str, xml2: str, msg: None = ...) -> None: ...
|
||||
def assertXMLNotEqual(self, xml1: str, xml2: str, msg: None = ...) -> None: ...
|
||||
def assertJSONEqual(
|
||||
self, raw: str, expected_data: Union[Dict[str, str], bool, str], msg: Optional[str] = ...
|
||||
) -> None: ...
|
||||
def assertJSONNotEqual(self, raw: str, expected_data: str, msg: Optional[str] = ...) -> None: ...
|
||||
def assertXMLEqual(self, xml1: str, xml2: str, msg: Optional[str] = ...) -> None: ...
|
||||
def assertXMLNotEqual(self, xml1: str, xml2: str, msg: Optional[str] = ...) -> None: ...
|
||||
|
||||
class TransactionTestCase(SimpleTestCase):
|
||||
reset_sequences: bool = ...
|
||||
@@ -141,7 +143,7 @@ class TransactionTestCase(SimpleTestCase):
|
||||
values: Union[List[None], List[Tuple[str, str]], List[date], List[int], List[str], Set[str], QuerySet],
|
||||
transform: Union[Callable, Type[str]] = ...,
|
||||
ordered: bool = ...,
|
||||
msg: None = ...,
|
||||
msg: Optional[str] = ...,
|
||||
) -> None: ...
|
||||
def assertNumQueries(
|
||||
self, num: int, func: Optional[Union[Callable, Type[list]]] = ..., *args: Any, using: Any = ..., **kwargs: Any
|
||||
|
||||
@@ -39,7 +39,7 @@ class MultiValueDict(MutableMapping[_K, _V]):
|
||||
def __init__(self, key_to_list_mapping: Iterable[Tuple[_K, List[_V]]] = ...) -> None: ...
|
||||
def getlist(self, key: _K, default: Any = ...) -> List[_V]: ...
|
||||
def setlist(self, key: _K, list_: List[_V]) -> None: ...
|
||||
def setlistdefault(self, key: _K, default_list: List[_V] = None) -> List[_V]: ...
|
||||
def setlistdefault(self, key: _K, default_list: Optional[List[_V]] = ...) -> List[_V]: ...
|
||||
def appendlist(self, key: _K, value: _V) -> None: ...
|
||||
def lists(self) -> Iterable[Tuple[_K, List[_V]]]: ...
|
||||
def dict(self) -> Dict[_K, Union[_V, List[_V]]]: ...
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
from datetime import date
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Optional, Dict
|
||||
|
||||
TIME_STRINGS: Any
|
||||
TIME_STRINGS: Dict[str, str]
|
||||
TIMESINCE_CHUNKS: Any
|
||||
|
||||
def timesince(d: date, now: Optional[date] = ..., reversed: bool = ..., time_strings: None = ...) -> str: ...
|
||||
def timeuntil(d: date, now: Optional[date] = ..., time_strings: None = ...) -> str: ...
|
||||
def timesince(
|
||||
d: date, now: Optional[date] = ..., reversed: bool = ..., time_strings: Optional[Dict[str, str]] = ...
|
||||
) -> str: ...
|
||||
def timeuntil(d: date, now: Optional[date] = ..., time_strings: Optional[Dict[str, str]] = ...) -> str: ...
|
||||
|
||||
@@ -39,16 +39,13 @@ ungettext = ngettext
|
||||
def pgettext(context: str, message: str) -> str: ...
|
||||
def npgettext(context: str, singular: str, plural: str, number: int) -> str: ...
|
||||
|
||||
gettext_lazy: Callable[[str], str]
|
||||
gettext_lazy = gettext
|
||||
ugettext_lazy = ugettext
|
||||
pgettext_lazy = pgettext
|
||||
ngettext_lazy = ngettext
|
||||
ungettext_lazy = ungettext
|
||||
npgettext_lazy = npgettext
|
||||
|
||||
ugettext_lazy: Callable[[str], str]
|
||||
pgettext_lazy: Callable[[str], str]
|
||||
|
||||
def ngettext_lazy(singular: Any, plural: Any, number: Optional[Any] = ...): ...
|
||||
|
||||
ungettext_lazy = ngettext_lazy
|
||||
|
||||
def npgettext_lazy(context: Any, singular: Any, plural: Any, number: Optional[Any] = ...): ...
|
||||
def activate(language: str) -> None: ...
|
||||
def deactivate() -> None: ...
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class FormMixin(ContextMixin):
|
||||
def get_initial(self) -> Dict[str, Any]: ...
|
||||
def get_prefix(self) -> Optional[str]: ...
|
||||
def get_form_class(self) -> Type[BaseForm]: ...
|
||||
def get_form(self, form_class: Optional[Type[BaseForm]] = None) -> BaseForm: ...
|
||||
def get_form(self, form_class: Optional[Type[BaseForm]] = ...) -> BaseForm: ...
|
||||
def get_form_kwargs(self) -> Dict[str, Any]: ...
|
||||
def get_success_url(self) -> str: ...
|
||||
def form_valid(self, form: BaseForm) -> HttpResponse: ...
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Any, Dict, Optional, Sequence, Tuple, Type
|
||||
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models.query import QuerySet
|
||||
from django.db.models.query import QuerySet, _BaseQuerySet
|
||||
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
|
||||
|
||||
from django.db.models import Model
|
||||
@@ -22,14 +22,14 @@ class MultipleObjectMixin(ContextMixin):
|
||||
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]: ...
|
||||
def get_paginate_by(self, queryset: QuerySet) -> Optional[int]: ...
|
||||
def paginate_queryset(self, queryset: _BaseQuerySet, page_size: int) -> Tuple[Paginator, int, QuerySet, bool]: ...
|
||||
def get_paginate_by(self, queryset: _BaseQuerySet) -> Optional[int]: ...
|
||||
def get_paginator(
|
||||
self, queryset: QuerySet, per_page: int, orphans: int = ..., allow_empty_first_page: bool = ..., **kwargs: Any
|
||||
) -> Paginator: ...
|
||||
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_object_name(self, object_list: _BaseQuerySet) -> Optional[str]: ...
|
||||
|
||||
class BaseListView(MultipleObjectMixin, View):
|
||||
def render_to_response(self, context: Dict[str, Any], **response_kwargs: Any) -> HttpResponse: ...
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
import os
|
||||
from collections import defaultdict
|
||||
from contextlib import contextmanager
|
||||
from typing import TYPE_CHECKING, Dict, Iterator, List, Optional, Tuple, Type
|
||||
from typing import Dict, Iterator, Optional, Set, TYPE_CHECKING, Tuple, Type, Union
|
||||
|
||||
from django.core.exceptions import FieldError
|
||||
from django.db.models.base import Model
|
||||
from django.db.models.fields import AutoField, CharField, Field
|
||||
from django.db.models.fields.related import ForeignKey, RelatedField
|
||||
from django.db.models.fields.reverse_related import ForeignObjectRel
|
||||
from django.db.models.sql.query import Query
|
||||
from django.utils.functional import cached_property
|
||||
from mypy.checker import TypeChecker
|
||||
from mypy.types import AnyType, Instance
|
||||
from mypy.types import Type as MypyType
|
||||
from mypy.types import TypeOfAny
|
||||
from mypy.types import AnyType, Instance, Type as MypyType, TypeOfAny
|
||||
|
||||
from django.db.models.fields import AutoField, CharField, Field
|
||||
from mypy_django_plugin.lib import helpers
|
||||
|
||||
try:
|
||||
@@ -115,11 +113,13 @@ class DjangoFieldsContext:
|
||||
|
||||
is_nullable = self.get_field_nullability(field, method)
|
||||
if isinstance(field, RelatedField):
|
||||
related_model_cls = self.django_context.fields_context.get_related_model_cls(field)
|
||||
|
||||
if method == 'values':
|
||||
primary_key_field = self.django_context.get_primary_key_field(field.related_model)
|
||||
primary_key_field = self.django_context.get_primary_key_field(related_model_cls)
|
||||
return self.get_field_get_type(api, primary_key_field, method=method)
|
||||
|
||||
model_info = helpers.lookup_class_typeinfo(api, field.related_model)
|
||||
model_info = helpers.lookup_class_typeinfo(api, related_model_cls)
|
||||
if model_info is None:
|
||||
return AnyType(TypeOfAny.unannotated)
|
||||
|
||||
@@ -128,6 +128,25 @@ class DjangoFieldsContext:
|
||||
return helpers.get_private_descriptor_type(field_info, '_pyi_private_get_type',
|
||||
is_nullable=is_nullable)
|
||||
|
||||
def get_related_model_cls(self, field: Union[RelatedField, ForeignObjectRel]) -> Type[Model]:
|
||||
if isinstance(field, RelatedField):
|
||||
related_model_cls = field.remote_field.model
|
||||
else:
|
||||
related_model_cls = field.field.model
|
||||
|
||||
if isinstance(related_model_cls, str):
|
||||
if related_model_cls == 'self':
|
||||
# same model
|
||||
related_model_cls = field.model
|
||||
elif '.' not in related_model_cls:
|
||||
# same file model
|
||||
related_model_fullname = field.model.__module__ + '.' + related_model_cls
|
||||
related_model_cls = self.django_context.get_model_class_by_fullname(related_model_fullname)
|
||||
else:
|
||||
related_model_cls = self.django_context.apps_registry.get_model(related_model_cls)
|
||||
|
||||
return related_model_cls
|
||||
|
||||
|
||||
class DjangoLookupsContext:
|
||||
def __init__(self, django_context: 'DjangoContext'):
|
||||
@@ -146,12 +165,12 @@ class DjangoLookupsContext:
|
||||
return self.django_context.get_primary_key_field(currently_observed_model)
|
||||
|
||||
current_field = currently_observed_model._meta.get_field(field_part)
|
||||
if not isinstance(current_field, (ForeignObjectRel, RelatedField)):
|
||||
continue
|
||||
|
||||
currently_observed_model = self.django_context.fields_context.get_related_model_cls(current_field)
|
||||
if isinstance(current_field, ForeignObjectRel):
|
||||
currently_observed_model = current_field.related_model
|
||||
current_field = self.django_context.get_primary_key_field(currently_observed_model)
|
||||
else:
|
||||
if isinstance(current_field, RelatedField):
|
||||
currently_observed_model = current_field.related_model
|
||||
|
||||
# if it is None, solve_lookup_type() will fail earlier
|
||||
assert current_field is not None
|
||||
@@ -170,20 +189,26 @@ class DjangoContext:
|
||||
self.settings = settings
|
||||
|
||||
@cached_property
|
||||
def model_modules(self) -> Dict[str, List[Type[Model]]]:
|
||||
def model_modules(self) -> Dict[str, Set[Type[Model]]]:
|
||||
""" All modules that contain Django models. """
|
||||
if self.apps_registry is None:
|
||||
return {}
|
||||
|
||||
modules: Dict[str, List[Type[Model]]] = defaultdict(list)
|
||||
for model_cls in self.apps_registry.get_models():
|
||||
modules[model_cls.__module__].append(model_cls)
|
||||
modules: Dict[str, Set[Type[Model]]] = defaultdict(set)
|
||||
for concrete_model_cls in self.apps_registry.get_models():
|
||||
modules[concrete_model_cls.__module__].add(concrete_model_cls)
|
||||
# collect abstract=True models
|
||||
for model_cls in concrete_model_cls.mro()[1:]:
|
||||
if (issubclass(model_cls, Model)
|
||||
and hasattr(model_cls, '_meta')
|
||||
and model_cls._meta.abstract):
|
||||
modules[model_cls.__module__].add(model_cls)
|
||||
return modules
|
||||
|
||||
def get_model_class_by_fullname(self, fullname: str) -> Optional[Type[Model]]:
|
||||
# Returns None if Model is abstract
|
||||
module, _, model_cls_name = fullname.rpartition('.')
|
||||
for model_cls in self.model_modules.get(module, []):
|
||||
for model_cls in self.model_modules.get(module, set()):
|
||||
if model_cls.__name__ == model_cls_name:
|
||||
return model_cls
|
||||
return None
|
||||
@@ -209,10 +234,11 @@ class DjangoContext:
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
|
||||
expected_types = {}
|
||||
# add pk
|
||||
primary_key_field = self.get_primary_key_field(model_cls)
|
||||
field_set_type = self.fields_context.get_field_set_type(api, primary_key_field, method=method)
|
||||
expected_types['pk'] = field_set_type
|
||||
# add pk if not abstract=True
|
||||
if not model_cls._meta.abstract:
|
||||
primary_key_field = self.get_primary_key_field(model_cls)
|
||||
field_set_type = self.fields_context.get_field_set_type(api, primary_key_field, method=method)
|
||||
expected_types['pk'] = field_set_type
|
||||
|
||||
for field in model_cls._meta.get_fields():
|
||||
if isinstance(field, Field):
|
||||
@@ -228,9 +254,9 @@ class DjangoContext:
|
||||
expected_types[field_name] = AnyType(TypeOfAny.unannotated)
|
||||
continue
|
||||
|
||||
related_model = field.related_model
|
||||
if related_model._meta.proxy_for_model:
|
||||
related_model = field.related_model._meta.proxy_for_model
|
||||
related_model = self.fields_context.get_related_model_cls(field)
|
||||
if related_model._meta.proxy_for_model is not None:
|
||||
related_model = related_model._meta.proxy_for_model
|
||||
|
||||
related_model_info = helpers.lookup_class_typeinfo(api, related_model)
|
||||
if related_model_info is None:
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
from collections import OrderedDict
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Union, cast
|
||||
from typing import Any, Dict, List, Optional, Set, TYPE_CHECKING, Union, cast
|
||||
|
||||
from mypy import checker
|
||||
from mypy.checker import TypeChecker
|
||||
from mypy.mro import calculate_mro
|
||||
from mypy.nodes import (
|
||||
GDEF, MDEF, Block, ClassDef, Expression, MemberExpr, MypyFile, NameExpr, StrExpr, SymbolNode, SymbolTable,
|
||||
SymbolTableNode, TypeInfo, Var,
|
||||
)
|
||||
from mypy.nodes import (Block, ClassDef, Expression, GDEF, MDEF, MemberExpr, MypyFile, NameExpr, StrExpr, SymbolNode,
|
||||
SymbolTable, SymbolTableNode, TypeInfo, Var)
|
||||
from mypy.plugin import (
|
||||
AttributeContext, CheckerPluginInterface, FunctionContext, MethodContext,
|
||||
)
|
||||
from mypy.types import AnyType, Instance, NoneTyp, TupleType
|
||||
from mypy.types import Type as MypyType
|
||||
from mypy.types import TypedDictType, TypeOfAny, UnionType
|
||||
from mypy.types import AnyType, Instance, NoneTyp, TupleType, Type as MypyType, TypeOfAny, TypedDictType, UnionType
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from mypy_django_plugin.django.context import DjangoContext
|
||||
|
||||
@@ -7,7 +7,7 @@ from mypy.errors import Errors
|
||||
from mypy.nodes import MypyFile, TypeInfo
|
||||
from mypy.options import Options
|
||||
from mypy.plugin import (
|
||||
AnalyzeTypeContext, AttributeContext, ClassDefContext, FunctionContext, MethodContext, Plugin,
|
||||
AttributeContext, ClassDefContext, FunctionContext, MethodContext, Plugin,
|
||||
)
|
||||
from mypy.types import Type as MypyType
|
||||
|
||||
@@ -148,12 +148,14 @@ class NewSemanalDjangoPlugin(Plugin):
|
||||
# forward relations
|
||||
for field in self.django_context.get_model_fields(model_class):
|
||||
if isinstance(field, RelatedField):
|
||||
related_model_module = field.related_model.__module__
|
||||
related_model_cls = self.django_context.fields_context.get_related_model_cls(field)
|
||||
related_model_module = related_model_cls.__module__
|
||||
if related_model_module != file.fullname():
|
||||
deps.add(self._new_dependency(related_model_module))
|
||||
# reverse relations
|
||||
for relation in model_class._meta.related_objects:
|
||||
related_model_module = relation.related_model.__module__
|
||||
related_model_cls = self.django_context.fields_context.get_related_model_cls(relation)
|
||||
related_model_module = related_model_cls.__module__
|
||||
if related_model_module != file.fullname():
|
||||
deps.add(self._new_dependency(related_model_module))
|
||||
return list(deps)
|
||||
@@ -233,15 +235,6 @@ class NewSemanalDjangoPlugin(Plugin):
|
||||
return partial(request.set_auth_user_model_as_type_for_request_user, django_context=self.django_context)
|
||||
return None
|
||||
|
||||
def get_type_analyze_hook(self, fullname: str
|
||||
) -> Optional[Callable[[AnalyzeTypeContext], MypyType]]:
|
||||
info = self._get_typeinfo_or_none(fullname)
|
||||
if (info
|
||||
and info.has_base(fullnames.QUERYSET_CLASS_FULLNAME)
|
||||
and not info.has_base(fullnames.BASE_MANAGER_CLASS_FULLNAME)):
|
||||
return partial(querysets.set_first_generic_param_as_default_for_second, fullname=fullname)
|
||||
return None
|
||||
|
||||
|
||||
def plugin(version):
|
||||
return NewSemanalDjangoPlugin
|
||||
|
||||
@@ -44,9 +44,12 @@ def fill_descriptor_types_for_related_field(ctx: FunctionContext, django_context
|
||||
|
||||
assert isinstance(current_field, RelatedField)
|
||||
|
||||
related_model = related_model_to_set = current_field.related_model
|
||||
if related_model_to_set._meta.proxy_for_model:
|
||||
related_model_to_set = related_model._meta.proxy_for_model
|
||||
related_model_cls = django_context.fields_context.get_related_model_cls(current_field)
|
||||
|
||||
related_model = related_model_cls
|
||||
related_model_to_set = related_model_cls
|
||||
if related_model_to_set._meta.proxy_for_model is not None:
|
||||
related_model_to_set = related_model_to_set._meta.proxy_for_model
|
||||
|
||||
typechecker_api = helpers.get_typechecker_api(ctx)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ from mypy.types import Type as MypyType
|
||||
from mypy.types import TypeOfAny
|
||||
|
||||
from mypy_django_plugin.django.context import DjangoContext
|
||||
from mypy_django_plugin.lib import fullnames, helpers
|
||||
from mypy_django_plugin.lib import helpers
|
||||
|
||||
|
||||
def _get_field_instance(ctx: MethodContext, field_fullname: str) -> MypyType:
|
||||
@@ -20,26 +20,32 @@ def return_proper_field_type_from_get_field(ctx: MethodContext, django_context:
|
||||
# Options instance
|
||||
assert isinstance(ctx.type, Instance)
|
||||
|
||||
# bail if list of generic params is empty
|
||||
if len(ctx.type.args) == 0:
|
||||
return ctx.default_return_type
|
||||
|
||||
model_type = ctx.type.args[0]
|
||||
if not isinstance(model_type, Instance):
|
||||
return _get_field_instance(ctx, fullnames.FIELD_FULLNAME)
|
||||
return ctx.default_return_type
|
||||
|
||||
model_cls = django_context.get_model_class_by_fullname(model_type.type.fullname())
|
||||
if model_cls is None:
|
||||
return _get_field_instance(ctx, fullnames.FIELD_FULLNAME)
|
||||
return ctx.default_return_type
|
||||
|
||||
field_name_expr = helpers.get_call_argument_by_name(ctx, 'field_name')
|
||||
if field_name_expr is None:
|
||||
return _get_field_instance(ctx, fullnames.FIELD_FULLNAME)
|
||||
return ctx.default_return_type
|
||||
|
||||
field_name = helpers.resolve_string_attribute_value(field_name_expr, ctx, django_context)
|
||||
if field_name is None:
|
||||
return _get_field_instance(ctx, fullnames.FIELD_FULLNAME)
|
||||
return ctx.default_return_type
|
||||
|
||||
try:
|
||||
field = model_cls._meta.get_field(field_name)
|
||||
except FieldDoesNotExist as exc:
|
||||
ctx.api.fail(exc.args[0], ctx.context)
|
||||
# if model is abstract, do not raise exception, skip false positives
|
||||
if not model_cls._meta.abstract:
|
||||
ctx.api.fail(exc.args[0], ctx.context)
|
||||
return AnyType(TypeOfAny.from_error)
|
||||
|
||||
field_fullname = helpers.get_class_fullname(field.__class__)
|
||||
|
||||
@@ -100,7 +100,8 @@ class AddRelatedModelsId(ModelClassInitializer):
|
||||
def run_with_model_cls(self, model_cls: Type[Model]) -> None:
|
||||
for field in model_cls._meta.get_fields():
|
||||
if isinstance(field, ForeignKey):
|
||||
rel_primary_key_field = self.django_context.get_primary_key_field(field.related_model)
|
||||
related_model_cls = self.django_context.fields_context.get_related_model_cls(field)
|
||||
rel_primary_key_field = self.django_context.get_primary_key_field(related_model_cls)
|
||||
field_info = self.lookup_class_typeinfo_or_incomplete_defn_error(rel_primary_key_field.__class__)
|
||||
is_nullable = self.django_context.fields_context.get_field_nullability(field, None)
|
||||
set_type, get_type = get_field_descriptor_types(field_info, is_nullable)
|
||||
@@ -156,7 +157,8 @@ class AddManagers(ModelClassInitializer):
|
||||
# no reverse accessor
|
||||
continue
|
||||
|
||||
related_model_info = self.lookup_class_typeinfo_or_incomplete_defn_error(relation.related_model)
|
||||
related_model_cls = self.django_context.fields_context.get_related_model_cls(relation)
|
||||
related_model_info = self.lookup_class_typeinfo_or_incomplete_defn_error(related_model_cls)
|
||||
|
||||
if isinstance(relation, OneToOneRel):
|
||||
self.add_new_node_to_model_class(attname, Instance(related_model_info, []))
|
||||
|
||||
@@ -1,20 +1,26 @@
|
||||
from collections import OrderedDict
|
||||
from typing import List, Optional, Sequence, Type, Union, cast
|
||||
from typing import List, Optional, Sequence, Type, Union
|
||||
|
||||
from django.core.exceptions import FieldError
|
||||
from django.db.models.base import Model
|
||||
from mypy.newsemanal.typeanal import TypeAnalyser
|
||||
from mypy.nodes import Expression, NameExpr, TypeInfo
|
||||
from mypy.plugin import AnalyzeTypeContext, FunctionContext, MethodContext
|
||||
from mypy.types import AnyType, Instance
|
||||
from mypy.types import Type as MypyType
|
||||
from mypy.types import TypeOfAny
|
||||
|
||||
from django.db.models.fields.related import RelatedField
|
||||
from mypy.nodes import Expression, NameExpr
|
||||
from mypy.plugin import FunctionContext, MethodContext
|
||||
from mypy.types import AnyType, Instance, Type as MypyType, TypeOfAny
|
||||
|
||||
from mypy_django_plugin.django.context import DjangoContext
|
||||
from mypy_django_plugin.lib import fullnames, helpers
|
||||
|
||||
|
||||
def _extract_model_type_from_queryset(queryset_type: Instance) -> Optional[Instance]:
|
||||
for base_type in [queryset_type, *queryset_type.type.bases]:
|
||||
if (len(base_type.args)
|
||||
and isinstance(base_type.args[0], Instance)
|
||||
and base_type.args[0].type.has_base(fullnames.MODEL_CLASS_FULLNAME)):
|
||||
return base_type.args[0]
|
||||
return None
|
||||
|
||||
|
||||
def determine_proper_manager_type(ctx: FunctionContext) -> MypyType:
|
||||
default_return_type = ctx.default_return_type
|
||||
assert isinstance(default_return_type, Instance)
|
||||
@@ -36,7 +42,8 @@ def get_field_type_from_lookup(ctx: MethodContext, django_context: DjangoContext
|
||||
return None
|
||||
|
||||
if isinstance(lookup_field, RelatedField) and lookup_field.column == lookup:
|
||||
lookup_field = django_context.get_primary_key_field(lookup_field.related_model)
|
||||
related_model_cls = django_context.fields_context.get_related_model_cls(lookup_field)
|
||||
lookup_field = django_context.get_primary_key_field(related_model_cls)
|
||||
|
||||
field_get_type = django_context.fields_context.get_field_get_type(helpers.get_typechecker_api(ctx),
|
||||
lookup_field, method=method)
|
||||
@@ -98,11 +105,10 @@ def extract_proper_type_queryset_values_list(ctx: MethodContext, django_context:
|
||||
assert isinstance(ctx.type, Instance)
|
||||
assert isinstance(ctx.default_return_type, Instance)
|
||||
|
||||
# bail if queryset of Any or other non-instances
|
||||
if not isinstance(ctx.type.args[0], Instance):
|
||||
model_type = _extract_model_type_from_queryset(ctx.type)
|
||||
if model_type is None:
|
||||
return AnyType(TypeOfAny.from_omitted_generics)
|
||||
|
||||
model_type = ctx.type.args[0]
|
||||
model_cls = django_context.get_model_class_by_fullname(model_type.type.fullname())
|
||||
if model_cls is None:
|
||||
return ctx.default_return_type
|
||||
@@ -148,11 +154,10 @@ def extract_proper_type_queryset_values(ctx: MethodContext, django_context: Djan
|
||||
assert isinstance(ctx.type, Instance)
|
||||
assert isinstance(ctx.default_return_type, Instance)
|
||||
|
||||
# if queryset of non-instance type
|
||||
if not isinstance(ctx.type.args[0], Instance):
|
||||
model_type = _extract_model_type_from_queryset(ctx.type)
|
||||
if model_type is None:
|
||||
return AnyType(TypeOfAny.from_omitted_generics)
|
||||
|
||||
model_type = ctx.type.args[0]
|
||||
model_cls = django_context.get_model_class_by_fullname(model_type.type.fullname())
|
||||
if model_cls is None:
|
||||
return ctx.default_return_type
|
||||
@@ -176,20 +181,3 @@ def extract_proper_type_queryset_values(ctx: MethodContext, django_context: Djan
|
||||
|
||||
row_type = helpers.make_typeddict(ctx.api, column_types, set(column_types.keys()))
|
||||
return helpers.reparametrize_instance(ctx.default_return_type, [model_type, row_type])
|
||||
|
||||
|
||||
def set_first_generic_param_as_default_for_second(ctx: AnalyzeTypeContext, fullname: str) -> MypyType:
|
||||
type_analyser_api = cast(TypeAnalyser, ctx.api)
|
||||
|
||||
info = helpers.lookup_fully_qualified_typeinfo(type_analyser_api.api, fullname) # type: ignore
|
||||
assert isinstance(info, TypeInfo)
|
||||
|
||||
if not ctx.type.args:
|
||||
return Instance(info, [AnyType(TypeOfAny.explicit), AnyType(TypeOfAny.explicit)])
|
||||
|
||||
args = ctx.type.args
|
||||
if len(args) == 1:
|
||||
args = [args[0], args[0]]
|
||||
|
||||
analyzed_args = [type_analyser_api.analyze_type(arg) for arg in args]
|
||||
return Instance(info, analyzed_args)
|
||||
|
||||
@@ -28,7 +28,6 @@ IGNORED_ERRORS = {
|
||||
'Cannot assign to a type',
|
||||
'"HttpResponse" has no attribute',
|
||||
'"HttpResponseBase" has no attribute',
|
||||
# '"HttpRequest" has no attribute',
|
||||
'"object" has no attribute',
|
||||
'defined in the current module',
|
||||
re.compile(r'"Callable\[(\[(Any(, )?)*((, )?VarArg\(Any\))?((, )?KwArg\(Any\))?\]|\.\.\.), Any\]" '
|
||||
@@ -73,6 +72,12 @@ IGNORED_ERRORS = {
|
||||
'Incompatible types in assignment (expression has type "Callable[',
|
||||
'SimpleLazyObject'
|
||||
],
|
||||
'aggregation': [
|
||||
re.compile(r'got "Optional\[(Author|Publisher)\]", expected "Union\[(Author|Publisher), Combinable\]"')
|
||||
],
|
||||
'annotations': [
|
||||
'Incompatible type for "store" of "Employee" (got "Optional[Store]", expected "Union[Store, Combinable]")'
|
||||
],
|
||||
'apps': [
|
||||
'Incompatible types in assignment (expression has type "str", target has type "type")',
|
||||
],
|
||||
@@ -90,7 +95,8 @@ IGNORED_ERRORS = {
|
||||
'basic': [
|
||||
'Unexpected keyword argument "unknown_kwarg" for "refresh_from_db" of "Model"',
|
||||
'Unexpected attribute "foo" for model "Article"',
|
||||
'has no attribute "touched"'
|
||||
'has no attribute "touched"',
|
||||
'Incompatible types in assignment (expression has type "Type[CustomQuerySet]"'
|
||||
],
|
||||
'backends': [
|
||||
'"DatabaseError" has no attribute "pgcode"'
|
||||
@@ -114,14 +120,15 @@ IGNORED_ERRORS = {
|
||||
'custom_managers': [
|
||||
'Unsupported dynamic base class',
|
||||
'"Book" has no attribute "favorite_avg"',
|
||||
'Incompatible types in assignment (expression has type "CharField'
|
||||
'Incompatible types in assignment (expression has type "CharField',
|
||||
'Item "Book" of "Optional[Book]" has no attribute "favorite_avg"'
|
||||
],
|
||||
'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"',
|
||||
'Too few arguments for "dates" of',
|
||||
],
|
||||
'defer': [
|
||||
'Too many arguments for "refresh_from_db" of "Model"'
|
||||
@@ -135,6 +142,7 @@ IGNORED_ERRORS = {
|
||||
],
|
||||
'db_functions': [
|
||||
'"FloatModel" has no attribute',
|
||||
'Incompatible types in assignment (expression has type "Optional[Any]", variable has type "FloatModel")'
|
||||
],
|
||||
'decorators': [
|
||||
'"Type[object]" has no attribute "method"'
|
||||
@@ -164,9 +172,9 @@ IGNORED_ERRORS = {
|
||||
],
|
||||
'get_object_or_404': [
|
||||
'Argument 1 to "get_object_or_404" has incompatible type "str"; '
|
||||
+ 'expected "Union[Type[<nothing>], QuerySet[<nothing>, <nothing>]]"',
|
||||
+ 'expected "Union[Type[<nothing>], QuerySet[<nothing>]]"',
|
||||
'Argument 1 to "get_list_or_404" has incompatible type "List[Type[Article]]"; '
|
||||
+ 'expected "Union[Type[<nothing>], QuerySet[<nothing>, <nothing>]]"',
|
||||
+ 'expected "Union[Type[<nothing>], QuerySet[<nothing>]]"',
|
||||
'CustomClass'
|
||||
],
|
||||
'generic_relations_regress': [
|
||||
@@ -181,7 +189,7 @@ IGNORED_ERRORS = {
|
||||
'Argument 1 to "append" of "list" has incompatible type "None"; expected "str"'
|
||||
],
|
||||
'lookup': [
|
||||
'Unexpected keyword argument "headline__startswith" for "in_bulk" of "QuerySet"',
|
||||
'Unexpected keyword argument "headline__startswith" for "in_bulk" of',
|
||||
'is called with more than one field'
|
||||
],
|
||||
'messages_tests': [
|
||||
@@ -234,7 +242,9 @@ IGNORED_ERRORS = {
|
||||
'"Dimension" has no attribute "set_component_order"',
|
||||
],
|
||||
'one_to_one': [
|
||||
'expression has type "None", variable has type "UndergroundBar"'
|
||||
'expression has type "None", variable has type "UndergroundBar"',
|
||||
'Item "OneToOneField[Union[Place, Combinable], Place]" '
|
||||
+ 'of "Union[OneToOneField[Union[Place, Combinable], Place], Any]"',
|
||||
],
|
||||
'postgres_tests': [
|
||||
'DummyArrayField',
|
||||
@@ -255,9 +265,10 @@ IGNORED_ERRORS = {
|
||||
'"Person" has no attribute "houses_lst"',
|
||||
'"Book" has no attribute "first_authors"',
|
||||
'"Book" has no attribute "the_authors"',
|
||||
'Incompatible types in assignment (expression has type "List[Room]", variable has type "QuerySet[Room, Room]")',
|
||||
'"Room" has no attribute "main_room_of_attr"',
|
||||
'"Room" has no attribute "house_attr"'
|
||||
'Incompatible types in assignment (expression has type "List[Room]", variable has type "Manager[Room]")',
|
||||
'Item "Room" of "Optional[Room]" has no attribute "house_attr"',
|
||||
'Item "Room" of "Optional[Room]" has no attribute "main_room_of_attr"',
|
||||
'Argument 2 to "Prefetch" has incompatible type "ValuesQuerySet'
|
||||
],
|
||||
'proxy_models': [
|
||||
'Incompatible types in assignment',
|
||||
@@ -266,12 +277,13 @@ IGNORED_ERRORS = {
|
||||
'queries': [
|
||||
'Incompatible types in assignment (expression has type "None", variable has type "str")',
|
||||
'Invalid index type "Optional[str]" for "Dict[str, int]"; expected type "str"',
|
||||
'Unsupported operand types for & ("QuerySet[Author, Author]" and "QuerySet[Tag, Tag]")',
|
||||
'Unsupported operand types for | ("QuerySet[Author, Author]" and "QuerySet[Tag, Tag]")',
|
||||
'Unsupported operand types for & ("Manager[Author]" and "Manager[Tag]")',
|
||||
'Unsupported operand types for | ("Manager[Author]" and "Manager[Tag]")',
|
||||
'ObjectA',
|
||||
'ObjectB',
|
||||
'ObjectC',
|
||||
"'flat' and 'named' can't be used together",
|
||||
'"Collection[Any]" has no attribute "explain"'
|
||||
],
|
||||
'requests': [
|
||||
'Incompatible types in assignment (expression has type "Dict[str, str]", variable has type "QueryDict")'
|
||||
@@ -285,6 +297,9 @@ IGNORED_ERRORS = {
|
||||
'signals': [
|
||||
'Argument 1 to "append" of "list" has incompatible type "Tuple[Any, Any, Optional[Any], Any]";'
|
||||
],
|
||||
'sites_framework': [
|
||||
'expression has type "CurrentSiteManager[CustomArticle]", base class "AbstractArticle"'
|
||||
],
|
||||
'syndication_tests': [
|
||||
'List or tuple expected as variable arguments'
|
||||
],
|
||||
@@ -293,6 +308,10 @@ IGNORED_ERRORS = {
|
||||
'Incompatible types in assignment (expression has type "None", variable has type "int")',
|
||||
'"AbstractBaseSession" has no attribute'
|
||||
],
|
||||
'select_related': [
|
||||
'Item "ForeignKey[Union[Genus, Combinable], Genus]" '
|
||||
+ 'of "Union[ForeignKey[Union[Genus, Combinable], Genus], Any]"'
|
||||
],
|
||||
'select_related_onetoone': [
|
||||
'Incompatible types in assignment (expression has type "Parent2", variable has type "Parent1")',
|
||||
'"Parent1" has no attribute'
|
||||
|
||||
12
setup.cfg
12
setup.cfg
@@ -1,17 +1,17 @@
|
||||
[isort]
|
||||
skip =
|
||||
django-sources,
|
||||
django-stubs,
|
||||
test-data
|
||||
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
|
||||
django-sources
|
||||
django-stubs
|
||||
test-data
|
||||
max_line_length = 120
|
||||
|
||||
[metadata]
|
||||
|
||||
2
setup.py
2
setup.py
@@ -28,7 +28,7 @@ dependencies = [
|
||||
|
||||
setup(
|
||||
name="django-stubs",
|
||||
version="1.0.1",
|
||||
version="1.1.0",
|
||||
description='Mypy stubs for Django',
|
||||
long_description=readme,
|
||||
long_description_content_type='text/markdown',
|
||||
|
||||
@@ -519,4 +519,56 @@
|
||||
class Book(Entry):
|
||||
pass
|
||||
class Article(Entry):
|
||||
pass
|
||||
|
||||
|
||||
- case: test_related_fields_returned_as_descriptors_from_model_class
|
||||
main: |
|
||||
from myapp.models import Author, Blog, Publisher, Profile
|
||||
reveal_type(Author.blogs) # N: Revealed type is 'django.db.models.fields.related_descriptors.ManyToManyDescriptor'
|
||||
reveal_type(Blog.publisher) # N: Revealed type is 'django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor'
|
||||
reveal_type(Publisher.profile) # N: Revealed type is 'django.db.models.fields.related_descriptors.ForwardOneToOneDescriptor'
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
- path: myapp/__init__.py
|
||||
- path: myapp/models.py
|
||||
content: |
|
||||
from django.db import models
|
||||
class Profile(models.Model):
|
||||
pass
|
||||
class Publisher(models.Model):
|
||||
profile = models.OneToOneField(Profile, on_delete=models.CASCADE)
|
||||
class Blog(models.Model):
|
||||
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
|
||||
class Author(models.Model):
|
||||
blogs = models.ManyToManyField(Blog)
|
||||
file = models.FileField()
|
||||
|
||||
|
||||
- case: test_foreign_key_from_superclass_inherits_correctly
|
||||
main: |
|
||||
from myapp.models import MyUser, Book, Article, LibraryEntity
|
||||
reveal_type(Book().registered_by_user) # N: Revealed type is 'myapp.models.MyUser*'
|
||||
reveal_type(Article().registered_by_user) # N: Revealed type is 'myapp.models.MyUser*'
|
||||
|
||||
user = MyUser()
|
||||
reveal_type(user.book_set) # N: Revealed type is 'django.db.models.manager.RelatedManager[myapp.models.Book]'
|
||||
reveal_type(user.article_set) # N: Revealed type is 'django.db.models.manager.RelatedManager[myapp.models.Article]'
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
- path: myapp/__init__.py
|
||||
- path: myapp/models.py
|
||||
content: |
|
||||
from django.db import models
|
||||
class MyUser(models.Model):
|
||||
pass
|
||||
class LibraryEntity(models.Model):
|
||||
class Meta:
|
||||
abstract = True
|
||||
registered_by_user = models.ForeignKey(MyUser, on_delete=models.CASCADE)
|
||||
class Book(LibraryEntity):
|
||||
pass
|
||||
class Article(LibraryEntity):
|
||||
pass
|
||||
@@ -3,22 +3,22 @@
|
||||
from myapp.models import Blog
|
||||
|
||||
qs = Blog.objects.all()
|
||||
reveal_type(qs) # N: Revealed type is 'django.db.models.query.QuerySet[myapp.models.Blog*, myapp.models.Blog*]'
|
||||
reveal_type(qs) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.Blog]'
|
||||
reveal_type(qs.get(id=1)) # N: Revealed type is 'myapp.models.Blog*'
|
||||
reveal_type(iter(qs)) # N: Revealed type is 'typing.Iterator[myapp.models.Blog*]'
|
||||
reveal_type(qs.iterator()) # N: Revealed type is 'typing.Iterator[myapp.models.Blog*]'
|
||||
reveal_type(qs.first()) # N: Revealed type is 'myapp.models.Blog*'
|
||||
reveal_type(qs.first()) # N: Revealed type is 'Union[myapp.models.Blog*, None]'
|
||||
reveal_type(qs.earliest()) # N: Revealed type is 'myapp.models.Blog*'
|
||||
reveal_type(qs[0]) # N: Revealed type is 'myapp.models.Blog*'
|
||||
reveal_type(qs[:9]) # N: Revealed type is 'django.db.models.query.QuerySet[myapp.models.Blog*, myapp.models.Blog*]'
|
||||
reveal_type(qs[:9]) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.Blog]'
|
||||
reveal_type(qs.in_bulk()) # N: Revealed type is 'builtins.dict[Any, myapp.models.Blog*]'
|
||||
|
||||
# .dates / .datetimes
|
||||
reveal_type(Blog.objects.dates("created_at", "day")) # N: Revealed type is 'django.db.models.query.QuerySet[myapp.models.Blog*, datetime.date]'
|
||||
reveal_type(Blog.objects.datetimes("created_at", "day")) # N: Revealed type is 'django.db.models.query.QuerySet[myapp.models.Blog*, datetime.datetime]'
|
||||
reveal_type(Blog.objects.dates("created_at", "day")) # N: Revealed type is 'django.db.models.query.ValuesQuerySet[myapp.models.Blog*, datetime.date]'
|
||||
reveal_type(Blog.objects.datetimes("created_at", "day")) # N: Revealed type is 'django.db.models.query.ValuesQuerySet[myapp.models.Blog*, datetime.datetime]'
|
||||
|
||||
# AND-ing QuerySets
|
||||
reveal_type(Blog.objects.all() & Blog.objects.all()) # N: Revealed type is 'django.db.models.query.QuerySet[myapp.models.Blog*, myapp.models.Blog*]'
|
||||
reveal_type(Blog.objects.all() & Blog.objects.all()) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.Blog]'
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
@@ -28,11 +28,4 @@
|
||||
from django.db import models
|
||||
|
||||
class Blog(models.Model):
|
||||
created_at = models.DateTimeField()
|
||||
|
||||
- case: queryset_could_be_specified_with_one_type
|
||||
main: |
|
||||
from typing import Optional
|
||||
from django.db import models
|
||||
queryset: models.QuerySet[models.Model] = models.QuerySet()
|
||||
reveal_type(queryset) # N: Revealed type is 'django.db.models.query.QuerySet[django.db.models.base.Model, django.db.models.base.Model]'
|
||||
created_at = models.DateTimeField()
|
||||
@@ -53,7 +53,7 @@
|
||||
text = models.CharField(max_length=100)
|
||||
blog = models.ForeignKey(to=Blog, on_delete=models.CASCADE)
|
||||
|
||||
- case: values_list_flat_true
|
||||
- case: values_list_flat_true_methods
|
||||
main: |
|
||||
from myapp.models import MyUser, MyUser2
|
||||
reveal_type(MyUser.objects.values_list('name', flat=True).get()) # N: Revealed type is 'builtins.str*'
|
||||
@@ -192,8 +192,10 @@
|
||||
- case: values_list_flat_true_with_ids
|
||||
main: |
|
||||
from myapp.models import Blog, Publisher
|
||||
reveal_type(Blog.objects.values_list('id', flat=True)) # N: Revealed type is 'django.db.models.query.QuerySet[myapp.models.Blog, builtins.int]'
|
||||
reveal_type(Blog.objects.values_list('publisher_id', flat=True)) # N: Revealed type is 'django.db.models.query.QuerySet[myapp.models.Blog, builtins.int]'
|
||||
reveal_type(Blog.objects.values_list('id', flat=True)) # N: Revealed type is 'django.db.models.query.ValuesQuerySet[myapp.models.Blog, builtins.int]'
|
||||
reveal_type(Blog.objects.values_list('publisher_id', flat=True)) # N: Revealed type is 'django.db.models.query.ValuesQuerySet[myapp.models.Blog, builtins.int]'
|
||||
# is Iterable[int]
|
||||
reveal_type(list(Blog.objects.values_list('id', flat=True))) # N: Revealed type is 'builtins.list[builtins.int*]'
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
@@ -204,4 +206,22 @@
|
||||
class Publisher(models.Model):
|
||||
pass
|
||||
class Blog(models.Model):
|
||||
publisher = models.ForeignKey(to=Publisher, on_delete=models.CASCADE)
|
||||
publisher = models.ForeignKey(to=Publisher, on_delete=models.CASCADE)
|
||||
|
||||
- case: subclass_of_queryset_has_proper_typings_on_methods
|
||||
main: |
|
||||
from myapp.models import TransactionQuerySet
|
||||
reveal_type(TransactionQuerySet()) # N: Revealed type is 'myapp.models.TransactionQuerySet'
|
||||
reveal_type(TransactionQuerySet().values()) # N: Revealed type is 'django.db.models.query.ValuesQuerySet[myapp.models.Transaction, TypedDict({'id': builtins.int, 'total': builtins.int})]'
|
||||
reveal_type(TransactionQuerySet().values_list()) # N: Revealed type is 'django.db.models.query.ValuesQuerySet[myapp.models.Transaction, Tuple[builtins.int, builtins.int]]'
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
- path: myapp/__init__.py
|
||||
- path: myapp/models.py
|
||||
content: |
|
||||
from django.db import models
|
||||
class TransactionQuerySet(models.QuerySet['Transaction']):
|
||||
pass
|
||||
class Transaction(models.Model):
|
||||
total = models.IntegerField()
|
||||
|
||||
@@ -197,10 +197,10 @@
|
||||
main: |
|
||||
from myapp.models import UnrelatedModel, MyModel
|
||||
reveal_type(UnrelatedModel.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.UnrelatedModel]'
|
||||
reveal_type(UnrelatedModel.objects.first()) # N: Revealed type is 'myapp.models.UnrelatedModel*'
|
||||
reveal_type(UnrelatedModel.objects.first()) # N: Revealed type is 'Union[myapp.models.UnrelatedModel*, None]'
|
||||
|
||||
reveal_type(MyModel.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel]'
|
||||
reveal_type(MyModel.objects.first()) # N: Revealed type is 'myapp.models.MyModel*'
|
||||
reveal_type(MyModel.objects.first()) # N: Revealed type is 'Union[myapp.models.MyModel*, None]'
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
@@ -218,10 +218,10 @@
|
||||
main: |
|
||||
from myapp.models import UnrelatedModel2, MyModel2
|
||||
reveal_type(UnrelatedModel2.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.UnrelatedModel2]'
|
||||
reveal_type(UnrelatedModel2.objects.first()) # N: Revealed type is 'myapp.models.UnrelatedModel2*'
|
||||
reveal_type(UnrelatedModel2.objects.first()) # N: Revealed type is 'Union[myapp.models.UnrelatedModel2*, None]'
|
||||
|
||||
reveal_type(MyModel2.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel2]'
|
||||
reveal_type(MyModel2.objects.first()) # N: Revealed type is 'myapp.models.MyModel2*'
|
||||
reveal_type(MyModel2.objects.first()) # N: Revealed type is 'Union[myapp.models.MyModel2*, None]'
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
@@ -239,10 +239,10 @@
|
||||
main: |
|
||||
from myapp.models import ParentOfMyModel3, MyModel3
|
||||
reveal_type(ParentOfMyModel3.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.ParentOfMyModel3]'
|
||||
reveal_type(ParentOfMyModel3.objects.first()) # N: Revealed type is 'myapp.models.ParentOfMyModel3*'
|
||||
reveal_type(ParentOfMyModel3.objects.first()) # N: Revealed type is 'Union[myapp.models.ParentOfMyModel3*, None]'
|
||||
|
||||
reveal_type(MyModel3.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel3]'
|
||||
reveal_type(MyModel3.objects.first()) # N: Revealed type is 'myapp.models.MyModel3*'
|
||||
reveal_type(MyModel3.objects.first()) # N: Revealed type is 'Union[myapp.models.MyModel3*, None]'
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
@@ -260,10 +260,10 @@
|
||||
main: |
|
||||
from myapp.models import ParentOfMyModel4, MyModel4
|
||||
reveal_type(ParentOfMyModel4.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.ParentOfMyModel4]'
|
||||
reveal_type(ParentOfMyModel4.objects.first()) # N: Revealed type is 'myapp.models.ParentOfMyModel4*'
|
||||
reveal_type(ParentOfMyModel4.objects.first()) # N: Revealed type is 'Union[myapp.models.ParentOfMyModel4*, None]'
|
||||
|
||||
reveal_type(MyModel4.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel4]'
|
||||
reveal_type(MyModel4.objects.first()) # N: Revealed type is 'myapp.models.MyModel4*'
|
||||
reveal_type(MyModel4.objects.first()) # N: Revealed type is 'Union[myapp.models.MyModel4*, None]'
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
@@ -308,7 +308,7 @@
|
||||
main: |
|
||||
from myapp.models import User
|
||||
reveal_type(User.objects.get()) # N: Revealed type is 'myapp.models.User*'
|
||||
reveal_type(User.objects.select_related()) # N: Revealed type is 'django.db.models.query.QuerySet[myapp.models.User*, myapp.models.User*]'
|
||||
reveal_type(User.objects.select_related()) # N: Revealed type is 'myapp.models.User_MyManager[myapp.models.User]'
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
|
||||
@@ -233,3 +233,25 @@
|
||||
name = models.CharField(primary_key=True, max_length=100)
|
||||
class Book(models.Model):
|
||||
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
|
||||
|
||||
|
||||
- case: init_in_abstract_model_classmethod_should_not_throw_error_for_valid_fields
|
||||
main: |
|
||||
from myapp.models import MyModel
|
||||
MyModel.base_init()
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
- path: myapp/__init__.py
|
||||
- path: myapp/models.py
|
||||
content: |
|
||||
from django.db import models
|
||||
class AbstractModel(models.Model):
|
||||
class Meta:
|
||||
abstract = True
|
||||
text = models.CharField(max_length=100)
|
||||
@classmethod
|
||||
def base_init(cls) -> 'AbstractModel':
|
||||
return cls(text='mytext')
|
||||
class MyModel(AbstractModel):
|
||||
pass
|
||||
@@ -36,3 +36,23 @@
|
||||
name = models.CharField(max_length=100)
|
||||
age = models.IntegerField()
|
||||
to_user = models.ForeignKey('self', on_delete=models.SET_NULL)
|
||||
|
||||
- case: get_field_with_abstract_inheritance
|
||||
main: |
|
||||
from myapp.models import AbstractModel
|
||||
class MyModel(AbstractModel):
|
||||
pass
|
||||
reveal_type(MyModel._meta.get_field('field')) # N: Revealed type is 'Any'
|
||||
installed_apps:
|
||||
- myapp
|
||||
files:
|
||||
- path: myapp/__init__.py
|
||||
- path: myapp/models.py
|
||||
content: |
|
||||
from django.db import models
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
class AbstractModel(models.Model):
|
||||
class Meta:
|
||||
abstract = True
|
||||
class MyModel(AbstractModel):
|
||||
field = ArrayField(models.IntegerField(), default=[])
|
||||
|
||||
Reference in New Issue
Block a user