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

Where does pylance get the existence of pandas.DataFrame.__iadd__? #1245

Closed
Azureblade3808 opened this issue May 7, 2021 · 5 comments
Closed
Labels
typestub Issue relating to our bundled type stubs

Comments

@Azureblade3808
Copy link

Azureblade3808 commented May 7, 2021

Try with the bundled Pandas stubs:

from pandas import DataFrame

df = DataFrame()  # Type of `df` is `DataFrame`.
df += 0
df  # Type of `df` becomes `Unknown`.

df = DataFrame()  # Type of `df` is reset to `DataFrame`.
df.__iadd__  # Type of method `__iadd__` is `Unknown`, but the access here is not warned.

i = int(0)  # Type of `i` is `int`.
i.__iadd__  # Got warning here, since `int` doesn't have a member of `__iadd__`.

Pylance seems to think that DataFrame has a member of __iadd__ with no explicit signature, but I searched through the stubs and failed to find a valid definition of __iadd__ in DataFrame or any of its ancestors. There is __iadd__ in the library code though.

Is it from the library code instead of the stubs?

@github-actions github-actions bot added the triage label May 7, 2021
@jakebailey
Copy link
Member

We wrote and bundled stubs for pandas that are mirrored here: https://github.com/microsoft/python-type-stubs

To be clear, this is a function that you're saying the stub is missing?

@gramster

@jakebailey jakebailey added the typestub Issue relating to our bundled type stubs label May 7, 2021
@github-actions github-actions bot removed the triage label May 7, 2021
@Azureblade3808
Copy link
Author

Finally, I've figured it out. According to the bundled stub, __iadd__ on pandas.DataFrame instances is ensured by pandas.NDFrame.__getattr__ which has no explicit return type, so its type is Unknown.

@Azureblade3808
Copy link
Author

There is another problem --

Try running the example:

class C:
    def __iadd__(self, x):
        return 0

c = C()
c += "abc"
print(c)  # Prints 0.

c = C()
c.__iadd__ = lambda x: 1 
c += "abc"
print(c)  # Still prints 0, instead of 1.

By using +=, what gets called is the __iadd__ defined on the class instead of the instance. It is the same case for + with __add__, len(...) with __len__, abs(...) with __abs__, etc.

Normally, we are not writing code like in the example, so it needs not to be concerned whether the method implementation is different between the class and the instance. But I think the results returned by __getattr__ need to be distinguished. In my opinion, __getattr__ should be ignored during implicit member checks such as operator availability and protocol conforming.

@Azureblade3808
Copy link
Author

Related: #1252

@Azureblade3808
Copy link
Author

I'm closing this issue, because the question in the title has already had an answer.

Besides, I don't think the root of problems lies in the bundled stub. The stub should work correctly once #1252 were fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
typestub Issue relating to our bundled type stubs
Projects
None yet
Development

No branches or pull requests

2 participants