mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Accept __index__ for the remaining int-bound arguments (#8999)
#8828 made bin(), chr() and several other arguments that were bound as PyIntRef go through __index__, but these still downcast to int and reject an object that only defines __index__: the start and end of the str/bytes/bytearray find family, enumerate(start=), itertools.combinations/combinations_with_replacement/batched, _thread.stack_size, resource.getrlimit/setrlimit, pwd.getpwuid, grp.getgrgid, fcntl.fcntl/lockf and mmap.move/madvise. CPython converts all of them with _PyNumber_Index or _PyEval_SliceIndex. Bind them as ArgIndex, as #8828 did for the others. test_mmap.test_madvise and test_mmap_closed_by_int_scenarios now pass, so drop their expectedFailure markers. Assisted-by: Claude Code:claude-opus-5-5
This commit is contained in:
1 parent
a39d6c9676
commit
95686c08e4
13 files changed
+132
-60
No files matched your search
Vendored
-2
@@ -897,7 +897,6 @@ class MmapTests(unittest.TestCase):
|
||||
match = closed_mmap_repr_pat.match(repr(mm))
|
||||
self.assertIsNotNone(match)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
@unittest.skipUnless(hasattr(mmap.mmap, 'madvise'), 'needs madvise')
|
||||
def test_madvise(self):
|
||||
size = 2 * PAGESIZE
|
||||
@@ -1039,7 +1038,6 @@ class MmapTests(unittest.TestCase):
|
||||
self.assertEqual(m1[:data_length], data)
|
||||
self.assertEqual(m2[:data_length], data)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_mmap_closed_by_int_scenarios(self):
|
||||
"""
|
||||
gh-103987: Test that mmap objects raise ValueError
|
||||
|
||||
@@ -8,9 +8,8 @@ mod fcntl {
|
||||
|
||||
use crate::vm::{
|
||||
PyResult, VirtualMachine,
|
||||
builtins::PyIntRef,
|
||||
convert::ToPyException,
|
||||
function::{ArgMemoryBuffer, ArgStrOrBytesLike, Either, OptionalArg},
|
||||
function::{ArgIndex, ArgMemoryBuffer, ArgStrOrBytesLike, Either, OptionalArg},
|
||||
stdlib::_io,
|
||||
};
|
||||
use rustpython_host_env::io::is_interrupted_error;
|
||||
@@ -86,7 +85,7 @@ mod fcntl {
|
||||
#[derive(FromArgs)]
|
||||
struct FcntlArg {
|
||||
#[pyarg(positional, default = 0)]
|
||||
arg: Either<ArgStrOrBytesLike, PyIntRef>,
|
||||
arg: Either<ArgStrOrBytesLike, ArgIndex>,
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
@@ -114,7 +113,7 @@ mod fcntl {
|
||||
)?;
|
||||
return Ok(vm.ctx.new_bytes(buf[..arg_len].to_vec()).into());
|
||||
}
|
||||
Either::B(i) => i.as_u32_mask(),
|
||||
Either::B(i) => i.as_ref().as_u32_mask(),
|
||||
};
|
||||
let ret = retry_on_eintr(
|
||||
vm,
|
||||
@@ -213,9 +212,9 @@ mod fcntl {
|
||||
#[derive(FromArgs)]
|
||||
struct LockfArgs {
|
||||
#[pyarg(positional, default = 0)]
|
||||
len: PyIntRef,
|
||||
len: ArgIndex,
|
||||
#[pyarg(positional, default = 0)]
|
||||
start: PyIntRef,
|
||||
start: ArgIndex,
|
||||
#[pyarg(positional, default)]
|
||||
whence: i32,
|
||||
}
|
||||
@@ -229,8 +228,8 @@ mod fcntl {
|
||||
LockfArgs { len, start, whence }: LockfArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
let start = start.try_to_primitive(vm)?;
|
||||
let len = len.try_to_primitive(vm)?;
|
||||
let start = start.as_ref().try_to_primitive(vm)?;
|
||||
let len = len.as_ref().try_to_primitive(vm)?;
|
||||
// F_LOCK and F_TLOCK differ in exactly this: the first one waits.
|
||||
let ret = retry_on_eintr(
|
||||
vm,
|
||||
|
||||
@@ -5,9 +5,10 @@ pub(crate) use grp::module_def;
|
||||
mod grp {
|
||||
use crate::vm::{
|
||||
PyObjectRef, PyResult, VirtualMachine,
|
||||
builtins::{PyIntRef, PyListRef, PyUtf8StrRef},
|
||||
builtins::{PyListRef, PyUtf8StrRef},
|
||||
convert::{IntoPyException, ToPyObject},
|
||||
exceptions,
|
||||
function::ArgIndex,
|
||||
types::PyStructSequence,
|
||||
};
|
||||
use core::hint::cold_path;
|
||||
@@ -44,12 +45,12 @@ mod grp {
|
||||
#[derive(FromArgs)]
|
||||
struct GetGrGidArgs {
|
||||
#[pyarg(any)]
|
||||
id: PyIntRef,
|
||||
id: ArgIndex,
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn getgrgid(id: GetGrGidArgs, vm: &VirtualMachine) -> PyResult<GroupData> {
|
||||
let gid = id.id;
|
||||
let gid = id.id.into_int_ref();
|
||||
let gr_gid = gid.as_bigint();
|
||||
let gid = host_grp::gid_t::try_from(gr_gid).ok();
|
||||
let group = gid
|
||||
|
||||
@@ -14,7 +14,7 @@ mod mmap {
|
||||
builtins::{PyBytes, PyBytesRef, PyInt, PyIntRef, PyType, PyTypeRef},
|
||||
byte::{bytes_from_object, value_from_object},
|
||||
convert::ToPyException,
|
||||
function::ArgBytesLike,
|
||||
function::{ArgBytesLike, ArgIndex},
|
||||
protocol::{
|
||||
BufferDescriptor, BufferMethods, PyBuffer, PyMappingMethods, PySequenceMethods,
|
||||
},
|
||||
@@ -330,9 +330,9 @@ mod mmap {
|
||||
option: core::ffi::c_int,
|
||||
// None means 0.
|
||||
#[pyarg(positional, default, py_default = "0")]
|
||||
start: Option<PyIntRef>,
|
||||
start: Option<ArgIndex>,
|
||||
#[pyarg(positional, optional)]
|
||||
length: Option<PyIntRef>,
|
||||
length: Option<ArgIndex>,
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(target_os = "redox")))]
|
||||
@@ -345,7 +345,8 @@ mod mmap {
|
||||
let start = self
|
||||
.start
|
||||
.map(|s| {
|
||||
s.try_to_primitive::<usize>(vm)
|
||||
s.as_ref()
|
||||
.try_to_primitive::<usize>(vm)
|
||||
.ok()
|
||||
.filter(|s| *s < len)
|
||||
.ok_or_else(|| vm.new_value_error("madvise start out of bounds"))
|
||||
@@ -355,7 +356,8 @@ mod mmap {
|
||||
let length = self
|
||||
.length
|
||||
.map(|s| {
|
||||
s.try_to_primitive::<usize>(vm)
|
||||
s.as_ref()
|
||||
.try_to_primitive::<usize>(vm)
|
||||
.map_err(|_| vm.new_value_error("madvise length invalid"))
|
||||
})
|
||||
.transpose()?
|
||||
@@ -920,9 +922,9 @@ mod mmap {
|
||||
#[pymethod(name = "move")]
|
||||
fn move_(
|
||||
zelf: &Py<Self>,
|
||||
dest: PyIntRef,
|
||||
src: PyIntRef,
|
||||
count: PyIntRef,
|
||||
dest: ArgIndex,
|
||||
src: ArgIndex,
|
||||
count: ArgIndex,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
fn args(
|
||||
@@ -948,7 +950,7 @@ mod mmap {
|
||||
}
|
||||
|
||||
let size = zelf.__len__();
|
||||
let (dest, src, cnt) = args(&dest, &src, &count, size, vm)
|
||||
let (dest, src, cnt) = args(dest.as_ref(), src.as_ref(), count.as_ref(), size, vm)
|
||||
.ok_or_else(|| vm.new_value_error("source, destination, or count out of range"))?;
|
||||
|
||||
let dest_end = dest + cnt;
|
||||
|
||||
@@ -6,8 +6,9 @@ pub(crate) use resource::module_def;
|
||||
mod resource {
|
||||
use crate::vm::{
|
||||
Py, PyObject, PyObjectRef, PyResult, TryFromBorrowedObject, VirtualMachine,
|
||||
builtins::{PyInt, PyIntRef},
|
||||
builtins::PyInt,
|
||||
convert::{ToPyException, ToPyObject},
|
||||
function::ArgIndex,
|
||||
types::PyStructSequence,
|
||||
};
|
||||
use num_traits::Signed;
|
||||
@@ -185,8 +186,8 @@ mod resource {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn getrlimit(resource: PyIntRef, vm: &VirtualMachine) -> PyResult<Limits> {
|
||||
let resource = py2rlim(&resource, vm)?;
|
||||
fn getrlimit(resource: ArgIndex, vm: &VirtualMachine) -> PyResult<Limits> {
|
||||
let resource = py2rlim(resource.as_ref(), vm)?;
|
||||
|
||||
if resource >= RLIM_NLIMITS as host_resource::rlim_t {
|
||||
return Err(vm.new_value_error("invalid resource specified"));
|
||||
@@ -197,8 +198,8 @@ mod resource {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn setrlimit(resource: PyIntRef, limits: Limits, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let resource = py2rlim(&resource, vm)?;
|
||||
fn setrlimit(resource: ArgIndex, limits: Limits, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let resource = py2rlim(resource.as_ref(), vm)?;
|
||||
|
||||
if resource >= RLIM_NLIMITS as host_resource::rlim_t {
|
||||
return Err(vm.new_value_error("invalid resource specified"));
|
||||
|
||||
@@ -5,9 +5,9 @@ use rustpython_unicode::case;
|
||||
|
||||
use crate::{
|
||||
AsObject, Py, PyObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine,
|
||||
builtins::{PyInt, PyIntRef, PyTuple},
|
||||
builtins::{PyInt, PyTuple},
|
||||
convert::TryFromBorrowedObject,
|
||||
function::PySsize,
|
||||
function::{ArgIndex, PySsize},
|
||||
};
|
||||
|
||||
#[derive(FromArgs)]
|
||||
@@ -41,17 +41,17 @@ pub(crate) struct StartsEndsWithArgs {
|
||||
#[pyarg(positional)]
|
||||
affix: PyObjectRef,
|
||||
#[pyarg(positional, default)]
|
||||
start: Option<PyIntRef>,
|
||||
start: Option<ArgIndex>,
|
||||
#[pyarg(positional, default)]
|
||||
end: Option<PyIntRef>,
|
||||
end: Option<ArgIndex>,
|
||||
}
|
||||
|
||||
impl StartsEndsWithArgs {
|
||||
pub(crate) fn get_value(self, len: usize) -> (PyObjectRef, Option<Range<usize>>) {
|
||||
let range = if self.start.is_some() || self.end.is_some() {
|
||||
Some(adjust_indices(
|
||||
self.start.as_deref(),
|
||||
self.end.as_deref(),
|
||||
self.start.as_ref().map(AsRef::as_ref),
|
||||
self.end.as_ref().map(AsRef::as_ref),
|
||||
len,
|
||||
))
|
||||
} else {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use super::{
|
||||
IterStatus, PositionIterInternal, PyGenericAlias, PyIntRef, PyTupleRef, PyType, PyTypeRef,
|
||||
IterStatus, PositionIterInternal, PyGenericAlias, PyTupleRef, PyType, PyTypeRef,
|
||||
iter::builtins_reversed, locked_rev_next,
|
||||
};
|
||||
use crate::common::lock::{PyMutex, PyRwLock};
|
||||
use crate::{
|
||||
AsObject, Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
|
||||
class::PyClassImpl,
|
||||
function::ArgIndex,
|
||||
protocol::{PyIter, PyIterReturn},
|
||||
raise_if_stop,
|
||||
types::{Constructor, IterNext, Iterable, SelfIter},
|
||||
@@ -56,7 +57,7 @@ pub struct EnumerateArgs {
|
||||
#[pyarg(any)]
|
||||
iterable: PyIter,
|
||||
#[pyarg(any, default = 0)]
|
||||
start: PyIntRef,
|
||||
start: ArgIndex,
|
||||
}
|
||||
|
||||
impl Constructor for PyEnumerate {
|
||||
@@ -67,6 +68,7 @@ impl Constructor for PyEnumerate {
|
||||
Self::Args { iterable, start }: Self::Args,
|
||||
_vm: &VirtualMachine,
|
||||
) -> PyResult<Self> {
|
||||
let start = start.into_int_ref();
|
||||
let counter = match start.as_bigint().to_usize() {
|
||||
Some(n) => Counter::Small(n),
|
||||
None => Counter::Big(start.as_bigint().clone()),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
PositionIterInternal, PyBytesRef, PyDict, PyList, PyTuple, PyTupleRef, PyType, PyTypeRef,
|
||||
int::{PyInt, PyIntRef},
|
||||
int::PyInt,
|
||||
iter::{IterStatus, builtins_iter},
|
||||
};
|
||||
use crate::{
|
||||
@@ -17,7 +17,7 @@ use crate::{
|
||||
},
|
||||
convert::{ToPyException, ToPyObject, ToPyResult},
|
||||
format::{format, format_map},
|
||||
function::{ArgIterable, FuncArgs, OptionalArg, PyComparisonValue, PySsize},
|
||||
function::{ArgIndex, ArgIterable, FuncArgs, OptionalArg, PyComparisonValue, PySsize},
|
||||
intern::PyInterned,
|
||||
object::{MaybeTraverse, Traverse, TraverseFn},
|
||||
protocol::{
|
||||
@@ -1871,14 +1871,18 @@ pub(crate) struct FindArgs {
|
||||
#[pyarg(positional)]
|
||||
sub: PyStrRef,
|
||||
#[pyarg(positional, default)]
|
||||
start: Option<PyIntRef>,
|
||||
start: Option<ArgIndex>,
|
||||
#[pyarg(positional, default)]
|
||||
end: Option<PyIntRef>,
|
||||
end: Option<ArgIndex>,
|
||||
}
|
||||
|
||||
impl FindArgs {
|
||||
fn get_value(self, len: usize) -> (PyStrRef, core::ops::Range<usize>) {
|
||||
let range = adjust_indices(self.start.as_deref(), self.end.as_deref(), len);
|
||||
let range = adjust_indices(
|
||||
self.start.as_ref().map(AsRef::as_ref),
|
||||
self.end.as_ref().map(AsRef::as_ref),
|
||||
len,
|
||||
);
|
||||
(self.sub, range)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
cformat::cformat_bytes,
|
||||
common::wtf8::is_py_ascii_whitespace,
|
||||
common::{borrow::BorrowedValue, hash},
|
||||
function::{ArgIterable, Either, OptionalArg, PyComparisonValue},
|
||||
function::{ArgIndex, ArgIterable, Either, OptionalArg, PyComparisonValue},
|
||||
literal::escape::Escape,
|
||||
protocol::{BufferFlags, PyBuffer},
|
||||
sequence::{SequenceExt, SequenceMutExt},
|
||||
@@ -315,9 +315,9 @@ pub struct ByteInnerFindOptions {
|
||||
#[pyarg(positional)]
|
||||
sub: ByteInnerSub,
|
||||
#[pyarg(positional, default)]
|
||||
start: Option<PyIntRef>,
|
||||
start: Option<ArgIndex>,
|
||||
#[pyarg(positional, default)]
|
||||
end: Option<PyIntRef>,
|
||||
end: Option<ArgIndex>,
|
||||
}
|
||||
|
||||
impl ByteInnerFindOptions {
|
||||
@@ -327,7 +327,11 @@ impl ByteInnerFindOptions {
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<(Vec<u8>, core::ops::Range<usize>)> {
|
||||
let sub = self.sub.into_vec(vm)?;
|
||||
let range = anystr::adjust_indices(self.start.as_deref(), self.end.as_deref(), len);
|
||||
let range = anystr::adjust_indices(
|
||||
self.start.as_ref().map(AsRef::as_ref),
|
||||
self.end.as_ref().map(AsRef::as_ref),
|
||||
len,
|
||||
);
|
||||
Ok((sub, range))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ pub(crate) mod _thread {
|
||||
convert::ToPyException,
|
||||
frame::FrameObjectRef,
|
||||
function::{
|
||||
ArgCallable, ArgumentError, DefaultRepr, FromArgs, FuncArgs, KwArgs, NameExcInfo,
|
||||
OptionalArg, Param, ParamKind, PosArgs, PySetterValue, TimeoutSeconds,
|
||||
ArgCallable, ArgIndex, ArgumentError, DefaultRepr, FromArgs, FuncArgs, KwArgs,
|
||||
NameExcInfo, OptionalArg, Param, ParamKind, PosArgs, PySetterValue, TimeoutSeconds,
|
||||
},
|
||||
object::{Traverse, TraverseFn},
|
||||
types::{Constructor, GetAttr, PyStructSequence, Representable, SetAttr},
|
||||
@@ -847,7 +847,7 @@ pub(crate) mod _thread {
|
||||
#[derive(FromArgs)]
|
||||
struct StackSizeArgs {
|
||||
#[pyarg(positional, default = 0)]
|
||||
size: PyIntRef,
|
||||
size: ArgIndex,
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
@@ -855,7 +855,7 @@ pub(crate) mod _thread {
|
||||
const MIN_SIZE: usize = PY_OS_MIN_STACK_SIZE + SYSTEM_PAGE_SIZE;
|
||||
let StackSizeArgs { size } = args;
|
||||
|
||||
let Ok(size) = size.try_to_primitive(vm) else {
|
||||
let Ok(size) = size.as_ref().try_to_primitive(vm) else {
|
||||
return Err(vm.new_value_error(format!("size must be at least {MIN_SIZE} bytes")));
|
||||
};
|
||||
|
||||
|
||||
@@ -5,13 +5,11 @@ mod decl {
|
||||
use crate::{
|
||||
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, PyWeakRef, TryFromObject,
|
||||
VirtualMachine,
|
||||
builtins::{
|
||||
PyGenericAlias, PyInt, PyIntRef, PyList, PyTuple, PyTupleRef, PyType, PyTypeRef, int,
|
||||
},
|
||||
builtins::{PyGenericAlias, PyInt, PyList, PyTuple, PyTupleRef, PyType, PyTypeRef, int},
|
||||
class::PyClassDef,
|
||||
common::lock::{PyMutex, PyRwLock, PyRwLockWriteGuard},
|
||||
convert::ToPyObject,
|
||||
function::{FuncArgs, NameIterables, PosArgs},
|
||||
function::{ArgIndex, FuncArgs, NameIterables, PosArgs},
|
||||
protocol::{PyIter, PyIterReturn, PyNumber},
|
||||
raise_if_stop,
|
||||
stdlib::sys,
|
||||
@@ -1329,7 +1327,7 @@ mod decl {
|
||||
#[pyarg(any)]
|
||||
iterable: PyObjectRef,
|
||||
#[pyarg(any)]
|
||||
r: PyIntRef,
|
||||
r: ArgIndex,
|
||||
}
|
||||
|
||||
impl Constructor for PyItertoolsCombinations {
|
||||
@@ -1342,6 +1340,7 @@ mod decl {
|
||||
) -> PyResult<Self> {
|
||||
let pool: Vec<_> = iterable.try_to_value(vm)?;
|
||||
|
||||
let r = r.into_int_ref();
|
||||
let r = r.as_bigint();
|
||||
if r.is_negative() {
|
||||
return Err(vm.new_value_error("r must be non-negative"));
|
||||
@@ -1454,6 +1453,7 @@ mod decl {
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Self> {
|
||||
let pool: Vec<_> = iterable.try_to_value(vm)?;
|
||||
let r = r.into_int_ref();
|
||||
let r = r.as_bigint();
|
||||
if r.is_negative() {
|
||||
return Err(vm.new_value_error("r must be non-negative"));
|
||||
@@ -1800,7 +1800,7 @@ mod decl {
|
||||
#[pyarg(any)]
|
||||
iterable: PyObjectRef,
|
||||
#[pyarg(any)]
|
||||
n: PyIntRef,
|
||||
n: ArgIndex,
|
||||
#[pyarg(named, default)]
|
||||
strict: bool,
|
||||
}
|
||||
@@ -1817,6 +1817,7 @@ mod decl {
|
||||
}: Self::Args,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Self> {
|
||||
let n = n.into_int_ref();
|
||||
let n = n.as_bigint();
|
||||
if n.lt(&BigInt::one()) {
|
||||
return Err(vm.new_value_error("n must be at least one"));
|
||||
|
||||
@@ -5,11 +5,8 @@ pub(crate) use pwd::module_def;
|
||||
#[pymodule]
|
||||
mod pwd {
|
||||
use crate::{
|
||||
PyResult, VirtualMachine,
|
||||
builtins::{PyIntRef, PyUtf8StrRef},
|
||||
convert::IntoPyException,
|
||||
exceptions,
|
||||
types::PyStructSequence,
|
||||
PyResult, VirtualMachine, builtins::PyUtf8StrRef, convert::IntoPyException, exceptions,
|
||||
function::ArgIndex, types::PyStructSequence,
|
||||
};
|
||||
use core::hint::cold_path;
|
||||
use rustpython_host_env::pwd as host_pwd;
|
||||
@@ -68,7 +65,8 @@ mod pwd {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn getpwuid(uidobj: PyIntRef, vm: &VirtualMachine) -> PyResult<PasswdData> {
|
||||
fn getpwuid(uidobj: ArgIndex, vm: &VirtualMachine) -> PyResult<PasswdData> {
|
||||
let uidobj = uidobj.into_int_ref();
|
||||
let uid_t = libc::uid_t::try_from(uidobj.as_bigint()).ok();
|
||||
let user = uid_t
|
||||
.map(host_pwd::getpwuid)
|
||||
|
||||
@@ -312,3 +312,65 @@ class HintIndex:
|
||||
|
||||
with assert_raises(TypeError):
|
||||
operator.length_hint(HintIndex())
|
||||
|
||||
|
||||
# Arguments bound as `int` objects accept `__index__` as well.
|
||||
assert "abcabc".find("a", Index(1)) == 3
|
||||
assert "abcabc".rfind("a", 0, Index(3)) == 0
|
||||
assert "abcabc".index("c", Index(3)) == 5
|
||||
assert "abcabc".rindex("a", Index(1), Index(4)) == 3
|
||||
assert "aaaaaa".count("a", Index(2), Index(-1)) == 3
|
||||
assert "abcdef".startswith("d", Index(3))
|
||||
assert "abcdef".endswith("c", 0, Index(3))
|
||||
assert b"abcabc".find(b"a", Index(1)) == 3
|
||||
assert b"abcabc".count(b"b", Index(2)) == 1
|
||||
assert b"abcdef".startswith(b"d", Index(3))
|
||||
assert bytearray(b"abcabc").rindex(b"a", 0, Index(3)) == 0
|
||||
assert bytearray(b"abcdef").endswith(b"c", 0, Index(3))
|
||||
|
||||
assert list(enumerate("ab", Index(3))) == [(3, "a"), (4, "b")]
|
||||
assert list(enumerate("ab", start=Index(3))) == [(3, "a"), (4, "b")]
|
||||
|
||||
import itertools
|
||||
|
||||
assert list(itertools.combinations("abc", Index(2))) == [
|
||||
("a", "b"),
|
||||
("a", "c"),
|
||||
("b", "c"),
|
||||
]
|
||||
assert list(itertools.combinations_with_replacement("ab", Index(2))) == [
|
||||
("a", "a"),
|
||||
("a", "b"),
|
||||
("b", "b"),
|
||||
]
|
||||
assert list(itertools.batched("abcde", Index(2))) == [("a", "b"), ("c", "d"), ("e",)]
|
||||
|
||||
assert _thread.stack_size(Index(0)) == 0
|
||||
|
||||
import mmap
|
||||
|
||||
mapped = mmap.mmap(-1, 6)
|
||||
mapped.write(b"abcdef")
|
||||
mapped.move(Index(0), Index(3), Index(3))
|
||||
assert mapped[:] == b"defdef"
|
||||
if hasattr(mapped, "madvise"):
|
||||
mapped.madvise(mmap.MADV_NORMAL, Index(0), Index(6))
|
||||
|
||||
if sys.platform != "win32":
|
||||
import fcntl
|
||||
import grp
|
||||
import pwd
|
||||
import resource
|
||||
import tempfile
|
||||
|
||||
assert pwd.getpwuid(Index(0)).pw_uid == 0
|
||||
assert grp.getgrgid(Index(0)).gr_gid == 0
|
||||
|
||||
nofile = resource.getrlimit(resource.RLIMIT_NOFILE)
|
||||
assert resource.getrlimit(Index(resource.RLIMIT_NOFILE)) == nofile
|
||||
resource.setrlimit(Index(resource.RLIMIT_NOFILE), nofile)
|
||||
|
||||
with tempfile.TemporaryFile() as f:
|
||||
assert fcntl.fcntl(f, fcntl.F_SETFD, Index(fcntl.FD_CLOEXEC)) == 0
|
||||
assert fcntl.fcntl(f, fcntl.F_GETFD) == fcntl.FD_CLOEXEC
|
||||
fcntl.lockf(f, fcntl.LOCK_SH | fcntl.LOCK_NB, Index(0), Index(0))
|
||||
Reference in new issue
Block a user