Skip to content

Commit 78db5ea

Browse files
Merge pull request RustPython#835 from RustPython/coolreader18/weakproxy
Add weakproxy
2 parents 2c3f4b6 + 1612c95 commit 78db5ea

File tree

8 files changed

+83
-3
lines changed

8 files changed

+83
-3
lines changed

tests/snippets/weakrefs.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from _weakref import ref
1+
from _weakref import ref, proxy
2+
from testutils import assert_raises
23

34

45
class X:
@@ -11,3 +12,17 @@ class X:
1112
assert callable(b)
1213
assert b() is a
1314

15+
16+
class G:
17+
def __init__(self, h):
18+
self.h = h
19+
20+
21+
g = G(5)
22+
p = proxy(g)
23+
24+
assert p.h == 5
25+
26+
del g
27+
28+
assert_raises(ReferenceError, lambda: p.h)

vm/src/builtins.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,7 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef) {
751751
"NameError" => ctx.exceptions.name_error.clone(),
752752
"OverflowError" => ctx.exceptions.overflow_error.clone(),
753753
"RuntimeError" => ctx.exceptions.runtime_error.clone(),
754+
"ReferenceError" => ctx.exceptions.reference_error.clone(),
754755
"NotImplementedError" => ctx.exceptions.not_implemented_error.clone(),
755756
"TypeError" => ctx.exceptions.type_error.clone(),
756757
"ValueError" => ctx.exceptions.value_error.clone(),

vm/src/exceptions.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ pub struct ExceptionZoo {
118118
pub os_error: PyClassRef,
119119
pub overflow_error: PyClassRef,
120120
pub permission_error: PyClassRef,
121+
pub reference_error: PyClassRef,
121122
pub runtime_error: PyClassRef,
122123
pub stop_iteration: PyClassRef,
123124
pub syntax_error: PyClassRef,
@@ -152,6 +153,7 @@ impl ExceptionZoo {
152153
let name_error = create_type("NameError", &type_type, &exception_type);
153154
let os_error = create_type("OSError", &type_type, &exception_type);
154155
let runtime_error = create_type("RuntimeError", &type_type, &exception_type);
156+
let reference_error = create_type("ReferenceError", &type_type, &exception_type);
155157
let stop_iteration = create_type("StopIteration", &type_type, &exception_type);
156158
let syntax_error = create_type("SyntaxError", &type_type, &exception_type);
157159
let type_error = create_type("TypeError", &type_type, &exception_type);
@@ -208,6 +210,7 @@ impl ExceptionZoo {
208210
syntax_warning,
209211
resource_warning,
210212
runtime_warning,
213+
reference_error,
211214
user_warning,
212215
}
213216
}

vm/src/obj/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ pub mod objstr;
3434
pub mod objsuper;
3535
pub mod objtuple;
3636
pub mod objtype;
37+
pub mod objweakproxy;
3738
pub mod objweakref;
3839
pub mod objzip;

vm/src/obj/objweakproxy.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use super::objweakref::PyWeak;
2+
use crate::function::OptionalArg;
3+
use crate::obj::objtype::PyClassRef;
4+
use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue};
5+
use crate::vm::VirtualMachine;
6+
7+
#[derive(Debug)]
8+
pub struct PyWeakProxy {
9+
weak: PyWeak,
10+
}
11+
12+
impl PyValue for PyWeakProxy {
13+
fn class(vm: &VirtualMachine) -> PyClassRef {
14+
vm.ctx.weakproxy_type()
15+
}
16+
}
17+
18+
pub type PyWeakProxyRef = PyRef<PyWeakProxy>;
19+
20+
impl PyWeakProxyRef {
21+
// TODO callbacks
22+
fn create(
23+
cls: PyClassRef,
24+
referent: PyObjectRef,
25+
_callback: OptionalArg<PyObjectRef>,
26+
vm: &VirtualMachine,
27+
) -> PyResult<Self> {
28+
PyWeakProxy {
29+
weak: PyWeak::downgrade(&referent),
30+
}
31+
.into_ref_with_type(vm, cls)
32+
}
33+
34+
fn getattr(self, attr_name: PyObjectRef, vm: &VirtualMachine) -> PyResult {
35+
match self.weak.upgrade() {
36+
Some(obj) => vm.get_attribute(obj, attr_name),
37+
None => Err(vm.new_exception(
38+
vm.ctx.exceptions.reference_error.clone(),
39+
"weakly-referenced object no longer exists".to_string(),
40+
)),
41+
}
42+
}
43+
}
44+
45+
pub fn init(context: &PyContext) {
46+
extend_class!(context, &context.weakproxy_type, {
47+
"__new__" => context.new_rustfunc(PyWeakProxyRef::create),
48+
"__getattr__" => context.new_rustfunc(PyWeakProxyRef::getattr),
49+
});
50+
}

vm/src/obj/objweakref.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
use crate::function::OptionalArg;
12
use crate::obj::objtype::PyClassRef;
23
use crate::pyobject::PyValue;
34
use crate::pyobject::{PyContext, PyObject, PyObjectPayload, PyObjectRef, PyRef, PyResult};
45
use crate::vm::VirtualMachine;
56

6-
use crate::function::OptionalArg;
77
use std::rc::{Rc, Weak};
88

99
#[derive(Debug)]

vm/src/pyobject.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use crate::obj::objstr;
5151
use crate::obj::objsuper;
5252
use crate::obj::objtuple::{self, PyTuple, PyTupleRef};
5353
use crate::obj::objtype::{self, PyClass, PyClassRef};
54+
use crate::obj::objweakproxy;
5455
use crate::obj::objweakref;
5556
use crate::obj::objzip;
5657
use crate::vm::VirtualMachine;
@@ -158,6 +159,7 @@ pub struct PyContext {
158159
pub module_type: PyClassRef,
159160
pub bound_method_type: PyClassRef,
160161
pub weakref_type: PyClassRef,
162+
pub weakproxy_type: PyClassRef,
161163
pub object: PyClassRef,
162164
pub exceptions: exceptions::ExceptionZoo,
163165
}
@@ -255,6 +257,7 @@ impl PyContext {
255257
let readonly_property_type = create_type("readonly_property", &type_type, &object_type);
256258
let super_type = create_type("super", &type_type, &object_type);
257259
let weakref_type = create_type("ref", &type_type, &object_type);
260+
let weakproxy_type = create_type("weakproxy", &type_type, &object_type);
258261
let generator_type = create_type("generator", &type_type, &object_type);
259262
let bound_method_type = create_type("method", &type_type, &object_type);
260263
let str_type = create_type("str", &type_type, &object_type);
@@ -361,6 +364,7 @@ impl PyContext {
361364
module_type,
362365
bound_method_type,
363366
weakref_type,
367+
weakproxy_type,
364368
type_type,
365369
exceptions,
366370
};
@@ -396,6 +400,7 @@ impl PyContext {
396400
objcode::init(&context);
397401
objframe::init(&context);
398402
objweakref::init(&context);
403+
objweakproxy::init(&context);
399404
objnone::init(&context);
400405
objmodule::init(&context);
401406
exceptions::init(&context);
@@ -554,6 +559,10 @@ impl PyContext {
554559
self.weakref_type.clone()
555560
}
556561

562+
pub fn weakproxy_type(&self) -> PyClassRef {
563+
self.weakproxy_type.clone()
564+
}
565+
557566
pub fn type_type(&self) -> PyClassRef {
558567
self.type_type.clone()
559568
}

vm/src/stdlib/weakref.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
1212
let ctx = &vm.ctx;
1313

1414
py_module!(vm, "_weakref", {
15-
"ref" => ctx.weakref_type()
15+
"ref" => ctx.weakref_type(),
16+
"proxy" => ctx.weakproxy_type(),
1617
})
1718
}

0 commit comments

Comments
 (0)