Skip to content

Commit 304f403

Browse files
committed
Fix WeakSet equality testing
1 parent 4c5dc29 commit 304f403

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

Lib/_weakrefset.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,6 @@ def union(self, other):
194194

195195
def isdisjoint(self, other):
196196
return len(self.intersection(other)) == 0
197+
198+
def __repr__(self):
199+
return repr(self.data)

vm/src/obj/objweakref.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
use super::objtype::PyClassRef;
22
use crate::function::{OptionalArg, PyFuncArgs};
33
use crate::pyobject::{
4-
PyClassImpl, PyContext, PyObject, PyObjectPayload, PyObjectRef, PyRef, PyResult, PyValue,
4+
IdProtocol, PyClassImpl, PyContext, PyObject, PyObjectPayload, PyObjectRef, PyRef, PyResult,
5+
PyValue, TypeProtocol,
56
};
67
use crate::slots::SlotCall;
78
use crate::vm::VirtualMachine;
89

10+
use crate::pyhash::PyHash;
11+
use crossbeam_utils::atomic::AtomicCell;
912
use std::sync::{Arc, Weak};
1013

1114
#[pyclass]
1215
#[derive(Debug)]
1316
pub struct PyWeak {
1417
referent: Weak<PyObject<dyn PyObjectPayload>>,
18+
hash: AtomicCell<Option<PyHash>>,
1519
}
1620

1721
impl PyWeak {
1822
pub fn downgrade(obj: &PyObjectRef) -> PyWeak {
1923
PyWeak {
2024
referent: Arc::downgrade(obj),
25+
hash: AtomicCell::new(None),
2126
}
2227
}
2328

@@ -53,6 +58,48 @@ impl PyWeak {
5358
) -> PyResult<PyRef<Self>> {
5459
PyWeak::downgrade(&referent).into_ref_with_type(vm, cls)
5560
}
61+
62+
#[pymethod(magic)]
63+
fn hash(&self, vm: &VirtualMachine) -> PyResult<PyHash> {
64+
match self.hash.load() {
65+
Some(hash) => Ok(hash),
66+
None => {
67+
let obj = self
68+
.upgrade()
69+
.ok_or_else(|| vm.new_type_error("weak object has gone away".to_owned()))?;
70+
let hash = vm._hash(&obj)?;
71+
self.hash.store(Some(hash));
72+
Ok(hash)
73+
}
74+
}
75+
}
76+
77+
#[pymethod(magic)]
78+
fn eq(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
79+
if let Some(other) = other.payload_if_subclass::<Self>(vm) {
80+
self.upgrade()
81+
.and_then(|s| other.upgrade().map(|o| (s, o)))
82+
.map_or(Ok(false), |(a, b)| vm.bool_eq(a, b))
83+
.map(|b| vm.new_bool(b))
84+
} else {
85+
Ok(vm.ctx.not_implemented())
86+
}
87+
}
88+
89+
#[pymethod(magic)]
90+
fn repr(zelf: PyRef<Self>) -> String {
91+
let id = zelf.get_id();
92+
if let Some(o) = zelf.upgrade() {
93+
format!(
94+
"<weakref at {}; to '{}' at {}>",
95+
id,
96+
o.class().name,
97+
o.get_id(),
98+
)
99+
} else {
100+
format!("<weakref at {}; dead>", id)
101+
}
102+
}
56103
}
57104

58105
pub fn init(context: &PyContext) {

0 commit comments

Comments
 (0)