mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-14 07:47:09 +08:00
updated package setup (#485)
* updated package setup * updated to use python 3.9 * fixed test runner * fixed typecheck tests * fixed discrepencies * added override to runner * updated travis * updated pre-commit hooks * updated dep
This commit is contained in:
committed by
GitHub
parent
a3624dec36
commit
44151c485d
@@ -1,39 +1,34 @@
|
||||
MODEL_CLASS_FULLNAME = "django.db.models.base.Model"
|
||||
FIELD_FULLNAME = "django.db.models.fields.Field"
|
||||
CHAR_FIELD_FULLNAME = "django.db.models.fields.CharField"
|
||||
ARRAY_FIELD_FULLNAME = "django.contrib.postgres.fields.array.ArrayField"
|
||||
AUTO_FIELD_FULLNAME = "django.db.models.fields.AutoField"
|
||||
GENERIC_FOREIGN_KEY_FULLNAME = "django.contrib.contenttypes.fields.GenericForeignKey"
|
||||
FOREIGN_KEY_FULLNAME = "django.db.models.fields.related.ForeignKey"
|
||||
ONETOONE_FIELD_FULLNAME = "django.db.models.fields.related.OneToOneField"
|
||||
MANYTOMANY_FIELD_FULLNAME = "django.db.models.fields.related.ManyToManyField"
|
||||
DUMMY_SETTINGS_BASE_CLASS = "django.conf._DjangoConfLazyObject"
|
||||
|
||||
MODEL_CLASS_FULLNAME = 'django.db.models.base.Model'
|
||||
FIELD_FULLNAME = 'django.db.models.fields.Field'
|
||||
CHAR_FIELD_FULLNAME = 'django.db.models.fields.CharField'
|
||||
ARRAY_FIELD_FULLNAME = 'django.contrib.postgres.fields.array.ArrayField'
|
||||
AUTO_FIELD_FULLNAME = 'django.db.models.fields.AutoField'
|
||||
GENERIC_FOREIGN_KEY_FULLNAME = 'django.contrib.contenttypes.fields.GenericForeignKey'
|
||||
FOREIGN_KEY_FULLNAME = 'django.db.models.fields.related.ForeignKey'
|
||||
ONETOONE_FIELD_FULLNAME = 'django.db.models.fields.related.OneToOneField'
|
||||
MANYTOMANY_FIELD_FULLNAME = 'django.db.models.fields.related.ManyToManyField'
|
||||
DUMMY_SETTINGS_BASE_CLASS = 'django.conf._DjangoConfLazyObject'
|
||||
QUERYSET_CLASS_FULLNAME = "django.db.models.query.QuerySet"
|
||||
BASE_MANAGER_CLASS_FULLNAME = "django.db.models.manager.BaseManager"
|
||||
MANAGER_CLASS_FULLNAME = "django.db.models.manager.Manager"
|
||||
RELATED_MANAGER_CLASS = "django.db.models.manager.RelatedManager"
|
||||
|
||||
QUERYSET_CLASS_FULLNAME = 'django.db.models.query.QuerySet'
|
||||
BASE_MANAGER_CLASS_FULLNAME = 'django.db.models.manager.BaseManager'
|
||||
MANAGER_CLASS_FULLNAME = 'django.db.models.manager.Manager'
|
||||
RELATED_MANAGER_CLASS = 'django.db.models.manager.RelatedManager'
|
||||
BASEFORM_CLASS_FULLNAME = "django.forms.forms.BaseForm"
|
||||
FORM_CLASS_FULLNAME = "django.forms.forms.Form"
|
||||
MODELFORM_CLASS_FULLNAME = "django.forms.models.ModelForm"
|
||||
|
||||
BASEFORM_CLASS_FULLNAME = 'django.forms.forms.BaseForm'
|
||||
FORM_CLASS_FULLNAME = 'django.forms.forms.Form'
|
||||
MODELFORM_CLASS_FULLNAME = 'django.forms.models.ModelForm'
|
||||
|
||||
FORM_MIXIN_CLASS_FULLNAME = 'django.views.generic.edit.FormMixin'
|
||||
FORM_MIXIN_CLASS_FULLNAME = "django.views.generic.edit.FormMixin"
|
||||
|
||||
MANAGER_CLASSES = {
|
||||
MANAGER_CLASS_FULLNAME,
|
||||
BASE_MANAGER_CLASS_FULLNAME,
|
||||
}
|
||||
|
||||
RELATED_FIELDS_CLASSES = {
|
||||
FOREIGN_KEY_FULLNAME,
|
||||
ONETOONE_FIELD_FULLNAME,
|
||||
MANYTOMANY_FIELD_FULLNAME
|
||||
}
|
||||
RELATED_FIELDS_CLASSES = {FOREIGN_KEY_FULLNAME, ONETOONE_FIELD_FULLNAME, MANYTOMANY_FIELD_FULLNAME}
|
||||
|
||||
MIGRATION_CLASS_FULLNAME = 'django.db.migrations.migration.Migration'
|
||||
OPTIONS_CLASS_FULLNAME = 'django.db.models.options.Options'
|
||||
HTTPREQUEST_CLASS_FULLNAME = 'django.http.request.HttpRequest'
|
||||
MIGRATION_CLASS_FULLNAME = "django.db.migrations.migration.Migration"
|
||||
OPTIONS_CLASS_FULLNAME = "django.db.models.options.Options"
|
||||
HTTPREQUEST_CLASS_FULLNAME = "django.http.request.HttpRequest"
|
||||
|
||||
F_EXPRESSION_FULLNAME = 'django.db.models.expressions.F'
|
||||
F_EXPRESSION_FULLNAME = "django.db.models.expressions.F"
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
from collections import OrderedDict
|
||||
from typing import (
|
||||
TYPE_CHECKING, Any, Dict, Iterable, Iterator, List, Optional, Set, Tuple, Union,
|
||||
)
|
||||
from typing import TYPE_CHECKING, Any, Dict, Iterable, Iterator, List, Optional, Set, Tuple, Union
|
||||
|
||||
from django.db.models.fields import Field
|
||||
from django.db.models.fields.related import RelatedField
|
||||
@@ -10,11 +8,31 @@ from mypy import checker
|
||||
from mypy.checker import TypeChecker
|
||||
from mypy.mro import calculate_mro
|
||||
from mypy.nodes import (
|
||||
GDEF, MDEF, Argument, Block, ClassDef, Expression, FuncDef, MemberExpr, MypyFile, NameExpr, PlaceholderNode,
|
||||
StrExpr, SymbolNode, SymbolTable, SymbolTableNode, TypeInfo, Var,
|
||||
GDEF,
|
||||
MDEF,
|
||||
Argument,
|
||||
Block,
|
||||
ClassDef,
|
||||
Expression,
|
||||
FuncDef,
|
||||
MemberExpr,
|
||||
MypyFile,
|
||||
NameExpr,
|
||||
PlaceholderNode,
|
||||
StrExpr,
|
||||
SymbolNode,
|
||||
SymbolTable,
|
||||
SymbolTableNode,
|
||||
TypeInfo,
|
||||
Var,
|
||||
)
|
||||
from mypy.plugin import (
|
||||
AttributeContext, CheckerPluginInterface, ClassDefContext, DynamicClassDefContext, FunctionContext, MethodContext,
|
||||
AttributeContext,
|
||||
CheckerPluginInterface,
|
||||
ClassDefContext,
|
||||
DynamicClassDefContext,
|
||||
FunctionContext,
|
||||
MethodContext,
|
||||
)
|
||||
from mypy.plugins.common import add_method
|
||||
from mypy.semanal import SemanticAnalyzer
|
||||
@@ -29,7 +47,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
def get_django_metadata(model_info: TypeInfo) -> Dict[str, Any]:
|
||||
return model_info.metadata.setdefault('django', {})
|
||||
return model_info.metadata.setdefault("django", {})
|
||||
|
||||
|
||||
class IncompleteDefnException(Exception):
|
||||
@@ -37,9 +55,9 @@ class IncompleteDefnException(Exception):
|
||||
|
||||
|
||||
def lookup_fully_qualified_sym(fullname: str, all_modules: Dict[str, MypyFile]) -> Optional[SymbolTableNode]:
|
||||
if '.' not in fullname:
|
||||
if "." not in fullname:
|
||||
return None
|
||||
module, cls_name = fullname.rsplit('.', 1)
|
||||
module, cls_name = fullname.rsplit(".", 1)
|
||||
|
||||
module_file = all_modules.get(module)
|
||||
if module_file is None:
|
||||
@@ -71,12 +89,11 @@ def lookup_class_typeinfo(api: TypeChecker, klass: type) -> Optional[TypeInfo]:
|
||||
|
||||
|
||||
def reparametrize_instance(instance: Instance, new_args: List[MypyType]) -> Instance:
|
||||
return Instance(instance.type, args=new_args,
|
||||
line=instance.line, column=instance.column)
|
||||
return Instance(instance.type, args=new_args, line=instance.line, column=instance.column)
|
||||
|
||||
|
||||
def get_class_fullname(klass: type) -> str:
|
||||
return klass.__module__ + '.' + klass.__qualname__
|
||||
return klass.__module__ + "." + klass.__qualname__
|
||||
|
||||
|
||||
def get_call_argument_by_name(ctx: Union[FunctionContext, MethodContext], name: str) -> Optional[Expression]:
|
||||
@@ -115,9 +132,9 @@ def make_optional(typ: MypyType) -> MypyType:
|
||||
|
||||
def parse_bool(expr: Expression) -> Optional[bool]:
|
||||
if isinstance(expr, NameExpr):
|
||||
if expr.fullname == 'builtins.True':
|
||||
if expr.fullname == "builtins.True":
|
||||
return True
|
||||
if expr.fullname == 'builtins.False':
|
||||
if expr.fullname == "builtins.False":
|
||||
return False
|
||||
return None
|
||||
|
||||
@@ -164,27 +181,24 @@ def get_field_lookup_exact_type(api: TypeChecker, field: Field) -> MypyType:
|
||||
field_info = lookup_class_typeinfo(api, field.__class__)
|
||||
if field_info is None:
|
||||
return AnyType(TypeOfAny.explicit)
|
||||
return get_private_descriptor_type(field_info, '_pyi_lookup_exact_type',
|
||||
is_nullable=field.null)
|
||||
return get_private_descriptor_type(field_info, "_pyi_lookup_exact_type", is_nullable=field.null)
|
||||
|
||||
|
||||
def get_nested_meta_node_for_current_class(info: TypeInfo) -> Optional[TypeInfo]:
|
||||
metaclass_sym = info.names.get('Meta')
|
||||
metaclass_sym = info.names.get("Meta")
|
||||
if metaclass_sym is not None and isinstance(metaclass_sym.node, TypeInfo):
|
||||
return metaclass_sym.node
|
||||
return None
|
||||
|
||||
|
||||
def add_new_class_for_module(module: MypyFile,
|
||||
name: str,
|
||||
bases: List[Instance],
|
||||
fields: Optional[Dict[str, MypyType]] = None
|
||||
) -> TypeInfo:
|
||||
def add_new_class_for_module(
|
||||
module: MypyFile, name: str, bases: List[Instance], fields: Optional[Dict[str, MypyType]] = None
|
||||
) -> TypeInfo:
|
||||
new_class_unique_name = checker.gen_unique_name(name, module.names)
|
||||
|
||||
# make new class expression
|
||||
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
|
||||
new_typeinfo = TypeInfo(SymbolTable(), classdef, module.fullname)
|
||||
@@ -197,7 +211,7 @@ def add_new_class_for_module(module: MypyFile,
|
||||
for field_name, field_type in fields.items():
|
||||
var = Var(field_name, type=field_type)
|
||||
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)
|
||||
|
||||
classdef.info = new_typeinfo
|
||||
@@ -215,18 +229,17 @@ def get_current_module(api: TypeChecker) -> MypyFile:
|
||||
return current_module
|
||||
|
||||
|
||||
def make_oneoff_named_tuple(api: TypeChecker, name: str, fields: 'OrderedDict[str, MypyType]') -> TupleType:
|
||||
def make_oneoff_named_tuple(api: TypeChecker, name: str, fields: "OrderedDict[str, MypyType]") -> TupleType:
|
||||
current_module = get_current_module(api)
|
||||
namedtuple_info = add_new_class_for_module(current_module, name,
|
||||
bases=[api.named_generic_type('typing.NamedTuple', [])],
|
||||
fields=fields)
|
||||
namedtuple_info = add_new_class_for_module(
|
||||
current_module, name, bases=[api.named_generic_type("typing.NamedTuple", [])], fields=fields
|
||||
)
|
||||
return TupleType(list(fields.values()), fallback=Instance(namedtuple_info, []))
|
||||
|
||||
|
||||
def make_tuple(api: 'TypeChecker', fields: List[MypyType]) -> TupleType:
|
||||
def make_tuple(api: "TypeChecker", fields: List[MypyType]) -> TupleType:
|
||||
# fallback for tuples is any builtins.tuple instance
|
||||
fallback = api.named_generic_type('builtins.tuple',
|
||||
[AnyType(TypeOfAny.special_form)])
|
||||
fallback = api.named_generic_type("builtins.tuple", [AnyType(TypeOfAny.special_form)])
|
||||
return TupleType(fields, fallback=fallback)
|
||||
|
||||
|
||||
@@ -235,8 +248,7 @@ def convert_any_to_type(typ: MypyType, referred_to_type: MypyType) -> MypyType:
|
||||
converted_items = []
|
||||
for item in typ.items:
|
||||
converted_items.append(convert_any_to_type(item, referred_to_type))
|
||||
return UnionType.make_union(converted_items,
|
||||
line=typ.line, column=typ.column)
|
||||
return UnionType.make_union(converted_items, line=typ.line, column=typ.column)
|
||||
if isinstance(typ, Instance):
|
||||
args = []
|
||||
for default_arg in typ.args:
|
||||
@@ -252,21 +264,22 @@ def convert_any_to_type(typ: MypyType, referred_to_type: MypyType) -> MypyType:
|
||||
return typ
|
||||
|
||||
|
||||
def make_typeddict(api: CheckerPluginInterface, fields: 'OrderedDict[str, MypyType]',
|
||||
required_keys: Set[str]) -> TypedDictType:
|
||||
object_type = api.named_generic_type('mypy_extensions._TypedDict', [])
|
||||
def make_typeddict(
|
||||
api: CheckerPluginInterface, fields: "OrderedDict[str, MypyType]", required_keys: Set[str]
|
||||
) -> TypedDictType:
|
||||
object_type = api.named_generic_type("mypy_extensions._TypedDict", [])
|
||||
typed_dict_type = TypedDictType(fields, required_keys=required_keys, fallback=object_type)
|
||||
return typed_dict_type
|
||||
|
||||
|
||||
def resolve_string_attribute_value(attr_expr: Expression, django_context: 'DjangoContext') -> Optional[str]:
|
||||
def resolve_string_attribute_value(attr_expr: Expression, django_context: "DjangoContext") -> Optional[str]:
|
||||
if isinstance(attr_expr, StrExpr):
|
||||
return attr_expr.value
|
||||
|
||||
# support extracting from settings, in general case it's unresolvable yet
|
||||
if isinstance(attr_expr, MemberExpr):
|
||||
member_name = attr_expr.name
|
||||
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):
|
||||
return getattr(django_context.settings, member_name)
|
||||
return None
|
||||
@@ -274,27 +287,27 @@ def resolve_string_attribute_value(attr_expr: Expression, django_context: 'Djang
|
||||
|
||||
def get_semanal_api(ctx: Union[ClassDefContext, DynamicClassDefContext]) -> SemanticAnalyzer:
|
||||
if not isinstance(ctx.api, SemanticAnalyzer):
|
||||
raise ValueError('Not a SemanticAnalyzer')
|
||||
raise ValueError("Not a SemanticAnalyzer")
|
||||
return ctx.api
|
||||
|
||||
|
||||
def get_typechecker_api(ctx: Union[AttributeContext, MethodContext, FunctionContext]) -> TypeChecker:
|
||||
if not isinstance(ctx.api, TypeChecker):
|
||||
raise ValueError('Not a TypeChecker')
|
||||
raise ValueError("Not a TypeChecker")
|
||||
return ctx.api
|
||||
|
||||
|
||||
def is_model_subclass_info(info: TypeInfo, django_context: 'DjangoContext') -> bool:
|
||||
return (info.fullname in django_context.all_registered_model_class_fullnames
|
||||
or info.has_base(fullnames.MODEL_CLASS_FULLNAME))
|
||||
def is_model_subclass_info(info: TypeInfo, django_context: "DjangoContext") -> bool:
|
||||
return info.fullname in django_context.all_registered_model_class_fullnames or info.has_base(
|
||||
fullnames.MODEL_CLASS_FULLNAME
|
||||
)
|
||||
|
||||
|
||||
def check_types_compatible(ctx: Union[FunctionContext, MethodContext],
|
||||
*, expected_type: MypyType, actual_type: MypyType, error_message: str) -> None:
|
||||
def check_types_compatible(
|
||||
ctx: Union[FunctionContext, MethodContext], *, expected_type: MypyType, actual_type: MypyType, error_message: str
|
||||
) -> None:
|
||||
api = get_typechecker_api(ctx)
|
||||
api.check_subtype(actual_type, expected_type,
|
||||
ctx.context, error_message,
|
||||
'got', 'expected')
|
||||
api.check_subtype(actual_type, expected_type, ctx.context, error_message, "got", "expected")
|
||||
|
||||
|
||||
def add_new_sym_for_info(info: TypeInfo, *, name: str, sym_type: MypyType) -> None:
|
||||
@@ -302,11 +315,10 @@ def add_new_sym_for_info(info: TypeInfo, *, name: str, sym_type: MypyType) -> No
|
||||
var = Var(name=name, type=sym_type)
|
||||
# var.info: type of the object variable is bound to
|
||||
var.info = info
|
||||
var._fullname = info.fullname + '.' + name
|
||||
var._fullname = info.fullname + "." + name
|
||||
var.is_initialized_in_class = True
|
||||
var.is_inferred = True
|
||||
info.names[name] = SymbolTableNode(MDEF, var,
|
||||
plugin_generated=True)
|
||||
info.names[name] = SymbolTableNode(MDEF, var, plugin_generated=True)
|
||||
|
||||
|
||||
def build_unannotated_method_args(method_node: FuncDef) -> Tuple[List[Argument], MypyType]:
|
||||
@@ -322,8 +334,9 @@ def build_unannotated_method_args(method_node: FuncDef) -> Tuple[List[Argument],
|
||||
return prepared_arguments, return_type
|
||||
|
||||
|
||||
def copy_method_to_another_class(ctx: ClassDefContext, self_type: Instance,
|
||||
new_method_name: str, method_node: FuncDef) -> None:
|
||||
def copy_method_to_another_class(
|
||||
ctx: ClassDefContext, self_type: Instance, new_method_name: str, method_node: FuncDef
|
||||
) -> None:
|
||||
semanal_api = get_semanal_api(ctx)
|
||||
if method_node.type is None:
|
||||
if not semanal_api.final_iteration:
|
||||
@@ -331,11 +344,7 @@ def copy_method_to_another_class(ctx: ClassDefContext, self_type: Instance,
|
||||
return
|
||||
|
||||
arguments, return_type = build_unannotated_method_args(method_node)
|
||||
add_method(ctx,
|
||||
new_method_name,
|
||||
args=arguments,
|
||||
return_type=return_type,
|
||||
self_type=self_type)
|
||||
add_method(ctx, new_method_name, args=arguments, return_type=return_type, self_type=self_type)
|
||||
return
|
||||
|
||||
method_type = method_node.type
|
||||
@@ -345,17 +354,16 @@ def copy_method_to_another_class(ctx: ClassDefContext, self_type: Instance,
|
||||
return
|
||||
|
||||
arguments = []
|
||||
bound_return_type = semanal_api.anal_type(method_type.ret_type,
|
||||
allow_placeholder=True)
|
||||
bound_return_type = semanal_api.anal_type(method_type.ret_type, allow_placeholder=True)
|
||||
|
||||
assert bound_return_type is not None
|
||||
|
||||
if isinstance(bound_return_type, PlaceholderNode):
|
||||
return
|
||||
|
||||
for arg_name, arg_type, original_argument in zip(method_type.arg_names[1:],
|
||||
method_type.arg_types[1:],
|
||||
method_node.arguments[1:]):
|
||||
for arg_name, arg_type, original_argument in zip(
|
||||
method_type.arg_names[1:], method_type.arg_types[1:], method_node.arguments[1:]
|
||||
):
|
||||
bound_arg_type = semanal_api.anal_type(arg_type, allow_placeholder=True)
|
||||
if bound_arg_type is None and not semanal_api.final_iteration:
|
||||
semanal_api.defer()
|
||||
@@ -366,19 +374,16 @@ def copy_method_to_another_class(ctx: ClassDefContext, self_type: Instance,
|
||||
if isinstance(bound_arg_type, PlaceholderNode):
|
||||
return
|
||||
|
||||
var = Var(name=original_argument.variable.name,
|
||||
type=arg_type)
|
||||
var = Var(name=original_argument.variable.name, type=arg_type)
|
||||
var.line = original_argument.variable.line
|
||||
var.column = original_argument.variable.column
|
||||
argument = Argument(variable=var,
|
||||
type_annotation=bound_arg_type,
|
||||
initializer=original_argument.initializer,
|
||||
kind=original_argument.kind)
|
||||
argument = Argument(
|
||||
variable=var,
|
||||
type_annotation=bound_arg_type,
|
||||
initializer=original_argument.initializer,
|
||||
kind=original_argument.kind,
|
||||
)
|
||||
argument.set_line(original_argument)
|
||||
arguments.append(argument)
|
||||
|
||||
add_method(ctx,
|
||||
new_method_name,
|
||||
args=arguments,
|
||||
return_type=bound_return_type,
|
||||
self_type=self_type)
|
||||
add_method(ctx, new_method_name, args=arguments, return_type=bound_return_type, self_type=self_type)
|
||||
|
||||
Reference in New Issue
Block a user