Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions mypyc/lib-rt/str_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,7 @@ PyObject *CPyStr_GetItem(PyObject *str, CPyTagged index) {
return NULL;
}
} else {
PyObject *index_obj = CPyTagged_AsObject(index);
PyObject *result = PyObject_GetItem(str, index_obj);
Py_DECREF(index_obj);
return result;
return NULL;
}
}

Expand Down Expand Up @@ -218,7 +215,11 @@ PyObject *CPyStr_Build(Py_ssize_t len, ...) {
Py_ssize_t itemlen = PyUnicode_GET_LENGTH(item);
if (itemlen != 0) {
#if CPY_3_13_FEATURES
PyUnicode_CopyCharacters(res, res_offset, item, 0, itemlen);
if (PyUnicode_CopyCharacters(res, res_offset, item, 0, itemlen) < 0) {
va_end(args);
Py_DECREF(res);
return NULL;
}
#else
_PyUnicode_FastCopyCharacters(res, res_offset, item, 0, itemlen);
#endif
Expand Down Expand Up @@ -419,6 +420,9 @@ int CPyStr_Startswith(PyObject *self, PyObject *subobj) {
return 2;
}
int result = PyUnicode_Tailmatch(self, substring, start, end, -1);
if (result < 0) {
return 2;
}
if (result) {
return 1;
}
Expand All @@ -443,6 +447,9 @@ int CPyStr_Endswith(PyObject *self, PyObject *subobj) {
return 2;
}
int result = PyUnicode_Tailmatch(self, substring, start, end, 1);
if (result < 0) {
return 2;
}
if (result) {
return 1;
}
Expand All @@ -455,6 +462,9 @@ int CPyStr_Endswith(PyObject *self, PyObject *subobj) {
PyObject *CPyStr_Removeprefix(PyObject *self, PyObject *prefix) {
Py_ssize_t end = PyUnicode_GET_LENGTH(self);
int match = PyUnicode_Tailmatch(self, prefix, 0, end, -1);
if (match < 0) {
return NULL;
}
if (match) {
Py_ssize_t prefix_end = PyUnicode_GET_LENGTH(prefix);
return PyUnicode_Substring(self, prefix_end, end);
Expand All @@ -465,6 +475,9 @@ PyObject *CPyStr_Removeprefix(PyObject *self, PyObject *prefix) {
PyObject *CPyStr_Removesuffix(PyObject *self, PyObject *suffix) {
Py_ssize_t end = PyUnicode_GET_LENGTH(self);
int match = PyUnicode_Tailmatch(self, suffix, 0, end, 1);
if (match < 0) {
return NULL;
}
if (match) {
Py_ssize_t suffix_end = PyUnicode_GET_LENGTH(suffix);
return PyUnicode_Substring(self, 0, end - suffix_end);
Expand Down
4 changes: 2 additions & 2 deletions mypyc/primitives/str_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@
arg_types=[str_rprimitive, str_rprimitive],
return_type=str_rprimitive,
c_function_name="CPyStr_Removeprefix",
error_kind=ERR_NEVER,
error_kind=ERR_MAGIC,
)

# str.removesuffix(str)
Expand All @@ -274,7 +274,7 @@
arg_types=[str_rprimitive, str_rprimitive],
return_type=str_rprimitive,
c_function_name="CPyStr_Removesuffix",
error_kind=ERR_NEVER,
error_kind=ERR_MAGIC,
)

# str.split(...) and str.rsplit(...)
Expand Down
19 changes: 19 additions & 0 deletions mypyc/test-data/exceptions.test
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,25 @@ L3:
r2 = <error> :: int
return r2

[case testStrRemovePrefixSuffixError]
def f(s: str, prefix: str, suffix: str) -> str:
return s.removeprefix(prefix).removesuffix(suffix)
[out]
def f(s, prefix, suffix):
s, prefix, suffix, r0, r1, r2 :: str
L0:
r0 = CPyStr_Removeprefix(s, prefix)
if is_error(r0) goto L3 (error at f:2) else goto L1
L1:
r1 = CPyStr_Removesuffix(r0, suffix)
dec_ref r0
if is_error(r1) goto L3 (error at f:2) else goto L2
L2:
return r1
L3:
r2 = <error> :: str
return r2

[case testListAppendAndSetItemError]
from typing import List
def f(x: List[int], y: int, z: int) -> None:
Expand Down
6 changes: 6 additions & 0 deletions mypyc/test-data/run-strings.test
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ assert match_tuple_literal_args('abc', 'z', 'c') == (False, True)
assert remove_prefix_suffix('', '') == ('', '')
assert remove_prefix_suffix('abc', 'a') == ('bc', 'abc')
assert remove_prefix_suffix('abc', 'c') == ('abc', 'ab')
assert remove_prefix_suffix('abc', '') == ('abc', 'abc')
assert remove_prefix_suffix('abc', 'abc') == ('', '')
assert remove_prefix_suffix('abc', 'abcd') == ('abc', 'abc')
assert remove_prefix_suffix('abc', 'b') == ('abc', 'abc')
assert remove_prefix_suffix('\u1234abc\U0001f600', '\u1234') == ('abc\U0001f600', '\u1234abc\U0001f600')
assert remove_prefix_suffix('\u1234abc\U0001f600', '\U0001f600') == ('\u1234abc\U0001f600', '\u1234abc')

[case testStringEquality]
def eq(a: str, b: str) -> bool:
Expand Down
Loading