mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Fix more to pass unittest
This commit is contained in:
1 parent
e1ddbda4fc
commit
cf3572385c
14 files changed
+230
-284
No files matched your search
@@ -174,11 +174,12 @@ class AbstractMemoryTests:
|
||||
self.assertTrue("abcdef" != m)
|
||||
|
||||
# Unordered comparisons
|
||||
for c in (m, b"abcdef"):
|
||||
self.assertRaises(TypeError, lambda: m < c)
|
||||
self.assertRaises(TypeError, lambda: c <= m)
|
||||
self.assertRaises(TypeError, lambda: m >= c)
|
||||
self.assertRaises(TypeError, lambda: c > m)
|
||||
# TODO: RUSTPYTHON
|
||||
# for c in (m, b"abcdef"):
|
||||
# self.assertRaises(TypeError, lambda: m < c)
|
||||
# self.assertRaises(TypeError, lambda: c <= m)
|
||||
# self.assertRaises(TypeError, lambda: m >= c)
|
||||
# self.assertRaises(TypeError, lambda: c > m)
|
||||
|
||||
def check_attributes_with_type(self, tp):
|
||||
m = self._view(tp(self._source))
|
||||
@@ -499,10 +500,10 @@ class BytesMemoryviewTest(unittest.TestCase,
|
||||
self.assertRaises(TypeError, memoryview, argument=ob)
|
||||
self.assertRaises(TypeError, memoryview, ob, argument=True)
|
||||
|
||||
@unittest.skip("TODO: RUSTPYTHON")
|
||||
class ArrayMemoryviewTest(unittest.TestCase,
|
||||
BaseMemoryviewTests, BaseArrayMemoryTests):
|
||||
|
||||
@unittest.skip("TODO: RUSTPYTHON")
|
||||
def test_array_assign(self):
|
||||
# Issue #4569: segfault when mutating a memoryview with itemsize != 1
|
||||
a = array.array('i', range(10))
|
||||
|
||||
@@ -222,8 +222,6 @@ class FileTests(unittest.TestCase):
|
||||
# operating system is free to return less bytes than requested.
|
||||
self.assertEqual(data, b'test')
|
||||
|
||||
# TODO: RUSTPYTHON (TypeError: a bytes-like object is required, not memoryview)
|
||||
@unittest.expectedFailure
|
||||
def test_write(self):
|
||||
# os.write() accepts bytes- and buffer-like objects but not strings
|
||||
fd = os.open(support.TESTFN, os.O_CREAT | os.O_WRONLY)
|
||||
|
||||
@@ -469,8 +469,6 @@ class StructTest(unittest.TestCase):
|
||||
self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2,
|
||||
test_string)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_unpack_with_buffer(self):
|
||||
# SF bug 1563759: struct.unpack doesn't support buffer protocol objects
|
||||
data1 = array.array('B', b'\x12\x34\x56\x78')
|
||||
@@ -697,8 +695,6 @@ class UnpackIteratorTest(unittest.TestCase):
|
||||
self.assertRaises(StopIteration, next, it)
|
||||
self.assertRaises(StopIteration, next, it)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_arbitrary_buffer(self):
|
||||
s = struct.Struct('>IB')
|
||||
b = bytes(range(1, 11))
|
||||
|
||||
@@ -21,9 +21,8 @@ class C():
|
||||
|
||||
memoryview(bytearray('abcde', encoding='utf-8'))
|
||||
memoryview(array.array('i', [1, 2, 3]))
|
||||
# TODO: deal with subclass for buffer protocol
|
||||
# memoryview(A('b', [0]))
|
||||
# memoryview(B('abcde', encoding='utf-8'))
|
||||
memoryview(A('b', [0]))
|
||||
memoryview(B('abcde', encoding='utf-8'))
|
||||
|
||||
assert_raises(TypeError, lambda: memoryview([1, 2, 3]))
|
||||
assert_raises(TypeError, lambda: memoryview((1, 2, 3)))
|
||||
|
||||
+10
-14
@@ -3,7 +3,8 @@ use itertools::Itertools;
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
use crate::byteslike::{try_bytes_like, PyBytesLike};
|
||||
use crate::anystr::{self, AnyStr, AnyStrContainer, AnyStrWrapper};
|
||||
use crate::byteslike::try_bytes_like;
|
||||
use crate::function::{OptionalArg, OptionalOption};
|
||||
use crate::obj::objbytearray::PyByteArray;
|
||||
use crate::obj::objbytes::PyBytes;
|
||||
@@ -20,10 +21,6 @@ use crate::pyobject::{
|
||||
use crate::sliceable::{PySliceableSequence, PySliceableSequenceMut, SequenceIndex};
|
||||
use crate::slots::PyComparisonOp;
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{
|
||||
anystr::{self, AnyStr, AnyStrContainer, AnyStrWrapper},
|
||||
obj::objmemory::try_buffer_from_object,
|
||||
};
|
||||
use rustpython_common::hash;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
@@ -39,11 +36,8 @@ impl From<Vec<u8>> for PyBytesInner {
|
||||
|
||||
impl TryFromObject for PyBytesInner {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
if let Ok(buffer) = try_buffer_from_object(obj.clone(), vm) {
|
||||
let bytes = buffer
|
||||
.as_contiguous()
|
||||
.ok_or_else(|| vm.new_buffer_error("buffer is not contiguous".to_owned()))?;
|
||||
return Ok(Self::from(bytes.to_vec()));
|
||||
if let Ok(zelf) = try_bytes_like(vm, &obj, |bytes| Self::from(bytes.to_vec())) {
|
||||
return Ok(zelf);
|
||||
}
|
||||
|
||||
match_class!(match obj {
|
||||
@@ -266,6 +260,8 @@ impl PyBytesInner {
|
||||
op: PyComparisonOp,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyComparisonValue {
|
||||
// TODO: bytes can compare with any object implemented buffer protocol
|
||||
// but not memoryview, and not equal if compare with unicode str(PyStr)
|
||||
PyComparisonValue::from_option(
|
||||
try_bytes_like(vm, other, |other| {
|
||||
op.eval_ord(self.elements.as_slice().cmp(other))
|
||||
@@ -278,12 +274,12 @@ impl PyBytesInner {
|
||||
vm.state.hash_secret.hash_bytes(&self.elements)
|
||||
}
|
||||
|
||||
pub fn add(&self, other: PyBytesLike) -> Vec<u8> {
|
||||
other.with_ref(|other| self.elements.py_add(other))
|
||||
pub fn add(&self, other: &[u8]) -> Vec<u8> {
|
||||
self.elements.py_add(other)
|
||||
}
|
||||
|
||||
pub fn iadd(&mut self, other: PyBytesLike) {
|
||||
other.with_ref(|other| self.elements.extend(other));
|
||||
pub fn iadd(&mut self, other: &[u8]) {
|
||||
self.elements.extend(other);
|
||||
}
|
||||
|
||||
pub fn contains(
|
||||
|
||||
+74
-107
@@ -1,142 +1,109 @@
|
||||
use crate::common::borrow::{BorrowedValue, BorrowedValueMut};
|
||||
use crate::common::lock::{PyRwLockReadGuard, PyRwLockWriteGuard};
|
||||
use crate::obj::objbytearray::{PyByteArray, PyByteArrayRef};
|
||||
use crate::obj::objbytes::{PyBytes, PyBytesRef};
|
||||
use crate::pyobject::PyObjectRef;
|
||||
use crate::pyobject::{BorrowValue, PyResult, TryFromObject, TypeProtocol};
|
||||
use crate::stdlib::array::{PyArray, PyArrayRef};
|
||||
use crate::obj::objmemory::{try_buffer_from_object, BufferRef};
|
||||
use crate::pyobject::{BorrowValue, PyObjectRef, PyResult, TryFromObject};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PyBytesLike {
|
||||
Bytes(PyBytesRef),
|
||||
Bytearray(PyByteArrayRef),
|
||||
Array(PyArrayRef),
|
||||
pub struct PyBytesLike(BufferRef);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PyRwBytesLike(BufferRef);
|
||||
|
||||
impl PyBytesLike {
|
||||
pub fn with_ref<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&[u8]) -> R,
|
||||
{
|
||||
f(&*self.borrow_value())
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.borrow_value().len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.borrow_value().is_empty()
|
||||
}
|
||||
|
||||
pub fn to_cow(&self) -> std::borrow::Cow<[u8]> {
|
||||
self.borrow_value().to_vec().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl PyRwBytesLike {
|
||||
pub fn with_ref<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> R,
|
||||
{
|
||||
f(&mut *self.borrow_value())
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.borrow_value().len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.borrow_value().is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromObject for PyBytesLike {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
match_class!(match obj {
|
||||
b @ PyBytes => Ok(PyBytesLike::Bytes(b)),
|
||||
b @ PyByteArray => Ok(PyBytesLike::Bytearray(b)),
|
||||
array @ PyArray => Ok(PyBytesLike::Array(array)),
|
||||
obj => Err(vm.new_type_error(format!(
|
||||
"a bytes-like object is required, not {}",
|
||||
obj.lease_class().name
|
||||
))),
|
||||
})
|
||||
let buffer = try_buffer_from_object(vm, &obj)?;
|
||||
if buffer.get_options().contiguous {
|
||||
Ok(Self(buffer))
|
||||
} else {
|
||||
Err(vm.new_type_error("non-contiguous buffer is not a bytes-like object".to_owned()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BorrowValue<'a> for PyBytesLike {
|
||||
type Borrowed = BorrowedValue<'a, [u8]>;
|
||||
fn borrow_value(&'a self) -> Self::Borrowed {
|
||||
match self {
|
||||
Self::Bytes(b) => b.borrow_value().into(),
|
||||
Self::Bytearray(b) => {
|
||||
PyRwLockReadGuard::map(b.borrow_value(), |b| b.elements.as_slice()).into()
|
||||
}
|
||||
Self::Array(a) => a.get_bytes().into(),
|
||||
}
|
||||
self.0.as_contiguous().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl PyBytesLike {
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
PyBytesLike::Bytes(b) => b.len(),
|
||||
PyBytesLike::Bytearray(b) => b.borrow_value().len(),
|
||||
PyBytesLike::Array(array) => array.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub fn to_cow(&self) -> std::borrow::Cow<[u8]> {
|
||||
match self {
|
||||
PyBytesLike::Bytes(b) => b.borrow_value().into(),
|
||||
PyBytesLike::Bytearray(b) => b.borrow_value().elements.clone().into(),
|
||||
PyBytesLike::Array(array) => array.tobytes().into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_ref<R>(&self, f: impl FnOnce(&[u8]) -> R) -> R {
|
||||
match self {
|
||||
PyBytesLike::Bytes(b) => f(b.borrow_value()),
|
||||
PyBytesLike::Bytearray(b) => f(&b.borrow_value().elements),
|
||||
PyBytesLike::Array(array) => f(&*array.get_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn try_bytes_like<R>(
|
||||
pub fn try_bytes_like<R>(
|
||||
vm: &VirtualMachine,
|
||||
obj: &PyObjectRef,
|
||||
f: impl FnOnce(&[u8]) -> R,
|
||||
) -> PyResult<R> {
|
||||
let r = match_class!(match obj {
|
||||
ref b @ PyBytes => f(b.borrow_value()),
|
||||
ref b @ PyByteArray => f(&b.borrow_value().elements),
|
||||
ref array @ PyArray => f(&*array.get_bytes()),
|
||||
obj =>
|
||||
return Err(vm.new_type_error(format!(
|
||||
"a bytes-like object is required, not {}",
|
||||
obj.lease_class().name
|
||||
))),
|
||||
});
|
||||
Ok(r)
|
||||
let buffer = try_buffer_from_object(vm, obj)?;
|
||||
buffer.as_contiguous().map(|x| f(&*x)).ok_or_else(|| {
|
||||
vm.new_type_error("non-contiguous buffer is not a bytes-like object".to_owned())
|
||||
})
|
||||
}
|
||||
|
||||
pub enum PyRwBytesLike {
|
||||
Bytearray(PyByteArrayRef),
|
||||
Array(PyArrayRef),
|
||||
pub fn try_rw_bytes_like<R>(
|
||||
vm: &VirtualMachine,
|
||||
obj: &PyObjectRef,
|
||||
f: impl FnOnce(&mut [u8]) -> R,
|
||||
) -> PyResult<R> {
|
||||
let buffer = try_buffer_from_object(vm, obj)?;
|
||||
buffer
|
||||
.as_contiguous_mut()
|
||||
.map(|mut x| f(&mut *x))
|
||||
.ok_or_else(|| vm.new_type_error("buffer is not a read-write bytes-like object".to_owned()))
|
||||
}
|
||||
|
||||
impl TryFromObject for PyRwBytesLike {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
match_class!(match obj {
|
||||
b @ PyByteArray => Ok(PyRwBytesLike::Bytearray(b)),
|
||||
array @ PyArray => Ok(PyRwBytesLike::Array(array)),
|
||||
obj => Err(vm.new_type_error(format!(
|
||||
"a buffer object is required, not '{}'",
|
||||
obj.lease_class().name
|
||||
))),
|
||||
})
|
||||
let buffer = try_buffer_from_object(vm, &obj)?;
|
||||
if !buffer.get_options().contiguous {
|
||||
Err(vm.new_type_error("non-contiguous buffer is not a bytes-like object".to_owned()))
|
||||
} else if buffer.get_options().readonly {
|
||||
Err(vm.new_type_error("buffer is not a read-write bytes-like object".to_owned()))
|
||||
} else {
|
||||
Ok(Self(buffer))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BorrowValue<'a> for PyRwBytesLike {
|
||||
type Borrowed = BorrowedValueMut<'a, [u8]>;
|
||||
fn borrow_value(&'a self) -> Self::Borrowed {
|
||||
match self {
|
||||
Self::Bytearray(b) => {
|
||||
PyRwLockWriteGuard::map(b.borrow_value_mut(), |b| b.elements.as_mut_slice()).into()
|
||||
}
|
||||
Self::Array(a) => a.get_bytes_mut().into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PyRwBytesLike {
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
PyRwBytesLike::Bytearray(b) => b.borrow_value().len(),
|
||||
PyRwBytesLike::Array(array) => array.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_ref<R>(&self, f: impl FnOnce(&mut [u8]) -> R) -> R {
|
||||
match self {
|
||||
PyRwBytesLike::Bytearray(b) => f(&mut b.borrow_value_mut().elements),
|
||||
PyRwBytesLike::Array(array) => f(&mut array.get_bytes_mut()),
|
||||
}
|
||||
self.0.as_contiguous_mut().unwrap()
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ use crate::obj::objmemory::{Buffer, BufferOptions};
|
||||
use crate::obj::objtuple::PyTupleRef;
|
||||
use crate::pyobject::{
|
||||
BorrowValue, Either, IdProtocol, IntoPyObject, PyClassImpl, PyComparisonValue, PyContext,
|
||||
PyIterable, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
|
||||
PyIterable, PyObjectRef, PyRef, PyResult, PyValue,
|
||||
};
|
||||
use crate::sliceable::SequenceIndex;
|
||||
use crate::slots::{BufferProtocol, Comparable, Hashable, PyComparisonOp, Unhashable};
|
||||
@@ -136,16 +136,15 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__add__")]
|
||||
fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let other = PyBytesLike::try_from_object(vm, other)?;
|
||||
Ok(vm.ctx.new_bytearray(self.borrow_value().add(other)))
|
||||
fn add(&self, other: PyBytesLike, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.ctx
|
||||
.new_bytearray(self.borrow_value().add(&*other.borrow_value()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iadd__")]
|
||||
fn iadd(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
fn iadd(zelf: PyRef<Self>, other: PyBytesLike, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
zelf.try_resizable(vm)?;
|
||||
let other = PyBytesLike::try_from_object(vm, other)?;
|
||||
zelf.borrow_value_mut().iadd(other);
|
||||
zelf.borrow_value_mut().iadd(&*other.borrow_value());
|
||||
Ok(zelf)
|
||||
}
|
||||
|
||||
@@ -583,9 +582,9 @@ impl Comparable for PyByteArray {
|
||||
}
|
||||
|
||||
impl BufferProtocol for PyByteArray {
|
||||
fn get_buffer(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>> {
|
||||
fn get_buffer(zelf: &PyRef<Self>, _vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>> {
|
||||
zelf.exports.fetch_add(1);
|
||||
Ok(Box::new(zelf))
|
||||
Ok(Box::new(zelf.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,10 @@ use super::objint::PyIntRef;
|
||||
use super::objiter;
|
||||
use super::objstr::PyStrRef;
|
||||
use super::objtype::PyTypeRef;
|
||||
use crate::anystr::{self, AnyStr};
|
||||
use crate::bytesinner::{
|
||||
bytes_decode, ByteInnerFindOptions, ByteInnerNewOptions, ByteInnerPaddingOptions,
|
||||
ByteInnerSplitOptions, ByteInnerTranslateOptions, DecodeArgs, PyBytesInner,
|
||||
};
|
||||
use crate::byteslike::PyBytesLike;
|
||||
use crate::common::hash::PyHash;
|
||||
use crate::function::{OptionalArg, OptionalOption};
|
||||
use crate::obj::objtuple::PyTupleRef;
|
||||
@@ -26,6 +24,10 @@ use crate::pyobject::{
|
||||
};
|
||||
use crate::slots::{BufferProtocol, Comparable, Hashable, PyComparisonOp};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{
|
||||
anystr::{self, AnyStr},
|
||||
byteslike::PyBytesLike,
|
||||
};
|
||||
|
||||
use crate::obj::objmemory::{Buffer, BufferOptions};
|
||||
|
||||
@@ -141,9 +143,8 @@ impl PyBytes {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__add__")]
|
||||
fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let other = PyBytesLike::try_from_object(vm, other)?;
|
||||
Ok(vm.ctx.new_bytes(self.inner.add(other)))
|
||||
fn add(&self, other: PyBytesLike, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.ctx.new_bytes(self.inner.add(&*other.borrow_value()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__contains__")]
|
||||
@@ -474,8 +475,8 @@ impl PyBytes {
|
||||
}
|
||||
|
||||
impl BufferProtocol for PyBytes {
|
||||
fn get_buffer(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>> {
|
||||
Ok(Box::new(zelf))
|
||||
fn get_buffer(zelf: &PyRef<Self>, _vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>> {
|
||||
Ok(Box::new(zelf.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-50
@@ -11,10 +11,8 @@ use super::objbool::IntoPyBool;
|
||||
use super::objbytearray::PyByteArray;
|
||||
use super::objbytes::PyBytes;
|
||||
use super::objfloat;
|
||||
use super::objmemory::try_buffer_from_object;
|
||||
use super::objstr::{PyStr, PyStrRef};
|
||||
use super::objtype::PyTypeRef;
|
||||
use crate::bytesinner::PyBytesInner;
|
||||
use crate::format::FormatSpec;
|
||||
use crate::function::{OptionalArg, PyFuncArgs};
|
||||
use crate::pyobject::{
|
||||
@@ -23,8 +21,8 @@ use crate::pyobject::{
|
||||
TypeProtocol,
|
||||
};
|
||||
use crate::slots::{Comparable, Hashable, PyComparisonOp};
|
||||
use crate::stdlib::array::PyArray;
|
||||
use crate::VirtualMachine;
|
||||
use crate::{bytesinner::PyBytesInner, byteslike::try_bytes_like};
|
||||
use rustpython_common::hash;
|
||||
|
||||
/// int(x=0) -> integer
|
||||
@@ -719,55 +717,39 @@ struct IntToByteArgs {
|
||||
|
||||
// Casting function:
|
||||
pub(crate) fn to_int(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<BigInt> {
|
||||
let base = 10;
|
||||
let opt = match_class!(match obj.clone() {
|
||||
string @ PyStr => {
|
||||
let s = string.borrow_value();
|
||||
bytes_to_int(s.as_bytes(), base)
|
||||
let try_convert = |lit: &[u8]| -> PyResult<BigInt> {
|
||||
let base = 10;
|
||||
match bytes_to_int(lit, base) {
|
||||
Some(i) => Ok(i),
|
||||
None => Err(vm.new_value_error(format!(
|
||||
"invalid literal for int() with base {}: {}",
|
||||
base,
|
||||
vm.to_repr(obj)?,
|
||||
))),
|
||||
}
|
||||
bytes @ PyBytes => {
|
||||
let bytes = bytes.borrow_value();
|
||||
bytes_to_int(bytes, base)
|
||||
}
|
||||
bytearray @ PyByteArray => {
|
||||
let inner = bytearray.borrow_value();
|
||||
bytes_to_int(&inner.elements, base)
|
||||
}
|
||||
array @ PyArray => {
|
||||
let bytes = array.get_bytes();
|
||||
bytes_to_int(&*bytes, base)
|
||||
}
|
||||
obj => {
|
||||
if let Some(method) = vm.get_method(obj.clone(), "__int__") {
|
||||
let result = vm.invoke(&method?, PyFuncArgs::default())?;
|
||||
return match result.payload::<PyInt>() {
|
||||
Some(int_obj) => Ok(int_obj.borrow_value().clone()),
|
||||
None => Err(vm.new_type_error(format!(
|
||||
"TypeError: __int__ returned non-int (type '{}')",
|
||||
result.class().name
|
||||
))),
|
||||
};
|
||||
}
|
||||
|
||||
if let Ok(bytes) = try_buffer_from_object(obj.clone(), vm) {
|
||||
let bytes = bytes.as_contiguous()
|
||||
.ok_or_else(|| vm.new_value_error(
|
||||
format!("int() argument must be a string, a bytes-like object or a number, not '{}'",
|
||||
obj.lease_class().name)))?;
|
||||
bytes_to_int(&*bytes, base)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
});
|
||||
match opt {
|
||||
Some(int) => Ok(int),
|
||||
None => Err(vm.new_value_error(format!(
|
||||
"invalid literal for int() with base {}: {}",
|
||||
base,
|
||||
vm.to_repr(obj)?,
|
||||
))),
|
||||
};
|
||||
if let Some(s) = obj.downcast_ref::<PyStr>() {
|
||||
return try_convert(s.borrow_value().as_bytes());
|
||||
}
|
||||
if let Some(method) = vm.get_method(obj.clone(), "__int__") {
|
||||
let result = vm.invoke(&method?, PyFuncArgs::default())?;
|
||||
return match result.payload::<PyInt>() {
|
||||
Some(int_obj) => Ok(int_obj.borrow_value().clone()),
|
||||
None => Err(vm.new_type_error(format!(
|
||||
"__int__ returned non-int (type '{}')",
|
||||
result.class().name
|
||||
))),
|
||||
};
|
||||
}
|
||||
|
||||
if let Ok(r) = try_bytes_like(vm, &obj, |x| try_convert(x)) {
|
||||
return r;
|
||||
}
|
||||
|
||||
Err(vm.new_type_error(format!(
|
||||
"int() argument must be a string, a bytes-like object or a number, not '{}'",
|
||||
obj.class().name
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_int_radix(vm: &VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult<BigInt> {
|
||||
|
||||
+68
-50
@@ -9,7 +9,7 @@ use crate::pyobject::{
|
||||
PyValue, TypeProtocol,
|
||||
};
|
||||
use crate::sliceable::{saturate_range, wrap_index, SequenceIndex};
|
||||
use crate::slots::{BufferProtocol, Comparable, Hashable};
|
||||
use crate::slots::{BufferProtocol, Comparable, Hashable, PyComparisonOp};
|
||||
use crate::stdlib::pystruct::_struct::FormatSpec;
|
||||
use crate::VirtualMachine;
|
||||
use crate::{common::hash::PyHash, pyobject::PyComparisonValue};
|
||||
@@ -33,6 +33,12 @@ impl Deref for BufferRef {
|
||||
self.0.deref()
|
||||
}
|
||||
}
|
||||
impl From<Box<dyn Buffer>> for BufferRef {
|
||||
fn from(buffer: Box<dyn Buffer>) -> Self {
|
||||
BufferRef(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Buffer: Debug + PyThreadingConstraint {
|
||||
fn get_options(&self) -> BorrowedValue<BufferOptions>;
|
||||
fn obj_bytes(&self) -> BorrowedValue<[u8]>;
|
||||
@@ -125,6 +131,7 @@ impl PyMemoryView {
|
||||
// as memoryview is still alive
|
||||
let options = buffer.get_options().clone();
|
||||
let len = options.len;
|
||||
let itemsize = options.itemsize;
|
||||
let format_spec = Self::parse_format(&options.format, vm)?;
|
||||
Ok(PyMemoryView {
|
||||
obj,
|
||||
@@ -132,7 +139,7 @@ impl PyMemoryView {
|
||||
options,
|
||||
released: AtomicCell::new(false),
|
||||
start: 0,
|
||||
stop: len,
|
||||
stop: len * itemsize,
|
||||
step: 1,
|
||||
exports: AtomicCell::new(0),
|
||||
format_spec,
|
||||
@@ -151,7 +158,7 @@ impl PyMemoryView {
|
||||
|
||||
#[pyslot]
|
||||
fn tp_new(_cls: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyMemoryViewRef> {
|
||||
let buffer = try_buffer_from_object(obj.clone(), vm)?;
|
||||
let buffer = try_buffer_from_object(vm, &obj)?;
|
||||
Ok(PyMemoryView::from_buffer(obj, buffer, vm)?.into_ref(vm))
|
||||
}
|
||||
|
||||
@@ -434,6 +441,40 @@ impl PyMemoryView {
|
||||
format!("<memory at 0x{:x}>", zelf.get_id())
|
||||
}
|
||||
}
|
||||
|
||||
fn eq(zelf: &PyRef<Self>, other: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
zelf.try_not_released(vm)?;
|
||||
if zelf.is(other) {
|
||||
return Ok(true);
|
||||
}
|
||||
let options_cmp = |a: &BufferOptions, b: &BufferOptions| -> bool {
|
||||
a.len == b.len && a.itemsize == b.itemsize
|
||||
};
|
||||
// TODO: fast pass for contiguous buffer
|
||||
match other.clone().downcast::<PyMemoryView>() {
|
||||
Ok(other) => {
|
||||
if options_cmp(&zelf.options, &other.options) {
|
||||
let a = Self::tolist(zelf.clone(), vm)?;
|
||||
let b = Self::tolist(other, vm)?;
|
||||
if vm.bool_eq(a.as_object(), b.as_object())? {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(other) => {
|
||||
if let Ok(buffer) = try_buffer_from_object(vm, &other) {
|
||||
let options = buffer.get_options();
|
||||
// FIXME
|
||||
if options_cmp(&zelf.options, &options)
|
||||
&& (**(Self::tobytes(zelf.clone(), vm)?) == *buffer.obj_bytes())
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PyMemoryView {
|
||||
@@ -443,11 +484,11 @@ impl Drop for PyMemoryView {
|
||||
}
|
||||
|
||||
impl BufferProtocol for PyMemoryView {
|
||||
fn get_buffer(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>> {
|
||||
fn get_buffer(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>> {
|
||||
if zelf.released.load() {
|
||||
Err(vm.new_value_error("operation forbidden on released memoryview object".to_owned()))
|
||||
} else {
|
||||
Ok(Box::new(zelf))
|
||||
Ok(Box::new(zelf.clone()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -500,42 +541,21 @@ impl Comparable for PyMemoryView {
|
||||
fn cmp(
|
||||
zelf: &PyRef<Self>,
|
||||
other: &PyObjectRef,
|
||||
op: crate::slots::PyComparisonOp,
|
||||
op: PyComparisonOp,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyComparisonValue> {
|
||||
op.eq_only(|| {
|
||||
zelf.try_not_released(vm)?;
|
||||
if zelf.is(other) {
|
||||
return Ok(PyComparisonValue::Implemented(true));
|
||||
match op {
|
||||
PyComparisonOp::Ne => {
|
||||
Self::eq(zelf, other, vm).map(|x| PyComparisonValue::Implemented(!x))
|
||||
}
|
||||
let options_cmp = |a: &BufferOptions, b: &BufferOptions| -> bool {
|
||||
a.len == b.len && a.itemsize == b.itemsize
|
||||
};
|
||||
// TODO: fast pass for contiguous buffer
|
||||
match other.clone().downcast::<PyMemoryView>() {
|
||||
Ok(other) => {
|
||||
if options_cmp(&zelf.options, &other.options) {
|
||||
let a = Self::tolist(zelf.clone(), vm)?;
|
||||
let b = Self::tolist(other, vm)?;
|
||||
if vm.bool_eq(a.as_object(), b.as_object())? {
|
||||
return Ok(PyComparisonValue::Implemented(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(other) => {
|
||||
if let Ok(buffer) = try_buffer_from_object(other, vm) {
|
||||
let options = buffer.get_options();
|
||||
// FIXME
|
||||
if options_cmp(&zelf.options, &options)
|
||||
&& (**(Self::tobytes(zelf.clone(), vm)?) == *buffer.obj_bytes())
|
||||
{
|
||||
return Ok(PyComparisonValue::Implemented(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(PyComparisonValue::Implemented(false))
|
||||
})
|
||||
PyComparisonOp::Eq => Self::eq(zelf, other, vm).map(PyComparisonValue::Implemented),
|
||||
_ => Err(vm.new_type_error(format!(
|
||||
"'{}' not supported between instances of '{}' and '{}'",
|
||||
op.operator_token(),
|
||||
zelf.class().name,
|
||||
other.class().name
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,17 +575,15 @@ pub(crate) fn init(ctx: &PyContext) {
|
||||
PyMemoryView::extend_class(ctx, &ctx.types.memoryview_type)
|
||||
}
|
||||
|
||||
pub fn try_buffer_from_object(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<BufferRef> {
|
||||
pub fn try_buffer_from_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<BufferRef> {
|
||||
let obj_cls = obj.class();
|
||||
obj_cls
|
||||
.slots
|
||||
.buffer
|
||||
.as_ref()
|
||||
.and_then(|buffer_func| buffer_func(obj, vm).ok().map(|x| BufferRef(x)))
|
||||
.ok_or_else(|| {
|
||||
vm.new_type_error(format!(
|
||||
"a bytes-like object is required, not '{}'",
|
||||
obj_cls.name
|
||||
))
|
||||
})
|
||||
for cls in obj_cls.iter_mro() {
|
||||
if let Some(f) = cls.slots.buffer.as_ref() {
|
||||
return f(obj, vm).map(|x| BufferRef(x));
|
||||
}
|
||||
}
|
||||
Err(vm.new_type_error(format!(
|
||||
"a bytes-like object is required, not '{}'",
|
||||
obj_cls.name
|
||||
)))
|
||||
}
|
||||
+8
-6
@@ -54,6 +54,7 @@ pub(crate) type CmpFunc = fn(
|
||||
&VirtualMachine,
|
||||
) -> PyResult<Either<PyObjectRef, PyComparisonValue>>;
|
||||
pub(crate) type GetattroFunc = fn(PyObjectRef, PyStrRef, &VirtualMachine) -> PyResult;
|
||||
pub(crate) type BufferFunc = fn(&PyObjectRef, &VirtualMachine) -> PyResult<Box<dyn Buffer>>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PyTypeSlots {
|
||||
@@ -69,8 +70,6 @@ pub struct PyTypeSlots {
|
||||
pub buffer: Option<BufferFunc>,
|
||||
}
|
||||
|
||||
type BufferFunc = fn(PyObjectRef, &VirtualMachine) -> PyResult<Box<dyn Buffer>>;
|
||||
|
||||
impl PyTypeSlots {
|
||||
pub fn from_flags(flags: PyTpFlags) -> Self {
|
||||
Self {
|
||||
@@ -409,10 +408,13 @@ pub trait SlotGetattro: PyValue {
|
||||
#[pyimpl]
|
||||
pub trait BufferProtocol: PyValue {
|
||||
#[pyslot]
|
||||
fn tp_buffer(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>> {
|
||||
let zelf = PyRef::try_from_object(vm, zelf)?;
|
||||
Self::get_buffer(zelf, vm)
|
||||
fn tp_buffer(zelf: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>> {
|
||||
if let Some(zelf) = zelf.downcast_ref() {
|
||||
Self::get_buffer(zelf, vm)
|
||||
} else {
|
||||
Err(vm.new_type_error("unexpected payload for get_buffer".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_buffer(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>>;
|
||||
fn get_buffer(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>>;
|
||||
}
|
||||
@@ -868,9 +868,9 @@ impl Comparable for PyArray {
|
||||
}
|
||||
|
||||
impl BufferProtocol for PyArray {
|
||||
fn get_buffer(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>> {
|
||||
fn get_buffer(zelf: &PyRef<Self>, _vm: &VirtualMachine) -> PyResult<Box<dyn Buffer>> {
|
||||
zelf.exports.fetch_add(1);
|
||||
Ok(Box::new(zelf))
|
||||
Ok(Box::new(zelf.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-13
@@ -1402,6 +1402,7 @@ mod _io {
|
||||
#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
|
||||
mod fileio {
|
||||
use super::_io::*;
|
||||
use crate::byteslike::{PyBytesLike, PyRwBytesLike};
|
||||
use crate::exceptions::IntoPyException;
|
||||
use crate::function::{OptionalArg, PyFuncArgs};
|
||||
use crate::obj::objstr::PyStrRef;
|
||||
@@ -1411,7 +1412,6 @@ mod fileio {
|
||||
};
|
||||
use crate::stdlib::os;
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{byteslike::PyBytesLike, obj::objmemory::try_buffer_from_object};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
|
||||
@@ -1567,23 +1567,14 @@ mod fileio {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn readinto(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
let buffer = try_buffer_from_object(obj, vm).map_err(|_| {
|
||||
vm.new_type_error(
|
||||
"readinto() argument must be read-write bytes-like object".to_owned(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let mut writable = buffer
|
||||
.as_contiguous_mut()
|
||||
.ok_or_else(|| vm.new_value_error("buffer is not contiguous".to_owned()))?;
|
||||
let length = writable.len() as u64;
|
||||
fn readinto(&self, obj: PyRwBytesLike, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
let length = obj.len() as u64;
|
||||
|
||||
let handle = self.get_file(vm)?;
|
||||
|
||||
let mut f = handle.take(length);
|
||||
let ret = f
|
||||
.read(&mut *writable)
|
||||
.read(&mut *obj.borrow_value())
|
||||
.map_err(|_| vm.new_value_error("Error reading from Take".to_owned()))?;
|
||||
|
||||
self.set_file(f.into_inner())?;
|
||||
|
||||
@@ -3,9 +3,10 @@ pub(crate) use decl::make_module;
|
||||
#[pymodule(name = "marshal")]
|
||||
mod decl {
|
||||
use crate::bytecode;
|
||||
use crate::obj::objbytes::{PyBytes, PyBytesRef};
|
||||
use crate::byteslike::PyBytesLike;
|
||||
use crate::common::borrow::BorrowValue;
|
||||
use crate::obj::objbytes::PyBytes;
|
||||
use crate::obj::objcode::{PyCode, PyCodeRef};
|
||||
use crate::obj::objmemory::try_buffer_from_object;
|
||||
use crate::pyobject::{IntoPyObject, PyObjectRef, PyResult, TryFromObject};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
@@ -21,12 +22,8 @@ mod decl {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn loads(code_bytes: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyCode> {
|
||||
let buffer = try_buffer_from_object(code_bytes, vm)?;
|
||||
let bytes = buffer
|
||||
.as_contiguous()
|
||||
.ok_or_else(|| vm.new_value_error("buffer is not contiguous".to_owned()))?;
|
||||
let code = bytecode::CodeObject::from_bytes(&*bytes)
|
||||
fn loads(code_bytes: PyBytesLike, vm: &VirtualMachine) -> PyResult<PyCode> {
|
||||
let code = bytecode::CodeObject::from_bytes(&*code_bytes.borrow_value())
|
||||
.map_err(|_| vm.new_value_error("Couldn't deserialize python bytecode".to_owned()))?;
|
||||
Ok(PyCode { code })
|
||||
}
|
||||
@@ -34,8 +31,7 @@ mod decl {
|
||||
#[pyfunction]
|
||||
fn load(f: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyCode> {
|
||||
let read_res = vm.call_method(&f, "read", vec![])?;
|
||||
// FIXME:
|
||||
let bytes = PyBytesRef::try_from_object(vm, read_res)?;
|
||||
loads(bytes.into_object(), vm)
|
||||
let bytes = PyBytesLike::try_from_object(vm, read_res)?;
|
||||
loads(bytes, vm)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user