mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-10 05:51:53 +08:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7e1cfc6c7 | ||
|
|
d0c25e3bce | ||
|
|
1c31e71ffc | ||
|
|
6b3b6be3c1 |
@@ -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.exceptions import ValidationError
|
||||
from django.db.models.manager import Manager
|
||||
from django.db.models.manager import BaseManager
|
||||
from django.db.models.options import Options
|
||||
|
||||
_Self = TypeVar("_Self", bound="Model")
|
||||
@@ -13,9 +13,9 @@ class Model(metaclass=ModelBase):
|
||||
class DoesNotExist(Exception): ...
|
||||
class MultipleObjectsReturned(Exception): ...
|
||||
class Meta: ...
|
||||
_default_manager: Manager[Model]
|
||||
_meta: Options[Any]
|
||||
objects: Manager[Any]
|
||||
_default_manager: BaseManager[Model]
|
||||
objects: BaseManager[Any]
|
||||
pk: Any = ...
|
||||
def __init__(self: _Self, *args, **kwargs) -> None: ...
|
||||
def delete(self, using: Any = ..., keep_parents: bool = ...) -> Tuple[int, Dict[str, int]]: ...
|
||||
|
||||
@@ -31,6 +31,7 @@ _T = TypeVar("_T", bound=models.Model, covariant=True)
|
||||
_QS = TypeVar("_QS", bound="_BaseQuerySet")
|
||||
|
||||
class _BaseQuerySet(Generic[_T], Sized):
|
||||
model: Type[_T]
|
||||
query: Query
|
||||
def __init__(
|
||||
self,
|
||||
|
||||
@@ -205,10 +205,9 @@ class CallableChoiceIterator:
|
||||
def __iter__(self) -> None: ...
|
||||
|
||||
class ChoiceField(Field):
|
||||
choices: Any = ...
|
||||
def __init__(
|
||||
self,
|
||||
choices: Any = ...,
|
||||
choices: _FieldChoices = ...,
|
||||
required: bool = ...,
|
||||
widget: Optional[Union[Widget, Type[Widget]]] = ...,
|
||||
label: Optional[Any] = ...,
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
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 uuid import UUID
|
||||
|
||||
@@ -24,6 +40,11 @@ _Fields = Union[List[Union[Callable, str]], Sequence[str], Literal["__all__"]]
|
||||
_Labels = 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(
|
||||
instance: Model, fields: Optional[_Fields] = ..., exclude: Optional[_Fields] = ...
|
||||
) -> Dict[str, Any]: ...
|
||||
@@ -76,7 +97,8 @@ class BaseModelForm(BaseForm):
|
||||
save_m2m: Any = ...
|
||||
def save(self, commit: bool = ...) -> Any: ...
|
||||
|
||||
class ModelForm(BaseModelForm): ...
|
||||
class ModelForm(BaseModelForm, metaclass=ModelFormMetaclass):
|
||||
base_fields: ClassVar[Dict[str, Field]] = ...
|
||||
|
||||
def modelform_factory(
|
||||
model: Type[Model],
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
from typing import Any, Callable, Dict, Optional, Sequence, Type, Union
|
||||
|
||||
from django.forms.forms import BaseForm
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
|
||||
from django.views.generic.detail import BaseDetailView, SingleObjectMixin, SingleObjectTemplateResponseMixin
|
||||
from typing_extensions import Literal
|
||||
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
|
||||
class FormMixin(ContextMixin):
|
||||
initial: Dict[str, Any] = ...
|
||||
form_class: Optional[Type[BaseForm]] = ...
|
||||
|
||||
@@ -23,9 +23,7 @@ FORM_MIXIN_CLASS_FULLNAME = 'django.views.generic.edit.FormMixin'
|
||||
|
||||
MANAGER_CLASSES = {
|
||||
MANAGER_CLASS_FULLNAME,
|
||||
RELATED_MANAGER_CLASS,
|
||||
BASE_MANAGER_CLASS_FULLNAME,
|
||||
# QUERYSET_CLASS_FULLNAME
|
||||
}
|
||||
|
||||
RELATED_FIELDS_CLASSES = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from mypy.nodes import (
|
||||
GDEF, FuncDef, MemberExpr, NameExpr, StrExpr, SymbolTableNode, TypeInfo,
|
||||
GDEF, FuncDef, MemberExpr, NameExpr, RefExpr, StrExpr, SymbolTableNode, TypeInfo,
|
||||
)
|
||||
from mypy.plugin import ClassDefContext, DynamicClassDefContext
|
||||
from mypy.types import AnyType, Instance, TypeOfAny
|
||||
@@ -10,9 +10,11 @@ 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)
|
||||
|
||||
assert isinstance(ctx.call.callee, MemberExpr)
|
||||
assert isinstance(ctx.call.callee.expr, NameExpr)
|
||||
base_manager_info = ctx.call.callee.expr.node
|
||||
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()
|
||||
|
||||
@@ -144,7 +144,7 @@ class AddManagers(ModelClassInitializer):
|
||||
return False
|
||||
|
||||
def is_any_parametrized_manager(self, typ: Instance) -> bool:
|
||||
return typ.type.fullname == fullnames.MANAGER_CLASS_FULLNAME and isinstance(typ.args[0], AnyType)
|
||||
return typ.type.fullname in fullnames.MANAGER_CLASSES and isinstance(typ.args[0], AnyType)
|
||||
|
||||
def get_generated_manager_mappings(self, base_manager_fullname: str) -> Dict[str, str]:
|
||||
base_manager_info = self.lookup_typeinfo(base_manager_fullname)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import re
|
||||
|
||||
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_ordering', 'admin_changelist', 'admin_views',
|
||||
'invalid_models_tests', 'i18n', 'model_formsets',
|
||||
@@ -271,7 +271,7 @@ IGNORED_ERRORS = {
|
||||
'"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 "Manager[Any]"',
|
||||
'base class "Model" defined the type as "BaseManager[Any]"',
|
||||
'Argument 1 to "RunPython" has incompatible type "str"',
|
||||
|
||||
],
|
||||
@@ -283,6 +283,14 @@ IGNORED_ERRORS = {
|
||||
'Incompatible type for "size" of "FloatModel" (got "object", expected "Union[float, int, str, Combinable]")',
|
||||
'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': [
|
||||
'Argument "condition" to "Index" has incompatible type "str"; expected "Optional[Q]"'
|
||||
],
|
||||
|
||||
@@ -14,8 +14,8 @@ from scripts.enabled_test_modules import (
|
||||
)
|
||||
|
||||
DJANGO_COMMIT_REFS: Dict[str, Tuple[str, str]] = {
|
||||
'2.2': ('stable/2.2.x', 'e8b0903976077b951795938b260211214ed7fe41'),
|
||||
'3.0': ('stable/3.0.x', '7ec5962638144cbf4c2e47ea7d8dc02d1ce44394')
|
||||
'2.2': ('stable/2.2.x', '86befcc172c23170a720b3e0c06db51a99b3da59'),
|
||||
'3.0': ('stable/3.0.x', '6cb30414bc0f83b49afc4cae76d4af5656effe9a')
|
||||
}
|
||||
PROJECT_DIRECTORY = Path(__file__).parent.parent
|
||||
DJANGO_SOURCE_DIRECTORY = PROJECT_DIRECTORY / 'django-sources' # type: Path
|
||||
|
||||
2
setup.py
2
setup.py
@@ -28,7 +28,7 @@ dependencies = [
|
||||
|
||||
setup(
|
||||
name="django-stubs",
|
||||
version="1.3.1",
|
||||
version="1.3.2",
|
||||
description='Mypy stubs for Django',
|
||||
long_description=readme,
|
||||
long_description_content_type='text/markdown',
|
||||
|
||||
@@ -1,4 +1,48 @@
|
||||
- case: test_from_queryset_returns_intersection_of_manager_and_queryset
|
||||
- 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'
|
||||
@@ -24,7 +68,7 @@
|
||||
class MyModel(models.Model):
|
||||
objects = NewManager()
|
||||
|
||||
- case: test_from_queryset_with_class_name_provided
|
||||
- case: from_queryset_with_class_name_provided
|
||||
main: |
|
||||
from myapp.models import MyModel, NewManager
|
||||
reveal_type(NewManager()) # N: Revealed type is 'myapp.models.NewManager'
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
class Base(Generic[_T]):
|
||||
def __init__(self, model_cls: Type[_T]):
|
||||
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):
|
||||
pass
|
||||
class Child(Base[MyModel]):
|
||||
|
||||
Reference in New Issue
Block a user