Search code examples
pythonpylint

Can an API tell Pylint not to complain in the client code?


I have some code in a reusable class that modifies some types. Here's a simplified version.

class Foo:
    def __init__(self):
        self.count = 0

    def increment(self):
        self.count += 1

# Add another method outside of the class definition.
# Pylint doesn't care about this, and rates this file 10/10.

Foo.__dict__["current_count"] = lambda self: self.count

In the real code, "current_count" is a variable, not a fixed string, which is why I didn't write:

Foo.current_count = lambda self: self.count # Cannot do in my scenario.

Now, when my clients come to use the new function, Pylint jumps up and down in horror.

import server_api

def main():
    foo_count = server_api.Foo()
    foo_count.increment()


    print foo_count.current_count()
    # Pylint complains here:
    #     E1101:  8:main: Instance of 'Foo' has no 'current_count' member
    # I don't want to have to tell pylint to disable that message in every client.

main()

Every class that uses this new function gets chastised, and I am forced to disable the message in every reference. I would RATHER put some code in the API to tell Pylint to chill when there are unknown references on this class.

Alas, the pylint documentation is... ummm... not of a quality conducive to my understanding, and I have been unable to find any suggestions there.

So boiling it down: Can I tell pylint in my API code to turn off the E1101 rule in relation to this class, whenever a client refers to it? Is there another solution?


Solution

  • Here is my solution inspired by the example in ActiveState cookbook recipe, provided in Yoni H's answer.

    To the Foo class, I added this useless __getattr__ method.

    def __getattr__(self, name):
        # This is only called when the normal mechanism fails, so in practice should never be called.
        # It is only provided to satisfy pylint that it is okay not to raise E1101 errors in the client code.
        raise AttributeError("%r instance has no attribute %r" % (self, name))
    

    This should be nigh indistinguishable from the previous version. It should not be called in the normal course of events, but it is enough to persuade pylint to remain quiet about this error.

    p.s. You are allowed to grumble that this code isn't very pretty. I share that opinion. But I think its benefits for the client outweigh its code smell.