rustpython_vm/function/
getset.rs

1/*! Python `attribute` descriptor class. (PyGetSet)
2
3*/
4use crate::{
5    convert::ToPyResult,
6    function::{BorrowedParam, OwnedParam, RefParam},
7    object::PyThreadingConstraint,
8    Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
9};
10
11#[derive(result_like::OptionLike, is_macro::Is, Debug)]
12pub enum PySetterValue<T = PyObjectRef> {
13    Assign(T),
14    Delete,
15}
16
17impl 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
26trait FromPySetterValue
27where
28    Self: Sized,
29{
30    fn from_setter_value(vm: &VirtualMachine, obj: PySetterValue) -> PyResult<Self>;
31}
32
33impl<T> FromPySetterValue for T
34where
35    T: Sized + TryFromObject,
36{
37    #[inline]
38    fn from_setter_value(vm: &VirtualMachine, obj: PySetterValue) -> PyResult<Self> {
39        let obj = obj.ok_or_else(|| vm.new_type_error("can't delete attribute".to_owned()))?;
40        T::try_from_object(vm, obj)
41    }
42}
43
44impl<T> FromPySetterValue for PySetterValue<T>
45where
46    T: Sized + TryFromObject,
47{
48    #[inline]
49    fn from_setter_value(vm: &VirtualMachine, obj: PySetterValue) -> PyResult<Self> {
50        obj.map(|obj| T::try_from_object(vm, obj)).transpose()
51    }
52}
53
54pub type PyGetterFunc = Box<py_dyn_fn!(dyn Fn(&VirtualMachine, PyObjectRef) -> PyResult)>;
55pub type PySetterFunc =
56    Box<py_dyn_fn!(dyn Fn(&VirtualMachine, PyObjectRef, PySetterValue) -> PyResult<()>)>;
57
58pub trait IntoPyGetterFunc<T>: PyThreadingConstraint + Sized + 'static {
59    fn get(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult;
60    fn into_getter(self) -> PyGetterFunc {
61        Box::new(move |vm, obj| self.get(obj, vm))
62    }
63}
64
65impl<F, T, R> IntoPyGetterFunc<(OwnedParam<T>, R, VirtualMachine)> for F
66where
67    F: Fn(T, &VirtualMachine) -> R + 'static + Send + Sync,
68    T: TryFromObject,
69    R: ToPyResult,
70{
71    fn get(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
72        let obj = T::try_from_object(vm, obj)?;
73        (self)(obj, vm).to_pyresult(vm)
74    }
75}
76
77impl<F, S, R> IntoPyGetterFunc<(BorrowedParam<S>, R, VirtualMachine)> for F
78where
79    F: Fn(&Py<S>, &VirtualMachine) -> R + 'static + Send + Sync,
80    S: PyPayload,
81    R: ToPyResult,
82{
83    fn get(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
84        let zelf = PyRef::<S>::try_from_object(vm, obj)?;
85        (self)(&zelf, vm).to_pyresult(vm)
86    }
87}
88
89impl<F, S, R> IntoPyGetterFunc<(RefParam<S>, R, VirtualMachine)> for F
90where
91    F: Fn(&S, &VirtualMachine) -> R + 'static + Send + Sync,
92    S: PyPayload,
93    R: ToPyResult,
94{
95    fn get(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
96        let zelf = PyRef::<S>::try_from_object(vm, obj)?;
97        (self)(&zelf, vm).to_pyresult(vm)
98    }
99}
100
101impl<F, T, R> IntoPyGetterFunc<(OwnedParam<T>, R)> for F
102where
103    F: Fn(T) -> R + 'static + Send + Sync,
104    T: TryFromObject,
105    R: ToPyResult,
106{
107    fn get(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
108        let obj = T::try_from_object(vm, obj)?;
109        (self)(obj).to_pyresult(vm)
110    }
111}
112
113impl<F, S, R> IntoPyGetterFunc<(BorrowedParam<S>, R)> for F
114where
115    F: Fn(&Py<S>) -> R + 'static + Send + Sync,
116    S: PyPayload,
117    R: ToPyResult,
118{
119    fn get(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
120        let zelf = PyRef::<S>::try_from_object(vm, obj)?;
121        (self)(&zelf).to_pyresult(vm)
122    }
123}
124
125impl<F, S, R> IntoPyGetterFunc<(RefParam<S>, R)> for F
126where
127    F: Fn(&S) -> R + 'static + Send + Sync,
128    S: PyPayload,
129    R: ToPyResult,
130{
131    fn get(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
132        let zelf = PyRef::<S>::try_from_object(vm, obj)?;
133        (self)(&zelf).to_pyresult(vm)
134    }
135}
136
137pub trait IntoPyNoResult {
138    fn into_noresult(self) -> PyResult<()>;
139}
140
141impl IntoPyNoResult for () {
142    #[inline]
143    fn into_noresult(self) -> PyResult<()> {
144        Ok(())
145    }
146}
147
148impl IntoPyNoResult for PyResult<()> {
149    #[inline]
150    fn into_noresult(self) -> PyResult<()> {
151        self
152    }
153}
154
155pub trait IntoPySetterFunc<T>: PyThreadingConstraint + Sized + 'static {
156    fn set(&self, obj: PyObjectRef, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()>;
157    fn into_setter(self) -> PySetterFunc {
158        Box::new(move |vm, obj, value| self.set(obj, value, vm))
159    }
160}
161
162impl<F, T, V, R> IntoPySetterFunc<(OwnedParam<T>, V, R, VirtualMachine)> for F
163where
164    F: Fn(T, V, &VirtualMachine) -> R + 'static + Send + Sync,
165    T: TryFromObject,
166    V: FromPySetterValue,
167    R: IntoPyNoResult,
168{
169    fn set(&self, obj: PyObjectRef, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()> {
170        let obj = T::try_from_object(vm, obj)?;
171        let value = V::from_setter_value(vm, value)?;
172        (self)(obj, value, vm).into_noresult()
173    }
174}
175
176impl<F, S, V, R> IntoPySetterFunc<(BorrowedParam<S>, V, R, VirtualMachine)> for F
177where
178    F: Fn(&Py<S>, V, &VirtualMachine) -> R + 'static + Send + Sync,
179    S: PyPayload,
180    V: FromPySetterValue,
181    R: IntoPyNoResult,
182{
183    fn set(&self, obj: PyObjectRef, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()> {
184        let zelf = PyRef::<S>::try_from_object(vm, obj)?;
185        let value = V::from_setter_value(vm, value)?;
186        (self)(&zelf, value, vm).into_noresult()
187    }
188}
189
190impl<F, S, V, R> IntoPySetterFunc<(RefParam<S>, V, R, VirtualMachine)> for F
191where
192    F: Fn(&S, V, &VirtualMachine) -> R + 'static + Send + Sync,
193    S: PyPayload,
194    V: FromPySetterValue,
195    R: IntoPyNoResult,
196{
197    fn set(&self, obj: PyObjectRef, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()> {
198        let zelf = PyRef::<S>::try_from_object(vm, obj)?;
199        let value = V::from_setter_value(vm, value)?;
200        (self)(&zelf, value, vm).into_noresult()
201    }
202}
203
204impl<F, T, V, R> IntoPySetterFunc<(OwnedParam<T>, V, R)> for F
205where
206    F: Fn(T, V) -> R + 'static + Send + Sync,
207    T: TryFromObject,
208    V: FromPySetterValue,
209    R: IntoPyNoResult,
210{
211    fn set(&self, obj: PyObjectRef, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()> {
212        let obj = T::try_from_object(vm, obj)?;
213        let value = V::from_setter_value(vm, value)?;
214        (self)(obj, value).into_noresult()
215    }
216}
217
218impl<F, S, V, R> IntoPySetterFunc<(BorrowedParam<S>, V, R)> for F
219where
220    F: Fn(&Py<S>, V) -> R + 'static + Send + Sync,
221    S: PyPayload,
222    V: FromPySetterValue,
223    R: IntoPyNoResult,
224{
225    fn set(&self, obj: PyObjectRef, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()> {
226        let zelf = PyRef::<S>::try_from_object(vm, obj)?;
227        let value = V::from_setter_value(vm, value)?;
228        (self)(&zelf, value).into_noresult()
229    }
230}
231
232impl<F, S, V, R> IntoPySetterFunc<(RefParam<S>, V, R)> for F
233where
234    F: Fn(&S, V) -> R + 'static + Send + Sync,
235    S: PyPayload,
236    V: FromPySetterValue,
237    R: IntoPyNoResult,
238{
239    fn set(&self, obj: PyObjectRef, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()> {
240        let zelf = PyRef::<S>::try_from_object(vm, obj)?;
241        let value = V::from_setter_value(vm, value)?;
242        (self)(&zelf, value).into_noresult()
243    }
244}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.