implement SlotConstructor for every class

This commit is contained in:
eldpswp99 authored and Jeong YunWon committed 2021-09-04 20:18:13 +09:00
1 parent 407cc7aae2
commit 55709b71b6
48 files changed
+972 -737

No files matched your search

+2 -8
View File
@@ -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()) {
+2 -2
View File
@@ -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
View File
@@ -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("", "")
+11 -8
View File
@@ -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()
+2 -1
View File
@@ -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
View File
@@ -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)]
+2 -2
View File
@@ -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)]
+10 -7
View File
@@ -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)?;
+19 -9
View File
@@ -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
View File
@@ -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())
+3 -1
View File
@@ -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
View File
@@ -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),
+1 -1
View File
@@ -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
+3 -7
View File
@@ -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
View File
@@ -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| {
+9 -6
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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)]
+10 -6
View File
@@ -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);
}
+2 -3
View File
@@ -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 {
+2 -2
View File
@@ -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
View File
@@ -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) {
+11 -8
View File
@@ -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
View File
@@ -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),
}
}
}
+1 -1
View File
@@ -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);
+4 -4
View File
@@ -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
View File
@@ -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 {
+22 -13
View File
@@ -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.
+12 -9
View File
@@ -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()
+10 -7
View File
@@ -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
View File
@@ -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 {
+20 -10
View File
@@ -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
View File
@@ -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();
+9 -8
View File
@@ -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
View File
@@ -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`
+4
View File
@@ -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
View File
@@ -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]
+41 -34
View File
@@ -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
View File
@@ -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
View File
@@ -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(&copyable, "__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 -6
View File
@@ -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
View File
@@ -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()) {
+9 -10
View File
@@ -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
View File
@@ -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();
+2 -2
View File
@@ -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
View File
@@ -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]
+4 -4
View File
@@ -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)
}
}
+4 -3
View File
@@ -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)?))
}
}