Skip to content

Commit a363b05

Browse files
committed
PySetterValue for descr_set and setattro
1 parent 711acaa commit a363b05

15 files changed

Lines changed: 91 additions & 78 deletions

File tree

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_exceptions.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,8 +586,6 @@ def testInvalidTraceback(self):
586586
else:
587587
self.fail("No exception raised")
588588

589-
# TODO: RUSTPYTHON
590-
@unittest.expectedFailure
591589
def testInvalidAttrs(self):
592590
self.assertRaises(TypeError, setattr, Exception(), '__cause__', 1)
593591
self.assertRaises(TypeError, delattr, Exception(), '__cause__')

vm/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ libc = "0.2.126"
5252
nix = "0.23.1"
5353
paste = "1.0.7"
5454
is-macro = "0.2.0"
55-
result-like ="0.4.4"
55+
result-like = "0.4.5"
5656
num_enum = "0.5.7"
5757
bstr = "0.2.17"
5858
crossbeam-utils = "0.8.8"

vm/src/builtins/frame.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
33
*/
44

5-
use super::{PyCode, PyDictRef, PyStrRef};
5+
use super::{PyCode, PyDictRef};
66
use crate::{
77
class::PyClassImpl,
88
frame::{Frame, FrameRef},
9+
function::PySetterValue,
910
types::{Constructor, Unconstructible},
1011
AsObject, Context, PyObjectRef, PyRef, PyResult, VirtualMachine,
1112
};
@@ -25,15 +26,6 @@ impl FrameRef {
2526
"<frame object at .. >".to_owned()
2627
}
2728

28-
#[pymethod(magic)]
29-
fn delattr(self, value: PyStrRef, vm: &VirtualMachine) {
30-
// CPython' Frame.f_trace is set to None when deleted.
31-
// The strange behavior is mimicked here make bdb.py happy about it.
32-
if value.to_string() == "f_trace" {
33-
self.set_f_trace(vm.ctx.none());
34-
};
35-
}
36-
3729
#[pymethod]
3830
fn clear(self) {
3931
// TODO
@@ -86,8 +78,8 @@ impl FrameRef {
8678
}
8779

8880
#[pyproperty(setter)]
89-
fn set_f_trace(self, value: PyObjectRef) {
81+
fn set_f_trace(self, value: PySetterValue, vm: &VirtualMachine) {
9082
let mut storage = self.trace.lock();
91-
*storage = value;
83+
*storage = value.unwrap_or_none(vm);
9284
}
9385
}

vm/src/builtins/getset.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use super::PyType;
55
use crate::{
66
class::PyClassImpl,
7-
function::{IntoPyGetterFunc, IntoPySetterFunc, PyGetterFunc, PySetterFunc},
7+
function::{IntoPyGetterFunc, IntoPySetterFunc, PyGetterFunc, PySetterFunc, PySetterValue},
88
types::{Constructor, GetDescriptor, Unconstructible},
99
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
1010
};
@@ -102,12 +102,12 @@ impl PyGetSet {
102102
fn descr_set(
103103
zelf: PyObjectRef,
104104
obj: PyObjectRef,
105-
value: Option<PyObjectRef>,
105+
value: PySetterValue<PyObjectRef>,
106106
vm: &VirtualMachine,
107107
) -> PyResult<()> {
108108
let zelf = PyRef::<Self>::try_from_object(vm, zelf)?;
109109
if let Some(ref f) = zelf.setter {
110-
f(vm, obj, value.into())
110+
f(vm, obj, value)
111111
} else {
112112
Err(vm.new_attribute_error(format!(
113113
"attribute '{}' of '{}' objects is not writable",
@@ -123,11 +123,11 @@ impl PyGetSet {
123123
value: PyObjectRef,
124124
vm: &VirtualMachine,
125125
) -> PyResult<()> {
126-
Self::descr_set(zelf, obj, Some(value), vm)
126+
Self::descr_set(zelf, obj, PySetterValue::Assign(value), vm)
127127
}
128128
#[pymethod]
129129
fn __delete__(zelf: PyObjectRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
130-
Self::descr_set(zelf, obj, None, vm)
130+
Self::descr_set(zelf, obj, PySetterValue::Delete, vm)
131131
}
132132

133133
#[pyproperty(magic)]

vm/src/builtins/object.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ use super::{PyDict, PyDictRef, PyList, PyStr, PyStrRef, PyType, PyTypeRef};
22
use crate::common::hash::PyHash;
33
use crate::{
44
class::PyClassImpl,
5-
function::Either,
6-
function::{FuncArgs, PyArithmeticValue, PyComparisonValue},
5+
function::{Either, FuncArgs, PyArithmeticValue, PyComparisonValue, PySetterValue},
76
types::PyComparisonOp,
87
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
98
};
@@ -162,20 +161,20 @@ impl PyBaseObject {
162161
value: PyObjectRef,
163162
vm: &VirtualMachine,
164163
) -> PyResult<()> {
165-
obj.generic_setattr(name, Some(value), vm)
164+
obj.generic_setattr(name, PySetterValue::Assign(value), vm)
166165
}
167166

168167
/// Implement delattr(self, name).
169168
#[pymethod]
170169
fn __delattr__(obj: PyObjectRef, name: PyStrRef, vm: &VirtualMachine) -> PyResult<()> {
171-
obj.generic_setattr(name, None, vm)
170+
obj.generic_setattr(name, PySetterValue::Delete, vm)
172171
}
173172

174173
#[pyslot]
175174
fn slot_setattro(
176175
obj: &PyObject,
177176
attr_name: PyStrRef,
178-
value: Option<PyObjectRef>,
177+
value: PySetterValue,
179178
vm: &VirtualMachine,
180179
) -> PyResult<()> {
181180
obj.generic_setattr(attr_name, value, vm)

vm/src/builtins/property.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::{PyType, PyTypeRef};
55
use crate::common::lock::PyRwLock;
66
use crate::{
77
class::PyClassImpl,
8-
function::FuncArgs,
8+
function::{FuncArgs, PySetterValue},
99
types::{Constructor, GetDescriptor, Initializer},
1010
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
1111
};
@@ -95,19 +95,19 @@ impl PyProperty {
9595
fn descr_set(
9696
zelf: PyObjectRef,
9797
obj: PyObjectRef,
98-
value: Option<PyObjectRef>,
98+
value: PySetterValue,
9999
vm: &VirtualMachine,
100100
) -> PyResult<()> {
101101
let zelf = PyRef::<Self>::try_from_object(vm, zelf)?;
102102
match value {
103-
Some(value) => {
103+
PySetterValue::Assign(value) => {
104104
if let Some(setter) = zelf.setter.read().as_ref() {
105105
vm.invoke(setter, (obj, value)).map(drop)
106106
} else {
107107
Err(vm.new_attribute_error("can't set attribute".to_owned()))
108108
}
109109
}
110-
None => {
110+
PySetterValue::Delete => {
111111
if let Some(deleter) = zelf.deleter.read().as_ref() {
112112
vm.invoke(deleter, (obj,)).map(drop)
113113
} else {
@@ -123,11 +123,11 @@ impl PyProperty {
123123
value: PyObjectRef,
124124
vm: &VirtualMachine,
125125
) -> PyResult<()> {
126-
Self::descr_set(zelf, obj, Some(value), vm)
126+
Self::descr_set(zelf, obj, PySetterValue::Assign(value), vm)
127127
}
128128
#[pymethod]
129129
fn __delete__(zelf: PyObjectRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
130-
Self::descr_set(zelf, obj, None, vm)
130+
Self::descr_set(zelf, obj, PySetterValue::Delete, vm)
131131
}
132132

133133
// Access functions

vm/src/builtins/type.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::common::{
1010
use crate::{
1111
builtins::PyBaseExceptionRef,
1212
class::{PyClassImpl, StaticType},
13-
function::{FuncArgs, KwArgs, OptionalArg},
13+
function::{FuncArgs, KwArgs, OptionalArg, PySetterValue},
1414
identifier,
1515
protocol::PyNumberMethods,
1616
types::{Callable, GetAttr, PyTypeFlags, PyTypeSlots, SetAttr},
@@ -757,7 +757,7 @@ impl SetAttr for PyType {
757757
fn setattro(
758758
zelf: &crate::Py<Self>,
759759
attr_name: PyStrRef,
760-
value: Option<PyObjectRef>,
760+
value: PySetterValue,
761761
vm: &VirtualMachine,
762762
) -> PyResult<()> {
763763
// TODO: pass PyRefExact instead of &str
@@ -768,10 +768,10 @@ impl SetAttr for PyType {
768768
return descriptor(attr, zelf.to_owned().into(), value, vm);
769769
}
770770
}
771-
let assign = value.is_some();
771+
let assign = value.is_assign();
772772

773773
let mut attributes = zelf.attributes.write();
774-
if let Some(value) = value {
774+
if let PySetterValue::Assign(value) = value {
775775
attributes.insert(attr_name, value);
776776
} else {
777777
let prev_value = attributes.remove(attr_name);
@@ -848,7 +848,7 @@ fn subtype_set_dict(obj: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -
848848
cls.name()
849849
))
850850
})?;
851-
descr_set(descr, obj, Some(value), vm)
851+
descr_set(descr, obj, PySetterValue::Assign(value), vm)
852852
}
853853
None => {
854854
object::object_set_dict(obj, value.try_into_value(vm)?, vm)?;

vm/src/builtins/weakproxy.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::{PyStrRef, PyType, PyTypeRef, PyWeak};
22
use crate::{
33
class::PyClassImpl,
4-
function::{OptionalArg, PyComparisonValue},
4+
function::{OptionalArg, PyComparisonValue, PySetterValue},
55
protocol::{PyMappingMethods, PySequence, PySequenceMethods},
66
types::{AsMapping, AsSequence, Comparable, Constructor, GetAttr, PyComparisonOp, SetAttr},
77
Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
@@ -134,7 +134,7 @@ impl SetAttr for PyWeakProxy {
134134
fn setattro(
135135
zelf: &crate::Py<Self>,
136136
attr_name: PyStrRef,
137-
value: Option<PyObjectRef>,
137+
value: PySetterValue,
138138
vm: &VirtualMachine,
139139
) -> PyResult<()> {
140140
let obj = zelf.try_upgrade(vm)?;

vm/src/function/getset.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,21 @@ use crate::{
88
PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
99
};
1010

11-
#[derive(result_like::OptionLike)]
11+
#[derive(result_like::OptionLike, is_macro::Is)]
1212
pub enum PySetterValue<T = PyObjectRef> {
1313
Assign(T),
1414
Delete,
1515
}
1616

17+
impl PySetterValue {
18+
pub fn unwrap_or_none(self, vm: &VirtualMachine) -> PyObjectRef {
19+
match self {
20+
Self::Assign(value) => value,
21+
Self::Delete => vm.ctx.none(),
22+
}
23+
}
24+
}
25+
1726
trait FromPySetterValue
1827
where
1928
Self: Sized,
@@ -25,6 +34,7 @@ impl<T> FromPySetterValue for T
2534
where
2635
T: Sized + TryFromObject,
2736
{
37+
#[inline]
2838
fn from_setter_value(vm: &VirtualMachine, obj: PySetterValue) -> PyResult<Self> {
2939
let obj = obj.ok_or_else(|| vm.new_type_error("can't delete attribute".to_owned()))?;
3040
T::try_from_object(vm, obj)
@@ -35,8 +45,9 @@ impl<T> FromPySetterValue for PySetterValue<T>
3545
where
3646
T: Sized + TryFromObject,
3747
{
48+
#[inline]
3849
fn from_setter_value(vm: &VirtualMachine, obj: PySetterValue) -> PyResult<Self> {
39-
Ok(obj.map(|obj| T::try_from_object(vm, obj)).transpose()?)
50+
obj.map(|obj| T::try_from_object(vm, obj)).transpose()
4051
}
4152
}
4253

0 commit comments

Comments
 (0)