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

ctypes.Structure and Iterable #10272

Open
giladreti opened this issue Apr 1, 2021 · 2 comments
Open

ctypes.Structure and Iterable #10272

giladreti opened this issue Apr 1, 2021 · 2 comments
Labels
bug mypy got something wrong

Comments

@giladreti
Copy link

giladreti commented Apr 1, 2021

Bug Report

For some reason ctypes.Structure instances pass mypy's isinstance checks although mypy also claims that they are not iterable.
For example, consider the following code:

from ctypes import Structure

from typing import Iterable


class S(Structure):
    pass


s = S()

if isinstance(s, Iterable):
    for _ in s:
        pass

mypy gives the following error:

test.py:13: error: "S" has no attribute "__iter__" (not iterable)
Found 1 error in 1 file (checked 1 source file)

replacing it with iter(s) make mypy happy again.

Your Environment

  • Mypy version used: mypy 0.790
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: Python 3.8.6
  • Operating system and version: Linux ubuntu 5.10.0 Invalid type inferred for 'or' and 'and' expressions #17 SMP Mon Dec 14 10:04:17 IST 2020 x86_64 x86_64 x86_64 GNU/Linux
@giladreti giladreti added the bug mypy got something wrong label Apr 1, 2021
@JulienPalard
Copy link
Member

I don't think a Structure is meant to be iterable, looks like it is not:

$ cat  test.py
from ctypes import Structure

class S(Structure):
    pass


s = S()

iter(s)

$ python test.py
Traceback (most recent call last):
  File "/home/mdk/clones/JulienPalard/oeis/test.py", line 9, in <module>
    iter(s)
TypeError: 'S' object is not iterable

So I think the bug is more than adding iter mutes the error, while it should not?

@JelleZijlstra
Copy link
Member

The weird thing then is that mypy thinks the isinstance(S, Iterable) check succeeds. I think that's because ctypes.Structure has a __getattr__ method in typeshed (https://github.com/python/typeshed/blob/5d45e3babc7241001a63e66146a03c3a1d959227/stdlib/ctypes/__init__.pyi#L251).

Here's a simpler repro case: https://mypy-play.net/?mypy=latest&python=3.10&gist=858d8c8589cfdc893dce41f54f08b046

from typing import Iterable, Any


class Structure:
    def __getattr__(self, attr: str) -> Any: ...

class S(Structure):
    pass


s = S()

if isinstance(s, Iterable):
    for _ in s:
        pass

Presumably mypy conceptually looks at the instance for the isinstance() check, so the __getattr__ allows it to think there's an __iter__ method, but when checking for _ in s: it (correctly) looks at the class, which doesn't have an __iter__ method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

3 participants