-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
[mypyc] Fix direct __dict__ access on inner functions in new Python #16084
Conversation
Nice! I can confirm that, with this patch, both snippets I pasted in #16077 work for me locally on Python 3.12 once they've been mypycified. |
Hmm, looks like the new test passes with py312 but not with any other Python version? |
Hmm maybe we can just drop support for all these legacy Python versions? |
I opted for a simple "fix" for older Python versions, which is to test less. But I think we can make the |
|
||
def foo() -> None: | ||
def inner() -> str: return "bar" | ||
print(inner.__dict__) # type: ignore[attr-defined] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a lot of type ignores in this test, do we really need that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, fixtures, also mypy genuinely won't understand inner.x
print(inner.__dict__) # type: ignore[attr-defined] | ||
inner.__dict__.update({"x": 1}) # type: ignore[attr-defined] | ||
print(inner.__dict__) # type: ignore[attr-defined] | ||
print(inner.x) # type: ignore[attr-defined] | ||
|
||
if sys.version_info >= (3, 12): # type: ignore | ||
foo() | ||
[out] | ||
[out version>=3.12] | ||
{} | ||
{'x': 1} | ||
1 | ||
|
||
[case testFunctoolsUpdateWrapper] | ||
import functools | ||
|
||
def bar() -> None: | ||
def inner() -> str: return "bar" | ||
functools.update_wrapper(inner, bar) # type: ignore | ||
print(inner.__dict__) # type: ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a hacky way of getting rid of a bunch of type: ignore
s in the test file. The tests all still pass for me locally with this change (on py311 and py312):
print(inner.__dict__) # type: ignore[attr-defined] | |
inner.__dict__.update({"x": 1}) # type: ignore[attr-defined] | |
print(inner.__dict__) # type: ignore[attr-defined] | |
print(inner.x) # type: ignore[attr-defined] | |
if sys.version_info >= (3, 12): # type: ignore | |
foo() | |
[out] | |
[out version>=3.12] | |
{} | |
{'x': 1} | |
1 | |
[case testFunctoolsUpdateWrapper] | |
import functools | |
def bar() -> None: | |
def inner() -> str: return "bar" | |
functools.update_wrapper(inner, bar) # type: ignore | |
print(inner.__dict__) # type: ignore | |
print(getattr(inner, "__dict__")) | |
getattr(inner, "__dict__").update({"x": 1}) | |
print(getattr(inner, "__dict__")) | |
print(getattr(inner, "x")) | |
if sys.version_info >= (3, 12): # type: ignore | |
foo() | |
[out] | |
[out version>=3.12] | |
{} | |
{'x': 1} | |
1 | |
[case testFunctoolsUpdateWrapper] | |
import functools | |
def bar() -> None: | |
def inner() -> str: return "bar" | |
functools.update_wrapper(inner, bar) # type: ignore | |
print(getattr(inner, "__dict__")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's okay as is, I kinda feel obfuscation here makes it less clear to the reader what is being tested
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah i didn't really like this either, was just throwing it out there as an option :)
Merging since this has been open for a bit and unblocks Python 3.12 mypyc in black, let me know if this change is actually incorrect! |
Fixes #16077