Add PyTypSlot::init

This commit is contained in:
Jeong YunWon
2021-11-27 20:15:38 +09:00
committed by Jeong Yunwon
parent a19efa21ce
commit 88080505e4
17 changed files with 118 additions and 76 deletions

View File

@@ -381,9 +381,10 @@ pub(crate) fn impl_define_exception(exc_def: PyExceptionDef) -> Result<TokenStre
#slot_new_impl
}
#[pyslot]
#[pymethod(magic)]
pub(crate) fn init(
zelf: ::rustpython_vm::PyRef<::rustpython_vm::builtins::PyBaseException>,
zelf: PyObjectRef,
args: ::rustpython_vm::function::FuncArgs,
vm: &::rustpython_vm::VirtualMachine,
) -> ::rustpython_vm::PyResult<()> {

View File

@@ -15,8 +15,10 @@ mod _contextvars {
#[pyimpl]
impl PyContext {
#[pyslot]
#[pymethod(magic)]
fn init(&self, _vm: &VirtualMachine) -> PyResult<()> {
fn init(zelf: PyObjectRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let _zelf: PyRef<Self> = zelf.try_into_value(vm)?;
unimplemented!("Context.__init__ is currently under construction")
}
@@ -97,8 +99,10 @@ mod _contextvars {
#[pyimpl]
impl ContextVar {
#[pyslot]
#[pymethod(magic)]
fn init(&self, _args: ContextVarOptions, _vm: &VirtualMachine) -> PyResult<()> {
fn init(_zelf: PyObjectRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let _: ContextVarOptions = _args.bind(vm)?;
unimplemented!("ContextVar.__init__() is currently under construction")
}
@@ -167,8 +171,10 @@ mod _contextvars {
#[pyimpl]
impl ContextToken {
#[pyslot]
#[pymethod(magic)]
fn init(&self, _args: ContextTokenOptions, _vm: &VirtualMachine) -> PyResult<()> {
fn init(_zelf: PyObjectRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let _: ContextTokenOptions = _args.bind(vm)?;
unimplemented!("Token.__init__() is currently under construction")
}

View File

@@ -16,7 +16,7 @@ mod _socket {
convert::{ToPyException, ToPyObject, TryFromBorrowedObject, TryFromObject},
function::{ArgBytesLike, ArgMemoryBuffer, Either, FuncArgs, OptionalArg, OptionalOption},
utils::ToCString,
AsObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
AsObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use crossbeam_utils::atomic::AtomicCell;
use num_traits::ToPrimitive;
@@ -548,15 +548,16 @@ mod _socket {
Self::default().into_ref_with_type(vm, cls).map(Into::into)
}
#[pyslot]
#[pymethod(magic)]
fn init(
&self,
family: OptionalArg<i32>,
socket_kind: OptionalArg<i32>,
proto: OptionalArg<i32>,
fileno: OptionalOption<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult<()> {
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let (family, socket_kind, proto, fileno): (
OptionalArg<i32>,
OptionalArg<i32>,
OptionalArg<i32>,
OptionalOption<PyObjectRef>,
) = args.bind(vm)?;
let mut family = family.unwrap_or(-1);
let mut socket_kind = socket_kind.unwrap_or(-1);
let mut proto = proto.unwrap_or(-1);
@@ -628,7 +629,7 @@ mod _socket {
)
.map_err(|err| err.to_pyexception(vm))?;
};
self.init_inner(family, socket_kind, proto, sock, vm)
zelf.init_inner(family, socket_kind, proto, sock, vm)
}
#[pymethod]

View File

@@ -105,11 +105,14 @@ impl PyByteArray {
.map(Into::into)
}
#[pyslot]
#[pymethod(magic)]
fn init(&self, options: ByteInnerNewOptions, vm: &VirtualMachine) -> PyResult<()> {
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let options: ByteInnerNewOptions = args.bind(vm)?;
// First unpack bytearray and *then* get a lock to set it.
let mut inner = options.get_bytearray_inner(vm)?;
std::mem::swap(&mut *self.inner_mut(), &mut inner);
std::mem::swap(&mut *zelf.inner_mut(), &mut inner);
Ok(())
}

View File

@@ -88,14 +88,12 @@ impl PyDict {
.map(Into::into)
}
#[pyslot]
#[pymethod(magic)]
fn init(
&self,
dict_obj: OptionalArg<PyObjectRef>,
kwargs: KwArgs,
vm: &VirtualMachine,
) -> PyResult<()> {
self.update(dict_obj, kwargs, vm)
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let (dict_obj, kwargs): (OptionalArg<PyObjectRef>, KwArgs) = args.bind(vm)?;
zelf.update(dict_obj, kwargs, vm)
}
// Used in update and ior.

View File

@@ -345,14 +345,17 @@ impl PyList {
.map(Into::into)
}
#[pyslot]
#[pymethod(magic)]
fn init(&self, iterable: OptionalArg<PyObjectRef>, vm: &VirtualMachine) -> PyResult<()> {
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let iterable: OptionalArg<PyObjectRef> = args.bind(vm)?;
let mut elements = if let OptionalArg::Present(iterable) = iterable {
iterable.try_to_value(vm)?
} else {
vec![]
};
std::mem::swap(self.borrow_vec_mut().deref_mut(), &mut elements);
std::mem::swap(zelf.borrow_vec_mut().deref_mut(), &mut elements);
Ok(())
}

View File

@@ -38,14 +38,18 @@ impl PyModule {
PyModule {}.into_ref_with_type(vm, cls).map(Into::into)
}
#[pyslot]
#[pymethod(magic)]
fn init(zelf: PyRef<Self>, args: ModuleInitArgs, vm: &VirtualMachine) {
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let args: ModuleInitArgs = args.bind(vm)?;
debug_assert!(zelf
.class()
.slots
.flags
.has_feature(crate::types::PyTypeFlags::HAS_DICT));
zelf.init_module_dict(args.name.into(), args.doc.to_pyobject(vm), vm);
Ok(())
}
fn getattr_inner(zelf: &Py<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult {

View File

@@ -5,7 +5,7 @@ use crate::{
function::{FuncArgs, PyComparisonValue},
recursion::ReprGuard,
types::{Comparable, Constructor, PyComparisonOp},
AsObject, Context, PyObject, PyPayload, PyRef, PyResult, VirtualMachine,
AsObject, Context, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
/// A simple attribute-based namespace.
@@ -41,8 +41,10 @@ impl PyNamespace {
#[pyimpl(flags(BASETYPE, HAS_DICT), with(Constructor, Comparable))]
impl PyNamespace {
#[pyslot]
#[pymethod(magic)]
fn init(zelf: PyRef<Self>, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
if !args.args.is_empty() {
return Err(vm.new_type_error("no positional arguments expected".to_owned()));
}

View File

@@ -250,8 +250,11 @@ impl PyBaseObject {
}
}
#[pyslot]
#[pymethod(magic)]
fn init(_args: FuncArgs) {}
fn init(_zelf: PyObjectRef, _args: FuncArgs, _vm: &VirtualMachine) -> PyResult<()> {
Ok(())
}
#[pyproperty(name = "__class__")]
fn get_class(obj: PyObjectRef) -> PyTypeRef {

View File

@@ -99,12 +99,18 @@ impl PyProperty {
.map(Into::into)
}
#[pyslot]
#[pymethod(magic)]
fn init(&self, args: PropertyArgs) {
*self.getter.write() = args.fget;
*self.setter.write() = args.fset;
*self.deleter.write() = args.fdel;
*self.doc.write() = args.doc;
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let args: PropertyArgs = args.bind(vm)?;
*zelf.getter.write() = args.fget;
*zelf.setter.write() = args.fset;
*zelf.deleter.write() = args.fdel;
*zelf.doc.write() = args.doc;
Ok(())
}
// Descriptor methods

View File

@@ -401,13 +401,16 @@ impl PySet {
PySet::default().into_ref_with_type(vm, cls).map(Into::into)
}
#[pyslot]
#[pymethod(magic)]
fn init(&self, iterable: OptionalArg<ArgIterable>, vm: &VirtualMachine) -> PyResult<()> {
if self.len() > 0 {
self.clear();
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let iterable: OptionalArg<ArgIterable> = args.bind(vm)?;
if zelf.len() > 0 {
zelf.clear();
}
if let OptionalArg::Present(it) = iterable {
self.update(PosArgs::new(vec![it]), vm)?;
zelf.update(PosArgs::new(vec![it]), vm)?;
}
Ok(())
}

View File

@@ -719,12 +719,8 @@ impl Callable for PyType {
return Ok(obj);
}
if let Some(init_method_or_err) = vm.get_method(obj.clone(), "__init__") {
let init_method = init_method_or_err?;
let res = vm.invoke(&init_method, args)?;
if !vm.is_none(&res) {
return Err(vm.new_type_error("__init__ must return None".to_owned()));
}
if let Some(init_method) = obj.class().mro_find_map(|cls| cls.slots.init.load()) {
init_method(obj.clone(), args, vm)?;
}
Ok(obj)
}

View File

@@ -431,8 +431,10 @@ impl PyBaseException {
.map(Into::into)
}
#[pyslot]
#[pymethod(magic)]
pub(crate) fn init(zelf: PyRef<Self>, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
pub(crate) fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
*zelf.args.write() = PyTuple::new_ref(args.args, &vm.ctx);
Ok(())
}
@@ -1160,12 +1162,7 @@ pub(super) mod types {
PyBaseException::slot_new(cls, args, vm)
}
fn import_error_init(
zelf: PyRef<PyBaseException>,
args: FuncArgs,
vm: &VirtualMachine,
) -> PyResult<()> {
let zelf: PyObjectRef = zelf.into();
fn import_error_init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
zelf.set_attr(
"name",
vm.unwrap_or_none(args.kwargs.get("name").cloned()),
@@ -1270,11 +1267,7 @@ pub(super) mod types {
PyBaseException::slot_new(cls, args, vm)
}
fn base_exception_init(
zelf: PyRef<PyBaseException>,
args: FuncArgs,
vm: &VirtualMachine,
) -> PyResult<()> {
fn base_exception_init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
PyBaseException::init(zelf, args, vm)
}

View File

@@ -31,10 +31,10 @@ mod _ast {
#[pyimpl(flags(BASETYPE, HAS_DICT))]
impl AstNode {
#[pyslot]
#[pymethod(magic)]
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let obj: PyObjectRef = zelf.class().clone().into();
let fields = obj.get_attr("_fields", vm)?;
let fields = zelf.clone().get_attr("_fields", vm)?;
let fields: Vec<PyStrRef> = fields.try_to_value(vm)?;
let numargs = args.args.len();
if numargs > fields.len() {

View File

@@ -63,12 +63,12 @@ mod _collections {
.map(Into::into)
}
#[pyslot]
#[pymethod(magic)]
fn init(
zelf: PyRef<Self>,
PyDequeOptions { iterable, maxlen }: PyDequeOptions,
vm: &VirtualMachine,
) -> PyResult<()> {
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let PyDequeOptions { iterable, maxlen } = args.bind(vm)?;
// TODO: This is _basically_ pyobject_to_opt_usize in itertools.rs
// need to move that function elsewhere and refactor usages.
let maxlen = if let Some(obj) = maxlen.into_option() {

View File

@@ -1371,6 +1371,13 @@ mod _io {
.ok_or_else(|| vm.new_runtime_error("reentrant call inside buffered io".to_owned()))
}
#[pyslot]
fn slot_init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let (raw, BufferSize { buffer_size }): (PyObjectRef, _) = args.bind(vm)?;
zelf.init(raw, BufferSize { buffer_size }, vm)
}
#[pymethod(magic)]
fn init(
&self,
@@ -1783,16 +1790,14 @@ mod _io {
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
Self::default().into_ref_with_type(vm, cls).map(Into::into)
}
#[pyslot]
#[pymethod(magic)]
fn init(
&self,
reader: PyObjectRef,
writer: PyObjectRef,
buffer_size: BufferSize,
vm: &VirtualMachine,
) -> PyResult<()> {
self.read.init(reader, buffer_size.clone(), vm)?;
self.write.init(writer, buffer_size, vm)?;
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let (reader, writer, buffer_size): (PyObjectRef, PyObjectRef, BufferSize) =
args.bind(vm)?;
zelf.read.init(reader, buffer_size.clone(), vm)?;
zelf.write.init(writer, buffer_size, vm)?;
Ok(())
}
@@ -2193,9 +2198,12 @@ mod _io {
.map_err(|_| vm.new_value_error("I/O operation on uninitialized object".to_owned()))
}
#[pyslot]
#[pymethod(magic)]
fn init(&self, args: TextIOWrapperArgs, vm: &VirtualMachine) -> PyResult<()> {
let mut data = self.lock_opt(vm)?;
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let args: TextIOWrapperArgs = args.bind(vm)?;
let mut data = zelf.lock_opt(vm)?;
*data = None;
let encoding = match args.encoding {
@@ -3829,8 +3837,11 @@ mod fileio {
.map(Into::into)
}
#[pyslot]
#[pymethod(magic)]
fn init(zelf: PyRef<Self>, args: FileIOArgs, vm: &VirtualMachine) -> PyResult<()> {
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let args: FileIOArgs = args.bind(vm)?;
let mode_obj = args.mode.unwrap_or_else(|| PyStr::from("rb").into_ref(vm));
let mode_str = mode_obj.as_str();
let name = args.name;

View File

@@ -61,7 +61,7 @@ pub struct PyTypeSlots {
pub descr_get: AtomicCell<Option<DescrGetFunc>>,
pub descr_set: AtomicCell<Option<DescrSetFunc>>,
// tp_dictoffset
// tp_init
pub init: AtomicCell<Option<InitFunc>>,
// tp_alloc
pub new: AtomicCell<Option<NewFunc>>,
// tp_free
@@ -155,6 +155,7 @@ pub(crate) type DescrGetFunc =
pub(crate) type DescrSetFunc =
fn(PyObjectRef, PyObjectRef, Option<PyObjectRef>, &VirtualMachine) -> PyResult<()>;
pub(crate) type NewFunc = fn(PyTypeRef, FuncArgs, &VirtualMachine) -> PyResult;
pub(crate) type InitFunc = fn(PyObjectRef, FuncArgs, &VirtualMachine) -> PyResult<()>;
pub(crate) type DelFunc = fn(&PyObject, &VirtualMachine) -> PyResult<()>;
pub(crate) type AsSequenceFunc = fn(&PyObject, &VirtualMachine) -> Cow<'static, PySequenceMethods>;
@@ -324,6 +325,14 @@ fn descr_set_wrapper(
.map(drop)
}
fn init_wrapper(obj: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let res = vm.call_special_method(obj, "__init__", args)?;
if !vm.is_none(&res) {
return Err(vm.new_type_error("__init__ must return None".to_owned()));
}
Ok(())
}
fn new_wrapper(cls: PyTypeRef, mut args: FuncArgs, vm: &VirtualMachine) -> PyResult {
let new = vm
.get_attribute_opt(cls.as_object().to_owned(), "__new__")?
@@ -379,6 +388,9 @@ impl PyType {
"__set__" | "__delete__" => {
update_slot!(descr_set, descr_set_wrapper);
}
"__init__" => {
update_slot!(init, init_wrapper);
}
"__new__" => {
update_slot!(new, new_wrapper);
}