diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index f091262a6..5b9c1a117 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -355,6 +355,31 @@ impl PyType { attributes } + + // bound method for every type + pub(crate) fn __new__(zelf: PyRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult { + let (subtype, args): (PyRef, FuncArgs) = args.bind(vm)?; + if !subtype.fast_issubclass(&zelf) { + return Err(vm.new_type_error(format!( + "{zelf}.__new__({subtype}): {subtype} is not a subtype of {zelf}", + zelf = zelf.name(), + subtype = subtype.name(), + ))); + } + call_slot_new(zelf, subtype, args, vm) + } + + pub fn name(&self) -> BorrowedValue { + PyRwLockReadGuard::map(self.slots.name.read(), |slot_name| { + let name = slot_name.as_ref().unwrap(); + if self.slots.flags.has_feature(PyTypeFlags::HEAPTYPE) { + name.as_str() + } else { + name.rsplit('.').next().unwrap() + } + }) + .into() + } } impl Py { @@ -375,30 +400,10 @@ impl Py { } #[pyclass( - with(GetAttr, SetAttr, Callable, AsNumber, Representable), + with(Py, GetAttr, SetAttr, Callable, AsNumber, Representable), flags(BASETYPE) )] impl PyType { - // bound method for every type - pub(crate) fn __new__(zelf: PyRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult { - let (subtype, args): (PyRef, FuncArgs) = args.bind(vm)?; - if !subtype.fast_issubclass(&zelf) { - return Err(vm.new_type_error(format!( - "{zelf}.__new__({subtype}): {subtype} is not a subtype of {zelf}", - zelf = zelf.name(), - subtype = subtype.name(), - ))); - } - call_slot_new(zelf, subtype, args, vm) - } - - #[pygetset(name = "__mro__")] - fn get_mro(zelf: PyRef) -> PyTuple { - let elements: Vec = - zelf.iter_mro().map(|x| x.as_object().to_owned()).collect(); - PyTuple::new_unchecked(elements.into_boxed_slice()) - } - #[pygetset(magic)] fn bases(&self, vm: &VirtualMachine) -> PyTupleRef { vm.ctx.new_tuple( @@ -419,48 +424,11 @@ impl PyType { self.slots.flags.bits() } - #[pymethod(magic)] - fn dir(zelf: PyRef, _vm: &VirtualMachine) -> PyList { - let attributes: Vec = zelf - .get_attributes() - .into_iter() - .map(|(k, _)| k.to_object()) - .collect(); - PyList::from(attributes) - } - - #[pymethod(magic)] - fn instancecheck(zelf: PyRef, obj: PyObjectRef) -> bool { - obj.fast_isinstance(&zelf) - } - - #[pymethod(magic)] - fn subclasscheck(zelf: PyRef, subclass: PyTypeRef) -> bool { - subclass.fast_issubclass(&zelf) - } - - #[pyclassmethod(magic)] - fn subclasshook(_args: FuncArgs, vm: &VirtualMachine) -> PyObjectRef { - vm.ctx.not_implemented() - } - #[pygetset] fn __name__(&self) -> String { self.name().to_string() } - pub fn name(&self) -> BorrowedValue { - PyRwLockReadGuard::map(self.slots.name.read(), |slot_name| { - let name = slot_name.as_ref().unwrap(); - if self.slots.flags.has_feature(PyTypeFlags::HEAPTYPE) { - name.as_str() - } else { - name.rsplit('.').next().unwrap() - } - }) - .into() - } - #[pygetset(magic)] pub fn qualname(&self, vm: &VirtualMachine) -> PyObjectRef { self.attributes @@ -607,11 +575,6 @@ impl PyType { ) } - #[pymethod] - fn mro(zelf: PyRef) -> Vec { - zelf.iter_mro().map(|cls| cls.to_owned().into()).collect() - } - #[pymethod(magic)] pub fn ror(zelf: PyObjectRef, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { or_(other, zelf, vm) @@ -906,6 +869,46 @@ impl PyType { } } +#[pyclass] +impl Py { + #[pygetset(name = "__mro__")] + fn get_mro(&self) -> PyTuple { + let elements: Vec = + self.iter_mro().map(|x| x.as_object().to_owned()).collect(); + PyTuple::new_unchecked(elements.into_boxed_slice()) + } + + #[pymethod(magic)] + fn dir(&self) -> PyList { + let attributes: Vec = self + .get_attributes() + .into_iter() + .map(|(k, _)| k.to_object()) + .collect(); + PyList::from(attributes) + } + + #[pymethod(magic)] + fn instancecheck(&self, obj: PyObjectRef) -> bool { + obj.fast_isinstance(self) + } + + #[pymethod(magic)] + fn subclasscheck(&self, subclass: PyTypeRef) -> bool { + subclass.fast_issubclass(self) + } + + #[pyclassmethod(magic)] + fn subclasshook(_args: FuncArgs, vm: &VirtualMachine) -> PyObjectRef { + vm.ctx.not_implemented() + } + + #[pymethod] + fn mro(&self) -> Vec { + self.iter_mro().map(|cls| cls.to_owned().into()).collect() + } +} + const SIGNATURE_END_MARKER: &str = ")\n--\n\n"; fn get_signature(doc: &str) -> Option<&str> { doc.find(SIGNATURE_END_MARKER).map(|index| &doc[..=index])