mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-08 21:14:49 +08:00
attempt to add flake8 and isort
This commit is contained in:
16
.travis.yml
16
.travis.yml
@@ -4,10 +4,6 @@ dist: xenial
|
|||||||
sudo: required
|
sudo: required
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- name: Typecheck Django test suite
|
|
||||||
python: 3.7
|
|
||||||
script: 'python ./scripts/typecheck_tests.py'
|
|
||||||
|
|
||||||
- name: Run plugin test suite with python 3.7
|
- name: Run plugin test suite with python 3.7
|
||||||
python: 3.7
|
python: 3.7
|
||||||
script: |
|
script: |
|
||||||
@@ -20,10 +16,22 @@ jobs:
|
|||||||
set -e
|
set -e
|
||||||
pytest
|
pytest
|
||||||
|
|
||||||
|
- name: Typecheck Django test suite
|
||||||
|
python: 3.7
|
||||||
|
script: 'python ./scripts/typecheck_tests.py'
|
||||||
|
|
||||||
- name: Lint with black
|
- name: Lint with black
|
||||||
python: 3.7
|
python: 3.7
|
||||||
script: 'black --check --line-length=120 django-stubs/'
|
script: 'black --check --line-length=120 django-stubs/'
|
||||||
|
|
||||||
|
- name: Lint plugin code with flake8
|
||||||
|
python: 3.7
|
||||||
|
script: 'flake8'
|
||||||
|
|
||||||
|
- name: Lint plugin code with isort
|
||||||
|
python: 3.7
|
||||||
|
script: 'isort --check'
|
||||||
|
|
||||||
before_install: |
|
before_install: |
|
||||||
# Upgrade pip, setuptools, and wheel
|
# Upgrade pip, setuptools, and wheel
|
||||||
pip install -U pip setuptools wheel
|
pip install -U pip setuptools wheel
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
black
|
black
|
||||||
pytest-mypy-plugins
|
pytest-mypy-plugins
|
||||||
|
flake8
|
||||||
|
isort==4.3.4
|
||||||
-e .
|
-e .
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from typing import List, Optional
|
from typing import Optional
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
@@ -16,10 +16,12 @@ class Config:
|
|||||||
if not ini_config.has_section('mypy_django_plugin'):
|
if not ini_config.has_section('mypy_django_plugin'):
|
||||||
raise ValueError('Invalid config file: no [mypy_django_plugin] section')
|
raise ValueError('Invalid config file: no [mypy_django_plugin] section')
|
||||||
|
|
||||||
django_settings = ini_config.get('mypy_django_plugin', 'django_settings',
|
django_settings = ini_config.get('mypy_django_plugin', 'django_settings')
|
||||||
fallback=None)
|
if type(django_settings) == object:
|
||||||
if django_settings:
|
django_settings = None
|
||||||
|
else:
|
||||||
django_settings = django_settings.strip()
|
django_settings = django_settings.strip()
|
||||||
|
|
||||||
return Config(django_settings_module=django_settings,
|
return Config(django_settings_module=django_settings,
|
||||||
ignore_missing_settings=ini_config.get('mypy_django_plugin', 'ignore_missing_settings',
|
ignore_missing_settings=bool(ini_config.get('mypy_django_plugin', 'ignore_missing_settings',
|
||||||
fallback=False))
|
fallback=False)))
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ import typing
|
|||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from mypy.checker import TypeChecker
|
from mypy.checker import TypeChecker
|
||||||
from mypy.nodes import AssignmentStmt, ClassDef, Expression, ImportedName, Lvalue, MypyFile, NameExpr, SymbolNode, \
|
from mypy.nodes import (
|
||||||
TypeInfo
|
AssignmentStmt, ClassDef, Expression, ImportedName, Lvalue, MypyFile, NameExpr, SymbolNode, TypeInfo,
|
||||||
|
)
|
||||||
from mypy.plugin import FunctionContext, MethodContext
|
from mypy.plugin import FunctionContext, MethodContext
|
||||||
from mypy.types import AnyType, Instance, NoneTyp, Type, TypeOfAny, TypeVarType, UnionType
|
from mypy.types import (
|
||||||
|
AnyType, Instance, NoneTyp, Type, TypeOfAny, TypeVarType, UnionType,
|
||||||
|
)
|
||||||
|
|
||||||
MODEL_CLASS_FULLNAME = 'django.db.models.base.Model'
|
MODEL_CLASS_FULLNAME = 'django.db.models.base.Model'
|
||||||
FIELD_FULLNAME = 'django.db.models.fields.Field'
|
FIELD_FULLNAME = 'django.db.models.fields.Field'
|
||||||
|
|||||||
@@ -2,19 +2,28 @@ import os
|
|||||||
from typing import Callable, Dict, Optional, Union, cast
|
from typing import Callable, Dict, Optional, Union, cast
|
||||||
|
|
||||||
from mypy.checker import TypeChecker
|
from mypy.checker import TypeChecker
|
||||||
from mypy.nodes import MemberExpr, TypeInfo, NameExpr
|
from mypy.nodes import MemberExpr, NameExpr, TypeInfo
|
||||||
from mypy.options import Options
|
from mypy.options import Options
|
||||||
from mypy.plugin import AttributeContext, ClassDefContext, FunctionContext, MethodContext, Plugin
|
from mypy.plugin import (
|
||||||
from mypy.types import AnyType, Instance, Type, TypeOfAny, TypeType, UnionType, CallableType, NoneTyp
|
AttributeContext, ClassDefContext, FunctionContext, MethodContext, Plugin,
|
||||||
|
)
|
||||||
|
from mypy.types import (
|
||||||
|
AnyType, CallableType, Instance, NoneTyp, Type, TypeOfAny, TypeType, UnionType,
|
||||||
|
)
|
||||||
|
|
||||||
from mypy_django_plugin import helpers, monkeypatch
|
from mypy_django_plugin import helpers, monkeypatch
|
||||||
from mypy_django_plugin.config import Config
|
from mypy_django_plugin.config import Config
|
||||||
from mypy_django_plugin.transformers import fields, init_create
|
from mypy_django_plugin.transformers import fields, init_create
|
||||||
from mypy_django_plugin.transformers.forms import make_meta_nested_class_inherit_from_any
|
from mypy_django_plugin.transformers.forms import (
|
||||||
from mypy_django_plugin.transformers.migrations import determine_model_cls_from_string_for_migrations, \
|
make_meta_nested_class_inherit_from_any,
|
||||||
get_string_value_from_expr
|
)
|
||||||
|
from mypy_django_plugin.transformers.migrations import (
|
||||||
|
determine_model_cls_from_string_for_migrations, get_string_value_from_expr,
|
||||||
|
)
|
||||||
from mypy_django_plugin.transformers.models import process_model_class
|
from mypy_django_plugin.transformers.models import process_model_class
|
||||||
from mypy_django_plugin.transformers.settings import AddSettingValuesToDjangoConfObject, get_settings_metadata
|
from mypy_django_plugin.transformers.settings import (
|
||||||
|
AddSettingValuesToDjangoConfObject, get_settings_metadata,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def transform_model_class(ctx: ClassDefContext) -> None:
|
def transform_model_class(ctx: ClassDefContext) -> None:
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
from .dependencies import (add_modules_as_a_source_seed_files,
|
|
||||||
inject_modules_as_dependencies_for_django_conf_settings,
|
|
||||||
restore_original_load_graph,
|
|
||||||
restore_original_dependencies_handling)
|
|
||||||
@@ -3,9 +3,11 @@ from typing import Optional, cast
|
|||||||
from mypy.checker import TypeChecker
|
from mypy.checker import TypeChecker
|
||||||
from mypy.nodes import ListExpr, NameExpr, StrExpr, TupleExpr, TypeInfo, Var
|
from mypy.nodes import ListExpr, NameExpr, StrExpr, TupleExpr, TypeInfo, Var
|
||||||
from mypy.plugin import FunctionContext
|
from mypy.plugin import FunctionContext
|
||||||
from mypy.types import AnyType, CallableType, Instance, TupleType, Type, TypeOfAny, UnionType
|
from mypy.types import (
|
||||||
|
AnyType, CallableType, Instance, TupleType, Type, TypeOfAny, UnionType,
|
||||||
|
)
|
||||||
|
|
||||||
from mypy_django_plugin import helpers
|
from mypy_django_plugin import helpers
|
||||||
from mypy_django_plugin.transformers.models import iter_over_assignments
|
|
||||||
|
|
||||||
|
|
||||||
def extract_referred_to_type(ctx: FunctionContext) -> Optional[Instance]:
|
def extract_referred_to_type(ctx: FunctionContext) -> Optional[Instance]:
|
||||||
@@ -154,7 +156,7 @@ def record_field_properties_into_outer_model_class(ctx: FunctionContext) -> None
|
|||||||
return
|
return
|
||||||
|
|
||||||
field_name = None
|
field_name = None
|
||||||
for name_expr, stmt in iter_over_assignments(outer_model.defn):
|
for name_expr, stmt in helpers.iter_over_assignments(outer_model.defn):
|
||||||
if stmt == ctx.context and isinstance(name_expr, NameExpr):
|
if stmt == ctx.context and isinstance(name_expr, NameExpr):
|
||||||
field_name = name_expr.name
|
field_name = name_expr.name
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from mypy.plugin import ClassDefContext
|
from mypy.plugin import ClassDefContext
|
||||||
|
|
||||||
from mypy_django_plugin import helpers
|
from mypy_django_plugin import helpers
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ from mypy.checker import TypeChecker
|
|||||||
from mypy.nodes import TypeInfo, Var
|
from mypy.nodes import TypeInfo, Var
|
||||||
from mypy.plugin import FunctionContext, MethodContext
|
from mypy.plugin import FunctionContext, MethodContext
|
||||||
from mypy.types import AnyType, Instance, Type, TypeOfAny
|
from mypy.types import AnyType, Instance, Type, TypeOfAny
|
||||||
|
|
||||||
from mypy_django_plugin import helpers
|
from mypy_django_plugin import helpers
|
||||||
from mypy_django_plugin.helpers import extract_field_setter_type, extract_explicit_set_type_of_model_primary_key, get_fields_metadata
|
|
||||||
from mypy_django_plugin.transformers.fields import get_private_descriptor_type
|
from mypy_django_plugin.transformers.fields import get_private_descriptor_type
|
||||||
|
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ def redefine_and_typecheck_model_create(ctx: MethodContext) -> Type:
|
|||||||
|
|
||||||
|
|
||||||
def extract_choices_type(model: TypeInfo, field_name: str) -> Optional[str]:
|
def extract_choices_type(model: TypeInfo, field_name: str) -> Optional[str]:
|
||||||
field_metadata = get_fields_metadata(model).get(field_name, {})
|
field_metadata = helpers.get_fields_metadata(model).get(field_name, {})
|
||||||
if 'choices' in field_metadata:
|
if 'choices' in field_metadata:
|
||||||
return field_metadata['choices']
|
return field_metadata['choices']
|
||||||
return None
|
return None
|
||||||
@@ -117,7 +117,7 @@ def extract_expected_types(ctx: FunctionContext, model: TypeInfo,
|
|||||||
api = cast(TypeChecker, ctx.api)
|
api = cast(TypeChecker, ctx.api)
|
||||||
|
|
||||||
expected_types: Dict[str, Type] = {}
|
expected_types: Dict[str, Type] = {}
|
||||||
primary_key_type = extract_explicit_set_type_of_model_primary_key(model)
|
primary_key_type = helpers.extract_explicit_set_type_of_model_primary_key(model)
|
||||||
if not primary_key_type:
|
if not primary_key_type:
|
||||||
# no explicit primary key, set pk to Any and add id
|
# no explicit primary key, set pk to Any and add id
|
||||||
primary_key_type = AnyType(TypeOfAny.special_form)
|
primary_key_type = AnyType(TypeOfAny.special_form)
|
||||||
@@ -143,7 +143,7 @@ def extract_expected_types(ctx: FunctionContext, model: TypeInfo,
|
|||||||
expected_types[name + '_id'] = AnyType(TypeOfAny.from_unimported_type)
|
expected_types[name + '_id'] = AnyType(TypeOfAny.from_unimported_type)
|
||||||
|
|
||||||
elif isinstance(typ, Instance):
|
elif isinstance(typ, Instance):
|
||||||
field_type = extract_field_setter_type(typ)
|
field_type = helpers.extract_field_setter_type(typ)
|
||||||
if field_type is None:
|
if field_type is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -156,8 +156,9 @@ def extract_expected_types(ctx: FunctionContext, model: TypeInfo,
|
|||||||
if is_nullable:
|
if is_nullable:
|
||||||
referred_to_model = helpers.make_required(typ.args[1])
|
referred_to_model = helpers.make_required(typ.args[1])
|
||||||
|
|
||||||
if isinstance(referred_to_model, Instance) and referred_to_model.type.has_base(helpers.MODEL_CLASS_FULLNAME):
|
if isinstance(referred_to_model, Instance) and referred_to_model.type.has_base(
|
||||||
pk_type = extract_explicit_set_type_of_model_primary_key(referred_to_model.type)
|
helpers.MODEL_CLASS_FULLNAME):
|
||||||
|
pk_type = helpers.extract_explicit_set_type_of_model_primary_key(referred_to_model.type)
|
||||||
if not pk_type:
|
if not pk_type:
|
||||||
# extract set type of AutoField
|
# extract set type of AutoField
|
||||||
autofield_info = api.lookup_typeinfo('django.db.models.fields.AutoField')
|
autofield_info = api.lookup_typeinfo('django.db.models.fields.AutoField')
|
||||||
@@ -170,7 +171,7 @@ def extract_expected_types(ctx: FunctionContext, model: TypeInfo,
|
|||||||
|
|
||||||
expected_types[name + '_id'] = related_primary_key_type
|
expected_types[name + '_id'] = related_primary_key_type
|
||||||
|
|
||||||
field_metadata = get_fields_metadata(model).get(name, {})
|
field_metadata = helpers.get_fields_metadata(model).get(name, {})
|
||||||
if field_type:
|
if field_type:
|
||||||
# related fields could be None in __init__ (but should be specified before save())
|
# related fields could be None in __init__ (but should be specified before save())
|
||||||
if helpers.has_any_of_bases(typ.type, (helpers.FOREIGN_KEY_FULLNAME,
|
if helpers.has_any_of_bases(typ.type, (helpers.FOREIGN_KEY_FULLNAME,
|
||||||
@@ -178,7 +179,8 @@ def extract_expected_types(ctx: FunctionContext, model: TypeInfo,
|
|||||||
field_type = helpers.make_optional(field_type)
|
field_type = helpers.make_optional(field_type)
|
||||||
|
|
||||||
# if primary_key=True and default specified
|
# if primary_key=True and default specified
|
||||||
elif field_metadata.get('primary_key', False) and field_metadata.get('default_specified', False):
|
elif field_metadata.get('primary_key', False) and field_metadata.get('default_specified',
|
||||||
|
False):
|
||||||
field_type = helpers.make_optional(field_type)
|
field_type = helpers.make_optional(field_type)
|
||||||
|
|
||||||
expected_types[name] = field_type
|
expected_types[name] = field_type
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from mypy.checker import TypeChecker
|
|||||||
from mypy.nodes import Expression, StrExpr, TypeInfo
|
from mypy.nodes import Expression, StrExpr, TypeInfo
|
||||||
from mypy.plugin import MethodContext
|
from mypy.plugin import MethodContext
|
||||||
from mypy.types import Instance, Type, TypeType
|
from mypy.types import Instance, Type, TypeType
|
||||||
|
|
||||||
from mypy_django_plugin import helpers
|
from mypy_django_plugin import helpers
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,16 @@ from abc import ABCMeta, abstractmethod
|
|||||||
from typing import Dict, Iterator, List, Optional, Tuple, cast
|
from typing import Dict, Iterator, List, Optional, Tuple, cast
|
||||||
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
from mypy.nodes import ARG_STAR, ARG_STAR2, Argument, CallExpr, ClassDef, Expression, IndexExpr, \
|
from mypy.nodes import (
|
||||||
Lvalue, MDEF, MemberExpr, MypyFile, NameExpr, StrExpr, SymbolTableNode, TypeInfo, Var
|
ARG_STAR, ARG_STAR2, MDEF, Argument, CallExpr, ClassDef, Expression, IndexExpr, Lvalue, MemberExpr, MypyFile,
|
||||||
|
NameExpr, StrExpr, SymbolTableNode, TypeInfo, Var,
|
||||||
|
)
|
||||||
from mypy.plugin import ClassDefContext
|
from mypy.plugin import ClassDefContext
|
||||||
from mypy.plugins.common import add_method
|
from mypy.plugins.common import add_method
|
||||||
from mypy.semanal import SemanticAnalyzerPass2
|
from mypy.semanal import SemanticAnalyzerPass2
|
||||||
from mypy.types import AnyType, Instance, NoneTyp, TypeOfAny
|
from mypy.types import AnyType, Instance, NoneTyp, TypeOfAny
|
||||||
|
|
||||||
from mypy_django_plugin import helpers
|
from mypy_django_plugin import helpers
|
||||||
from mypy_django_plugin.helpers import iter_over_assignments
|
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
@@ -48,7 +50,7 @@ class ModelClassInitializer(metaclass=ABCMeta):
|
|||||||
|
|
||||||
|
|
||||||
def iter_call_assignments(klass: ClassDef) -> Iterator[Tuple[Lvalue, CallExpr]]:
|
def iter_call_assignments(klass: ClassDef) -> Iterator[Tuple[Lvalue, CallExpr]]:
|
||||||
for lvalue, rvalue in iter_over_assignments(klass):
|
for lvalue, rvalue in helpers.iter_over_assignments(klass):
|
||||||
if isinstance(rvalue, CallExpr):
|
if isinstance(rvalue, CallExpr):
|
||||||
yield lvalue, rvalue
|
yield lvalue, rvalue
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@ def iter_call_assignments(klass: ClassDef) -> Iterator[Tuple[Lvalue, CallExpr]]:
|
|||||||
def iter_over_one_to_n_related_fields(klass: ClassDef) -> Iterator[Tuple[NameExpr, CallExpr]]:
|
def iter_over_one_to_n_related_fields(klass: ClassDef) -> Iterator[Tuple[NameExpr, CallExpr]]:
|
||||||
for lvalue, rvalue in iter_call_assignments(klass):
|
for lvalue, rvalue in iter_call_assignments(klass):
|
||||||
if (isinstance(lvalue, NameExpr)
|
if (isinstance(lvalue, NameExpr)
|
||||||
and isinstance(rvalue.callee, MemberExpr)):
|
and isinstance(rvalue.callee, MemberExpr)):
|
||||||
if rvalue.callee.fullname in {helpers.FOREIGN_KEY_FULLNAME,
|
if rvalue.callee.fullname in {helpers.FOREIGN_KEY_FULLNAME,
|
||||||
helpers.ONETOONE_FIELD_FULLNAME}:
|
helpers.ONETOONE_FIELD_FULLNAME}:
|
||||||
yield lvalue, rvalue
|
yield lvalue, rvalue
|
||||||
@@ -107,8 +109,8 @@ class AddDefaultObjectsManager(ModelClassInitializer):
|
|||||||
if isinstance(callee_expr, IndexExpr):
|
if isinstance(callee_expr, IndexExpr):
|
||||||
callee_expr = callee_expr.analyzed.expr
|
callee_expr = callee_expr.analyzed.expr
|
||||||
if isinstance(callee_expr, (MemberExpr, NameExpr)) \
|
if isinstance(callee_expr, (MemberExpr, NameExpr)) \
|
||||||
and isinstance(callee_expr.node, TypeInfo) \
|
and isinstance(callee_expr.node, TypeInfo) \
|
||||||
and callee_expr.node.has_base(helpers.BASE_MANAGER_CLASS_FULLNAME):
|
and callee_expr.node.has_base(helpers.BASE_MANAGER_CLASS_FULLNAME):
|
||||||
managers.append((manager_name, callee_expr.node))
|
managers.append((manager_name, callee_expr.node))
|
||||||
return managers
|
return managers
|
||||||
|
|
||||||
@@ -147,7 +149,7 @@ class AddIdAttributeIfPrimaryKeyTrueIsNotSet(ModelClassInitializer):
|
|||||||
|
|
||||||
for _, rvalue in iter_call_assignments(self.model_classdef):
|
for _, rvalue in iter_call_assignments(self.model_classdef):
|
||||||
if ('primary_key' in rvalue.arg_names
|
if ('primary_key' in rvalue.arg_names
|
||||||
and self.api.parse_bool(rvalue.args[rvalue.arg_names.index('primary_key')])):
|
and self.api.parse_bool(rvalue.args[rvalue.arg_names.index('primary_key')])):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
self.add_new_node_to_model_class('id', self.api.builtin_type('builtins.object'))
|
self.add_new_node_to_model_class('id', self.api.builtin_type('builtins.object'))
|
||||||
@@ -202,10 +204,10 @@ def is_related_field(expr: CallExpr, module_file: MypyFile) -> bool:
|
|||||||
if isinstance(expr.callee, MemberExpr) and isinstance(expr.callee.expr, NameExpr):
|
if isinstance(expr.callee, MemberExpr) and isinstance(expr.callee.expr, NameExpr):
|
||||||
module = module_file.names.get(expr.callee.expr.name)
|
module = module_file.names.get(expr.callee.expr.name)
|
||||||
if module \
|
if module \
|
||||||
and module.fullname == 'django.db.models' \
|
and module.fullname == 'django.db.models' \
|
||||||
and expr.callee.name in {'ForeignKey',
|
and expr.callee.name in {'ForeignKey',
|
||||||
'OneToOneField',
|
'OneToOneField',
|
||||||
'ManyToManyField'}:
|
'ManyToManyField'}:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
from typing import Iterable, List, Optional, cast
|
from typing import Iterable, List, Optional, cast
|
||||||
|
|
||||||
from mypy.nodes import ClassDef, Context, ImportAll, MypyFile, SymbolNode, SymbolTableNode, TypeInfo, Var
|
from mypy.nodes import (
|
||||||
|
ClassDef, Context, ImportAll, MypyFile, SymbolNode, SymbolTableNode, TypeInfo, Var,
|
||||||
|
)
|
||||||
from mypy.plugin import ClassDefContext
|
from mypy.plugin import ClassDefContext
|
||||||
from mypy.semanal import SemanticAnalyzerPass2
|
from mypy.semanal import SemanticAnalyzerPass2
|
||||||
from mypy.types import AnyType, Instance, NoneTyp, Type, TypeOfAny, UnionType
|
from mypy.types import AnyType, Instance, NoneTyp, Type, TypeOfAny, UnionType
|
||||||
@@ -56,7 +58,7 @@ def load_settings_from_names(settings_classdef: ClassDef,
|
|||||||
settings_classdef.info.names[name] = copied
|
settings_classdef.info.names[name] = copied
|
||||||
else:
|
else:
|
||||||
var = Var(name, AnyType(TypeOfAny.unannotated))
|
var = Var(name, AnyType(TypeOfAny.unannotated))
|
||||||
var.info = api.named_type('__builtins__.object').type
|
var.info = api.named_type('__builtins__.object').type # outer class type
|
||||||
settings_classdef.info.names[name] = SymbolTableNode(sym.kind, var)
|
settings_classdef.info.names[name] = SymbolTableNode(sym.kind, var)
|
||||||
|
|
||||||
settings_metadata[name] = module.fullname()
|
settings_metadata[name] = module.fullname()
|
||||||
@@ -67,11 +69,12 @@ def get_import_star_modules(api: SemanticAnalyzerPass2, module: MypyFile) -> Lis
|
|||||||
for module_import in module.imports:
|
for module_import in module.imports:
|
||||||
# relative import * are not resolved by mypy
|
# relative import * are not resolved by mypy
|
||||||
if isinstance(module_import, ImportAll) and module_import.relative:
|
if isinstance(module_import, ImportAll) and module_import.relative:
|
||||||
absolute_import_path, correct = correct_relative_import(module.fullname(), module_import.relative, module_import.id,
|
absolute_import_path, correct = correct_relative_import(module.fullname(), module_import.relative,
|
||||||
is_cur_package_init_file=False)
|
module_import.id, is_cur_package_init_file=False)
|
||||||
if not correct:
|
if not correct:
|
||||||
return []
|
return []
|
||||||
for path in [absolute_import_path] + get_import_star_modules(api, module=api.modules.get(absolute_import_path)):
|
for path in [absolute_import_path] + get_import_star_modules(api,
|
||||||
|
module=api.modules.get(absolute_import_path)):
|
||||||
if path not in import_star_modules:
|
if path not in import_star_modules:
|
||||||
import_star_modules.append(path)
|
import_star_modules.append(path)
|
||||||
return import_star_modules
|
return import_star_modules
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
[pytest]
|
[pytest]
|
||||||
|
|
||||||
testpaths = ./test-data
|
testpaths = ./test-data
|
||||||
addopts =
|
addopts =
|
||||||
--tb=native
|
--tb=native
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ IGNORED_ERRORS = {
|
|||||||
# settings
|
# settings
|
||||||
re.compile(r'Module has no attribute "[A-Z_]+"'),
|
re.compile(r'Module has no attribute "[A-Z_]+"'),
|
||||||
# attributes assigned to test functions
|
# attributes assigned to test functions
|
||||||
re.compile(r'"Callable\[(\[(Any(, )?)*((, )?VarArg\(Any\))?((, )?KwArg\(Any\))?\]|\.\.\.), Any\]" has no attribute'),
|
re.compile(
|
||||||
|
r'"Callable\[(\[(Any(, )?)*((, )?VarArg\(Any\))?((, )?KwArg\(Any\))?\]|\.\.\.), Any\]" has no attribute'),
|
||||||
# assign empty tuple
|
# assign empty tuple
|
||||||
re.compile(r'Incompatible types in assignment \(expression has type "Tuple\[\]", '
|
re.compile(r'Incompatible types in assignment \(expression has type "Tuple\[\]", '
|
||||||
r'variable has type "Tuple\[[A-Za-z, ]+\]"'),
|
r'variable has type "Tuple\[[A-Za-z, ]+\]"'),
|
||||||
@@ -54,8 +55,9 @@ IGNORED_ERRORS = {
|
|||||||
'ValuesIterable',
|
'ValuesIterable',
|
||||||
'Value of type "Optional[Dict[str, Any]]" is not indexable',
|
'Value of type "Optional[Dict[str, Any]]" is not indexable',
|
||||||
'Argument 1 to "len" has incompatible type "Optional[List[_Record]]"; expected "Sized"',
|
'Argument 1 to "len" has incompatible type "Optional[List[_Record]]"; expected "Sized"',
|
||||||
'Argument 1 to "loads" has incompatible type "Union[bytes, str, None]"; expected "Union[str, bytes, bytearray]"',
|
'Argument 1 to "loads" has incompatible type "Union[bytes, str, None]"; '
|
||||||
'Incompatible types in assignment (expression has type "None", variable has type Module)'
|
+ 'expected "Union[str, bytes, bytearray]"',
|
||||||
|
'Incompatible types in assignment (expression has type "None", variable has type Module)',
|
||||||
],
|
],
|
||||||
'admin_changelist': [
|
'admin_changelist': [
|
||||||
'Incompatible types in assignment (expression has type "FilteredChildAdmin", variable has type "ChildAdmin")'
|
'Incompatible types in assignment (expression has type "FilteredChildAdmin", variable has type "ChildAdmin")'
|
||||||
@@ -65,8 +67,9 @@ IGNORED_ERRORS = {
|
|||||||
],
|
],
|
||||||
'admin_widgets': [
|
'admin_widgets': [
|
||||||
'Incompatible types in assignment (expression has type "RelatedFieldWidgetWrapper", '
|
'Incompatible types in assignment (expression has type "RelatedFieldWidgetWrapper", '
|
||||||
'variable has type "AdminRadioSelect")',
|
+ 'variable has type "AdminRadioSelect")',
|
||||||
'Incompatible types in assignment (expression has type "Union[Widget, Any]", variable has type "AutocompleteSelect")'
|
'Incompatible types in assignment (expression has type "Union[Widget, Any]", '
|
||||||
|
+ 'variable has type "AutocompleteSelect")'
|
||||||
],
|
],
|
||||||
'admin_utils': [
|
'admin_utils': [
|
||||||
re.compile(r'Argument [0-9] to "lookup_field" has incompatible type'),
|
re.compile(r'Argument [0-9] to "lookup_field" has incompatible type'),
|
||||||
@@ -91,11 +94,13 @@ IGNORED_ERRORS = {
|
|||||||
'Incompatible types in assignment (expression has type "FlatValuesListIterable", '
|
'Incompatible types in assignment (expression has type "FlatValuesListIterable", '
|
||||||
+ 'variable has type "ValuesListIterable")',
|
+ 'variable has type "ValuesListIterable")',
|
||||||
'Incompatible type for "contact" of "Book" (got "Optional[Author]", expected "Union[Author, Combinable]")',
|
'Incompatible type for "contact" of "Book" (got "Optional[Author]", expected "Union[Author, Combinable]")',
|
||||||
'Incompatible type for "publisher" of "Book" (got "Optional[Publisher]", expected "Union[Publisher, Combinable]")'
|
'Incompatible type for "publisher" of "Book" (got "Optional[Publisher]", '
|
||||||
|
+ 'expected "Union[Publisher, Combinable]")'
|
||||||
],
|
],
|
||||||
'aggregation_regress': [
|
'aggregation_regress': [
|
||||||
'Incompatible types in assignment (expression has type "List[str]", variable has type "QuerySet[Author]")',
|
'Incompatible types in assignment (expression has type "List[str]", variable has type "QuerySet[Author]")',
|
||||||
'Incompatible types in assignment (expression has type "FlatValuesListIterable", variable has type "QuerySet[Any]")',
|
'Incompatible types in assignment (expression has type "FlatValuesListIterable", '
|
||||||
|
+ 'variable has type "QuerySet[Any]")',
|
||||||
'Too few arguments for "count" of "Sequence"'
|
'Too few arguments for "count" of "Sequence"'
|
||||||
],
|
],
|
||||||
'apps': [
|
'apps': [
|
||||||
@@ -176,8 +181,8 @@ IGNORED_ERRORS = {
|
|||||||
'variable has type "SongForm"',
|
'variable has type "SongForm"',
|
||||||
'"full_clean" of "BaseForm" does not return a value',
|
'"full_clean" of "BaseForm" does not return a value',
|
||||||
'No overload variant of "zip" matches argument types "Tuple[str, str, str]", "object"',
|
'No overload variant of "zip" matches argument types "Tuple[str, str, str]", "object"',
|
||||||
'note:',
|
'Incompatible types in assignment (expression has type "GetDateShowHiddenInitial", '
|
||||||
'Incompatible types in assignment (expression has type "GetDateShowHiddenInitial", variable has type "GetDate")',
|
+ 'variable has type "GetDate")',
|
||||||
re.compile(r'Incompatible types in assignment \(expression has type "[a-zA-Z]+Field", '
|
re.compile(r'Incompatible types in assignment \(expression has type "[a-zA-Z]+Field", '
|
||||||
r'base class "BaseForm" defined the type as "Dict\[str, Any\]"\)'),
|
r'base class "BaseForm" defined the type as "Dict\[str, Any\]"\)'),
|
||||||
'List or tuple expected as variable arguments',
|
'List or tuple expected as variable arguments',
|
||||||
@@ -216,13 +221,13 @@ IGNORED_ERRORS = {
|
|||||||
],
|
],
|
||||||
'lookup': [
|
'lookup': [
|
||||||
'Unexpected keyword argument "headline__startswith" for "in_bulk" of "QuerySet"',
|
'Unexpected keyword argument "headline__startswith" for "in_bulk" of "QuerySet"',
|
||||||
'note: '
|
|
||||||
],
|
],
|
||||||
'many_to_one': [
|
'many_to_one': [
|
||||||
'Incompatible type for "parent" of "Child" (got "None", expected "Union[Parent, Combinable]")'
|
'Incompatible type for "parent" of "Child" (got "None", expected "Union[Parent, Combinable]")'
|
||||||
],
|
],
|
||||||
'model_inheritance_regress': [
|
'model_inheritance_regress': [
|
||||||
'Incompatible types in assignment (expression has type "List[Supplier]", variable has type "QuerySet[Supplier]")'
|
'Incompatible types in assignment (expression has type "List[Supplier]", '
|
||||||
|
+ 'variable has type "QuerySet[Supplier]")'
|
||||||
],
|
],
|
||||||
'model_meta': [
|
'model_meta': [
|
||||||
'"object" has no attribute "items"',
|
'"object" has no attribute "items"',
|
||||||
@@ -238,10 +243,10 @@ IGNORED_ERRORS = {
|
|||||||
'Cannot assign multiple types to name "PersonTwoImages" without an explicit "Type[...]" annotation',
|
'Cannot assign multiple types to name "PersonTwoImages" without an explicit "Type[...]" annotation',
|
||||||
'Incompatible types in assignment (expression has type "Type[Person]", '
|
'Incompatible types in assignment (expression has type "Type[Person]", '
|
||||||
+ 'base class "ImageFieldTestMixin" defined the type as "Type[PersonWithHeightAndWidth]")',
|
+ 'base class "ImageFieldTestMixin" defined the type as "Type[PersonWithHeightAndWidth]")',
|
||||||
'note: "Person" defined here'
|
|
||||||
],
|
],
|
||||||
'model_formsets': [
|
'model_formsets': [
|
||||||
'Incompatible types in string interpolation (expression has type "object", placeholder has type "Union[int, float]")'
|
'Incompatible types in string interpolation (expression has type "object", '
|
||||||
|
+ 'placeholder has type "Union[int, float]")'
|
||||||
],
|
],
|
||||||
'model_formsets_regress': [
|
'model_formsets_regress': [
|
||||||
'Incompatible types in assignment (expression has type "Model", variable has type "User")'
|
'Incompatible types in assignment (expression has type "Model", variable has type "User")'
|
||||||
@@ -287,9 +292,11 @@ IGNORED_ERRORS = {
|
|||||||
'Incompatible types in assignment (expression has type "Type[Field[Any, Any]]',
|
'Incompatible types in assignment (expression has type "Type[Field[Any, Any]]',
|
||||||
'DummyArrayField',
|
'DummyArrayField',
|
||||||
'DummyJSONField',
|
'DummyJSONField',
|
||||||
'Argument "encoder" to "JSONField" has incompatible type "DjangoJSONEncoder"; expected "Optional[Type[JSONEncoder]]"',
|
'Argument "encoder" to "JSONField" has incompatible type "DjangoJSONEncoder"; '
|
||||||
|
+ 'expected "Optional[Type[JSONEncoder]]"',
|
||||||
'for model "CITestModel"',
|
'for model "CITestModel"',
|
||||||
'Incompatible type for "field" of "IntegerArrayModel" (got "None", expected "Union[Sequence[int], Combinable]")'
|
'Incompatible type for "field" of "IntegerArrayModel" (got "None", '
|
||||||
|
+ 'expected "Union[Sequence[int], Combinable]")'
|
||||||
],
|
],
|
||||||
'properties': [
|
'properties': [
|
||||||
re.compile('Unexpected attribute "(full_name|full_name_2)" for model "Person"')
|
re.compile('Unexpected attribute "(full_name|full_name_2)" for model "Person"')
|
||||||
@@ -334,11 +341,14 @@ IGNORED_ERRORS = {
|
|||||||
'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]")'
|
||||||
],
|
],
|
||||||
'test_client': [
|
'test_client': [
|
||||||
'Incompatible types in assignment (expression has type "StreamingHttpResponse", variable has type "HttpResponse")',
|
'Incompatible types in assignment (expression has type "StreamingHttpResponse", '
|
||||||
'Incompatible types in assignment (expression has type "HttpResponse", variable has type "StreamingHttpResponse")'
|
+ 'variable has type "HttpResponse")',
|
||||||
|
'Incompatible types in assignment (expression has type "HttpResponse", '
|
||||||
|
+ 'variable has type "StreamingHttpResponse")'
|
||||||
],
|
],
|
||||||
'test_client_regress': [
|
'test_client_regress': [
|
||||||
'Incompatible types in assignment (expression has type "Dict[<nothing>, <nothing>]", variable has type "SessionBase")',
|
'Incompatible types in assignment (expression has type "Dict[<nothing>, <nothing>]", '
|
||||||
|
+ 'variable has type "SessionBase")',
|
||||||
'Unsupported left operand type for + ("None")',
|
'Unsupported left operand type for + ("None")',
|
||||||
'Both left and right operands are unions'
|
'Both left and right operands are unions'
|
||||||
],
|
],
|
||||||
@@ -348,7 +358,8 @@ IGNORED_ERRORS = {
|
|||||||
'test_runner': [
|
'test_runner': [
|
||||||
'Value of type "TestSuite" is not indexable',
|
'Value of type "TestSuite" is not indexable',
|
||||||
'"TestSuite" has no attribute "_tests"',
|
'"TestSuite" has no attribute "_tests"',
|
||||||
'Argument "result" to "run" of "TestCase" has incompatible type "RemoteTestResult"; expected "Optional[TestResult]"',
|
'Argument "result" to "run" of "TestCase" has incompatible type "RemoteTestResult"; '
|
||||||
|
+ 'expected "Optional[TestResult]"',
|
||||||
'Item "TestSuite" of "Union[TestCase, TestSuite]" has no attribute "id"',
|
'Item "TestSuite" of "Union[TestCase, TestSuite]" has no attribute "id"',
|
||||||
'MockTestRunner',
|
'MockTestRunner',
|
||||||
'Incompatible types in assignment (expression has type "Tuple[Union[TestCase, TestSuite], ...]", '
|
'Incompatible types in assignment (expression has type "Tuple[Union[TestCase, TestSuite], ...]", '
|
||||||
|
|||||||
29
setup.cfg
Normal file
29
setup.cfg
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
[isort]
|
||||||
|
skip =
|
||||||
|
django-sources,
|
||||||
|
django-stubs,
|
||||||
|
test-data
|
||||||
|
include_trailing_comma = true
|
||||||
|
multi_line_output = 5
|
||||||
|
wrap_length = 120
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
exclude =
|
||||||
|
django-sources,
|
||||||
|
django-stubs,
|
||||||
|
test-data
|
||||||
|
max_line_length = 120
|
||||||
|
|
||||||
|
[tool:pytest]
|
||||||
|
testpaths = ./test-data
|
||||||
|
addopts =
|
||||||
|
--tb=native
|
||||||
|
--mypy-ini-file=./test-data/plugins.ini
|
||||||
|
-s
|
||||||
|
-v
|
||||||
|
|
||||||
|
[bdist_wheel]
|
||||||
|
universal = 1
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
license_file = LICENSE.txt
|
||||||
Reference in New Issue
Block a user