Skip to content

Commit d964098

Browse files
committed
Implemented the ability to del __dict__
This PR is based on the work by key262yek. Signed-off-by: Hanif Ariffin <[email protected]>
1 parent 73ed9c0 commit d964098

File tree

4 files changed

+26
-14
lines changed

4 files changed

+26
-14
lines changed

vm/src/builtins/object.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ pub fn object_set_dict(
502502
vm: &VirtualMachine,
503503
) -> PyResult<()> {
504504
obj.set_dict(dict)
505-
.map_err(|_| vm.new_attribute_error("This object has no __dict__ to delete".to_owned()))
505+
.ok_or_else(|| vm.new_type_error("cannot delete __dict__".to_owned()))
506506
}
507507

508508
pub fn init(ctx: &Context) {

vm/src/builtins/type.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,7 +1272,11 @@ fn subtype_get_dict(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
12721272
Ok(ret)
12731273
}
12741274

1275-
fn subtype_set_dict(obj: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
1275+
fn subtype_set_dict(
1276+
obj: PyObjectRef,
1277+
value: PySetterValue<PyObjectRef>,
1278+
vm: &VirtualMachine,
1279+
) -> PyResult<()> {
12761280
let cls = obj.class();
12771281
match find_base_dict_descr(cls, vm) {
12781282
Some(descr) => {
@@ -1285,10 +1289,11 @@ fn subtype_set_dict(obj: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -
12851289
cls.name()
12861290
))
12871291
})?;
1288-
descr_set(&descr, obj, PySetterValue::Assign(value), vm)
1292+
descr_set(&descr, obj, value, vm)
12891293
}
12901294
None => {
1291-
object::object_set_dict(obj, PySetterValue::Assign(value.try_into_value(vm)?), vm)?;
1295+
let dict = value.map(|s| s.try_into_value(vm)).transpose()?;
1296+
object::object_set_dict(obj, dict, vm)?;
12921297
Ok(())
12931298
}
12941299
}

vm/src/function/getset.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,8 @@ where
3636
{
3737
#[inline]
3838
fn from_setter_value(vm: &VirtualMachine, obj: PySetterValue) -> PyResult<Self> {
39-
match obj {
40-
PySetterValue::Assign(obj) => T::try_from_object(vm, obj),
41-
PySetterValue::Delete => T::try_from_object(vm, vm.ctx.none()),
42-
}
39+
let obj = obj.ok_or_else(|| vm.new_type_error("can't delete attribute".to_owned()))?;
40+
T::try_from_object(vm, obj)
4341
}
4442
}
4543

vm/src/object/core.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -712,28 +712,37 @@ impl PyObject {
712712

713713
/// Set the dict field. Returns `Err(dict)` if this object does not have a dict field
714714
/// in the first place.
715-
pub fn set_dict(&self, dict: PySetterValue<PyDictRef>) -> Result<(), PySetterValue<PyDictRef>> {
715+
pub fn set_dict(&self, dict: PySetterValue<PyDictRef>) -> Option<()> {
716+
// NOTE(hanif) - So far, this is the only error condition that I know of so we can use Option
717+
// for now.
718+
if self.payload_is::<crate::builtins::function::PyFunction>() {
719+
return None;
720+
}
721+
716722
match (self.instance_dict(), dict) {
717723
(Some(d), PySetterValue::Assign(dict)) => {
718724
d.set(dict);
719-
Ok(())
720725
}
721726
(None, PySetterValue::Assign(dict)) => {
727+
// self.0.dict = Some(InstanceDict::new(dict));
722728
unsafe {
723729
let ptr = self as *const _ as *mut PyObject;
724730
(*ptr).0.dict = Some(InstanceDict::new(dict));
725731
}
726-
Ok(())
727732
}
728733
(Some(_), PySetterValue::Delete) => {
734+
// self.0.dict = None;
729735
unsafe {
730736
let ptr = self as *const _ as *mut PyObject;
731737
(*ptr).0.dict = None;
732738
}
733-
Ok(())
734739
}
735-
(None, PySetterValue::Delete) => Err(PySetterValue::Delete),
736-
}
740+
(None, PySetterValue::Delete) => {
741+
// NOTE(hanif) - noop?
742+
}
743+
};
744+
745+
Some(())
737746
}
738747

739748
#[inline(always)]

0 commit comments

Comments
 (0)