Skip to content
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

Pylint assumes an incorrect member type ('int') #400

Closed
pylint-bot opened this issue Nov 29, 2014 · 8 comments · Fixed by pylint-dev/astroid#1151
Closed

Pylint assumes an incorrect member type ('int') #400

pylint-bot opened this issue Nov 29, 2014 · 8 comments · Fixed by pylint-dev/astroid#1151
Labels

Comments

@pylint-bot
Copy link

Originally reported by: Paul Smith (BitBucket: pdsmith, GitHub: @pdsmith?)


I'm updating from an old pylint 1.1.0 to pylint 1.4.0 (I'm using Python 2.7.8). In the new version I'm getting an incorrect error like this:

E:123,10: Instance of 'int' has no 'get_domain' member (no-member)

even though the instance does have a method of that name. It seems that the way my code assigns a value to this member (in a separate thread, asynchronously based on some XML content sent over a socket) can't be tracked by pylint and where the previous version would ignore the issue the new one appears to assume a type of 'int' and fails. Even if I invoked a garbage method the old pylint never complained: the new pylint complains for all methods, real or garbage.

I've attached a repro case.


@pylint-bot
Copy link
Author

Original comment by Claudiu Popa (BitBucket: PCManticore, GitHub: @PCManticore):


A simpler test which triggers the problem:

#!python

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

    def wait(self, timeout):
        result = self._latest
        self._latest = None
        return result

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


listener = TestListener()
broker = listener.wait(3).get_domain()

The problem is not related to multithreading or sockets or whatever, it's just that Astroid, Pylint's inference engine, passes contexts in wrong way. For instance, in peer_join Astroid will think that peer is actually 3 which will make it think that wait returns None and/or 3, then yielding the no-member warning.

@rogalski
Copy link
Contributor

Isn't it "fixed" by bf3e06f?

@PCManticore
Copy link
Contributor

No. That commit just hides the underlying problem.

@madscientist
Copy link

Just wondering if there any hope of fixing this issue? Still seeing this with Python 2.7.14 / Pylint 1.8.1 / Astroid 1.6.0.

I'm still stuck with Pylint 1.1.0 / Astroid 1.0.1, which is the last version I tried that didn't fail for me with this error, until the issue is fixed. I'm not sure what is so different about my code which causes me to get tons of these messages, but no one else seems to get them or care about this (based on lack of comments here etc. since reported 3 years ago). Is there some way I can modify my code to work around this problem?

Or does everyone just always disable E1101 everywhere?

@madscientist
Copy link

I'm happy to provide astroid hints that specify what classes are returned by certain functions. Since this is centralized in one location it would be simple for me to do so. I spent some time trying to understand how to do this, but the Astroid documentation is, to put it very kindly, lacking.

Suppose I had a method in a class that returned an object, and I wanted to tell astroid that the returned value would always be either None or an instance of another class. Can someone point out an example of how I might do that?

@PCManticore
Copy link
Contributor

Sorry for having troubles with this one @madscientist . Since we are all volunteers, we sometimes (or most of the time) lack enough resources to tackle older issues. Unless it's something that is broken for everyone (e.g a crash), these tend to not get solved too soon.

Regarding your question, currently we can't do an Either return, a la mypy. There two potential solutions:

  • using an astroid hint, rewrite the said method to basically to an if statement, as in:
def transform(node):
    n = extract_node('''
    def some_method(self):
       if some_condition:
           return None
       return SomeClass()
    ```)
   node.locals['some_method'] = n
  • or always return an instance of the said class. Depending on what you need, this mostly means that either we're creating nodes on the fly and returning them from a transform or either we have to implement an inference method.
    Reading the brain directory from astroid could be an inspiration starting point

@madscientist
Copy link

Believe me I get it, as a volunteer maintaining an open source codebase myself.

I did try to make some hay by looking at the brains examples for an hour or two but I'm just missing some fundamental knowledge and I can't seem to get oriented. I did post a stackoverflow message with info on my attempts so far: https://stackoverflow.com/questions/47988540/tell-pylint-what-the-return-type-of-a-method-is

At this point I don't even think my transform method is being invoked (I added some code in the plugin and also in the transform function to write some text to a file and while the output printed in the plugin outer scope appeared, the output printed by my transform plugin didn't appear) so I feel very lost.

@PCManticore
Copy link
Contributor

You might try with

astroid.MANAGER.register_transform(astroid.ClassDef,  _class_transform,
                                   optional_transform_predicate)

msuozzo pushed a commit to msuozzo/pylint that referenced this issue Feb 18, 2022
…dev pin (pylint-dev#400)

Expand pins on library dependencies in preparation for these dependencies taking a new major version. See googleapis/google-cloud-python#10566.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants