mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-10 22:11:54 +08:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7e1cfc6c7 | ||
|
|
d0c25e3bce | ||
|
|
1c31e71ffc | ||
|
|
6b3b6be3c1 | ||
|
|
5832605053 | ||
|
|
31e795016f | ||
|
|
0cba3f9fd6 | ||
|
|
f02050911f | ||
|
|
e8e6fca78c | ||
|
|
ade48b6546 | ||
|
|
b8f29027d8 | ||
|
|
eba3f6cb15 | ||
|
|
5a45544e76 | ||
|
|
8c2de7da56 | ||
|
|
d43c6dc7e2 | ||
|
|
f7e2109e06 | ||
|
|
cea62abf5a | ||
|
|
3b69ec6a72 | ||
|
|
7e794534c0 | ||
|
|
f5f33b061d | ||
|
|
58b26fdbd3 | ||
|
|
9ca79c24a2 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@ pip-wheel-metadata/
|
|||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
/.envrc
|
/.envrc
|
||||||
/.direnv
|
/.direnv
|
||||||
|
django-sources/
|
||||||
@@ -11,19 +11,16 @@ jobs:
|
|||||||
- name: Typecheck Django 3.0 test suite with python 3.7
|
- name: Typecheck Django 3.0 test suite with python 3.7
|
||||||
python: 3.7
|
python: 3.7
|
||||||
script: |
|
script: |
|
||||||
pip install Django==3.0.*
|
|
||||||
python ./scripts/typecheck_tests.py --django_version=3.0
|
python ./scripts/typecheck_tests.py --django_version=3.0
|
||||||
|
|
||||||
- name: Typecheck Django 3.0 test suite with python 3.6
|
- name: Typecheck Django 3.0 test suite with python 3.6
|
||||||
python: 3.6
|
python: 3.6
|
||||||
script: |
|
script: |
|
||||||
pip install Django==3.0.*
|
|
||||||
python ./scripts/typecheck_tests.py --django_version=3.0
|
python ./scripts/typecheck_tests.py --django_version=3.0
|
||||||
|
|
||||||
- name: Typecheck Django 2.2 test suite with python 3.7
|
- name: Typecheck Django 2.2 test suite with python 3.7
|
||||||
python: 3.7
|
python: 3.7
|
||||||
script: |
|
script: |
|
||||||
pip install Django==2.2.*
|
|
||||||
python ./scripts/typecheck_tests.py --django_version=2.2
|
python ./scripts/typecheck_tests.py --django_version=2.2
|
||||||
|
|
||||||
- name: Mypy for plugin code
|
- name: Mypy for plugin code
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
black
|
black
|
||||||
pytest-mypy-plugins==1.1.0
|
pytest-mypy-plugins==1.1.0
|
||||||
psycopg2
|
psycopg2
|
||||||
flake8==3.7.8
|
flake8==3.7.9
|
||||||
flake8-pyi==19.3.0
|
flake8-pyi==19.3.0
|
||||||
isort==4.3.21
|
isort==4.3.21
|
||||||
gitpython==3.0.5
|
gitpython==3.0.5
|
||||||
|
|||||||
@@ -1,24 +1,22 @@
|
|||||||
import threading
|
import threading
|
||||||
from collections import OrderedDict
|
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Type, Union
|
||||||
from typing import Any, Callable, DefaultDict, Dict, Iterable, List, Optional, Tuple, Type, Union
|
|
||||||
|
|
||||||
from django.db.migrations.state import AppConfigStub
|
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
|
|
||||||
from .config import AppConfig
|
from .config import AppConfig
|
||||||
|
|
||||||
class Apps:
|
class Apps:
|
||||||
all_models: Dict[str, OrderedDict[str, Type[Model]]] = ...
|
all_models: Dict[str, Dict[str, Type[Model]]] = ...
|
||||||
app_configs: OrderedDict[str, AppConfig] = ...
|
app_configs: Dict[str, AppConfig] = ...
|
||||||
stored_app_configs: List[Any] = ...
|
stored_app_configs: List[Any] = ...
|
||||||
apps_ready: bool = ...
|
apps_ready: bool = ...
|
||||||
ready_event: threading.Event = ...
|
ready_event: threading.Event = ...
|
||||||
loading: bool = ...
|
loading: bool = ...
|
||||||
_pending_operations: DefaultDict[Tuple[str, str], List]
|
_pending_operations: Dict[Tuple[str, str], List]
|
||||||
models_ready: bool = ...
|
models_ready: bool = ...
|
||||||
ready: bool = ...
|
ready: bool = ...
|
||||||
def __init__(self, installed_apps: Optional[Union[List[AppConfigStub], List[str], Tuple]] = ...) -> None: ...
|
def __init__(self, installed_apps: Optional[Iterable[Union[AppConfig, str]]] = ...) -> None: ...
|
||||||
def populate(self, installed_apps: Union[List[AppConfigStub], List[str], Tuple] = ...) -> None: ...
|
def populate(self, installed_apps: Iterable[Union[AppConfig, str]] = ...) -> None: ...
|
||||||
def check_apps_ready(self) -> None: ...
|
def check_apps_ready(self) -> None: ...
|
||||||
def check_models_ready(self) -> None: ...
|
def check_models_ready(self) -> None: ...
|
||||||
def get_app_configs(self) -> Iterable[AppConfig]: ...
|
def get_app_configs(self) -> Iterable[AppConfig]: ...
|
||||||
@@ -31,9 +29,9 @@ class Apps:
|
|||||||
def get_containing_app_config(self, object_name: str) -> Optional[AppConfig]: ...
|
def get_containing_app_config(self, object_name: str) -> Optional[AppConfig]: ...
|
||||||
def get_registered_model(self, app_label: str, model_name: str) -> Type[Model]: ...
|
def get_registered_model(self, app_label: str, model_name: str) -> Type[Model]: ...
|
||||||
def get_swappable_settings_name(self, to_string: str) -> Optional[str]: ...
|
def get_swappable_settings_name(self, to_string: str) -> Optional[str]: ...
|
||||||
def set_available_apps(self, available: List[str]) -> None: ...
|
def set_available_apps(self, available: Iterable[str]) -> None: ...
|
||||||
def unset_available_apps(self) -> None: ...
|
def unset_available_apps(self) -> None: ...
|
||||||
def set_installed_apps(self, installed: Union[List[str], Tuple[str]]) -> None: ...
|
def set_installed_apps(self, installed: Iterable[str]) -> None: ...
|
||||||
def unset_installed_apps(self) -> None: ...
|
def unset_installed_apps(self) -> None: ...
|
||||||
def clear_cache(self) -> None: ...
|
def clear_cache(self) -> None: ...
|
||||||
def lazy_model_operation(self, function: Callable, *model_keys: Any) -> None: ...
|
def lazy_model_operation(self, function: Callable, *model_keys: Any) -> None: ...
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
from typing import Any, List, Union
|
from typing import Any, List, Union, Iterable, Optional
|
||||||
|
|
||||||
from django.contrib.admin.options import BaseModelAdmin
|
from django.contrib.admin.options import BaseModelAdmin
|
||||||
from django.core.checks.messages import Error
|
from django.core.checks.messages import Error
|
||||||
|
|
||||||
|
from django.apps.config import AppConfig
|
||||||
|
|
||||||
_CheckError = Union[str, Error]
|
_CheckError = Union[str, Error]
|
||||||
|
|
||||||
def check_admin_app(app_configs: None, **kwargs: Any) -> List[_CheckError]: ...
|
def check_admin_app(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[_CheckError]: ...
|
||||||
def check_dependencies(**kwargs: Any) -> List[_CheckError]: ...
|
def check_dependencies(**kwargs: Any) -> List[_CheckError]: ...
|
||||||
|
|
||||||
class BaseModelAdminChecks:
|
class BaseModelAdminChecks:
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ from django.template.response import TemplateResponse
|
|||||||
from django.urls.resolvers import URLResolver
|
from django.urls.resolvers import URLResolver
|
||||||
from django.utils.functional import LazyObject
|
from django.utils.functional import LazyObject
|
||||||
|
|
||||||
|
from django.apps.config import AppConfig
|
||||||
|
|
||||||
all_sites: Any
|
all_sites: Any
|
||||||
|
|
||||||
class AlreadyRegistered(Exception): ...
|
class AlreadyRegistered(Exception): ...
|
||||||
@@ -28,7 +30,7 @@ class AdminSite:
|
|||||||
name: str = ...
|
name: str = ...
|
||||||
_registry: Dict[Type[Model], ModelAdmin]
|
_registry: Dict[Type[Model], ModelAdmin]
|
||||||
def __init__(self, name: str = ...) -> None: ...
|
def __init__(self, name: str = ...) -> None: ...
|
||||||
def check(self, app_configs: None) -> List[Any]: ...
|
def check(self, app_configs: Optional[Iterable[AppConfig]]) -> List[Any]: ...
|
||||||
def register(
|
def register(
|
||||||
self,
|
self,
|
||||||
model_or_iterable: Union[Type[Model], Iterable[Type[Model]]],
|
model_or_iterable: Union[Type[Model], Iterable[Type[Model]]],
|
||||||
@@ -37,7 +39,7 @@ class AdminSite:
|
|||||||
) -> None: ...
|
) -> None: ...
|
||||||
def unregister(self, model_or_iterable: Union[Type[Model], Iterable[Type[Model]]]) -> None: ...
|
def unregister(self, model_or_iterable: Union[Type[Model], Iterable[Type[Model]]]) -> None: ...
|
||||||
def is_registered(self, model: Type[Model]) -> bool: ...
|
def is_registered(self, model: Type[Model]) -> bool: ...
|
||||||
def add_action(self, action: Callable, name: None = ...) -> None: ...
|
def add_action(self, action: Callable, name: Optional[str] = ...) -> None: ...
|
||||||
def disable_action(self, name: str) -> None: ...
|
def disable_action(self, name: str) -> None: ...
|
||||||
def get_action(self, name: str) -> Callable: ...
|
def get_action(self, name: str) -> Callable: ...
|
||||||
@property
|
@property
|
||||||
@@ -52,14 +54,20 @@ class AdminSite:
|
|||||||
@property
|
@property
|
||||||
def urls(self) -> Tuple[List[URLResolver], str, str]: ...
|
def urls(self) -> Tuple[List[URLResolver], str, str]: ...
|
||||||
def each_context(self, request: Any): ...
|
def each_context(self, request: Any): ...
|
||||||
def password_change(self, request: WSGIRequest, extra_context: Dict[str, str] = ...) -> TemplateResponse: ...
|
def password_change(
|
||||||
def password_change_done(self, request: WSGIRequest, extra_context: None = ...) -> TemplateResponse: ...
|
self, request: WSGIRequest, extra_context: Optional[Dict[str, Any]] = ...
|
||||||
|
) -> TemplateResponse: ...
|
||||||
|
def password_change_done(
|
||||||
|
self, request: WSGIRequest, extra_context: Optional[Dict[str, Any]] = ...
|
||||||
|
) -> TemplateResponse: ...
|
||||||
def i18n_javascript(self, request: WSGIRequest, extra_context: Optional[Dict[Any, Any]] = ...) -> HttpResponse: ...
|
def i18n_javascript(self, request: WSGIRequest, extra_context: Optional[Dict[Any, Any]] = ...) -> HttpResponse: ...
|
||||||
def logout(self, request: WSGIRequest, extra_context: None = ...) -> TemplateResponse: ...
|
def logout(self, request: WSGIRequest, extra_context: Optional[Dict[str, Any]] = ...) -> TemplateResponse: ...
|
||||||
def login(self, request: WSGIRequest, extra_context: None = ...) -> HttpResponse: ...
|
def login(self, request: WSGIRequest, extra_context: Optional[Dict[str, Any]] = ...) -> HttpResponse: ...
|
||||||
def get_app_list(self, request: WSGIRequest) -> List[Any]: ...
|
def get_app_list(self, request: WSGIRequest) -> List[Any]: ...
|
||||||
def index(self, request: WSGIRequest, extra_context: Optional[Dict[str, str]] = ...) -> TemplateResponse: ...
|
def index(self, request: WSGIRequest, extra_context: Optional[Dict[str, Any]] = ...) -> TemplateResponse: ...
|
||||||
def app_index(self, request: WSGIRequest, app_label: str, extra_context: None = ...) -> TemplateResponse: ...
|
def app_index(
|
||||||
|
self, request: WSGIRequest, app_label: str, extra_context: Optional[Dict[str, Any]] = ...
|
||||||
|
) -> TemplateResponse: ...
|
||||||
|
|
||||||
class DefaultAdminSite(LazyObject): ...
|
class DefaultAdminSite(LazyObject): ...
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,10 @@ from django.contrib.auth.forms import AdminPasswordChangeForm
|
|||||||
from django.core.handlers.wsgi import WSGIRequest
|
from django.core.handlers.wsgi import WSGIRequest
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
from django.db.models.deletion import Collector
|
from django.db.models.deletion import Collector
|
||||||
from django.db.models.fields.mixins import FieldCacheMixin
|
|
||||||
from django.db.models.fields.reverse_related import ManyToOneRel
|
from django.db.models.fields.reverse_related import ManyToOneRel
|
||||||
from django.db.models.options import Options
|
from django.db.models.options import Options
|
||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from django.forms.forms import BaseForm
|
from django.forms.forms import BaseForm
|
||||||
from django.utils.safestring import SafeText
|
|
||||||
|
|
||||||
from django.db.models.fields import Field, reverse_related
|
from django.db.models.fields import Field, reverse_related
|
||||||
|
|
||||||
@@ -27,7 +25,7 @@ def unquote(s: str) -> str: ...
|
|||||||
def flatten(fields: Any) -> List[Union[Callable, str]]: ...
|
def flatten(fields: Any) -> List[Union[Callable, str]]: ...
|
||||||
def flatten_fieldsets(fieldsets: Any) -> List[Union[Callable, str]]: ...
|
def flatten_fieldsets(fieldsets: Any) -> List[Union[Callable, str]]: ...
|
||||||
def get_deleted_objects(
|
def get_deleted_objects(
|
||||||
objs: QuerySet, request: WSGIRequest, admin_site: AdminSite
|
objs: Sequence[Optional[Model]], request: WSGIRequest, admin_site: AdminSite
|
||||||
) -> Tuple[List[Any], Dict[Any, Any], Set[Any], List[Any]]: ...
|
) -> Tuple[List[Any], Dict[Any, Any], Set[Any], List[Any]]: ...
|
||||||
|
|
||||||
class NestedObjects(Collector):
|
class NestedObjects(Collector):
|
||||||
@@ -41,22 +39,14 @@ class NestedObjects(Collector):
|
|||||||
model_objs: Any = ...
|
model_objs: Any = ...
|
||||||
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
||||||
def add_edge(self, source: Optional[Model], target: Model) -> None: ...
|
def add_edge(self, source: Optional[Model], target: Model) -> None: ...
|
||||||
def collect(
|
def related_objects(self, related: ManyToOneRel, objs: Sequence[Optional[Model]]) -> QuerySet: ...
|
||||||
self,
|
def nested(self, format_callback: Callable = ...) -> List[Any]: ...
|
||||||
objs: Union[Sequence[Optional[Model]], QuerySet],
|
|
||||||
source: Optional[Type[Model]] = ...,
|
|
||||||
source_attr: Optional[str] = ...,
|
|
||||||
**kwargs: Any
|
|
||||||
) -> None: ...
|
|
||||||
def related_objects(self, related: ManyToOneRel, objs: List[Model]) -> QuerySet: ...
|
|
||||||
def nested(self, format_callback: Callable = ...) -> Union[List[SafeText], List[int]]: ...
|
|
||||||
def can_fast_delete(self, *args: Any, **kwargs: Any) -> bool: ...
|
|
||||||
|
|
||||||
def model_format_dict(obj: Any): ...
|
def model_format_dict(obj: Any): ...
|
||||||
def model_ngettext(obj: Union[Options, QuerySet], n: Optional[int] = ...) -> str: ...
|
def model_ngettext(obj: Union[Options, QuerySet], n: Optional[int] = ...) -> str: ...
|
||||||
def lookup_field(
|
def lookup_field(
|
||||||
name: Union[Callable, str], obj: Model, model_admin: BaseModelAdmin = ...
|
name: Union[Callable, str], obj: Model, model_admin: BaseModelAdmin = ...
|
||||||
) -> Tuple[Optional[Field], Callable, Callable]: ...
|
) -> Tuple[Optional[Field], Any, Any]: ...
|
||||||
def label_for_field(
|
def label_for_field(
|
||||||
name: Union[Callable, str],
|
name: Union[Callable, str],
|
||||||
model: Type[Model],
|
model: Type[Model],
|
||||||
@@ -65,16 +55,14 @@ def label_for_field(
|
|||||||
form: Optional[BaseForm] = ...,
|
form: Optional[BaseForm] = ...,
|
||||||
) -> Union[Tuple[Optional[str], Union[Callable, Type[str]]], str]: ...
|
) -> Union[Tuple[Optional[str], Union[Callable, Type[str]]], str]: ...
|
||||||
def help_text_for_field(name: str, model: Type[Model]) -> str: ...
|
def help_text_for_field(name: str, model: Type[Model]) -> str: ...
|
||||||
def display_for_field(
|
def display_for_field(value: Any, field: Field, empty_value_display: str) -> str: ...
|
||||||
value: Any, field: Union[Field, reverse_related.OneToOneRel], empty_value_display: str
|
|
||||||
) -> str: ...
|
|
||||||
def display_for_value(value: Any, empty_value_display: str, boolean: bool = ...) -> str: ...
|
def display_for_value(value: Any, empty_value_display: str, boolean: bool = ...) -> str: ...
|
||||||
|
|
||||||
class NotRelationField(Exception): ...
|
class NotRelationField(Exception): ...
|
||||||
|
|
||||||
def get_model_from_relation(field: Union[Field, reverse_related.ForeignObjectRel]) -> Type[Model]: ...
|
def get_model_from_relation(field: Union[Field, reverse_related.ForeignObjectRel]) -> Type[Model]: ...
|
||||||
def reverse_field_path(model: Type[Model], path: str) -> Tuple[Type[Model], str]: ...
|
def reverse_field_path(model: Type[Model], path: str) -> Tuple[Type[Model], str]: ...
|
||||||
def get_fields_from_path(model: Type[Model], path: str) -> List[Union[Field, FieldCacheMixin]]: ...
|
def get_fields_from_path(model: Type[Model], path: str) -> List[Field]: ...
|
||||||
def construct_change_message(
|
def construct_change_message(
|
||||||
form: AdminPasswordChangeForm, formsets: None, add: bool
|
form: AdminPasswordChangeForm, formsets: None, add: bool
|
||||||
) -> List[Dict[str, Dict[str, List[str]]]]: ...
|
) -> List[Dict[str, Dict[str, List[str]]]]: ...
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from typing import Any, Optional, Set, Union
|
from typing import Any, Optional, Set, Union
|
||||||
|
|
||||||
from django.contrib.auth.base_user import AbstractBaseUser
|
from django.contrib.auth.base_user import AbstractBaseUser
|
||||||
from django.contrib.auth.models import AnonymousUser, User
|
from django.contrib.auth.models import AnonymousUser, User, Permission
|
||||||
|
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
|
|
||||||
@@ -9,17 +9,26 @@ _AnyUser = Union[Model, AnonymousUser]
|
|||||||
|
|
||||||
UserModel: Any
|
UserModel: Any
|
||||||
|
|
||||||
class ModelBackend:
|
class BaseBackend:
|
||||||
def authenticate(
|
def authenticate(
|
||||||
self, request: Any, username: Optional[str] = ..., password: Optional[str] = ..., **kwargs: Any
|
self, request: Any, username: Optional[str] = ..., password: Optional[str] = ..., **kwargs: Any
|
||||||
) -> Optional[AbstractBaseUser]: ...
|
) -> Optional[AbstractBaseUser]: ...
|
||||||
def user_can_authenticate(self, user: Optional[_AnyUser]) -> bool: ...
|
def get_user(self, user_id: int) -> Optional[AbstractBaseUser]: ...
|
||||||
def get_user_permissions(self, user_obj: _AnyUser, obj: Optional[Model] = ...) -> Set[str]: ...
|
def get_user_permissions(self, user_obj: _AnyUser, obj: Optional[Model] = ...) -> Set[str]: ...
|
||||||
def get_group_permissions(self, user_obj: _AnyUser, obj: Optional[Model] = ...) -> Set[str]: ...
|
def get_group_permissions(self, user_obj: _AnyUser, obj: Optional[Model] = ...) -> Set[str]: ...
|
||||||
def get_all_permissions(self, user_obj: _AnyUser, obj: Optional[Model] = ...) -> Set[str]: ...
|
def get_all_permissions(self, user_obj: _AnyUser, obj: Optional[Model] = ...) -> Set[str]: ...
|
||||||
def has_perm(self, user_obj: _AnyUser, perm: str, obj: Optional[Model] = ...) -> bool: ...
|
def has_perm(self, user_obj: _AnyUser, perm: str, obj: Optional[Model] = ...) -> bool: ...
|
||||||
|
|
||||||
|
class ModelBackend(BaseBackend):
|
||||||
def has_module_perms(self, user_obj: _AnyUser, app_label: str) -> bool: ...
|
def has_module_perms(self, user_obj: _AnyUser, app_label: str) -> bool: ...
|
||||||
def get_user(self, user_id: int) -> AbstractBaseUser: ...
|
def user_can_authenticate(self, user: Optional[_AnyUser]) -> bool: ...
|
||||||
|
def with_perm(
|
||||||
|
self,
|
||||||
|
perm: Union[str, Permission],
|
||||||
|
is_active: bool = ...,
|
||||||
|
include_superusers: bool = ...,
|
||||||
|
obj: Optional[Model] = ...,
|
||||||
|
): ...
|
||||||
|
|
||||||
class AllowAllUsersModelBackend(ModelBackend): ...
|
class AllowAllUsersModelBackend(ModelBackend): ...
|
||||||
|
|
||||||
|
|||||||
@@ -13,11 +13,10 @@ class BaseUserManager(models.Manager[_T]):
|
|||||||
def get_by_natural_key(self, username: Optional[str]) -> _T: ...
|
def get_by_natural_key(self, username: Optional[str]) -> _T: ...
|
||||||
|
|
||||||
class AbstractBaseUser(models.Model):
|
class AbstractBaseUser(models.Model):
|
||||||
|
REQUIRED_FIELDS: List[str] = ...
|
||||||
|
|
||||||
password = models.CharField(max_length=128)
|
password = models.CharField(max_length=128)
|
||||||
last_login = models.DateTimeField(blank=True, null=True)
|
last_login = models.DateTimeField(blank=True, null=True)
|
||||||
|
|
||||||
REQUIRED_FIELDS: List[str] = ...
|
|
||||||
class Meta: ...
|
|
||||||
def get_username(self) -> str: ...
|
def get_username(self) -> str: ...
|
||||||
def natural_key(self) -> Tuple[str]: ...
|
def natural_key(self) -> Tuple[str]: ...
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
from typing import Any, List
|
from typing import Any, List, Iterable, Optional
|
||||||
|
|
||||||
from django.core.checks.messages import CheckMessage
|
from django.core.checks.messages import CheckMessage
|
||||||
|
|
||||||
def check_user_model(app_configs: None = ..., **kwargs: Any) -> List[CheckMessage]: ...
|
from django.apps.config import AppConfig
|
||||||
def check_models_permissions(app_configs: None = ..., **kwargs: Any) -> List[Any]: ...
|
|
||||||
|
def check_user_model(app_configs: Optional[Iterable[AppConfig]] = ..., **kwargs: Any) -> List[CheckMessage]: ...
|
||||||
|
def check_models_permissions(app_configs: Optional[Iterable[AppConfig]] = ..., **kwargs: Any) -> List[Any]: ...
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from typing import Any, Collection, Optional, Set, Tuple, Type, TypeVar, Union
|
from typing import Any, Collection, Optional, Set, Tuple, Type, TypeVar, Union
|
||||||
|
|
||||||
|
from django.contrib.auth.backends import ModelBackend
|
||||||
from django.contrib.auth.base_user import AbstractBaseUser as AbstractBaseUser, BaseUserManager as BaseUserManager
|
from django.contrib.auth.base_user import AbstractBaseUser as AbstractBaseUser, BaseUserManager as BaseUserManager
|
||||||
from django.contrib.auth.validators import UnicodeUsernameValidator
|
from django.contrib.auth.validators import UnicodeUsernameValidator
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
@@ -43,11 +44,20 @@ class UserManager(BaseUserManager[_T]):
|
|||||||
def create_superuser(
|
def create_superuser(
|
||||||
self, username: str, email: Optional[str], password: Optional[str], **extra_fields: Any
|
self, username: str, email: Optional[str], password: Optional[str], **extra_fields: Any
|
||||||
) -> _T: ...
|
) -> _T: ...
|
||||||
|
def with_perm(
|
||||||
|
self,
|
||||||
|
perm: Union[str, Permission],
|
||||||
|
is_active: bool = ...,
|
||||||
|
include_superusers: bool = ...,
|
||||||
|
backend: Optional[Union[Type[ModelBackend], str]] = ...,
|
||||||
|
obj: Optional[Model] = ...,
|
||||||
|
): ...
|
||||||
|
|
||||||
class PermissionsMixin(models.Model):
|
class PermissionsMixin(models.Model):
|
||||||
is_superuser = models.BooleanField()
|
is_superuser = models.BooleanField()
|
||||||
groups = models.ManyToManyField(Group)
|
groups = models.ManyToManyField(Group)
|
||||||
user_permissions = models.ManyToManyField(Permission)
|
user_permissions = models.ManyToManyField(Permission)
|
||||||
|
def get_user_permissions(self, obj: Optional[_AnyUser] = ...) -> Set[str]: ...
|
||||||
def get_group_permissions(self, obj: Optional[_AnyUser] = ...) -> Set[str]: ...
|
def get_group_permissions(self, obj: Optional[_AnyUser] = ...) -> Set[str]: ...
|
||||||
def get_all_permissions(self, obj: Optional[_AnyUser] = ...) -> Set[str]: ...
|
def get_all_permissions(self, obj: Optional[_AnyUser] = ...) -> Set[str]: ...
|
||||||
def has_perm(self, perm: str, obj: Optional[_AnyUser] = ...) -> bool: ...
|
def has_perm(self, perm: str, obj: Optional[_AnyUser] = ...) -> bool: ...
|
||||||
@@ -88,6 +98,7 @@ class AnonymousUser:
|
|||||||
def groups(self) -> EmptyManager: ...
|
def groups(self) -> EmptyManager: ...
|
||||||
@property
|
@property
|
||||||
def user_permissions(self) -> EmptyManager: ...
|
def user_permissions(self) -> EmptyManager: ...
|
||||||
|
def get_user_permissions(self, obj: Optional[_AnyUser] = ...) -> Set[str]: ...
|
||||||
def get_group_permissions(self, obj: Optional[_AnyUser] = ...) -> Set[Any]: ...
|
def get_group_permissions(self, obj: Optional[_AnyUser] = ...) -> Set[Any]: ...
|
||||||
def get_all_permissions(self, obj: Optional[_AnyUser] = ...) -> Set[str]: ...
|
def get_all_permissions(self, obj: Optional[_AnyUser] = ...) -> Set[str]: ...
|
||||||
def has_perm(self, perm: str, obj: Optional[_AnyUser] = ...) -> bool: ...
|
def has_perm(self, perm: str, obj: Optional[_AnyUser] = ...) -> bool: ...
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ class PasswordResetDoneView(PasswordContextMixin, TemplateView):
|
|||||||
class PasswordResetConfirmView(PasswordContextMixin, FormView):
|
class PasswordResetConfirmView(PasswordContextMixin, FormView):
|
||||||
post_reset_login: bool = ...
|
post_reset_login: bool = ...
|
||||||
post_reset_login_backend: Any = ...
|
post_reset_login_backend: Any = ...
|
||||||
|
reset_url_token: str = ...
|
||||||
title: Any = ...
|
title: Any = ...
|
||||||
token_generator: Any = ...
|
token_generator: Any = ...
|
||||||
validlink: bool = ...
|
validlink: bool = ...
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
from typing import Any, List
|
from typing import Any, List, Iterable, Optional
|
||||||
|
|
||||||
def check_generic_foreign_keys(app_configs: None = ..., **kwargs: Any) -> List[Any]: ...
|
from django.apps.config import AppConfig
|
||||||
def check_model_name_lengths(app_configs: None = ..., **kwargs: Any) -> List[Any]: ...
|
|
||||||
|
def check_generic_foreign_keys(app_configs: Optional[Iterable[AppConfig]] = ..., **kwargs: Any) -> List[Any]: ...
|
||||||
|
def check_model_name_lengths(app_configs: Optional[Iterable[AppConfig]] = ..., **kwargs: Any) -> List[Any]: ...
|
||||||
|
|||||||
18
django-stubs/contrib/postgres/constraints.pyi
Normal file
18
django-stubs/contrib/postgres/constraints.pyi
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from typing import Optional, Sequence, Tuple, Union
|
||||||
|
|
||||||
|
from django.db.models.constraints import BaseConstraint
|
||||||
|
from django.db.models.expressions import Combinable
|
||||||
|
from django.db.models.query_utils import Q
|
||||||
|
|
||||||
|
class ExclusionConstraint(BaseConstraint):
|
||||||
|
expressions: Sequence[Tuple[Union[str, Combinable], str]]
|
||||||
|
index_type: str
|
||||||
|
condition: Optional[Q]
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
name: str,
|
||||||
|
expressions: Sequence[Tuple[Union[str, Combinable], str]],
|
||||||
|
condition: Optional[Q] = ...,
|
||||||
|
index_type: Optional[str] = ...,
|
||||||
|
): ...
|
||||||
@@ -8,6 +8,8 @@ from .ranges import (
|
|||||||
FloatRangeField as FloatRangeField,
|
FloatRangeField as FloatRangeField,
|
||||||
DateRangeField as DateRangeField,
|
DateRangeField as DateRangeField,
|
||||||
DateTimeRangeField as DateTimeRangeField,
|
DateTimeRangeField as DateTimeRangeField,
|
||||||
|
RangeOperators as RangeOperators,
|
||||||
|
RangeBoundary as RangeBoundary,
|
||||||
)
|
)
|
||||||
from .hstore import HStoreField as HStoreField
|
from .hstore import HStoreField as HStoreField
|
||||||
from .citext import (
|
from .citext import (
|
||||||
|
|||||||
@@ -29,3 +29,20 @@ class DateTimeRangeField(RangeField):
|
|||||||
|
|
||||||
class DateRangeField(RangeField):
|
class DateRangeField(RangeField):
|
||||||
def __get__(self, instance, owner) -> DateRange: ...
|
def __get__(self, instance, owner) -> DateRange: ...
|
||||||
|
|
||||||
|
class RangeOperators:
|
||||||
|
EQUAL: str
|
||||||
|
NOT_EQUAL: str
|
||||||
|
CONTAINS: str
|
||||||
|
CONTAINED_BY: str
|
||||||
|
OVERLAPS: str
|
||||||
|
FULLY_LT: str
|
||||||
|
FULLY_GT: str
|
||||||
|
NOT_LT: str
|
||||||
|
NOT_GT: str
|
||||||
|
ADJACENT_TO: str
|
||||||
|
|
||||||
|
class RangeBoundary(models.Expression):
|
||||||
|
lower: str
|
||||||
|
upper: str
|
||||||
|
def __init__(self, inclusive_lower: bool = ..., inclusive_upper: bool = ...): ...
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from django.apps.config import AppConfig
|
||||||
from django.apps.registry import Apps
|
from django.apps.registry import Apps
|
||||||
from django.contrib.sites.apps import SitesConfig
|
|
||||||
|
|
||||||
def create_default_site(
|
def create_default_site(
|
||||||
app_config: SitesConfig,
|
app_config: AppConfig,
|
||||||
verbosity: int = ...,
|
verbosity: int = ...,
|
||||||
interactive: bool = ...,
|
interactive: bool = ...,
|
||||||
using: str = ...,
|
using: str = ...,
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
from typing import Any, List
|
from typing import Any, List, Iterable, Optional
|
||||||
|
|
||||||
from django.core.checks.messages import Error
|
from django.core.checks.messages import Error
|
||||||
|
|
||||||
def check_finders(app_configs: None = ..., **kwargs: Any) -> List[Error]: ...
|
from django.apps.config import AppConfig
|
||||||
|
|
||||||
|
def check_finders(app_configs: Optional[Iterable[AppConfig]] = ..., **kwargs: Any) -> List[Error]: ...
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from typing import Any, List
|
from typing import Any, List, Iterable, Optional
|
||||||
|
|
||||||
from django.core.checks.messages import Error
|
from django.core.checks.messages import Error
|
||||||
|
|
||||||
|
from django.apps.config import AppConfig
|
||||||
|
|
||||||
E001: Any
|
E001: Any
|
||||||
|
|
||||||
def check_default_cache_is_configured(app_configs: None, **kwargs: Any) -> List[Error]: ...
|
def check_default_cache_is_configured(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Error]: ...
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
from typing import Any, List
|
from typing import Any, List, Iterable, Optional
|
||||||
|
|
||||||
from django.core.checks.messages import Warning
|
from django.core.checks.messages import Warning
|
||||||
|
|
||||||
def check_all_models(app_configs: None = ..., **kwargs: Any) -> List[Warning]: ...
|
from django.apps.config import AppConfig
|
||||||
def check_lazy_references(app_configs: None = ..., **kwargs: Any) -> List[Any]: ...
|
|
||||||
|
def check_all_models(app_configs: Optional[Iterable[AppConfig]] = ..., **kwargs: Any) -> List[Warning]: ...
|
||||||
|
def check_lazy_references(app_configs: Optional[Iterable[AppConfig]] = ..., **kwargs: Any) -> List[Any]: ...
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from typing import Any, List
|
from typing import Any, List, Iterable, Optional
|
||||||
|
|
||||||
from django.core.checks.messages import Warning
|
from django.core.checks.messages import Warning
|
||||||
|
|
||||||
|
from django.apps.config import AppConfig
|
||||||
|
|
||||||
SECRET_KEY_MIN_LENGTH: int
|
SECRET_KEY_MIN_LENGTH: int
|
||||||
SECRET_KEY_MIN_UNIQUE_CHARACTERS: int
|
SECRET_KEY_MIN_UNIQUE_CHARACTERS: int
|
||||||
W001: Any
|
W001: Any
|
||||||
@@ -17,15 +19,15 @@ W019: Any
|
|||||||
W020: Any
|
W020: Any
|
||||||
W021: Any
|
W021: Any
|
||||||
|
|
||||||
def check_security_middleware(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_security_middleware(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_xframe_options_middleware(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_xframe_options_middleware(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_sts(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_sts(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_sts_include_subdomains(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_sts_include_subdomains(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_sts_preload(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_sts_preload(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_content_type_nosniff(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_content_type_nosniff(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_xss_filter(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_xss_filter(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_ssl_redirect(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_ssl_redirect(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_secret_key(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_secret_key(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_debug(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_debug(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_xframe_deny(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_xframe_deny(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_allowed_hosts(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_allowed_hosts(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
from typing import Any, List
|
from typing import Any, List, Iterable, Optional
|
||||||
|
|
||||||
from django.core.checks.messages import Warning
|
from django.core.checks.messages import Warning
|
||||||
|
|
||||||
|
from django.apps.config import AppConfig
|
||||||
|
|
||||||
W003: Any
|
W003: Any
|
||||||
W016: Any
|
W016: Any
|
||||||
|
|
||||||
def check_csrf_middleware(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_csrf_middleware(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_csrf_cookie_secure(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_csrf_cookie_secure(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from typing import Any, List
|
from typing import Any, List, Iterable, Optional
|
||||||
|
|
||||||
from django.core.checks.messages import Warning
|
from django.core.checks.messages import Warning
|
||||||
|
|
||||||
|
from django.apps.config import AppConfig
|
||||||
|
|
||||||
def add_session_cookie_message(message: Any): ...
|
def add_session_cookie_message(message: Any): ...
|
||||||
|
|
||||||
W010: Any
|
W010: Any
|
||||||
@@ -14,5 +16,5 @@ W013: Any
|
|||||||
W014: Any
|
W014: Any
|
||||||
W015: Any
|
W015: Any
|
||||||
|
|
||||||
def check_session_cookie_secure(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_session_cookie_secure(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def check_session_cookie_httponly(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_session_cookie_httponly(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
from typing import Any, List
|
from typing import Any, List, Iterable, Optional
|
||||||
|
|
||||||
from django.core.checks.messages import Error
|
from django.core.checks.messages import Error
|
||||||
|
|
||||||
|
from django.apps.config import AppConfig
|
||||||
|
|
||||||
E001: Any
|
E001: Any
|
||||||
E002: Any
|
E002: Any
|
||||||
|
|
||||||
def check_setting_app_dirs_loaders(app_configs: None, **kwargs: Any) -> List[Error]: ...
|
def check_setting_app_dirs_loaders(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Error]: ...
|
||||||
def check_string_if_invalid_is_string(app_configs: None, **kwargs: Any) -> List[Error]: ...
|
def check_string_if_invalid_is_string(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Error]: ...
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
from typing import Any, Callable, List, Tuple, Union
|
from typing import Any, Callable, List, Tuple, Union, Iterable, Optional
|
||||||
|
|
||||||
from django.core.checks.messages import CheckMessage, Error, Warning
|
from django.core.checks.messages import CheckMessage, Error, Warning
|
||||||
from django.urls.resolvers import URLPattern, URLResolver
|
from django.urls.resolvers import URLPattern, URLResolver
|
||||||
|
|
||||||
def check_url_config(app_configs: None, **kwargs: Any) -> List[CheckMessage]: ...
|
from django.apps.config import AppConfig
|
||||||
|
|
||||||
|
def check_url_config(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[CheckMessage]: ...
|
||||||
def check_resolver(resolver: Union[Tuple[str, Callable], URLPattern, URLResolver]) -> List[CheckMessage]: ...
|
def check_resolver(resolver: Union[Tuple[str, Callable], URLPattern, URLResolver]) -> List[CheckMessage]: ...
|
||||||
def check_url_namespaces_unique(app_configs: None, **kwargs: Any) -> List[Warning]: ...
|
def check_url_namespaces_unique(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Warning]: ...
|
||||||
def get_warning_for_invalid_pattern(pattern: Any) -> List[Error]: ...
|
def get_warning_for_invalid_pattern(pattern: Any) -> List[Error]: ...
|
||||||
def check_url_settings(app_configs: None, **kwargs: Any) -> List[Error]: ...
|
def check_url_settings(app_configs: Optional[Iterable[AppConfig]], **kwargs: Any) -> List[Error]: ...
|
||||||
def E006(name: str) -> Error: ...
|
def E006(name: str) -> Error: ...
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from datetime import date
|
from datetime import date
|
||||||
from io import BufferedReader, StringIO, TextIOWrapper
|
from io import BufferedReader, StringIO, TextIOWrapper
|
||||||
from typing import Any, Dict, Iterable, List, Mapping, Optional, Type, Union
|
from typing import Any, Dict, Iterable, List, Mapping, Optional, Type, Union, Collection
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from django.core.management.base import OutputWrapper
|
from django.core.management.base import OutputWrapper
|
||||||
@@ -35,18 +35,18 @@ class Serializer:
|
|||||||
internal_use_only: bool = ...
|
internal_use_only: bool = ...
|
||||||
progress_class: Any = ...
|
progress_class: Any = ...
|
||||||
stream_class: Any = ...
|
stream_class: Any = ...
|
||||||
options: Any = ...
|
options: Dict[str, Any] = ...
|
||||||
stream: Any = ...
|
stream: Any = ...
|
||||||
selected_fields: Any = ...
|
selected_fields: Optional[Collection[str]] = ...
|
||||||
use_natural_foreign_keys: Any = ...
|
use_natural_foreign_keys: bool = ...
|
||||||
use_natural_primary_keys: Any = ...
|
use_natural_primary_keys: bool = ...
|
||||||
first: bool = ...
|
first: bool = ...
|
||||||
def serialize(
|
def serialize(
|
||||||
self,
|
self,
|
||||||
queryset: Iterable[Model],
|
queryset: Iterable[Model],
|
||||||
*,
|
*,
|
||||||
stream: Optional[Any] = ...,
|
stream: Optional[Any] = ...,
|
||||||
fields: Optional[Any] = ...,
|
fields: Optional[Collection[str]] = ...,
|
||||||
use_natural_foreign_keys: bool = ...,
|
use_natural_foreign_keys: bool = ...,
|
||||||
use_natural_primary_keys: bool = ...,
|
use_natural_primary_keys: bool = ...,
|
||||||
progress_output: Optional[Any] = ...,
|
progress_output: Optional[Any] = ...,
|
||||||
@@ -63,7 +63,7 @@ class Serializer:
|
|||||||
def getvalue(self) -> Optional[Union[bytes, str]]: ...
|
def getvalue(self) -> Optional[Union[bytes, str]]: ...
|
||||||
|
|
||||||
class Deserializer:
|
class Deserializer:
|
||||||
options: Any = ...
|
options: Dict[str, Any] = ...
|
||||||
stream: Any = ...
|
stream: Any = ...
|
||||||
def __init__(self, stream_or_string: Union[BufferedReader, TextIOWrapper, str], **options: Any) -> None: ...
|
def __init__(self, stream_or_string: Union[BufferedReader, TextIOWrapper, str], **options: Any) -> None: ...
|
||||||
def __iter__(self) -> Deserializer: ...
|
def __iter__(self) -> Deserializer: ...
|
||||||
|
|||||||
@@ -1,24 +1,10 @@
|
|||||||
import json
|
import json
|
||||||
from datetime import datetime
|
from typing import Any, Dict
|
||||||
from decimal import Decimal
|
|
||||||
from io import TextIOWrapper
|
|
||||||
from typing import Any, Union, Dict
|
|
||||||
from uuid import UUID
|
|
||||||
|
|
||||||
from django.core.serializers.python import Serializer as PythonSerializer
|
from django.core.serializers.python import Serializer as PythonSerializer
|
||||||
from django.db.models.base import Model
|
|
||||||
|
|
||||||
class Serializer(PythonSerializer):
|
class Serializer(PythonSerializer):
|
||||||
json_kwargs: Dict[str, Any]
|
json_kwargs: Dict[str, Any]
|
||||||
options: Dict[str, None]
|
|
||||||
selected_fields: None
|
|
||||||
stream: TextIOWrapper
|
|
||||||
use_natural_foreign_keys: bool
|
|
||||||
use_natural_primary_keys: bool
|
|
||||||
internal_use_only: bool = ...
|
|
||||||
def start_serialization(self) -> None: ...
|
|
||||||
def end_serialization(self) -> None: ...
|
|
||||||
def end_object(self, obj: Model) -> None: ...
|
|
||||||
|
|
||||||
def Deserializer(stream_or_string: Any, **options: Any) -> None: ...
|
def Deserializer(stream_or_string: Any, **options: Any) -> None: ...
|
||||||
|
|
||||||
@@ -29,4 +15,3 @@ class DjangoJSONEncoder(json.JSONEncoder):
|
|||||||
indent: int
|
indent: int
|
||||||
skipkeys: bool
|
skipkeys: bool
|
||||||
sort_keys: bool
|
sort_keys: bool
|
||||||
def default(self, o: Union[datetime, Decimal, UUID]) -> str: ...
|
|
||||||
|
|||||||
@@ -1,31 +1,15 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from io import TextIOWrapper
|
from typing import Any, Dict, Iterator, List, Optional
|
||||||
from typing import Any, Dict, Iterator, List
|
|
||||||
|
|
||||||
from django.core.serializers.base import DeserializedObject
|
from django.core.serializers.base import DeserializedObject
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
from django.db.models.fields.related import ForeignKey, ManyToManyField
|
|
||||||
|
|
||||||
from django.core.serializers import base
|
from django.core.serializers import base
|
||||||
from django.db.models.fields import Field
|
|
||||||
|
|
||||||
class Serializer(base.Serializer):
|
class Serializer(base.Serializer):
|
||||||
options: Dict[Any, Any]
|
|
||||||
selected_fields: None
|
|
||||||
stream: TextIOWrapper
|
|
||||||
use_natural_foreign_keys: bool
|
|
||||||
use_natural_primary_keys: bool
|
|
||||||
internal_use_only: bool = ...
|
|
||||||
objects: List[Any] = ...
|
objects: List[Any] = ...
|
||||||
def start_serialization(self) -> None: ...
|
|
||||||
def end_serialization(self) -> None: ...
|
|
||||||
def start_object(self, obj: Model) -> None: ...
|
|
||||||
def end_object(self, obj: Model) -> None: ...
|
|
||||||
def get_dump_object(self, obj: Model) -> OrderedDict: ...
|
def get_dump_object(self, obj: Model) -> OrderedDict: ...
|
||||||
def handle_field(self, obj: Model, field: Field) -> None: ...
|
|
||||||
def handle_fk_field(self, obj: Model, field: ForeignKey) -> None: ...
|
|
||||||
def handle_m2m_field(self, obj: Model, field: ManyToManyField) -> None: ...
|
|
||||||
|
|
||||||
def Deserializer(
|
def Deserializer(
|
||||||
object_list: List[Dict[str, Any]], *, using: Any = ..., ignorenonexistent: bool = ..., **options: Any
|
object_list: List[Dict[str, Any]], *, using: Optional[str] = ..., ignorenonexistent: bool = ..., **options: Any
|
||||||
) -> Iterator[DeserializedObject]: ...
|
) -> Iterator[DeserializedObject]: ...
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
from datetime import datetime
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from re import RegexFlag
|
from re import RegexFlag
|
||||||
from typing import Any, Dict, List, Optional, Union, Pattern, Collection
|
from typing import Any, Dict, List, Optional, Union, Pattern, Collection, Callable, Tuple
|
||||||
from uuid import UUID
|
|
||||||
|
|
||||||
from django.core.files.base import File
|
from django.core.files.base import File
|
||||||
from django.core.exceptions import ValidationError as ValidationError # noqa: F401
|
|
||||||
|
|
||||||
EMPTY_VALUES: Any
|
EMPTY_VALUES: Any
|
||||||
|
|
||||||
_Regex = Union[str, Pattern[str]]
|
_Regex = Union[str, Pattern[str]]
|
||||||
|
_ErrorMessage = Union[str, Any]
|
||||||
|
|
||||||
def _lazy_re_compile(regex: _Regex, flags: int = ...): ...
|
def _lazy_re_compile(regex: _Regex, flags: int = ...): ...
|
||||||
|
|
||||||
@@ -22,7 +20,7 @@ class RegexValidator:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
regex: Optional[_Regex] = ...,
|
regex: Optional[_Regex] = ...,
|
||||||
message: Optional[str] = ...,
|
message: Optional[_ErrorMessage] = ...,
|
||||||
code: Optional[str] = ...,
|
code: Optional[str] = ...,
|
||||||
inverse_match: Optional[bool] = ...,
|
inverse_match: Optional[bool] = ...,
|
||||||
flags: Optional[RegexFlag] = ...,
|
flags: Optional[RegexFlag] = ...,
|
||||||
@@ -45,67 +43,53 @@ integer_validator: Any
|
|||||||
def validate_integer(value: Optional[Union[float, str]]) -> None: ...
|
def validate_integer(value: Optional[Union[float, str]]) -> None: ...
|
||||||
|
|
||||||
class EmailValidator:
|
class EmailValidator:
|
||||||
message: Any = ...
|
message: str = ...
|
||||||
code: str = ...
|
code: str = ...
|
||||||
user_regex: Any = ...
|
user_regex: Any = ...
|
||||||
domain_regex: Any = ...
|
domain_regex: Any = ...
|
||||||
literal_regex: Any = ...
|
literal_regex: Any = ...
|
||||||
domain_whitelist: Any = ...
|
domain_whitelist: Any = ...
|
||||||
def __init__(
|
def __init__(
|
||||||
self, message: Optional[str] = ..., code: Optional[str] = ..., whitelist: Optional[Collection[str]] = ...
|
self,
|
||||||
|
message: Optional[_ErrorMessage] = ...,
|
||||||
|
code: Optional[str] = ...,
|
||||||
|
whitelist: Optional[Collection[str]] = ...,
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def __call__(self, value: Optional[str]) -> None: ...
|
def __call__(self, value: Optional[str]) -> None: ...
|
||||||
def validate_domain_part(self, domain_part: str) -> bool: ...
|
def validate_domain_part(self, domain_part: str) -> bool: ...
|
||||||
|
|
||||||
validate_email: Any
|
validate_email: EmailValidator = ...
|
||||||
slug_re: Any
|
slug_re: Pattern = ...
|
||||||
validate_slug: Any
|
validate_slug: RegexValidator = ...
|
||||||
slug_unicode_re: Any
|
slug_unicode_re: Pattern = ...
|
||||||
validate_unicode_slug: Any
|
validate_unicode_slug: RegexValidator = ...
|
||||||
|
|
||||||
def validate_ipv4_address(value: str) -> None: ...
|
def validate_ipv4_address(value: str) -> None: ...
|
||||||
def validate_ipv6_address(value: str) -> None: ...
|
def validate_ipv6_address(value: str) -> None: ...
|
||||||
def validate_ipv46_address(value: str) -> None: ...
|
def validate_ipv46_address(value: str) -> None: ...
|
||||||
|
|
||||||
ip_address_validator_map: Any
|
ip_address_validator_map: Dict[str, Tuple[Callable[[Any], None], str]]
|
||||||
|
|
||||||
def ip_address_validators(protocol: str, unpack_ipv4: bool) -> Any: ...
|
def ip_address_validators(protocol: str, unpack_ipv4: bool) -> Any: ...
|
||||||
def int_list_validator(
|
def int_list_validator(
|
||||||
sep: str = ..., message: None = ..., code: str = ..., allow_negative: bool = ...
|
sep: str = ..., message: Optional[_ErrorMessage] = ..., code: str = ..., allow_negative: bool = ...
|
||||||
) -> RegexValidator: ...
|
) -> RegexValidator: ...
|
||||||
|
|
||||||
validate_comma_separated_integer_list: Any
|
validate_comma_separated_integer_list: Any
|
||||||
|
|
||||||
class BaseValidator:
|
class BaseValidator:
|
||||||
message: Any = ...
|
message: str = ...
|
||||||
code: str = ...
|
code: str = ...
|
||||||
limit_value: Any = ...
|
limit_value: Any = ...
|
||||||
def __init__(self, limit_value: Any, message: Optional[str] = ...) -> None: ...
|
def __init__(self, limit_value: Any, message: Optional[_ErrorMessage] = ...) -> None: ...
|
||||||
def __call__(self, value: Any) -> None: ...
|
def __call__(self, value: Any) -> None: ...
|
||||||
def compare(self, a: bool, b: bool) -> bool: ...
|
def compare(self, a: Any, b: Any) -> bool: ...
|
||||||
def clean(self, x: Any) -> Any: ...
|
def clean(self, x: Any) -> Any: ...
|
||||||
|
|
||||||
class MaxValueValidator(BaseValidator):
|
class MaxValueValidator(BaseValidator): ...
|
||||||
message: Any = ...
|
class MinValueValidator(BaseValidator): ...
|
||||||
code: str = ...
|
class MinLengthValidator(BaseValidator): ...
|
||||||
def compare(self, a: Union[datetime, Decimal, float], b: Union[datetime, Decimal, float]) -> bool: ...
|
class MaxLengthValidator(BaseValidator): ...
|
||||||
|
|
||||||
class MinValueValidator(BaseValidator):
|
|
||||||
message: Any = ...
|
|
||||||
code: str = ...
|
|
||||||
def compare(self, a: Union[datetime, Decimal, float], b: Union[datetime, Decimal, float]) -> bool: ...
|
|
||||||
|
|
||||||
class MinLengthValidator(BaseValidator):
|
|
||||||
message: Any = ...
|
|
||||||
code: str = ...
|
|
||||||
def compare(self, a: int, b: int) -> bool: ...
|
|
||||||
def clean(self, x: str) -> int: ...
|
|
||||||
|
|
||||||
class MaxLengthValidator(BaseValidator):
|
|
||||||
message: Any = ...
|
|
||||||
code: str = ...
|
|
||||||
def compare(self, a: int, b: int) -> bool: ...
|
|
||||||
def clean(self, x: Union[bytes, str]) -> int: ...
|
|
||||||
|
|
||||||
class DecimalValidator:
|
class DecimalValidator:
|
||||||
messages: Any = ...
|
messages: Any = ...
|
||||||
@@ -115,13 +99,13 @@ class DecimalValidator:
|
|||||||
def __call__(self, value: Decimal) -> None: ...
|
def __call__(self, value: Decimal) -> None: ...
|
||||||
|
|
||||||
class FileExtensionValidator:
|
class FileExtensionValidator:
|
||||||
message: Any = ...
|
message: str = ...
|
||||||
code: str = ...
|
code: str = ...
|
||||||
allowed_extensions: List[str] = ...
|
allowed_extensions: List[str] = ...
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
allowed_extensions: Optional[Collection[str]] = ...,
|
allowed_extensions: Optional[Collection[str]] = ...,
|
||||||
message: Optional[str] = ...,
|
message: Optional[_ErrorMessage] = ...,
|
||||||
code: Optional[str] = ...,
|
code: Optional[str] = ...,
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def __call__(self, value: File) -> None: ...
|
def __call__(self, value: File) -> None: ...
|
||||||
@@ -130,7 +114,7 @@ def get_available_image_extensions() -> List[str]: ...
|
|||||||
def validate_image_file_extension(value: File) -> None: ...
|
def validate_image_file_extension(value: File) -> None: ...
|
||||||
|
|
||||||
class ProhibitNullCharactersValidator:
|
class ProhibitNullCharactersValidator:
|
||||||
message: Any = ...
|
message: str = ...
|
||||||
code: str = ...
|
code: str = ...
|
||||||
def __init__(self, message: Optional[str] = ..., code: Optional[str] = ...) -> None: ...
|
def __init__(self, message: Optional[_ErrorMessage] = ..., code: Optional[str] = ...) -> None: ...
|
||||||
def __call__(self, value: Optional[Union[Dict[Any, Any], str, UUID]]) -> None: ...
|
def __call__(self, value: Any) -> None: ...
|
||||||
|
|||||||
@@ -10,3 +10,5 @@ class DatabaseWrapper(BaseDatabaseWrapper): ...
|
|||||||
FORMAT_QMARK_REGEX: Any
|
FORMAT_QMARK_REGEX: Any
|
||||||
|
|
||||||
class SQLiteCursorWrapper(Database.Cursor): ...
|
class SQLiteCursorWrapper(Database.Cursor): ...
|
||||||
|
|
||||||
|
def check_sqlite_version() -> None: ...
|
||||||
|
|||||||
@@ -1,21 +1,13 @@
|
|||||||
from typing import Any, DefaultDict, Dict, Iterator, List, Optional, Sequence, Tuple, Type, Union, Set
|
from typing import Any, Dict, Iterator, List, Optional, Sequence, Tuple, Type, Union, Set
|
||||||
|
|
||||||
|
from django.apps import AppConfig
|
||||||
from django.apps.registry import Apps
|
from django.apps.registry import Apps
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
from django.db.models.manager import Manager
|
from django.db.models.manager import Manager
|
||||||
|
|
||||||
from django.db.models.fields import Field
|
from django.db.models.fields import Field
|
||||||
|
|
||||||
class AppConfigStub:
|
class AppConfigStub(AppConfig): ...
|
||||||
apps: None
|
|
||||||
label: str
|
|
||||||
models: None
|
|
||||||
models_module: None
|
|
||||||
module: None
|
|
||||||
name: str
|
|
||||||
verbose_name: str
|
|
||||||
def __init__(self, label: str) -> None: ...
|
|
||||||
def import_models(self) -> None: ...
|
|
||||||
|
|
||||||
class ModelState:
|
class ModelState:
|
||||||
name: str
|
name: str
|
||||||
@@ -66,13 +58,7 @@ class ProjectState:
|
|||||||
def remove_model(self, app_label: str, model_name: str) -> None: ...
|
def remove_model(self, app_label: str, model_name: str) -> None: ...
|
||||||
|
|
||||||
class StateApps(Apps):
|
class StateApps(Apps):
|
||||||
all_models: DefaultDict
|
|
||||||
apps_ready: bool
|
|
||||||
loading: bool
|
|
||||||
models_ready: bool
|
|
||||||
ready: bool
|
|
||||||
real_models: List[ModelState]
|
real_models: List[ModelState]
|
||||||
stored_app_configs: List[Any]
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, real_apps: List[str], models: Dict[Tuple[str, str], ModelState], ignore_swappable: bool = ...
|
self, real_apps: List[str], models: Dict[Tuple[str, str], ModelState], ignore_swappable: bool = ...
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Tuple, Ty
|
|||||||
|
|
||||||
from django.core.checks.messages import CheckMessage
|
from django.core.checks.messages import CheckMessage
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db.models.manager import Manager
|
from django.db.models.manager import BaseManager
|
||||||
from django.db.models.options import Options
|
from django.db.models.options import Options
|
||||||
|
|
||||||
_Self = TypeVar("_Self", bound="Model")
|
_Self = TypeVar("_Self", bound="Model")
|
||||||
@@ -13,9 +13,9 @@ class Model(metaclass=ModelBase):
|
|||||||
class DoesNotExist(Exception): ...
|
class DoesNotExist(Exception): ...
|
||||||
class MultipleObjectsReturned(Exception): ...
|
class MultipleObjectsReturned(Exception): ...
|
||||||
class Meta: ...
|
class Meta: ...
|
||||||
_default_manager: Manager[Model]
|
|
||||||
_meta: Options[Any]
|
_meta: Options[Any]
|
||||||
objects: Manager[Any]
|
_default_manager: BaseManager[Model]
|
||||||
|
objects: BaseManager[Any]
|
||||||
pk: Any = ...
|
pk: Any = ...
|
||||||
def __init__(self: _Self, *args, **kwargs) -> None: ...
|
def __init__(self: _Self, *args, **kwargs) -> None: ...
|
||||||
def delete(self, using: Any = ..., keep_parents: bool = ...) -> Tuple[int, Dict[str, int]]: ...
|
def delete(self, using: Any = ..., keep_parents: bool = ...) -> Tuple[int, Dict[str, int]]: ...
|
||||||
@@ -41,7 +41,7 @@ class Model(metaclass=ModelBase):
|
|||||||
using: Optional[str] = ...,
|
using: Optional[str] = ...,
|
||||||
update_fields: Optional[Union[Sequence[str], str]] = ...,
|
update_fields: Optional[Union[Sequence[str], str]] = ...,
|
||||||
): ...
|
): ...
|
||||||
def refresh_from_db(self: _Self, using: Optional[str] = ..., fields: Optional[List[str]] = ...) -> _Self: ...
|
def refresh_from_db(self: _Self, using: Optional[str] = ..., fields: Optional[List[str]] = ...) -> None: ...
|
||||||
def get_deferred_fields(self) -> Set[str]: ...
|
def get_deferred_fields(self) -> Set[str]: ...
|
||||||
@classmethod
|
@classmethod
|
||||||
def check(cls, **kwargs: Any) -> List[CheckMessage]: ...
|
def check(cls, **kwargs: Any) -> List[CheckMessage]: ...
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import Any, Callable, Iterable, Optional, Union
|
from typing import Any, Callable, Iterable, Optional, Union, Collection, Type
|
||||||
|
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
|
|
||||||
@@ -18,4 +18,11 @@ class ProtectedError(IntegrityError): ...
|
|||||||
|
|
||||||
class Collector:
|
class Collector:
|
||||||
def __init__(self, using: str) -> None: ...
|
def __init__(self, using: str) -> None: ...
|
||||||
|
def collect(
|
||||||
|
self,
|
||||||
|
objs: Collection[Optional[Model]],
|
||||||
|
source: Optional[Type[Model]] = ...,
|
||||||
|
source_attr: Optional[str] = ...,
|
||||||
|
**kwargs: Any
|
||||||
|
) -> None: ...
|
||||||
def can_fast_delete(self, objs: Union[Model, Iterable[Model]], from_field: Optional[Field] = ...) -> bool: ...
|
def can_fast_delete(self, objs: Union[Model, Iterable[Model]], from_field: Optional[Field] = ...) -> bool: ...
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ from django.forms import Field as FormField, Widget
|
|||||||
|
|
||||||
class NOT_PROVIDED: ...
|
class NOT_PROVIDED: ...
|
||||||
|
|
||||||
|
BLANK_CHOICE_DASH: List[Tuple[str, str]] = ...
|
||||||
|
|
||||||
_Choice = Tuple[Any, Any]
|
_Choice = Tuple[Any, Any]
|
||||||
_ChoiceNamedGroup = Tuple[str, Iterable[_Choice]]
|
_ChoiceNamedGroup = Tuple[str, Iterable[_Choice]]
|
||||||
_FieldChoices = Iterable[Union[_Choice, _ChoiceNamedGroup]]
|
_FieldChoices = Iterable[Union[_Choice, _ChoiceNamedGroup]]
|
||||||
@@ -63,7 +65,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
|
|||||||
null: bool = ...
|
null: bool = ...
|
||||||
editable: bool = ...
|
editable: bool = ...
|
||||||
empty_strings_allowed: bool = ...
|
empty_strings_allowed: bool = ...
|
||||||
choices: Optional[_FieldChoices] = ...
|
choices: _FieldChoices = ...
|
||||||
db_column: Optional[str]
|
db_column: Optional[str]
|
||||||
column: str
|
column: str
|
||||||
default: Any
|
default: Any
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Callable, Iterable, List, Optional, Tuple, Type, TypeVar, Union, overload
|
from typing import Any, Callable, Iterable, Optional, Type, TypeVar, Union, overload
|
||||||
|
|
||||||
from django.core.files.base import File
|
from django.core.files.base import File
|
||||||
from django.core.files.images import ImageFile
|
from django.core.files.images import ImageFile
|
||||||
@@ -8,8 +8,6 @@ from django.db.models.base import Model
|
|||||||
|
|
||||||
from django.db.models.fields import Field, _FieldChoices, _ValidatorCallable, _ErrorMessagesToOverride
|
from django.db.models.fields import Field, _FieldChoices, _ValidatorCallable, _ErrorMessagesToOverride
|
||||||
|
|
||||||
BLANK_CHOICE_DASH: List[Tuple[str, str]] = ...
|
|
||||||
|
|
||||||
class FieldFile(File):
|
class FieldFile(File):
|
||||||
instance: Model = ...
|
instance: Model = ...
|
||||||
field: FileField = ...
|
field: FileField = ...
|
||||||
|
|||||||
@@ -14,9 +14,14 @@ from .text import (
|
|||||||
Trim as Trim,
|
Trim as Trim,
|
||||||
Ord as Ord,
|
Ord as Ord,
|
||||||
Repeat as Repeat,
|
Repeat as Repeat,
|
||||||
|
SHA1 as SHA1,
|
||||||
|
SHA224 as SHA224,
|
||||||
|
SHA256 as SHA256,
|
||||||
|
SHA384 as SHA384,
|
||||||
|
SHA512 as SHA512,
|
||||||
StrIndex as StrIndex,
|
StrIndex as StrIndex,
|
||||||
Replace as Replace,
|
|
||||||
Substr as Substr,
|
Substr as Substr,
|
||||||
|
Replace as Replace,
|
||||||
Reverse as Reverse,
|
Reverse as Reverse,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -81,6 +86,7 @@ from .math import (
|
|||||||
Power as Power,
|
Power as Power,
|
||||||
Radians as Radians,
|
Radians as Radians,
|
||||||
Round as Round,
|
Round as Round,
|
||||||
|
Sign as Sign,
|
||||||
Sin as Sin,
|
Sin as Sin,
|
||||||
Sqrt as Sqrt,
|
Sqrt as Sqrt,
|
||||||
Tan as Tan,
|
Tan as Tan,
|
||||||
|
|||||||
@@ -23,3 +23,4 @@ class Round(Transform): ...
|
|||||||
class Sin(NumericOutputFieldMixin, Transform): ...
|
class Sin(NumericOutputFieldMixin, Transform): ...
|
||||||
class Sqrt(NumericOutputFieldMixin, Transform): ...
|
class Sqrt(NumericOutputFieldMixin, Transform): ...
|
||||||
class Tan(NumericOutputFieldMixin, Transform): ...
|
class Tan(NumericOutputFieldMixin, Transform): ...
|
||||||
|
class Sign(Transform): ...
|
||||||
|
|||||||
@@ -55,3 +55,11 @@ class Substr(Func):
|
|||||||
class Trim(Transform): ...
|
class Trim(Transform): ...
|
||||||
class Upper(Transform): ...
|
class Upper(Transform): ...
|
||||||
class Reverse(Transform): ...
|
class Reverse(Transform): ...
|
||||||
|
class MySQLSHA2Mixin: ...
|
||||||
|
class OracleHashMixin: ...
|
||||||
|
class PostgreSQLSHAMixin: ...
|
||||||
|
class SHA1(OracleHashMixin, PostgreSQLSHAMixin, Transform): ...
|
||||||
|
class SHA224(MySQLSHA2Mixin, PostgreSQLSHAMixin, Transform): ...
|
||||||
|
class SHA256(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ...
|
||||||
|
class SHA384(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ...
|
||||||
|
class SHA512(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ...
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from django.contrib.postgres.fields.array import ArrayField
|
|||||||
from django.contrib.postgres.fields.citext import CIText
|
from django.contrib.postgres.fields.citext import CIText
|
||||||
from django.db.backends.sqlite3.base import DatabaseWrapper
|
from django.db.backends.sqlite3.base import DatabaseWrapper
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
|
from django.db.models.constraints import BaseConstraint
|
||||||
from django.db.models.fields.mixins import FieldCacheMixin
|
from django.db.models.fields.mixins import FieldCacheMixin
|
||||||
from django.db.models.fields.related import ManyToManyField, OneToOneField
|
from django.db.models.fields.related import ManyToManyField, OneToOneField
|
||||||
from django.db.models.fields.reverse_related import ForeignObjectRel
|
from django.db.models.fields.reverse_related import ForeignObjectRel
|
||||||
@@ -34,6 +35,7 @@ _M = TypeVar("_M", bound=Model)
|
|||||||
class Options(Generic[_M]):
|
class Options(Generic[_M]):
|
||||||
base_manager: Manager
|
base_manager: Manager
|
||||||
concrete_fields: ImmutableList
|
concrete_fields: ImmutableList
|
||||||
|
constraints: List[BaseConstraint]
|
||||||
default_manager: Manager
|
default_manager: Manager
|
||||||
fields: ImmutableList
|
fields: ImmutableList
|
||||||
local_concrete_fields: ImmutableList
|
local_concrete_fields: ImmutableList
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ from typing import (
|
|||||||
TypeVar,
|
TypeVar,
|
||||||
Union,
|
Union,
|
||||||
overload,
|
overload,
|
||||||
|
Reversible,
|
||||||
)
|
)
|
||||||
|
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
@@ -30,6 +31,7 @@ _T = TypeVar("_T", bound=models.Model, covariant=True)
|
|||||||
_QS = TypeVar("_QS", bound="_BaseQuerySet")
|
_QS = TypeVar("_QS", bound="_BaseQuerySet")
|
||||||
|
|
||||||
class _BaseQuerySet(Generic[_T], Sized):
|
class _BaseQuerySet(Generic[_T], Sized):
|
||||||
|
model: Type[_T]
|
||||||
query: Query
|
query: Query
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -121,13 +123,14 @@ class _BaseQuerySet(Generic[_T], Sized):
|
|||||||
def db(self) -> str: ...
|
def db(self) -> str: ...
|
||||||
def resolve_expression(self, *args: Any, **kwargs: Any) -> Any: ...
|
def resolve_expression(self, *args: Any, **kwargs: Any) -> Any: ...
|
||||||
|
|
||||||
class QuerySet(_BaseQuerySet[_T], Collection[_T], Sized):
|
class QuerySet(_BaseQuerySet[_T], Collection[_T], Reversible[_T], Sized):
|
||||||
def __iter__(self) -> Iterator[_T]: ...
|
def __iter__(self) -> Iterator[_T]: ...
|
||||||
def __contains__(self, x: object) -> bool: ...
|
def __contains__(self, x: object) -> bool: ...
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(self, i: int) -> _T: ...
|
def __getitem__(self, i: int) -> _T: ...
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(self: _QS, s: slice) -> _QS: ...
|
def __getitem__(self: _QS, s: slice) -> _QS: ...
|
||||||
|
def __reversed__(self) -> Iterator[_T]: ...
|
||||||
|
|
||||||
_Row = TypeVar("_Row", covariant=True)
|
_Row = TypeVar("_Row", covariant=True)
|
||||||
|
|
||||||
|
|||||||
@@ -205,10 +205,9 @@ class CallableChoiceIterator:
|
|||||||
def __iter__(self) -> None: ...
|
def __iter__(self) -> None: ...
|
||||||
|
|
||||||
class ChoiceField(Field):
|
class ChoiceField(Field):
|
||||||
choices: Any = ...
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
choices: Any = ...,
|
choices: _FieldChoices = ...,
|
||||||
required: bool = ...,
|
required: bool = ...,
|
||||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||||
label: Optional[Any] = ...,
|
label: Optional[Any] = ...,
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Callable, Dict, Iterator, List, Mapping, MutableMapping, Optional, Sequence, Tuple, Type, Union
|
from typing import (
|
||||||
|
Any,
|
||||||
|
Callable,
|
||||||
|
Dict,
|
||||||
|
Iterator,
|
||||||
|
List,
|
||||||
|
Mapping,
|
||||||
|
MutableMapping,
|
||||||
|
Optional,
|
||||||
|
Sequence,
|
||||||
|
Tuple,
|
||||||
|
Type,
|
||||||
|
Union,
|
||||||
|
ClassVar,
|
||||||
|
Container,
|
||||||
|
TypeVar,
|
||||||
|
)
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
@@ -24,6 +40,11 @@ _Fields = Union[List[Union[Callable, str]], Sequence[str], Literal["__all__"]]
|
|||||||
_Labels = Dict[str, str]
|
_Labels = Dict[str, str]
|
||||||
_ErrorMessages = Dict[str, Dict[str, str]]
|
_ErrorMessages = Dict[str, Dict[str, str]]
|
||||||
|
|
||||||
|
_M = TypeVar("_M", bound=Model)
|
||||||
|
|
||||||
|
def construct_instance(
|
||||||
|
form: BaseForm, instance: _M, fields: Optional[Container[str]] = ..., exclude: Optional[Container[str]] = ...
|
||||||
|
) -> _M: ...
|
||||||
def model_to_dict(
|
def model_to_dict(
|
||||||
instance: Model, fields: Optional[_Fields] = ..., exclude: Optional[_Fields] = ...
|
instance: Model, fields: Optional[_Fields] = ..., exclude: Optional[_Fields] = ...
|
||||||
) -> Dict[str, Any]: ...
|
) -> Dict[str, Any]: ...
|
||||||
@@ -76,7 +97,8 @@ class BaseModelForm(BaseForm):
|
|||||||
save_m2m: Any = ...
|
save_m2m: Any = ...
|
||||||
def save(self, commit: bool = ...) -> Any: ...
|
def save(self, commit: bool = ...) -> Any: ...
|
||||||
|
|
||||||
class ModelForm(BaseModelForm): ...
|
class ModelForm(BaseModelForm, metaclass=ModelFormMetaclass):
|
||||||
|
base_fields: ClassVar[Dict[str, Field]] = ...
|
||||||
|
|
||||||
def modelform_factory(
|
def modelform_factory(
|
||||||
model: Type[Model],
|
model: Type[Model],
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ from typing import (
|
|||||||
|
|
||||||
from django.contrib.auth.base_user import AbstractBaseUser
|
from django.contrib.auth.base_user import AbstractBaseUser
|
||||||
from django.contrib.sessions.backends.base import SessionBase
|
from django.contrib.sessions.backends.base import SessionBase
|
||||||
|
from django.contrib.sites.models import Site
|
||||||
from django.utils.datastructures import CaseInsensitiveMapping, ImmutableList, MultiValueDict
|
from django.utils.datastructures import CaseInsensitiveMapping, ImmutableList, MultiValueDict
|
||||||
|
|
||||||
from django.core.files import uploadedfile, uploadhandler
|
from django.core.files import uploadedfile, uploadhandler
|
||||||
@@ -51,6 +52,7 @@ class HttpRequest(BytesIO):
|
|||||||
content_type: Optional[str] = ...
|
content_type: Optional[str] = ...
|
||||||
content_params: Optional[Dict[str, str]] = ...
|
content_params: Optional[Dict[str, str]] = ...
|
||||||
user: AbstractBaseUser
|
user: AbstractBaseUser
|
||||||
|
site: Site
|
||||||
session: SessionBase
|
session: SessionBase
|
||||||
encoding: Optional[str] = ...
|
encoding: Optional[str] = ...
|
||||||
upload_handlers: UploadHandlerList = ...
|
upload_handlers: UploadHandlerList = ...
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ class HttpResponseBase(Iterable[Any]):
|
|||||||
class HttpResponse(HttpResponseBase):
|
class HttpResponse(HttpResponseBase):
|
||||||
client: Client
|
client: Client
|
||||||
context: Context
|
context: Context
|
||||||
|
content: Any
|
||||||
csrf_cookie_set: bool
|
csrf_cookie_set: bool
|
||||||
redirect_chain: List[Tuple[str, int]]
|
redirect_chain: List[Tuple[str, int]]
|
||||||
request: Dict[str, Any]
|
request: Dict[str, Any]
|
||||||
@@ -78,10 +79,6 @@ class HttpResponse(HttpResponseBase):
|
|||||||
def __init__(self, content: object = ..., *args: Any, **kwargs: Any) -> None: ...
|
def __init__(self, content: object = ..., *args: Any, **kwargs: Any) -> None: ...
|
||||||
def serialize(self) -> bytes: ...
|
def serialize(self) -> bytes: ...
|
||||||
@property
|
@property
|
||||||
def content(self) -> Any: ...
|
|
||||||
@content.setter
|
|
||||||
def content(self, value: Any) -> None: ...
|
|
||||||
@property
|
|
||||||
def url(self) -> str: ...
|
def url(self) -> str: ...
|
||||||
def json(self) -> Dict[str, Any]: ...
|
def json(self) -> Dict[str, Any]: ...
|
||||||
|
|
||||||
@@ -107,7 +104,7 @@ class FileResponse(StreamingHttpResponse):
|
|||||||
def json(self) -> Dict[str, Any]: ...
|
def json(self) -> Dict[str, Any]: ...
|
||||||
|
|
||||||
class HttpResponseRedirectBase(HttpResponse):
|
class HttpResponseRedirectBase(HttpResponse):
|
||||||
allowed_schemes = ... # type: List[str]
|
allowed_schemes: List[str] = ...
|
||||||
def __init__(self, redirect_to: str, *args: Any, **kwargs: Any) -> None: ...
|
def __init__(self, redirect_to: str, *args: Any, **kwargs: Any) -> None: ...
|
||||||
|
|
||||||
class HttpResponseRedirect(HttpResponseRedirectBase): ...
|
class HttpResponseRedirect(HttpResponseRedirectBase): ...
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import threading
|
import threading
|
||||||
import unittest
|
import unittest
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Type, Union, ClassVar
|
from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Type, Union, ClassVar, overload
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.handlers.wsgi import WSGIHandler
|
from django.core.handlers.wsgi import WSGIHandler
|
||||||
@@ -146,9 +146,14 @@ class TransactionTestCase(SimpleTestCase):
|
|||||||
ordered: bool = ...,
|
ordered: bool = ...,
|
||||||
msg: Optional[str] = ...,
|
msg: Optional[str] = ...,
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
|
@overload
|
||||||
def assertNumQueries(
|
def assertNumQueries(
|
||||||
self, num: int, func: Optional[Union[Callable, Type[list]]] = ..., *args: Any, using: Any = ..., **kwargs: Any
|
self, num: int, func: Callable[..., Any], *args: Any, using: str = ..., **kwargs: Any
|
||||||
) -> Optional[_AssertNumQueriesContext]: ...
|
) -> None: ...
|
||||||
|
@overload
|
||||||
|
def assertNumQueries(
|
||||||
|
self, num: int, func: None = ..., *args: Any, using: str = ..., **kwargs: Any
|
||||||
|
) -> _AssertNumQueriesContext: ...
|
||||||
|
|
||||||
class TestCase(TransactionTestCase):
|
class TestCase(TransactionTestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -1,25 +1,59 @@
|
|||||||
from typing import Any, Optional
|
import datetime
|
||||||
|
from decimal import Decimal
|
||||||
|
from typing import Any, TypeVar, overload, Union
|
||||||
|
|
||||||
|
from django.utils.functional import Promise
|
||||||
|
from typing_extensions import Literal
|
||||||
|
|
||||||
class DjangoUnicodeDecodeError(UnicodeDecodeError):
|
class DjangoUnicodeDecodeError(UnicodeDecodeError):
|
||||||
obj: bytes = ...
|
obj: bytes = ...
|
||||||
def __init__(self, obj: bytes, *args: Any) -> None: ...
|
def __init__(self, obj: bytes, *args: Any) -> None: ...
|
||||||
|
|
||||||
python_2_unicode_compatible: Any
|
_P = TypeVar("_P", bound=Promise)
|
||||||
|
_S = TypeVar("_S", bound=str)
|
||||||
|
_PT = TypeVar("_PT", None, int, float, Decimal, datetime.datetime, datetime.date, datetime.time)
|
||||||
|
@overload
|
||||||
|
def smart_text(s: _P, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> _P: ...
|
||||||
|
@overload
|
||||||
|
def smart_text(s: _PT, encoding: str = ..., strings_only: Literal[True] = ..., errors: str = ...) -> _PT: ...
|
||||||
|
@overload
|
||||||
|
def smart_text(s: _S, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> _S: ...
|
||||||
|
@overload
|
||||||
def smart_text(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> str: ...
|
def smart_text(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> str: ...
|
||||||
def is_protected_type(obj: Any) -> bool: ...
|
def is_protected_type(obj: Any) -> bool: ...
|
||||||
def force_text(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> Optional[str]: ...
|
@overload
|
||||||
|
def force_text(s: _PT, encoding: str = ..., strings_only: Literal[True] = ..., errors: str = ...) -> _PT: ...
|
||||||
|
@overload
|
||||||
|
def force_text(s: _S, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> _S: ...
|
||||||
|
@overload
|
||||||
|
def force_text(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> str: ...
|
||||||
|
@overload
|
||||||
|
def smart_bytes(s: _P, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> _P: ...
|
||||||
|
@overload
|
||||||
|
def smart_bytes(s: _PT, encoding: str = ..., strings_only: Literal[True] = ..., errors: str = ...) -> _PT: ...
|
||||||
|
@overload
|
||||||
def smart_bytes(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> bytes: ...
|
def smart_bytes(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> bytes: ...
|
||||||
|
@overload
|
||||||
|
def force_bytes(s: _PT, encoding: str = ..., strings_only: Literal[True] = ..., errors: str = ...) -> _PT: ...
|
||||||
|
@overload
|
||||||
def force_bytes(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> bytes: ...
|
def force_bytes(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> bytes: ...
|
||||||
|
|
||||||
smart_str = smart_text
|
smart_str = smart_text
|
||||||
force_str = force_text
|
force_str = force_text
|
||||||
|
@overload
|
||||||
def iri_to_uri(iri: Optional[str]) -> Optional[str]: ...
|
def iri_to_uri(iri: None) -> None: ...
|
||||||
def uri_to_iri(uri: Optional[str]) -> Optional[str]: ...
|
@overload
|
||||||
|
def iri_to_uri(iri: Union[str, Promise]) -> str: ...
|
||||||
|
@overload
|
||||||
|
def uri_to_iri(iri: None) -> None: ...
|
||||||
|
@overload
|
||||||
|
def uri_to_iri(iri: str) -> str: ...
|
||||||
def escape_uri_path(path: str) -> str: ...
|
def escape_uri_path(path: str) -> str: ...
|
||||||
def repercent_broken_unicode(path: bytes) -> bytes: ...
|
def repercent_broken_unicode(path: bytes) -> bytes: ...
|
||||||
def filepath_to_uri(path: Optional[str]) -> Optional[str]: ...
|
@overload
|
||||||
|
def filepath_to_uri(path: None) -> None: ...
|
||||||
|
@overload
|
||||||
|
def filepath_to_uri(path: str) -> str: ...
|
||||||
def get_system_encoding() -> str: ...
|
def get_system_encoding() -> str: ...
|
||||||
|
|
||||||
DEFAULT_LOCALE_ENCODING: Any
|
DEFAULT_LOCALE_ENCODING: Any
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class Node:
|
|||||||
connector: str = ...
|
connector: str = ...
|
||||||
negated: bool = ...
|
negated: bool = ...
|
||||||
def __init__(
|
def __init__(
|
||||||
self, children: Optional[_NodeChildren] = ..., connector: Optional[str] = ..., negated: bool = ...,
|
self, children: Optional[_NodeChildren] = ..., connector: Optional[str] = ..., negated: bool = ...
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def __deepcopy__(self, memodict: Dict[Any, Any]) -> Node: ...
|
def __deepcopy__(self, memodict: Dict[Any, Any]) -> Node: ...
|
||||||
def __len__(self) -> int: ...
|
def __len__(self) -> int: ...
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
from typing import Any, Callable, Dict, Optional, Sequence, Type, Union
|
from typing import Any, Callable, Dict, Optional, Sequence, Type, Union
|
||||||
|
|
||||||
from django.forms.forms import BaseForm
|
from django.forms.forms import BaseForm
|
||||||
from django.http import HttpRequest, HttpResponse
|
|
||||||
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
|
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
|
||||||
from django.views.generic.detail import BaseDetailView, SingleObjectMixin, SingleObjectTemplateResponseMixin
|
from django.views.generic.detail import BaseDetailView, SingleObjectMixin, SingleObjectTemplateResponseMixin
|
||||||
from typing_extensions import Literal
|
from typing_extensions import Literal
|
||||||
|
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
|
||||||
class FormMixin(ContextMixin):
|
class FormMixin(ContextMixin):
|
||||||
initial: Dict[str, Any] = ...
|
initial: Dict[str, Any] = ...
|
||||||
form_class: Optional[Type[BaseForm]] = ...
|
form_class: Optional[Type[BaseForm]] = ...
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ class DjangoContext:
|
|||||||
if isinstance(field, ForeignObjectRel):
|
if isinstance(field, ForeignObjectRel):
|
||||||
yield field
|
yield field
|
||||||
|
|
||||||
def get_field_lookup_exact_type(self, api: TypeChecker, field: Field) -> MypyType:
|
def get_field_lookup_exact_type(self, api: TypeChecker, field: Union[Field, ForeignObjectRel]) -> MypyType:
|
||||||
if isinstance(field, (RelatedField, ForeignObjectRel)):
|
if isinstance(field, (RelatedField, ForeignObjectRel)):
|
||||||
related_model_cls = field.related_model
|
related_model_cls = field.related_model
|
||||||
primary_key_field = self.get_primary_key_field(related_model_cls)
|
primary_key_field = self.get_primary_key_field(related_model_cls)
|
||||||
@@ -134,10 +134,8 @@ class DjangoContext:
|
|||||||
if rel_model_info is None:
|
if rel_model_info is None:
|
||||||
return AnyType(TypeOfAny.explicit)
|
return AnyType(TypeOfAny.explicit)
|
||||||
|
|
||||||
model_and_primary_key_type = UnionType.make_union([Instance(rel_model_info, []),
|
model_and_primary_key_type = UnionType.make_union([Instance(rel_model_info, []), primary_key_type])
|
||||||
primary_key_type])
|
|
||||||
return helpers.make_optional(model_and_primary_key_type)
|
return helpers.make_optional(model_and_primary_key_type)
|
||||||
# return helpers.make_optional(Instance(rel_model_info, []))
|
|
||||||
|
|
||||||
field_info = helpers.lookup_class_typeinfo(api, field.__class__)
|
field_info = helpers.lookup_class_typeinfo(api, field.__class__)
|
||||||
if field_info is None:
|
if field_info is None:
|
||||||
@@ -228,21 +226,22 @@ class DjangoContext:
|
|||||||
attname = field.attname
|
attname = field.attname
|
||||||
return attname
|
return attname
|
||||||
|
|
||||||
def get_field_nullability(self, field: Field, method: Optional[str]) -> bool:
|
def get_field_nullability(self, field: Union[Field, ForeignObjectRel], method: Optional[str]) -> bool:
|
||||||
nullable = field.null
|
nullable = field.null
|
||||||
if not nullable and isinstance(field, CharField) and field.blank:
|
if not nullable and isinstance(field, CharField) and field.blank:
|
||||||
return True
|
return True
|
||||||
if method == '__init__':
|
if method == '__init__':
|
||||||
if field.primary_key or isinstance(field, ForeignKey):
|
if ((isinstance(field, Field) and field.primary_key)
|
||||||
|
or isinstance(field, ForeignKey)):
|
||||||
return True
|
return True
|
||||||
if method == 'create':
|
if method == 'create':
|
||||||
if isinstance(field, AutoField):
|
if isinstance(field, AutoField):
|
||||||
return True
|
return True
|
||||||
if field.has_default():
|
if isinstance(field, Field) and field.has_default():
|
||||||
return True
|
return True
|
||||||
return nullable
|
return nullable
|
||||||
|
|
||||||
def get_field_set_type(self, api: TypeChecker, field: Field, *, method: str) -> MypyType:
|
def get_field_set_type(self, api: TypeChecker, field: Union[Field, ForeignObjectRel], *, method: str) -> MypyType:
|
||||||
""" Get a type of __set__ for this specific Django field. """
|
""" Get a type of __set__ for this specific Django field. """
|
||||||
target_field = field
|
target_field = field
|
||||||
if isinstance(field, ForeignKey):
|
if isinstance(field, ForeignKey):
|
||||||
@@ -259,7 +258,7 @@ class DjangoContext:
|
|||||||
field_set_type = helpers.convert_any_to_type(field_set_type, argument_field_type)
|
field_set_type = helpers.convert_any_to_type(field_set_type, argument_field_type)
|
||||||
return field_set_type
|
return field_set_type
|
||||||
|
|
||||||
def get_field_get_type(self, api: TypeChecker, field: Field, *, method: str) -> MypyType:
|
def get_field_get_type(self, api: TypeChecker, field: Union[Field, ForeignObjectRel], *, method: str) -> MypyType:
|
||||||
""" Get a type of __get__ for this specific Django field. """
|
""" Get a type of __get__ for this specific Django field. """
|
||||||
field_info = helpers.lookup_class_typeinfo(api, field.__class__)
|
field_info = helpers.lookup_class_typeinfo(api, field.__class__)
|
||||||
if field_info is None:
|
if field_info is None:
|
||||||
@@ -303,7 +302,10 @@ class DjangoContext:
|
|||||||
|
|
||||||
return related_model_cls
|
return related_model_cls
|
||||||
|
|
||||||
def _resolve_field_from_parts(self, field_parts: Iterable[str], model_cls: Type[Model]) -> Field:
|
def _resolve_field_from_parts(self,
|
||||||
|
field_parts: Iterable[str],
|
||||||
|
model_cls: Type[Model]
|
||||||
|
) -> Union[Field, ForeignObjectRel]:
|
||||||
currently_observed_model = model_cls
|
currently_observed_model = model_cls
|
||||||
field = None
|
field = None
|
||||||
for field_part in field_parts:
|
for field_part in field_parts:
|
||||||
@@ -325,7 +327,7 @@ class DjangoContext:
|
|||||||
assert field is not None
|
assert field is not None
|
||||||
return field
|
return field
|
||||||
|
|
||||||
def resolve_lookup_into_field(self, model_cls: Type[Model], lookup: str) -> Field:
|
def resolve_lookup_into_field(self, model_cls: Type[Model], lookup: str) -> Union[Field, ForeignObjectRel]:
|
||||||
query = Query(model_cls)
|
query = Query(model_cls)
|
||||||
lookup_parts, field_parts, is_expression = query.solve_lookup_type(lookup)
|
lookup_parts, field_parts, is_expression = query.solve_lookup_type(lookup)
|
||||||
if lookup_parts:
|
if lookup_parts:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ DUMMY_SETTINGS_BASE_CLASS = 'django.conf._DjangoConfLazyObject'
|
|||||||
QUERYSET_CLASS_FULLNAME = 'django.db.models.query.QuerySet'
|
QUERYSET_CLASS_FULLNAME = 'django.db.models.query.QuerySet'
|
||||||
BASE_MANAGER_CLASS_FULLNAME = 'django.db.models.manager.BaseManager'
|
BASE_MANAGER_CLASS_FULLNAME = 'django.db.models.manager.BaseManager'
|
||||||
MANAGER_CLASS_FULLNAME = 'django.db.models.manager.Manager'
|
MANAGER_CLASS_FULLNAME = 'django.db.models.manager.Manager'
|
||||||
RELATED_MANAGER_CLASS_FULLNAME = 'django.db.models.manager.RelatedManager'
|
RELATED_MANAGER_CLASS = 'django.db.models.manager.RelatedManager'
|
||||||
|
|
||||||
BASEFORM_CLASS_FULLNAME = 'django.forms.forms.BaseForm'
|
BASEFORM_CLASS_FULLNAME = 'django.forms.forms.BaseForm'
|
||||||
FORM_CLASS_FULLNAME = 'django.forms.forms.Form'
|
FORM_CLASS_FULLNAME = 'django.forms.forms.Form'
|
||||||
@@ -23,9 +23,7 @@ FORM_MIXIN_CLASS_FULLNAME = 'django.views.generic.edit.FormMixin'
|
|||||||
|
|
||||||
MANAGER_CLASSES = {
|
MANAGER_CLASSES = {
|
||||||
MANAGER_CLASS_FULLNAME,
|
MANAGER_CLASS_FULLNAME,
|
||||||
RELATED_MANAGER_CLASS_FULLNAME,
|
|
||||||
BASE_MANAGER_CLASS_FULLNAME,
|
BASE_MANAGER_CLASS_FULLNAME,
|
||||||
# QUERYSET_CLASS_FULLNAME
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RELATED_FIELDS_CLASSES = {
|
RELATED_FIELDS_CLASSES = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from typing import (
|
from typing import (
|
||||||
TYPE_CHECKING, Any, Dict, Iterable, Iterator, List, Optional, Set, Union, cast,
|
TYPE_CHECKING, Any, Dict, Iterable, Iterator, List, Optional, Set, Tuple, Union,
|
||||||
)
|
)
|
||||||
|
|
||||||
from django.db.models.fields import Field
|
from django.db.models.fields import Field
|
||||||
@@ -10,13 +10,15 @@ from mypy import checker
|
|||||||
from mypy.checker import TypeChecker
|
from mypy.checker import TypeChecker
|
||||||
from mypy.mro import calculate_mro
|
from mypy.mro import calculate_mro
|
||||||
from mypy.nodes import (
|
from mypy.nodes import (
|
||||||
GDEF, MDEF, Block, ClassDef, Expression, MemberExpr, MypyFile, NameExpr, StrExpr, SymbolNode, SymbolTable,
|
GDEF, MDEF, Argument, Block, ClassDef, Expression, FuncDef, MemberExpr, MypyFile, NameExpr, StrExpr, SymbolNode,
|
||||||
SymbolTableNode, TypeInfo, Var,
|
SymbolTable, SymbolTableNode, TypeInfo, Var,
|
||||||
)
|
)
|
||||||
from mypy.plugin import (
|
from mypy.plugin import (
|
||||||
AttributeContext, CheckerPluginInterface, FunctionContext, MethodContext,
|
AttributeContext, CheckerPluginInterface, ClassDefContext, DynamicClassDefContext, FunctionContext, MethodContext,
|
||||||
)
|
)
|
||||||
from mypy.types import AnyType, Instance, NoneTyp, TupleType
|
from mypy.plugins.common import add_method
|
||||||
|
from mypy.semanal import SemanticAnalyzer
|
||||||
|
from mypy.types import AnyType, CallableType, Instance, NoneTyp, TupleType
|
||||||
from mypy.types import Type as MypyType
|
from mypy.types import Type as MypyType
|
||||||
from mypy.types import TypedDictType, TypeOfAny, UnionType
|
from mypy.types import TypedDictType, TypeOfAny, UnionType
|
||||||
|
|
||||||
@@ -55,7 +57,7 @@ def lookup_fully_qualified_generic(name: str, all_modules: Dict[str, MypyFile])
|
|||||||
return sym.node
|
return sym.node
|
||||||
|
|
||||||
|
|
||||||
def lookup_fully_qualified_typeinfo(api: TypeChecker, fullname: str) -> Optional[TypeInfo]:
|
def lookup_fully_qualified_typeinfo(api: Union[TypeChecker, SemanticAnalyzer], fullname: str) -> Optional[TypeInfo]:
|
||||||
node = lookup_fully_qualified_generic(fullname, api.modules)
|
node = lookup_fully_qualified_generic(fullname, api.modules)
|
||||||
if not isinstance(node, TypeInfo):
|
if not isinstance(node, TypeInfo):
|
||||||
return None
|
return None
|
||||||
@@ -173,8 +175,11 @@ def get_nested_meta_node_for_current_class(info: TypeInfo) -> Optional[TypeInfo]
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def add_new_class_for_module(module: MypyFile, name: str, bases: List[Instance],
|
def add_new_class_for_module(module: MypyFile,
|
||||||
fields: 'OrderedDict[str, MypyType]') -> TypeInfo:
|
name: str,
|
||||||
|
bases: List[Instance],
|
||||||
|
fields: Optional[Dict[str, MypyType]] = None
|
||||||
|
) -> TypeInfo:
|
||||||
new_class_unique_name = checker.gen_unique_name(name, module.names)
|
new_class_unique_name = checker.gen_unique_name(name, module.names)
|
||||||
|
|
||||||
# make new class expression
|
# make new class expression
|
||||||
@@ -188,6 +193,7 @@ def add_new_class_for_module(module: MypyFile, name: str, bases: List[Instance],
|
|||||||
new_typeinfo.calculate_metaclass_type()
|
new_typeinfo.calculate_metaclass_type()
|
||||||
|
|
||||||
# add fields
|
# add fields
|
||||||
|
if fields:
|
||||||
for field_name, field_type in fields.items():
|
for field_name, field_type in fields.items():
|
||||||
var = Var(field_name, type=field_type)
|
var = Var(field_name, type=field_type)
|
||||||
var.info = new_typeinfo
|
var.info = new_typeinfo
|
||||||
@@ -253,8 +259,7 @@ def make_typeddict(api: CheckerPluginInterface, fields: 'OrderedDict[str, MypyTy
|
|||||||
return typed_dict_type
|
return typed_dict_type
|
||||||
|
|
||||||
|
|
||||||
def resolve_string_attribute_value(attr_expr: Expression, ctx: Union[FunctionContext, MethodContext],
|
def resolve_string_attribute_value(attr_expr: Expression, django_context: 'DjangoContext') -> Optional[str]:
|
||||||
django_context: 'DjangoContext') -> Optional[str]:
|
|
||||||
if isinstance(attr_expr, StrExpr):
|
if isinstance(attr_expr, StrExpr):
|
||||||
return attr_expr.value
|
return attr_expr.value
|
||||||
|
|
||||||
@@ -264,15 +269,19 @@ def resolve_string_attribute_value(attr_expr: Expression, ctx: Union[FunctionCon
|
|||||||
if isinstance(attr_expr.expr, NameExpr) and attr_expr.expr.fullname == 'django.conf.settings':
|
if isinstance(attr_expr.expr, NameExpr) and attr_expr.expr.fullname == 'django.conf.settings':
|
||||||
if hasattr(django_context.settings, member_name):
|
if hasattr(django_context.settings, member_name):
|
||||||
return getattr(django_context.settings, member_name)
|
return getattr(django_context.settings, member_name)
|
||||||
|
|
||||||
ctx.api.fail(f'Expression of type {type(attr_expr).__name__!r} is not supported', ctx.context)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_semanal_api(ctx: Union[ClassDefContext, DynamicClassDefContext]) -> SemanticAnalyzer:
|
||||||
|
if not isinstance(ctx.api, SemanticAnalyzer):
|
||||||
|
raise ValueError('Not a SemanticAnalyzer')
|
||||||
|
return ctx.api
|
||||||
|
|
||||||
|
|
||||||
def get_typechecker_api(ctx: Union[AttributeContext, MethodContext, FunctionContext]) -> TypeChecker:
|
def get_typechecker_api(ctx: Union[AttributeContext, MethodContext, FunctionContext]) -> TypeChecker:
|
||||||
if not isinstance(ctx.api, TypeChecker):
|
if not isinstance(ctx.api, TypeChecker):
|
||||||
raise ValueError('Not a TypeChecker')
|
raise ValueError('Not a TypeChecker')
|
||||||
return cast(TypeChecker, ctx.api)
|
return ctx.api
|
||||||
|
|
||||||
|
|
||||||
def is_model_subclass_info(info: TypeInfo, django_context: 'DjangoContext') -> bool:
|
def is_model_subclass_info(info: TypeInfo, django_context: 'DjangoContext') -> bool:
|
||||||
@@ -298,3 +307,28 @@ def add_new_sym_for_info(info: TypeInfo, *, name: str, sym_type: MypyType) -> No
|
|||||||
var.is_inferred = True
|
var.is_inferred = True
|
||||||
info.names[name] = SymbolTableNode(MDEF, var,
|
info.names[name] = SymbolTableNode(MDEF, var,
|
||||||
plugin_generated=True)
|
plugin_generated=True)
|
||||||
|
|
||||||
|
|
||||||
|
def _prepare_new_method_arguments(node: FuncDef) -> Tuple[List[Argument], MypyType]:
|
||||||
|
arguments = []
|
||||||
|
for argument in node.arguments[1:]:
|
||||||
|
if argument.type_annotation is None:
|
||||||
|
argument.type_annotation = AnyType(TypeOfAny.unannotated)
|
||||||
|
arguments.append(argument)
|
||||||
|
|
||||||
|
if isinstance(node.type, CallableType):
|
||||||
|
return_type = node.type.ret_type
|
||||||
|
else:
|
||||||
|
return_type = AnyType(TypeOfAny.unannotated)
|
||||||
|
|
||||||
|
return arguments, return_type
|
||||||
|
|
||||||
|
|
||||||
|
def copy_method_to_another_class(ctx: ClassDefContext, self_type: Instance,
|
||||||
|
new_method_name: str, method_node: FuncDef) -> None:
|
||||||
|
arguments, return_type = _prepare_new_method_arguments(method_node)
|
||||||
|
add_method(ctx,
|
||||||
|
new_method_name,
|
||||||
|
args=arguments,
|
||||||
|
return_type=return_type,
|
||||||
|
self_type=self_type)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from mypy.errors import Errors
|
|||||||
from mypy.nodes import MypyFile, TypeInfo
|
from mypy.nodes import MypyFile, TypeInfo
|
||||||
from mypy.options import Options
|
from mypy.options import Options
|
||||||
from mypy.plugin import (
|
from mypy.plugin import (
|
||||||
AttributeContext, ClassDefContext, FunctionContext, MethodContext, Plugin,
|
AttributeContext, ClassDefContext, DynamicClassDefContext, FunctionContext, MethodContext, Plugin,
|
||||||
)
|
)
|
||||||
from mypy.types import Type as MypyType
|
from mypy.types import Type as MypyType
|
||||||
|
|
||||||
@@ -17,6 +17,9 @@ from mypy_django_plugin.lib import fullnames, helpers
|
|||||||
from mypy_django_plugin.transformers import (
|
from mypy_django_plugin.transformers import (
|
||||||
fields, forms, init_create, meta, querysets, request, settings,
|
fields, forms, init_create, meta, querysets, request, settings,
|
||||||
)
|
)
|
||||||
|
from mypy_django_plugin.transformers.managers import (
|
||||||
|
create_new_manager_class_from_from_queryset_method,
|
||||||
|
)
|
||||||
from mypy_django_plugin.transformers.models import process_model_class
|
from mypy_django_plugin.transformers.models import process_model_class
|
||||||
|
|
||||||
|
|
||||||
@@ -242,6 +245,15 @@ class NewSemanalDjangoPlugin(Plugin):
|
|||||||
return partial(request.set_auth_user_model_as_type_for_request_user, django_context=self.django_context)
|
return partial(request.set_auth_user_model_as_type_for_request_user, django_context=self.django_context)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_dynamic_class_hook(self, fullname: str
|
||||||
|
) -> Optional[Callable[[DynamicClassDefContext], None]]:
|
||||||
|
if fullname.endswith('from_queryset'):
|
||||||
|
class_name, _, _ = fullname.rpartition('.')
|
||||||
|
info = self._get_typeinfo_or_none(class_name)
|
||||||
|
if info and info.has_base(fullnames.BASE_MANAGER_CLASS_FULLNAME):
|
||||||
|
return create_new_manager_class_from_from_queryset_method
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def plugin(version):
|
def plugin(version):
|
||||||
return NewSemanalDjangoPlugin
|
return NewSemanalDjangoPlugin
|
||||||
|
|||||||
73
mypy_django_plugin/transformers/managers.py
Normal file
73
mypy_django_plugin/transformers/managers.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
from mypy.nodes import (
|
||||||
|
GDEF, FuncDef, MemberExpr, NameExpr, RefExpr, StrExpr, SymbolTableNode, TypeInfo,
|
||||||
|
)
|
||||||
|
from mypy.plugin import ClassDefContext, DynamicClassDefContext
|
||||||
|
from mypy.types import AnyType, Instance, TypeOfAny
|
||||||
|
|
||||||
|
from mypy_django_plugin.lib import helpers
|
||||||
|
|
||||||
|
|
||||||
|
def create_new_manager_class_from_from_queryset_method(ctx: DynamicClassDefContext) -> None:
|
||||||
|
semanal_api = helpers.get_semanal_api(ctx)
|
||||||
|
|
||||||
|
callee = ctx.call.callee
|
||||||
|
assert isinstance(callee, MemberExpr)
|
||||||
|
assert isinstance(callee.expr, RefExpr)
|
||||||
|
|
||||||
|
base_manager_info = callee.expr.node
|
||||||
|
if base_manager_info is None:
|
||||||
|
if not semanal_api.final_iteration:
|
||||||
|
semanal_api.defer()
|
||||||
|
return
|
||||||
|
|
||||||
|
assert isinstance(base_manager_info, TypeInfo)
|
||||||
|
new_manager_info = semanal_api.basic_new_typeinfo(ctx.name,
|
||||||
|
basetype_or_fallback=Instance(base_manager_info,
|
||||||
|
[AnyType(TypeOfAny.unannotated)]))
|
||||||
|
new_manager_info.line = ctx.call.line
|
||||||
|
new_manager_info.defn.line = ctx.call.line
|
||||||
|
new_manager_info.metaclass_type = new_manager_info.calculate_metaclass_type()
|
||||||
|
|
||||||
|
current_module = semanal_api.cur_mod_node
|
||||||
|
current_module.names[ctx.name] = SymbolTableNode(GDEF, new_manager_info,
|
||||||
|
plugin_generated=True)
|
||||||
|
passed_queryset = ctx.call.args[0]
|
||||||
|
assert isinstance(passed_queryset, NameExpr)
|
||||||
|
|
||||||
|
derived_queryset_fullname = passed_queryset.fullname
|
||||||
|
assert derived_queryset_fullname is not None
|
||||||
|
|
||||||
|
sym = semanal_api.lookup_fully_qualified_or_none(derived_queryset_fullname)
|
||||||
|
assert sym is not None
|
||||||
|
if sym.node is None:
|
||||||
|
if not semanal_api.final_iteration:
|
||||||
|
semanal_api.defer()
|
||||||
|
else:
|
||||||
|
# inherit from Any to prevent false-positives, if queryset class cannot be resolved
|
||||||
|
new_manager_info.fallback_to_any = True
|
||||||
|
return
|
||||||
|
|
||||||
|
derived_queryset_info = sym.node
|
||||||
|
assert isinstance(derived_queryset_info, TypeInfo)
|
||||||
|
|
||||||
|
if len(ctx.call.args) > 1:
|
||||||
|
expr = ctx.call.args[1]
|
||||||
|
assert isinstance(expr, StrExpr)
|
||||||
|
custom_manager_generated_name = expr.value
|
||||||
|
else:
|
||||||
|
custom_manager_generated_name = base_manager_info.name + 'From' + derived_queryset_info.name
|
||||||
|
|
||||||
|
custom_manager_generated_fullname = '.'.join(['django.db.models.manager', custom_manager_generated_name])
|
||||||
|
if 'from_queryset_managers' not in base_manager_info.metadata:
|
||||||
|
base_manager_info.metadata['from_queryset_managers'] = {}
|
||||||
|
base_manager_info.metadata['from_queryset_managers'][custom_manager_generated_fullname] = new_manager_info.fullname
|
||||||
|
|
||||||
|
class_def_context = ClassDefContext(cls=new_manager_info.defn,
|
||||||
|
reason=ctx.call, api=semanal_api)
|
||||||
|
self_type = Instance(new_manager_info, [])
|
||||||
|
for name, sym in derived_queryset_info.names.items():
|
||||||
|
if isinstance(sym.node, FuncDef):
|
||||||
|
helpers.copy_method_to_another_class(class_def_context,
|
||||||
|
self_type,
|
||||||
|
new_method_name=name,
|
||||||
|
method_node=sym.node)
|
||||||
@@ -36,7 +36,7 @@ def return_proper_field_type_from_get_field(ctx: MethodContext, django_context:
|
|||||||
if field_name_expr is None:
|
if field_name_expr is None:
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
|
|
||||||
field_name = helpers.resolve_string_attribute_value(field_name_expr, ctx, django_context)
|
field_name = helpers.resolve_string_attribute_value(field_name_expr, django_context)
|
||||||
if field_name is None:
|
if field_name is None:
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
from collections import OrderedDict
|
from typing import Dict, Optional, Type, cast
|
||||||
from typing import List, Tuple, Type
|
|
||||||
|
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
from django.db.models.fields import DateField, DateTimeField
|
from django.db.models.fields import DateField, DateTimeField
|
||||||
@@ -10,8 +9,8 @@ from django.db.models.fields.reverse_related import (
|
|||||||
from mypy.nodes import ARG_STAR2, Argument, Context, FuncDef, TypeInfo, Var
|
from mypy.nodes import ARG_STAR2, Argument, Context, FuncDef, TypeInfo, Var
|
||||||
from mypy.plugin import ClassDefContext
|
from mypy.plugin import ClassDefContext
|
||||||
from mypy.plugins import common
|
from mypy.plugins import common
|
||||||
from mypy.plugins.common import add_method
|
from mypy.semanal import SemanticAnalyzer
|
||||||
from mypy.types import AnyType, CallableType, Instance
|
from mypy.types import AnyType, Instance
|
||||||
from mypy.types import Type as MypyType
|
from mypy.types import Type as MypyType
|
||||||
from mypy.types import TypeOfAny
|
from mypy.types import TypeOfAny
|
||||||
|
|
||||||
@@ -22,17 +21,22 @@ from mypy_django_plugin.transformers.fields import get_field_descriptor_types
|
|||||||
|
|
||||||
|
|
||||||
class ModelClassInitializer:
|
class ModelClassInitializer:
|
||||||
|
api: SemanticAnalyzer
|
||||||
|
|
||||||
def __init__(self, ctx: ClassDefContext, django_context: DjangoContext):
|
def __init__(self, ctx: ClassDefContext, django_context: DjangoContext):
|
||||||
self.api = ctx.api
|
self.api = cast(SemanticAnalyzer, ctx.api)
|
||||||
self.model_classdef = ctx.cls
|
self.model_classdef = ctx.cls
|
||||||
self.django_context = django_context
|
self.django_context = django_context
|
||||||
self.ctx = ctx
|
self.ctx = ctx
|
||||||
|
|
||||||
|
def lookup_typeinfo(self, fullname: str) -> Optional[TypeInfo]:
|
||||||
|
return helpers.lookup_fully_qualified_typeinfo(self.api, fullname)
|
||||||
|
|
||||||
def lookup_typeinfo_or_incomplete_defn_error(self, fullname: str) -> TypeInfo:
|
def lookup_typeinfo_or_incomplete_defn_error(self, fullname: str) -> TypeInfo:
|
||||||
sym = self.api.lookup_fully_qualified_or_none(fullname)
|
info = self.lookup_typeinfo(fullname)
|
||||||
if sym is None or not isinstance(sym.node, TypeInfo):
|
if info is None:
|
||||||
raise helpers.IncompleteDefnException(f'No {fullname!r} found')
|
raise helpers.IncompleteDefnException(f'No {fullname!r} found')
|
||||||
return sym.node
|
return info
|
||||||
|
|
||||||
def lookup_class_typeinfo_or_incomplete_defn_error(self, klass: type) -> TypeInfo:
|
def lookup_class_typeinfo_or_incomplete_defn_error(self, klass: type) -> TypeInfo:
|
||||||
fullname = helpers.get_class_fullname(klass)
|
fullname = helpers.get_class_fullname(klass)
|
||||||
@@ -118,7 +122,14 @@ class AddRelatedModelsId(ModelClassInitializer):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
rel_primary_key_field = self.django_context.get_primary_key_field(related_model_cls)
|
rel_primary_key_field = self.django_context.get_primary_key_field(related_model_cls)
|
||||||
|
try:
|
||||||
field_info = self.lookup_class_typeinfo_or_incomplete_defn_error(rel_primary_key_field.__class__)
|
field_info = self.lookup_class_typeinfo_or_incomplete_defn_error(rel_primary_key_field.__class__)
|
||||||
|
except helpers.IncompleteDefnException as exc:
|
||||||
|
if not self.api.final_iteration:
|
||||||
|
raise exc
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
is_nullable = self.django_context.get_field_nullability(field, None)
|
is_nullable = self.django_context.get_field_nullability(field, None)
|
||||||
set_type, get_type = get_field_descriptor_types(field_info, is_nullable)
|
set_type, get_type = get_field_descriptor_types(field_info, is_nullable)
|
||||||
self.add_new_node_to_model_class(field.attname,
|
self.add_new_node_to_model_class(field.attname,
|
||||||
@@ -126,26 +137,26 @@ class AddRelatedModelsId(ModelClassInitializer):
|
|||||||
|
|
||||||
|
|
||||||
class AddManagers(ModelClassInitializer):
|
class AddManagers(ModelClassInitializer):
|
||||||
def _is_manager_any(self, typ: Instance) -> bool:
|
def has_any_parametrized_manager_as_base(self, info: TypeInfo) -> bool:
|
||||||
return typ.type.fullname == fullnames.MANAGER_CLASS_FULLNAME and type(typ.args[0]) == AnyType
|
for base in helpers.iter_bases(info):
|
||||||
|
if self.is_any_parametrized_manager(base):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def run_with_model_cls(self, model_cls: Type[Model]) -> None:
|
def is_any_parametrized_manager(self, typ: Instance) -> bool:
|
||||||
for manager_name, manager in model_cls._meta.managers_map.items():
|
return typ.type.fullname in fullnames.MANAGER_CLASSES and isinstance(typ.args[0], AnyType)
|
||||||
manager_fullname = helpers.get_class_fullname(manager.__class__)
|
|
||||||
manager_info = self.lookup_typeinfo_or_incomplete_defn_error(manager_fullname)
|
|
||||||
|
|
||||||
if manager_name not in self.model_classdef.info.names:
|
def get_generated_manager_mappings(self, base_manager_fullname: str) -> Dict[str, str]:
|
||||||
manager_type = Instance(manager_info, [Instance(self.model_classdef.info, [])])
|
base_manager_info = self.lookup_typeinfo(base_manager_fullname)
|
||||||
self.add_new_node_to_model_class(manager_name, manager_type)
|
if (base_manager_info is None
|
||||||
else:
|
or 'from_queryset_managers' not in base_manager_info.metadata):
|
||||||
# creates new MODELNAME_MANAGERCLASSNAME class that represents manager parametrized with current model
|
return {}
|
||||||
has_manager_any_base = any(self._is_manager_any(base) for base in manager_info.bases)
|
return base_manager_info.metadata['from_queryset_managers']
|
||||||
if has_manager_any_base:
|
|
||||||
custom_model_manager_name = manager.model.__name__ + '_' + manager.__class__.__name__
|
|
||||||
|
|
||||||
|
def create_new_model_parametrized_manager(self, name: str, base_manager_info: TypeInfo) -> Instance:
|
||||||
bases = []
|
bases = []
|
||||||
for original_base in manager_info.bases:
|
for original_base in base_manager_info.bases:
|
||||||
if self._is_manager_any(original_base):
|
if self.is_any_parametrized_manager(original_base):
|
||||||
if original_base.type is None:
|
if original_base.type is None:
|
||||||
raise helpers.IncompleteDefnException()
|
raise helpers.IncompleteDefnException()
|
||||||
|
|
||||||
@@ -155,24 +166,20 @@ class AddManagers(ModelClassInitializer):
|
|||||||
|
|
||||||
current_module = self.api.modules[self.model_classdef.info.module_name]
|
current_module = self.api.modules[self.model_classdef.info.module_name]
|
||||||
custom_manager_info = helpers.add_new_class_for_module(current_module,
|
custom_manager_info = helpers.add_new_class_for_module(current_module,
|
||||||
custom_model_manager_name,
|
name=name, bases=bases)
|
||||||
bases=bases,
|
|
||||||
fields=OrderedDict())
|
|
||||||
# copy fields to a new manager
|
# copy fields to a new manager
|
||||||
new_cls_def_context = ClassDefContext(cls=custom_manager_info.defn,
|
new_cls_def_context = ClassDefContext(cls=custom_manager_info.defn,
|
||||||
reason=self.ctx.reason,
|
reason=self.ctx.reason,
|
||||||
api=self.api)
|
api=self.api)
|
||||||
custom_manager_type = Instance(custom_manager_info, [Instance(self.model_classdef.info, [])])
|
custom_manager_type = Instance(custom_manager_info, [Instance(self.model_classdef.info, [])])
|
||||||
|
|
||||||
for name, sym in manager_info.names.items():
|
for name, sym in base_manager_info.names.items():
|
||||||
# replace self type with new class, if copying method
|
# replace self type with new class, if copying method
|
||||||
if isinstance(sym.node, FuncDef):
|
if isinstance(sym.node, FuncDef):
|
||||||
arguments, return_type = self.prepare_new_method_arguments(sym.node)
|
helpers.copy_method_to_another_class(new_cls_def_context,
|
||||||
add_method(new_cls_def_context,
|
self_type=custom_manager_type,
|
||||||
name,
|
new_method_name=name,
|
||||||
args=arguments,
|
method_node=sym.node)
|
||||||
return_type=return_type,
|
|
||||||
self_type=custom_manager_type)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
new_sym = sym.copy()
|
new_sym = sym.copy()
|
||||||
@@ -183,21 +190,45 @@ class AddManagers(ModelClassInitializer):
|
|||||||
new_sym.node = new_var
|
new_sym.node = new_var
|
||||||
custom_manager_info.names[name] = new_sym
|
custom_manager_info.names[name] = new_sym
|
||||||
|
|
||||||
self.add_new_node_to_model_class(manager_name, custom_manager_type)
|
return custom_manager_type
|
||||||
|
|
||||||
def prepare_new_method_arguments(self, node: FuncDef) -> Tuple[List[Argument], MypyType]:
|
def run_with_model_cls(self, model_cls: Type[Model]) -> None:
|
||||||
arguments = []
|
for manager_name, manager in model_cls._meta.managers_map.items():
|
||||||
for argument in node.arguments[1:]:
|
manager_class_name = manager.__class__.__name__
|
||||||
if argument.type_annotation is None:
|
manager_fullname = helpers.get_class_fullname(manager.__class__)
|
||||||
argument.type_annotation = AnyType(TypeOfAny.unannotated)
|
try:
|
||||||
arguments.append(argument)
|
manager_info = self.lookup_typeinfo_or_incomplete_defn_error(manager_fullname)
|
||||||
|
except helpers.IncompleteDefnException as exc:
|
||||||
if isinstance(node.type, CallableType):
|
if not self.api.final_iteration:
|
||||||
return_type = node.type.ret_type
|
raise exc
|
||||||
else:
|
else:
|
||||||
return_type = AnyType(TypeOfAny.unannotated)
|
base_manager_fullname = helpers.get_class_fullname(manager.__class__.__bases__[0])
|
||||||
|
generated_managers = self.get_generated_manager_mappings(base_manager_fullname)
|
||||||
|
if manager_fullname not in generated_managers:
|
||||||
|
# not a generated manager, continue with the loop
|
||||||
|
continue
|
||||||
|
real_manager_fullname = generated_managers[manager_fullname]
|
||||||
|
manager_info = self.lookup_typeinfo(real_manager_fullname) # type: ignore
|
||||||
|
if manager_info is None:
|
||||||
|
continue
|
||||||
|
manager_class_name = real_manager_fullname.rsplit('.', maxsplit=1)[1]
|
||||||
|
|
||||||
return arguments, return_type
|
if manager_name not in self.model_classdef.info.names:
|
||||||
|
manager_type = Instance(manager_info, [Instance(self.model_classdef.info, [])])
|
||||||
|
self.add_new_node_to_model_class(manager_name, manager_type)
|
||||||
|
else:
|
||||||
|
# creates new MODELNAME_MANAGERCLASSNAME class that represents manager parametrized with current model
|
||||||
|
if not self.has_any_parametrized_manager_as_base(manager_info):
|
||||||
|
continue
|
||||||
|
|
||||||
|
custom_model_manager_name = manager.model.__name__ + '_' + manager_class_name
|
||||||
|
try:
|
||||||
|
custom_manager_type = self.create_new_model_parametrized_manager(custom_model_manager_name,
|
||||||
|
base_manager_info=manager_info)
|
||||||
|
except helpers.IncompleteDefnException:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.add_new_node_to_model_class(manager_name, custom_manager_type)
|
||||||
|
|
||||||
|
|
||||||
class AddDefaultManagerAttribute(ModelClassInitializer):
|
class AddDefaultManagerAttribute(ModelClassInitializer):
|
||||||
@@ -223,13 +254,26 @@ class AddRelatedManagers(ModelClassInitializer):
|
|||||||
if related_model_cls is None:
|
if related_model_cls is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
related_model_info = self.lookup_class_typeinfo_or_incomplete_defn_error(related_model_cls)
|
related_model_info = self.lookup_class_typeinfo_or_incomplete_defn_error(related_model_cls)
|
||||||
|
except helpers.IncompleteDefnException as exc:
|
||||||
|
if not self.api.final_iteration:
|
||||||
|
raise exc
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
if isinstance(relation, OneToOneRel):
|
if isinstance(relation, OneToOneRel):
|
||||||
self.add_new_node_to_model_class(attname, Instance(related_model_info, []))
|
self.add_new_node_to_model_class(attname, Instance(related_model_info, []))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if isinstance(relation, (ManyToOneRel, ManyToManyRel)):
|
if isinstance(relation, (ManyToOneRel, ManyToManyRel)):
|
||||||
manager_info = self.lookup_typeinfo_or_incomplete_defn_error(fullnames.RELATED_MANAGER_CLASS_FULLNAME)
|
try:
|
||||||
|
manager_info = self.lookup_typeinfo_or_incomplete_defn_error(fullnames.RELATED_MANAGER_CLASS)
|
||||||
|
except helpers.IncompleteDefnException as exc:
|
||||||
|
if not self.api.final_iteration:
|
||||||
|
raise exc
|
||||||
|
else:
|
||||||
|
continue
|
||||||
self.add_new_node_to_model_class(attname,
|
self.add_new_node_to_model_class(attname,
|
||||||
Instance(manager_info, [Instance(related_model_info, [])]))
|
Instance(manager_info, [Instance(related_model_info, [])]))
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from typing import List, Optional, Sequence, Type, Union
|
from typing import List, Optional, Sequence, Type
|
||||||
|
|
||||||
from django.core.exceptions import FieldError
|
from django.core.exceptions import FieldError
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
from django.db.models.fields.related import RelatedField
|
from django.db.models.fields.related import RelatedField
|
||||||
|
from django.db.models.fields.reverse_related import ForeignObjectRel
|
||||||
from mypy.nodes import Expression, NameExpr
|
from mypy.nodes import Expression, NameExpr
|
||||||
from mypy.plugin import FunctionContext, MethodContext
|
from mypy.plugin import FunctionContext, MethodContext
|
||||||
from mypy.types import AnyType, Instance
|
from mypy.types import AnyType, Instance
|
||||||
@@ -47,7 +48,8 @@ def get_field_type_from_lookup(ctx: MethodContext, django_context: DjangoContext
|
|||||||
except LookupsAreUnsupported:
|
except LookupsAreUnsupported:
|
||||||
return AnyType(TypeOfAny.explicit)
|
return AnyType(TypeOfAny.explicit)
|
||||||
|
|
||||||
if isinstance(lookup_field, RelatedField) and lookup_field.column == lookup:
|
if ((isinstance(lookup_field, RelatedField) and lookup_field.column == lookup)
|
||||||
|
or isinstance(lookup_field, ForeignObjectRel)):
|
||||||
related_model_cls = django_context.get_field_related_model_cls(lookup_field)
|
related_model_cls = django_context.get_field_related_model_cls(lookup_field)
|
||||||
if related_model_cls is None:
|
if related_model_cls is None:
|
||||||
return AnyType(TypeOfAny.from_error)
|
return AnyType(TypeOfAny.from_error)
|
||||||
@@ -60,7 +62,7 @@ def get_field_type_from_lookup(ctx: MethodContext, django_context: DjangoContext
|
|||||||
|
|
||||||
def get_values_list_row_type(ctx: MethodContext, django_context: DjangoContext, model_cls: Type[Model],
|
def get_values_list_row_type(ctx: MethodContext, django_context: DjangoContext, model_cls: Type[Model],
|
||||||
flat: bool, named: bool) -> MypyType:
|
flat: bool, named: bool) -> MypyType:
|
||||||
field_lookups = resolve_field_lookups(ctx.args[0], ctx, django_context)
|
field_lookups = resolve_field_lookups(ctx.args[0], django_context)
|
||||||
if field_lookups is None:
|
if field_lookups is None:
|
||||||
return AnyType(TypeOfAny.from_error)
|
return AnyType(TypeOfAny.from_error)
|
||||||
|
|
||||||
@@ -146,11 +148,10 @@ def extract_proper_type_queryset_values_list(ctx: MethodContext, django_context:
|
|||||||
return helpers.reparametrize_instance(ctx.default_return_type, [model_type, row_type])
|
return helpers.reparametrize_instance(ctx.default_return_type, [model_type, row_type])
|
||||||
|
|
||||||
|
|
||||||
def resolve_field_lookups(lookup_exprs: Sequence[Expression], ctx: Union[FunctionContext, MethodContext],
|
def resolve_field_lookups(lookup_exprs: Sequence[Expression], django_context: DjangoContext) -> Optional[List[str]]:
|
||||||
django_context: DjangoContext) -> Optional[List[str]]:
|
|
||||||
field_lookups = []
|
field_lookups = []
|
||||||
for field_lookup_expr in lookup_exprs:
|
for field_lookup_expr in lookup_exprs:
|
||||||
field_lookup = helpers.resolve_string_attribute_value(field_lookup_expr, ctx, django_context)
|
field_lookup = helpers.resolve_string_attribute_value(field_lookup_expr, django_context)
|
||||||
if field_lookup is None:
|
if field_lookup is None:
|
||||||
return None
|
return None
|
||||||
field_lookups.append(field_lookup)
|
field_lookups.append(field_lookup)
|
||||||
@@ -170,7 +171,7 @@ def extract_proper_type_queryset_values(ctx: MethodContext, django_context: Djan
|
|||||||
if model_cls is None:
|
if model_cls is None:
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
|
|
||||||
field_lookups = resolve_field_lookups(ctx.args[0], ctx, django_context)
|
field_lookups = resolve_field_lookups(ctx.args[0], django_context)
|
||||||
if field_lookups is None:
|
if field_lookups is None:
|
||||||
return AnyType(TypeOfAny.from_error)
|
return AnyType(TypeOfAny.from_error)
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
# using this constant.
|
# using this constant.
|
||||||
import re
|
import re
|
||||||
|
|
||||||
IGNORED_MODULES = {'schema', 'gis_tests', 'admin_widgets', 'admin_filters', 'migrations',
|
IGNORED_MODULES = {'schema', 'gis_tests', 'admin_widgets', 'admin_filters',
|
||||||
'sitemaps_tests', 'staticfiles_tests', 'modeladmin', 'model_forms',
|
'sitemaps_tests', 'staticfiles_tests', 'modeladmin',
|
||||||
'generic_views', 'forms_tests', 'flatpages_tests', 'admin_utils',
|
'generic_views', 'forms_tests', 'flatpages_tests',
|
||||||
'admin_ordering', 'admin_changelist', 'admin_views', 'redirects_tests',
|
'admin_ordering', 'admin_changelist', 'admin_views',
|
||||||
'invalid_models_tests', 'i18n', 'migrate_signals', 'model_formsets',
|
'invalid_models_tests', 'i18n', 'model_formsets',
|
||||||
'template_tests', 'template_backends', 'test_runner', 'admin_scripts',
|
'template_tests', 'template_backends', 'test_runner', 'admin_scripts',
|
||||||
'sites_tests', 'inline_formsets', 'foreign_object', 'cache', 'test_client', 'test_client_regress'}
|
'inline_formsets', 'foreign_object', 'cache'}
|
||||||
|
|
||||||
MOCK_OBJECTS = ['MockRequest', 'MockCompiler', 'modelz', 'call_count', 'call_args_list',
|
MOCK_OBJECTS = ['MockRequest', 'MockCompiler', 'MockModelAdmin', 'modelz', 'call_count', 'call_args_list',
|
||||||
'call_args', 'MockUser', 'Xtemplate', 'DummyRequest', 'DummyUser', 'MinimalUser', 'DummyNode']
|
'call_args', 'MockUser', 'Xtemplate', 'DummyRequest', 'DummyUser', 'MinimalUser', 'DummyNode']
|
||||||
EXTERNAL_MODULES = ['psycopg2', 'PIL', 'selenium', 'oracle', 'mysql', 'sqlite3', 'sqlparse', 'tblib', 'numpy',
|
EXTERNAL_MODULES = ['psycopg2', 'PIL', 'selenium', 'oracle', 'mysql', 'sqlparse', 'tblib', 'numpy',
|
||||||
'bcrypt', 'argon2', 'xml.dom']
|
'bcrypt', 'argon2', 'xml.dom']
|
||||||
IGNORED_ERRORS = {
|
IGNORED_ERRORS = {
|
||||||
'__common__': [
|
'__common__': [
|
||||||
@@ -31,7 +31,6 @@ IGNORED_ERRORS = {
|
|||||||
re.compile(r'has no attribute ("|\')_[a-zA-Z_]+("|\')'),
|
re.compile(r'has no attribute ("|\')_[a-zA-Z_]+("|\')'),
|
||||||
"'Settings' object has no attribute",
|
"'Settings' object has no attribute",
|
||||||
'**Dict',
|
'**Dict',
|
||||||
re.compile(r"Expression of type '.*' is not supported"),
|
|
||||||
'has incompatible type "object"',
|
'has incompatible type "object"',
|
||||||
'undefined in superclass',
|
'undefined in superclass',
|
||||||
'Argument after ** must be a mapping',
|
'Argument after ** must be a mapping',
|
||||||
@@ -65,6 +64,10 @@ IGNORED_ERRORS = {
|
|||||||
'Incompatible types in string interpolation',
|
'Incompatible types in string interpolation',
|
||||||
'"None" has no attribute',
|
'"None" has no attribute',
|
||||||
'has no attribute "assert',
|
'has no attribute "assert',
|
||||||
|
'Unsupported dynamic base class'
|
||||||
|
],
|
||||||
|
'admin_utils': [
|
||||||
|
'"Article" has no attribute "non_field"',
|
||||||
],
|
],
|
||||||
'aggregation': [
|
'aggregation': [
|
||||||
re.compile(r'got "Optional\[(Author|Publisher)\]", expected "Union\[(Author|Publisher), Combinable\]"'),
|
re.compile(r'got "Optional\[(Author|Publisher)\]", expected "Union\[(Author|Publisher), Combinable\]"'),
|
||||||
@@ -130,7 +133,6 @@ IGNORED_ERRORS = {
|
|||||||
'"Employee" has no attribute "id"',
|
'"Employee" has no attribute "id"',
|
||||||
],
|
],
|
||||||
'custom_managers': [
|
'custom_managers': [
|
||||||
'Unsupported dynamic base class',
|
|
||||||
'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"',
|
'Item "Book" of "Optional[Book]" has no attribute "favorite_avg"',
|
||||||
],
|
],
|
||||||
@@ -259,6 +261,20 @@ IGNORED_ERRORS = {
|
|||||||
'middleware_exceptions': [
|
'middleware_exceptions': [
|
||||||
'Argument 1 to "append" of "list" has incompatible type "Tuple[Any, Any]"; expected "str"'
|
'Argument 1 to "append" of "list" has incompatible type "Tuple[Any, Any]"; expected "str"'
|
||||||
],
|
],
|
||||||
|
'migrate_signals': [
|
||||||
|
'Value of type "Optional[Any]" is not indexable',
|
||||||
|
'Argument 1 to "set" has incompatible type "Optional[Any]"; expected "Iterable[Any]"',
|
||||||
|
],
|
||||||
|
'migrations': [
|
||||||
|
'FakeMigration',
|
||||||
|
'FakeLoader',
|
||||||
|
'"Manager[Any]" has no attribute "args"',
|
||||||
|
'Dict entry 0 has incompatible type "Any"',
|
||||||
|
'Argument 1 to "append" of "list" has incompatible type',
|
||||||
|
'base class "Model" defined the type as "BaseManager[Any]"',
|
||||||
|
'Argument 1 to "RunPython" has incompatible type "str"',
|
||||||
|
|
||||||
|
],
|
||||||
'model_fields': [
|
'model_fields': [
|
||||||
'Item "Field[Any, Any]" of "Union[Field[Any, Any], ForeignObjectRel]" has no attribute',
|
'Item "Field[Any, Any]" of "Union[Field[Any, Any], ForeignObjectRel]" has no attribute',
|
||||||
'Incompatible types in assignment (expression has type "Type[Person',
|
'Incompatible types in assignment (expression has type "Type[Person',
|
||||||
@@ -267,6 +283,14 @@ IGNORED_ERRORS = {
|
|||||||
'Incompatible type for "size" of "FloatModel" (got "object", expected "Union[float, int, str, Combinable]")',
|
'Incompatible type for "size" of "FloatModel" (got "object", expected "Union[float, int, str, Combinable]")',
|
||||||
'Incompatible type for "value" of "IntegerModel" (got "object", expected',
|
'Incompatible type for "value" of "IntegerModel" (got "object", expected',
|
||||||
],
|
],
|
||||||
|
'model_forms': [
|
||||||
|
'"render" of "Widget"',
|
||||||
|
"Module 'django.core.validators' has no attribute 'ValidationError'",
|
||||||
|
'Incompatible types in assignment',
|
||||||
|
'NewForm',
|
||||||
|
'"type" has no attribute "base_fields"',
|
||||||
|
'Argument "instance" to "InvalidModelForm" has incompatible type "Type[Category]"',
|
||||||
|
],
|
||||||
'model_indexes': [
|
'model_indexes': [
|
||||||
'Argument "condition" to "Index" has incompatible type "str"; expected "Optional[Q]"'
|
'Argument "condition" to "Index" has incompatible type "str"; expected "Optional[Q]"'
|
||||||
],
|
],
|
||||||
@@ -368,6 +392,9 @@ IGNORED_ERRORS = {
|
|||||||
'expression has type "CurrentSiteManager[CustomArticle]", base class "AbstractArticle"',
|
'expression has type "CurrentSiteManager[CustomArticle]", base class "AbstractArticle"',
|
||||||
"Name 'Optional' is not defined",
|
"Name 'Optional' is not defined",
|
||||||
],
|
],
|
||||||
|
'sites_tests': [
|
||||||
|
'"RequestSite" of "Union[Site, RequestSite]" has no attribute "id"',
|
||||||
|
],
|
||||||
'syndication_tests': [
|
'syndication_tests': [
|
||||||
'List or tuple expected as variable arguments'
|
'List or tuple expected as variable arguments'
|
||||||
],
|
],
|
||||||
@@ -404,6 +431,13 @@ IGNORED_ERRORS = {
|
|||||||
'"PossessedCar" has no attribute "color"',
|
'"PossessedCar" has no attribute "color"',
|
||||||
'expression has type "None", variable has type "List[str]"',
|
'expression has type "None", variable has type "List[str]"',
|
||||||
],
|
],
|
||||||
|
'test_client': [
|
||||||
|
'(expression has type "HttpResponse", variable has type "StreamingHttpResponse")'
|
||||||
|
],
|
||||||
|
'test_client_regress': [
|
||||||
|
'(expression has type "Dict[<nothing>, <nothing>]", variable has type "SessionBase")',
|
||||||
|
'Unsupported left operand type for + ("None")',
|
||||||
|
],
|
||||||
'transactions': [
|
'transactions': [
|
||||||
'Incompatible types in assignment (expression has type "Thread", variable has type "Callable[[], Any]")'
|
'Incompatible types in assignment (expression has type "Thread", variable has type "Callable[[], Any]")'
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ import sys
|
|||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Pattern, Union
|
from typing import Dict, List, Pattern, Tuple, Union
|
||||||
|
|
||||||
from git import Repo
|
from git import RemoteProgress, Repo
|
||||||
|
|
||||||
from scripts.enabled_test_modules import (
|
from scripts.enabled_test_modules import (
|
||||||
EXTERNAL_MODULES, IGNORED_ERRORS, IGNORED_MODULES, MOCK_OBJECTS,
|
EXTERNAL_MODULES, IGNORED_ERRORS, IGNORED_MODULES, MOCK_OBJECTS,
|
||||||
)
|
)
|
||||||
|
|
||||||
DJANGO_COMMIT_REFS = {
|
DJANGO_COMMIT_REFS: Dict[str, Tuple[str, str]] = {
|
||||||
'2.2': 'e8b0903976077b951795938b260211214ed7fe41',
|
'2.2': ('stable/2.2.x', '86befcc172c23170a720b3e0c06db51a99b3da59'),
|
||||||
'3.0': '7ec5962638144cbf4c2e47ea7d8dc02d1ce44394'
|
'3.0': ('stable/3.0.x', '6cb30414bc0f83b49afc4cae76d4af5656effe9a')
|
||||||
}
|
}
|
||||||
PROJECT_DIRECTORY = Path(__file__).parent.parent
|
PROJECT_DIRECTORY = Path(__file__).parent.parent
|
||||||
DJANGO_SOURCE_DIRECTORY = PROJECT_DIRECTORY / 'django-sources' # type: Path
|
DJANGO_SOURCE_DIRECTORY = PROJECT_DIRECTORY / 'django-sources' # type: Path
|
||||||
@@ -75,10 +75,21 @@ def replace_with_clickable_location(error: str, abs_test_folder: Path) -> str:
|
|||||||
return error.replace(raw_path, clickable_location)
|
return error.replace(raw_path, clickable_location)
|
||||||
|
|
||||||
|
|
||||||
def get_django_repo_object() -> Repo:
|
class ProgressPrinter(RemoteProgress):
|
||||||
|
def line_dropped(self, line: str) -> None:
|
||||||
|
print(line)
|
||||||
|
|
||||||
|
def update(self, op_code, cur_count, max_count=None, message=''):
|
||||||
|
print(self._cur_line)
|
||||||
|
|
||||||
|
|
||||||
|
def get_django_repo_object(branch: str) -> Repo:
|
||||||
if not DJANGO_SOURCE_DIRECTORY.exists():
|
if not DJANGO_SOURCE_DIRECTORY.exists():
|
||||||
DJANGO_SOURCE_DIRECTORY.mkdir(exist_ok=True, parents=False)
|
DJANGO_SOURCE_DIRECTORY.mkdir(exist_ok=True, parents=False)
|
||||||
return Repo.clone_from('https://github.com/django/django.git', DJANGO_SOURCE_DIRECTORY)
|
return Repo.clone_from('https://github.com/django/django.git', DJANGO_SOURCE_DIRECTORY,
|
||||||
|
progress=ProgressPrinter(),
|
||||||
|
branch=branch,
|
||||||
|
depth=100)
|
||||||
else:
|
else:
|
||||||
repo = Repo(DJANGO_SOURCE_DIRECTORY)
|
repo = Repo(DJANGO_SOURCE_DIRECTORY)
|
||||||
return repo
|
return repo
|
||||||
@@ -89,10 +100,13 @@ if __name__ == '__main__':
|
|||||||
parser.add_argument('--django_version', choices=['2.2', '3.0'], required=True)
|
parser.add_argument('--django_version', choices=['2.2', '3.0'], required=True)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
commit_sha = DJANGO_COMMIT_REFS[args.django_version]
|
# install proper Django version
|
||||||
repo = get_django_repo_object()
|
subprocess.check_call([sys.executable, '-m', 'pip', 'install', f'Django=={args.django_version}.*'])
|
||||||
|
|
||||||
|
branch, commit_sha = DJANGO_COMMIT_REFS[args.django_version]
|
||||||
|
repo = get_django_repo_object(branch)
|
||||||
if repo.head.commit.hexsha != commit_sha:
|
if repo.head.commit.hexsha != commit_sha:
|
||||||
repo.git.fetch('origin')
|
repo.remote('origin').fetch(branch, progress=ProgressPrinter(), depth=100)
|
||||||
repo.git.checkout(commit_sha)
|
repo.git.checkout(commit_sha)
|
||||||
|
|
||||||
mypy_config_file = (PROJECT_DIRECTORY / 'scripts' / 'mypy.ini').absolute()
|
mypy_config_file = (PROJECT_DIRECTORY / 'scripts' / 'mypy.ini').absolute()
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -28,7 +28,7 @@ dependencies = [
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="django-stubs",
|
name="django-stubs",
|
||||||
version="1.3.0",
|
version="1.3.2",
|
||||||
description='Mypy stubs for Django',
|
description='Mypy stubs for Django',
|
||||||
long_description=readme,
|
long_description=readme,
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type='text/markdown',
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
- case: from_queryset_with_base_manager
|
||||||
|
main: |
|
||||||
|
from myapp.models import MyModel
|
||||||
|
reveal_type(MyModel().objects) # N: Revealed type is 'myapp.models.MyModel_NewManager[myapp.models.MyModel]'
|
||||||
|
reveal_type(MyModel().objects.get()) # N: Revealed type is 'myapp.models.MyModel*'
|
||||||
|
reveal_type(MyModel().objects.queryset_method()) # N: Revealed type is 'builtins.str'
|
||||||
|
installed_apps:
|
||||||
|
- myapp
|
||||||
|
files:
|
||||||
|
- path: myapp/__init__.py
|
||||||
|
- path: myapp/models.py
|
||||||
|
content: |
|
||||||
|
from django.db import models
|
||||||
|
from django.db.models.manager import BaseManager
|
||||||
|
|
||||||
|
class ModelQuerySet(models.QuerySet):
|
||||||
|
def queryset_method(self) -> str:
|
||||||
|
return 'hello'
|
||||||
|
NewManager = BaseManager.from_queryset(ModelQuerySet)
|
||||||
|
class MyModel(models.Model):
|
||||||
|
objects = NewManager()
|
||||||
|
|
||||||
|
- case: from_queryset_with_manager
|
||||||
|
main: |
|
||||||
|
from myapp.models import MyModel
|
||||||
|
reveal_type(MyModel().objects) # N: Revealed type is 'myapp.models.MyModel_NewManager[myapp.models.MyModel]'
|
||||||
|
reveal_type(MyModel().objects.get()) # N: Revealed type is 'myapp.models.MyModel*'
|
||||||
|
reveal_type(MyModel().objects.queryset_method()) # N: Revealed type is 'builtins.str'
|
||||||
|
installed_apps:
|
||||||
|
- myapp
|
||||||
|
files:
|
||||||
|
- path: myapp/__init__.py
|
||||||
|
- path: myapp/models.py
|
||||||
|
content: |
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class ModelQuerySet(models.QuerySet):
|
||||||
|
def queryset_method(self) -> str:
|
||||||
|
return 'hello'
|
||||||
|
|
||||||
|
NewManager = models.Manager.from_queryset(ModelQuerySet)
|
||||||
|
class MyModel(models.Model):
|
||||||
|
objects = NewManager()
|
||||||
|
|
||||||
|
- case: from_queryset_returns_intersection_of_manager_and_queryset
|
||||||
|
main: |
|
||||||
|
from myapp.models import MyModel, NewManager
|
||||||
|
reveal_type(NewManager()) # N: Revealed type is 'myapp.models.NewManager'
|
||||||
|
reveal_type(MyModel.objects) # N: Revealed type is 'myapp.models.MyModel_NewManager[myapp.models.MyModel]'
|
||||||
|
reveal_type(MyModel.objects.get()) # N: Revealed type is 'Any'
|
||||||
|
reveal_type(MyModel.objects.manager_only_method()) # N: Revealed type is 'builtins.int'
|
||||||
|
reveal_type(MyModel.objects.manager_and_queryset_method()) # N: Revealed type is 'builtins.str'
|
||||||
|
installed_apps:
|
||||||
|
- myapp
|
||||||
|
files:
|
||||||
|
- path: myapp/__init__.py
|
||||||
|
- path: myapp/models.py
|
||||||
|
content: |
|
||||||
|
from django.db import models
|
||||||
|
class ModelBaseManager(models.Manager):
|
||||||
|
def manager_only_method(self) -> int:
|
||||||
|
return 1
|
||||||
|
class ModelQuerySet(models.QuerySet):
|
||||||
|
def manager_and_queryset_method(self) -> str:
|
||||||
|
return 'hello'
|
||||||
|
|
||||||
|
NewManager = ModelBaseManager.from_queryset(ModelQuerySet)
|
||||||
|
class MyModel(models.Model):
|
||||||
|
objects = NewManager()
|
||||||
|
|
||||||
|
- case: from_queryset_with_class_name_provided
|
||||||
|
main: |
|
||||||
|
from myapp.models import MyModel, NewManager
|
||||||
|
reveal_type(NewManager()) # N: Revealed type is 'myapp.models.NewManager'
|
||||||
|
reveal_type(MyModel.objects) # N: Revealed type is 'myapp.models.MyModel_NewManager[myapp.models.MyModel]'
|
||||||
|
reveal_type(MyModel.objects.get()) # N: Revealed type is 'Any'
|
||||||
|
reveal_type(MyModel.objects.manager_only_method()) # N: Revealed type is 'builtins.int'
|
||||||
|
reveal_type(MyModel.objects.manager_and_queryset_method()) # N: Revealed type is 'builtins.str'
|
||||||
|
installed_apps:
|
||||||
|
- myapp
|
||||||
|
files:
|
||||||
|
- path: myapp/__init__.py
|
||||||
|
- path: myapp/models.py
|
||||||
|
content: |
|
||||||
|
from django.db import models
|
||||||
|
class ModelBaseManager(models.Manager):
|
||||||
|
def manager_only_method(self) -> int:
|
||||||
|
return 1
|
||||||
|
class ModelQuerySet(models.QuerySet):
|
||||||
|
def manager_and_queryset_method(self) -> str:
|
||||||
|
return 'hello'
|
||||||
|
|
||||||
|
NewManager = ModelBaseManager.from_queryset(ModelQuerySet, class_name='NewManager')
|
||||||
|
class MyModel(models.Model):
|
||||||
|
objects = NewManager()
|
||||||
|
|
||||||
@@ -107,3 +107,20 @@
|
|||||||
class Blog(models.Model):
|
class Blog(models.Model):
|
||||||
name = models.CharField(max_length=100)
|
name = models.CharField(max_length=100)
|
||||||
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
|
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
- case: values_of_many_to_many_field
|
||||||
|
main: |
|
||||||
|
from myapp.models import Author, Book
|
||||||
|
reveal_type(Book.objects.values('authors')) # N: Revealed type is 'django.db.models.query.ValuesQuerySet[myapp.models.Book, TypedDict({'authors': builtins.int})]'
|
||||||
|
reveal_type(Author.objects.values('books')) # N: Revealed type is 'django.db.models.query.ValuesQuerySet[myapp.models.Author, TypedDict({'books': builtins.int})]'
|
||||||
|
installed_apps:
|
||||||
|
- myapp
|
||||||
|
files:
|
||||||
|
- path: myapp/__init__.py
|
||||||
|
- path: myapp/models.py
|
||||||
|
content: |
|
||||||
|
from django.db import models
|
||||||
|
class Author(models.Model):
|
||||||
|
pass
|
||||||
|
class Book(models.Model):
|
||||||
|
authors = models.ManyToManyField(Author, related_name='books')
|
||||||
|
|||||||
@@ -224,3 +224,20 @@
|
|||||||
pass
|
pass
|
||||||
class Transaction(models.Model):
|
class Transaction(models.Model):
|
||||||
total = models.IntegerField()
|
total = models.IntegerField()
|
||||||
|
|
||||||
|
- case: values_list_of_many_to_many_field
|
||||||
|
main: |
|
||||||
|
from myapp.models import Author, Book
|
||||||
|
reveal_type(Book.objects.values_list('authors')) # N: Revealed type is 'django.db.models.query.ValuesQuerySet[myapp.models.Book, Tuple[builtins.int]]'
|
||||||
|
reveal_type(Author.objects.values_list('books')) # N: Revealed type is 'django.db.models.query.ValuesQuerySet[myapp.models.Author, Tuple[builtins.int]]'
|
||||||
|
installed_apps:
|
||||||
|
- myapp
|
||||||
|
files:
|
||||||
|
- path: myapp/__init__.py
|
||||||
|
- path: myapp/models.py
|
||||||
|
content: |
|
||||||
|
from django.db import models
|
||||||
|
class Author(models.Model):
|
||||||
|
pass
|
||||||
|
class Book(models.Model):
|
||||||
|
authors = models.ManyToManyField(Author, related_name='books')
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
class Base(Generic[_T]):
|
class Base(Generic[_T]):
|
||||||
def __init__(self, model_cls: Type[_T]):
|
def __init__(self, model_cls: Type[_T]):
|
||||||
self.model_cls = model_cls
|
self.model_cls = model_cls
|
||||||
reveal_type(self.model_cls._default_manager) # N: Revealed type is 'django.db.models.manager.Manager[django.db.models.base.Model]'
|
reveal_type(self.model_cls._default_manager) # N: Revealed type is 'django.db.models.manager.BaseManager[django.db.models.base.Model]'
|
||||||
class MyModel(models.Model):
|
class MyModel(models.Model):
|
||||||
pass
|
pass
|
||||||
class Child(Base[MyModel]):
|
class Child(Base[MyModel]):
|
||||||
|
|||||||
@@ -96,6 +96,7 @@
|
|||||||
import django.contrib.postgres.aggregates.general
|
import django.contrib.postgres.aggregates.general
|
||||||
import django.contrib.postgres.aggregates.mixins
|
import django.contrib.postgres.aggregates.mixins
|
||||||
import django.contrib.postgres.aggregates.statistics
|
import django.contrib.postgres.aggregates.statistics
|
||||||
|
import django.contrib.postgres.constraints
|
||||||
import django.contrib.postgres.fields
|
import django.contrib.postgres.fields
|
||||||
import django.contrib.postgres.fields.array
|
import django.contrib.postgres.fields.array
|
||||||
import django.contrib.postgres.fields.citext
|
import django.contrib.postgres.fields.citext
|
||||||
@@ -269,6 +270,7 @@
|
|||||||
import django.db.models.constraints
|
import django.db.models.constraints
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import django.db.models.expressions
|
import django.db.models.expressions
|
||||||
|
import django.db.models.enums
|
||||||
import django.db.models.fields
|
import django.db.models.fields
|
||||||
import django.db.models.fields.files
|
import django.db.models.fields.files
|
||||||
import django.db.models.fields.mixins
|
import django.db.models.fields.mixins
|
||||||
|
|||||||
Reference in New Issue
Block a user