remove some asserts that could be validly triggered

This commit is contained in:
Maxim Kurnikov
2019-07-25 19:53:12 +03:00
parent 409c01eb24
commit 62dac1d468
10 changed files with 77 additions and 35 deletions

View File

@@ -1,4 +1 @@
[mypy]
[mypy-mypy_django_plugin.monkeypatch.*]
ignore_errors = True

View File

@@ -1,20 +1,21 @@
import os
from collections import defaultdict
from contextlib import contextmanager
from typing import Dict, Iterator, List, Optional, TYPE_CHECKING, Tuple, Type
from typing import TYPE_CHECKING, Dict, Iterator, List, Optional, Tuple, Type
from django.contrib.postgres.fields import ArrayField
from django.core.exceptions import FieldError
from django.db.models.base import Model
from django.db.models.fields import AutoField, CharField, Field
from django.db.models.fields.related import ForeignKey, RelatedField
from django.db.models.fields.reverse_related import ForeignObjectRel
from django.db.models.sql.query import Query
from django.utils.functional import cached_property
from mypy.checker import TypeChecker
from mypy.nodes import TypeInfo
from mypy.types import AnyType, Instance, Type as MypyType, TypeOfAny
from mypy.types import AnyType, Instance
from mypy.types import Type as MypyType
from mypy.types import TypeOfAny
from django.contrib.postgres.fields import ArrayField
from django.db.models.fields import AutoField, CharField, Field
from mypy_django_plugin.lib import helpers
if TYPE_CHECKING:
@@ -104,7 +105,8 @@ class DjangoFieldsContext:
def get_field_get_type(self, api: TypeChecker, field: Field, *, method: str) -> MypyType:
""" Get a type of __get__ for this specific Django field. """
field_info = helpers.lookup_class_typeinfo(api, field.__class__)
assert isinstance(field_info, TypeInfo)
if field_info is None:
return AnyType(TypeOfAny.unannotated)
is_nullable = self.get_field_nullability(field, method)
if isinstance(field, RelatedField):
@@ -113,7 +115,8 @@ class DjangoFieldsContext:
return self.get_field_get_type(api, primary_key_field, method=method)
model_info = helpers.lookup_class_typeinfo(api, field.related_model)
assert isinstance(model_info, TypeInfo)
if model_info is None:
return AnyType(TypeOfAny.unannotated)
return Instance(model_info, [])
else:
@@ -215,14 +218,19 @@ class DjangoContext:
if isinstance(field, ForeignKey):
field_name = field.name
foreign_key_info = helpers.lookup_class_typeinfo(api, field.__class__)
assert isinstance(foreign_key_info, TypeInfo)
if foreign_key_info is None:
# maybe there's no type annotation for the field
expected_types[field_name] = AnyType(TypeOfAny.unannotated)
continue
related_model = field.related_model
if related_model._meta.proxy_for_model:
related_model = field.related_model._meta.proxy_for_model
related_model_info = helpers.lookup_class_typeinfo(api, related_model)
assert isinstance(related_model_info, TypeInfo)
if related_model_info is None:
expected_types[field_name] = AnyType(TypeOfAny.unannotated)
continue
is_nullable = self.fields_context.get_field_nullability(field, method)
foreign_key_set_type = helpers.get_private_descriptor_type(foreign_key_info,

View File

@@ -1,13 +1,19 @@
from collections import OrderedDict
from typing import Any, Dict, List, Optional, Set, TYPE_CHECKING, Union, cast
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Union, cast
from mypy import checker
from mypy.checker import TypeChecker
from mypy.mro import calculate_mro
from mypy.nodes import (Block, ClassDef, Expression, GDEF, MDEF, MemberExpr, MypyFile, NameExpr, StrExpr, SymbolNode,
SymbolTable, SymbolTableNode, TypeInfo, Var)
from mypy.plugin import AttributeContext, CheckerPluginInterface, FunctionContext, MethodContext
from mypy.types import AnyType, Instance, NoneTyp, TupleType, Type as MypyType, TypeOfAny, TypedDictType, UnionType
from mypy.nodes import (
GDEF, MDEF, Block, ClassDef, Expression, MemberExpr, MypyFile, NameExpr, StrExpr, SymbolNode, SymbolTable,
SymbolTableNode, TypeInfo, Var,
)
from mypy.plugin import (
AttributeContext, CheckerPluginInterface, FunctionContext, MethodContext,
)
from mypy.types import AnyType, Instance, NoneTyp, TupleType
from mypy.types import Type as MypyType
from mypy.types import TypedDictType, TypeOfAny, UnionType
if TYPE_CHECKING:
from mypy_django_plugin.django.context import DjangoContext

View File

@@ -6,7 +6,9 @@ from django.db.models.fields.related import RelatedField
from mypy.errors import Errors
from mypy.nodes import MypyFile, TypeInfo
from mypy.options import Options
from mypy.plugin import AnalyzeTypeContext, AttributeContext, ClassDefContext, FunctionContext, MethodContext, Plugin
from mypy.plugin import (
AnalyzeTypeContext, AttributeContext, ClassDefContext, FunctionContext, MethodContext, Plugin,
)
from mypy.types import Type as MypyType
from mypy_django_plugin.django.context import DjangoContext

View File

@@ -2,7 +2,7 @@ from typing import Optional, Tuple, cast
from django.db.models.fields import Field
from django.db.models.fields.related import RelatedField
from mypy.nodes import AssignmentStmt, TypeInfo, NameExpr
from mypy.nodes import AssignmentStmt, NameExpr, TypeInfo
from mypy.plugin import FunctionContext
from mypy.types import AnyType, Instance
from mypy.types import Type as MypyType
@@ -22,7 +22,8 @@ def _get_current_field_from_assignment(ctx: FunctionContext, django_context: Dja
for stmt in outer_model_info.defn.defs.body:
if isinstance(stmt, AssignmentStmt):
if stmt.rvalue == ctx.context:
assert isinstance(stmt.lvalues[0], NameExpr)
if not isinstance(stmt.lvalues[0], NameExpr):
return None
field_name = stmt.lvalues[0].name
break
if field_name is None:
@@ -50,16 +51,24 @@ def fill_descriptor_types_for_related_field(ctx: FunctionContext, django_context
typechecker_api = helpers.get_typechecker_api(ctx)
related_model_info = helpers.lookup_class_typeinfo(typechecker_api, related_model)
assert isinstance(related_model_info, TypeInfo)
if related_model_info is None:
# maybe no type stub
related_model_type = AnyType(TypeOfAny.unannotated)
else:
related_model_type = Instance(related_model_info, []) # type: ignore
related_model_to_set_info = helpers.lookup_class_typeinfo(typechecker_api, related_model_to_set)
assert isinstance(related_model_to_set_info, TypeInfo)
if related_model_to_set_info is None:
# maybe no type stub
related_model_to_set_type = AnyType(TypeOfAny.unannotated)
else:
related_model_to_set_type = Instance(related_model_to_set_info, []) # type: ignore
default_related_field_type = set_descriptor_types_for_field(ctx)
# replace Any with referred_to_type
args = [
helpers.convert_any_to_type(default_related_field_type.args[0], Instance(related_model_to_set_info, [])),
helpers.convert_any_to_type(default_related_field_type.args[1], Instance(related_model_info, [])),
helpers.convert_any_to_type(default_related_field_type.args[0], related_model_to_set_type),
helpers.convert_any_to_type(default_related_field_type.args[1], related_model_type),
]
return helpers.reparametrize_instance(default_related_field_type, new_args=args)

View File

@@ -2,7 +2,8 @@ from typing import List, Tuple, Type, Union
from django.db.models.base import Model
from mypy.plugin import FunctionContext, MethodContext
from mypy.types import Instance, Type as MypyType
from mypy.types import Instance
from mypy.types import Type as MypyType
from mypy_django_plugin.django.context import DjangoContext
from mypy_django_plugin.lib import helpers

View File

@@ -1,5 +1,4 @@
from django.core.exceptions import FieldDoesNotExist
from mypy.nodes import TypeInfo
from mypy.plugin import MethodContext
from mypy.types import AnyType, Instance
from mypy.types import Type as MypyType
@@ -12,7 +11,8 @@ from mypy_django_plugin.lib import fullnames, helpers
def _get_field_instance(ctx: MethodContext, field_fullname: str) -> MypyType:
field_info = helpers.lookup_fully_qualified_typeinfo(helpers.get_typechecker_api(ctx),
field_fullname)
assert isinstance(field_info, TypeInfo)
if field_info is None:
return AnyType(TypeOfAny.unannotated)
return Instance(field_info, [AnyType(TypeOfAny.explicit), AnyType(TypeOfAny.explicit)])

View File

@@ -5,8 +5,10 @@ from django.core.exceptions import FieldError
from django.db.models.base import Model
from mypy.newsemanal.typeanal import TypeAnalyser
from mypy.nodes import Expression, NameExpr, TypeInfo
from mypy.plugin import FunctionContext, MethodContext, AnalyzeTypeContext
from mypy.types import AnyType, Instance, Type as MypyType, TypeOfAny
from mypy.plugin import AnalyzeTypeContext, FunctionContext, MethodContext
from mypy.types import AnyType, Instance
from mypy.types import Type as MypyType
from mypy.types import TypeOfAny
from mypy_django_plugin.django.context import DjangoContext
from mypy_django_plugin.lib import fullnames, helpers

View File

@@ -1,6 +1,8 @@
from mypy.nodes import MemberExpr, TypeInfo
from mypy.nodes import MemberExpr
from mypy.plugin import AttributeContext, FunctionContext
from mypy.types import Instance, Type as MypyType, TypeType
from mypy.types import AnyType, Instance
from mypy.types import Type as MypyType
from mypy.types import TypeOfAny, TypeType
from mypy_django_plugin.django.context import DjangoContext
from mypy_django_plugin.lib import helpers
@@ -11,9 +13,10 @@ def get_user_model_hook(ctx: FunctionContext, django_context: DjangoContext) ->
model_cls = django_context.apps_registry.get_model(auth_user_model)
model_cls_fullname = helpers.get_class_fullname(model_cls)
model_info = helpers.lookup_fully_qualified_generic(model_cls_fullname,
helpers.get_typechecker_api(ctx).modules)
assert isinstance(model_info, TypeInfo)
model_info = helpers.lookup_fully_qualified_typeinfo(helpers.get_typechecker_api(ctx),
model_cls_fullname)
if model_info is None:
return AnyType(TypeOfAny.unannotated)
return TypeType(Instance(model_info, []))

View File

@@ -33,4 +33,18 @@
reveal_type(settings.NOT_EXISTING)
out: |
main:2: note: Revealed type is 'Any'
main:2: error: 'Settings' object has no attribute 'NOT_EXISTING'
main:2: error: 'Settings' object has no attribute 'NOT_EXISTING'
- case: override_default_setting_with_different_type_in_the_different_module
custom_settings: |
from settings.basic_settings import *
main: |
from django.conf import settings
reveal_type(settings.MEDIA_ROOT) # N: Revealed type is 'pathlib.Path'
reveal_type(settings.MEDIA_ROOT / 'part') # N: Revealed type is 'pathlib.Path*'
files:
- path: settings/__init__.py
- path: settings/basic_settings.py
content: |
from pathlib import Path
MEDIA_ROOT = Path()