Skip to content

Commit

Permalink
[mypyc] Fix direct __dict__ access on inner functions in new Python (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
hauntsaninja committed Oct 15, 2023
1 parent feb0fa7 commit 940fceb
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
5 changes: 4 additions & 1 deletion mypyc/codegen/emitclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def generate_class(cl: ClassIR, module: str, emitter: Emitter) -> None:
fields["tp_name"] = f'"{name}"'

generate_full = not cl.is_trait and not cl.builtin_base
needs_getseters = cl.needs_getseters or not cl.is_generated
needs_getseters = cl.needs_getseters or not cl.is_generated or cl.has_dict

if not cl.builtin_base:
fields["tp_new"] = new_name
Expand Down Expand Up @@ -886,6 +886,9 @@ def generate_getseters_table(cl: ClassIR, name: str, emitter: Emitter) -> None:
else:
emitter.emit_line("NULL, NULL, NULL},")

if cl.has_dict:
emitter.emit_line('{"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},')

emitter.emit_line("{NULL} /* Sentinel */")
emitter.emit_line("};")

Expand Down
30 changes: 30 additions & 0 deletions mypyc/test-data/run-functions.test
Original file line number Diff line number Diff line change
Expand Up @@ -1256,3 +1256,33 @@ def foo(**kwargs: Unpack[Person]) -> None:
foo(name='Jennifer', age=38)
[out]
Jennifer

[case testNestedFunctionDunderDict312]
import sys

def foo() -> None:
def inner() -> str: return "bar"
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

bar()
[out]
{'__module__': 'native', '__name__': 'bar', '__qualname__': 'bar', '__doc__': None, '__wrapped__': <built-in function bar>}

0 comments on commit 940fceb

Please sign in to comment.