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

typing.NamedTuple false positive no-member for methods #1628

Closed
quodlibetor opened this issue Aug 16, 2017 · 23 comments · Fixed by pylint-dev/astroid#673
Closed

typing.NamedTuple false positive no-member for methods #1628

quodlibetor opened this issue Aug 16, 2017 · 23 comments · Fixed by pylint-dev/astroid#673
Labels
Bug 🪲 Needs astroid Brain 🧠 Needs a brain tip in astroid (then an astroid upgrade)

Comments

@quodlibetor
Copy link
Contributor

Steps to reproduce

This is only legal in python 3.6.1 and higher:

$ cat nt.py
from typing import NamedTuple

class Example(NamedTuple):
    mything: int
    def as_string(self):
        return '%s' % self.mything

ex = Example(1)
print(ex.as_string())  # python happy, pylint error
$ python ./nt.py
1

$ pylint nt.py --disable=missing-docstring
No config file found, using default configuration
************* Module nt
R:  3, 0: Too few public methods (1/2) (too-few-public-methods)
E: 10, 6: Instance of 'Example' has no 'as_string' member (no-member)

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

$ pylint --version
No config file found, using default configuration
pylint 1.7.2,
astroid 1.5.3
Python 3.6.2 (default, Aug 11 2017, 09:37:39)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)]

In python 3.6.0 though you get the following error:

$ ~/.pyenv/versions/3.6.0/bin/python nt.py
Traceback (most recent call last):
  File "nt.py", line 10, in <module>
    print(ex.as_string())  # python happy, pylint error
AttributeError: 'Example' object has no attribute 'as_string'

Expected behavior

I would expect the existing member to not error.

I would also kind of not expect Too few public methods on subclasses of typing.NamedTuple, but I have so many data objects that I just have that disabled globally anyway.

@tarcisioe
Copy link

tarcisioe commented Aug 24, 2017

I have encountered the same problem. Unsure if it is a bug or if Pylint expects NamedTuple to be used as in 3.6.0 (methods could not be defined on NamedTuples then).

A (slightly annoying) workaround to make pylint happy is to have an intermediate data class:

class ExampleData(NamedTuple):
    mything: int

class Example(ExampleData):
    def as_string(self):
        return f'{self.mything}'

But definitely not ideal.

@k4nar
Copy link

k4nar commented Sep 11, 2017

I've stumbled upon the same issue. Note that creating the namedtuple using collections.namedtuple does not trigger it. But who wants to live in the past ? :)

@markedwards
Copy link

Also hitting this. Is there any plan to fix this issue?

@PCManticore
Copy link
Contributor

There is no plan to fix this per se. As with every issue, we'll get to it once we have time on our plate, there are hundreds of issues that needs a limited attention in one way or another.
Regarding the issue itself, it stems from the lossy implementation of typing.NamedTuple in astroid: https://github.com/PyCQA/astroid/blob/18583c261acf67a5d301dd29a58a852706a724e6/astroid/brain/brain_typing.py#L18. Anyone curious enough for a fix could check there why exactly we don't correctly infer the presence of as_string.

@PCManticore
Copy link
Contributor

This is fixed in astroid's master. Please give it a go and let me know how it works!

@thomassajot
Copy link

Hello this bug still occurs with the latest versions available:

Name: pylint
Version: 1.9.2
Summary: python code static checker
Home-page: https://github.com/PyCQA/pylint
Author: Python Code Quality Authority
Author-email: code-quality@python.org
License: GPL
Location: /.../venv/lib/python3.6/site-packages
Requires: mccabe, astroid, isort, six
Required-by:

Name: astroid
Version: 1.6.5
Summary: A abstract syntax tree for Python with inference support.
Home-page: https://github.com/PyCQA/astroid
Author: Python Code Quality Authority
Author-email: code-quality@python.org
License: LGPL
Location: /.../venv/lib/python3.6/site-packages
Requires: wrapt, lazy-object-proxy, six
Required-by: pylint

@PCManticore
Copy link
Contributor

The fix wasn't backported to 1.9 branch, the only way to get it is to use the pre-release for 2.0 with pip install pylint astroid -U --pre.

@thomassajot
Copy link

Awesome news. Thank you for the quick response.

nickdrozd pushed a commit to nickdrozd/astroid that referenced this issue Jul 7, 2018
typing.Namedtuple are collections.namedtuple in disguise. We do quite a lot of
work around understanding namedtuples, but we weren't doing the same for typing.NamedTuple.
In order to get a consistent experience, we moved typing.NamedTuple inference support
in the brain file corresponding to collections's namedtuple, and there we can leverage the
namedtuple inference rewriting functions. Now a new capability that typing.NamedTuple has is
to understand that we can define methods on the class, so that they can be used on the instance
when instantiated.
Another small bug that was fixed was to put Name nodes in .bases when building a namedtuple,
instead of putting the class node itself.

Close pylint-dev/pylint#1628
@orenbenkiki
Copy link

I'm using pylint version 2.0.0, asteroid version 2.0.1, Python version 3.7.0.

Writing:

"""Example"""
from typing import NamedTuple
class _Point(NamedTuple):
    x: int
    y: int

I get the error:

example.py:3:0: R0903: Too few public methods (0/2) (too-few-public-methods)

I tried writing pip install pylint astroid --pre --user just in case, but all I got was a list of Requirement already satisfied.

So, on the one hand @PCManticore said this is in pre-release just 17 days ago, so it makes sense this isn't published yet. But on the other hand he said "pre-release for 2.0" which seems to be available already. Is it actually pre-release for version 2.1?

@PCManticore
Copy link
Contributor

@orenbenkiki This issue is about the no-member error that the OP reported. It's not about the too-few-public-methods you are getting.

@orenbenkiki
Copy link

Oops, my bad. I got thrown by the error listed in the example above.

Should I open a separate issue for it then?

@jhbuhrman
Copy link

Orenbenkiki wrote:

Oops, my bad. I got thrown by the error listed in the example above.

Should I open a separate issue for it then?

@PCManticore I did my best identifying an issue explicitly addressing this problem, but could not find any and the too-few-public-methods is still output, so I think the question above is still valid. Should a separate issue be opened for it?

pylint --version output

pylint 2.1.1
astroid 2.0.4
Python 3.7.0 (default, Jun 29 2018, 20:13:13) 
[Clang 9.1.0 (clang-902.0.39.2)]

@PCManticore
Copy link
Contributor

@jhbuhrman yes, please.

@jhbuhrman
Copy link

Created #2459 just now.

@PCManticore
Copy link
Contributor

Awesome, thank you!

@officialcryptomaster
Copy link

officialcryptomaster commented Mar 4, 2019

@PCManticore Problem seems to persist in latest versions:

(pyveil_env) ➜  pyveil git:(master) ✗ pylint --version
pylint 2.3.1
astroid 2.2.2
Python 3.7.2 (default, Dec 27 2018, 07:35:52)
[Clang 10.0.0 (clang-1000.11.45.5)]

ran on following code:

cat >test_named_tuple.py << EOL
from typing import NamedTuple
class Test(NamedTuple):
    MEMBER = "member"

print(Test.MEMBER)
EOL
pylint --disable=too-few-public-methods,missing-docstring test_named_tuple.py

gives result:

************* Module test_named_tuple
test_named_tuple.py:10:6: E1101: Class 'Test' has no 'MEMBER' member (no-member)

------------------------------------
Your code has been rated at -2.50/10

@PCManticore
Copy link
Contributor

Thanks @officialcryptomaster I can reproduce this. Probably your example uses a different code path than my fix from pylint-dev/astroid@5e30daa.

@PCManticore PCManticore reopened this Mar 4, 2019
@PCManticore PCManticore added the Needs astroid Brain 🧠 Needs a brain tip in astroid (then an astroid upgrade) label Mar 4, 2019
@officialcryptomaster
Copy link

@PCManticore thanks for the quick reply. Is there an open issue for this? Would you be able to check and port the fix some time soon?

@officialcryptomaster
Copy link

Ah I see you reopened the issue! Thanks. Would be good if I have an approximate idea of when it might be fixed... I am for now moving to just using Enum instead for my use case...

@PCManticore
Copy link
Contributor

@officialcryptomaster I don't have any timeline for this fix, if you want feel free to tackle it in a PR, but it's not on my priority list for now.

@ankostis
Copy link

ankostis commented May 8, 2020

Shouldn't this issue be left open to track resolution of this bug?

@Seanny123
Copy link

I agree with @ankostis this issue seems to have been accidentally close as part of an unrelated MR. I'm still getting an error as demonstrated in the original description with the following:

pylint 2.6.0
astroid 2.4.2
Python 3.9.0 (default, Oct  6 2020, 00:00:00) 
[GCC 10.2.1 20200826 (Red Hat 10.2.1-3)]

@Seanny123
Copy link

Please ignore my previous comment.This issue is now being tracked in #3876

powersj pushed a commit to canonical/curtin that referenced this issue May 13, 2021
For some obscure reason setting

  generated-members=DISTROS\.

in pylintrc makes the pylint run flaky, causing failures like:

curtin/commands/install_grub.py:93:19:
  E1101: Instance of 'Distros' has no 'debian' member (no-member)
curtin/commands/install_grub.py:155:28:
  E1101: Instance of 'Distros' has no 'redhat' member (no-member)

These failures:

 - happen on about 15% of the time, at least on Bionic
 - also happen with the latest stable version of pylint (2.8.2)
 - only happen on install_grub.py (which only refers to debian and redhat)
 - do not seem to happen on Impish.
 - possibly related: pylint-dev/pylint#1628

But the truth is I don't understand why generated-members=DISTROS\.
even works some of the time for some generated members. Let's replace
it with the explicit list of the (non auto-detected) generated members,
so it will always work, and we'll know why it does.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug 🪲 Needs astroid Brain 🧠 Needs a brain tip in astroid (then an astroid upgrade)
Projects
None yet
Development

Successfully merging a pull request may close this issue.