Skip to content

Commit a115005

Browse files
committed
Fix find/index/count not to raise error for bigint start/end arguments
1 parent 8ca22df commit a115005

File tree

5 files changed

+57
-67
lines changed

5 files changed

+57
-67
lines changed

Lib/test/string_tests.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,6 @@ def test_count(self):
156156
self.assertEqual(rem, 0, '%s != 0 for %s' % (rem, i))
157157
self.assertEqual(r1, r2, '%s != %s for %s' % (r1, r2, i))
158158

159-
# TODO: RUSTPYTHON
160-
@unittest.expectedFailure
161159
def test_find(self):
162160
self.checkequal(0, 'abcdefghiabc', 'find', 'abc')
163161
self.checkequal(9, 'abcdefghiabc', 'find', 'abc', 1)
@@ -215,8 +213,6 @@ def test_find(self):
215213
if loc != -1:
216214
self.assertEqual(i[loc:loc+len(j)], j)
217215

218-
# TODO: RUSTPYTHON
219-
@unittest.expectedFailure
220216
def test_rfind(self):
221217
self.checkequal(9, 'abcdefghiabc', 'rfind', 'abc')
222218
self.checkequal(12, 'abcdefghiabc', 'rfind', '')

Lib/test/test_unicode.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,7 @@ def test_count(self):
199199
self.checkequal(0, 'a' * 10, 'count', 'a\U00100304')
200200
self.checkequal(0, '\u0102' * 10, 'count', '\u0102\U00100304')
201201

202-
# TODO: RUSTPYTHON
203-
@unittest.expectedFailure
202+
@unittest.skip("TODO: RUSTPYTHON")
204203
def test_find(self):
205204
string_tests.CommonTest.test_find(self)
206205
# test implementation details of the memchr fast path
@@ -232,8 +231,7 @@ def test_find(self):
232231
self.checkequal(-1, 'a' * 100, 'find', 'a\U00100304')
233232
self.checkequal(-1, '\u0102' * 100, 'find', '\u0102\U00100304')
234233

235-
# TODO: RUSTPYTHON
236-
@unittest.expectedFailure
234+
@unittest.skip("TODO: RUSTPYTHON")
237235
def test_rfind(self):
238236
string_tests.CommonTest.test_rfind(self)
239237
# test implementation details of the memrchr fast path

vm/src/obj/objbyteinner.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,10 @@ impl ByteInnerNewOptions {
154154
pub struct ByteInnerFindOptions {
155155
#[pyarg(positional_only, optional = false)]
156156
sub: Either<PyByteInner, PyIntRef>,
157-
#[pyarg(positional_only, optional = true)]
158-
start: OptionalArg<Option<isize>>,
159-
#[pyarg(positional_only, optional = true)]
160-
end: OptionalArg<Option<isize>>,
157+
#[pyarg(positional_only, default = "None")]
158+
start: Option<PyIntRef>,
159+
#[pyarg(positional_only, default = "None")]
160+
end: Option<PyIntRef>,
161161
}
162162

163163
impl ByteInnerFindOptions {

vm/src/obj/objstr.rs

Lines changed: 30 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -813,63 +813,35 @@ impl PyString {
813813
}
814814

815815
#[inline]
816-
fn _find<F>(
817-
&self,
818-
sub: PyStringRef,
819-
start: OptionalArg<Option<isize>>,
820-
end: OptionalArg<Option<isize>>,
821-
find: F,
822-
) -> Option<usize>
816+
fn _find<F>(&self, args: FindArgs, find: F) -> Option<usize>
823817
where
824818
F: Fn(&str, &str) -> Option<usize>,
825819
{
826-
let range = adjust_indices(start, end, self.value.len());
820+
let (sub, range) = args.get_value(self.len());
827821
self.value.py_find(&sub.value, range, find)
828822
}
829823

830824
#[pymethod]
831-
fn find(
832-
&self,
833-
sub: PyStringRef,
834-
start: OptionalArg<Option<isize>>,
835-
end: OptionalArg<Option<isize>>,
836-
) -> isize {
837-
self._find(sub, start, end, |r, s| r.find(s))
825+
fn find(&self, args: FindArgs) -> isize {
826+
self._find(args, |r, s| r.find(s))
838827
.map_or(-1, |v| v as isize)
839828
}
840829

841830
#[pymethod]
842-
fn rfind(
843-
&self,
844-
sub: PyStringRef,
845-
start: OptionalArg<Option<isize>>,
846-
end: OptionalArg<Option<isize>>,
847-
) -> isize {
848-
self._find(sub, start, end, |r, s| r.rfind(s))
831+
fn rfind(&self, args: FindArgs) -> isize {
832+
self._find(args, |r, s| r.rfind(s))
849833
.map_or(-1, |v| v as isize)
850834
}
851835

852836
#[pymethod]
853-
fn index(
854-
&self,
855-
sub: PyStringRef,
856-
start: OptionalArg<Option<isize>>,
857-
end: OptionalArg<Option<isize>>,
858-
vm: &VirtualMachine,
859-
) -> PyResult<usize> {
860-
self._find(sub, start, end, |r, s| r.find(s))
837+
fn index(&self, args: FindArgs, vm: &VirtualMachine) -> PyResult<usize> {
838+
self._find(args, |r, s| r.find(s))
861839
.ok_or_else(|| vm.new_value_error("substring not found".to_owned()))
862840
}
863841

864842
#[pymethod]
865-
fn rindex(
866-
&self,
867-
sub: PyStringRef,
868-
start: OptionalArg<Option<isize>>,
869-
end: OptionalArg<Option<isize>>,
870-
vm: &VirtualMachine,
871-
) -> PyResult<usize> {
872-
self._find(sub, start, end, |r, s| r.rfind(s))
843+
fn rindex(&self, args: FindArgs, vm: &VirtualMachine) -> PyResult<usize> {
844+
self._find(args, |r, s| r.rfind(s))
873845
.ok_or_else(|| vm.new_value_error("substring not found".to_owned()))
874846
}
875847

@@ -944,15 +916,10 @@ impl PyString {
944916
}
945917

946918
#[pymethod]
947-
fn count(
948-
&self,
949-
sub: PyStringRef,
950-
start: OptionalArg<Option<isize>>,
951-
end: OptionalArg<Option<isize>>,
952-
) -> usize {
953-
let range = adjust_indices(start, end, self.value.len());
919+
fn count(&self, args: FindArgs) -> usize {
920+
let (needle, range) = args.get_value(self.len());
954921
self.value
955-
.py_count(&sub.value, range, |h, n| h.matches(n).count())
922+
.py_count(&needle.value, range, |h, n| h.matches(n).count())
956923
}
957924

958925
#[pymethod]
@@ -1250,6 +1217,23 @@ impl TryFromObject for std::ffi::CString {
12501217

12511218
type SplitArgs = pystr::SplitArgs<PyStringRef, str, char>;
12521219

1220+
#[derive(FromArgs)]
1221+
pub struct FindArgs {
1222+
#[pyarg(positional_only, optional = false)]
1223+
sub: PyStringRef,
1224+
#[pyarg(positional_only, default = "None")]
1225+
start: Option<PyIntRef>,
1226+
#[pyarg(positional_only, default = "None")]
1227+
end: Option<PyIntRef>,
1228+
}
1229+
1230+
impl FindArgs {
1231+
fn get_value(self, len: usize) -> (PyStringRef, std::ops::Range<usize>) {
1232+
let range = adjust_indices(self.start, self.end, len);
1233+
(self.sub, range)
1234+
}
1235+
}
1236+
12531237
pub fn init(ctx: &PyContext) {
12541238
PyString::extend_class(ctx, &ctx.types.str_type);
12551239

vm/src/obj/pystr.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use crate::function::{single_or_tuple_any, OptionalOption};
2+
use crate::obj::objint::PyIntRef;
23
use crate::pyobject::{PyObjectRef, PyResult, TryFromObject, TypeProtocol};
34
use crate::vm::VirtualMachine;
4-
use num_traits::cast::ToPrimitive;
5+
use num_traits::{cast::ToPrimitive, sign::Signed};
56

67
#[derive(FromArgs)]
78
pub struct SplitArgs<T, S, E>
@@ -58,10 +59,10 @@ impl ExpandTabsArgs {
5859
pub struct StartsEndsWithArgs {
5960
#[pyarg(positional_only, optional = false)]
6061
affix: PyObjectRef,
61-
#[pyarg(positional_only, optional = true)]
62-
start: OptionalOption<isize>,
63-
#[pyarg(positional_only, optional = true)]
64-
end: OptionalOption<isize>,
62+
#[pyarg(positional_only, default = "None")]
63+
start: Option<PyIntRef>,
64+
#[pyarg(positional_only, default = "None")]
65+
end: Option<PyIntRef>,
6566
}
6667

6768
impl StartsEndsWithArgs {
@@ -71,14 +72,25 @@ impl StartsEndsWithArgs {
7172
}
7273
}
7374

75+
fn cap_to_isize(py_int: PyIntRef) -> isize {
76+
let big = py_int.as_bigint();
77+
big.to_isize().unwrap_or_else(|| {
78+
if big.is_negative() {
79+
std::isize::MIN
80+
} else {
81+
std::isize::MAX
82+
}
83+
})
84+
}
85+
7486
// help get optional string indices
7587
pub fn adjust_indices(
76-
start: OptionalOption<isize>,
77-
end: OptionalOption<isize>,
88+
start: Option<PyIntRef>,
89+
end: Option<PyIntRef>,
7890
len: usize,
7991
) -> std::ops::Range<usize> {
80-
let mut start = start.flat_option().unwrap_or(0);
81-
let mut end = end.flat_option().unwrap_or(len as isize);
92+
let mut start = start.map_or(0, cap_to_isize);
93+
let mut end = end.map_or(len as isize, cap_to_isize);
8294
if end > len as isize {
8395
end = len as isize;
8496
} else if end < 0 {

0 commit comments

Comments
 (0)