mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-09 22:49:57 +09:00
10
Lib/test/_test_atexit.py
vendored
10
Lib/test/_test_atexit.py
vendored
@@ -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
6
Lib/test/test_io.py
vendored
@@ -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.
|
||||
|
||||
3
Lib/test/test_signal.py
vendored
3
Lib/test/test_signal.py
vendored
@@ -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):
|
||||
|
||||
2
Lib/test/test_thread.py
vendored
2
Lib/test/test_thread.py
vendored
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -60,7 +60,8 @@ mod _json {
|
||||
parse_constant,
|
||||
ctx,
|
||||
}
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
.into_ref_with_type(vm, cls)
|
||||
.map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
@@ -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())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
@@ -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,
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use crate::{
|
||||
builtins::{PyBaseObject, PyBoundMethod, PyType, PyTypeRef},
|
||||
pyobject::{PyObjectPayload, PyObjectRef, PyRef},
|
||||
object::{PyObjectPayload, PyObjectRef, PyRef},
|
||||
types::{PyTypeFlags, PyTypeSlots},
|
||||
vm::Context,
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
pyobject::{AsObject, PyObject, PyPayload, PyRef, PyResult},
|
||||
object::{AsObject, PyObject, PyPayload, PyRef, PyResult},
|
||||
vm::VirtualMachine,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
pyobject::{AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult},
|
||||
object::{AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult},
|
||||
vm::VirtualMachine,
|
||||
};
|
||||
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
convert::{ToPyObject, TryFromObject},
|
||||
pyobject::{AsObject, PyObjectRef, PyResult},
|
||||
object::{AsObject, PyObjectRef, PyResult},
|
||||
VirtualMachine,
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
276
vm/src/object/ext.rs
Normal 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
7
vm/src/object/mod.rs
Normal 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
76
vm/src/object/payload.rs
Normal 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
6
vm/src/prelude.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
pub use crate::{
|
||||
object::{
|
||||
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult, PyWeakRef,
|
||||
},
|
||||
vm::{Context, InitParameter, Interpreter, Settings, VirtualMachine},
|
||||
};
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ mod decl {
|
||||
bytecode,
|
||||
convert::ToPyObject,
|
||||
function::ArgBytesLike,
|
||||
object::AsObject,
|
||||
protocol::PyBuffer,
|
||||
pyobject::AsObject,
|
||||
PyObjectRef, PyResult, TryFromObject, VirtualMachine,
|
||||
};
|
||||
/// TODO
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
builtins::{PyTuple, PyTupleRef, PyTypeRef},
|
||||
pyclass::{PyClassImpl, StaticType},
|
||||
class::{PyClassImpl, StaticType},
|
||||
vm::Context,
|
||||
AsObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
142
vm/src/vm/method.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -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)? {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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};
|
||||
|
||||
Reference in New Issue
Block a user