Skip to content

Commit 07d4a1b

Browse files
feat: new mypyc primitive for weakref.ref (#19099)
This PR adds a new mypyc primitive for `weakref.ref` I wasn't able to figure out what name mypyc expects for `weakref.proxy`, so I took that out and will keep that for a separate PR later on. ref is more commonly used than proxy anyway. for later, I tried: - weakref.proxy - weakref.ProxyType - weakref.weakproxy no luck with those also for later, I'll need to finish #19145 to add a primitive for `weakref.ref.__call__`
1 parent 7534898 commit 07d4a1b

File tree

7 files changed

+118
-1
lines changed

7 files changed

+118
-1
lines changed

mypyc/primitives/registry.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,4 +371,5 @@ def load_address_op(name: str, type: RType, src: str) -> LoadAddressDescription:
371371
import mypyc.primitives.list_ops
372372
import mypyc.primitives.misc_ops
373373
import mypyc.primitives.str_ops
374-
import mypyc.primitives.tuple_ops # noqa: F401
374+
import mypyc.primitives.tuple_ops
375+
import mypyc.primitives.weakref_ops # noqa: F401

mypyc/primitives/weakref_ops.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from mypyc.ir.ops import ERR_MAGIC
2+
from mypyc.ir.rtypes import object_rprimitive, pointer_rprimitive
3+
from mypyc.primitives.registry import function_op
4+
5+
# Weakref operations
6+
7+
new_ref_op = function_op(
8+
name="weakref.ReferenceType",
9+
arg_types=[object_rprimitive],
10+
return_type=object_rprimitive,
11+
c_function_name="PyWeakref_NewRef",
12+
extra_int_constants=[(0, pointer_rprimitive)],
13+
error_kind=ERR_MAGIC,
14+
)
15+
16+
new_ref__with_callback_op = function_op(
17+
name="weakref.ReferenceType",
18+
arg_types=[object_rprimitive, object_rprimitive],
19+
return_type=object_rprimitive,
20+
c_function_name="PyWeakref_NewRef",
21+
error_kind=ERR_MAGIC,
22+
)

mypyc/test-data/irbuild-weakref.test

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
[case testWeakrefRef]
2+
import weakref
3+
from typing import Any, Callable
4+
def f(x: object) -> object:
5+
return weakref.ref(x)
6+
7+
[out]
8+
def f(x):
9+
x, r0 :: object
10+
L0:
11+
r0 = PyWeakref_NewRef(x, 0)
12+
return r0
13+
14+
[case testWeakrefRefCallback]
15+
import weakref
16+
from typing import Any, Callable
17+
def f(x: object, cb: Callable[[object], Any]) -> object:
18+
return weakref.ref(x, cb)
19+
20+
[out]
21+
def f(x, cb):
22+
x, cb, r0 :: object
23+
L0:
24+
r0 = PyWeakref_NewRef(x, cb)
25+
return r0
26+
27+
[case testFromWeakrefRef]
28+
from typing import Any, Callable
29+
from weakref import ref
30+
def f(x: object) -> object:
31+
return ref(x)
32+
33+
[out]
34+
def f(x):
35+
x, r0 :: object
36+
L0:
37+
r0 = PyWeakref_NewRef(x, 0)
38+
return r0
39+
40+
[case testFromWeakrefRefCallback]
41+
from typing import Any, Callable
42+
from weakref import ref
43+
def f(x: object, cb: Callable[[object], Any]) -> object:
44+
return ref(x, cb)
45+
46+
[out]
47+
def f(x, cb):
48+
x, cb, r0 :: object
49+
L0:
50+
r0 = PyWeakref_NewRef(x, cb)
51+
return r0

mypyc/test-data/run-weakref.test

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Test cases for weakrefs (compile and run)
2+
3+
[case testWeakrefRef]
4+
from weakref import ref
5+
from mypy_extensions import mypyc_attr
6+
7+
@mypyc_attr(native_class=False)
8+
class Object:
9+
"""some random weakreffable object"""
10+
pass
11+
12+
def test_weakref_ref():
13+
obj = Object()
14+
r = ref(obj)
15+
assert r() is obj
16+
obj = None
17+
assert r() is None, r()
18+
19+
def test_weakref_ref_with_callback():
20+
obj = Object()
21+
r = ref(obj, lambda x: x)
22+
assert r() is obj
23+
obj = None
24+
assert r() is None, r()
25+
26+
[file driver.py]
27+
from native import test_weakref_ref, test_weakref_ref_with_callback
28+
29+
test_weakref_ref()
30+
test_weakref_ref_with_callback()

mypyc/test/test_irbuild.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"irbuild-constant-fold.test",
5454
"irbuild-glue-methods.test",
5555
"irbuild-math.test",
56+
"irbuild-weakref.test",
5657
]
5758

5859
if sys.version_info >= (3, 10):

mypyc/test/test_run.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"run-singledispatch.test",
7171
"run-attrs.test",
7272
"run-signatures.test",
73+
"run-weakref.test",
7374
"run-python37.test",
7475
"run-python38.test",
7576
]

test-data/unit/lib-stub/weakref.pyi

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from collections.abc import Callable
2+
from typing import Any, Generic, TypeVar
3+
from typing_extensions import Self
4+
5+
_T = TypeVar("_T")
6+
7+
class ReferenceType(Generic[_T]): # "weakref"
8+
__callback__: Callable[[Self], Any]
9+
def __new__(cls, o: _T, callback: Callable[[Self], Any] | None = ..., /) -> Self: ...
10+
11+
ref = ReferenceType

0 commit comments

Comments
 (0)