mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-07 20:54:29 +08:00
Support mypy 0.750
This commit is contained in:
@@ -22,6 +22,7 @@ pip install django-stubs
|
|||||||
|
|
||||||
| django-stubs | mypy version | django version | python version
|
| django-stubs | mypy version | django version | python version
|
||||||
| ------------ | ---- | ---- | ---- |
|
| ------------ | ---- | ---- | ---- |
|
||||||
|
| 1.3.0 | 0.750 | 2.2.x | ^3.6
|
||||||
| 1.2.0 | 0.730 | 2.2.x | ^3.6
|
| 1.2.0 | 0.730 | 2.2.x | ^3.6
|
||||||
| 1.1.0 | 0.720 | 2.2.x | ^3.6
|
| 1.1.0 | 0.720 | 2.2.x | ^3.6
|
||||||
| 0.12.x | old semantic analyzer (<0.711), dmypy support | 2.1.x | ^3.6
|
| 0.12.x | old semantic analyzer (<0.711), dmypy support | 2.1.x | ^3.6
|
||||||
|
|||||||
@@ -1,9 +1,22 @@
|
|||||||
import decimal
|
import decimal
|
||||||
import warnings
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from typing import Any, Callable, Dict, Iterable, Iterator, List, Mapping, Optional, Set, Tuple, Type, Union
|
from typing import (
|
||||||
|
Any,
|
||||||
|
Callable,
|
||||||
|
Dict,
|
||||||
|
Iterable,
|
||||||
|
Iterator,
|
||||||
|
List,
|
||||||
|
Mapping,
|
||||||
|
Optional,
|
||||||
|
Set,
|
||||||
|
Tuple,
|
||||||
|
Type,
|
||||||
|
Union,
|
||||||
|
ContextManager,
|
||||||
|
)
|
||||||
|
|
||||||
from django.apps.registry import Apps
|
from django.apps.registry import Apps
|
||||||
from django.core.checks.registry import CheckRegistry
|
from django.core.checks.registry import CheckRegistry
|
||||||
@@ -86,7 +99,7 @@ class ignore_warnings(TestContextDecorator):
|
|||||||
ignore_kwargs: Dict[str, Any] = ...
|
ignore_kwargs: Dict[str, Any] = ...
|
||||||
filter_func: Callable = ...
|
filter_func: Callable = ...
|
||||||
def __init__(self, **kwargs: Any) -> None: ...
|
def __init__(self, **kwargs: Any) -> None: ...
|
||||||
catch_warnings: warnings.catch_warnings = ...
|
catch_warnings: ContextManager[Optional[list]] = ...
|
||||||
|
|
||||||
requires_tz_support: Any
|
requires_tz_support: Any
|
||||||
|
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ class DjangoContext:
|
|||||||
lookup_type: MypyType = lookup_base.args[0]
|
lookup_type: MypyType = lookup_base.args[0]
|
||||||
# if it's Field, consider lookup_type a __get__ of current field
|
# if it's Field, consider lookup_type a __get__ of current field
|
||||||
if (isinstance(lookup_type, Instance)
|
if (isinstance(lookup_type, Instance)
|
||||||
and lookup_type.type.fullname() == fullnames.FIELD_FULLNAME):
|
and lookup_type.type.fullname == fullnames.FIELD_FULLNAME):
|
||||||
field_info = helpers.lookup_class_typeinfo(helpers.get_typechecker_api(ctx), field.__class__)
|
field_info = helpers.lookup_class_typeinfo(helpers.get_typechecker_api(ctx), field.__class__)
|
||||||
if field_info is None:
|
if field_info is None:
|
||||||
return AnyType(TypeOfAny.explicit)
|
return AnyType(TypeOfAny.explicit)
|
||||||
|
|||||||
@@ -179,10 +179,10 @@ def add_new_class_for_module(module: MypyFile, name: str, bases: List[Instance],
|
|||||||
|
|
||||||
# make new class expression
|
# make new class expression
|
||||||
classdef = ClassDef(new_class_unique_name, Block([]))
|
classdef = ClassDef(new_class_unique_name, Block([]))
|
||||||
classdef.fullname = module.fullname() + '.' + new_class_unique_name
|
classdef.fullname = module.fullname + '.' + new_class_unique_name
|
||||||
|
|
||||||
# make new TypeInfo
|
# make new TypeInfo
|
||||||
new_typeinfo = TypeInfo(SymbolTable(), classdef, module.fullname())
|
new_typeinfo = TypeInfo(SymbolTable(), classdef, module.fullname)
|
||||||
new_typeinfo.bases = bases
|
new_typeinfo.bases = bases
|
||||||
calculate_mro(new_typeinfo)
|
calculate_mro(new_typeinfo)
|
||||||
new_typeinfo.calculate_metaclass_type()
|
new_typeinfo.calculate_metaclass_type()
|
||||||
@@ -191,7 +191,7 @@ def add_new_class_for_module(module: MypyFile, name: str, bases: List[Instance],
|
|||||||
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
|
||||||
var._fullname = new_typeinfo.fullname() + '.' + field_name
|
var._fullname = new_typeinfo.fullname + '.' + field_name
|
||||||
new_typeinfo.names[field_name] = SymbolTableNode(MDEF, var, plugin_generated=True)
|
new_typeinfo.names[field_name] = SymbolTableNode(MDEF, var, plugin_generated=True)
|
||||||
|
|
||||||
classdef.info = new_typeinfo
|
classdef.info = new_typeinfo
|
||||||
@@ -276,7 +276,7 @@ def get_typechecker_api(ctx: Union[AttributeContext, MethodContext, FunctionCont
|
|||||||
|
|
||||||
|
|
||||||
def is_model_subclass_info(info: TypeInfo, django_context: 'DjangoContext') -> bool:
|
def is_model_subclass_info(info: TypeInfo, django_context: 'DjangoContext') -> bool:
|
||||||
return (info.fullname() in django_context.all_registered_model_class_fullnames
|
return (info.fullname in django_context.all_registered_model_class_fullnames
|
||||||
or info.has_base(fullnames.MODEL_CLASS_FULLNAME))
|
or info.has_base(fullnames.MODEL_CLASS_FULLNAME))
|
||||||
|
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ def add_new_sym_for_info(info: TypeInfo, *, name: str, sym_type: MypyType) -> No
|
|||||||
var = Var(name=name, type=sym_type)
|
var = Var(name=name, type=sym_type)
|
||||||
# var.info: type of the object variable is bound to
|
# var.info: type of the object variable is bound to
|
||||||
var.info = info
|
var.info = info
|
||||||
var._fullname = info.fullname() + '.' + name
|
var._fullname = info.fullname + '.' + name
|
||||||
var.is_initialized_in_class = True
|
var.is_initialized_in_class = True
|
||||||
var.is_inferred = True
|
var.is_inferred = True
|
||||||
info.names[name] = SymbolTableNode(MDEF, var,
|
info.names[name] = SymbolTableNode(MDEF, var,
|
||||||
|
|||||||
@@ -121,17 +121,17 @@ class NewSemanalDjangoPlugin(Plugin):
|
|||||||
|
|
||||||
def get_additional_deps(self, file: MypyFile) -> List[Tuple[int, str, int]]:
|
def get_additional_deps(self, file: MypyFile) -> List[Tuple[int, str, int]]:
|
||||||
# for settings
|
# for settings
|
||||||
if file.fullname() == 'django.conf' and self.django_context.django_settings_module:
|
if file.fullname == 'django.conf' and self.django_context.django_settings_module:
|
||||||
return [self._new_dependency(self.django_context.django_settings_module)]
|
return [self._new_dependency(self.django_context.django_settings_module)]
|
||||||
|
|
||||||
# for values / values_list
|
# for values / values_list
|
||||||
if file.fullname() == 'django.db.models':
|
if file.fullname == 'django.db.models':
|
||||||
return [self._new_dependency('mypy_extensions'), self._new_dependency('typing')]
|
return [self._new_dependency('mypy_extensions'), self._new_dependency('typing')]
|
||||||
|
|
||||||
# for `get_user_model()`
|
# for `get_user_model()`
|
||||||
if self.django_context.settings:
|
if self.django_context.settings:
|
||||||
if (file.fullname() == 'django.contrib.auth'
|
if (file.fullname == 'django.contrib.auth'
|
||||||
or file.fullname() in {'django.http', 'django.http.request'}):
|
or file.fullname in {'django.http', 'django.http.request'}):
|
||||||
auth_user_model_name = self.django_context.settings.AUTH_USER_MODEL
|
auth_user_model_name = self.django_context.settings.AUTH_USER_MODEL
|
||||||
try:
|
try:
|
||||||
auth_user_module = self.django_context.apps_registry.get_model(auth_user_model_name).__module__
|
auth_user_module = self.django_context.apps_registry.get_model(auth_user_model_name).__module__
|
||||||
@@ -141,7 +141,7 @@ class NewSemanalDjangoPlugin(Plugin):
|
|||||||
return [self._new_dependency(auth_user_module)]
|
return [self._new_dependency(auth_user_module)]
|
||||||
|
|
||||||
# ensure that all mentioned to='someapp.SomeModel' are loaded with corresponding related Fields
|
# ensure that all mentioned to='someapp.SomeModel' are loaded with corresponding related Fields
|
||||||
defined_model_classes = self.django_context.model_modules.get(file.fullname())
|
defined_model_classes = self.django_context.model_modules.get(file.fullname)
|
||||||
if not defined_model_classes:
|
if not defined_model_classes:
|
||||||
return []
|
return []
|
||||||
deps = set()
|
deps = set()
|
||||||
@@ -153,13 +153,13 @@ class NewSemanalDjangoPlugin(Plugin):
|
|||||||
if related_model_cls is None:
|
if related_model_cls is None:
|
||||||
continue
|
continue
|
||||||
related_model_module = related_model_cls.__module__
|
related_model_module = related_model_cls.__module__
|
||||||
if related_model_module != file.fullname():
|
if related_model_module != file.fullname:
|
||||||
deps.add(self._new_dependency(related_model_module))
|
deps.add(self._new_dependency(related_model_module))
|
||||||
# reverse relations
|
# reverse relations
|
||||||
for relation in model_class._meta.related_objects:
|
for relation in model_class._meta.related_objects:
|
||||||
related_model_cls = self.django_context.get_field_related_model_cls(relation)
|
related_model_cls = self.django_context.get_field_related_model_cls(relation)
|
||||||
related_model_module = related_model_cls.__module__
|
related_model_module = related_model_cls.__module__
|
||||||
if related_model_module != file.fullname():
|
if related_model_module != file.fullname:
|
||||||
deps.add(self._new_dependency(related_model_module))
|
deps.add(self._new_dependency(related_model_module))
|
||||||
return list(deps)
|
return list(deps)
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ def _get_current_field_from_assignment(ctx: FunctionContext, django_context: Dja
|
|||||||
if field_name is None:
|
if field_name is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
model_cls = django_context.get_model_class_by_fullname(outer_model_info.fullname())
|
model_cls = django_context.get_model_class_by_fullname(outer_model_info.fullname)
|
||||||
if model_cls is None:
|
if model_cls is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ def typecheck_model_method(ctx: Union[FunctionContext, MethodContext], django_co
|
|||||||
def redefine_and_typecheck_model_init(ctx: FunctionContext, django_context: DjangoContext) -> MypyType:
|
def redefine_and_typecheck_model_init(ctx: FunctionContext, django_context: DjangoContext) -> MypyType:
|
||||||
assert isinstance(ctx.default_return_type, Instance)
|
assert isinstance(ctx.default_return_type, Instance)
|
||||||
|
|
||||||
model_fullname = ctx.default_return_type.type.fullname()
|
model_fullname = ctx.default_return_type.type.fullname
|
||||||
model_cls = django_context.get_model_class_by_fullname(model_fullname)
|
model_cls = django_context.get_model_class_by_fullname(model_fullname)
|
||||||
if model_cls is None:
|
if model_cls is None:
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
@@ -67,7 +67,7 @@ def redefine_and_typecheck_model_create(ctx: MethodContext, django_context: Djan
|
|||||||
# only work with ctx.default_return_type = model Instance
|
# only work with ctx.default_return_type = model Instance
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
|
|
||||||
model_fullname = ctx.default_return_type.type.fullname()
|
model_fullname = ctx.default_return_type.type.fullname
|
||||||
model_cls = django_context.get_model_class_by_fullname(model_fullname)
|
model_cls = django_context.get_model_class_by_fullname(model_fullname)
|
||||||
if model_cls is None:
|
if model_cls is None:
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ def return_proper_field_type_from_get_field(ctx: MethodContext, django_context:
|
|||||||
if not isinstance(model_type, Instance):
|
if not isinstance(model_type, Instance):
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
|
|
||||||
model_cls = django_context.get_model_class_by_fullname(model_type.type.fullname())
|
model_cls = django_context.get_model_class_by_fullname(model_type.type.fullname)
|
||||||
if model_cls is None:
|
if model_cls is None:
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class ModelClassInitializer:
|
|||||||
var = Var(name=name, type=typ)
|
var = Var(name=name, type=typ)
|
||||||
# var.info: type of the object variable is bound to
|
# var.info: type of the object variable is bound to
|
||||||
var.info = self.model_classdef.info
|
var.info = self.model_classdef.info
|
||||||
var._fullname = self.model_classdef.info.fullname() + '.' + name
|
var._fullname = self.model_classdef.info.fullname + '.' + name
|
||||||
var.is_initialized_in_class = True
|
var.is_initialized_in_class = True
|
||||||
var.is_inferred = True
|
var.is_inferred = True
|
||||||
return var
|
return var
|
||||||
@@ -126,7 +126,7 @@ class AddRelatedModelsId(ModelClassInitializer):
|
|||||||
|
|
||||||
class AddManagers(ModelClassInitializer):
|
class AddManagers(ModelClassInitializer):
|
||||||
def _is_manager_any(self, typ: Instance) -> bool:
|
def _is_manager_any(self, typ: Instance) -> bool:
|
||||||
return typ.type.fullname() == fullnames.MANAGER_CLASS_FULLNAME and type(typ.args[0]) == AnyType
|
return typ.type.fullname == fullnames.MANAGER_CLASS_FULLNAME and type(typ.args[0]) == AnyType
|
||||||
|
|
||||||
def run_with_model_cls(self, model_cls: Type[Model]) -> None:
|
def run_with_model_cls(self, model_cls: Type[Model]) -> None:
|
||||||
for manager_name, manager in model_cls._meta.managers_map.items():
|
for manager_name, manager in model_cls._meta.managers_map.items():
|
||||||
@@ -163,7 +163,7 @@ class AddManagers(ModelClassInitializer):
|
|||||||
if isinstance(new_sym.node, Var):
|
if isinstance(new_sym.node, Var):
|
||||||
new_var = Var(name, type=sym.type)
|
new_var = Var(name, type=sym.type)
|
||||||
new_var.info = custom_manager_info
|
new_var.info = custom_manager_info
|
||||||
new_var._fullname = custom_manager_info.fullname() + '.' + name
|
new_var._fullname = custom_manager_info.fullname + '.' + name
|
||||||
new_sym.node = new_var
|
new_sym.node = new_var
|
||||||
custom_manager_info.names[name] = new_sym
|
custom_manager_info.names[name] = new_sym
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ def typecheck_queryset_filter(ctx: MethodContext, django_context: DjangoContext)
|
|||||||
if not ctx.type.args or not isinstance(ctx.type.args[0], Instance):
|
if not ctx.type.args or not isinstance(ctx.type.args[0], Instance):
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
|
|
||||||
model_cls_fullname = ctx.type.args[0].type.fullname()
|
model_cls_fullname = ctx.type.args[0].type.fullname
|
||||||
model_cls = django_context.get_model_class_by_fullname(model_cls_fullname)
|
model_cls = django_context.get_model_class_by_fullname(model_cls_fullname)
|
||||||
if model_cls is None:
|
if model_cls is None:
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
@@ -44,7 +44,7 @@ def typecheck_queryset_filter(ctx: MethodContext, django_context: DjangoContext)
|
|||||||
|
|
||||||
|
|
||||||
def resolve_combinable_type(combinable_type: Instance, django_context: DjangoContext) -> MypyType:
|
def resolve_combinable_type(combinable_type: Instance, django_context: DjangoContext) -> MypyType:
|
||||||
if combinable_type.type.fullname() != fullnames.F_EXPRESSION_FULLNAME:
|
if combinable_type.type.fullname != fullnames.F_EXPRESSION_FULLNAME:
|
||||||
# Combinables aside from F expressions are unsupported
|
# Combinables aside from F expressions are unsupported
|
||||||
return AnyType(TypeOfAny.explicit)
|
return AnyType(TypeOfAny.explicit)
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ def extract_proper_type_queryset_values_list(ctx: MethodContext, django_context:
|
|||||||
if model_type is None:
|
if model_type is None:
|
||||||
return AnyType(TypeOfAny.from_omitted_generics)
|
return AnyType(TypeOfAny.from_omitted_generics)
|
||||||
|
|
||||||
model_cls = django_context.get_model_class_by_fullname(model_type.type.fullname())
|
model_cls = django_context.get_model_class_by_fullname(model_type.type.fullname)
|
||||||
if model_cls is None:
|
if model_cls is None:
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ def extract_proper_type_queryset_values(ctx: MethodContext, django_context: Djan
|
|||||||
if model_type is None:
|
if model_type is None:
|
||||||
return AnyType(TypeOfAny.from_omitted_generics)
|
return AnyType(TypeOfAny.from_omitted_generics)
|
||||||
|
|
||||||
model_cls = django_context.get_model_class_by_fullname(model_type.type.fullname())
|
model_cls = django_context.get_model_class_by_fullname(model_type.type.fullname)
|
||||||
if model_cls is None:
|
if model_cls is None:
|
||||||
return ctx.default_return_type
|
return ctx.default_return_type
|
||||||
|
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -21,7 +21,7 @@ with open('README.md', 'r') as f:
|
|||||||
readme = f.read()
|
readme = f.read()
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
'mypy>=0.740,<0.750',
|
'mypy>=0.750,<0.760',
|
||||||
'typing-extensions',
|
'typing-extensions',
|
||||||
'django',
|
'django',
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -318,7 +318,7 @@
|
|||||||
content: |
|
content: |
|
||||||
from django.db import models
|
from django.db import models
|
||||||
class MyManager(models.Manager):
|
class MyManager(models.Manager):
|
||||||
def get_instance(self) -> int:
|
def get_instance(self: "models.Manager[User]") -> int:
|
||||||
pass
|
pass
|
||||||
class User(models.Model):
|
class User(models.Model):
|
||||||
objects = MyManager()
|
objects = MyManager()
|
||||||
|
|||||||
Reference in New Issue
Block a user