mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
implement SlotConstructor for every class
This commit is contained in:
1 parent
407cc7aae2
commit
55709b71b6
48 files changed
+972
-737
No files matched your search
@@ -476,14 +476,8 @@ where
|
||||
let slot_ident = item_meta.slot_name()?;
|
||||
let slot_name = slot_ident.to_string();
|
||||
let tokens = {
|
||||
let into_func = if slot_name == "new" {
|
||||
quote_spanned! {ident.span() =>
|
||||
::rustpython_vm::function::IntoPyNativeFunc::into_func(Self::#ident)
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {ident.span() =>
|
||||
Self::#ident as _
|
||||
}
|
||||
let into_func = quote_spanned! {ident.span() =>
|
||||
Self::#ident as _
|
||||
};
|
||||
const NON_ATOMIC_SLOTS: &[&str] = &["as_buffer"];
|
||||
if NON_ATOMIC_SLOTS.contains(&slot_name.as_str()) {
|
||||
|
||||
@@ -102,8 +102,8 @@ pub(crate) fn init(context: &PyContext) {
|
||||
#[pyimpl(flags(BASETYPE), with(Hashable, Comparable, AsBuffer, Iterable))]
|
||||
impl PyByteArray {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
PyByteArray::default().into_ref_with_type(vm, cls)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyByteArray::default().into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
|
||||
+17
-13
@@ -12,12 +12,14 @@ use crate::bytesinner::{
|
||||
use crate::byteslike::ArgBytesLike;
|
||||
use crate::common::hash::PyHash;
|
||||
use crate::function::{OptionalArg, OptionalOption};
|
||||
use crate::slots::{AsBuffer, Callable, Comparable, Hashable, Iterable, PyComparisonOp, PyIter};
|
||||
use crate::slots::{
|
||||
AsBuffer, Callable, Comparable, Hashable, Iterable, PyComparisonOp, PyIter, SlotConstructor,
|
||||
};
|
||||
use crate::utils::Either;
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{
|
||||
IdProtocol, IntoPyObject, PyClassImpl, PyComparisonValue, PyContext, PyIterable, PyObjectRef,
|
||||
PyRef, PyResult, PyValue, TryFromBorrowedObject, TypeProtocol,
|
||||
IdProtocol, IntoPyObject, IntoPyResult, PyClassImpl, PyComparisonValue, PyContext, PyIterable,
|
||||
PyObjectRef, PyRef, PyResult, PyValue, TryFromBorrowedObject, TypeProtocol,
|
||||
};
|
||||
use bstr::ByteSlice;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
@@ -96,17 +98,19 @@ pub(crate) fn init(context: &PyContext) {
|
||||
PyBytesIterator::extend_class(context, &context.types.bytes_iterator_type);
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Hashable, Comparable, AsBuffer, Iterable))]
|
||||
impl PyBytes {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
options: ByteInnerNewOptions,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
options.get_bytes(cls, vm)
|
||||
}
|
||||
impl SlotConstructor for PyBytes {
|
||||
type Args = ByteInnerNewOptions;
|
||||
|
||||
fn py_new(cls: PyTypeRef, options: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
options.get_bytes(cls, vm).into_pyresult(vm)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(
|
||||
flags(BASETYPE),
|
||||
with(Hashable, Comparable, AsBuffer, Iterable, SlotConstructor)
|
||||
)]
|
||||
impl PyBytes {
|
||||
#[pymethod(magic)]
|
||||
pub(crate) fn repr(&self) -> String {
|
||||
self.inner.repr("", "")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::slots::SlotDescriptor;
|
||||
use crate::slots::{SlotConstructor, SlotDescriptor};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol};
|
||||
use crate::{PyClassImpl, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol};
|
||||
|
||||
/// classmethod(function) -> method
|
||||
///
|
||||
@@ -54,13 +54,16 @@ impl SlotDescriptor for PyClassMethod {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotDescriptor), flags(BASETYPE, HAS_DICT))]
|
||||
impl PyClassMethod {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, callable: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
PyClassMethod { callable }.into_ref_with_type(vm, cls)
|
||||
}
|
||||
impl SlotConstructor for PyClassMethod {
|
||||
type Args = PyObjectRef;
|
||||
|
||||
fn py_new(cls: PyTypeRef, callable: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
PyClassMethod { callable }.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotDescriptor, SlotConstructor), flags(BASETYPE, HAS_DICT))]
|
||||
impl PyClassMethod {
|
||||
#[pyproperty(magic)]
|
||||
fn func(&self) -> PyObjectRef {
|
||||
self.callable.clone()
|
||||
|
||||
@@ -7,6 +7,7 @@ use std::ops::Deref;
|
||||
|
||||
use super::{PyStrRef, PyTypeRef};
|
||||
use crate::bytecode::{self, BorrowedConstant, Constant, ConstantBag};
|
||||
use crate::function::FuncArgs;
|
||||
use crate::VirtualMachine;
|
||||
use crate::{
|
||||
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, StaticType,
|
||||
@@ -196,7 +197,7 @@ impl PyCode {}
|
||||
#[pyimpl]
|
||||
impl PyCodeRef {
|
||||
#[pyslot]
|
||||
fn tp_new(_cls: PyTypeRef, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
fn tp_new(_cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error("Cannot directly create code object".to_owned()))
|
||||
}
|
||||
|
||||
|
||||
+79
-76
@@ -6,7 +6,7 @@ use super::float;
|
||||
use super::pystr::PyStr;
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::function::{OptionalArg, OptionalOption};
|
||||
use crate::slots::{Comparable, Hashable, PyComparisonOp};
|
||||
use crate::slots::{Comparable, Hashable, PyComparisonOp, SlotConstructor};
|
||||
use crate::VirtualMachine;
|
||||
use crate::{
|
||||
IdProtocol, IntoPyObject,
|
||||
@@ -83,7 +83,83 @@ fn inner_pow(v1: Complex64, v2: Complex64, vm: &VirtualMachine) -> PyResult<Comp
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Comparable, Hashable))]
|
||||
impl SlotConstructor for PyComplex {
|
||||
type Args = ComplexArgs;
|
||||
|
||||
fn py_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let imag_missing = args.imag.is_missing();
|
||||
let (real, real_was_complex) = match args.real {
|
||||
OptionalArg::Missing => (Complex64::new(0.0, 0.0), false),
|
||||
OptionalArg::Present(val) => {
|
||||
let val = if cls.is(&vm.ctx.types.complex_type) && imag_missing {
|
||||
match val.downcast_exact::<PyComplex>(vm) {
|
||||
Ok(c) => {
|
||||
return Ok(c.into_object());
|
||||
}
|
||||
Err(val) => val,
|
||||
}
|
||||
} else {
|
||||
val
|
||||
};
|
||||
|
||||
if let Some(c) = try_complex(&val, vm)? {
|
||||
c
|
||||
} else if let Some(s) = val.payload_if_subclass::<PyStr>(vm) {
|
||||
if args.imag.is_present() {
|
||||
return Err(vm.new_type_error(
|
||||
"complex() can't take second arg if first is a string".to_owned(),
|
||||
));
|
||||
}
|
||||
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);
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"complex() first argument must be a string or a number, not '{}'",
|
||||
val.class().name
|
||||
)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let (imag, imag_was_complex) = match args.imag {
|
||||
// Copy the imaginary from the real to the real of the imaginary
|
||||
// if an imaginary argument is not passed in
|
||||
OptionalArg::Missing => (Complex64::new(real.im, 0.0), false),
|
||||
OptionalArg::Present(obj) => {
|
||||
if let Some(c) = try_complex(&obj, vm)? {
|
||||
c
|
||||
} else if obj.class().issubclass(&vm.ctx.types.str_type) {
|
||||
return Err(
|
||||
vm.new_type_error("complex() second arg can't be a string".to_owned())
|
||||
);
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"complex() second argument must be a number, not '{}'",
|
||||
obj.class().name
|
||||
)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let final_real = if imag_was_complex {
|
||||
real.re - imag.im
|
||||
} else {
|
||||
real.re
|
||||
};
|
||||
|
||||
let final_imag = if real_was_complex && !imag_missing {
|
||||
imag.re + real.im
|
||||
} else {
|
||||
imag.re
|
||||
};
|
||||
let value = Complex64::new(final_real, final_imag);
|
||||
Self::from(value).into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Comparable, Hashable, SlotConstructor))]
|
||||
impl PyComplex {
|
||||
pub fn to_complex(&self) -> Complex64 {
|
||||
self.value
|
||||
@@ -267,79 +343,6 @@ impl PyComplex {
|
||||
!Complex64::is_zero(&self.value)
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, args: ComplexArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
let imag_missing = args.imag.is_missing();
|
||||
let (real, real_was_complex) = match args.real {
|
||||
OptionalArg::Missing => (Complex64::new(0.0, 0.0), false),
|
||||
OptionalArg::Present(val) => {
|
||||
let val = if cls.is(&vm.ctx.types.complex_type) && imag_missing {
|
||||
match val.downcast_exact::<PyComplex>(vm) {
|
||||
Ok(c) => {
|
||||
return Ok(c);
|
||||
}
|
||||
Err(val) => val,
|
||||
}
|
||||
} else {
|
||||
val
|
||||
};
|
||||
|
||||
if let Some(c) = try_complex(&val, vm)? {
|
||||
c
|
||||
} else if let Some(s) = val.payload_if_subclass::<PyStr>(vm) {
|
||||
if args.imag.is_present() {
|
||||
return Err(vm.new_type_error(
|
||||
"complex() can't take second arg if first is a string".to_owned(),
|
||||
));
|
||||
}
|
||||
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_ref_with_type(vm, cls);
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"complex() first argument must be a string or a number, not '{}'",
|
||||
val.class().name
|
||||
)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let (imag, imag_was_complex) = match args.imag {
|
||||
// Copy the imaginary from the real to the real of the imaginary
|
||||
// if an imaginary argument is not passed in
|
||||
OptionalArg::Missing => (Complex64::new(real.im, 0.0), false),
|
||||
OptionalArg::Present(obj) => {
|
||||
if let Some(c) = try_complex(&obj, vm)? {
|
||||
c
|
||||
} else if obj.class().issubclass(&vm.ctx.types.str_type) {
|
||||
return Err(
|
||||
vm.new_type_error("complex() second arg can't be a string".to_owned())
|
||||
);
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"complex() second argument must be a number, not '{}'",
|
||||
obj.class().name
|
||||
)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let final_real = if imag_was_complex {
|
||||
real.re - imag.im
|
||||
} else {
|
||||
real.re
|
||||
};
|
||||
|
||||
let final_imag = if real_was_complex && !imag_missing {
|
||||
imag.re + real.im
|
||||
} else {
|
||||
imag.re
|
||||
};
|
||||
let value = Complex64::new(final_real, final_imag);
|
||||
Self::from(value).into_ref_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn getnewargs(&self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let Complex64 { re, im } = self.value;
|
||||
@@ -377,7 +380,7 @@ impl Hashable for PyComplex {
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct ComplexArgs {
|
||||
pub struct ComplexArgs {
|
||||
#[pyarg(any, optional)]
|
||||
real: OptionalArg<PyObjectRef>,
|
||||
#[pyarg(any, optional)]
|
||||
|
||||
@@ -54,8 +54,8 @@ impl PyValue for PyDict {
|
||||
#[pyimpl(with(Hashable, Comparable, Iterable), flags(BASETYPE))]
|
||||
impl PyDict {
|
||||
#[pyslot]
|
||||
fn tp_new(class: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
PyDict::default().into_ref_with_type(vm, class)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyDict::default().into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
|
||||
@@ -11,7 +11,7 @@ use super::iter::{
|
||||
};
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::slots::PyIter;
|
||||
use crate::slots::{PyIter, SlotConstructor};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{iterator, ItemProtocol, TypeProtocol};
|
||||
use crate::{IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
@@ -30,17 +30,17 @@ impl PyValue for PyEnumerate {
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct EnumerateArgs {
|
||||
pub struct EnumerateArgs {
|
||||
#[pyarg(any)]
|
||||
iterable: PyObjectRef,
|
||||
#[pyarg(any, optional)]
|
||||
start: OptionalArg<PyIntRef>,
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter), flags(BASETYPE))]
|
||||
impl PyEnumerate {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, args: EnumerateArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for PyEnumerate {
|
||||
type Args = EnumerateArgs;
|
||||
|
||||
fn py_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let counter = match args.start {
|
||||
OptionalArg::Present(start) => start.as_bigint().clone(),
|
||||
OptionalArg::Missing => BigInt::zero(),
|
||||
@@ -51,10 +51,13 @@ impl PyEnumerate {
|
||||
counter: PyRwLock::new(counter),
|
||||
iterator,
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor), flags(BASETYPE))]
|
||||
impl PyEnumerate {}
|
||||
|
||||
impl PyIter for PyEnumerate {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let next_obj = iterator::call_next(vm, &zelf.iterator)?;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::pybool;
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::iterator;
|
||||
use crate::slots::PyIter;
|
||||
use crate::slots::{PyIter, SlotConstructor};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
|
||||
@@ -22,25 +22,35 @@ impl PyValue for PyFilter {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter), flags(BASETYPE))]
|
||||
impl PyFilter {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
#[derive(FromArgs)]
|
||||
pub struct FilterArgs {
|
||||
#[pyarg(positional)]
|
||||
function: PyObjectRef,
|
||||
#[pyarg(positional)]
|
||||
iterable: PyObjectRef,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyFilter {
|
||||
type Args = FilterArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
function: PyObjectRef,
|
||||
iterable: PyObjectRef,
|
||||
Self::Args { function, iterable }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let iterator = iterator::get_iter(vm, iterable)?;
|
||||
|
||||
Self {
|
||||
predicate: function,
|
||||
iterator,
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor), flags(BASETYPE))]
|
||||
impl PyFilter {}
|
||||
|
||||
impl PyIter for PyFilter {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let predicate = &zelf.predicate;
|
||||
|
||||
+10
-11
@@ -2,7 +2,7 @@ use super::{int, PyBytes, PyInt, PyIntRef, PyStr, PyStrRef, PyTypeRef};
|
||||
use crate::common::{float_ops, hash};
|
||||
use crate::format::FormatSpec;
|
||||
use crate::function::{OptionalArg, OptionalOption};
|
||||
use crate::slots::{Comparable, Hashable, PyComparisonOp};
|
||||
use crate::slots::{Comparable, Hashable, PyComparisonOp, SlotConstructor};
|
||||
use crate::VirtualMachine;
|
||||
use crate::{
|
||||
IdProtocol, IntoPyObject,
|
||||
@@ -154,20 +154,16 @@ pub fn float_pow(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Comparable, Hashable))]
|
||||
impl PyFloat {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
arg: OptionalArg<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for PyFloat {
|
||||
type Args = OptionalArg<PyObjectRef>;
|
||||
|
||||
fn py_new(cls: PyTypeRef, arg: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let float_val = match arg {
|
||||
OptionalArg::Missing => 0.0,
|
||||
OptionalArg::Present(val) => {
|
||||
let val = if cls.is(&vm.ctx.types.float_type) {
|
||||
match val.downcast_exact::<PyFloat>(vm) {
|
||||
Ok(f) => return Ok(f),
|
||||
Ok(f) => return Ok(f.into_object()),
|
||||
Err(val) => val,
|
||||
}
|
||||
} else {
|
||||
@@ -195,9 +191,12 @@ impl PyFloat {
|
||||
}
|
||||
}
|
||||
};
|
||||
PyFloat::from(float_val).into_ref_with_type(vm, cls)
|
||||
PyFloat::from(float_val).into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Comparable, Hashable, SlotConstructor))]
|
||||
impl PyFloat {
|
||||
#[pymethod(magic)]
|
||||
fn format(&self, spec: PyStrRef, vm: &VirtualMachine) -> PyResult<String> {
|
||||
match FormatSpec::parse(spec.as_str())
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
use super::code::PyCodeRef;
|
||||
use super::dict::PyDictRef;
|
||||
use super::pystr::PyStrRef;
|
||||
use crate::builtins::PyTypeRef;
|
||||
use crate::frame::{Frame, FrameRef};
|
||||
use crate::function::FuncArgs;
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult};
|
||||
|
||||
@@ -19,7 +21,7 @@ impl Frame {}
|
||||
#[pyimpl]
|
||||
impl FrameRef {
|
||||
#[pyslot]
|
||||
fn tp_new(_cls: FrameRef, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
fn tp_new(_cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error("Cannot directly create frame object".to_owned()))
|
||||
}
|
||||
|
||||
|
||||
+36
-18
@@ -14,7 +14,9 @@ use crate::common::lock::PyMutex;
|
||||
use crate::frame::Frame;
|
||||
use crate::function::{FuncArgs, OptionalArg};
|
||||
use crate::scope::Scope;
|
||||
use crate::slots::{Callable, Comparable, PyComparisonOp, SlotDescriptor, SlotGetattro};
|
||||
use crate::slots::{
|
||||
Callable, Comparable, PyComparisonOp, SlotConstructor, SlotDescriptor, SlotGetattro,
|
||||
};
|
||||
#[cfg(feature = "jit")]
|
||||
use crate::IntoPyObject;
|
||||
use crate::VirtualMachine;
|
||||
@@ -465,22 +467,35 @@ impl SlotGetattro for PyBoundMethod {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(Callable, Comparable, SlotGetattro), flags(HAS_DICT))]
|
||||
#[derive(FromArgs)]
|
||||
pub struct PyBoundMethodNewArgs {
|
||||
#[pyarg(positional)]
|
||||
function: PyObjectRef,
|
||||
#[pyarg(positional)]
|
||||
object: PyObjectRef,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyBoundMethod {
|
||||
type Args = PyBoundMethodNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
Self::Args { function, object }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
PyBoundMethod::new(object, function).into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(
|
||||
with(Callable, Comparable, SlotGetattro, SlotConstructor),
|
||||
flags(HAS_DICT)
|
||||
)]
|
||||
impl PyBoundMethod {
|
||||
pub fn new(object: PyObjectRef, function: PyObjectRef) -> Self {
|
||||
PyBoundMethod { object, function }
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
function: PyObjectRef,
|
||||
object: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
PyBoundMethod::new(object, function).into_ref_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
|
||||
let funcname =
|
||||
@@ -559,13 +574,16 @@ impl PyValue for PyCell {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
impl PyCell {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, value: OptionalArg, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
Self::new(value.into_option()).into_ref_with_type(vm, cls)
|
||||
}
|
||||
impl SlotConstructor 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)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotConstructor))]
|
||||
impl PyCell {
|
||||
pub fn new(contents: Option<PyObjectRef>) -> Self {
|
||||
Self {
|
||||
contents: PyMutex::new(contents),
|
||||
|
||||
@@ -238,7 +238,7 @@ fn inner_truediv(i1: &BigInt, i2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
impl SlotConstructor for PyInt {
|
||||
type Args = IntOptions;
|
||||
|
||||
fn py_new(cls: PyTypeRef, options: IntOptions, vm: &VirtualMachine) -> PyResult {
|
||||
fn py_new(cls: PyTypeRef, options: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let value = if let OptionalArg::Present(val) = options.val_options {
|
||||
if let OptionalArg::Present(base) = options.base {
|
||||
let base = vm
|
||||
|
||||
@@ -16,7 +16,7 @@ use super::PyInt;
|
||||
use crate::common::lock::{
|
||||
PyMappedRwLockReadGuard, PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard,
|
||||
};
|
||||
use crate::function::OptionalArg;
|
||||
use crate::function::{FuncArgs, OptionalArg};
|
||||
use crate::sequence::{self, SimpleSeq};
|
||||
use crate::sliceable::{PySliceableSequence, PySliceableSequenceMut, SequenceIndex};
|
||||
use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter, Unhashable};
|
||||
@@ -397,12 +397,8 @@ impl PyList {
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
_iterable: OptionalArg<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
PyList::default().into_ref_with_type(vm, cls)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyList::default().into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
|
||||
+9
-12
@@ -1,7 +1,7 @@
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::function::Args;
|
||||
use crate::iterator;
|
||||
use crate::slots::PyIter;
|
||||
use crate::slots::{PyIter, SlotConstructor};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
|
||||
@@ -22,15 +22,10 @@ impl PyValue for PyMap {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter), flags(BASETYPE))]
|
||||
impl PyMap {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
function: PyObjectRef,
|
||||
iterables: Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for PyMap {
|
||||
type Args = (PyObjectRef, Args<PyObjectRef>);
|
||||
|
||||
fn py_new(cls: PyTypeRef, (function, iterables): Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let iterators = iterables
|
||||
.into_iter()
|
||||
.map(|iterable| iterator::get_iter(vm, iterable))
|
||||
@@ -39,10 +34,12 @@ impl PyMap {
|
||||
mapper: function,
|
||||
iterators,
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return an estimate of the number of items.
|
||||
#[pyimpl(with(PyIter, SlotConstructor), flags(BASETYPE))]
|
||||
impl PyMap {
|
||||
#[pymethod(magic)]
|
||||
fn length_hint(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
self.iterators.iter().try_fold(0, |prev, cur| {
|
||||
|
||||
@@ -3,7 +3,7 @@ use super::pystr::PyStrRef;
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::iterator;
|
||||
use crate::slots::Iterable;
|
||||
use crate::slots::{Iterable, SlotConstructor};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{
|
||||
IntoPyObject, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue,
|
||||
@@ -36,16 +36,19 @@ impl PyMappingProxy {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(Iterable))]
|
||||
impl PyMappingProxy {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, mapping: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for PyMappingProxy {
|
||||
type Args = PyObjectRef;
|
||||
|
||||
fn py_new(cls: PyTypeRef, mapping: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
Self {
|
||||
mapping: MappingProxyInner::Dict(mapping),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(Iterable, SlotConstructor))]
|
||||
impl PyMappingProxy {
|
||||
fn get_inner(&self, key: PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>> {
|
||||
let opt = match &self.mapping {
|
||||
MappingProxyInner::Class(class) => {
|
||||
|
||||
+13
-14
@@ -10,7 +10,7 @@ use crate::common::hash::PyHash;
|
||||
use crate::common::lock::OnceCell;
|
||||
use crate::function::{FuncArgs, OptionalArg};
|
||||
use crate::sliceable::{convert_slice, saturate_range, wrap_index, SequenceIndex};
|
||||
use crate::slots::{AsBuffer, Comparable, Hashable, PyComparisonOp};
|
||||
use crate::slots::{AsBuffer, Comparable, Hashable, PyComparisonOp, SlotConstructor};
|
||||
use crate::stdlib::pystruct::_struct::FormatSpec;
|
||||
use crate::utils::Either;
|
||||
use crate::{
|
||||
@@ -25,7 +25,7 @@ use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct PyMemoryViewNewArgs {
|
||||
pub struct PyMemoryViewNewArgs {
|
||||
#[pyarg(any)]
|
||||
object: PyObjectRef,
|
||||
}
|
||||
@@ -49,9 +49,19 @@ pub struct PyMemoryView {
|
||||
hash: OnceCell<PyHash>,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyMemoryView {
|
||||
type Args = PyMemoryViewNewArgs;
|
||||
|
||||
fn py_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let buffer = PyBufferRef::try_from_borrowed_object(vm, &args.object)?;
|
||||
let zelf = PyMemoryView::from_buffer(args.object, buffer, vm)?;
|
||||
zelf.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
type PyMemoryViewRef = PyRef<PyMemoryView>;
|
||||
|
||||
#[pyimpl(with(Hashable, Comparable, AsBuffer))]
|
||||
#[pyimpl(with(Hashable, Comparable, AsBuffer, SlotConstructor))]
|
||||
impl PyMemoryView {
|
||||
fn parse_format(format: &str, vm: &VirtualMachine) -> PyResult<FormatSpec> {
|
||||
FormatSpec::parse(format, vm)
|
||||
@@ -116,17 +126,6 @@ impl PyMemoryView {
|
||||
})
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
args: PyMemoryViewNewArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
let buffer = PyBufferRef::try_from_borrowed_object(vm, &args.object)?;
|
||||
let zelf = PyMemoryView::from_buffer(args.object, buffer, vm)?;
|
||||
zelf.into_ref_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn release(&self) {
|
||||
// avoid double release
|
||||
|
||||
@@ -53,8 +53,8 @@ struct ModuleInitArgs {
|
||||
#[pyimpl(with(SlotGetattro), flags(BASETYPE, HAS_DICT))]
|
||||
impl PyModule {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
PyModule {}.into_ref_with_type(vm, cls)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyModule {}.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::function::KwArgs;
|
||||
use crate::slots::SlotConstructor;
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{PyClassImpl, PyContext, PyRef, PyResult, PyValue};
|
||||
use crate::{IntoPyObject, PyClassImpl, PyContext, PyResult, PyValue};
|
||||
|
||||
/// A simple attribute-based namespace.
|
||||
///
|
||||
@@ -16,18 +17,21 @@ impl PyValue for PyNamespace {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE, HAS_DICT))]
|
||||
impl PyNamespace {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, kwargs: KwArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for PyNamespace {
|
||||
type Args = KwArgs;
|
||||
|
||||
fn py_new(cls: PyTypeRef, kwargs: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let zelf = PyNamespace.into_ref_with_type(vm, cls)?;
|
||||
for (name, value) in kwargs.into_iter() {
|
||||
vm.set_attr(zelf.as_object(), name, value)?;
|
||||
}
|
||||
Ok(zelf)
|
||||
Ok(zelf.into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE, HAS_DICT), with(SlotConstructor))]
|
||||
impl PyNamespace {}
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
PyNamespace::extend_class(context, &context.types.namespace_type);
|
||||
}
|
||||
@@ -11,7 +11,7 @@ use crate::utils::Either;
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{
|
||||
IdProtocol, ItemProtocol, PyArithmaticValue, PyAttributes, PyClassImpl, PyComparisonValue,
|
||||
PyContext, PyObject, PyObjectRef, PyResult, PyValue, TryFromObject, TypeProtocol,
|
||||
PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
|
||||
};
|
||||
|
||||
/// object()
|
||||
@@ -35,9 +35,8 @@ impl PyValue for PyBaseObject {
|
||||
impl PyBaseObject {
|
||||
/// Create and return a new object. See help(type) for accurate signature.
|
||||
#[pyslot]
|
||||
fn tp_new(mut args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
// more or less __new__ operator
|
||||
let cls = PyTypeRef::try_from_object(vm, args.shift())?;
|
||||
let dict = if cls.is(&vm.ctx.types.object_type) {
|
||||
None
|
||||
} else {
|
||||
|
||||
@@ -91,14 +91,14 @@ impl SlotDescriptor for PyProperty {
|
||||
#[pyimpl(with(SlotDescriptor), flags(BASETYPE))]
|
||||
impl PyProperty {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyProperty {
|
||||
getter: PyRwLock::new(None),
|
||||
setter: PyRwLock::new(None),
|
||||
deleter: PyRwLock::new(None),
|
||||
doc: PyRwLock::new(None),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
|
||||
+37
-19
@@ -3,12 +3,15 @@ use num_traits::Zero;
|
||||
|
||||
use super::int::PyInt;
|
||||
use super::pystr::PyStrRef;
|
||||
use crate::builtins::PyTypeRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::slots::SlotConstructor;
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{
|
||||
IdProtocol, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyResult, TryFromBorrowedObject,
|
||||
TryFromObject, TypeProtocol,
|
||||
IdProtocol, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyResult, PyValue,
|
||||
TryFromBorrowedObject, TryFromObject, TypeProtocol,
|
||||
};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
impl IntoPyObject for bool {
|
||||
fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
@@ -79,7 +82,38 @@ pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
|
||||
#[pyclass(name = "bool", module = false, base = "PyInt")]
|
||||
pub struct PyBool;
|
||||
|
||||
#[pyimpl]
|
||||
impl PyValue for PyBool {
|
||||
fn class(vm: &VirtualMachine) -> &PyTypeRef {
|
||||
&vm.ctx.types.bool_type
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for PyBool {
|
||||
fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyBool {
|
||||
type Args = OptionalArg<PyObjectRef>;
|
||||
|
||||
fn py_new(zelf: PyTypeRef, x: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
if !zelf.isinstance(&vm.ctx.types.type_type) {
|
||||
let actual_type = &zelf.class().name;
|
||||
return Err(vm.new_type_error(format!(
|
||||
"requires a 'type' object but received a '{}'",
|
||||
actual_type
|
||||
)));
|
||||
}
|
||||
let val = match x {
|
||||
OptionalArg::Present(val) => boolval(vm, val)?,
|
||||
OptionalArg::Missing => false,
|
||||
};
|
||||
Ok(vm.ctx.new_bool(val))
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotConstructor))]
|
||||
impl PyBool {
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: bool) -> String {
|
||||
@@ -130,22 +164,6 @@ impl PyBool {
|
||||
get_py_int(&lhs).xor(rhs, vm).into_pyobject(vm)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(zelf: PyObjectRef, x: OptionalArg<PyObjectRef>, vm: &VirtualMachine) -> PyResult {
|
||||
if !zelf.isinstance(&vm.ctx.types.type_type) {
|
||||
let actual_type = &zelf.class().name;
|
||||
return Err(vm.new_type_error(format!(
|
||||
"requires a 'type' object but received a '{}'",
|
||||
actual_type
|
||||
)));
|
||||
}
|
||||
let val = match x {
|
||||
OptionalArg::Present(val) => boolval(vm, val)?,
|
||||
OptionalArg::Missing => false,
|
||||
};
|
||||
Ok(vm.ctx.new_bool(val))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn init(context: &PyContext) {
|
||||
|
||||
@@ -24,7 +24,7 @@ use crate::exceptions::IntoPyException;
|
||||
use crate::format::{FormatSpec, FormatString, FromTemplate};
|
||||
use crate::function::{FuncArgs, OptionalArg, OptionalOption};
|
||||
use crate::sliceable::PySliceableSequence;
|
||||
use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter};
|
||||
use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter, SlotConstructor};
|
||||
use crate::utils::Either;
|
||||
use crate::VirtualMachine;
|
||||
use crate::{
|
||||
@@ -203,7 +203,7 @@ impl PyIter for PyStrIterator {
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct StrArgs {
|
||||
pub struct StrArgs {
|
||||
#[pyarg(any, optional)]
|
||||
object: OptionalArg<PyObjectRef>,
|
||||
#[pyarg(any, optional)]
|
||||
@@ -212,10 +212,10 @@ struct StrArgs {
|
||||
errors: OptionalArg<PyStrRef>,
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Hashable, Comparable, Iterable))]
|
||||
impl PyStr {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, args: StrArgs, vm: &VirtualMachine) -> PyResult<PyStrRef> {
|
||||
impl SlotConstructor for PyStr {
|
||||
type Args = StrArgs;
|
||||
|
||||
fn py_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let string: PyStrRef = match args.object {
|
||||
OptionalArg::Present(input) => {
|
||||
if let OptionalArg::Present(enc) = args.encoding {
|
||||
@@ -234,12 +234,15 @@ impl PyStr {
|
||||
}
|
||||
};
|
||||
if string.class().is(&cls) {
|
||||
Ok(string)
|
||||
Ok(string.into_object())
|
||||
} else {
|
||||
PyStr::from(string.as_str()).into_ref_with_type(vm, cls)
|
||||
PyStr::from(string.as_str()).into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Hashable, Comparable, Iterable, SlotConstructor))]
|
||||
impl PyStr {
|
||||
#[pymethod(magic)]
|
||||
fn add(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if let Some(other) = other.payload::<PyStr>() {
|
||||
|
||||
+36
-26
@@ -9,7 +9,7 @@ https://github.com/python/cpython/blob/50b48572d9a90c5bb36e2bef6179548ea927a35a/
|
||||
use super::pystr::PyStrRef;
|
||||
use super::pytype::{PyType, PyTypeRef};
|
||||
use crate::function::OptionalArg;
|
||||
use crate::slots::{SlotDescriptor, SlotGetattro};
|
||||
use crate::slots::{SlotConstructor, SlotDescriptor, SlotGetattro};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{
|
||||
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
|
||||
@@ -28,34 +28,22 @@ impl PyValue for PySuper {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotGetattro, SlotDescriptor))]
|
||||
impl PySuper {
|
||||
fn new(typ: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
let obj = if vm.is_none(&obj) {
|
||||
None
|
||||
} else {
|
||||
let obj_type = supercheck(typ.clone(), obj.clone(), vm)?;
|
||||
Some((obj, obj_type))
|
||||
};
|
||||
Ok(Self { typ, obj })
|
||||
}
|
||||
#[derive(FromArgs)]
|
||||
pub struct PySuperNewArgs {
|
||||
#[pyarg(positional, optional)]
|
||||
py_type: OptionalArg<PyTypeRef>,
|
||||
#[pyarg(positional, optional)]
|
||||
py_obj: OptionalArg<PyObjectRef>,
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(&self) -> String {
|
||||
let typname = &self.typ.name;
|
||||
match self.obj {
|
||||
Some((_, ref ty)) => format!("<super: <class '{}'>, <{} object>>", typname, ty.name),
|
||||
None => format!("<super: <class '{}'>, NULL>", typname),
|
||||
}
|
||||
}
|
||||
impl SlotConstructor for PySuper {
|
||||
type Args = PySuperNewArgs;
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
py_type: OptionalArg<PyTypeRef>,
|
||||
py_obj: OptionalArg<PyObjectRef>,
|
||||
Self::Args { py_type, py_obj }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
// Get the type:
|
||||
let (typ, obj) = if let OptionalArg::Present(ty) = py_type {
|
||||
(ty, py_obj.unwrap_or_none(vm))
|
||||
@@ -107,7 +95,29 @@ impl PySuper {
|
||||
(typ, obj)
|
||||
};
|
||||
|
||||
PySuper::new(typ, obj, vm)?.into_ref_with_type(vm, cls)
|
||||
PySuper::new(typ, obj, vm)?.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotGetattro, SlotDescriptor, SlotConstructor))]
|
||||
impl PySuper {
|
||||
fn new(typ: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
let obj = if vm.is_none(&obj) {
|
||||
None
|
||||
} else {
|
||||
let obj_type = supercheck(typ.clone(), obj.clone(), vm)?;
|
||||
Some((obj, obj_type))
|
||||
};
|
||||
Ok(Self { typ, obj })
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(&self) -> String {
|
||||
let typname = &self.typ.name;
|
||||
match self.obj {
|
||||
Some((_, ref ty)) => format!("<super: <class '{}'>, <{} object>>", typname, ty.name),
|
||||
None => format!("<super: <class '{}'>, NULL>", typname),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -405,7 +405,7 @@ impl PyType {
|
||||
)
|
||||
}
|
||||
#[pyslot]
|
||||
fn tp_new(metatype: PyTypeRef, mut args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
fn tp_new(metatype: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
vm_trace!("type.__new__ {:?}", args);
|
||||
|
||||
let is_type_type = metatype.is(&vm.ctx.types.type_type);
|
||||
|
||||
@@ -362,12 +362,12 @@ impl PyRange {
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let range = if args.args.len() <= 2 {
|
||||
let (cls, stop) = args.bind(vm)?;
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let range = if args.args.len() <= 1 {
|
||||
let stop = args.bind(vm)?;
|
||||
PyRange::new(cls, stop, vm)
|
||||
} else {
|
||||
let (cls, start, stop, step) = args.bind(vm)?;
|
||||
let (start, stop, step) = args.bind(vm)?;
|
||||
PyRange::new_from(cls, start, stop, step, vm)
|
||||
}?;
|
||||
|
||||
|
||||
+28
-26
@@ -4,9 +4,12 @@
|
||||
use super::{pytype::PyTypeRef, IterStatus, PyDictRef};
|
||||
use crate::common::hash::PyHash;
|
||||
use crate::common::rc::PyRc;
|
||||
use crate::dictdatatype::{self, DictSize};
|
||||
use crate::dictdatatype;
|
||||
use crate::dictdatatype::DictSize;
|
||||
use crate::function::{Args, FuncArgs, OptionalArg};
|
||||
use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter, Unhashable};
|
||||
use crate::slots::{
|
||||
Comparable, Hashable, Iterable, PyComparisonOp, PyIter, SlotConstructor, Unhashable,
|
||||
};
|
||||
use crate::vm::{ReprGuard, VirtualMachine};
|
||||
use crate::{
|
||||
IdProtocol, PyClassImpl, PyComparisonValue, PyContext, PyIterable, PyObjectRef, PyRef,
|
||||
@@ -359,8 +362,8 @@ macro_rules! multi_args_set {
|
||||
#[pyimpl(with(Hashable, Comparable, Iterable), flags(BASETYPE))]
|
||||
impl PySet {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
PySet::default().into_ref_with_type(vm, cls)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PySet::default().into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
@@ -595,30 +598,14 @@ macro_rules! multi_args_frozenset {
|
||||
}};
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Hashable, Comparable, Iterable))]
|
||||
impl PyFrozenSet {
|
||||
// Also used by ssl.rs windows.
|
||||
pub(crate) fn from_iter(
|
||||
vm: &VirtualMachine,
|
||||
it: impl IntoIterator<Item = PyObjectRef>,
|
||||
) -> PyResult<Self> {
|
||||
let inner = PySetInner::default();
|
||||
for elem in it {
|
||||
inner.add(elem, vm)?;
|
||||
}
|
||||
Ok(Self { inner })
|
||||
}
|
||||
impl SlotConstructor for PyFrozenSet {
|
||||
type Args = OptionalArg<PyObjectRef>;
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
iterable: OptionalArg<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
fn py_new(cls: PyTypeRef, iterable: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let elements = if let OptionalArg::Present(iterable) = iterable {
|
||||
let iterable = if cls.is(&vm.ctx.types.frozenset_type) {
|
||||
match iterable.downcast_exact::<Self>(vm) {
|
||||
Ok(fs) => return Ok(fs),
|
||||
Ok(fs) => return Ok(fs.into_object()),
|
||||
Err(iterable) => iterable,
|
||||
}
|
||||
} else {
|
||||
@@ -631,11 +618,26 @@ impl PyFrozenSet {
|
||||
|
||||
// Return empty fs if iterable passed is empty and only for exact fs types.
|
||||
if elements.is_empty() && cls.is(&vm.ctx.types.frozenset_type) {
|
||||
Ok(vm.ctx.empty_frozenset.clone())
|
||||
Ok(vm.ctx.empty_frozenset.clone().into_object())
|
||||
} else {
|
||||
Self::from_iter(vm, elements).and_then(|o| o.into_ref_with_type(vm, cls))
|
||||
Self::from_iter(vm, elements).and_then(|o| o.into_pyresult_with_type(vm, cls))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Hashable, Comparable, Iterable, SlotConstructor))]
|
||||
impl PyFrozenSet {
|
||||
// Also used by ssl.rs windows.
|
||||
pub(crate) fn from_iter(
|
||||
vm: &VirtualMachine,
|
||||
it: impl IntoIterator<Item = PyObjectRef>,
|
||||
) -> PyResult<Self> {
|
||||
let inner = PySetInner::default();
|
||||
for elem in it {
|
||||
inner.add(elem, vm)?;
|
||||
}
|
||||
Ok(Self { inner })
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn len(&self) -> usize {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::slots::SlotConstructor;
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyValue, TypeProtocol};
|
||||
use crate::{
|
||||
IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
|
||||
};
|
||||
|
||||
#[pyclass(module = false, name = "NoneType")]
|
||||
#[derive(Debug)]
|
||||
@@ -30,13 +33,16 @@ impl<T: IntoPyObject> IntoPyObject for Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
impl PyNone {
|
||||
#[pyslot]
|
||||
fn tp_new(_: PyTypeRef, vm: &VirtualMachine) -> PyRef<Self> {
|
||||
vm.ctx.none.clone()
|
||||
}
|
||||
impl SlotConstructor for PyNone {
|
||||
type Args = ();
|
||||
|
||||
fn py_new(_: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(vm.ctx.none.clone().into_object())
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotConstructor))]
|
||||
impl PyNone {
|
||||
#[pymethod(magic)]
|
||||
fn repr(&self) -> String {
|
||||
"None".to_owned()
|
||||
@@ -59,13 +65,16 @@ impl PyValue for PyNotImplemented {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
impl PyNotImplemented {
|
||||
#[pyslot]
|
||||
fn tp_new(_: PyTypeRef, vm: &VirtualMachine) -> PyRef<Self> {
|
||||
vm.ctx.not_implemented.clone()
|
||||
}
|
||||
impl SlotConstructor for PyNotImplemented {
|
||||
type Args = ();
|
||||
|
||||
fn py_new(_: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(vm.ctx.not_implemented.clone().into_object())
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotConstructor))]
|
||||
impl PyNotImplemented {
|
||||
// TODO: As per https://bugs.python.org/issue35712, using NotImplemented
|
||||
// in boolean contexts will need to raise a DeprecationWarning in 3.9
|
||||
// and, eventually, a TypeError.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use super::int::{PyInt, PyIntRef};
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::function::{FuncArgs, OptionalArg};
|
||||
use crate::slots::{Comparable, Hashable, PyComparisonOp, Unhashable};
|
||||
use crate::slots::{Comparable, Hashable, PyComparisonOp, SlotConstructor, Unhashable};
|
||||
use crate::VirtualMachine;
|
||||
use crate::{
|
||||
IntoPyObject, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue,
|
||||
@@ -94,7 +94,7 @@ impl PySlice {
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let slice: PySlice = match args.args.len() {
|
||||
0 => {
|
||||
return Err(
|
||||
@@ -119,7 +119,7 @@ impl PySlice {
|
||||
}
|
||||
}
|
||||
};
|
||||
slice.into_ref_with_type(vm, cls)
|
||||
slice.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
pub(crate) fn inner_indices(
|
||||
@@ -293,13 +293,16 @@ impl PyValue for PyEllipsis {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
impl PyEllipsis {
|
||||
#[pyslot]
|
||||
fn tp_new(_cls: PyTypeRef, vm: &VirtualMachine) -> PyRef<Self> {
|
||||
vm.ctx.ellipsis.clone()
|
||||
}
|
||||
impl SlotConstructor for PyEllipsis {
|
||||
type Args = ();
|
||||
|
||||
fn py_new(_cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(vm.ctx.ellipsis.clone().into_object())
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotConstructor))]
|
||||
impl PyEllipsis {
|
||||
#[pymethod(magic)]
|
||||
fn repr(&self) -> String {
|
||||
"Ellipsis".to_owned()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::slots::SlotDescriptor;
|
||||
use crate::slots::{SlotConstructor, SlotDescriptor};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::{PyClassImpl, PyContext, PyObjectRef, PyResult, PyValue};
|
||||
|
||||
#[pyclass(module = false, name = "staticmethod")]
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -33,14 +33,17 @@ impl From<PyObjectRef> for PyStaticMethod {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotDescriptor), flags(BASETYPE, HAS_DICT))]
|
||||
impl PyStaticMethod {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, callable: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
PyStaticMethod { callable }.into_ref_with_type(vm, cls)
|
||||
impl SlotConstructor for PyStaticMethod {
|
||||
type Args = PyObjectRef;
|
||||
|
||||
fn py_new(cls: PyTypeRef, callable: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
PyStaticMethod { callable }.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotDescriptor, SlotConstructor), flags(BASETYPE, HAS_DICT))]
|
||||
impl PyStaticMethod {}
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
PyStaticMethod::extend_class(context, &context.types.staticmethod_type);
|
||||
}
|
||||
+31
-32
@@ -15,7 +15,7 @@ use crate::common::hash::PyHash;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::sequence::{self, SimpleSeq};
|
||||
use crate::sliceable::PySliceableSequence;
|
||||
use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter};
|
||||
use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter, SlotConstructor};
|
||||
use crate::utils::Either;
|
||||
use crate::vm::{ReprGuard, VirtualMachine};
|
||||
use crate::{
|
||||
@@ -83,7 +83,36 @@ impl PyTupleRef {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Hashable, Comparable, Iterable))]
|
||||
impl SlotConstructor for PyTuple {
|
||||
type Args = OptionalArg<PyObjectRef>;
|
||||
|
||||
fn py_new(cls: PyTypeRef, iterable: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let elements = if let OptionalArg::Present(iterable) = iterable {
|
||||
let iterable = if cls.is(&vm.ctx.types.tuple_type) {
|
||||
match iterable.downcast_exact::<Self>(vm) {
|
||||
Ok(tuple) => return Ok(tuple.into_object()),
|
||||
Err(iterable) => iterable,
|
||||
}
|
||||
} else {
|
||||
iterable
|
||||
};
|
||||
vm.extract_elements(&iterable)?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
// Return empty tuple only for exact tuple types if the iterable is empty.
|
||||
if elements.is_empty() && cls.is(&vm.ctx.types.tuple_type) {
|
||||
Ok(vm.ctx.empty_tuple.clone().into_object())
|
||||
} else {
|
||||
Self {
|
||||
elements: elements.into_boxed_slice(),
|
||||
}
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Hashable, Comparable, Iterable, SlotConstructor))]
|
||||
impl PyTuple {
|
||||
/// Creating a new tuple with given boxed slice.
|
||||
/// NOTE: for usual case, you probably want to use PyTupleRef::with_elements.
|
||||
@@ -254,36 +283,6 @@ impl PyTuple {
|
||||
};
|
||||
(tup_arg,)
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
iterable: OptionalArg<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
let elements = if let OptionalArg::Present(iterable) = iterable {
|
||||
let iterable = if cls.is(&vm.ctx.types.tuple_type) {
|
||||
match iterable.downcast_exact::<Self>(vm) {
|
||||
Ok(tuple) => return Ok(tuple),
|
||||
Err(iterable) => iterable,
|
||||
}
|
||||
} else {
|
||||
iterable
|
||||
};
|
||||
vm.extract_elements(&iterable)?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
// Return empty tuple only for exact tuple types if the iterable is empty.
|
||||
if elements.is_empty() && cls.is(&vm.ctx.types.tuple_type) {
|
||||
Ok(vm.ctx.empty_tuple.clone())
|
||||
} else {
|
||||
Self {
|
||||
elements: elements.into_boxed_slice(),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Hashable for PyTuple {
|
||||
|
||||
@@ -2,7 +2,7 @@ use super::pytype::PyTypeRef;
|
||||
use super::weakref::PyWeak;
|
||||
use super::PyStrRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::slots::SlotSetattro;
|
||||
use crate::slots::{SlotConstructor, SlotSetattro};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
|
||||
@@ -18,25 +18,35 @@ impl PyValue for PyWeakProxy {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotSetattro))]
|
||||
impl PyWeakProxy {
|
||||
// TODO: callbacks
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
#[derive(FromArgs)]
|
||||
pub struct WeakProxyNewArgs {
|
||||
#[pyarg(positional)]
|
||||
referent: PyObjectRef,
|
||||
#[pyarg(positional, optional)]
|
||||
callback: OptionalArg<PyObjectRef>,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyWeakProxy {
|
||||
type Args = WeakProxyNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
referent: PyObjectRef,
|
||||
callback: OptionalArg<PyObjectRef>,
|
||||
Self::Args { referent, callback }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
if callback.is_present() {
|
||||
panic!("Passed a callback to weakproxy, but weakproxy does not yet support proxies.");
|
||||
}
|
||||
PyWeakProxy {
|
||||
weak: PyWeak::downgrade(&referent),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotSetattro, SlotConstructor))]
|
||||
impl PyWeakProxy {
|
||||
// TODO: callbacks
|
||||
#[pymethod(magic)]
|
||||
fn getattr(&self, attr_name: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
match self.weak.upgrade() {
|
||||
|
||||
+26
-13
@@ -1,7 +1,7 @@
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::common::hash::PyHash;
|
||||
use crate::function::{FuncArgs, OptionalArg};
|
||||
use crate::slots::{Callable, Comparable, Hashable, PyComparisonOp};
|
||||
use crate::slots::{Callable, Comparable, Hashable, PyComparisonOp, SlotConstructor};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{
|
||||
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyObjectWeak, PyRef, PyResult, PyValue,
|
||||
@@ -30,6 +30,14 @@ impl PyWeak {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
pub struct WeakNewArgs {
|
||||
#[pyarg(positional)]
|
||||
referent: PyObjectRef,
|
||||
#[pyarg(positional, optional)]
|
||||
_callback: OptionalArg<PyObjectRef>,
|
||||
}
|
||||
|
||||
impl PyValue for PyWeak {
|
||||
fn class(vm: &VirtualMachine) -> &PyTypeRef {
|
||||
&vm.ctx.types.weakref_type
|
||||
@@ -43,19 +51,24 @@ impl Callable for PyWeak {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(Callable, Hashable, Comparable), flags(BASETYPE))]
|
||||
impl PyWeak {
|
||||
// TODO callbacks
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
referent: PyObjectRef,
|
||||
_callback: OptionalArg<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
PyWeak::downgrade(&referent).into_ref_with_type(vm, cls)
|
||||
}
|
||||
impl SlotConstructor for PyWeak {
|
||||
type Args = WeakNewArgs;
|
||||
|
||||
// TODO callbacks
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
Self::Args {
|
||||
referent,
|
||||
_callback,
|
||||
}: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
PyWeak::downgrade(&referent).into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(Callable, Hashable, Comparable, SlotConstructor), flags(BASETYPE))]
|
||||
impl PyWeak {
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyRef<Self>) -> String {
|
||||
let id = zelf.get_id();
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::function::Args;
|
||||
use crate::iterator;
|
||||
use crate::slots::PyIter;
|
||||
use crate::slots::{PyIter, SlotConstructor};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
|
||||
pub type PyZipRef = PyRef<PyZip>;
|
||||
|
||||
#[pyclass(module = false, name = "zip")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyZip {
|
||||
@@ -19,18 +17,21 @@ impl PyValue for PyZip {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter), flags(BASETYPE))]
|
||||
impl PyZip {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, iterables: Args, vm: &VirtualMachine) -> PyResult<PyZipRef> {
|
||||
impl SlotConstructor for PyZip {
|
||||
type Args = Args;
|
||||
|
||||
fn py_new(cls: PyTypeRef, iterables: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let iterators = iterables
|
||||
.into_iter()
|
||||
.map(|iterable| iterator::get_iter(vm, iterable))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
PyZip { iterators }.into_ref_with_type(vm, cls)
|
||||
PyZip { iterators }.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor), flags(BASETYPE))]
|
||||
impl PyZip {}
|
||||
|
||||
impl PyIter for PyZip {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
if zelf.iterators.is_empty() {
|
||||
|
||||
+3
-11
@@ -63,12 +63,8 @@ impl PyBaseException {
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
pub(crate) fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
args: FuncArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
PyBaseException::new(args.args, vm).into_ref_with_type(vm, cls)
|
||||
pub(crate) fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyBaseException::new(args.args, vm).into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
@@ -555,11 +551,7 @@ macro_rules! extends_exception {
|
||||
#[pyimpl(flags(BASETYPE, HAS_DICT))]
|
||||
impl $class_name {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
args: FuncArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<PyBaseException>> {
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
// We need this method, because of how `CPython` copies `init`
|
||||
// from `BaseException` in `SimpleExtendsException` macro.
|
||||
// See: `BaseException_new`
|
||||
|
||||
@@ -1016,6 +1016,10 @@ pub trait PyValue: fmt::Debug + PyThreadingConstraint + Sized + 'static {
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn into_pyresult_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult {
|
||||
self.into_ref_with_type(vm, cls).into_pyresult(vm)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyObjectPayload: Any + fmt::Debug + PyThreadingConstraint + 'static {}
|
||||
|
||||
+25
-15
@@ -26,7 +26,7 @@ mod array {
|
||||
use crate::sliceable::{
|
||||
saturate_index, PySliceableSequence, PySliceableSequenceMut, SequenceIndex,
|
||||
};
|
||||
use crate::slots::{AsBuffer, Comparable, Iterable, PyComparisonOp, PyIter};
|
||||
use crate::slots::{AsBuffer, Comparable, Iterable, PyComparisonOp, PyIter, SlotConstructor};
|
||||
use crate::stdlib::array::wchar_t;
|
||||
use crate::{
|
||||
IdProtocol, IntoPyObject, PyComparisonValue, PyIterable, PyObjectRef, PyRef, PyResult,
|
||||
@@ -612,23 +612,22 @@ mod array {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Comparable, AsBuffer, Iterable))]
|
||||
impl PyArray {
|
||||
fn read(&self) -> PyRwLockReadGuard<'_, ArrayContentType> {
|
||||
self.array.read()
|
||||
}
|
||||
#[derive(FromArgs)]
|
||||
pub struct ArrayNewArgs {
|
||||
#[pyarg(positional)]
|
||||
spec: PyStrRef,
|
||||
#[pyarg(positional, optional)]
|
||||
init: OptionalArg<PyObjectRef>,
|
||||
}
|
||||
|
||||
fn write(&self) -> PyRwLockWriteGuard<'_, ArrayContentType> {
|
||||
self.array.write()
|
||||
}
|
||||
impl SlotConstructor for PyArray {
|
||||
type Args = ArrayNewArgs;
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
spec: PyStrRef,
|
||||
init: OptionalArg<PyObjectRef>,
|
||||
Self::Args { spec, init }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyArrayRef> {
|
||||
) -> PyResult {
|
||||
let spec = spec.as_str().chars().exactly_one().map_err(|_| {
|
||||
vm.new_type_error(
|
||||
"array() argument 1 must be a unicode character, not str".to_owned(),
|
||||
@@ -675,7 +674,18 @@ mod array {
|
||||
}
|
||||
|
||||
let zelf = Self::from(array).into_ref_with_type(vm, cls)?;
|
||||
Ok(zelf)
|
||||
Ok(zelf.into_object())
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(Comparable, AsBuffer, Iterable, SlotConstructor))]
|
||||
impl PyArray {
|
||||
fn read(&self) -> PyRwLockReadGuard<'_, ArrayContentType> {
|
||||
self.array.read()
|
||||
}
|
||||
|
||||
fn write(&self) -> PyRwLockWriteGuard<'_, ArrayContentType> {
|
||||
self.array.write()
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
|
||||
@@ -4,7 +4,9 @@ pub(crate) use _collections::make_module;
|
||||
mod _collections {
|
||||
use crate::common::lock::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard};
|
||||
use crate::function::{FuncArgs, KwArgs, OptionalArg};
|
||||
use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter, Unhashable};
|
||||
use crate::slots::{
|
||||
Comparable, Hashable, Iterable, PyComparisonOp, PyIter, SlotConstructor, Unhashable,
|
||||
};
|
||||
use crate::vm::ReprGuard;
|
||||
use crate::VirtualMachine;
|
||||
use crate::{
|
||||
@@ -78,8 +80,8 @@ mod _collections {
|
||||
#[pyimpl(flags(BASETYPE), with(Comparable, Hashable, Iterable))]
|
||||
impl PyDeque {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
PyDeque::default().into_ref_with_type(vm, cls)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyDeque::default().into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__init__")]
|
||||
@@ -589,24 +591,14 @@ mod _collections {
|
||||
index: OptionalArg<isize>,
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyDequeIterator {
|
||||
pub(crate) fn new(deque: PyDequeRef) -> Self {
|
||||
PyDequeIterator {
|
||||
position: AtomicCell::new(0),
|
||||
status: AtomicCell::new(IterStatus::Active),
|
||||
length: deque.len(),
|
||||
deque,
|
||||
}
|
||||
}
|
||||
impl SlotConstructor for PyDequeIterator {
|
||||
type Args = (DequeIterArgs, KwArgs);
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
DequeIterArgs { deque, index }: DequeIterArgs,
|
||||
_kwargs: KwArgs,
|
||||
(DequeIterArgs { deque, index }, _kwargs): Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let len = deque.len();
|
||||
let iter = PyDequeIterator::new(deque);
|
||||
if let OptionalArg::Present(index) = index {
|
||||
@@ -617,7 +609,19 @@ mod _collections {
|
||||
iter.status.store(Exhausted);
|
||||
}
|
||||
}
|
||||
iter.into_ref_with_type(vm, cls)
|
||||
iter.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyDequeIterator {
|
||||
pub(crate) fn new(deque: PyDequeRef) -> Self {
|
||||
PyDequeIterator {
|
||||
position: AtomicCell::new(0),
|
||||
status: AtomicCell::new(IterStatus::Active),
|
||||
length: deque.len(),
|
||||
deque,
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
@@ -681,23 +685,15 @@ mod _collections {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyReverseDequeIterator {
|
||||
#[pymethod(magic)]
|
||||
fn length_hint(&self) -> usize {
|
||||
match self.status.load() {
|
||||
Active => self.position.load(),
|
||||
Exhausted => 0,
|
||||
}
|
||||
}
|
||||
impl SlotConstructor for PyReverseDequeIterator {
|
||||
type Args = (DequeIterArgs, KwArgs);
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
DequeIterArgs { deque, index }: DequeIterArgs,
|
||||
_kwargs: KwArgs,
|
||||
|
||||
(DequeIterArgs { deque, index }, _kwargs): Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let len = deque.len();
|
||||
let iter = PyDeque::reversed(deque)?;
|
||||
if let OptionalArg::Present(index) = index {
|
||||
@@ -707,7 +703,18 @@ mod _collections {
|
||||
}
|
||||
iter.position.store(len.saturating_sub(index));
|
||||
}
|
||||
iter.into_ref_with_type(vm, cls)
|
||||
iter.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyReverseDequeIterator {
|
||||
#[pymethod(magic)]
|
||||
fn length_hint(&self) -> usize {
|
||||
match self.status.load() {
|
||||
Active => self.position.load(),
|
||||
Exhausted => 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
|
||||
+57
-53
@@ -92,6 +92,7 @@ mod _io {
|
||||
use crate::common::rc::PyRc;
|
||||
use crate::exceptions::{self, IntoPyException, PyBaseExceptionRef};
|
||||
use crate::function::{FuncArgs, OptionalArg, OptionalOption};
|
||||
use crate::slots::SlotConstructor;
|
||||
use crate::utils::Either;
|
||||
use crate::vm::{ReprGuard, VirtualMachine};
|
||||
use crate::{
|
||||
@@ -1667,8 +1668,8 @@ mod _io {
|
||||
#[pyimpl(with(BufferedMixin, BufferedReadable), flags(BASETYPE, HAS_DICT))]
|
||||
impl BufferedReader {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
Self::default().into_ref_with_type(vm, cls)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Self::default().into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1721,8 +1722,8 @@ mod _io {
|
||||
#[pyimpl(with(BufferedMixin, BufferedWritable), flags(BASETYPE, HAS_DICT))]
|
||||
impl BufferedWriter {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
Self::default().into_ref_with_type(vm, cls)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Self::default().into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1764,8 +1765,8 @@ mod _io {
|
||||
)]
|
||||
impl BufferedRandom {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
Self::default().into_ref_with_type(vm, cls)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Self::default().into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1796,8 +1797,8 @@ mod _io {
|
||||
#[pyimpl(with(BufferedReadable, BufferedWritable), flags(BASETYPE, HAS_DICT))]
|
||||
impl BufferedRWPair {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
Self::default().into_ref_with_type(vm, cls)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Self::default().into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
#[pymethod(magic)]
|
||||
fn init(
|
||||
@@ -2198,8 +2199,8 @@ mod _io {
|
||||
#[pyimpl(flags(BASETYPE))]
|
||||
impl TextIOWrapper {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
Self::default().into_ref_with_type(vm, cls)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Self::default().into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
fn lock_opt(
|
||||
@@ -3044,14 +3045,6 @@ mod _io {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct StringIOArgs {
|
||||
#[pyarg(any, default)]
|
||||
#[allow(dead_code)]
|
||||
// TODO: use this
|
||||
newline: Newlines,
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "StringIO", base = "_TextIOBase")]
|
||||
#[derive(Debug)]
|
||||
@@ -3068,23 +3061,26 @@ mod _io {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE, HAS_DICT), with(PyRef))]
|
||||
impl StringIO {
|
||||
fn buffer(&self, vm: &VirtualMachine) -> PyResult<PyRwLockWriteGuard<'_, BufferedIO>> {
|
||||
if !self.closed.load() {
|
||||
Ok(self.buffer.write())
|
||||
} else {
|
||||
Err(io_closed_error(vm))
|
||||
}
|
||||
}
|
||||
#[derive(FromArgs)]
|
||||
struct StringIONewArgs {
|
||||
#[pyarg(positional, optional)]
|
||||
object: OptionalOption<PyStrRef>,
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
// TODO: use this
|
||||
#[pyarg(any, default)]
|
||||
#[allow(dead_code)]
|
||||
newline: Newlines,
|
||||
}
|
||||
|
||||
impl SlotConstructor for StringIO {
|
||||
type Args = StringIONewArgs;
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
object: OptionalOption<PyStrRef>,
|
||||
_args: StringIOArgs,
|
||||
Self::Args { object, newline }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<StringIORef> {
|
||||
) -> PyResult {
|
||||
let raw_bytes = object
|
||||
.flatten()
|
||||
.map_or_else(Vec::new, |v| v.as_str().as_bytes().to_vec());
|
||||
@@ -3093,7 +3089,18 @@ mod _io {
|
||||
buffer: PyRwLock::new(BufferedIO::new(Cursor::new(raw_bytes))),
|
||||
closed: AtomicCell::new(false),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE, HAS_DICT), with(PyRef, SlotConstructor))]
|
||||
impl StringIO {
|
||||
fn buffer(&self, vm: &VirtualMachine) -> PyResult<PyRwLockWriteGuard<'_, BufferedIO>> {
|
||||
if !self.closed.load() {
|
||||
Ok(self.buffer.write())
|
||||
} else {
|
||||
Err(io_closed_error(vm))
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -3211,22 +3218,10 @@ mod _io {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE, HAS_DICT), with(PyRef))]
|
||||
impl BytesIO {
|
||||
fn buffer(&self, vm: &VirtualMachine) -> PyResult<PyRwLockWriteGuard<'_, BufferedIO>> {
|
||||
if !self.closed.load() {
|
||||
Ok(self.buffer.write())
|
||||
} else {
|
||||
Err(io_closed_error(vm))
|
||||
}
|
||||
}
|
||||
impl SlotConstructor for BytesIO {
|
||||
type Args = OptionalArg<Option<PyBytesRef>>;
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
object: OptionalArg<Option<PyBytesRef>>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<BytesIORef> {
|
||||
fn py_new(cls: PyTypeRef, object: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let raw_bytes = object
|
||||
.flatten()
|
||||
.map_or_else(Vec::new, |input| input.as_bytes().to_vec());
|
||||
@@ -3236,7 +3231,18 @@ mod _io {
|
||||
closed: AtomicCell::new(false),
|
||||
exports: AtomicCell::new(0),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE, HAS_DICT), with(PyRef, SlotConstructor))]
|
||||
impl BytesIO {
|
||||
fn buffer(&self, vm: &VirtualMachine) -> PyResult<PyRwLockWriteGuard<'_, BufferedIO>> {
|
||||
if !self.closed.load() {
|
||||
Ok(self.buffer.write())
|
||||
} else {
|
||||
Err(io_closed_error(vm))
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -3844,8 +3850,6 @@ mod fileio {
|
||||
seekable: AtomicCell<Option<bool>>,
|
||||
}
|
||||
|
||||
type FileIORef = PyRef<FileIO>;
|
||||
|
||||
impl PyValue for FileIO {
|
||||
fn class(_vm: &VirtualMachine) -> &PyTypeRef {
|
||||
Self::static_type()
|
||||
@@ -3867,14 +3871,14 @@ mod fileio {
|
||||
#[pyimpl(flags(BASETYPE, HAS_DICT))]
|
||||
impl FileIO {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<FileIORef> {
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
FileIO {
|
||||
fd: AtomicCell::new(-1),
|
||||
closefd: AtomicCell::new(false),
|
||||
mode: AtomicCell::new(Mode::empty()),
|
||||
seekable: AtomicCell::new(None),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
|
||||
+279
-176
@@ -15,7 +15,7 @@ mod decl {
|
||||
use crate::common::rc::PyRc;
|
||||
use crate::function::{Args, FuncArgs, OptionalArg, OptionalOption};
|
||||
use crate::iterator::{call_next, get_all, get_iter, get_next_object};
|
||||
use crate::slots::PyIter;
|
||||
use crate::slots::{PyIter, SlotConstructor};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{
|
||||
IdProtocol, IntoPyObject, PyCallable, PyObjectRef, PyRef, PyResult, PyValue, PyWeakRef,
|
||||
@@ -40,13 +40,13 @@ mod decl {
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsChain {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyItertoolsChain {
|
||||
iterables: args.args,
|
||||
cur_idx: AtomicCell::new(0),
|
||||
cached_iter: PyRwLock::new(None),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pyclassmethod]
|
||||
@@ -117,15 +117,22 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsCompress {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
#[derive(FromArgs)]
|
||||
struct CompressNewArgs {
|
||||
#[pyarg(positional)]
|
||||
data: PyObjectRef,
|
||||
#[pyarg(positional)]
|
||||
selector: PyObjectRef,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyItertoolsCompress {
|
||||
type Args = CompressNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
data: PyObjectRef,
|
||||
selector: PyObjectRef,
|
||||
Self::Args { data, selector }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let data_iter = get_iter(vm, data)?;
|
||||
let selector_iter = get_iter(vm, selector)?;
|
||||
|
||||
@@ -133,9 +140,13 @@ mod decl {
|
||||
data: data_iter,
|
||||
selector: selector_iter,
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsCompress {}
|
||||
|
||||
impl PyIter for PyItertoolsCompress {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
loop {
|
||||
@@ -164,15 +175,23 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsCount {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
#[derive(FromArgs)]
|
||||
struct CountNewArgs {
|
||||
#[pyarg(positional, optional)]
|
||||
start: OptionalArg<PyIntRef>,
|
||||
|
||||
#[pyarg(positional, optional)]
|
||||
step: OptionalArg<PyIntRef>,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyItertoolsCount {
|
||||
type Args = CountNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
start: OptionalArg<PyIntRef>,
|
||||
step: OptionalArg<PyIntRef>,
|
||||
Self::Args { start, step }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let start = match start.into_option() {
|
||||
Some(int) => int.as_bigint().clone(),
|
||||
None => BigInt::zero(),
|
||||
@@ -186,9 +205,12 @@ mod decl {
|
||||
cur: PyRwLock::new(start),
|
||||
step,
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsCount {}
|
||||
impl PyIter for PyItertoolsCount {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let mut cur = zelf.cur.write();
|
||||
@@ -213,14 +235,10 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsCycle {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
iterable: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for PyItertoolsCycle {
|
||||
type Args = PyObjectRef;
|
||||
|
||||
fn py_new(cls: PyTypeRef, iterable: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let iter = get_iter(vm, iterable)?;
|
||||
|
||||
PyItertoolsCycle {
|
||||
@@ -228,9 +246,12 @@ mod decl {
|
||||
saved: PyRwLock::new(Vec::new()),
|
||||
index: AtomicCell::new(0),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsCycle {}
|
||||
impl PyIter for PyItertoolsCycle {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let item = if let Some(item) = get_next_object(vm, &zelf.iter)? {
|
||||
@@ -277,14 +298,14 @@ mod decl {
|
||||
times: OptionalArg<PyIntRef>,
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter), flags(BASETYPE))]
|
||||
impl PyItertoolsRepeat {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
impl SlotConstructor for PyItertoolsRepeat {
|
||||
type Args = PyRepeatNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
PyRepeatNewArgs { object, times }: PyRepeatNewArgs,
|
||||
Self::Args { object, times }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let times = match times.into_option() {
|
||||
Some(int) => {
|
||||
let val = int.as_bigint();
|
||||
@@ -296,9 +317,12 @@ mod decl {
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
PyItertoolsRepeat { object, times }.into_ref_with_type(vm, cls)
|
||||
PyItertoolsRepeat { object, times }.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor), flags(BASETYPE))]
|
||||
impl PyItertoolsRepeat {
|
||||
#[pymethod(magic)]
|
||||
fn length_hint(&self, vm: &VirtualMachine) -> PyResult {
|
||||
match self.times {
|
||||
@@ -362,20 +386,30 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsStarmap {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
#[derive(FromArgs)]
|
||||
struct StarmapNewArgs {
|
||||
#[pyarg(positional)]
|
||||
function: PyObjectRef,
|
||||
#[pyarg(positional)]
|
||||
iterable: PyObjectRef,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyItertoolsStarmap {
|
||||
type Args = StarmapNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
function: PyObjectRef,
|
||||
iterable: PyObjectRef,
|
||||
Self::Args { function, iterable }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let iter = get_iter(vm, iterable)?;
|
||||
|
||||
PyItertoolsStarmap { function, iter }.into_ref_with_type(vm, cls)
|
||||
PyItertoolsStarmap { function, iter }.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsStarmap {}
|
||||
impl PyIter for PyItertoolsStarmap {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let obj = call_next(vm, &zelf.iter)?;
|
||||
@@ -400,15 +434,25 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsTakewhile {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
#[derive(FromArgs)]
|
||||
struct TakewhileNewArgs {
|
||||
#[pyarg(positional)]
|
||||
predicate: PyObjectRef,
|
||||
#[pyarg(positional)]
|
||||
iterable: PyObjectRef,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyItertoolsTakewhile {
|
||||
type Args = TakewhileNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
predicate: PyObjectRef,
|
||||
iterable: PyObjectRef,
|
||||
Self::Args {
|
||||
predicate,
|
||||
iterable,
|
||||
}: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let iter = get_iter(vm, iterable)?;
|
||||
|
||||
PyItertoolsTakewhile {
|
||||
@@ -416,9 +460,12 @@ mod decl {
|
||||
iterable: iter,
|
||||
stop_flag: AtomicCell::new(false),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsTakewhile {}
|
||||
impl PyIter for PyItertoolsTakewhile {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
if zelf.stop_flag.load() {
|
||||
@@ -455,15 +502,25 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsDropwhile {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
#[derive(FromArgs)]
|
||||
struct DropwhileNewArgs {
|
||||
#[pyarg(positional)]
|
||||
predicate: PyCallable,
|
||||
#[pyarg(positional)]
|
||||
iterable: PyObjectRef,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyItertoolsDropwhile {
|
||||
type Args = DropwhileNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
predicate: PyCallable,
|
||||
iterable: PyObjectRef,
|
||||
Self::Args {
|
||||
predicate,
|
||||
iterable,
|
||||
}: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let iter = get_iter(vm, iterable)?;
|
||||
|
||||
PyItertoolsDropwhile {
|
||||
@@ -471,9 +528,12 @@ mod decl {
|
||||
iterable: iter,
|
||||
start_flag: AtomicCell::new(false),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsDropwhile {}
|
||||
impl PyIter for PyItertoolsDropwhile {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let predicate = &zelf.predicate;
|
||||
@@ -551,10 +611,10 @@ mod decl {
|
||||
key: OptionalOption<PyObjectRef>,
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsGroupBy {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, args: GroupByArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for PyItertoolsGroupBy {
|
||||
type Args = GroupByArgs;
|
||||
|
||||
fn py_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let iter = get_iter(vm, args.iterable)?;
|
||||
|
||||
PyItertoolsGroupBy {
|
||||
@@ -567,9 +627,12 @@ mod decl {
|
||||
grouper: None,
|
||||
}),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsGroupBy {
|
||||
pub(super) fn advance(&self, vm: &VirtualMachine) -> PyResult<(PyObjectRef, PyObjectRef)> {
|
||||
let new_value = call_next(vm, &self.iterable)?;
|
||||
let new_key = if let Some(ref kf) = self.key_func {
|
||||
@@ -709,7 +772,7 @@ mod decl {
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsIslice {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let (iter, start, stop, step) = match args.args.len() {
|
||||
0 | 1 => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
@@ -766,7 +829,7 @@ mod decl {
|
||||
stop,
|
||||
step,
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,24 +871,37 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsFilterFalse {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
#[derive(FromArgs)]
|
||||
struct FilterFalseNewArgs {
|
||||
#[pyarg(positional)]
|
||||
predicate: PyObjectRef,
|
||||
#[pyarg(positional)]
|
||||
iterable: PyObjectRef,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyItertoolsFilterFalse {
|
||||
type Args = FilterFalseNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
predicate: PyObjectRef,
|
||||
iterable: PyObjectRef,
|
||||
Self::Args {
|
||||
predicate,
|
||||
iterable,
|
||||
}: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let iter = get_iter(vm, iterable)?;
|
||||
|
||||
PyItertoolsFilterFalse {
|
||||
predicate,
|
||||
iterable: iter,
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsFilterFalse {}
|
||||
impl PyIter for PyItertoolsFilterFalse {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let predicate = &zelf.predicate;
|
||||
@@ -871,14 +947,10 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsAccumulate {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
args: AccumulateArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for PyItertoolsAccumulate {
|
||||
type Args = AccumulateArgs;
|
||||
|
||||
fn py_new(cls: PyTypeRef, args: AccumulateArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let iter = get_iter(vm, args.iterable)?;
|
||||
|
||||
PyItertoolsAccumulate {
|
||||
@@ -887,9 +959,13 @@ mod decl {
|
||||
initial: args.initial.flatten(),
|
||||
acc_value: PyRwLock::new(None),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsAccumulate {}
|
||||
|
||||
impl PyIter for PyItertoolsAccumulate {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let iterable = &zelf.iterable;
|
||||
@@ -952,32 +1028,25 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsTee {
|
||||
fn from_iter(iterable: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let class = PyItertoolsTee::class(vm);
|
||||
let it = get_iter(vm, iterable)?;
|
||||
if it.class().is(PyItertoolsTee::class(vm)) {
|
||||
return vm.call_method(&it, "__copy__", ());
|
||||
}
|
||||
Ok(PyItertoolsTee {
|
||||
tee_data: PyItertoolsTeeData::new(it, vm)?,
|
||||
index: AtomicCell::new(0),
|
||||
}
|
||||
.into_ref_with_type(vm, class.clone())?
|
||||
.into_object())
|
||||
}
|
||||
#[derive(FromArgs)]
|
||||
struct TeeNewArgs {
|
||||
#[pyarg(positional)]
|
||||
iterable: PyObjectRef,
|
||||
#[pyarg(positional, optional)]
|
||||
n: OptionalArg<usize>,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyItertoolsTee {
|
||||
type Args = TeeNewArgs;
|
||||
|
||||
// TODO: make tee() a function, rename this class to itertools._tee and make
|
||||
// teedata a python class
|
||||
#[pyslot]
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
fn tp_new(
|
||||
fn py_new(
|
||||
_cls: PyTypeRef,
|
||||
iterable: PyObjectRef,
|
||||
n: OptionalArg<usize>,
|
||||
Self::Args { iterable, n }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyTupleRef> {
|
||||
) -> PyResult {
|
||||
let n = n.unwrap_or(2);
|
||||
|
||||
let copyable = if iterable.class().has_attr("__copy__") {
|
||||
@@ -991,7 +1060,24 @@ mod decl {
|
||||
tee_vec.push(vm.call_method(©able, "__copy__", ())?);
|
||||
}
|
||||
|
||||
Ok(PyTupleRef::with_elements(tee_vec, &vm.ctx))
|
||||
Ok(PyTupleRef::with_elements(tee_vec, &vm.ctx).into_object())
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsTee {
|
||||
fn from_iter(iterable: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let class = PyItertoolsTee::class(vm);
|
||||
let it = get_iter(vm, iterable)?;
|
||||
if it.class().is(PyItertoolsTee::class(vm)) {
|
||||
return vm.call_method(&it, "__copy__", ());
|
||||
}
|
||||
Ok(PyItertoolsTee {
|
||||
tee_data: PyItertoolsTeeData::new(it, vm)?,
|
||||
index: AtomicCell::new(0),
|
||||
}
|
||||
.into_ref_with_type(vm, class.clone())?
|
||||
.into_object())
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
@@ -1034,17 +1120,11 @@ mod decl {
|
||||
repeat: OptionalArg<usize>,
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsProduct {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
iterables: Args<PyObjectRef>,
|
||||
args: ProductArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
let repeat = args.repeat.unwrap_or(1);
|
||||
impl SlotConstructor for PyItertoolsProduct {
|
||||
type Args = (Args<PyObjectRef>, ProductArgs);
|
||||
|
||||
fn py_new(cls: PyTypeRef, (iterables, args): Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let repeat = args.repeat.unwrap_or(1);
|
||||
let mut pools = Vec::new();
|
||||
for arg in iterables.into_iter() {
|
||||
let it = get_iter(vm, arg)?;
|
||||
@@ -1065,9 +1145,12 @@ mod decl {
|
||||
cur: AtomicCell::new(l.wrapping_sub(1)),
|
||||
stop: AtomicCell::new(false),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsProduct {
|
||||
fn update_idxs(&self, mut idxs: PyRwLockWriteGuard<'_, Vec<usize>>) {
|
||||
if idxs.len() == 0 {
|
||||
self.stop.store(true);
|
||||
@@ -1137,15 +1220,22 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsCombinations {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
#[derive(FromArgs)]
|
||||
struct CombinationsNewArgs {
|
||||
#[pyarg(positional)]
|
||||
iterable: PyObjectRef,
|
||||
#[pyarg(positional)]
|
||||
r: PyIntRef,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyItertoolsCombinations {
|
||||
type Args = CombinationsNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
iterable: PyObjectRef,
|
||||
r: PyIntRef,
|
||||
Self::Args { iterable, r }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let iter = get_iter(vm, iterable)?;
|
||||
let pool = get_all(vm, &iter)?;
|
||||
|
||||
@@ -1163,9 +1253,12 @@ mod decl {
|
||||
r: AtomicCell::new(r),
|
||||
exhausted: AtomicCell::new(r > n),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsCombinations {}
|
||||
impl PyIter for PyItertoolsCombinations {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
// stop signal
|
||||
@@ -1232,15 +1325,14 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsCombinationsWithReplacement {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
impl SlotConstructor for PyItertoolsCombinationsWithReplacement {
|
||||
type Args = CombinationsNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
iterable: PyObjectRef,
|
||||
r: PyIntRef,
|
||||
Self::Args { iterable, r }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let iter = get_iter(vm, iterable)?;
|
||||
let pool = get_all(vm, &iter)?;
|
||||
|
||||
@@ -1258,9 +1350,13 @@ mod decl {
|
||||
r: AtomicCell::new(r),
|
||||
exhausted: AtomicCell::new(n == 0 && r > 0),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsCombinationsWithReplacement {}
|
||||
|
||||
impl PyIter for PyItertoolsCombinationsWithReplacement {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
// stop signal
|
||||
@@ -1324,15 +1420,22 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsPermutations {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
#[derive(FromArgs)]
|
||||
struct PermutationsNewArgs {
|
||||
#[pyarg(positional)]
|
||||
iterable: PyObjectRef,
|
||||
#[pyarg(positional, optional)]
|
||||
r: OptionalOption<PyObjectRef>,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyItertoolsPermutations {
|
||||
type Args = PermutationsNewArgs;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
iterable: PyObjectRef,
|
||||
r: OptionalOption<PyObjectRef>,
|
||||
Self::Args { iterable, r }: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
let pool = vm.extract_elements(&iterable)?;
|
||||
|
||||
let n = pool.len();
|
||||
@@ -1361,9 +1464,12 @@ mod decl {
|
||||
r: AtomicCell::new(r),
|
||||
exhausted: AtomicCell::new(r > n),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsPermutations {}
|
||||
impl PyIter for PyItertoolsPermutations {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
// stop signal
|
||||
@@ -1431,6 +1537,30 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct ZipLongestArgs {
|
||||
#[pyarg(named, optional)]
|
||||
fillvalue: OptionalArg<PyObjectRef>,
|
||||
}
|
||||
|
||||
impl SlotConstructor for PyItertoolsZipLongest {
|
||||
type Args = (Args<PyObjectRef>, ZipLongestArgs);
|
||||
|
||||
fn py_new(cls: PyTypeRef, (iterables, args): Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let fillvalue = args.fillvalue.unwrap_or_none(vm);
|
||||
let iterators = iterables
|
||||
.into_iter()
|
||||
.map(|iterable| get_iter(vm, iterable))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
PyItertoolsZipLongest {
|
||||
iterators,
|
||||
fillvalue,
|
||||
}
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "zip_longest")]
|
||||
#[derive(Debug)]
|
||||
@@ -1445,34 +1575,8 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct ZipLongestArgs {
|
||||
#[pyarg(named, optional)]
|
||||
fillvalue: OptionalArg<PyObjectRef>,
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsZipLongest {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
iterables: Args,
|
||||
args: ZipLongestArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
let fillvalue = args.fillvalue.unwrap_or_none(vm);
|
||||
let iterators = iterables
|
||||
.into_iter()
|
||||
.map(|iterable| get_iter(vm, iterable))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
PyItertoolsZipLongest {
|
||||
iterators,
|
||||
fillvalue,
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsZipLongest {}
|
||||
impl PyIter for PyItertoolsZipLongest {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
if zelf.iterators.is_empty() {
|
||||
@@ -1516,23 +1620,22 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter))]
|
||||
impl PyItertoolsPairwise {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
iterable: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for PyItertoolsPairwise {
|
||||
type Args = PyObjectRef;
|
||||
|
||||
fn py_new(cls: PyTypeRef, iterable: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let iterator = get_iter(vm, iterable)?;
|
||||
|
||||
PyItertoolsPairwise {
|
||||
iterator,
|
||||
old: PyRwLock::new(None),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyIter, SlotConstructor))]
|
||||
impl PyItertoolsPairwise {}
|
||||
impl PyIter for PyItertoolsPairwise {
|
||||
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let old = match zelf.old.read().clone() {
|
||||
|
||||
@@ -9,7 +9,7 @@ mod _json {
|
||||
use crate::exceptions::PyBaseExceptionRef;
|
||||
use crate::function::{FuncArgs, OptionalArg};
|
||||
use crate::iterator;
|
||||
use crate::slots::Callable;
|
||||
use crate::slots::{Callable, SlotConstructor};
|
||||
use crate::VirtualMachine;
|
||||
use crate::{
|
||||
IdProtocol, IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue, StaticType, TryFromObject,
|
||||
@@ -37,10 +37,10 @@ mod _json {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(Callable))]
|
||||
impl JsonScanner {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, ctx: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for JsonScanner {
|
||||
type Args = PyObjectRef;
|
||||
|
||||
fn py_new(cls: PyTypeRef, ctx: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let strict = pybool::boolval(vm, vm.get_attribute(ctx.clone(), "strict")?)?;
|
||||
let object_hook = vm.option_if_none(vm.get_attribute(ctx.clone(), "object_hook")?);
|
||||
let object_pairs_hook =
|
||||
@@ -69,9 +69,12 @@ mod _json {
|
||||
parse_constant,
|
||||
ctx,
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(Callable, SlotConstructor))]
|
||||
impl JsonScanner {
|
||||
fn parse(
|
||||
&self,
|
||||
s: &str,
|
||||
|
||||
+13
-15
@@ -22,8 +22,8 @@ mod _operator {
|
||||
use crate::function::OptionalArg;
|
||||
use crate::iterator;
|
||||
use crate::pyobject::TypeProtocol;
|
||||
use crate::slots::Callable;
|
||||
use crate::slots::PyComparisonOp::{Eq, Ge, Gt, Le, Lt, Ne};
|
||||
use crate::slots::{Callable, SlotConstructor};
|
||||
use crate::utils::Either;
|
||||
use crate::vm::ReprGuard;
|
||||
use crate::IdProtocol;
|
||||
@@ -450,7 +450,7 @@ mod _operator {
|
||||
#[pyimpl(with(Callable))]
|
||||
impl PyAttrGetter {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let nattr = args.args.len();
|
||||
// Check we get no keyword and at least one positional.
|
||||
if !args.kwargs.is_empty() {
|
||||
@@ -467,7 +467,7 @@ mod _operator {
|
||||
return Err(vm.new_type_error("attribute name must be a string".to_owned()));
|
||||
}
|
||||
}
|
||||
PyAttrGetter { attrs }.into_ref_with_type(vm, cls)
|
||||
PyAttrGetter { attrs }.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
@@ -553,7 +553,7 @@ mod _operator {
|
||||
#[pyimpl(with(Callable))]
|
||||
impl PyItemGetter {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
// Check we get no keyword and at least one positional.
|
||||
if !args.kwargs.is_empty() {
|
||||
return Err(vm.new_type_error("itemgetter() takes no keyword arguments".to_owned()));
|
||||
@@ -561,7 +561,7 @@ 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_ref_with_type(vm, cls)
|
||||
PyItemGetter { items: args.args }.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
@@ -626,22 +626,20 @@ mod _operator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(Callable))]
|
||||
impl PyMethodCaller {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
name: PyObjectRef,
|
||||
args: FuncArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for PyMethodCaller {
|
||||
type Args = (PyObjectRef, FuncArgs);
|
||||
|
||||
fn py_new(cls: PyTypeRef, (name, args): Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
if let Ok(name) = name.try_into_ref(vm) {
|
||||
PyMethodCaller { name, args }.into_ref_with_type(vm, cls)
|
||||
PyMethodCaller { name, args }.into_pyresult_with_type(vm, cls)
|
||||
} else {
|
||||
Err(vm.new_type_error("method name must be a string".to_owned()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(Callable, SlotConstructor))]
|
||||
impl PyMethodCaller {
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
|
||||
let fmt = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
|
||||
|
||||
@@ -26,7 +26,7 @@ pub(crate) mod _struct {
|
||||
use crate::byteslike::{ArgBytesLike, ArgMemoryBuffer};
|
||||
use crate::exceptions::PyBaseExceptionRef;
|
||||
use crate::function::Args;
|
||||
use crate::slots::PyIter;
|
||||
use crate::slots::{PyIter, SlotConstructor};
|
||||
use crate::stdlib::array::wchar_t;
|
||||
use crate::utils::Either;
|
||||
use crate::VirtualMachine;
|
||||
@@ -882,23 +882,22 @@ pub(crate) mod _struct {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
impl PyStruct {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
cls: PyTypeRef,
|
||||
fmt: Either<PyStrRef, PyBytesRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
impl SlotConstructor for PyStruct {
|
||||
type Args = Either<PyStrRef, PyBytesRef>;
|
||||
|
||||
fn py_new(cls: PyTypeRef, fmt: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let spec = FormatSpec::decode_and_parse(vm, &fmt)?;
|
||||
let fmt_str = match fmt {
|
||||
Either::A(s) => s,
|
||||
Either::B(b) => PyStr::from(std::str::from_utf8(b.as_bytes()).unwrap())
|
||||
.into_ref_with_type(vm, vm.ctx.types.str_type.clone())?,
|
||||
};
|
||||
PyStruct { spec, fmt_str }.into_ref_with_type(vm, cls)
|
||||
PyStruct { spec, fmt_str }.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotConstructor))]
|
||||
impl PyStruct {
|
||||
#[pyproperty]
|
||||
fn format(&self) -> PyStrRef {
|
||||
self.fmt_str.clone()
|
||||
|
||||
+12
-8
@@ -8,8 +8,9 @@ mod _random {
|
||||
use crate::builtins::pytype::PyTypeRef;
|
||||
use crate::common::lock::PyMutex;
|
||||
use crate::function::OptionalOption;
|
||||
use crate::slots::SlotConstructor;
|
||||
use crate::VirtualMachine;
|
||||
use crate::{PyObjectRef, PyRef, PyResult, PyValue, StaticType};
|
||||
use crate::{PyObjectRef, PyResult, PyValue, StaticType};
|
||||
use num_bigint::{BigInt, Sign};
|
||||
use num_traits::{Signed, Zero};
|
||||
use rand::{rngs::StdRng, RngCore, SeedableRng};
|
||||
@@ -66,21 +67,24 @@ mod _random {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE))]
|
||||
impl PyRandom {
|
||||
#[pyslot(new)]
|
||||
fn new(
|
||||
impl SlotConstructor for PyRandom {
|
||||
type Args = OptionalOption<PyObjectRef>;
|
||||
|
||||
fn py_new(
|
||||
cls: PyTypeRef,
|
||||
// TODO: use x as the seed.
|
||||
_x: OptionalOption<PyObjectRef>,
|
||||
_x: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
) -> PyResult {
|
||||
PyRandom {
|
||||
rng: PyMutex::default(),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(SlotConstructor))]
|
||||
impl PyRandom {
|
||||
#[pymethod]
|
||||
fn random(&self) -> f64 {
|
||||
let mut rng = self.rng.lock();
|
||||
|
||||
@@ -191,8 +191,8 @@ impl PySocket {
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
Self::default().into_ref_with_type(vm, cls)
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Self::default().into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
|
||||
+19
-15
@@ -12,6 +12,7 @@ use crate::{
|
||||
StaticType,
|
||||
};
|
||||
|
||||
use crate::slots::SlotConstructor;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use foreign_types_shared::{ForeignType, ForeignTypeRef};
|
||||
use openssl::{
|
||||
@@ -273,21 +274,10 @@ fn builder_as_ctx(x: &SslContextBuilder) -> &ssl::SslContextRef {
|
||||
unsafe { ssl::SslContextRef::from_ptr(x.as_ptr()) }
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE))]
|
||||
impl PySslContext {
|
||||
fn builder(&self) -> PyRwLockWriteGuard<'_, SslContextBuilder> {
|
||||
self.ctx.write()
|
||||
}
|
||||
fn exec_ctx<F, R>(&self, func: F) -> R
|
||||
where
|
||||
F: Fn(&ssl::SslContextRef) -> R,
|
||||
{
|
||||
let c = self.ctx.read();
|
||||
func(builder_as_ctx(&c))
|
||||
}
|
||||
impl SlotConstructor for PySslContext {
|
||||
type Args = i32;
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, proto_version: i32, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
fn py_new(cls: PyTypeRef, proto_version: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let proto = SslVersion::try_from(proto_version)
|
||||
.map_err(|_| vm.new_value_error("invalid protocol version".to_owned()))?;
|
||||
let method = match proto {
|
||||
@@ -339,7 +329,21 @@ impl PySslContext {
|
||||
check_hostname: AtomicCell::new(check_hostname),
|
||||
protocol: proto,
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE), with(SlotConstructor))]
|
||||
impl PySslContext {
|
||||
fn builder(&self) -> PyRwLockWriteGuard<'_, SslContextBuilder> {
|
||||
self.ctx.write()
|
||||
}
|
||||
fn exec_ctx<F, R>(&self, func: F) -> R
|
||||
where
|
||||
F: Fn(&ssl::SslContextRef) -> R,
|
||||
{
|
||||
let c = self.ctx.read();
|
||||
func(builder_as_ctx(&c))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
|
||||
@@ -169,11 +169,11 @@ impl fmt::Debug for PyRLock {
|
||||
#[pyimpl]
|
||||
impl PyRLock {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyRLock {
|
||||
mu: RawRMutex::INIT,
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -321,11 +321,11 @@ impl PyLocal {
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyLocal {
|
||||
data: ThreadLocal::new(),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.into_pyresult_with_type(vm, cls)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ use chrono::{Datelike, Timelike};
|
||||
|
||||
use crate::builtins::pystr::PyStrRef;
|
||||
use crate::builtins::pytype::PyTypeRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::function::{FuncArgs, OptionalArg};
|
||||
use crate::utils::Either;
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{PyClassImpl, PyObjectRef, PyResult, PyStructSequence, TryFromObject};
|
||||
@@ -227,9 +227,10 @@ impl PyStructTime {
|
||||
}
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(_cls: PyTypeRef, seq: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
fn tp_new(_cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
// cls is ignorable because this is not a basetype
|
||||
Self::try_from_object(vm, seq)
|
||||
let seq = args.bind(vm)?;
|
||||
Ok(vm.new_pyobj(Self::try_from_object(vm, seq)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user