Skip to content

Commit 52a2d85

Browse files
committed
Tests for all rules
1 parent a76234e commit 52a2d85

File tree

12 files changed

+308
-92
lines changed

12 files changed

+308
-92
lines changed

.pre-commit-config.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
repos:
2+
- repo: https://github.com/asottile/seed-isort-config
3+
rev: v2.2.0
4+
hooks:
5+
- id: seed-isort-config
6+
27
- repo: https://github.com/pre-commit/mirrors-isort
38
rev: v4.3.21
49
hooks:

conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import pytest
2+
23
from extra_checks.checks.self_checks import CheckConfig
34
from extra_checks.controller import Registry
45

setup.cfg

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
[metadata]
2+
name = django-extra-checks
3+
version = 0.2.0
4+
author = Konstantin Alekseev
5+
author_email = [email protected]
6+
description = Collection of useful checks for Django Checks Framework
7+
keywords = django, checks
8+
url = https://github.com/kalekseev/django-extra-checks
9+
long_description = file: README.md
10+
long_description_content_type = text/markdown
11+
classifiers =
12+
Development Status :: 4 - Beta
13+
Environment :: Web Environment
14+
Framework :: Django
15+
Framework :: Django :: 2.2
16+
Framework :: Django :: 3.0
17+
Framework :: Django :: 3.1
18+
Intended Audience :: Developers
19+
License :: OSI Approved :: BSD License
20+
Operating System :: OS Independent
21+
Programming Language :: Python
22+
Programming Language :: Python :: 3
23+
Programming Language :: Python :: 3.6
24+
Programming Language :: Python :: 3.7
25+
Programming Language :: Python :: 3.8
26+
27+
[options]
28+
package_dir=
29+
=src
30+
packages = find:
31+
install_requires = Django>=2.2
32+
python_requires = >=3.6
33+
34+
[options.packages.find]
35+
where = src
36+
37+
[options.extras_require]
38+
dev =
39+
pytest
40+
pytest-django
41+
pytest-cov
42+
Django
43+
django-stubs==1.5.0
44+
flake8
45+
flake8-bugbear
46+
pre-commit
47+
isort
48+
pdbpp
49+
tox
50+
51+
[flake8]
52+
max-line-length = 110
53+
ignore = E126,E127,E501,E731,W503
54+
55+
[isort]
56+
multi_line_output = 3
57+
include_trailing_comma = True
58+
force_grid_wrap = 0
59+
use_parentheses = True
60+
line_length = 88
61+
known_first_party = extra_checks
62+
known_third_party = django,pytest,setuptools

setup.py

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,3 @@
1-
from __future__ import absolute_import
1+
from setuptools import setup
22

3-
import io
4-
import os
5-
from glob import glob
6-
7-
from setuptools import find_packages, setup
8-
9-
10-
def read(*names, **kwargs):
11-
return io.open(
12-
os.path.join(os.path.dirname(__file__), *names),
13-
encoding=kwargs.get("encoding", "utf8"),
14-
).read()
15-
16-
17-
setup(
18-
name="django-extra-checks",
19-
version="0.1.0a0",
20-
description="Collection of useful checks for Django Checks Frameworks",
21-
long_description=read("README.md"),
22-
long_description_content_type="text/markdown",
23-
author="Konstantin Alekseev",
24-
author_email="[email protected]",
25-
url="https://github.com/kalekseev/django-extra-checks",
26-
packages=find_packages("src"),
27-
package_dir={"": "src"},
28-
py_modules=[
29-
os.path.splitext(os.path.basename(path))[0] for path in glob("src/*.py")
30-
],
31-
include_package_data=True,
32-
zip_safe=False,
33-
extras_require={
34-
"dev": [
35-
"pytest",
36-
"pytest-django",
37-
"pytest-cov",
38-
"Django",
39-
"mypy<0.780",
40-
"django-stubs==1.5.0",
41-
"flake8",
42-
"flake8-bugbear",
43-
"pre-commit",
44-
"isort",
45-
"pdbpp",
46-
"tox",
47-
]
48-
},
49-
classifiers=[
50-
"Development Status :: 4 - Beta",
51-
"Environment :: Web Environment",
52-
"Framework :: Django",
53-
"Intended Audience :: Developers",
54-
"License :: OSI Approved :: BSD License",
55-
"Operating System :: OS Independent",
56-
"Programming Language :: Python",
57-
"Programming Language :: Python :: 3",
58-
"Programming Language :: Python :: 3.6",
59-
"Programming Language :: Python :: 3.7",
60-
"Programming Language :: Python :: 3.8",
61-
],
62-
keywords=["django", "checks"],
63-
)
3+
setup()

src/extra_checks/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ class CheckId(str, enum.Enum):
1212
X053 = "field-help-text-gettext"
1313
X054 = "field-file-upload-to"
1414
X055 = "field-text-null"
15-
X056 = "field-null-boolean"
16-
X057 = "field-null-false"
17-
X058 = "field-foreign-key-index"
15+
X056 = "field-boolean-null"
16+
X057 = "field-null"
17+
X058 = "field-foreign-key-db-index"
1818

1919

2020
_IGNORED = {}

src/extra_checks/checks/base_checks.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ def is_ignored(self, obj: Any) -> bool:
3737
def message(
3838
self, message: str, hint: Optional[str] = None, obj: Any = None
3939
) -> django.core.checks.CheckMessage:
40-
return MESSAGE_MAP[self.level](message, hint=hint, obj=obj, id=self.Id.name)
40+
return MESSAGE_MAP[self.level](
41+
message + f" [{self.Id.value}]", hint=hint, obj=obj, id=self.Id.name
42+
)
4143

4244

4345
if TYPE_CHECKING:

src/extra_checks/checks/model_field_checks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ def apply(
196196
if self.when == "unique_together":
197197
if any(field.name in index for index in model._meta.unique_together):
198198
yield self.message(
199-
"ForeignKey must set `db_index` explicitly if it present in unique_together",
199+
"ForeignKey must set `db_index` explicitly if it present in unique_together.",
200200
hint="Specify `db_index` field argument.",
201201
obj=field,
202202
)

tests/example/models.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from django.contrib.sites.models import Site
22
from django.db import models
3+
from django.utils.translation import gettext_lazy
4+
5+
_ = gettext_lazy
36

47

58
class Article(models.Model):
@@ -14,3 +17,79 @@ class Meta:
1417
class Author(models.Model):
1518
first_name = models.CharField(max_length=100)
1619
last_name = models.CharField(max_length=100)
20+
21+
22+
class NestedField(models.Field):
23+
"""Resembles fields like postgres ArrayField."""
24+
25+
def __init__(self, base_field, **kwargs):
26+
self.base_field = base_field
27+
super().__init__(**kwargs)
28+
29+
30+
class ModelFieldVerboseName(models.Model):
31+
first_arg_name = models.CharField("first arg name [test]")
32+
kwarg_name = models.CharField(verbose_name="kwarg name [test]")
33+
arg_gettext = models.CharField(_("arg name [test]"))
34+
kwargs_gettext = models.CharField(verbose_name=_("kwarg name [test]"))
35+
gettext_case = models.CharField(verbose_name=_("Kwarg Name [test]"))
36+
gettext = models.CharField(verbose_name=gettext_lazy("kwarg name [test]"))
37+
name_related = models.ForeignKey(
38+
Article,
39+
on_delete=models.CASCADE,
40+
related_name="+",
41+
verbose_name="name related test [X050]",
42+
)
43+
nested_field = NestedField(
44+
models.CharField(max_length=100), verbose_name="nested field [X050]"
45+
)
46+
no_name = models.CharField()
47+
no_name_related = models.ForeignKey(
48+
Article, on_delete=models.CASCADE, related_name="+"
49+
)
50+
no_name_nested_field = NestedField(models.CharField(max_length=100))
51+
52+
53+
class ModelFieldFileUploadTo(models.Model):
54+
image = models.ImageField(upload_to="/path/to/media")
55+
file = models.FileField(upload_to="/path/to/files")
56+
image_fail = models.ImageField()
57+
file_fail = models.FileField()
58+
59+
60+
class CustomTextField(models.TextField):
61+
pass
62+
63+
64+
class ModelFieldTextNull(models.Model):
65+
text = models.TextField()
66+
chars = models.CharField()
67+
custom = CustomTextField()
68+
text_fail = models.TextField(null=True)
69+
chars_fail = models.CharField(null=True)
70+
custom_fail = CustomTextField(null=True)
71+
72+
73+
class ModelFieldNullFalse(models.Model):
74+
myfield = models.IntegerField()
75+
myfield_fail = models.IntegerField(null=False)
76+
77+
78+
class ModelFieldForeignKeyIndex(models.Model):
79+
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name="+")
80+
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="+")
81+
another_article = models.ForeignKey(
82+
Article, on_delete=models.CASCADE, related_name="+"
83+
)
84+
another_author = models.ForeignKey(
85+
Article, on_delete=models.CASCADE, related_name="+", db_index=True
86+
)
87+
filed_one = models.ForeignKey(
88+
ModelFieldTextNull, on_delete=models.CASCADE, related_name="+", db_index=False
89+
)
90+
filed_two = models.ForeignKey(
91+
ModelFieldNullFalse, on_delete=models.CASCADE, related_name="+", db_index=True
92+
)
93+
94+
class Meta:
95+
unique_together = (("article", "author"), ("field_one", "field_two"))

tests/test_model_checks.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
def test_check_model_attrs(settings, use_models, registry):
88
use_models(Article)
9-
settings.EXTRA_CHECKS = {"checks": [{"id": "model-attribute", "attrs": ["site"]}]}
9+
settings.EXTRA_CHECKS = {
10+
"checks": [{"id": model_checks.CheckModelAttribute.Id.value, "attrs": ["site"]}]
11+
}
1012
registry._register(
1113
[django.core.checks.Tags.models], model_checks.CheckModelAttribute
1214
)

0 commit comments

Comments
 (0)