convince mypy that user.is_staff (and friends) are booleans (#542)

closes #512

Co-authored-by: proxi <51172302+3n-k1@users.noreply.github.com>
This commit is contained in:
proxi
2020-12-16 15:28:01 -05:00
committed by GitHub
parent cfd9379b58
commit caaa23ab8f
5 changed files with 39 additions and 5 deletions

View File

@@ -1,3 +1,5 @@
ABSTRACT_USER_MODEL_FULLNAME = "django.contrib.auth.models.AbstractUser"
PERMISSION_MIXIN_CLASS_FULLNAME = "django.contrib.auth.models.PermissionsMixin"
MODEL_CLASS_FULLNAME = "django.db.models.base.Model"
FIELD_FULLNAME = "django.db.models.fields.Field"
CHAR_FIELD_FULLNAME = "django.db.models.fields.CharField"

View File

@@ -22,7 +22,7 @@ from mypy_django_plugin.django.context import DjangoContext
from mypy_django_plugin.lib import fullnames, helpers
from mypy_django_plugin.transformers import fields, forms, init_create, meta, querysets, request, settings
from mypy_django_plugin.transformers.managers import create_new_manager_class_from_from_queryset_method
from mypy_django_plugin.transformers.models import process_model_class
from mypy_django_plugin.transformers.models import process_model_class, set_auth_user_model_boolean_fields
def transform_model_class(ctx: ClassDefContext, django_context: DjangoContext) -> None:
@@ -270,8 +270,12 @@ class NewSemanalDjangoPlugin(Plugin):
return partial(settings.get_type_of_settings_attribute, django_context=self.django_context)
info = self._get_typeinfo_or_none(class_name)
if info and info.has_base(fullnames.PERMISSION_MIXIN_CLASS_FULLNAME) and attr_name == "is_superuser":
return partial(set_auth_user_model_boolean_fields, django_context=self.django_context)
if info and info.has_base(fullnames.HTTPREQUEST_CLASS_FULLNAME) and attr_name == "user":
return partial(request.set_auth_user_model_as_type_for_request_user, django_context=self.django_context)
if info and info.has_base(fullnames.ABSTRACT_USER_MODEL_FULLNAME) and attr_name in ("is_staff", "is_active"):
return partial(set_auth_user_model_boolean_fields, django_context=self.django_context)
return None
def get_dynamic_class_hook(self, fullname: str) -> Optional[Callable[[DynamicClassDefContext], None]]:

View File

@@ -5,7 +5,7 @@ from django.db.models.fields import DateField, DateTimeField
from django.db.models.fields.related import ForeignKey
from django.db.models.fields.reverse_related import ManyToManyRel, ManyToOneRel, OneToOneRel
from mypy.nodes import ARG_STAR2, Argument, Context, FuncDef, TypeInfo, Var
from mypy.plugin import ClassDefContext
from mypy.plugin import AttributeContext, ClassDefContext
from mypy.plugins import common
from mypy.semanal import SemanticAnalyzer
from mypy.types import AnyType, Instance
@@ -355,3 +355,9 @@ def process_model_class(ctx: ClassDefContext, django_context: DjangoContext) ->
except helpers.IncompleteDefnException:
if not ctx.api.final_iteration:
ctx.api.defer()
def set_auth_user_model_boolean_fields(ctx: AttributeContext, django_context: DjangoContext) -> MypyType:
boolinfo = helpers.lookup_class_typeinfo(helpers.get_typechecker_api(ctx), bool)
assert boolinfo is not None
return Instance(boolinfo, [])