Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tell pylint what the return type of a method is

Tags:

python

pylint

To give details: this is a constrained environment with Python 2.7.14, Pylint 1.8.1, and Astroid 1.6.0 and various other modules, but I can't easily install new modules such as mypy (not even with virtualenv) or make major changes to the codebase.

Due to https://github.com/PyCQA/pylint/issues/400 I'm getting errors from pylint on some of my code. I've worked around this issue in a hacky way (by removing the integer argument to the wait() method) and now I don't get errors, but no checking is done (pylint can't determine what the type of the variable is at all).

What I'd really like to do is tell pylint what the return type is. I've tried reading the Astroid docs, perusing the various astroid/brains files, and looking at other SO questions and answers such as Set multiple inferred types based on arguments for pylint plugin and pylint, coroutines, decorators and type inferencing but I guess I'm just not getting it. I have added my own load-plugins and I know it's loaded during pylint (because it had syntax errors at first :)). But I'm just not sure what it needs to do.

Suppose I had this code:

class Peer(object):
    def get_domain(self):
        return "foo"

class TestListener(object):
    def __init__(self):
        self._latest = None

    def get(self, timeout):
        # tricks here
        return self._latest

    def peer_joined(self, peer):
        self._latest = peer

peer = TestListener().get(3)
print(peer.get_domain())
print(peer.get_foo())

During # tricks here we are really waiting on a threading.Event() during which another thread will invoke peer_joined() and pass an object of type Peer(), but pylint doesn't grok this.

What I'd like to do is annotate the TestListener.get() method to tell pylint that it will return a Peer object, so that pylint will catch the error in the second print call.

I've tried this but clearly I'm missing something fundamental, since it appears my transform method is never even invoked (if I put a bogus method call there no error is printed):

from astroid import MANAGER, register_module_extender
from astroid.builder import AstroidBuilder

def TestListener_transform():
    return AstroidBuilder(MANAGER).string_build('''
class TestListener(object):
    def get(self, timeout):
        return Peer()
''')

register_module_extender(MANAGER, 'TestListener', TestListener_transform)

# for pylint load-plugins
def register(linter):
    pass
like image 467
MadScientist Avatar asked Nov 17 '25 04:11

MadScientist


1 Answers

def get(self, timeout):
    """
    :param timeout: How many seconds to wait
    :type timeout: int
    :rtype: threading.Event
    """
    # tricks here
    return self._latest

This is a reStructuredText format for writing a python docstring (a multiline string that appear right after function definition. You can document there all parameter types, and what the function return along with their datatypes.

pylint can parse that docstring to figure out the datatype of that function's return value.

This stackoverflow answer has more comprehensive explanation What is the standard Python docstring format?

like image 152
Ramast Avatar answered Nov 18 '25 18:11

Ramast