Skip to content

MyPy 1.11.0 loop variable persistance #17541

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

Open
j6mes opened this issue Jul 19, 2024 · 3 comments
Open

MyPy 1.11.0 loop variable persistance #17541

j6mes opened this issue Jul 19, 2024 · 3 comments
Labels
bug mypy got something wrong

Comments

@j6mes
Copy link

j6mes commented Jul 19, 2024

Bug Report
In MyPy version 1.11.0, the type inference for loop variables seems to persist across different loops when the same variable name is used. This behavior differs from MyPy version 1.10.1, where the code works without issues.

To Reproduce

from functools import WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES

class Test:
  def test(self) -> None:
    self.stage_fn = lambda x: x
    for attr in WRAPPER_ASSIGNMENTS:
      object.__setattr__(self, attr, getattr(self.stage_fn, attr))

    for attr in WRAPPER_UPDATES:
      getattr(self, attr).update(getattr(self.stage_fn, attr, {}))

Expected Behavior
In previous versions, this did not raise an issue.

Actual Behavior

test.py:9: error: Incompatible types in assignment (expression has type "Literal['__dict__']", variable has type "Literal['__module__', '__name__', '__qualname__', '__doc__', '__annotations__']")  [assignment]
Found 1 error in 1 file (checked 1 source file)

This is seemingly fixed by changing the loop variables

for attr_1 in WRAPPER_ASSIGNMENTS:
    object.__setattr__(self, attr_1, getattr(self.stage_fn, attr_1))

for attr_2 in WRAPPER_UPDATES:
    getattr(self, attr_2).update(getattr(self.stage_fn, attr_2, {}))

This workaround should not be necessary, as loop variables should be scoped independently.

Your Environment

mypy==1.11.0
mypy-boto3-s3==1.34.138
mypy-extensions==1.0.0

pyproject.toml:

[tool.mypy]
explicit_package_bases = true
files = "src,test"
mypy_path = "src"
plugins = ["pydantic.mypy"]
strict = true   

@j6mes j6mes added the bug mypy got something wrong label Jul 19, 2024
@j6mes j6mes changed the title MyPy 1.11.0 broke MyPy 1.11.0 loop variable persistance Jul 19, 2024
@koogoro
Copy link
Collaborator

koogoro commented Jul 19, 2024

I think this isn't a bug. Loop variables in Python are function-scoped and do continue existing beyond the end of the loop. Examples like

a: list[str]
b: list[int]

for x in a:
    pass
for x in b:
    pass

have failed since at least mypy 1.0. I think the difference is that mypy 1.11 now assigns the type Literal['__module__', '__name__', '__qualname__', '__doc__', '__annotations__', '__type_params__'] to attr on the first loop instead of the type str. If you want this to succeed without needing to rename the variable, maybe try declaring attr: str before the first loop?

@hauntsaninja
Copy link
Collaborator

Yeah, agree with koogoro. The relevant mypy change here is #17408

@hauntsaninja hauntsaninja closed this as not planned Won't fix, can't repro, duplicate, stale Jul 20, 2024
@hauntsaninja hauntsaninja reopened this Jul 20, 2024
@scajanus
Copy link

scajanus commented Apr 4, 2025

Was this reopened by mistake or on purpose? @hauntsaninja

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

4 participants