mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Merge branch 'master' into dev3
This commit is contained in:
6 files changed
+203
-26
No files matched your search
@@ -25,7 +25,10 @@ class ArraySubclassWithKwargs(array.array):
|
||||
def __init__(self, typecode, newarg=None):
|
||||
array.array.__init__(self)
|
||||
|
||||
typecodes = 'ubBhHiIlLfdqQ'
|
||||
# TODO: RUSTPYTHON
|
||||
# We did not support typecode u for unicode yet
|
||||
# typecodes = 'ubBhHiIlLfdqQ'
|
||||
typecodes = 'bBhHiIlLfdqQ'
|
||||
|
||||
class MiscTest(unittest.TestCase):
|
||||
|
||||
@@ -497,8 +500,6 @@ class BaseTest:
|
||||
b = array.array(self.typecode, a)
|
||||
self.assertEqual(a, b)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_repr(self):
|
||||
a = array.array(self.typecode, 2*self.example)
|
||||
self.assertEqual(a, eval(repr(a), {"array": array.array}))
|
||||
@@ -801,8 +802,6 @@ class BaseTest:
|
||||
self.assertEqual(list(a[start:stop:step]),
|
||||
list(a)[start:stop:step])
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_setslice(self):
|
||||
a = array.array(self.typecode, self.example)
|
||||
a[:1] = a
|
||||
@@ -1235,8 +1234,6 @@ class NumberTest(BaseTest):
|
||||
a = array.array(self.typecode, range(10))
|
||||
del a[9::1<<333]
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_assignment(self):
|
||||
a = array.array(self.typecode, range(10))
|
||||
a[::2] = array.array(self.typecode, [42]*5)
|
||||
|
||||
@@ -32,3 +32,17 @@ def test_float_with_integer_input():
|
||||
assert f == array("f", [-2, 0, 2, 3, 4])
|
||||
|
||||
test_float_with_integer_input()
|
||||
|
||||
# slice assignment step overflow behaviour test
|
||||
T = 'I'
|
||||
a = array(T, range(10))
|
||||
b = array(T, [100])
|
||||
a[::9999999999] = b
|
||||
assert a == array(T, [100, 1, 2, 3, 4, 5, 6, 7, 8, 9])
|
||||
a[::-9999999999] = b
|
||||
assert a == array(T, [100, 1, 2, 3, 4, 5, 6, 7, 8, 100])
|
||||
c = array(T)
|
||||
a[0:0:9999999999] = c
|
||||
assert a == array(T, [100, 1, 2, 3, 4, 5, 6, 7, 8, 100])
|
||||
a[0:0:-9999999999] = c
|
||||
assert a == array(T, [100, 1, 2, 3, 4, 5, 6, 7, 8, 100])
|
||||
@@ -252,13 +252,11 @@ impl PyBytesInner {
|
||||
let mut res = String::with_capacity(self.elements.len());
|
||||
for i in self.elements.iter() {
|
||||
match i {
|
||||
0..=8 => res.push_str(&format!("\\x0{}", i)),
|
||||
9 => res.push_str("\\t"),
|
||||
10 => res.push_str("\\n"),
|
||||
11 => res.push_str(&format!("\\x0{:x}", i)),
|
||||
13 => res.push_str("\\r"),
|
||||
32..=126 => res.push(*(i) as char),
|
||||
_ => res.push_str(&format!("\\x{:x}", i)),
|
||||
_ => res.push_str(&format!("\\x{:02x}", i)),
|
||||
}
|
||||
}
|
||||
res
|
||||
|
||||
+158
-16
@@ -5,18 +5,21 @@ use crate::common::cell::{
|
||||
use crate::function::OptionalArg;
|
||||
use crate::obj::objbytes::PyBytesRef;
|
||||
use crate::obj::objfloat::try_float;
|
||||
use crate::obj::objsequence::PySliceableSequence;
|
||||
use crate::obj::objsequence::{get_slice_range, PySliceableSequence};
|
||||
use crate::obj::objslice::PySliceRef;
|
||||
use crate::obj::objstr::PyStringRef;
|
||||
use crate::obj::objtype::PyClassRef;
|
||||
use crate::obj::{objbool, objiter};
|
||||
use crate::pyobject::{
|
||||
BorrowValue, Either, IntoPyObject, PyArithmaticValue, PyClassImpl, PyComparisonValue,
|
||||
PyIterable, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol,
|
||||
BorrowValue, Either, IdProtocol, IntoPyObject, PyArithmaticValue, PyClassImpl,
|
||||
PyComparisonValue, PyIterable, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
|
||||
TypeProtocol,
|
||||
};
|
||||
use crate::VirtualMachine;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use itertools::Itertools;
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
use std::fmt;
|
||||
|
||||
struct ArrayTypeSpecifierError {
|
||||
@@ -34,7 +37,7 @@ impl fmt::Display for ArrayTypeSpecifierError {
|
||||
|
||||
macro_rules! def_array_enum {
|
||||
($(($n:ident, $t:ident, $c:literal)),*$(,)?) => {
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
enum ArrayContentType {
|
||||
$($n(Vec<$t>),)*
|
||||
}
|
||||
@@ -230,18 +233,128 @@ macro_rules! def_array_enum {
|
||||
Either::B(slice) => self.getitem_by_slice(slice, vm),
|
||||
}
|
||||
}
|
||||
|
||||
fn setitem_by_slice(&mut self, slice: PySliceRef, items: &ArrayContentType, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let start = slice.start_index(vm)?;
|
||||
let stop = slice.stop_index(vm)?;
|
||||
let step = slice.step_index(vm)?.unwrap_or_else(BigInt::one);
|
||||
|
||||
fn setitem(&mut self, needle: Either<isize, PySliceRef>, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
match needle {
|
||||
Either::A(i) => {
|
||||
let i = self.idx(i, "array assignment", vm)?;
|
||||
match self {
|
||||
$(ArrayContentType::$n(v) => { v[i] = $t::try_into_from_object(vm, value)? },)*
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Either::B(_slice) => Err(vm.new_not_implemented_error("array slice is not implemented".to_owned())),
|
||||
if step.is_zero() {
|
||||
return Err(vm.new_value_error("slice step cannot be zero".to_owned()));
|
||||
}
|
||||
|
||||
match self {
|
||||
$(ArrayContentType::$n(elements) => if let ArrayContentType::$n(items) = items {
|
||||
if step == BigInt::one() {
|
||||
let range = get_slice_range(&start, &stop, elements.len());
|
||||
let range = if range.end < range.start {
|
||||
range.start..range.start
|
||||
} else {
|
||||
range
|
||||
};
|
||||
elements.splice(range, items.iter().cloned());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let (start, stop, step, is_negative_step) = if step.is_negative() {
|
||||
(
|
||||
stop.map(|x| if x == -BigInt::one() {
|
||||
elements.len() + BigInt::one()
|
||||
} else {
|
||||
x + 1
|
||||
}),
|
||||
start.map(|x| if x == -BigInt::one() {
|
||||
BigInt::from(elements.len())
|
||||
} else {
|
||||
x + 1
|
||||
}),
|
||||
-step,
|
||||
true
|
||||
)
|
||||
} else {
|
||||
(start, stop, step, false)
|
||||
};
|
||||
|
||||
let range = get_slice_range(&start, &stop, elements.len());
|
||||
let range = if range.end < range.start {
|
||||
range.start..range.start
|
||||
} else {
|
||||
range
|
||||
};
|
||||
|
||||
// step is not negative here
|
||||
if let Some(step) = step.to_usize() {
|
||||
let slicelen = if range.end > range.start {
|
||||
(range.end - range.start - 1) / step + 1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
if slicelen == items.len() {
|
||||
if is_negative_step {
|
||||
for (i, &item) in range.rev().step_by(step).zip(items) {
|
||||
elements[i] = item;
|
||||
}
|
||||
} else {
|
||||
for (i, &item) in range.step_by(step).zip(items) {
|
||||
elements[i] = item;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(vm.new_value_error(format!(
|
||||
"attempt to assign sequence of size {} to extended slice of size {}",
|
||||
items.len(), slicelen
|
||||
)))
|
||||
}
|
||||
} else {
|
||||
// edge case, step is too big for usize
|
||||
// same behaviour as CPython
|
||||
let slicelen = if range.start < range.end { 1 } else { 0 };
|
||||
if match items.len() {
|
||||
0 => slicelen == 0,
|
||||
1 => {
|
||||
elements[
|
||||
if is_negative_step { range.end - 1 } else { range.start }
|
||||
] = items[0];
|
||||
true
|
||||
},
|
||||
_ => false,
|
||||
} {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(vm.new_value_error(format!(
|
||||
"attempt to assign sequence of size {} to extended slice of size {}",
|
||||
items.len(), slicelen
|
||||
)))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(vm.new_type_error("bad argument type for built-in operation".to_owned()))
|
||||
},)*
|
||||
}
|
||||
}
|
||||
|
||||
fn setitem_by_idx(&mut self, i: isize, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let i = self.idx(i, "array assignment", vm)?;
|
||||
match self {
|
||||
$(ArrayContentType::$n(v) => { v[i] = TryFromObject::try_from_object(vm, value)? },)*
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn repr(&self, _vm: &VirtualMachine) -> PyResult<String> {
|
||||
// we don't need ReprGuard here
|
||||
let s = match self {
|
||||
$(ArrayContentType::$n(v) => {
|
||||
if v.is_empty() {
|
||||
format!("array('{}')", $c)
|
||||
} else {
|
||||
format!("array('{}', [{}])", $c, v.iter().format(", "))
|
||||
}
|
||||
})*
|
||||
};
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn iter<'a>(&'a self, vm: &'a VirtualMachine) -> impl Iterator<Item = PyObjectRef> + 'a {
|
||||
@@ -479,12 +592,41 @@ impl PyArray {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn setitem(
|
||||
&self,
|
||||
zelf: PyRef<Self>,
|
||||
needle: Either<isize, PySliceRef>,
|
||||
obj: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
self.borrow_value_mut().setitem(needle, obj, vm)
|
||||
match needle {
|
||||
Either::A(i) => zelf.borrow_value_mut().setitem_by_idx(i, obj, vm),
|
||||
Either::B(slice) => {
|
||||
let cloned;
|
||||
let guard;
|
||||
let items = if zelf.is(&obj) {
|
||||
cloned = zelf.borrow_value().clone();
|
||||
&cloned
|
||||
} else {
|
||||
match obj.payload::<PyArray>() {
|
||||
Some(array) => {
|
||||
guard = array.borrow_value();
|
||||
&*guard
|
||||
}
|
||||
None => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"can only assign array (not \"{}\") to array slice",
|
||||
obj.class().name
|
||||
)));
|
||||
}
|
||||
}
|
||||
};
|
||||
zelf.borrow_value_mut().setitem_by_slice(slice, items, vm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
|
||||
zelf.borrow_value().repr(vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__eq__")]
|
||||
|
||||
@@ -719,6 +719,14 @@ mod _os {
|
||||
std::process::exit(code)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn abort() {
|
||||
extern "C" {
|
||||
fn abort();
|
||||
}
|
||||
unsafe { abort() }
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn urandom(size: usize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
|
||||
let mut buf = vec![0u8; size];
|
||||
|
||||
@@ -579,6 +579,23 @@ fn socket_gethostbyaddr(
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn socket_gethostbyname(name: PyStringRef, vm: &VirtualMachine) -> PyResult<String> {
|
||||
match socket_gethostbyaddr(name, vm) {
|
||||
Ok((_, _, hosts)) => {
|
||||
let lst = vm.extract_elements::<PyStringRef>(&hosts)?;
|
||||
Ok(lst.get(0).unwrap().to_string())
|
||||
}
|
||||
Err(_) => {
|
||||
let error_type = vm.class("_socket", "gaierror");
|
||||
Err(vm.new_exception_msg(
|
||||
error_type,
|
||||
"nodename nor servname provided, or not known".to_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_addr<T, I>(vm: &VirtualMachine, addr: T) -> PyResult<socket2::SockAddr>
|
||||
where
|
||||
T: ToSocketAddrs<Iter = I>,
|
||||
@@ -707,6 +724,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
extend_module!(vm, module, {
|
||||
"getaddrinfo" => ctx.new_function(socket_getaddrinfo),
|
||||
"gethostbyaddr" => ctx.new_function(socket_gethostbyaddr),
|
||||
"gethostbyname" => ctx.new_function(socket_gethostbyname),
|
||||
});
|
||||
|
||||
extend_module_platform_specific(vm, &module);
|
||||
|
||||
Reference in new issue
Block a user