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

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

Closed
povesma opened this issue Apr 19, 2021 · 2 comments · Fixed by pylint-dev/astroid#1151
Labels
Bug 🪲 False Positive 🦟 A message is emitted but nothing is wrong with the code

Comments

@povesma
Copy link

povesma commented Apr 19, 2021

New look of #597:
I got no-member warnings from code like this:

    parsed_url = parse.urlparse(url)
    sorted_query = parse.urlencode(sorted(parse.parse_qsl(parsed_url.query), key=lambda param: param[0]))
    new_parsed_url = parse.ParseResult._replace(parsed_url, query=sorted_query)
    new_url = new_parsed_url.geturl()

if I use an instance of ParseResult (new_parsed_url) instead of class static method, like:
new_parsed_url = parsed_url._replace(query=sorted_query)

the warning disappears.

$ pylint --version

pylint 2.7.4
astroid 2.5.3
Python 3.8.7 (default, Mar  9 2021, 10:52:42)
[Clang 12.0.0 (clang-1200.0.32.29)]

Steps to reproduce

pylint

Output is:

tests/api_test.py:28:14: E1101: Instance of 'ParseResult' has no 'geturl' member (no-member)
@Pierre-Sassoulas Pierre-Sassoulas added the False Positive 🦟 A message is emitted but nothing is wrong with the code label Apr 19, 2021
@yushao2
Copy link
Collaborator

yushao2 commented May 21, 2021

from what i understand it seems like the issue lies with it being inferred as a namedtuple subclass due to _replace.

This is what I got from investigating the code that you've attached

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

Since geturl is not an attribute of this inferred class, the warning is triggered.

I might be wrong here, still not too sure how to debug this except playing around with astroid

@yushao2
Copy link
Collaborator

yushao2 commented May 21, 2021

I wrote a draft PR in an attempt to resolve this, please take a look and let me know if this is the correct approach 🙏

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
4 participants