Skip to content

Commit 655ebf2

Browse files
committed
Supress some protected-access warnings when django-simple-history is installed.
django-simple-hisory is a fairly popular [1] package for keeping track of changes in django objects. Setting the `_change_reason` property of an object is the officially documented way to provide a value for the `history_change_reason` field of historical objects [2]. When django-simple-hisory is installed, protected-access warnings for setting `_change_reason` is most likely a false positive, and should be supressed. Because of inherent limitations of pylint, this may lead to some false negatives if `_change_reason` is used elsewhere. [1] https://pypistats.org/packages/django-simple-history [2] https://django-simple-history.readthedocs.io/en/latest/historical_model.html#change-reason
1 parent 955f779 commit 655ebf2

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

Diff for: pylint_django/augmentations/__init__.py

+26
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from astroid.nodes.scoped_nodes import Module
1010
from astroid.objects import Super
1111
from django import VERSION as django_version
12+
from django.conf import settings
1213
from django.utils import termcolors
1314
from django.views.generic.base import ContextMixin, RedirectView, View
1415
from django.views.generic.dates import DateMixin, DayMixin, MonthMixin, WeekMixin, YearMixin
@@ -752,6 +753,23 @@ def allow_meta_protected_access(node):
752753
return False
753754

754755

756+
def allow_simple_history_protected_access(assign_node):
757+
# NOTE: Only consider the first assignment target, mirroring current pylint behavior.
758+
# See pylint ClassChecker::visit_assign().
759+
# Because the type of assign_target typically cannot be inferred, this will suppress
760+
# the warning even in assignments on objects not related to simple_history.
761+
assign_target = assign_node.targets[0]
762+
assign_target_attrname = getattr(assign_target, "attrname", None)
763+
764+
if assign_target_attrname is None or assign_target_attrname not in ("_change_reason",):
765+
return False
766+
767+
if "simple_history" not in settings.INSTALLED_APPS:
768+
return False
769+
770+
return True
771+
772+
755773
class IsClass: # pylint: disable=too-few-public-methods
756774
def __init__(self, class_name):
757775
self.class_name = class_name
@@ -968,6 +986,14 @@ def apply_augmentations(linter):
968986
is_model_mpttmeta_subclass,
969987
)
970988

989+
# django-simple-history
990+
suppress_message(
991+
linter,
992+
ClassChecker.visit_assign,
993+
"protected-access",
994+
allow_simple_history_protected_access,
995+
)
996+
971997
# factory_boy's DjangoModelFactory
972998
suppress_message(linter, TypeChecker.visit_attribute, "no-member", is_model_factory)
973999
suppress_message(

0 commit comments

Comments
 (0)