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

Missing Member for Pydantic Model #8759

Open
alvinmaottd opened this issue Jun 10, 2023 · 1 comment
Open

Missing Member for Pydantic Model #8759

alvinmaottd opened this issue Jun 10, 2023 · 1 comment
Labels
Lib specific 💅 This affect the code from a particular library Needs decision 🔒 Needs a decision before implemention or rejection
Milestone

Comments

@alvinmaottd
Copy link

Bug description

hey team, I'm running into:
E1101: Instance of 'Response' has no 'versionInfo' member (no-member)
Provided the following code:

☁  test_py  cat main.py 
from response import Response
from run import f

r = f()
r.versionInfo = r.versionInfo | {"hi":"bye"}
print(r)%                                                                                                                                                                                     ☁  test_py  cat response.py 
from pydantic import BaseModel


class Response(BaseModel):
    versionInfo: dict[str, str]
    fm: dict[int, float]
☁  test_py  cat run.py 
from response import Response

def f() -> Response:
  return Response(verionInfo={}, fm={})%

Running pylint on main.py I get the following:
main.py:5:16: E1101: Instance of 'Response' has no 'versionInfo' member (no-member)

However, versionInfo is defined in the Response class.

I've got a theory for what's wrong and a work around. Specifically, I think it has something to do with how the BaseModel in pydantic isn't defining the fields using self / something more python native. When I replace the BaseModel with a normal class and define the fields with self linting passes.

Curious what the team thought should be done here. It's not strictly a bug given it's related to a separate dependency in pydantic.

Configuration

pylint 2.17.0
astroid 2.15.0
Python 3.9.6 (default, May  7 2023, 23:32:44) 
[Clang 14.0.3 (clang-1403.0.22.14.1)]

Command used

☁  test_py  pylint main.py

Pylint output

************* Module main
main.py:6:0: C0304: Final newline missing (missing-final-newline)
main.py:1:0: C0114: Missing module docstring (missing-module-docstring)
main.py:5:16: E1101: Instance of 'Response' has no 'versionInfo' member (no-member)
main.py:1:0: W0611: Unused Response imported from response (unused-import)

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

Expected behavior

************* Module main
main.py:6:0: C0304: Final newline missing (missing-final-newline)
main.py:1:0: C0114: Missing module docstring (missing-module-docstring)
main.py:1:0: W0611: Unused Response imported from response (unused-import)

^ no more:
main.py:5:16: E1101: Instance of 'Response' has no 'versionInfo' member (no-member)
or the option to do away with it.

Pylint version

pylint 2.17.0
astroid 2.15.0
Python 3.9.6 (default, May  7 2023, 23:32:44) 
[Clang 14.0.3 (clang-1403.0.22.14.1)]

OS / Environment

ProductName: macOS
ProductVersion: 13.4
BuildVersion: 22F66

Additional dependencies

No response

@alvinmaottd alvinmaottd added the Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling label Jun 10, 2023
@mbyrnepr2
Copy link
Member

mbyrnepr2 commented Jun 14, 2023

Thank you @alvinmaottd. This is the same situation as the comment in issue 4562. While the fix in 4562 addressed the false negatives, it didn't address the false positive.

I've been thinking about what to do here and I wonder what others think about this: Re-introduce the false-negatives from 4562 while also removing the false positive. The rationale for doing this would be:

  • It's part of Pylint goals to prefer false negatives over false positives
  • It aligns with a potential design-change idea that has arisen recently (8756 comment and 6281 comment) around using .pyi files to check for a member if that member cannot be found in a .py module.

Note for simplicity of reproducing, I've re-written your code example:

from pydantic import BaseModel


class Response(BaseModel):
    versionInfo: dict[str, str]
    fm: dict[int, float]

rr = Response(versionInfo={}, fm={})
rr.versionInfo = rr.versionInfo | {"hi":"bye"}  # Currently a false-positive but we could change this behaviour to ignore no-member if we find `versionInfo: <some annotation>` on the class

@Pierre-Sassoulas do you think this is feasible?

@mbyrnepr2 mbyrnepr2 added Needs decision 🔒 Needs a decision before implemention or rejection and removed Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling labels Jun 14, 2023
mbyrnepr2 added a commit to mbyrnepr2/pylint that referenced this issue Jun 14, 2023
mbyrnepr2 added a commit to mbyrnepr2/pylint that referenced this issue Jun 15, 2023
mbyrnepr2 added a commit to mbyrnepr2/pylint that referenced this issue Jun 21, 2023
mbyrnepr2 added a commit to mbyrnepr2/pylint that referenced this issue Jul 14, 2023
mbyrnepr2 added a commit to mbyrnepr2/pylint that referenced this issue Jul 16, 2023
@Pierre-Sassoulas Pierre-Sassoulas added the Lib specific 💅 This affect the code from a particular library label Aug 17, 2023
mbyrnepr2 added a commit to mbyrnepr2/pylint that referenced this issue Aug 30, 2023
@Pierre-Sassoulas Pierre-Sassoulas added this to the 4.0.0 milestone Sep 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Lib specific 💅 This affect the code from a particular library Needs decision 🔒 Needs a decision before implemention or rejection
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants