Skip to content

Commit e5c92d6

Browse files
Merge pull request #1496 from rls1004/issue1404
Implement delattr for type object
2 parents cc76649 + 37a3b2c commit e5c92d6

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

tests/snippets/attr.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,21 @@
44
class A:
55
pass
66

7+
class B:
8+
x = 50
79

810
a = A()
911
a.b = 10
1012
assert hasattr(a, 'b')
1113
assert a.b == 10
1214

15+
assert B.x == 50
16+
17+
# test delete class attribute with del keyword
18+
del B.x
19+
with assert_raises(AttributeError):
20+
_ = B.x
21+
1322
# test override attribute
1423
setattr(a, 'b', 12)
1524
assert a.b == 12

vm/src/obj/objtype.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,23 @@ impl PyClassRef {
199199
Ok(())
200200
}
201201

202+
fn del_attr(self, attr_name: PyStringRef, vm: &VirtualMachine) -> PyResult<()> {
203+
if let Some(attr) = class_get_attr(&self.class(), attr_name.as_str()) {
204+
if let Some(ref descriptor) = class_get_attr(&attr.class(), "__delete__") {
205+
return vm
206+
.invoke(descriptor, vec![attr, self.into_object()])
207+
.map(|_| ());
208+
}
209+
}
210+
211+
if class_get_attr(&self, attr_name.as_str()).is_some() {
212+
self.attributes.borrow_mut().remove(attr_name.as_str());
213+
Ok(())
214+
} else {
215+
Err(vm.new_attribute_error(attr_name.as_str().to_string()))
216+
}
217+
}
218+
202219
// This is used for class initialisation where the vm is not yet available.
203220
pub fn set_str_attr<V: Into<PyObjectRef>>(&self, attr_name: &str, value: V) {
204221
self.attributes
@@ -255,8 +272,8 @@ pub fn init(ctx: &PyContext) {
255272
"__prepare__" => ctx.new_rustfunc(PyClassRef::prepare),
256273
"__getattribute__" => ctx.new_rustfunc(PyClassRef::getattribute),
257274
"__setattr__" => ctx.new_rustfunc(PyClassRef::set_attr),
275+
"__delattr__" => ctx.new_rustfunc(PyClassRef::del_attr),
258276
"__subclasses__" => ctx.new_rustfunc(PyClassRef::subclasses),
259-
"__getattribute__" => ctx.new_rustfunc(PyClassRef::getattribute),
260277
"__instancecheck__" => ctx.new_rustfunc(PyClassRef::instance_check),
261278
"__subclasscheck__" => ctx.new_rustfunc(PyClassRef::subclass_check),
262279
"__doc__" => ctx.new_str(type_doc.to_string()),

0 commit comments

Comments
 (0)