make mypy.checker import locally to prevent import cycles

This commit is contained in:
Maxim Kurnikov
2019-04-01 19:39:50 +03:00
parent 304cb19de6
commit 28a3f126ee
2 changed files with 15 additions and 7 deletions

View File

@@ -2,7 +2,6 @@ import typing
from collections import OrderedDict
from typing import Dict, Optional, cast
from mypy.checker import TypeChecker, gen_unique_name
from mypy.mro import calculate_mro
from mypy.nodes import (
AssignmentStmt, ClassDef, Expression, ImportedName, Lvalue, MypyFile, NameExpr, SymbolNode, TypeInfo,
@@ -12,6 +11,9 @@ from mypy.types import (
AnyType, Instance, NoneTyp, Type, TypeOfAny, TypeVarType, UnionType,
TupleType, TypedDictType)
if typing.TYPE_CHECKING:
from mypy.checker import TypeChecker
MODEL_CLASS_FULLNAME = 'django.db.models.base.Model'
FIELD_FULLNAME = 'django.db.models.fields.Field'
CHAR_FIELD_FULLNAME = 'django.db.models.fields.CharField'
@@ -165,7 +167,7 @@ def get_argument_type_by_name(ctx: typing.Union[FunctionContext, MethodContext],
return arg_types[0]
def get_setting_expr(api: TypeChecker, setting_name: str) -> Optional[Expression]:
def get_setting_expr(api: 'TypeChecker', setting_name: str) -> Optional[Expression]:
try:
settings_sym = api.modules['django.conf'].names['settings']
except KeyError:
@@ -314,11 +316,12 @@ def is_foreign_key(t: Type) -> bool:
return has_any_of_bases(t.type, (FOREIGN_KEY_FULLNAME, ONETOONE_FIELD_FULLNAME))
def build_class_with_annotated_fields(api: TypeChecker, base: Type, fields: 'OrderedDict[str, Type]',
def build_class_with_annotated_fields(api: 'TypeChecker', base: Type, fields: 'OrderedDict[str, Type]',
name: str) -> Instance:
"""Build an Instance with `name` that contains the specified `fields` as attributes and extends `base`."""
# Credit: This code is largely copied/modified from TypeChecker.intersect_instance_callable and
# NamedTupleAnalyzer.build_namedtuple_typeinfo
from mypy.checker import gen_unique_name
cur_module = cast(MypyFile, api.scope.stack[0])
gen_name = gen_unique_name(name, cur_module.names)
@@ -348,7 +351,7 @@ def build_class_with_annotated_fields(api: TypeChecker, base: Type, fields: 'Ord
return Instance(info, [])
def make_named_tuple(api: TypeChecker, fields: 'OrderedDict[str, Type]', name: str) -> Type:
def make_named_tuple(api: 'TypeChecker', fields: 'OrderedDict[str, Type]', name: str) -> Type:
if not fields:
# No fields specified, so fallback to a subclass of NamedTuple that allows
# __getattr__ / __setattr__ for any attribute name.
@@ -363,13 +366,13 @@ def make_named_tuple(api: TypeChecker, fields: 'OrderedDict[str, Type]', name: s
return TupleType(list(fields.values()), fallback=fallback)
def make_typeddict(api: TypeChecker, fields: 'OrderedDict[str, Type]', required_keys: typing.Set[str]) -> Type:
def make_typeddict(api: 'TypeChecker', fields: 'OrderedDict[str, Type]', required_keys: typing.Set[str]) -> Type:
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 make_tuple(api: TypeChecker, fields: typing.List[Type]) -> Type:
def make_tuple(api: 'TypeChecker', fields: typing.List[Type]) -> Type:
implicit_any = AnyType(TypeOfAny.special_form)
fallback = api.named_generic_type('builtins.tuple', [implicit_any])
return TupleType(fields, fallback=fallback)

View File

@@ -2,7 +2,6 @@ import os
from functools import partial
from typing import Callable, Dict, Optional, Union, cast
from mypy.checker import TypeChecker
from mypy.nodes import MemberExpr, NameExpr, TypeInfo
from mypy.options import Options
from mypy.plugin import (
@@ -55,6 +54,8 @@ def transform_form_class(ctx: ClassDefContext) -> None:
def determine_proper_manager_type(ctx: FunctionContext) -> Type:
from mypy.checker import TypeChecker
api = cast(TypeChecker, ctx.api)
ret = ctx.default_return_type
if not api.tscope.classes:
@@ -104,6 +105,8 @@ def set_first_generic_param_as_default_for_second(fullname: str, ctx: AnalyzeTyp
def return_user_model_hook(ctx: FunctionContext) -> Type:
from mypy.checker import TypeChecker
api = cast(TypeChecker, ctx.api)
setting_expr = helpers.get_setting_expr(api, 'AUTH_USER_MODEL')
if setting_expr is None:
@@ -183,6 +186,8 @@ class ExtractSettingType:
self.module_fullname = module_fullname
def __call__(self, ctx: AttributeContext) -> Type:
from mypy.checker import TypeChecker
api = cast(TypeChecker, ctx.api)
original_module = api.modules.get(self.module_fullname)
if original_module is None: