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

Fixed false positive of no-member for methods of namedtuples instances #4487

Closed
wants to merge 3 commits into from

Conversation

yushao2
Copy link
Contributor

@yushao2 yushao2 commented May 21, 2021

Steps

  • Add a ChangeLog entry describing what your PR does.
  • If it's a new feature or an important bug fix, add a What's New entry in
    doc/whatsnew/<current release.rst>. (not sure if important bugfix)
  • Write a good description on what the PR does.

Description

From investigation, it seems like _replace() yields a NamedTuple instance and .geturl() is not a valid attribute -- therefore the warning is triggered.

>>> pprint(instance.as_string())
('\n'
 '\n'
 'class ParseResult(tuple):\n'
 '    __slots__ = ()\n'
 "    _fields = ['scheme', 'netloc', 'path', 'params', 'query', 'fragment']\n"
 '    \n'
 '    def _asdict(self):\n'
 '        return self.__dict__\n'
 '    \n'
 '    @classmethod\n'
 '    def _make(cls, iterable, new=tuple.__new__, len=len):\n'
 '        return new(cls, iterable)\n'
 '    \n'
 '    def _replace(self, scheme=None, netloc=None, path=None, params=None, '
 'query=None, fragment=None):\n'
 '        return self\n'
 '    \n'
 '    def __getnewargs__(self):\n'
 '        return tuple(self)\n'
 "    scheme = property(lambda self: self[0], doc='Alias for field number 0')\n"
 "    netloc = property(lambda self: self[1], doc='Alias for field number 1')\n"
 "    path = property(lambda self: self[2], doc='Alias for field number 2')\n"
 "    params = property(lambda self: self[3], doc='Alias for field number 3')\n"
 "    query = property(lambda self: self[4], doc='Alias for field number 4')\n"
 "    fragment = property(lambda self: self[5], doc='Alias for field number "
 "5')\n")

Therefore to circumvent this false-positive,

  1. Check that it is a function call
  2. instance's class can be inferred to be derived from tuple
    --> Then we don't fire the error

I'm not too sure if this is the correct approach and thus it's marked as a draft PR, but opening this PR to get reviews / thoughts on whether this might be a potential solution / how to approach this issue

Type of Changes

Type
🐛 Bug fix

Related Issue

Closes #4377

@coveralls
Copy link

coveralls commented May 21, 2021

Coverage Status

Coverage increased (+0.001%) to 91.829% when pulling cac4e5d on yushao2:bug-4377 into 4628b74 on PyCQA:master.

@yushao2 yushao2 marked this pull request as ready for review May 22, 2021 17:17
@yushao2 yushao2 marked this pull request as draft May 23, 2021 08:25
@Pierre-Sassoulas Pierre-Sassoulas added Bug 🪲 False Positive 🦟 A message is emitted but nothing is wrong with the code labels May 23, 2021
@yushao2 yushao2 marked this pull request as ready for review May 25, 2021 11:26
@yushao2 yushao2 changed the title Fixed false positive for methods of namedtuples instances Fixed false positive of no-member for methods of namedtuples instances May 25, 2021
@yushao2
Copy link
Contributor Author

yushao2 commented May 25, 2021

Marking this as ready for review to get some comments -- to see if this is the correct approach to the issue

Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look good to me :)

Copy link
Member

@cdce8p cdce8p left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this should be fixed in pylint. To me it looks like a issue with the astroid inference of namedtuples. A smiliar one seems to be #4370

@nelfin Do you have an idea how to fix it? If I remember correctly, you've already worked on brain_namedtuple_enum.py.

@nelfin
Copy link
Contributor

nelfin commented Jun 2, 2021

I'm not sure this should be fixed in pylint. To me it looks like a issue with the astroid inference of namedtuples. A smiliar one seems to be #4370

@nelfin Do you have an idea how to fix it? If I remember correctly, you've already worked on brain_namedtuple_enum.py.

I'll have a look, it doesn't seem like it's an issue with subclassing NamedTuples at first glance. The sorted_query lines in the test are a red herring as well, I can make the same test give a false-positive with this:

from urllib import parse
parsed_url = parse.urlparse("http://www.this-is-weird.com")
a = parse.ParseResult._replace(parsed_url, query='foo')
b = a.geturl()  # false-positive: no-member

From investigation, it seems like _replace() yields a NamedTuple instance and .geturl() is not a valid attribute -- therefore the warning is triggered.

_replace returns self (in the transformed namedtuple class definition), not a new NamedTuple instance. I think what's happening here is urllib.parse defines a namedtuple and assigns it to a different name (which the astroid namedtuple brain ignore), then later subclasses that base namedtuple. I think then pylint attempts to infer that class definition and it only sees the first one, but I'm less familiar with pylint that I am with astroid.

# snippet from urllib.parse
_ParseResultBase = namedtuple('ParseResult', 'scheme netloc path params query fragment')
# ...
class ParseResult(_ParseResultBase, _NetlocResultMixinStr):
    __slots__ = ()
    def geturl(self):
        return urlunparse(self)

@Pierre-Sassoulas
Copy link
Member

Closing because @nelfin convinced me it should be fixed in astroid instead.

@yushao2 yushao2 deleted the bug-4377 branch January 4, 2023 13:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug 🪲 False Positive 🦟 A message is emitted but nothing is wrong with the code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

E1101: false positive with urlparse.ParseResult geturl() after <instance>._replace(...)
5 participants