solve more use cases for related managers and settings

This commit is contained in:
Maxim Kurnikov
2018-12-03 01:57:46 +03:00
parent fcd659837e
commit 3676cb3ac0
9 changed files with 222 additions and 148 deletions

View File

@@ -1,12 +1,10 @@
from typing import cast, List
from typing import cast, List, Optional
from mypy.nodes import Var, Context, SymbolNode, SymbolTableNode
from mypy.plugin import ClassDefContext
from mypy.semanal import SemanticAnalyzerPass2
from mypy.types import Instance, UnionType, NoneTyp, Type
from mypy_django_plugin import helpers
def get_error_context(node: SymbolNode) -> Context:
context = Context()
@@ -18,10 +16,24 @@ def filter_out_nones(typ: UnionType) -> List[Type]:
return [item for item in typ.items if not isinstance(item, NoneTyp)]
def copy_sym_of_instance(sym: SymbolTableNode) -> SymbolTableNode:
copied = sym.copy()
copied.node.info = sym.type.type
return copied
def make_sym_copy_of_setting(sym: SymbolTableNode) -> Optional[SymbolTableNode]:
if isinstance(sym.type, Instance):
copied = sym.copy()
copied.node.info = sym.type.type
return copied
elif isinstance(sym.type, UnionType):
instances = filter_out_nones(sym.type)
if len(instances) > 1:
# plain unions not supported yet
return None
typ = instances[0]
if isinstance(typ, Instance):
copied = sym.copy()
copied.node.info = typ.type
return copied
return None
else:
return None
def add_settings_to_django_conf_object(ctx: ClassDefContext,
@@ -33,25 +45,24 @@ def add_settings_to_django_conf_object(ctx: ClassDefContext,
settings_file = api.modules[settings_module]
for name, sym in settings_file.names.items():
if name.isupper() and isinstance(sym.node, Var):
if isinstance(sym.type, Instance):
copied = sym.copy()
copied.node.info = sym.type.type
ctx.cls.info.names[name] = copied
elif isinstance(sym.type, UnionType):
instances = filter_out_nones(sym.type)
if len(instances) > 1:
# plain unions not supported yet
if sym.type is not None:
copied = make_sym_copy_of_setting(sym)
if copied is None:
continue
typ = instances[0]
if isinstance(typ, Instance):
copied = sym.copy()
copied.node.info = typ.type
ctx.cls.info.names[name] = copied
ctx.cls.info.names[name] = copied
else:
context = Context()
module, node_name = sym.node.fullname().rsplit('.', 1)
module_file = api.modules.get(module)
if module_file is None:
return None
context.set_line(sym.node)
api.msg.report(f"Need type annotation for '{sym.node.name()}'", context,
severity='error', file=module_file.path)
class DjangoConfSettingsInitializerHook(object):
def __init__(self, settings_module: str):
def __init__(self, settings_module: Optional[str]):
self.settings_module = settings_module
def __call__(self, ctx: ClassDefContext) -> None: