Merge pull request #601 from ProtixIT/mypy-in-ci

Enable static type checks using mypy in CI
This commit is contained in:
Jelmer 2024-04-10 08:33:05 +02:00 committed by GitHub
commit 0fcfc113af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 54 additions and 18 deletions

View file

@ -7,6 +7,6 @@ try:
__version__ = importlib.metadata.version('django-model-utils')
except importlib.metadata.PackageNotFoundError: # pragma: no cover
# package is not installed
__version__ = None
__version__ = None # type: ignore[assignment]
__all__ = ("Choices", "FieldTracker", "ModelTracker")

16
mypy.ini Normal file
View file

@ -0,0 +1,16 @@
[mypy]
implicit_reexport=False
pretty=True
show_error_codes=True
strict_equality=True
warn_redundant_casts=True
warn_unreachable=True
warn_unused_ignores=True
mypy_path = $MYPY_CONFIG_FILE_DIR
plugins =
mypy_django_plugin.main
[mypy.plugins.django-stubs]
django_settings_module = "tests.settings"

2
requirements-mypy.txt Normal file
View file

@ -0,0 +1,2 @@
mypy==1.9.0
django-stubs==4.2.7

View file

@ -1,3 +1,7 @@
from __future__ import annotations
from typing import ClassVar
from django.db import models
from django.db.models import Manager
from django.db.models.query_utils import DeferredAttribute
@ -32,7 +36,7 @@ class InheritanceManagerTestParent(models.Model):
related_self = models.OneToOneField(
"self", related_name="imtests_self", null=True,
on_delete=models.CASCADE)
objects = InheritanceManager()
objects: ClassVar[InheritanceManager[InheritanceManagerTestParent]] = InheritanceManager()
def __str__(self):
return "{}({})".format(
@ -44,7 +48,7 @@ class InheritanceManagerTestParent(models.Model):
class InheritanceManagerTestChild1(InheritanceManagerTestParent):
non_related_field_using_descriptor_2 = models.FileField(upload_to="test")
normal_field_2 = models.TextField()
objects = InheritanceManager()
objects: ClassVar[InheritanceManager[InheritanceManagerTestParent]] = InheritanceManager()
class InheritanceManagerTestGrandChild1(InheritanceManagerTestChild1):
@ -172,8 +176,8 @@ class Post(models.Model):
order = models.IntegerField()
objects = models.Manager()
public = QueryManager(published=True)
public_confirmed = QueryManager(
public: ClassVar[QueryManager[Post]] = QueryManager(published=True)
public_confirmed: ClassVar[QueryManager[Post]] = QueryManager(
models.Q(published=True) & models.Q(confirmed=True))
public_reversed = QueryManager(published=True).order_by("-order")
@ -194,7 +198,7 @@ class SplitFieldAbstractParent(models.Model):
class AbstractTracked(models.Model):
number = 1
number: models.IntegerField
class Meta:
abstract = True
@ -340,13 +344,13 @@ class SoftDeletable(SoftDeletableModel):
"""
name = models.CharField(max_length=20)
all_objects = models.Manager()
all_objects: ClassVar[Manager[SoftDeletable]] = models.Manager()
class CustomSoftDelete(SoftDeletableModel):
is_read = models.BooleanField(default=False)
objects = CustomSoftDeleteManager()
objects: ClassVar[CustomSoftDeleteManager[SoftDeletableModel]] = CustomSoftDeleteManager()
class StringyDescriptor:
@ -390,7 +394,7 @@ class ModelWithCustomDescriptor(models.Model):
class BoxJoinModel(models.Model):
name = models.CharField(max_length=32)
objects = JoinManager()
objects: ClassVar[JoinManager[BoxJoinModel]] = JoinManager()
class JoinItemForeignKey(models.Model):
@ -400,7 +404,7 @@ class JoinItemForeignKey(models.Model):
null=True,
on_delete=models.CASCADE
)
objects = JoinManager()
objects: ClassVar[JoinManager[JoinItemForeignKey]] = JoinManager()
class CustomUUIDModel(UUIDModel):

View file

@ -19,7 +19,7 @@ else:
"USER": os.environ.get("POSTGRES_USER", 'postgres'),
"PASSWORD": os.environ.get("POSTGRES_PASSWORD", ""),
"HOST": os.environ.get("POSTGRES_HOST", "localhost"),
"PORT": os.environ.get("POSTGRES_PORT", 5432)
"PORT": os.environ.get("POSTGRES_PORT", "5432")
},
}
SECRET_KEY = 'dummy'

View file

@ -1,7 +1,10 @@
from __future__ import annotations
from unittest import skip
from django.core.cache import cache
from django.core.exceptions import FieldError
from django.db import models
from django.db.models.fields.files import FieldFile
from django.test import TestCase
@ -73,7 +76,7 @@ class FieldTrackerCommonTests:
class FieldTrackerTests(FieldTrackerTestCase, FieldTrackerCommonTests):
tracked_class = Tracked
tracked_class: type[models.Model] = Tracked
def setUp(self):
self.instance = self.tracked_class()
@ -280,7 +283,7 @@ class FieldTrackerMultipleInstancesTests(TestCase):
class FieldTrackedModelCustomTests(FieldTrackerTestCase,
FieldTrackerCommonTests):
tracked_class = TrackedNotDefault
tracked_class: type[models.Model] = TrackedNotDefault
def setUp(self):
self.instance = self.tracked_class()
@ -411,7 +414,7 @@ class FieldTrackedModelAttributeTests(FieldTrackerTestCase):
class FieldTrackedModelMultiTests(FieldTrackerTestCase,
FieldTrackerCommonTests):
tracked_class = TrackedMultiple
tracked_class: type[models.Model] = TrackedMultiple
def setUp(self):
self.instance = self.tracked_class()
@ -502,8 +505,8 @@ class FieldTrackedModelMultiTests(FieldTrackerTestCase,
class FieldTrackerForeignKeyTests(FieldTrackerTestCase):
fk_class = Tracked
tracked_class = TrackedFK
fk_class: type[models.Model] = Tracked
tracked_class: type[models.Model] = TrackedFK
def setUp(self):
self.old_fk = self.fk_class.objects.create(number=8)
@ -729,7 +732,7 @@ class FieldTrackerFileFieldTests(FieldTrackerTestCase):
class ModelTrackerTests(FieldTrackerTests):
tracked_class = ModelTracked
tracked_class: type[models.Model] = ModelTracked
def test_cache_compatible(self):
cache.set('key', self.instance)

13
tox.ini
View file

@ -8,11 +8,12 @@ envlist =
py{310,311,312}-dj{main}
flake8
isort
mypy
[gh-actions]
python =
3.7: py37
3.8: py38, flake8, isort
3.8: py38, flake8, isort, mypy
3.9: py39
3.10: py310
3.11: py311
@ -63,3 +64,13 @@ deps = isort
commands =
isort model_utils tests setup.py --check-only --diff
skip_install = True
[testenv:mypy]
basepython = python3.8
deps =
time-machine==2.8.2
-r requirements-mypy.txt
set_env =
SQLITE=1
commands =
mypy model_utils tests