From 492454d860d600034bf3912502f37696d28eae0c Mon Sep 17 00:00:00 2001 From: Tommy Wu Date: Mon, 2 Aug 2021 06:32:13 +0000 Subject: [PATCH] Make the ForeiginKey detection more accurate To handle this case: the project use tastypie and django. tastypie has a `ForeignKey` field which has the same name as django's `ForeignKey`. The issue is the lint trys resolving the `ForeignKey` for the tastypie `ForeignKey` which cause import error. In this commit, add a check to ensure the current class of the `ForeignKey` is a subclass of `Model` of django. Tested manually Test case added: func_noerror_foreign_key_in_non_django_class --- .../external_tastypie_noerror_foreign_key.py | 20 +++++++++++++++++++ pylint_django/transforms/foreignkey.py | 9 +++++++++ setup.py | 2 +- 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 pylint_django/tests/input/external_tastypie_noerror_foreign_key.py diff --git a/pylint_django/tests/input/external_tastypie_noerror_foreign_key.py b/pylint_django/tests/input/external_tastypie_noerror_foreign_key.py new file mode 100644 index 00000000..bf54f520 --- /dev/null +++ b/pylint_django/tests/input/external_tastypie_noerror_foreign_key.py @@ -0,0 +1,20 @@ +""" +Checks that Pylint doesn't raise an error when a 'ForeignKey' appears in a +non-django class + +The real case is described as follow: +The project use tastypie and django. +tastypie has a `ForeignKey` field which has the same name +as django's `ForeignKey`. +The issue is the lint trys resolving the `ForeignKey` for the +tastypie `ForeignKey` which cause import error. +""" +# pylint: disable=missing-docstring +from tastypie.resources import ModelResource +from tastypie import fields +from tastypie.fields import ForeignKey + + +class MyTestResource(ModelResource): # pylint: disable=too-few-public-methods + field1 = ForeignKey('myapp.api.resource', 'xxx') + field2 = fields.ForeignKey('myapp.api.resource', 'xxx') diff --git a/pylint_django/transforms/foreignkey.py b/pylint_django/transforms/foreignkey.py index d16b47c7..27e5c89e 100644 --- a/pylint_django/transforms/foreignkey.py +++ b/pylint_django/transforms/foreignkey.py @@ -16,6 +16,15 @@ def is_foreignkey_in_class(node): if not isinstance(node.parent.parent, ClassDef): return False + # Make sure the outfit class is the subclass of django.db.models.Model + is_in_django_model_class = node_is_subclass( + node.parent.parent, + 'django.db.models.base.Model', + '.Model' + ) + if not is_in_django_model_class: + return False + if isinstance(node.func, Attribute): attr = node.func.attrname elif isinstance(node.func, nodes.Name): diff --git a/setup.py b/setup.py index a5c1483b..a93ecd26 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ ], extras_require={ 'with_django': ['Django'], - 'for_tests': ['django_tables2', 'factory-boy', 'coverage', 'pytest'], + 'for_tests': ['django_tables2', 'factory-boy', 'coverage', 'pytest', 'django-tastypie'], }, license='GPLv2', classifiers=[