Skip to content

Commit 6e9e15b

Browse files
authored
Merge pull request RustPython#4885 from youknowone/super-init
super.__init__
2 parents 776bda6 + 2658c5c commit 6e9e15b

File tree

1 file changed

+74
-36
lines changed

1 file changed

+74
-36
lines changed

vm/src/builtins/super.rs

Lines changed: 74 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,74 @@ See also [CPython source code.](https://github.com/python/cpython/blob/50b48572d
66
use super::{PyStr, PyType, PyTypeRef};
77
use crate::{
88
class::PyClassImpl,
9-
function::{IntoFuncArgs, OptionalArg},
10-
types::{Callable, Constructor, GetAttr, GetDescriptor, Representable},
11-
AsObject, Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
9+
common::lock::PyRwLock,
10+
function::{FuncArgs, IntoFuncArgs, OptionalArg},
11+
types::{Callable, Constructor, GetAttr, GetDescriptor, Initializer, Representable},
12+
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
1213
};
1314

1415
#[pyclass(module = false, name = "super", traverse)]
1516
#[derive(Debug)]
1617
pub struct PySuper {
18+
inner: PyRwLock<PySuperInner>,
19+
}
20+
21+
#[derive(Debug, Traverse)]
22+
struct PySuperInner {
1723
typ: PyTypeRef,
1824
obj: Option<(PyObjectRef, PyTypeRef)>,
1925
}
2026

27+
impl PySuperInner {
28+
fn new(typ: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
29+
let obj = if vm.is_none(&obj) {
30+
None
31+
} else {
32+
let obj_type = supercheck(typ.clone(), obj.clone(), vm)?;
33+
Some((obj, obj_type))
34+
};
35+
Ok(Self { typ, obj })
36+
}
37+
}
38+
2139
impl PyPayload for PySuper {
2240
fn class(ctx: &Context) -> &'static Py<PyType> {
2341
ctx.types.super_type
2442
}
2543
}
2644

27-
#[derive(FromArgs, Traverse)]
28-
pub struct PySuperNewArgs {
45+
impl Constructor for PySuper {
46+
type Args = FuncArgs;
47+
48+
fn py_new(cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
49+
let obj = PySuper {
50+
inner: PyRwLock::new(PySuperInner::new(
51+
vm.ctx.types.object_type.to_owned(), // is this correct?
52+
vm.ctx.none(),
53+
vm,
54+
)?),
55+
}
56+
.into_ref_with_type(vm, cls)?;
57+
Ok(obj.into())
58+
}
59+
}
60+
61+
#[derive(FromArgs)]
62+
pub struct InitArgs {
2963
#[pyarg(positional, optional)]
3064
py_type: OptionalArg<PyTypeRef>,
3165
#[pyarg(positional, optional)]
3266
py_obj: OptionalArg<PyObjectRef>,
3367
}
3468

35-
impl Constructor for PySuper {
36-
type Args = PySuperNewArgs;
69+
impl Initializer for PySuper {
70+
type Args = InitArgs;
3771

38-
fn py_new(
39-
cls: PyTypeRef,
72+
fn init(
73+
zelf: PyRef<Self>,
4074
Self::Args { py_type, py_obj }: Self::Args,
4175
vm: &VirtualMachine,
42-
) -> PyResult {
76+
) -> PyResult<()> {
4377
// Get the type:
4478
let (typ, obj) = if let OptionalArg::Present(ty) = py_type {
4579
(ty, py_obj.unwrap_or_none(vm))
@@ -91,44 +125,36 @@ impl Constructor for PySuper {
91125
(typ, obj)
92126
};
93127

94-
PySuper::new(typ, obj, vm)?
95-
.into_ref_with_type(vm, cls)
96-
.map(Into::into)
128+
let mut inner = PySuperInner::new(typ, obj, vm)?;
129+
std::mem::swap(&mut inner, &mut zelf.inner.write());
130+
131+
Ok(())
97132
}
98133
}
99134

100-
#[pyclass(with(GetAttr, GetDescriptor, Constructor, Representable))]
135+
#[pyclass(with(GetAttr, GetDescriptor, Constructor, Initializer, Representable))]
101136
impl PySuper {
102-
fn new(typ: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
103-
let obj = if vm.is_none(&obj) {
104-
None
105-
} else {
106-
let obj_type = supercheck(typ.clone(), obj.clone(), vm)?;
107-
Some((obj, obj_type))
108-
};
109-
Ok(Self { typ, obj })
110-
}
111-
112137
#[pygetset(magic)]
113138
fn thisclass(&self) -> PyTypeRef {
114-
self.typ.clone()
139+
self.inner.read().typ.clone()
115140
}
116141

117142
#[pygetset(magic)]
118143
fn self_class(&self) -> Option<PyTypeRef> {
119-
Some(self.obj.as_ref()?.1.clone())
144+
Some(self.inner.read().obj.as_ref()?.1.clone())
120145
}
121146

122147
#[pygetset]
123148
fn __self__(&self) -> Option<PyObjectRef> {
124-
Some(self.obj.as_ref()?.0.clone())
149+
Some(self.inner.read().obj.as_ref()?.0.clone())
125150
}
126151
}
127152

128153
impl GetAttr for PySuper {
129154
fn getattro(zelf: &Py<Self>, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
130155
let skip = |zelf: &Py<Self>, name| zelf.as_object().generic_getattr(name, vm);
131-
let (obj, start_type): (PyObjectRef, PyTypeRef) = match zelf.obj.clone() {
156+
let obj = zelf.inner.read().obj.clone();
157+
let (obj, start_type): (PyObjectRef, PyTypeRef) = match obj {
132158
Some(o) => o,
133159
None => return skip(zelf, name),
134160
};
@@ -143,7 +169,7 @@ impl GetAttr for PySuper {
143169
// skip the classes in start_type.mro up to and including zelf.typ
144170
let mro: Vec<_> = start_type
145171
.iter_mro()
146-
.skip_while(|cls| !cls.is(&zelf.typ))
172+
.skip_while(|cls| !cls.is(&zelf.inner.read().typ))
147173
.skip(1) // skip su->type (if any)
148174
.collect();
149175
for cls in mro {
@@ -171,26 +197,38 @@ impl GetDescriptor for PySuper {
171197
vm: &VirtualMachine,
172198
) -> PyResult {
173199
let (zelf, obj) = Self::_unwrap(&zelf_obj, obj, vm)?;
174-
if vm.is_none(&obj) || zelf.obj.is_some() {
200+
if vm.is_none(&obj) || zelf.inner.read().obj.is_some() {
175201
return Ok(zelf_obj);
176202
}
177203
let zelf_class = zelf.as_object().class();
178204
if zelf_class.is(vm.ctx.types.super_type) {
179-
Ok(PySuper::new(zelf.typ.clone(), obj, vm)?.into_pyobject(vm))
205+
let typ = zelf.inner.read().typ.clone();
206+
Ok(PySuper {
207+
inner: PyRwLock::new(PySuperInner::new(typ, obj, vm)?),
208+
}
209+
.into_ref(&vm.ctx)
210+
.into())
180211
} else {
181-
let obj = vm.unwrap_or_none(zelf.obj.clone().map(|(o, _)| o));
182-
PyType::call(zelf.class(), (zelf.typ.clone(), obj).into_args(vm), vm)
212+
let (obj, typ) = {
213+
let lock = zelf.inner.read();
214+
let obj = lock.obj.as_ref().map(|(o, _)| o.to_owned());
215+
let typ = lock.typ.clone();
216+
(obj, typ)
217+
};
218+
let obj = vm.unwrap_or_none(obj);
219+
PyType::call(zelf.class(), (typ, obj).into_args(vm), vm)
183220
}
184221
}
185222
}
186223

187224
impl Representable for PySuper {
188225
#[inline]
189226
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
190-
let type_name = &zelf.typ.name();
191-
let repr = match zelf.obj {
227+
let type_name = zelf.inner.read().typ.name().to_owned();
228+
let obj = zelf.inner.read().obj.clone();
229+
let repr = match obj {
192230
Some((_, ref ty)) => {
193-
format!("<super: <class '{}'>, <{} object>>", type_name, ty.name())
231+
format!("<super: <class '{}'>, <{} object>>", &type_name, ty.name())
194232
}
195233
None => format!("<super: <class '{type_name}'>, NULL>"),
196234
};

0 commit comments

Comments
 (0)