Merge pull request #3653 from youknowone/prelude

vm::prelude sketch
This commit is contained in:
Jeong YunWon
2022-04-23 10:15:47 +09:00
committed by GitHub
95 changed files with 919 additions and 779 deletions

View File

@@ -45,8 +45,6 @@ class GeneralTest(unittest.TestCase):
('func2', (), {}),
('func1', (1, 2), {})])
# TODO: RUSTPYTHON, AttributeError: module 'sys' has no attribute 'unraisablehook'
@unittest.expectedFailure
def test_badargs(self):
def func():
pass
@@ -54,16 +52,12 @@ class GeneralTest(unittest.TestCase):
# func() has no parameter, but it's called with 2 parameters
self.assert_raises_unraisable(TypeError, func, 1 ,2)
# TODO: RUSTPYTHON, AttributeError: module 'sys' has no attribute 'unraisablehook'
@unittest.expectedFailure
def test_raise(self):
def raise_type_error():
raise TypeError
self.assert_raises_unraisable(TypeError, raise_type_error)
# TODO: RUSTPYTHON, AttributeError: module 'sys' has no attribute 'unraisablehook'
@unittest.expectedFailure
def test_raise_unnormalized(self):
# bpo-10756: Make sure that an unnormalized exception is handled
# properly.
@@ -72,8 +66,6 @@ class GeneralTest(unittest.TestCase):
self.assert_raises_unraisable(ZeroDivisionError, div_zero)
# TODO: RUSTPYTHON, AttributeError: module 'sys' has no attribute 'unraisablehook'
@unittest.expectedFailure
def test_exit(self):
self.assert_raises_unraisable(SystemExit, sys.exit)
@@ -124,8 +116,6 @@ class GeneralTest(unittest.TestCase):
atexit._run_exitfuncs()
self.assertEqual(l, [5])
# TODO: RUSTPYTHON, AttributeError: module 'sys' has no attribute 'unraisablehook'
@unittest.expectedFailure
def test_atexit_with_unregistered_function(self):
# See bpo-46025 for more info
def func():

6
Lib/test/test_io.py vendored
View File

@@ -1114,8 +1114,6 @@ class CommonBufferedTests:
# a ValueError.
self.assertRaises(ValueError, _with)
# TODO: RUSTPYTHON, sys.unraisablehook
@unittest.expectedFailure
def test_error_through_destructor(self):
# Test that the exception state is not modified by a destructor,
# even if close() fails.
@@ -2121,8 +2119,6 @@ class BufferedRWPairTest(unittest.TestCase):
# Silence destructor error
reader.close = lambda: None
# TODO: RUSTPYTHON, sys.unraisablehook
@unittest.expectedFailure
def test_writer_close_error_on_close(self):
def writer_close():
writer_non_existing
@@ -2952,8 +2948,6 @@ class TextIOWrapperTest(unittest.TestCase):
support.gc_collect()
self.assertEqual(record, [1, 2, 3])
# TODO: RUSTPYTHON, sys.unraisablehook
@unittest.expectedFailure
def test_error_through_destructor(self):
# Test that the exception state is not modified by a destructor,
# even if close() fails.

View File

@@ -1291,8 +1291,7 @@ class StressTest(unittest.TestCase):
# Python handler
self.assertEqual(len(sigs), N, "Some signals were lost")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.skip("TODO: RUSTPYTHON; hang")
@unittest.skipUnless(hasattr(signal, "SIGUSR1"),
"test needs SIGUSR1")
def test_stress_modifying_handlers(self):

View File

@@ -135,8 +135,6 @@ class ThreadRunningTests(BasicThreadTest):
time.sleep(POLL_SLEEP)
self.assertEqual(thread._count(), orig)
# TODO: RUSTPYTHON, AttributeError: module 'sys' has no attribute 'unraisablehook'
@unittest.expectedFailure
def test_unraisable_exception(self):
def task():
started.release()

View File

@@ -112,7 +112,7 @@ pub(crate) fn impl_pyimpl(attr: AttributeArgs, item: Item) -> Result<TokenStream
let class_extensions = &context.class_extensions;
quote! {
#imp
impl ::rustpython_vm::pyclass::PyClassImpl for #ty {
impl ::rustpython_vm::class::PyClassImpl for #ty {
const TP_FLAGS: ::rustpython_vm::types::PyTypeFlags = #flags;
fn impl_extend_class(
@@ -237,7 +237,7 @@ fn generate_class_def(
.map(|typ| {
quote! {
fn static_baseclass() -> &'static ::rustpython_vm::builtins::PyTypeRef {
use rustpython_vm::pyclass::StaticType;
use rustpython_vm::class::StaticType;
#typ::static_type()
}
}
@@ -247,21 +247,21 @@ fn generate_class_def(
let typ = Ident::new(&typ, ident.span());
quote! {
fn static_metaclass() -> &'static ::rustpython_vm::builtins::PyTypeRef {
use rustpython_vm::pyclass::StaticType;
use rustpython_vm::class::StaticType;
#typ::static_type()
}
}
});
let tokens = quote! {
impl ::rustpython_vm::pyclass::PyClassDef for #ident {
impl ::rustpython_vm::class::PyClassDef for #ident {
const NAME: &'static str = #name;
const MODULE_NAME: Option<&'static str> = #module_name;
const TP_NAME: &'static str = #module_class_name;
const DOC: Option<&'static str> = #doc;
}
impl ::rustpython_vm::pyclass::StaticType for #ident {
impl ::rustpython_vm::class::StaticType for #ident {
fn static_cell() -> &'static ::rustpython_vm::common::static_cell::StaticCell<::rustpython_vm::builtins::PyTypeRef> {
::rustpython_vm::common::static_cell! {
static CELL: ::rustpython_vm::builtins::PyTypeRef;

View File

@@ -432,7 +432,7 @@ impl ModuleItem for ClassItem {
class_meta.class_name()?
};
let class_new = quote_spanned!(ident.span() =>
let new_class = <#ident as ::rustpython_vm::pyclass::PyClassImpl>::make_class(&vm.ctx);
let new_class = <#ident as ::rustpython_vm::class::PyClassImpl>::make_class(&vm.ctx);
new_class.set_str_attr("__module__", vm.new_pyobj(#module_name));
);
(class_name, class_new)

View File

@@ -8,7 +8,7 @@ pub(crate) fn impl_pypayload(input: DeriveInput) -> Result<TokenStream> {
let ret = quote! {
impl ::rustpython_vm::PyPayload for #ty {
fn class(_vm: &::rustpython_vm::VirtualMachine) -> &rustpython_vm::builtins::PyTypeRef {
<Self as ::rustpython_vm::pyclass::StaticType>::static_type()
<Self as ::rustpython_vm::class::StaticType>::static_type()
}
}
};

View File

@@ -60,7 +60,8 @@ mod _json {
parse_constant,
ctx,
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -250,7 +250,9 @@ pub(crate) mod _struct {
fn py_new(cls: PyTypeRef, fmt: Self::Args, vm: &VirtualMachine) -> PyResult {
let spec = fmt.format_spec(vm)?;
let format = fmt.0;
PyStruct { spec, format }.into_pyresult_with_type(vm, cls)
PyStruct { spec, format }
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -73,7 +73,8 @@ mod _random {
PyRandom {
rng: PyMutex::default(),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -9,7 +9,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef {
#[cfg(unix)]
{
use crate::vm::pyclass::PyClassImpl;
use crate::vm::class::PyClassImpl;
decl::poll::PyPoll::make_class(&vm.ctx);
}

View File

@@ -547,7 +547,7 @@ mod _socket {
impl PySocket {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
Self::default().into_pyresult_with_type(vm, cls)
Self::default().into_ref_with_type(vm, cls).map(Into::into)
}
#[pymethod(magic)]

View File

@@ -489,7 +489,8 @@ mod _ssl {
check_hostname: AtomicCell::new(check_hostname),
protocol: proto,
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -1,11 +1,11 @@
use super::{PyCode, PyGenericAlias, PyStrRef, PyTypeRef};
use crate::{
builtins::PyBaseExceptionRef,
class::PyClassImpl,
coroutine::Coro,
frame::FrameRef,
function::OptionalArg,
protocol::PyIterReturn,
pyclass::PyClassImpl,
types::{Constructor, IterNext, IterNextIterable, Unconstructible},
AsObject, Context, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};

View File

@@ -1,6 +1,6 @@
use super::{PyInt, PyStrRef, PyTypeRef};
use crate::{
convert::ToPyObject, function::OptionalArg, pyclass::PyClassImpl, types::Constructor, AsObject,
class::PyClassImpl, convert::ToPyObject, function::OptionalArg, types::Constructor, AsObject,
Context, PyObject, PyObjectRef, PyPayload, PyResult, TryFromBorrowedObject, VirtualMachine,
};
use num_bigint::Sign;

View File

@@ -1,8 +1,8 @@
use super::{pytype, PyClassMethod, PyStaticMethod, PyStr, PyStrRef, PyTypeRef};
use super::{type_, PyClassMethod, PyStaticMethod, PyStr, PyStrRef, PyTypeRef};
use crate::{
builtins::PyBoundMethod,
class::PyClassImpl,
function::{FuncArgs, IntoPyNativeFunc, PyNativeFunc},
pyclass::PyClassImpl,
types::{Callable, Constructor, GetDescriptor, Unconstructible},
AsObject, Context, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -148,7 +148,7 @@ impl PyBuiltinFunction {
#[pyproperty(magic)]
fn text_signature(&self) -> Option<String> {
self.value.doc.as_ref().and_then(|doc| {
pytype::get_text_signature_from_internal_doc(self.value.name.as_str(), doc.as_str())
type_::get_text_signature_from_internal_doc(self.value.name.as_str(), doc.as_str())
.map(|signature| signature.to_string())
})
}
@@ -238,7 +238,7 @@ impl PyBuiltinMethod {
#[pyproperty(magic)]
fn text_signature(&self) -> Option<String> {
self.value.doc.as_ref().and_then(|doc| {
pytype::get_text_signature_from_internal_doc(self.value.name.as_str(), doc.as_str())
type_::get_text_signature_from_internal_doc(self.value.name.as_str(), doc.as_str())
.map(|signature| signature.to_string())
})
}

View File

@@ -11,6 +11,7 @@ use crate::{
ByteInnerNewOptions, ByteInnerPaddingOptions, ByteInnerSplitOptions,
ByteInnerTranslateOptions, DecodeArgs, PyBytesInner,
},
class::PyClassImpl,
common::{
atomic::{AtomicUsize, Ordering},
lock::{
@@ -26,7 +27,6 @@ use crate::{
BufferDescriptor, BufferMethods, BufferResizeGuard, PyBuffer, PyIterReturn,
PyMappingMethods, PySequenceMethods,
},
pyclass::PyClassImpl,
sliceable::{SequenceIndex, SliceableSequenceMutOp, SliceableSequenceOp},
types::{
AsBuffer, AsMapping, AsSequence, Callable, Comparable, Constructor, Hashable, IterNext,
@@ -100,7 +100,9 @@ pub(crate) fn init(context: &Context) {
impl PyByteArray {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
PyByteArray::default().into_pyresult_with_type(vm, cls)
PyByteArray::default()
.into_ref_with_type(vm, cls)
.map(Into::into)
}
#[pymethod(magic)]

View File

@@ -6,6 +6,7 @@ use crate::{
bytes_decode, ByteInnerFindOptions, ByteInnerNewOptions, ByteInnerPaddingOptions,
ByteInnerSplitOptions, ByteInnerTranslateOptions, DecodeArgs, PyBytesInner,
},
class::PyClassImpl,
common::{hash::PyHash, lock::PyMutex},
convert::{ToPyObject, ToPyResult},
function::{ArgBytesLike, ArgIterable, OptionalArg, OptionalOption, PyComparisonValue},
@@ -13,7 +14,6 @@ use crate::{
BufferDescriptor, BufferMethods, PyBuffer, PyIterReturn, PyMappingMethods,
PySequenceMethods,
},
pyclass::PyClassImpl,
sliceable::{SequenceIndex, SliceableSequenceOp},
types::{
AsBuffer, AsMapping, AsSequence, Callable, Comparable, Constructor, Hashable, IterNext,

View File

@@ -1,7 +1,7 @@
use super::PyTypeRef;
use crate::{
builtins::PyBoundMethod,
pyclass::PyClassImpl,
class::PyClassImpl,
types::{Constructor, GetDescriptor},
AsObject, Context, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -61,7 +61,9 @@ impl Constructor for PyClassMethod {
type Args = PyObjectRef;
fn py_new(cls: PyTypeRef, callable: Self::Args, vm: &VirtualMachine) -> PyResult {
PyClassMethod { callable }.into_pyresult_with_type(vm, cls)
PyClassMethod { callable }
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -5,8 +5,8 @@
use super::{PyStrRef, PyTupleRef, PyTypeRef};
use crate::{
bytecode::{self, BorrowedConstant, Constant, ConstantBag},
class::{PyClassImpl, StaticType},
function::FuncArgs,
pyclass::{PyClassImpl, StaticType},
AsObject, Context, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use num_traits::Zero;
@@ -31,7 +31,7 @@ fn borrow_obj_constant(obj: &PyObject) -> BorrowedConstant<PyConstant> {
match_class!(match obj {
ref i @ super::int::PyInt => {
let value = i.as_bigint();
if obj.class().is(super::pybool::PyBool::static_type()) {
if obj.class().is(super::bool_::PyBool::static_type()) {
BorrowedConstant::Boolean {
value: !value.is_zero(),
}

View File

@@ -1,12 +1,12 @@
use super::{float, PyStr, PyTypeRef};
use crate::{
class::PyClassImpl,
convert::ToPyObject,
function::{
OptionalArg, OptionalOption,
PyArithmeticValue::{self, *},
PyComparisonValue,
},
pyclass::PyClassImpl,
types::{Comparable, Constructor, Hashable, PyComparisonOp},
AsObject, Context, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -142,7 +142,9 @@ impl Constructor for PyComplex {
let value = parse_str(s.as_str().trim()).ok_or_else(|| {
vm.new_value_error("complex() arg is a malformed string".to_owned())
})?;
return Self::from(value).into_pyresult_with_type(vm, cls);
return Self::from(value)
.into_ref_with_type(vm, cls)
.map(Into::into);
} else {
return Err(vm.new_type_error(format!(
"complex() first argument must be a string or a number, not '{}'",
@@ -184,7 +186,9 @@ impl Constructor for PyComplex {
imag.re
};
let value = Complex64::new(final_real, final_imag);
Self::from(value).into_pyresult_with_type(vm, cls)
Self::from(value)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -1,10 +1,10 @@
use super::{PyCode, PyStrRef, PyTypeRef};
use crate::{
class::PyClassImpl,
coroutine::Coro,
frame::FrameRef,
function::OptionalArg,
protocol::PyIterReturn,
pyclass::PyClassImpl,
types::{Constructor, IterNext, IterNextIterable, Unconstructible},
AsObject, Context, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};

View File

@@ -5,9 +5,10 @@ use super::{
use crate::{
builtins::{
iter::{builtins_iter, builtins_reversed},
pytype::PyAttributes,
type_::PyAttributes,
PyTuple,
},
class::{PyClassDef, PyClassImpl},
common::ascii,
convert::ToPyObject,
dictdatatype::{self, DictKey},
@@ -15,7 +16,6 @@ use crate::{
ArgIterable, FuncArgs, KwArgs, OptionalArg, PyArithmeticValue::*, PyComparisonValue,
},
protocol::{PyIterIter, PyIterReturn, PyMappingMethods, PySequenceMethods},
pyclass::{PyClassDef, PyClassImpl},
recursion::ReprGuard,
types::{
AsMapping, AsSequence, Callable, Comparable, Constructor, Hashable, IterNext,
@@ -83,7 +83,9 @@ impl PyDict {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
PyDict::default().into_pyresult_with_type(vm, cls)
PyDict::default()
.into_ref_with_type(vm, cls)
.map(Into::into)
}
#[pymethod(magic)]

View File

@@ -1,10 +1,10 @@
use super::{IterStatus, PositionIterInternal, PyGenericAlias, PyIntRef, PyTupleRef, PyTypeRef};
use crate::common::lock::{PyMutex, PyRwLock};
use crate::{
class::PyClassImpl,
convert::ToPyObject,
function::OptionalArg,
protocol::{PyIter, PyIterReturn},
pyclass::PyClassImpl,
types::{Constructor, IterNext, IterNextIterable},
AsObject, Context, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -44,7 +44,8 @@ impl Constructor for PyEnumerate {
counter: PyRwLock::new(counter),
iterator,
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -1,7 +1,7 @@
use super::PyTypeRef;
use crate::{
class::PyClassImpl,
protocol::{PyIter, PyIterReturn},
pyclass::PyClassImpl,
types::{Constructor, IterNext, IterNextIterable},
Context, PyObjectRef, PyPayload, PyResult, VirtualMachine,
};
@@ -31,7 +31,8 @@ impl Constructor for PyFilter {
predicate: function,
iterator,
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -1,6 +1,7 @@
use super::{try_bigint_to_f64, PyByteArray, PyBytes, PyInt, PyIntRef, PyStr, PyStrRef, PyTypeRef};
use crate::common::{float_ops, hash};
use crate::{
class::PyClassImpl,
convert::ToPyObject,
format::FormatSpec,
function::{
@@ -8,7 +9,6 @@ use crate::{
PyArithmeticValue::{self, *},
PyComparisonValue,
},
pyclass::PyClassImpl,
types::{Comparable, Constructor, Hashable, PyComparisonOp},
AsObject, Context, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromBorrowedObject,
TryFromObject, VirtualMachine,
@@ -183,7 +183,9 @@ impl Constructor for PyFloat {
}
}
};
PyFloat::from(float_val).into_pyresult_with_type(vm, cls)
PyFloat::from(float_val)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -4,8 +4,8 @@
use super::{PyCode, PyDictRef, PyStrRef};
use crate::{
class::PyClassImpl,
frame::{Frame, FrameRef},
pyclass::PyClassImpl,
types::{Constructor, Unconstructible},
AsObject, Context, PyObjectRef, PyRef, PyResult, VirtualMachine,
};

View File

@@ -9,9 +9,9 @@ use crate::common::lock::PyMutex;
use crate::function::ArgMapping;
use crate::{
bytecode,
class::PyClassImpl,
frame::Frame,
function::{FuncArgs, OptionalArg, PyComparisonValue},
pyclass::PyClassImpl,
scope::Scope,
types::{Callable, Comparable, Constructor, GetAttr, GetDescriptor, PyComparisonOp},
AsObject, Context, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
@@ -485,7 +485,9 @@ impl Constructor for PyBoundMethod {
Self::Args { function, object }: Self::Args,
vm: &VirtualMachine,
) -> PyResult {
PyBoundMethod::new(object, function).into_pyresult_with_type(vm, cls)
PyBoundMethod::new(object, function)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -588,7 +590,9 @@ impl Constructor for PyCell {
type Args = OptionalArg;
fn py_new(cls: PyTypeRef, value: Self::Args, vm: &VirtualMachine) -> PyResult {
Self::new(value.into_option()).into_pyresult_with_type(vm, cls)
Self::new(value.into_option())
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -1,5 +1,5 @@
use crate::{
builtins::{float, int, pybool, PyBaseExceptionRef, PyDictRef, PyFunction, PyStrRef},
builtins::{bool_, float, int, PyBaseExceptionRef, PyDictRef, PyFunction, PyStrRef},
bytecode::CodeFlags,
convert::ToPyObject,
function::FuncArgs,
@@ -120,7 +120,7 @@ fn get_jit_value(vm: &VirtualMachine, obj: &PyObject) -> Result<AbiValue, ArgsEr
} else if cls.is(&vm.ctx.types.float_type) {
Ok(AbiValue::Float(float::get_value(obj)))
} else if cls.is(&vm.ctx.types.bool_type) {
Ok(AbiValue::Bool(pybool::get_value(obj)))
Ok(AbiValue::Bool(bool_::get_value(obj)))
} else {
Err(ArgsError::NonJitType)
}

View File

@@ -4,11 +4,11 @@
use super::{PyCode, PyStrRef, PyTypeRef};
use crate::{
class::PyClassImpl,
coroutine::Coro,
frame::FrameRef,
function::OptionalArg,
protocol::PyIterReturn,
pyclass::PyClassImpl,
types::{Constructor, IterNext, IterNextIterable, Unconstructible},
AsObject, Context, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};

View File

@@ -1,10 +1,10 @@
use crate::{
builtins::{PyList, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType, PyTypeRef},
class::PyClassImpl,
common::hash,
convert::ToPyObject,
function::{FuncArgs, PyComparisonValue},
protocol::PyMappingMethods,
pyclass::PyClassImpl,
types::{AsMapping, Callable, Comparable, Constructor, GetAttr, Hashable, PyComparisonOp},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
VirtualMachine,
@@ -49,7 +49,9 @@ impl Constructor for PyGenericAlias {
return Err(vm.new_type_error("GenericAlias() takes no keyword arguments".to_owned()));
}
let (origin, arguments): (_, PyObjectRef) = args.bind(vm)?;
PyGenericAlias::new(origin, arguments, vm).into_pyresult_with_type(vm, cls)
PyGenericAlias::new(origin, arguments, vm)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -3,10 +3,10 @@
*/
use super::PyTypeRef;
use crate::{
class::PyClassImpl,
convert::ToPyResult,
function::{OwnedParam, RefParam},
pyclass::PyClassImpl,
pyobject::PyThreadingConstraint,
object::PyThreadingConstraint,
types::{Constructor, GetDescriptor, Unconstructible},
AsObject, Context, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
};

View File

@@ -1,11 +1,11 @@
use super::{float, PyByteArray, PyBytes, PyStr, PyStrRef, PyTypeRef};
use crate::{
bytesinner::PyBytesInner,
class::PyClassImpl,
common::hash,
convert::{ToPyObject, ToPyResult},
format::FormatSpec,
function::{ArgIntoBool, OptionalArg, OptionalOption, PyArithmeticValue, PyComparisonValue},
pyclass::PyClassImpl,
types::{Comparable, Constructor, Hashable, PyComparisonOp},
AsObject, Context, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromBorrowedObject,
VirtualMachine,

View File

@@ -6,9 +6,9 @@ use std::borrow::Cow;
use super::{PyInt, PyTupleRef, PyTypeRef};
use crate::{
class::PyClassImpl,
function::ArgCallable,
protocol::{PyIterReturn, PySequence, PySequenceMethods},
pyclass::PyClassImpl,
types::{IterNext, IterNextIterable},
Context, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
};

View File

@@ -4,10 +4,10 @@ use crate::common::lock::{
};
use crate::TryFromBorrowedObject;
use crate::{
class::PyClassImpl,
convert::ToPyObject,
function::{FuncArgs, OptionalArg, PyComparisonValue},
protocol::{PyIterReturn, PyMappingMethods, PySequence, PySequenceMethods},
pyclass::PyClassImpl,
recursion::ReprGuard,
sequence::{MutObjectSequenceOp, ObjectSequenceOp, SequenceMutOp, SequenceOp},
sliceable::{saturate_index, SequenceIndex, SliceableSequenceMutOp, SliceableSequenceOp},
@@ -341,7 +341,9 @@ impl PyList {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
PyList::default().into_pyresult_with_type(vm, cls)
PyList::default()
.into_ref_with_type(vm, cls)
.map(Into::into)
}
#[pymethod(magic)]

View File

@@ -1,8 +1,8 @@
use super::PyTypeRef;
use crate::{
class::PyClassImpl,
function::PosArgs,
protocol::{PyIter, PyIterReturn},
pyclass::PyClassImpl,
types::{Constructor, IterNext, IterNextIterable},
Context, PyObjectRef, PyPayload, PyResult, VirtualMachine,
};
@@ -29,7 +29,9 @@ impl Constructor for PyMap {
fn py_new(cls: PyTypeRef, (mapper, iterators): Self::Args, vm: &VirtualMachine) -> PyResult {
let iterators = iterators.into_vec();
PyMap { mapper, iterators }.into_pyresult_with_type(vm, cls)
PyMap { mapper, iterators }
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -2,10 +2,10 @@ use std::borrow::Cow;
use super::{PyDict, PyGenericAlias, PyList, PyStr, PyStrRef, PyTuple, PyTypeRef};
use crate::{
class::PyClassImpl,
convert::ToPyObject,
function::OptionalArg,
protocol::{PyMapping, PyMappingMethods, PySequence, PySequenceMethods},
pyclass::PyClassImpl,
types::{AsMapping, AsSequence, Constructor, Iterable},
AsObject, Context, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
VirtualMachine,
@@ -53,7 +53,8 @@ impl Constructor for PyMappingProxy {
Self {
mapping: MappingProxyInner::Dict(mapping),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
}

View File

@@ -4,6 +4,7 @@ use super::{
use crate::{
buffer::FormatSpec,
bytesinner::bytes_to_hex,
class::PyClassImpl,
common::{
borrow::{BorrowedValue, BorrowedValueMut},
hash::PyHash,
@@ -14,7 +15,6 @@ use crate::{
protocol::{
BufferDescriptor, BufferMethods, PyBuffer, PyMappingMethods, PySequenceMethods, VecBuffer,
},
pyclass::PyClassImpl,
sequence::SequenceOp,
sliceable::wrap_index,
types::{AsBuffer, AsMapping, AsSequence, Comparable, Constructor, Hashable, PyComparisonOp},
@@ -57,7 +57,7 @@ impl Constructor for PyMemoryView {
fn py_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult {
let zelf = Self::from_object(&args.object, vm)?;
zelf.into_pyresult_with_type(vm, cls)
zelf.into_ref_with_type(vm, cls).map(Into::into)
}
}

View File

@@ -54,14 +54,18 @@ pub(crate) mod object;
pub use object::PyBaseObject;
pub(crate) mod property;
pub use property::PyProperty;
pub(crate) mod pybool;
pub use pybool::PyBool;
#[path = "bool.rs"]
pub(crate) mod bool_;
pub use bool_::PyBool;
#[path = "str.rs"]
pub(crate) mod pystr;
pub use pystr::{PyStr, PyStrRef};
pub(crate) mod pysuper;
pub use pysuper::PySuper;
pub(crate) mod pytype;
pub use pytype::{PyType, PyTypeRef};
#[path = "super.rs"]
pub(crate) mod super_;
pub use super_::PySuper;
#[path = "type.rs"]
pub(crate) mod type_;
pub use type_::{PyType, PyTypeRef};
pub(crate) mod range;
pub use range::PyRange;
pub(crate) mod set;
@@ -82,8 +86,9 @@ pub(crate) mod weakref;
pub use weakref::PyWeak;
pub(crate) mod zip;
pub use zip::PyZip;
pub(crate) mod pyunion;
pub use pyunion::PyUnion;
#[path = "union.rs"]
pub(crate) mod union_;
pub use union_::PyUnion;
pub use float::try_to_bigint as try_f64_to_bigint;
pub use int::try_to_float as try_bigint_to_f64;

View File

@@ -1,8 +1,8 @@
use super::pystr::IntoPyStrRef;
use super::{PyDictRef, PyStr, PyStrRef, PyTypeRef};
use crate::{
convert::ToPyObject, function::FuncArgs, pyclass::PyClassImpl, types::GetAttr, AsObject,
Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
class::PyClassImpl, convert::ToPyObject, function::FuncArgs, types::GetAttr, AsObject, Context,
Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
#[pyclass(module = false, name = "module")]
@@ -35,7 +35,7 @@ impl PyModule {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
PyModule {}.into_pyresult_with_type(vm, cls)
PyModule {}.into_ref_with_type(vm, cls).map(Into::into)
}
#[pymethod(magic)]

View File

@@ -1,8 +1,8 @@
use super::PyTypeRef;
use crate::{
builtins::PyDict,
class::PyClassImpl,
function::{FuncArgs, PyComparisonValue},
pyclass::PyClassImpl,
recursion::ReprGuard,
types::{Comparable, Constructor, PyComparisonOp},
AsObject, Context, PyObject, PyPayload, PyRef, PyResult, VirtualMachine,
@@ -25,7 +25,7 @@ impl Constructor for PyNamespace {
type Args = FuncArgs;
fn py_new(cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
PyNamespace {}.into_pyresult_with_type(vm, cls)
PyNamespace {}.into_ref_with_type(vm, cls).map(Into::into)
}
}

View File

@@ -1,8 +1,8 @@
use super::{PyDict, PyDictRef, PyList, PyStr, PyStrRef, PyType, PyTypeRef};
use crate::common::hash::PyHash;
use crate::{
class::PyClassImpl,
function::{FuncArgs, PyArithmeticValue, PyComparisonValue},
pyclass::PyClassImpl,
types::PyComparisonOp,
utils::Either,
AsObject, Context, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,

View File

@@ -4,7 +4,7 @@
use super::PyTypeRef;
use crate::common::lock::PyRwLock;
use crate::{
function::FuncArgs, pyclass::PyClassImpl, types::GetDescriptor, AsObject, Context, PyObjectRef,
class::PyClassImpl, function::FuncArgs, types::GetDescriptor, AsObject, Context, PyObjectRef,
PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
};
@@ -95,7 +95,8 @@ impl PyProperty {
deleter: PyRwLock::new(None),
doc: PyRwLock::new(None),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
#[pymethod(magic)]

View File

@@ -2,9 +2,9 @@ use super::{PyInt, PyIntRef, PySlice, PyTupleRef, PyTypeRef};
use crate::common::hash::PyHash;
use crate::{
builtins::builtins_iter,
class::PyClassImpl,
function::{FuncArgs, OptionalArg, PyComparisonValue},
protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods},
pyclass::PyClassImpl,
types::{
AsMapping, AsSequence, Comparable, Constructor, Hashable, IterNext, IterNextIterable,
Iterable, PyComparisonOp, Unconstructible,

View File

@@ -7,10 +7,10 @@ use super::{
};
use crate::common::{ascii, hash::PyHash, lock::PyMutex, rc::PyRc};
use crate::{
class::PyClassImpl,
dictdatatype::{self, DictSize},
function::{ArgIterable, FuncArgs, OptionalArg, PosArgs, PyArithmeticValue, PyComparisonValue},
protocol::{PyIterReturn, PySequenceMethods},
pyclass::PyClassImpl,
recursion::ReprGuard,
types::{
AsSequence, Comparable, Constructor, Hashable, IterNext, IterNextIterable, Iterable,
@@ -398,7 +398,7 @@ impl PySet {
impl PySet {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
PySet::default().into_pyresult_with_type(vm, cls)
PySet::default().into_ref_with_type(vm, cls).map(Into::into)
}
#[pymethod(magic)]
@@ -725,7 +725,8 @@ impl Constructor for PyFrozenSet {
if elements.is_empty() && cls.is(&vm.ctx.types.frozenset_type) {
Ok(vm.ctx.empty_frozenset.clone().into())
} else {
Self::from_iter(vm, elements).and_then(|o| o.into_pyresult_with_type(vm, cls))
Self::from_iter(vm, elements)
.and_then(|o| o.into_ref_with_type(vm, cls).map(Into::into))
}
}
}

View File

@@ -1,6 +1,6 @@
use super::PyTypeRef;
use crate::{
convert::ToPyObject, pyclass::PyClassImpl, types::Constructor, AsObject, Context, PyObjectRef,
class::PyClassImpl, convert::ToPyObject, types::Constructor, AsObject, Context, PyObjectRef,
PyPayload, PyResult, VirtualMachine,
};

View File

@@ -1,9 +1,9 @@
// sliceobject.{h,c} in CPython
use super::{PyInt, PyIntRef, PyTupleRef, PyTypeRef};
use crate::{
class::PyClassImpl,
convert::ToPyObject,
function::{FuncArgs, OptionalArg, PyComparisonValue},
pyclass::PyClassImpl,
types::{Comparable, Constructor, Hashable, PyComparisonOp, Unhashable},
AsObject, Context, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -101,7 +101,7 @@ impl PySlice {
}
}
};
slice.into_pyresult_with_type(vm, cls)
slice.into_ref_with_type(vm, cls).map(Into::into)
}
pub(crate) fn inner_indices(

View File

@@ -1,8 +1,8 @@
use super::{PyStr, PyTypeRef};
use crate::{
builtins::builtinfunc::PyBuiltinMethod,
class::PyClassImpl,
function::{FuncArgs, IntoPyNativeFunc},
pyclass::PyClassImpl,
types::{Callable, Constructor, GetDescriptor},
Context, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -41,7 +41,9 @@ impl Constructor for PyStaticMethod {
type Args = PyObjectRef;
fn py_new(cls: PyTypeRef, callable: Self::Args, vm: &VirtualMachine) -> PyResult {
PyStaticMethod { callable }.into_pyresult_with_type(vm, cls)
PyStaticMethod { callable }
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -5,11 +5,11 @@ use super::{
};
use crate::{
anystr::{self, adjust_indices, AnyStr, AnyStrContainer, AnyStrWrapper},
class::PyClassImpl,
convert::{ToPyException, ToPyObject},
format::{FormatSpec, FormatString, FromTemplate},
function::{ArgIterable, FuncArgs, OptionalArg, OptionalOption, PyComparisonValue},
protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods},
pyclass::PyClassImpl,
sequence::SequenceOp,
sliceable::{SequenceIndex, SliceableSequenceOp},
types::{
@@ -320,7 +320,9 @@ impl Constructor for PyStr {
if string.class().is(&cls) {
Ok(string.into())
} else {
PyStr::from(string.as_str()).into_pyresult_with_type(vm, cls)
PyStr::from(string.as_str())
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
}

View File

@@ -5,8 +5,8 @@ See also [CPython source code.](https://github.com/python/cpython/blob/50b48572d
use super::{PyStrRef, PyType, PyTypeRef};
use crate::{
class::PyClassImpl,
function::OptionalArg,
pyclass::PyClassImpl,
types::{Constructor, GetAttr, GetDescriptor},
AsObject, Context, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -91,7 +91,9 @@ impl Constructor for PySuper {
(typ, obj)
};
PySuper::new(typ, obj, vm)?.into_pyresult_with_type(vm, cls)
PySuper::new(typ, obj, vm)?
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -1,5 +1,5 @@
use super::PyTypeRef;
use crate::{frame::FrameRef, pyclass::PyClassImpl, Context, PyPayload, PyRef, VirtualMachine};
use crate::{class::PyClassImpl, frame::FrameRef, Context, PyPayload, PyRef, VirtualMachine};
#[pyclass(module = false, name = "traceback")]
#[derive(Debug)]

View File

@@ -1,10 +1,10 @@
use super::{PositionIterInternal, PyGenericAlias, PyTypeRef};
use crate::common::{hash::PyHash, lock::PyMutex};
use crate::{
class::PyClassImpl,
convert::{ToPyObject, TransmuteFromObject, TryFromBorrowedObject},
function::{OptionalArg, PyArithmeticValue, PyComparisonValue},
protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods},
pyclass::PyClassImpl,
recursion::ReprGuard,
sequence::{ObjectSequenceOp, SequenceOp},
sliceable::{SequenceIndex, SliceableSequenceOp},
@@ -113,7 +113,8 @@ impl Constructor for PyTuple {
Self {
elements: elements.into_boxed_slice(),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
}

View File

@@ -1,6 +1,6 @@
use super::{
mappingproxy::PyMappingProxy, object, pyunion, PyClassMethod, PyDictRef, PyList,
PyStaticMethod, PyStr, PyStrRef, PyTuple, PyTupleRef, PyWeak,
mappingproxy::PyMappingProxy, object, union_, PyClassMethod, PyDictRef, PyList, PyStaticMethod,
PyStr, PyStrRef, PyTuple, PyTupleRef, PyWeak,
};
use crate::common::{
ascii,
@@ -8,8 +8,8 @@ use crate::common::{
lock::{PyRwLock, PyRwLockReadGuard},
};
use crate::{
class::{PyClassImpl, StaticType},
function::{FuncArgs, KwArgs, OptionalArg},
pyclass::{PyClassImpl, StaticType},
types::{Callable, GetAttr, PyTypeFlags, PyTypeSlots, SetAttr},
AsObject, Context, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -402,12 +402,12 @@ impl PyType {
#[pymethod(name = "__ror__")]
#[pymethod(magic)]
pub fn or(zelf: PyObjectRef, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
if !pyunion::is_unionable(zelf.clone(), vm) || !pyunion::is_unionable(other.clone(), vm) {
if !union_::is_unionable(zelf.clone(), vm) || !union_::is_unionable(other.clone(), vm) {
return vm.ctx.not_implemented();
}
let tuple = PyTuple::new_ref(vec![zelf, other], &vm.ctx);
pyunion::make_union(tuple, vm)
union_::make_union(tuple, vm)
}
#[pyslot]

View File

@@ -1,11 +1,11 @@
use super::genericalias;
use crate::{
builtins::{PyFrozenSet, PyStr, PyStrRef, PyTuple, PyTupleRef, PyTypeRef},
class::PyClassImpl,
common::hash,
convert::ToPyObject,
function::PyComparisonValue,
protocol::PyMappingMethods,
pyclass::PyClassImpl,
types::{AsMapping, Comparable, GetAttr, Hashable, Iterable, PyComparisonOp},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
VirtualMachine,

View File

@@ -1,7 +1,7 @@
use super::{PyStrRef, PyTypeRef, PyWeak};
use crate::{
class::PyClassImpl,
function::OptionalArg,
pyclass::PyClassImpl,
types::{Constructor, SetAttr},
Context, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -48,7 +48,8 @@ impl Constructor for PyWeakProxy {
PyWeakProxy {
weak: referent.downgrade_with_typ(callback.into_option(), weak_cls.clone(), vm)?,
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -4,13 +4,13 @@ use crate::common::{
hash::{self, PyHash},
};
use crate::{
class::PyClassImpl,
function::OptionalArg,
pyclass::PyClassImpl,
types::{Callable, Comparable, Constructor, Hashable, PyComparisonOp},
AsObject, Context, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
pub use crate::pyobject::PyWeak;
pub use crate::object::PyWeak;
#[derive(FromArgs)]
pub struct WeakNewArgs {

View File

@@ -1,9 +1,9 @@
use super::PyTypeRef;
use crate::{
builtins::PyTupleRef,
class::PyClassImpl,
function::{ArgIntoBool, OptionalArg, PosArgs},
protocol::{PyIter, PyIterReturn},
pyclass::PyClassImpl,
types::{Constructor, IterNext, IterNextIterable},
AsObject, Context, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
};
@@ -34,7 +34,9 @@ impl Constructor for PyZip {
fn py_new(cls: PyTypeRef, (iterators, args): Self::Args, vm: &VirtualMachine) -> PyResult {
let iterators = iterators.into_vec();
let strict = Radium::new(args.strict.unwrap_or(false));
PyZip { iterators, strict }.into_pyresult_with_type(vm, cls)
PyZip { iterators, strict }
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -2,7 +2,7 @@
use crate::{
builtins::{PyBaseObject, PyBoundMethod, PyType, PyTypeRef},
pyobject::{PyObjectPayload, PyObjectRef, PyRef},
object::{PyObjectPayload, PyObjectRef, PyRef},
types::{PyTypeFlags, PyTypeSlots},
vm::Context,
};

View File

@@ -1,5 +1,5 @@
use crate::{
pyobject::{AsObject, PyObject, PyPayload, PyRef, PyResult},
object::{AsObject, PyObject, PyPayload, PyRef, PyResult},
vm::VirtualMachine,
};

View File

@@ -1,5 +1,5 @@
use crate::{
pyobject::{AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult},
object::{AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult},
vm::VirtualMachine,
};

View File

@@ -4,10 +4,10 @@ use crate::{
builtins::{
traceback::PyTracebackRef, PyNone, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType, PyTypeRef,
},
class::{PyClassImpl, StaticType},
convert::{ToPyException, ToPyObject},
function::{ArgIterable, FuncArgs},
py_io::{self, Write},
pyclass::{PyClassImpl, StaticType},
stdlib::sys,
suggestion::offer_suggestions,
AsObject, Context, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
@@ -427,7 +427,9 @@ impl PyBaseException {
#[pyslot]
pub(crate) fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
PyBaseException::new(args.args, vm).into_pyresult_with_type(vm, cls)
PyBaseException::new(args.args, vm)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
#[pymethod(magic)]

View File

@@ -16,8 +16,8 @@ use crate::{
scope::Scope,
stdlib::builtins,
types::PyComparisonOp,
AsObject, PyMethod, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
VirtualMachine,
vm::PyMethod,
AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
};
use indexmap::IndexMap;
use itertools::Itertools;

View File

@@ -1,6 +1,6 @@
use crate::{
convert::{ToPyObject, TryFromObject},
pyobject::{AsObject, PyObjectRef, PyResult},
object::{AsObject, PyObjectRef, PyResult},
VirtualMachine,
};

View File

@@ -1,7 +1,6 @@
use super::{FromArgs, FuncArgs};
use crate::{
convert::ToPyResult, pyobject::PyThreadingConstraint, PyPayload, PyRef, PyResult,
VirtualMachine,
convert::ToPyResult, object::PyThreadingConstraint, PyPayload, PyRef, PyResult, VirtualMachine,
};
use std::marker::PhantomData;

View File

@@ -67,7 +67,7 @@ impl std::borrow::Borrow<str> for CachedPyStrRef {
}
mod sealed {
use crate::{builtins::PyStr, pyobject::PyRefExact};
use crate::{builtins::PyStr, object::PyRefExact};
pub trait SealedInternable {}

View File

@@ -38,15 +38,12 @@ pub use rustpython_derive::*;
#[macro_use]
pub(crate) mod macros;
#[path = "pyobject.rs"]
mod _pyobject;
#[path = "pyobjectrc.rs"]
mod _pyobjectrc;
mod anystr;
pub mod buffer;
pub mod builtins;
mod bytesinner;
pub mod cformat;
pub mod class;
mod codecs;
pub mod convert;
mod coroutine;
@@ -62,10 +59,11 @@ mod frozen;
pub mod function;
pub mod import;
mod intern;
pub mod object;
pub mod prelude;
pub mod protocol;
pub mod py_io;
pub mod py_serde;
pub mod pyclass;
pub mod readline;
pub mod recursion;
pub mod scope;
@@ -77,18 +75,12 @@ pub mod suggestion;
pub mod types;
pub mod utils;
pub mod version;
mod vm;
mod pyobject {
pub use super::_pyobject::*;
pub use super::_pyobjectrc::*;
}
pub mod vm;
pub use self::convert::{TryFromBorrowedObject, TryFromObject};
// pyobject items
pub use self::pyobject::{AsObject, PyMethod, PyPayload, PyRefExact, PyResult};
// pyobjectrc items
pub use self::pyobject::{Py, PyObject, PyObjectRef, PyRef, PyWeakRef};
pub use self::object::{
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult, PyWeakRef,
};
pub use self::types::PyStructSequence;
pub use self::vm::{Context, InitParameter, Interpreter, Settings, VirtualMachine};

View File

@@ -49,7 +49,7 @@ macro_rules! py_namespace {
{
let namespace = $crate::builtins::PyNamespace::new_ref(&$vm.ctx);
$(
$vm.__module_set_attr($crate::pyobject::AsObject::as_object(&namespace), $name, $value).unwrap();
$vm.__module_set_attr($crate::object::AsObject::as_object(&namespace), $name, $value).unwrap();
)*
namespace
}

View File

@@ -11,23 +11,30 @@
//! PyRef<PyWeak> may looking like to be called as PyObjectWeak by the rule,
//! but not to do to remember it is a PyRef object.
use crate::common::atomic::{OncePtr, PyAtomic, Radium};
use crate::common::linked_list::{Link, LinkedList, Pointers};
use crate::common::lock::{PyMutex, PyMutexGuard, PyRwLock};
use crate::common::refcount::RefCount;
use super::{
ext::{AsObject, PyResult},
payload::PyObjectPayload,
};
use crate::common::{
atomic::{OncePtr, PyAtomic, Radium},
linked_list::{Link, LinkedList, Pointers},
lock::{PyMutex, PyMutexGuard, PyRwLock},
refcount::RefCount,
};
use crate::{
_pyobject::{AsObject, PyObjectPayload, PyResult},
builtins::{PyBaseExceptionRef, PyDictRef, PyTypeRef},
builtins::{PyDictRef, PyTypeRef},
vm::VirtualMachine,
};
use std::any::TypeId;
use std::borrow::Borrow;
use std::cell::UnsafeCell;
use std::fmt;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::ptr::{self, NonNull};
use std::{
any::TypeId,
borrow::Borrow,
cell::UnsafeCell,
fmt,
marker::PhantomData,
mem::ManuallyDrop,
ops::Deref,
ptr::{self, NonNull},
};
// so, PyObjectRef is basically equivalent to `PyRc<PyInner<dyn PyObjectPayload>>`, except it's
// only one pointer in width rather than 2. We do that by manually creating a vtable, and putting
@@ -732,7 +739,8 @@ impl PyObject {
let ret = crate::vm::thread::with_vm(self, |vm| {
self.0.ref_count.inc();
if let Err(e) = slot_del(self, vm) {
print_del_error(e, self, vm);
let del_method = self.get_class_attr("__del__").unwrap();
vm.run_unraisable(e, None, del_method);
}
self.0.ref_count.dec()
});
@@ -804,26 +812,6 @@ impl Drop for PyObjectRef {
}
}
#[cold]
fn print_del_error(e: PyBaseExceptionRef, zelf: &PyObject, vm: &VirtualMachine) {
// exception in del will be ignored but printed
print!("Exception ignored in: ",);
let del_method = zelf.get_class_attr("__del__").unwrap();
let repr = &del_method.repr(vm);
match repr {
Ok(v) => println!("{v}"),
Err(_) => println!("{}", del_method.class().name()),
}
let tb_module = vm.import("traceback", None, 0).unwrap();
// TODO: set exc traceback
let print_stack = tb_module.get_attr("print_stack", vm).unwrap();
vm.invoke(&print_stack, ()).unwrap();
if let Ok(repr) = e.as_object().repr(vm) {
println!("{}", repr.as_str());
}
}
impl fmt::Debug for PyObjectRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// SAFETY: the vtable contains functions that accept payload types that always match up
@@ -1057,7 +1045,7 @@ macro_rules! partially_init {
pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) {
use crate::{
builtins::{object, PyType},
pyclass::PyClassImpl,
class::PyClassImpl,
};
use std::mem::MaybeUninit;

276
vm/src/object/ext.rs Normal file
View File

@@ -0,0 +1,276 @@
use super::{
core::{Py, PyObject, PyObjectRef, PyRef},
payload::{PyObjectPayload, PyPayload},
};
use crate::common::lock::PyRwLockReadGuard;
use crate::{
builtins::{PyBaseExceptionRef, PyType},
convert::{ToPyObject, ToPyResult, TryFromObject},
VirtualMachine,
};
use std::{borrow::Borrow, fmt, ops::Deref};
/* Python objects and references.
Okay, so each python object itself is an class itself (PyObject). Each
python object can have several references to it (PyObjectRef). These
references are Rc (reference counting) rust smart pointers. So when
all references are destroyed, the object itself also can be cleaned up.
Basically reference counting, but then done by rust.
*/
/*
* Good reference: https://github.com/ProgVal/pythonvm-rust/blob/master/src/objects/mod.rs
*/
/// Use this type for functions which return a python object or an exception.
/// Both the python object and the python exception are `PyObjectRef` types
/// since exceptions are also python objects.
pub type PyResult<T = PyObjectRef> = Result<T, PyBaseExceptionRef>; // A valid value, or an exception
// TODO: remove these 2 impls
impl fmt::Display for PyObjectRef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(**self).fmt(f)
}
}
impl fmt::Display for PyObject {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "'{}' object", self.class().name())
}
}
impl<T: fmt::Display> fmt::Display for PyRef<T>
where
T: PyObjectPayload + fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: fmt::Display> fmt::Display for Py<T>
where
T: PyObjectPayload + fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
#[derive(Debug)]
pub struct PyRefExact<T: PyObjectPayload> {
inner: PyRef<T>,
}
impl<T: PyObjectPayload> PyRefExact<T> {
/// # Safety
/// obj must have exact type for the payload
pub unsafe fn new_unchecked(obj: PyRef<T>) -> Self {
Self { inner: obj }
}
pub fn into_pyref(self) -> PyRef<T> {
self.inner
}
}
impl<T: PyObjectPayload> Clone for PyRefExact<T> {
fn clone(&self) -> Self {
let inner = self.inner.clone();
Self { inner }
}
}
impl<T: PyPayload> TryFromObject for PyRefExact<T> {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
let target_cls = T::class(vm);
let cls = obj.class();
if cls.is(target_cls) {
drop(cls);
let obj = obj
.downcast()
.map_err(|obj| vm.new_downcast_runtime_error(target_cls, &obj))?;
Ok(Self { inner: obj })
} else if cls.fast_issubclass(target_cls) {
Err(vm.new_type_error(format!(
"Expected an exact instance of '{}', not a subclass '{}'",
target_cls.name(),
cls.name(),
)))
} else {
Err(vm.new_type_error(format!(
"Expected type '{}', not '{}'",
target_cls.name(),
cls.name(),
)))
}
}
}
impl<T: PyPayload> Deref for PyRefExact<T> {
type Target = PyRef<T>;
#[inline(always)]
fn deref(&self) -> &PyRef<T> {
&self.inner
}
}
impl<T: PyPayload> ToPyObject for PyRefExact<T> {
#[inline(always)]
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
self.inner.into()
}
}
pub trait AsObject
where
Self: Borrow<PyObject>,
{
#[inline(always)]
fn as_object(&self) -> &PyObject {
self.borrow()
}
#[inline(always)]
fn get_id(&self) -> usize {
self.as_object().unique_id()
}
#[inline(always)]
fn is<T>(&self, other: &T) -> bool
where
T: AsObject,
{
self.get_id() == other.get_id()
}
#[inline(always)]
fn class(&self) -> PyLease<'_, PyType> {
self.as_object().lease_class()
}
fn get_class_attr(&self, attr_name: &str) -> Option<PyObjectRef> {
self.class().get_attr(attr_name)
}
/// Determines if `obj` actually an instance of `cls`, this doesn't call __instancecheck__, so only
/// use this if `cls` is known to have not overridden the base __instancecheck__ magic method.
#[inline]
fn fast_isinstance(&self, cls: &Py<PyType>) -> bool {
self.class().fast_issubclass(cls)
}
}
impl<T> AsObject for T where T: Borrow<PyObject> {}
impl PyObject {
#[inline(always)]
fn unique_id(&self) -> usize {
self as *const PyObject as usize
}
#[inline]
fn lease_class(&self) -> PyLease<'_, PyType> {
PyLease {
inner: self.class_lock().read(),
}
}
}
// impl<T: ?Sized> Borrow<PyObject> for PyRc<T> {
// #[inline(always)]
// fn borrow(&self) -> &PyObject {
// unsafe { &*(&**self as *const T as *const PyObject) }
// }
// }
/// A borrow of a reference to a Python object. This avoids having clone the `PyRef<T>`/
/// `PyObjectRef`, which isn't that cheap as that increments the atomic reference counter.
pub struct PyLease<'a, T: PyObjectPayload> {
inner: PyRwLockReadGuard<'a, PyRef<T>>,
}
impl<'a, T: PyObjectPayload + PyPayload> PyLease<'a, T> {
#[inline(always)]
pub fn into_owned(self) -> PyRef<T> {
self.inner.clone()
}
}
impl<'a, T: PyObjectPayload + PyPayload> Borrow<PyObject> for PyLease<'a, T> {
#[inline(always)]
fn borrow(&self) -> &PyObject {
self.inner.as_ref()
}
}
impl<'a, T: PyObjectPayload + PyPayload> Deref for PyLease<'a, T> {
type Target = PyRef<T>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a, T> fmt::Display for PyLease<'a, T>
where
T: PyPayload + fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: PyObjectPayload> ToPyObject for PyRef<T> {
#[inline(always)]
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
self.into()
}
}
impl ToPyObject for PyObjectRef {
#[inline(always)]
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
self
}
}
impl ToPyObject for &PyObject {
#[inline(always)]
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
self.to_owned()
}
}
// Allows a built-in function to return any built-in object payload without
// explicitly implementing `ToPyObject`.
impl<T> ToPyObject for T
where
T: PyPayload + Sized,
{
#[inline(always)]
fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
PyPayload::into_pyobject(self, vm)
}
}
impl<T> ToPyResult for T
where
T: ToPyObject,
{
#[inline(always)]
fn to_pyresult(self, vm: &VirtualMachine) -> PyResult {
Ok(self.to_pyobject(vm))
}
}
impl<T> ToPyResult for PyResult<T>
where
T: ToPyObject,
{
#[inline(always)]
fn to_pyresult(self, vm: &VirtualMachine) -> PyResult {
self.map(|res| T::to_pyobject(res, vm))
}
}

7
vm/src/object/mod.rs Normal file
View File

@@ -0,0 +1,7 @@
mod core;
mod ext;
mod payload;
pub use self::core::*;
pub use self::ext::*;
pub use self::payload::*;

76
vm/src/object/payload.rs Normal file
View File

@@ -0,0 +1,76 @@
use super::{PyObject, PyObjectRef, PyRef, PyResult};
use crate::{
builtins::{PyBaseExceptionRef, PyTypeRef},
types::PyTypeFlags,
vm::VirtualMachine,
};
cfg_if::cfg_if! {
if #[cfg(feature = "threading")] {
pub trait PyThreadingConstraint: Send + Sync {}
impl<T: Send + Sync> PyThreadingConstraint for T {}
} else {
pub trait PyThreadingConstraint {}
impl<T> PyThreadingConstraint for T {}
}
}
pub trait PyPayload: std::fmt::Debug + PyThreadingConstraint + Sized + 'static {
fn class(vm: &VirtualMachine) -> &PyTypeRef;
#[inline]
fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
self.into_ref(vm).into()
}
#[inline(always)]
fn special_retrieve(_vm: &VirtualMachine, _obj: &PyObject) -> Option<PyResult<PyRef<Self>>> {
None
}
#[inline]
fn _into_ref(self, cls: PyTypeRef, vm: &VirtualMachine) -> PyRef<Self> {
let dict = if cls.slots.flags.has_feature(PyTypeFlags::HAS_DICT) {
Some(vm.ctx.new_dict())
} else {
None
};
PyRef::new_ref(self, cls, dict)
}
#[inline]
fn into_ref(self, vm: &VirtualMachine) -> PyRef<Self> {
let cls = Self::class(vm);
self._into_ref(cls.clone(), vm)
}
#[inline]
fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult<PyRef<Self>> {
let exact_class = Self::class(vm);
if cls.fast_issubclass(exact_class) {
Ok(self._into_ref(cls, vm))
} else {
#[cold]
#[inline(never)]
fn _into_ref_with_type_error(
vm: &VirtualMachine,
cls: &PyTypeRef,
exact_class: &PyTypeRef,
) -> PyBaseExceptionRef {
vm.new_type_error(format!(
"'{}' is not a subtype of '{}'",
&cls.name(),
exact_class.name()
))
}
Err(_into_ref_with_type_error(vm, &cls, exact_class))
}
}
}
pub trait PyObjectPayload:
std::any::Any + std::fmt::Debug + PyThreadingConstraint + 'static
{
}
impl<T: PyPayload + 'static> PyObjectPayload for T {}

6
vm/src/prelude.rs Normal file
View File

@@ -0,0 +1,6 @@
pub use crate::{
object::{
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult, PyWeakRef,
},
vm::{Context, InitParameter, Interpreter, Settings, VirtualMachine},
};

View File

@@ -6,7 +6,7 @@ use crate::{
borrow::{BorrowedValue, BorrowedValueMut},
lock::{MapImmutable, PyMutex, PyMutexGuard},
},
pyobject::PyObjectPayload,
object::PyObjectPayload,
sliceable::wrap_index,
types::{Constructor, Unconstructible},
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromBorrowedObject,

View File

@@ -3,7 +3,7 @@ use num_traits::sign::Signed;
use serde::de::{DeserializeSeed, Visitor};
use serde::ser::{Serialize, SerializeMap, SerializeSeq};
use crate::builtins::{dict::PyDictRef, float, int, list::PyList, pybool, tuple::PyTuple, PyStr};
use crate::builtins::{bool_, dict::PyDictRef, float, int, list::PyList, tuple::PyTuple, PyStr};
use crate::{AsObject, PyObject, PyObjectRef, VirtualMachine};
#[inline]
@@ -67,7 +67,7 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
} else if self.pyobject.fast_isinstance(&self.vm.ctx.types.float_type) {
serializer.serialize_f64(float::get_value(self.pyobject))
} else if self.pyobject.fast_isinstance(&self.vm.ctx.types.bool_type) {
serializer.serialize_bool(pybool::get_value(self.pyobject))
serializer.serialize_bool(bool_::get_value(self.pyobject))
} else if self.pyobject.fast_isinstance(&self.vm.ctx.types.int_type) {
let v = int::get_value(self.pyobject);
let int_too_large = || serde::ser::Error::custom("int too large to serialize");

View File

@@ -1,495 +0,0 @@
use crate::common::lock::PyRwLockReadGuard;
use crate::{
builtins::{object, pystr, PyBaseExceptionRef, PyType, PyTypeRef},
convert::{ToPyObject, ToPyResult, TryFromObject},
function::IntoFuncArgs,
types::PyTypeFlags,
VirtualMachine,
_pyobjectrc::{Py, PyObject, PyObjectRef, PyRef},
};
use std::{any::Any, borrow::Borrow, fmt, ops::Deref};
/* Python objects and references.
Okay, so each python object itself is an class itself (PyObject). Each
python object can have several references to it (PyObjectRef). These
references are Rc (reference counting) rust smart pointers. So when
all references are destroyed, the object itself also can be cleaned up.
Basically reference counting, but then done by rust.
*/
/*
* Good reference: https://github.com/ProgVal/pythonvm-rust/blob/master/src/objects/mod.rs
*/
/// Use this type for functions which return a python object or an exception.
/// Both the python object and the python exception are `PyObjectRef` types
/// since exceptions are also python objects.
pub type PyResult<T = PyObjectRef> = Result<T, PyBaseExceptionRef>; // A valid value, or an exception
// TODO: remove these 2 impls
impl fmt::Display for PyObjectRef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(**self).fmt(f)
}
}
impl fmt::Display for PyObject {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "'{}' object", self.class().name())
}
}
impl<T: fmt::Display> fmt::Display for PyRef<T>
where
T: PyObjectPayload + fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: fmt::Display> fmt::Display for Py<T>
where
T: PyObjectPayload + fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
#[derive(Debug)]
pub struct PyRefExact<T: PyObjectPayload> {
inner: PyRef<T>,
}
impl<T: PyObjectPayload> PyRefExact<T> {
/// # Safety
/// obj must have exact type for the payload
pub unsafe fn new_unchecked(obj: PyRef<T>) -> Self {
Self { inner: obj }
}
pub fn into_pyref(self) -> PyRef<T> {
self.inner
}
}
impl<T: PyObjectPayload> Clone for PyRefExact<T> {
fn clone(&self) -> Self {
let inner = self.inner.clone();
Self { inner }
}
}
impl<T: PyPayload> TryFromObject for PyRefExact<T> {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
let target_cls = T::class(vm);
let cls = obj.class();
if cls.is(target_cls) {
drop(cls);
let obj = obj
.downcast()
.map_err(|obj| vm.new_downcast_runtime_error(target_cls, &obj))?;
Ok(Self { inner: obj })
} else if cls.fast_issubclass(target_cls) {
Err(vm.new_type_error(format!(
"Expected an exact instance of '{}', not a subclass '{}'",
target_cls.name(),
cls.name(),
)))
} else {
Err(vm.new_type_error(format!(
"Expected type '{}', not '{}'",
target_cls.name(),
cls.name(),
)))
}
}
}
impl<T: PyPayload> Deref for PyRefExact<T> {
type Target = PyRef<T>;
#[inline(always)]
fn deref(&self) -> &PyRef<T> {
&self.inner
}
}
impl<T: PyPayload> ToPyObject for PyRefExact<T> {
#[inline(always)]
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
self.inner.into()
}
}
pub trait AsObject
where
Self: Borrow<PyObject>,
{
#[inline(always)]
fn as_object(&self) -> &PyObject {
self.borrow()
}
#[inline(always)]
fn get_id(&self) -> usize {
self.as_object().unique_id()
}
#[inline(always)]
fn is<T>(&self, other: &T) -> bool
where
T: AsObject,
{
self.get_id() == other.get_id()
}
#[inline(always)]
fn class(&self) -> PyLease<'_, PyType> {
self.as_object().lease_class()
}
fn get_class_attr(&self, attr_name: &str) -> Option<PyObjectRef> {
self.class().get_attr(attr_name)
}
/// Determines if `obj` actually an instance of `cls`, this doesn't call __instancecheck__, so only
/// use this if `cls` is known to have not overridden the base __instancecheck__ magic method.
#[inline]
fn fast_isinstance(&self, cls: &Py<PyType>) -> bool {
self.class().fast_issubclass(cls)
}
}
impl<T> AsObject for T where T: Borrow<PyObject> {}
impl PyObject {
#[inline(always)]
fn unique_id(&self) -> usize {
self as *const PyObject as usize
}
#[inline]
fn lease_class(&self) -> PyLease<'_, PyType> {
PyLease {
inner: self.class_lock().read(),
}
}
}
// impl<T: ?Sized> Borrow<PyObject> for PyRc<T> {
// #[inline(always)]
// fn borrow(&self) -> &PyObject {
// unsafe { &*(&**self as *const T as *const PyObject) }
// }
// }
/// A borrow of a reference to a Python object. This avoids having clone the `PyRef<T>`/
/// `PyObjectRef`, which isn't that cheap as that increments the atomic reference counter.
pub struct PyLease<'a, T: PyObjectPayload> {
inner: PyRwLockReadGuard<'a, PyRef<T>>,
}
impl<'a, T: PyObjectPayload + PyPayload> PyLease<'a, T> {
#[inline(always)]
pub fn into_owned(self) -> PyRef<T> {
self.inner.clone()
}
}
impl<'a, T: PyObjectPayload + PyPayload> Borrow<PyObject> for PyLease<'a, T> {
#[inline(always)]
fn borrow(&self) -> &PyObject {
self.inner.as_ref()
}
}
impl<'a, T: PyObjectPayload + PyPayload> Deref for PyLease<'a, T> {
type Target = PyRef<T>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a, T> fmt::Display for PyLease<'a, T>
where
T: PyPayload + fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: PyObjectPayload> ToPyObject for PyRef<T> {
#[inline(always)]
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
self.into()
}
}
impl ToPyObject for PyObjectRef {
#[inline(always)]
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
self
}
}
impl ToPyObject for &PyObject {
#[inline(always)]
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
self.to_owned()
}
}
// Allows a built-in function to return any built-in object payload without
// explicitly implementing `ToPyObject`.
impl<T> ToPyObject for T
where
T: PyPayload + Sized,
{
#[inline(always)]
fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
PyPayload::into_pyobject(self, vm)
}
}
impl<T> ToPyResult for T
where
T: ToPyObject,
{
#[inline(always)]
fn to_pyresult(self, vm: &VirtualMachine) -> PyResult {
Ok(self.to_pyobject(vm))
}
}
impl<T> ToPyResult for PyResult<T>
where
T: ToPyObject,
{
#[inline(always)]
fn to_pyresult(self, vm: &VirtualMachine) -> PyResult {
self.map(|res| T::to_pyobject(res, vm))
}
}
cfg_if::cfg_if! {
if #[cfg(feature = "threading")] {
pub trait PyThreadingConstraint: Send + Sync {}
impl<T: Send + Sync> PyThreadingConstraint for T {}
} else {
pub trait PyThreadingConstraint {}
impl<T> PyThreadingConstraint for T {}
}
}
pub trait PyPayload: fmt::Debug + PyThreadingConstraint + Sized + 'static {
fn class(vm: &VirtualMachine) -> &PyTypeRef;
#[inline]
fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
self.into_ref(vm).into()
}
#[inline(always)]
fn special_retrieve(_vm: &VirtualMachine, _obj: &PyObject) -> Option<PyResult<PyRef<Self>>> {
None
}
#[inline]
fn _into_ref(self, cls: PyTypeRef, vm: &VirtualMachine) -> PyRef<Self> {
let dict = if cls.slots.flags.has_feature(PyTypeFlags::HAS_DICT) {
Some(vm.ctx.new_dict())
} else {
None
};
PyRef::new_ref(self, cls, dict)
}
#[inline]
fn into_ref(self, vm: &VirtualMachine) -> PyRef<Self> {
let cls = Self::class(vm);
self._into_ref(cls.clone(), vm)
}
#[cold]
fn _into_ref_with_type_error(
vm: &VirtualMachine,
cls: &PyTypeRef,
exact_class: &PyTypeRef,
) -> PyBaseExceptionRef {
vm.new_type_error(format!(
"'{}' is not a subtype of '{}'",
&cls.name(),
exact_class.name()
))
}
#[inline]
fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult<PyRef<Self>> {
let exact_class = Self::class(vm);
if cls.fast_issubclass(exact_class) {
Ok(self._into_ref(cls, vm))
} else {
Err(Self::_into_ref_with_type_error(vm, &cls, exact_class))
}
}
#[inline]
fn into_pyresult_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult {
self.into_ref_with_type(vm, cls).to_pyresult(vm)
}
}
pub trait PyObjectPayload: Any + fmt::Debug + PyThreadingConstraint + 'static {}
impl<T: PyPayload + 'static> PyObjectPayload for T {}
pub trait PyObjectWrap
where
Self: AsObject,
{
fn into_object(self) -> PyObjectRef;
}
impl<T> From<T> for PyObjectRef
where
T: PyObjectWrap,
{
#[inline(always)]
fn from(py_ref: T) -> Self {
py_ref.into_object()
}
}
#[derive(Debug)]
pub enum PyMethod {
Function {
target: PyObjectRef,
func: PyObjectRef,
},
Attribute(PyObjectRef),
}
impl PyMethod {
pub fn get(obj: PyObjectRef, name: pystr::PyStrRef, vm: &VirtualMachine) -> PyResult<Self> {
let cls = obj.class();
let getattro = cls.mro_find_map(|cls| cls.slots.getattro.load()).unwrap();
if getattro as usize != object::PyBaseObject::getattro as usize {
drop(cls);
return obj.get_attr(name, vm).map(Self::Attribute);
}
let mut is_method = false;
let cls_attr = match cls.get_attr(name.as_str()) {
Some(descr) => {
let descr_cls = descr.class();
let descr_get = if descr_cls.slots.flags.has_feature(PyTypeFlags::METHOD_DESCR) {
is_method = true;
None
} else {
let descr_get = descr_cls.mro_find_map(|cls| cls.slots.descr_get.load());
if let Some(descr_get) = descr_get {
if descr_cls
.mro_find_map(|cls| cls.slots.descr_set.load())
.is_some()
{
drop(descr_cls);
let cls = cls.into_owned().into();
return descr_get(descr, Some(obj), Some(cls), vm).map(Self::Attribute);
}
}
descr_get
};
drop(descr_cls);
Some((descr, descr_get))
}
None => None,
};
if let Some(dict) = obj.dict() {
if let Some(attr) = dict.get_item_opt(name.clone(), vm)? {
return Ok(Self::Attribute(attr));
}
}
if let Some((attr, descr_get)) = cls_attr {
match descr_get {
None if is_method => {
drop(cls);
Ok(Self::Function {
target: obj,
func: attr,
})
}
Some(descr_get) => {
let cls = cls.into_owned().into();
descr_get(attr, Some(obj), Some(cls), vm).map(Self::Attribute)
}
None => Ok(Self::Attribute(attr)),
}
} else if let Some(getter) = cls.get_attr("__getattr__") {
drop(cls);
vm.invoke(&getter, (obj, name)).map(Self::Attribute)
} else {
let exc = vm.new_attribute_error(format!(
"'{}' object has no attribute '{}'",
cls.name(),
name
));
vm.set_attribute_error_context(&exc, obj.clone(), name);
Err(exc)
}
}
pub(crate) fn get_special(
obj: PyObjectRef,
name: &str,
vm: &VirtualMachine,
) -> PyResult<Result<Self, PyObjectRef>> {
let obj_cls = obj.class();
let func = match obj_cls.get_attr(name) {
Some(f) => f,
None => {
drop(obj_cls);
return Ok(Err(obj));
}
};
let meth = if func
.class()
.slots
.flags
.has_feature(PyTypeFlags::METHOD_DESCR)
{
drop(obj_cls);
Self::Function { target: obj, func }
} else {
let obj_cls = obj_cls.into_owned().into();
let attr = vm
.call_get_descriptor_specific(func, Some(obj), Some(obj_cls))
.unwrap_or_else(Ok)?;
Self::Attribute(attr)
};
Ok(Ok(meth))
}
pub fn invoke(self, args: impl IntoFuncArgs, vm: &VirtualMachine) -> PyResult {
let (func, args) = match self {
PyMethod::Function { target, func } => (func, args.into_method_args(target, vm)),
PyMethod::Attribute(func) => (func, args.into_args(vm)),
};
vm.invoke(&func, args)
}
pub fn invoke_ref(&self, args: impl IntoFuncArgs, vm: &VirtualMachine) -> PyResult {
let (func, args) = match self {
PyMethod::Function { target, func } => {
(func, args.into_method_args(target.clone(), vm))
}
PyMethod::Attribute(func) => (func, args.into_args(vm)),
};
vm.invoke(func, args)
}
}

View File

@@ -7,7 +7,7 @@ mod gen;
use crate::{
builtins::{self, PyStrRef, PyTypeRef},
pyclass::{PyClassImpl, StaticType},
class::{PyClassImpl, StaticType},
AsObject, Context, PyObject, PyObjectRef, PyPayload, PyResult, TryFromObject, VirtualMachine,
};
use num_complex::Complex64;

View File

@@ -33,24 +33,17 @@ mod atexit {
}
#[pyfunction]
pub fn _run_exitfuncs(vm: &VirtualMachine) -> PyResult<()> {
let mut last_exc = None;
for (func, args) in vm.state.atexit_funcs.lock().drain(..).rev() {
pub fn _run_exitfuncs(vm: &VirtualMachine) {
let funcs: Vec<_> = std::mem::take(&mut *vm.state.atexit_funcs.lock());
for (func, args) in funcs.into_iter().rev() {
if let Err(e) = vm.invoke(&func, args) {
last_exc = Some(e.clone());
if !e.fast_isinstance(&vm.ctx.exceptions.system_exit) {
writeln!(
crate::stdlib::sys::PyStderr(vm),
"Error in atexit._run_exitfuncs:"
);
vm.print_exception(e);
let exit = e.fast_isinstance(&vm.ctx.exceptions.system_exit);
vm.run_unraisable(e, Some("Error in atexit._run_exitfuncs".to_owned()), func);
if exit {
break;
}
}
}
match last_exc {
None => Ok(()),
Some(e) => Err(e),
}
}
#[pyfunction]

View File

@@ -1,7 +1,7 @@
//! Builtin function definitions.
//!
//! Implements the list of [builtin Python functions](https://docs.python.org/3/library/builtins.html).
use crate::{pyclass::PyClassImpl, PyObjectRef, VirtualMachine};
use crate::{class::PyClassImpl, PyObjectRef, VirtualMachine};
/// Built-in functions, exceptions, and other objects.
///
@@ -21,6 +21,7 @@ mod builtins {
PyByteArray, PyBytes, PyBytesRef, PyCode, PyDictRef, PyStr, PyStrRef, PyTuple,
PyTupleRef, PyType,
},
class::PyClassImpl,
common::{hash::PyHash, str::to_ascii},
function::{
ArgBytesLike, ArgCallable, ArgIntoBool, ArgIterable, ArgMapping, FuncArgs, KwArgs,
@@ -28,7 +29,6 @@ mod builtins {
},
protocol::{PyIter, PyIterReturn},
py_io,
pyclass::PyClassImpl,
readline::{Readline, ReadlineResult},
scope::Scope,
stdlib::sys,

View File

@@ -58,7 +58,9 @@ mod _collections {
impl PyDeque {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
PyDeque::default().into_pyresult_with_type(vm, cls)
PyDeque::default()
.into_ref_with_type(vm, cls)
.map(Into::into)
}
#[pymethod(magic)]
@@ -605,7 +607,7 @@ mod _collections {
let index = max(index, 0) as usize;
iter.internal.lock().position = index;
}
iter.into_pyresult_with_type(vm, cls)
iter.into_ref_with_type(vm, cls).map(Into::into)
}
}
@@ -678,7 +680,7 @@ mod _collections {
let index = max(index, 0) as usize;
iter.internal.lock().position = index;
}
iter.into_pyresult_with_type(vm, cls)
iter.into_ref_with_type(vm, cls).map(Into::into)
}
}

View File

@@ -99,6 +99,7 @@ mod _io {
PyBaseExceptionRef, PyByteArray, PyBytes, PyBytesRef, PyIntRef, PyMemoryView, PyStr,
PyStrRef, PyType, PyTypeRef,
},
class::StaticType,
common::lock::{
PyMappedThreadMutexGuard, PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard,
PyThreadMutex, PyThreadMutexGuard,
@@ -110,7 +111,6 @@ mod _io {
protocol::{
BufferDescriptor, BufferMethods, BufferResizeGuard, PyBuffer, PyIterReturn, VecBuffer,
},
pyclass::StaticType,
recursion::ReprGuard,
types::{Constructor, Destructor, IterNext, Iterable},
utils::Either,
@@ -1667,7 +1667,7 @@ mod _io {
impl BufferedReader {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
Self::default().into_pyresult_with_type(vm, cls)
Self::default().into_ref_with_type(vm, cls).map(Into::into)
}
}
@@ -1716,7 +1716,7 @@ mod _io {
impl BufferedWriter {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
Self::default().into_pyresult_with_type(vm, cls)
Self::default().into_ref_with_type(vm, cls).map(Into::into)
}
}
@@ -1754,7 +1754,7 @@ mod _io {
impl BufferedRandom {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
Self::default().into_pyresult_with_type(vm, cls)
Self::default().into_ref_with_type(vm, cls).map(Into::into)
}
}
@@ -1781,7 +1781,7 @@ mod _io {
impl BufferedRWPair {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
Self::default().into_pyresult_with_type(vm, cls)
Self::default().into_ref_with_type(vm, cls).map(Into::into)
}
#[pymethod(magic)]
fn init(
@@ -2176,7 +2176,7 @@ mod _io {
impl TextIOWrapper {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
Self::default().into_pyresult_with_type(vm, cls)
Self::default().into_ref_with_type(vm, cls).map(Into::into)
}
fn lock_opt(
@@ -3059,7 +3059,8 @@ mod _io {
buffer: PyRwLock::new(BufferedIO::new(Cursor::new(raw_bytes))),
closed: AtomicCell::new(false),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -3194,7 +3195,8 @@ mod _io {
closed: AtomicCell::new(false),
exports: AtomicCell::new(0),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -3823,7 +3825,8 @@ mod fileio {
mode: AtomicCell::new(Mode::empty()),
seekable: AtomicCell::new(None),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
#[pymethod(magic)]

View File

@@ -38,7 +38,8 @@ mod decl {
cur_idx: AtomicCell::new(0),
cached_iter: PyRwLock::new(None),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
#[pyclassmethod]
@@ -121,7 +122,9 @@ mod decl {
Self::Args { data, selector }: Self::Args,
vm: &VirtualMachine,
) -> PyResult {
PyItertoolsCompress { data, selector }.into_pyresult_with_type(vm, cls)
PyItertoolsCompress { data, selector }
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -184,7 +187,8 @@ mod decl {
cur: PyRwLock::new(start),
step,
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -218,7 +222,8 @@ mod decl {
saved: PyRwLock::new(Vec::new()),
index: AtomicCell::new(0),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -280,7 +285,9 @@ mod decl {
}
None => None,
};
PyItertoolsRepeat { object, times }.into_pyresult_with_type(vm, cls)
PyItertoolsRepeat { object, times }
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -353,7 +360,9 @@ mod decl {
Self::Args { function, iterable }: Self::Args,
vm: &VirtualMachine,
) -> PyResult {
PyItertoolsStarmap { function, iterable }.into_pyresult_with_type(vm, cls)
PyItertoolsStarmap { function, iterable }
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -407,7 +416,8 @@ mod decl {
iterable,
stop_flag: AtomicCell::new(false),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -471,7 +481,8 @@ mod decl {
iterable,
start_flag: AtomicCell::new(false),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -573,7 +584,8 @@ mod decl {
grouper: None,
}),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -784,7 +796,8 @@ mod decl {
stop,
step,
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -847,7 +860,8 @@ mod decl {
predicate,
iterable,
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -906,7 +920,8 @@ mod decl {
initial: args.initial.flatten(),
acc_value: PyRwLock::new(None),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -1091,7 +1106,8 @@ mod decl {
cur: AtomicCell::new(l.wrapping_sub(1)),
stop: AtomicCell::new(false),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -1193,7 +1209,8 @@ mod decl {
r: AtomicCell::new(r),
exhausted: AtomicCell::new(r > n),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -1283,7 +1300,8 @@ mod decl {
r: AtomicCell::new(r),
exhausted: AtomicCell::new(n == 0 && r > 0),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -1392,7 +1410,8 @@ mod decl {
r: AtomicCell::new(r),
exhausted: AtomicCell::new(r > n),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -1486,7 +1505,8 @@ mod decl {
iterators,
fillvalue,
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -1542,7 +1562,8 @@ mod decl {
iterator,
old: PyRwLock::new(None),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -10,8 +10,8 @@ mod decl {
bytecode,
convert::ToPyObject,
function::ArgBytesLike,
object::AsObject,
protocol::PyBuffer,
pyobject::AsObject,
PyObjectRef, PyResult, TryFromObject, VirtualMachine,
};
/// TODO

View File

@@ -490,7 +490,9 @@ mod _operator {
return Err(vm.new_type_error("attribute name must be a string".to_owned()));
}
}
PyAttrGetter { attrs }.into_pyresult_with_type(vm, cls)
PyAttrGetter { attrs }
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -555,7 +557,9 @@ mod _operator {
if args.args.is_empty() {
return Err(vm.new_type_error("itemgetter expected 1 argument, got 0.".to_owned()));
}
PyItemGetter { items: args.args }.into_pyresult_with_type(vm, cls)
PyItemGetter { items: args.args }
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
@@ -648,7 +652,9 @@ mod _operator {
fn py_new(cls: PyTypeRef, (name, args): Self::Args, vm: &VirtualMachine) -> PyResult {
if let Ok(name) = name.try_into_value(vm) {
PyMethodCaller { name, args }.into_pyresult_with_type(vm, cls)
PyMethodCaller { name, args }
.into_ref_with_type(vm, cls)
.map(Into::into)
} else {
Err(vm.new_type_error("method name must be a string".to_owned()))
}

View File

@@ -583,7 +583,8 @@ pub mod module {
SchedParam {
sched_priority: arg.sched_priority,
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -1,6 +1,6 @@
use crate::{convert::ToPyObject, PyObject, PyResult, VirtualMachine};
pub(crate) use sys::{MAXSIZE, MULTIARCH};
pub(crate) use sys::{UnraisableHookArgs, MAXSIZE, MULTIARCH};
#[pymodule]
mod sys {
@@ -16,7 +16,7 @@ mod sys {
types::PyStructSequence,
version,
vm::{Settings, VirtualMachine},
PyObjectRef, PyRef, PyRefExact, PyResult,
AsObject, PyObjectRef, PyRef, PyRefExact, PyResult,
};
use num_traits::ToPrimitive;
use std::{env, mem, path};
@@ -448,6 +448,66 @@ mod sys {
.into_struct_sequence(vm))
}
fn _unraisablehook(unraisable: UnraisableHookArgs, vm: &VirtualMachine) -> PyResult<()> {
use super::PyStderr;
let stderr = PyStderr(vm);
if !vm.is_none(&unraisable.object) {
if !vm.is_none(&unraisable.err_msg) {
write!(stderr, "{}: ", unraisable.err_msg.str(vm)?);
} else {
write!(stderr, "Exception ignored in: ");
}
// exception in del will be ignored but printed
let repr = &unraisable.object.repr(vm);
let str = match repr {
Ok(v) => v.to_string(),
Err(_) => format!(
"<object {} repr() failed>",
unraisable.object.class().name()
),
};
writeln!(stderr, "{str}");
} else if !vm.is_none(&unraisable.err_msg) {
writeln!(stderr, "{}:", unraisable.err_msg.str(vm)?);
}
// TODO: print received unraisable.exc_traceback
let tb_module = vm.import("traceback", None, 0)?;
let print_stack = tb_module.get_attr("print_stack", vm)?;
vm.invoke(&print_stack, ())?;
if vm.is_none(unraisable.exc_type.as_object()) {
// TODO: early return, but with what error?
}
assert!(unraisable
.exc_type
.fast_issubclass(&vm.ctx.exceptions.exception_type));
// TODO: print module name and qualname
if !vm.is_none(&unraisable.exc_value) {
write!(stderr, ": ");
if let Ok(str) = unraisable.exc_value.str(vm) {
write!(stderr, "{}", str.as_str());
} else {
write!(stderr, "<exception str() failed>");
}
}
writeln!(stderr);
// TODO: call file.flush()
Ok(())
}
#[pyattr]
#[pyfunction(name = "__unraisablehook__")]
fn unraisablehook(unraisable: UnraisableHookArgs, vm: &VirtualMachine) {
if let Err(e) = _unraisablehook(unraisable, vm) {
println!("{}", e.as_object().repr(vm).unwrap().as_str());
}
}
#[pyattr]
fn hash_info(vm: &VirtualMachine) -> PyTupleRef {
PyHashInfo::INFO.into_struct_sequence(vm)
@@ -672,6 +732,19 @@ mod sys {
#[cfg(windows)]
#[pyimpl(with(PyStructSequence))]
impl WindowsVersion {}
#[pyclass(noattr, module = "sys", name = "UnraisableHookArgs")]
#[derive(Debug, PyStructSequence, TryIntoPyStructSequence)]
pub struct UnraisableHookArgs {
pub exc_type: PyTypeRef,
pub exc_value: PyObjectRef,
pub exc_traceback: PyObjectRef,
pub err_msg: PyObjectRef,
pub object: PyObjectRef,
}
#[pyimpl(with(PyStructSequence))]
impl UnraisableHookArgs {}
}
pub(crate) fn init_module(vm: &VirtualMachine, module: &PyObject, builtins: &PyObject) {

View File

@@ -8,7 +8,6 @@ pub(crate) mod _thread {
builtins::{PyDictRef, PyStrRef, PyTupleRef, PyTypeRef},
convert::ToPyException,
function::{ArgCallable, FuncArgs, KwArgs, OptionalArg},
py_io,
types::{Constructor, GetAttr, SetAttr},
utils::Either,
AsObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
@@ -17,7 +16,7 @@ pub(crate) mod _thread {
lock_api::{RawMutex as RawMutexT, RawMutexTimed, RawReentrantMutex},
RawMutex, RawThreadId,
};
use std::{cell::RefCell, fmt, io::Write, thread, time::Duration};
use std::{cell::RefCell, fmt, thread, time::Duration};
use thread_local::ThreadLocal;
// TIMEOUT_MAX_IN_MICROSECONDS is a value in microseconds
@@ -168,7 +167,8 @@ pub(crate) mod _thread {
RLock {
mu: RawRMutex::INIT,
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
#[pymethod]
@@ -255,16 +255,11 @@ pub(crate) mod _thread {
Ok(_obj) => {}
Err(e) if e.fast_isinstance(&vm.ctx.exceptions.system_exit) => {}
Err(exc) => {
// TODO: sys.unraisablehook
let stderr = std::io::stderr();
let mut stderr = py_io::IoWriter(stderr.lock());
let repr = func.as_ref().repr(vm).ok();
let repr = repr
.as_ref()
.map_or("<object repr() failed>", |s| s.as_str());
writeln!(*stderr, "Exception ignored in thread started by: {}", repr)
.and_then(|()| vm.write_exception(&mut stderr, &exc))
.ok();
vm.run_unraisable(
exc,
Some("Exception ignored in thread started by".to_owned()),
func.into(),
);
}
}
SENTINELS.with(|sents| {
@@ -321,7 +316,8 @@ pub(crate) mod _thread {
Local {
data: ThreadLocal::new(),
}
.into_pyresult_with_type(vm, cls)
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}

View File

@@ -1,6 +1,6 @@
use crate::{
builtins::{PyTuple, PyTupleRef, PyTypeRef},
pyclass::{PyClassImpl, StaticType},
class::{PyClassImpl, StaticType},
vm::Context,
AsObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};

View File

@@ -1,14 +1,13 @@
use crate::{
builtins::{
asyncgenerator, builtinfunc, bytearray, bytes, classmethod, code, complex, coroutine, dict,
enumerate, filter, float, frame, function, generator, genericalias, getset, int, iter,
list, map, mappingproxy, memory, module, namespace, object, property, pybool, pystr,
pysuper,
pytype::{self, PyTypeRef},
pyunion, range, set, singletons, slice, staticmethod, traceback, tuple, weakproxy, weakref,
zip,
asyncgenerator, bool_, builtinfunc, bytearray, bytes, classmethod, code, complex,
coroutine, dict, enumerate, filter, float, frame, function, generator, genericalias,
getset, int, iter, list, map, mappingproxy, memory, module, namespace, object, property,
pystr, range, set, singletons, slice, staticmethod, super_, traceback, tuple,
type_::{self, PyTypeRef},
union_, weakproxy, weakref, zip,
},
pyclass::StaticType,
class::StaticType,
vm::Context,
};
@@ -93,16 +92,16 @@ pub struct TypeZoo {
impl TypeZoo {
#[cold]
pub(crate) fn init() -> Self {
let (type_type, object_type, weakref_type) = crate::pyobject::init_type_hierarchy();
let (type_type, object_type, weakref_type) = crate::object::init_type_hierarchy();
Self {
// the order matters for type, object, weakref, and int
type_type: pytype::PyType::init_manually(type_type).clone(),
type_type: type_::PyType::init_manually(type_type).clone(),
object_type: object::PyBaseObject::init_manually(object_type).clone(),
weakref_type: weakref::PyWeak::init_manually(weakref_type).clone(),
int_type: int::PyInt::init_bare_type().clone(),
// types exposed as builtins
bool_type: pybool::PyBool::init_bare_type().clone(),
bool_type: bool_::PyBool::init_bare_type().clone(),
bytearray_type: bytearray::PyByteArray::init_bare_type().clone(),
bytes_type: bytes::PyBytes::init_bare_type().clone(),
classmethod_type: classmethod::PyClassMethod::init_bare_type().clone(),
@@ -121,7 +120,7 @@ impl TypeZoo {
slice_type: slice::PySlice::init_bare_type().clone(),
staticmethod_type: staticmethod::PyStaticMethod::init_bare_type().clone(),
str_type: pystr::PyStr::init_bare_type().clone(),
super_type: pysuper::PySuper::init_bare_type().clone(),
super_type: super_::PySuper::init_bare_type().clone(),
tuple_type: tuple::PyTuple::init_bare_type().clone(),
zip_type: zip::PyZip::init_bare_type().clone(),
@@ -175,14 +174,14 @@ impl TypeZoo {
none_type: singletons::PyNone::init_bare_type().clone(),
not_implemented_type: singletons::PyNotImplemented::init_bare_type().clone(),
generic_alias_type: genericalias::PyGenericAlias::init_bare_type().clone(),
union_type: pyunion::PyUnion::init_bare_type().clone(),
union_type: union_::PyUnion::init_bare_type().clone(),
}
}
/// Fill attributes of builtin types.
#[cold]
pub(crate) fn extend(context: &Context) {
pytype::init(context);
type_::init(context);
object::init(context);
list::init(context);
set::init(context);
@@ -206,13 +205,13 @@ impl TypeZoo {
pystr::init(context);
range::init(context);
slice::init(context);
pysuper::init(context);
super_::init(context);
iter::init(context);
enumerate::init(context);
filter::init(context);
map::init(context);
zip::init(context);
pybool::init(context);
bool_::init(context);
code::init(context);
frame::init(context);
weakref::init(context);
@@ -223,6 +222,6 @@ impl TypeZoo {
mappingproxy::init(context);
traceback::init(context);
genericalias::init(context);
pyunion::init(context);
union_::init(context);
}
}

View File

@@ -47,7 +47,7 @@ impl VersionInfo {
};
#[pyslot]
fn slot_new(
_cls: crate::builtins::pytype::PyTypeRef,
_cls: crate::builtins::type_::PyTypeRef,
_args: crate::function::FuncArgs,
vm: &crate::VirtualMachine,
) -> crate::PyResult {

View File

@@ -4,15 +4,15 @@ use crate::{
bytes,
getset::{IntoPyGetterFunc, IntoPySetterFunc, PyGetSet},
object, pystr,
pytype::PyAttributes,
type_::PyAttributes,
PyBaseException, PyDict, PyDictRef, PyEllipsis, PyFloat, PyFrozenSet, PyInt, PyIntRef,
PyList, PyListRef, PyNone, PyNotImplemented, PyStr, PyTuple, PyTupleRef, PyType, PyTypeRef,
},
class::{PyClassImpl, StaticType},
exceptions,
function::IntoPyNativeFunc,
intern::{Internable, StringPool},
pyclass::{PyClassImpl, StaticType},
pyobject::{PyObjectPayload, PyObjectRef, PyPayload, PyRef, PyRefExact},
object::{PyObjectPayload, PyObjectRef, PyPayload, PyRef, PyRefExact},
types::{PyTypeFlags, PyTypeSlots, TypeZoo},
};
use num_bigint::BigInt;

142
vm/src/vm/method.rs Normal file
View File

@@ -0,0 +1,142 @@
//! This module will be replaced once #3100 is done
//! Do not expose this type to outside of this crate
use super::VirtualMachine;
use crate::{
builtins::{PyBaseObject, PyStrRef},
function::IntoFuncArgs,
object::{AsObject, PyObjectRef, PyResult},
types::PyTypeFlags,
};
#[derive(Debug)]
pub enum PyMethod {
Function {
target: PyObjectRef,
func: PyObjectRef,
},
Attribute(PyObjectRef),
}
impl PyMethod {
pub fn get(obj: PyObjectRef, name: PyStrRef, vm: &VirtualMachine) -> PyResult<Self> {
let cls = obj.class();
let getattro = cls.mro_find_map(|cls| cls.slots.getattro.load()).unwrap();
if getattro as usize != PyBaseObject::getattro as usize {
drop(cls);
return obj.get_attr(name, vm).map(Self::Attribute);
}
let mut is_method = false;
let cls_attr = match cls.get_attr(name.as_str()) {
Some(descr) => {
let descr_cls = descr.class();
let descr_get = if descr_cls.slots.flags.has_feature(PyTypeFlags::METHOD_DESCR) {
is_method = true;
None
} else {
let descr_get = descr_cls.mro_find_map(|cls| cls.slots.descr_get.load());
if let Some(descr_get) = descr_get {
if descr_cls
.mro_find_map(|cls| cls.slots.descr_set.load())
.is_some()
{
drop(descr_cls);
let cls = cls.into_owned().into();
return descr_get(descr, Some(obj), Some(cls), vm).map(Self::Attribute);
}
}
descr_get
};
drop(descr_cls);
Some((descr, descr_get))
}
None => None,
};
if let Some(dict) = obj.dict() {
if let Some(attr) = dict.get_item_opt(name.clone(), vm)? {
return Ok(Self::Attribute(attr));
}
}
if let Some((attr, descr_get)) = cls_attr {
match descr_get {
None if is_method => {
drop(cls);
Ok(Self::Function {
target: obj,
func: attr,
})
}
Some(descr_get) => {
let cls = cls.into_owned().into();
descr_get(attr, Some(obj), Some(cls), vm).map(Self::Attribute)
}
None => Ok(Self::Attribute(attr)),
}
} else if let Some(getter) = cls.get_attr("__getattr__") {
drop(cls);
vm.invoke(&getter, (obj, name)).map(Self::Attribute)
} else {
let exc = vm.new_attribute_error(format!(
"'{}' object has no attribute '{}'",
cls.name(),
name
));
vm.set_attribute_error_context(&exc, obj.clone(), name);
Err(exc)
}
}
pub(crate) fn get_special(
obj: PyObjectRef,
name: &str,
vm: &VirtualMachine,
) -> PyResult<Result<Self, PyObjectRef>> {
let obj_cls = obj.class();
let func = match obj_cls.get_attr(name) {
Some(f) => f,
None => {
drop(obj_cls);
return Ok(Err(obj));
}
};
let meth = if func
.class()
.slots
.flags
.has_feature(PyTypeFlags::METHOD_DESCR)
{
drop(obj_cls);
Self::Function { target: obj, func }
} else {
let obj_cls = obj_cls.into_owned().into();
let attr = vm
.call_get_descriptor_specific(func, Some(obj), Some(obj_cls))
.unwrap_or_else(Ok)?;
Self::Attribute(attr)
};
Ok(Ok(meth))
}
pub fn invoke(self, args: impl IntoFuncArgs, vm: &VirtualMachine) -> PyResult {
let (func, args) = match self {
PyMethod::Function { target, func } => (func, args.into_method_args(target, vm)),
PyMethod::Attribute(func) => (func, args.into_args(vm)),
};
vm.invoke(&func, args)
}
#[allow(dead_code)]
pub fn invoke_ref(&self, args: impl IntoFuncArgs, vm: &VirtualMachine) -> PyResult {
let (func, args) = match self {
PyMethod::Function { target, func } => {
(func, args.into_method_args(target.clone(), vm))
}
PyMethod::Attribute(func) => (func, args.into_args(vm)),
};
vm.invoke(func, args)
}
}

View File

@@ -7,6 +7,7 @@
mod compile;
mod context;
mod interpreter;
mod method;
mod setting;
pub mod thread;
mod vm_new;
@@ -42,6 +43,7 @@ use std::{
pub use context::Context;
pub use interpreter::Interpreter;
pub(crate) use method::PyMethod;
pub use setting::Settings;
// Objects are live when they are on stack, or referenced by a name (for now)
@@ -282,6 +284,28 @@ impl VirtualMachine {
self.run_frame_full(frame)
}
#[cold]
pub fn run_unraisable(&self, e: PyBaseExceptionRef, msg: Option<String>, object: PyObjectRef) {
use crate::stdlib::sys::UnraisableHookArgs;
let sys_module = self.import("sys", None, 0).unwrap();
let unraisablehook = sys_module.get_attr("unraisablehook", self).unwrap();
let exc_type = e.class().clone();
let exc_traceback = e.traceback().to_pyobject(self); // TODO: actual traceback
let exc_value = e.into();
let args = UnraisableHookArgs {
exc_type,
exc_value,
exc_traceback,
err_msg: self.new_pyobj(msg),
object,
};
if let Err(e) = self.invoke(&unraisablehook, (args,)) {
println!("{}", e.as_object().repr(self).unwrap().as_str());
}
}
#[inline(always)]
pub fn run_frame_full(&self, frame: FrameRef) -> PyResult {
match self.run_frame(frame)? {

View File

@@ -1,8 +1,9 @@
use super::PyMethod;
use crate::{
builtins::{PyBaseExceptionRef, PyList, PyStr},
function::{FuncArgs, IntoFuncArgs},
object::{AsObject, PyObject, PyObjectRef, PyPayload, PyResult},
vm::VirtualMachine,
AsObject, PyMethod, PyObject, PyObjectRef, PyPayload, PyResult,
};
/// Trace events for sys.settrace and sys.setprofile.

View File

@@ -1,10 +1,10 @@
use super::{PyMethod, VirtualMachine};
use crate::{
builtins::{PyInt, PyIntRef},
function::PyArithmeticValue,
object::{AsObject, PyObject, PyObjectRef, PyResult},
protocol::PyIterReturn,
types::PyComparisonOp,
vm::VirtualMachine,
AsObject, PyMethod, PyObject, PyObjectRef, PyResult,
};
/// Collection of operators

View File

@@ -8,10 +8,10 @@ mod _browser {
use js_sys::Promise;
use rustpython_vm::{
builtins::{PyDictRef, PyStrRef},
class::PyClassImpl,
convert::ToPyObject,
function::{ArgCallable, OptionalArg},
import::import_file,
pyclass::PyClassImpl,
PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use wasm_bindgen::{prelude::*, JsCast};