feat: reuse weak callable proxy (#8618)

This commit is contained in:
김은빈 authored and GitHub committed 2026-08-30 17:28:46 +09:00
1 parent 2c8d3ce50b
commit 8b65a5455f
6 files changed
+39 -8

No files matched your search

-1
View File
@@ -403,7 +403,6 @@ class ReferencesTestCase(TestBase):
p2 = makeref(o)
self.assertIs(p1, p2, "callbacks were None, NULL in the C API")
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_callable_proxy(self):
o = Callable()
ref1 = weakref.proxy(o)
+1 -1
View File
@@ -90,7 +90,7 @@ pub use traceback::PyTraceback;
pub(crate) mod tuple;
pub use tuple::{PyTuple, PyTupleRef};
pub(crate) mod weakproxy;
pub use weakproxy::PyWeakProxy;
pub use weakproxy::{PyWeakCallableProxy, PyWeakProxy};
pub(crate) mod weakref;
pub use weakref::PyWeak;
pub(crate) mod zip;
+30 -3
View File
@@ -8,8 +8,8 @@ use crate::{
protocol::{PyIter, PyIterReturn, PyMappingMethods, PyNumberMethods, PySequenceMethods},
stdlib::builtins::reversed,
types::{
AsMapping, AsNumber, AsSequence, Comparable, Constructor, GetAttr, Hashable, IterNext,
Iterable, PyComparisonOp, Representable, SetAttr,
AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, GetAttr, Hashable,
IterNext, Iterable, PyComparisonOp, Representable, SetAttr,
},
};
@@ -67,7 +67,11 @@ impl PyWeakProxy {
callback: Option<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult<PyRef<PyWeak>> {
let typ = vm.ctx.types.weakproxy_type.to_owned();
let typ = if referent.is_callable() {
vm.ctx.types.weakcallableproxy_type.to_owned()
} else {
vm.ctx.types.weakproxy_type.to_owned()
};
referent.downgrade_with_typ(callback, typ, vm)
}
@@ -77,6 +81,28 @@ impl PyWeakProxy {
}
}
#[pyclass(
module = false,
name = "weakcallableproxy",
base = PyWeakProxy,
ctx = "weakcallableproxy_type",
unhashable = true
)]
#[derive(Debug)]
#[repr(transparent)]
pub struct PyWeakCallableProxy(PyWeakProxy);
#[pyclass(with(Callable))]
impl PyWeakCallableProxy {}
impl Callable for PyWeakCallableProxy {
type Args = FuncArgs;
fn call(zelf: &Py<Self>, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
zelf.0.try_upgrade(vm)?.call(args, vm)
}
}
#[pyclass(with(
GetAttr,
SetAttr,
@@ -371,6 +397,7 @@ impl Representable for PyWeakProxy {
pub(crate) fn init(context: &'static Context) {
PyWeakProxy::extend_class(context, context.types.weakproxy_type);
PyWeakCallableProxy::extend_class(context, context.types.weakcallableproxy_type);
}
impl Hashable for PyWeakProxy {
+5 -2
View File
@@ -771,10 +771,12 @@ impl WeakRefList {
Some(candidate) => {
let node = unsafe { candidate.as_ref() };
let has_callback = unsafe { (&*node.0.payload.callback.get()).is_some() };
let node_cls = node.class();
// PyWeakref_CheckProxy: the basic-proxy slot is reserved for
// the canonical proxy type; subclasses and callback-less ref
// subclasses must not be mistaken for it.
let is_proxy = node.class().is(crate::builtins::PyWeakProxy::static_type());
let is_proxy = node_cls.is(crate::builtins::PyWeakProxy::static_type())
|| node_cls.is(crate::builtins::PyWeakCallableProxy::static_type());
if has_callback || !is_proxy {
ptr::null_mut()
} else {
@@ -1602,7 +1604,8 @@ impl PyObject {
None
};
let cls_is_weakref = typ.is(vm.ctx.types.weakref_type);
let cls_is_weakproxy = typ.is(vm.ctx.types.weakproxy_type);
let cls_is_weakproxy =
typ.is(vm.ctx.types.weakproxy_type) || typ.is(vm.ctx.types.weakcallableproxy_type);
let wrl = self.weak_ref_list().ok_or_else(|| {
vm.new_type_error(format!(
"cannot create weak reference to '{}' object",
+1 -1
View File
@@ -35,7 +35,7 @@ mod _weakref {
#[pyattr(name = "CallableProxyType")]
fn callable_proxy_type(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.weakproxy_type.to_owned()
vm.ctx.types.weakcallableproxy_type.to_owned()
}
#[pyfunction]
+2
View File
@@ -86,6 +86,7 @@ pub struct TypeZoo {
pub bound_method_type: &'static Py<PyType>,
pub weakref_type: &'static Py<PyType>,
pub weakproxy_type: &'static Py<PyType>,
pub weakcallableproxy_type: &'static Py<PyType>,
pub mappingproxy_type: &'static Py<PyType>,
pub traceback_type: &'static Py<PyType>,
pub object_type: &'static Py<PyType>,
@@ -198,6 +199,7 @@ impl TypeZoo {
traceback_type: traceback::PyTraceback::init_builtin_type(),
tuple_iterator_type: tuple::PyTupleIterator::init_builtin_type(),
weakproxy_type: weakproxy::PyWeakProxy::init_builtin_type(),
weakcallableproxy_type: weakproxy::PyWeakCallableProxy::init_builtin_type(),
method_descriptor_type: descriptor::PyMethodDescriptor::init_builtin_type(),
none_type: singletons::PyNone::init_builtin_type(),
typing_no_default_type: crate::stdlib::_typing::NoDefault::init_builtin_type(),