Pylint: typing.NamedTuple false positive no-member for methods

Created on 16 Aug 2017  Â·  23Comments  Â·  Source: PyCQA/pylint

Steps to reproduce

This is only legal in python 3.6.1 and higher:

$ cat nt.py

```python
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

```console
$ 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.

astroid brain bug

Most helpful comment

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 ? :)

All 23 comments

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.

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 ? :)

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

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.

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

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: [email protected]
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: [email protected]
License: LGPL
Location: /.../venv/lib/python3.6/site-packages
Requires: wrapt, lazy-object-proxy, six
Required-by: pylint

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.

Awesome news. Thank you for the quick response.

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?

@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.

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

Should I open a separate issue for it then?

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)]

@jhbuhrman yes, please.

Created #2459 just now.

Awesome, thank you!

@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

Thanks @officialcryptomaster I can reproduce this. Probably your example uses a different code path than my fix from https://github.com/PyCQA/astroid/commit/5e30daa4eacec3b5d64c032cb82cc2aa4ef7eb2b.

@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?

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...

@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.

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

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)]

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

Was this page helpful?
0 / 5 - 0 ratings