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

False positive (no-value-for-parameter) for lambda returned by a function. #2594

Closed
galv opened this issue Nov 13, 2018 · 3 comments · Fixed by pylint-dev/astroid#641
Closed
Assignees
Labels

Comments

@galv
Copy link

galv commented Nov 13, 2018

Steps to reproduce

  1. Create this file, and name it self.py:
#pylint: disable=missing-docstring

def lambda_factory():
    return lambda self: "Hello world"

class MyClass:
    f = lambda self: "Hello world"
    f2 = lambda_factory()

    def f_wrapper(self):
        return self.f()

    def f2_wrapper(self):
        return self.f2()

def test():
    obj = MyClass()
    assert obj.f2_wrapper() == obj.f_wrapper()

test()
  1. Run pylint self.py

Current behavior

************* Module self
self.py:14:15: E1120: No value for argument 'self' in lambda call (no-value-for-parameter)

------------------------------------------------------------------
Your code has been rated at 6.15/10 (previous run: 6.15/10, +0.00)

Expected behavior

There should not be any pylint error in this case. Note that the assertion succeeds in this file if you run the file.

The variables f and f2 are equivalent, and the call to self.f() correctly infers that self should be passed as the first argument. However, the call to self.f2() does not infer this. The extra level of indirection caused by lambda_factory seems to cause this problem for the static analyzer.

pylint --version output

pylint 2.1.1
astroid 2.1.0-dev
Python 3.6.7 |Anaconda, Inc.| (default, Oct 23 2018, 19:16:44) 
[GCC 7.3.0]
@mluo-cb
Copy link

mluo-cb commented Nov 13, 2018

I recommend editing the code sample for concision and clarity:

#pylint: disable=missing-docstring

def lambda_factory():
    return lambda self: "Hello world"

class MyClass:
    f = lambda self: "Hello world"
    f2 = lambda_factory()

def test():
    obj = MyClass()
    print(obj.f())
    print(obj.f2())

test()

Note that

  1. The wrapper functions are not necessary for pylint to generate the false positive.
  2. Pylint is fine with line 12, but complains on line 13, which better demonstrates that it is f2 that is the problem, not f.

@PCManticore
Copy link
Contributor

Thanks for creating an issue folks!

@hippo91 hippo91 self-assigned this Dec 22, 2018
@hippo91
Copy link
Contributor

hippo91 commented Dec 22, 2018

I'am working on this issue.
Just below a brief analysis of the problem.

The problem is that f2 is not inferred as a bound method contrary to f1.
The problem arises in the BaseInstance class of the astroid.bases module in the method _wrap_attr at line 248. The test

if attr.statement().scope() == self._proxied:

failed, preventing the return of a BoundMethod instance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment