Skip to content

Fix False Positive on tests with a no-member Lint Error on DecimalField #455

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
pablolucas890 opened this issue Mar 18, 2025 · 0 comments

Comments

@pablolucas890
Copy link

Pylint incorrectly raises a no-member warning when accessing DecimalField attributes in Django models. Specifically, calling methods like .compare() or .adjusted() on self.decimalfield triggers this false positive, even though self.decimalfield is correctly assigned and used within the model.

1. Steps to Reproduce:

Define a Django model with a DecimalField.
Implement a method that calls .compare() or .adjusted() on self.decimalfield.
Run Pylint and observe the no-member warning.

2. Expected Behavior:

Pylint should correctly recognize DecimalField as having the expected methods when retrieved from a model instance.

3. Proposed Solution:

Ensure proper type conversion of self.decimalfield to Decimal before calling its methods.
Update Pylint rules or Django stubs to correctly handle DecimalField attributes.

4. Additional Context:

It's happened when I was running tests with pytest in pylint_django/tests/input/func_noerror_form_fields.py and pylint_django/tests/input/func_noerror_model_fields.py:

/usr/lib/python3/dist-packages/pylint/testutils/lint_module_test.py:142: AssertionError
______________________________________ test_everything[/pkgs/pylint-django/pylint-django/pylint_django/tests/input/func_noerror_model_fields] ______________________________________

test_file = FunctionalTest:/pkgs/pylint-django/pylint-django/pylint_django/tests/input/func_noerror_model_fields

    @pytest.mark.parametrize("test_file", TESTS, ids=TESTS_NAMES)
    def test_everything(test_file):
        # copied from pylint.tests.test_functional.test_functional
        lint_test = PylintDjangoLintModuleTest(test_file)
        lint_test.setUp()
>       lint_test.runTest()

pylint_django/tests/test_func.py:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pylint_django.tests.test_func.PylintDjangoLintModuleTest object at 0x7fae93561630>

    def runTest(self) -> None:
>       self._runTest()
E       AssertionError: Wrong message(s) raised for "func_noerror_model_fields.py":
E         
E         Unexpected in testdata:
E           75: no-member
E       assert Counter() == Counter({(75,...-member'): 1})
E         
E         Right contains 1 more item:
E         {(75, 'no-member'): 1}
E         
E         Full diff:
E         - Counter({
E         ?         ^...
E         
E         ...Full output truncated (4 lines hidden), use '-vv' to show

/usr/lib/python3/dist-packages/pylint/testutils/lint_module_test.py:142: AssertionError

/usr/lib/python3/dist-packages/pylint/testutils/lint_module_test.py:142: AssertionError                                                                                             
______________________________________ test_everything[/pkgs/pylint-django/pylint-django/pylint_django/tests/input/func_noerror_form_fields] _______________________________________
                                                                                                                                                                                    
test_file = FunctionalTest:/pkgs/pylint-django/pylint-django/pylint_django/tests/input/func_noerror_form_fields                                                                     
                                                                                                                                                                                    
    @pytest.mark.parametrize("test_file", TESTS, ids=TESTS_NAMES)                                                                                                                   
    def test_everything(test_file):                                                                                                                                                 
        # copied from pylint.tests.test_functional.test_functional                                                                                                                  
        lint_test = PylintDjangoLintModuleTest(test_file)                                                                                                                           
        lint_test.setUp()                                                                                                                                                           
>       lint_test.runTest()                                                                                                                                                         
                                                                                                                                                                                    
pylint_django/tests/test_func.py:104:                                                                                                                                               
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pylint_django.tests.test_func.PylintDjangoLintModuleTest object at 0x7fae91a1dc50> 

    def runTest(self) -> None:
>       self._runTest()
E       AssertionError: Wrong message(s) raised for "func_noerror_form_fields.py":
E         
E         Unexpected in testdata:
E           61: no-member
E       assert Counter() == Counter({(61,...-member'): 1})
E         
E         Right contains 1 more item:
E         {(61, 'no-member'): 1}
E         
E         Full diff:
E         - Counter({
E         ?         ^...
E         
E         ...Full output truncated (4 lines hidden), use '-vv' to show

5. Patch:

This is a patch idea to fix, maybe adding just a # pylint: disable=no-member its more appropriate:

---                                                                                                                                                                                 
 pylint_django/tests/input/func_noerror_form_fields.py  | 3 ++-                                                                                                                     
 pylint_django/tests/input/func_noerror_model_fields.py | 2 +-                                                                                                                      
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/pylint_django/tests/input/func_noerror_form_fields.py b/pylint_django/tests/input/func_noerror_form_fields.py                                                          
index dada077..65f1e95 100644                                                                                                                                                       
--- a/pylint_django/tests/input/func_noerror_form_fields.py                                                                                                                         
+++ b/pylint_django/tests/input/func_noerror_form_fields.py                                                                                                                         
@@ -6,6 +6,7 @@ methods on Django form forms.                                                                                                                                       
 from __future__ import print_function

 from datetime import date, datetime
+from decimal import Decimal                                                                                                                                                        

 from django import forms
 from django.contrib.auth.forms import UserCreationForm
@@ -58,7 +59,7 @@ class ManyFieldsForm(forms.Form):                                                                                                                                 
         print(self.datefield.isoformat())

     def decimalfield_tests(self):
-        print(self.decimalfield.adjusted())                                                                                                                                        
+        print(Decimal(str(self.decimalfield)).adjusted())                                                                                                                          

     def durationfield_tests(self):
         now = datetime.now()
diff --git a/pylint_django/tests/input/func_noerror_model_fields.py b/pylint_django/tests/input/func_noerror_model_fields.py                                                        
index c0389ff..9111f23 100644                                                                                                                                                       
--- a/pylint_django/tests/input/func_noerror_model_fields.py                                                                                                                        
+++ b/pylint_django/tests/input/func_noerror_model_fields.py                                                                                                                        
@@ -72,7 +72,7 @@ class LotsOfFieldsModel(models.Model):                                                                                                                            
         print(self.datefield.isoformat())

     def decimalfield_tests(self):
-        print(self.decimalfield.compare(Decimal("1.4")))                                                                                                                           
+        print(Decimal(str(self.decimalfield)).compare(Decimal("1.4")))                                                                                                             

     def durationfield_tests(self):
         now = datetime.now()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant