pylint does not catch obvious error

1.2k views Asked by At

This is my code:

class Horse:

    def talk(self):
        print 'Hihaaa!'


class Farm:

    def __init__(self, animal):
        self.animal = animal

    def animaltalk(self):
        self.animal.sing()


def main():
    horse = Horse()
    farm = Farm(horse)
    farm.animaltalk()


main()

This is my pylint:

$ pylint --version
No config file found, using default configuration
pylint 1.4.3, 
astroid 1.3.6, common 0.63.2
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2]

This is the output of pylint:

$ pylint farm.py

************* Module farm
C:  1, 0: Missing module docstring (missing-docstring)
C:  1, 0: Missing class docstring (missing-docstring)
C:  1, 0: Old-style class defined. (old-style-class)
W:  1, 0: Class has no __init__ method (no-init)
C:  3, 4: Missing method docstring (missing-docstring)
R:  3, 4: Method could be a function (no-self-use)
R:  1, 0: Too few public methods (1/2) (too-few-public-methods)
C:  7, 0: Missing class docstring (missing-docstring)
C:  7, 0: Old-style class defined. (old-style-class)
C: 12, 4: Missing method docstring (missing-docstring)
R:  7, 0: Too few public methods (1/2) (too-few-public-methods)
C: 16, 0: Missing function docstring (missing-docstring)

I am not interested in all those warnings/messages, unless they really have to do with my problem, which is: pylint is unable to tell me that self.animal.sing() is an error (it should be self.animal.talk()).

  • Is there a way of forcing pylint to perform a deeper analysis, or is this a fundamental limitation of the Python language?

  • Or is there a better pattern to code this kind of functionality (an object collecting other pre-instantiated objects), so that pylint can perform better error-checking?

The reason why I need this is that, in complex code, big refactorings cause errors that are not caught by pylint, which means that the only way to catch them is with testing; unfortunately, I have no tests for all my code paths. A better pylint analysis would go a long way towards solving obvious problems in my code.

2

There are 2 answers

1
PCManticore On BEST ANSWER

Please report it to pylint's bug tracker: https://bitbucket.org/logilab/pylint/. That's actually a problem because in pylint, Instances don't know their arguments. This should be easily fixable.

2
Vasiliy Faronov On

Is there a way of forcing pylint to perform a deeper analysis

No.

or is this a fundamental limitation of the Python language?

Well, it’s theoretically possible to keep writing smarter and smarter analyzers. You could certainly write a Pylint plugin that would catch your particular error (but fail in other similar cases). There is PySonar2 which may or may not cover your case.

Or is there a better pattern to code this kind of functionality (an object collecting other pre-instantiated objects), so that pylint can perform better error-checking?

Good question. I find that there is often a way to tweak the code to make Pylint more useful on it. In your case, however, the best I can think of is using special subclasses of Farm, such as SingingFarm or HorseFarm, like this:

class Farm:

    def __init__(self, animal):
        self.animal = animal


class SingingFarm(Farm):

    def animalsing(self):
        self.animal.sing()

Then Pylint will complain if you call animalsing on a wrong type of Farm. Of course, this is a very limited approach that may not work for you.

Still, I believe grep is the only tool that can give you any sort of assurance when refactoring Python code. If I make my symbols unique enough (i.e. specific_term instead of value), and avoid dynamic attribute access as much as possible, at least I can count on grep to get me 99% of the way.