Skip to content

Commit 87704cd

Browse files
authored
[mypyc] Optimize str.partition and str.rpartition (#18702)
`PyUnicode_Partition` and `PyUnicode_RPartition` are currently still missing from the docs but have been part of the stable API since Python 3.2.
1 parent 3ef6ab1 commit 87704cd

File tree

4 files changed

+42
-3
lines changed

4 files changed

+42
-3
lines changed

mypyc/doc/str_operations.rst

+2
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ Methods
3333
* ``s1.endswith(s2: str)``
3434
* ``s1.endswith(t: tuple[str, ...])``
3535
* ``s.join(x: Iterable)``
36+
* ``s.partition(sep: str)``
3637
* ``s.removeprefix(prefix: str)``
3738
* ``s.removesuffix(suffix: str)``
3839
* ``s.replace(old: str, new: str)``
3940
* ``s.replace(old: str, new: str, count: int)``
41+
* ``s.rpartition(sep: str)``
4042
* ``s.rsplit()``
4143
* ``s.rsplit(sep: str)``
4244
* ``s.rsplit(sep: str, maxsplit: int)``

mypyc/primitives/str_ops.py

+18
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,24 @@
197197
error_kind=ERR_NEVER,
198198
)
199199

200+
# str.partition(str)
201+
method_op(
202+
name="partition",
203+
arg_types=[str_rprimitive, str_rprimitive],
204+
return_type=tuple_rprimitive,
205+
c_function_name="PyUnicode_Partition",
206+
error_kind=ERR_MAGIC,
207+
)
208+
209+
# str.rpartition(str)
210+
method_op(
211+
name="rpartition",
212+
arg_types=[str_rprimitive, str_rprimitive],
213+
return_type=tuple_rprimitive,
214+
c_function_name="PyUnicode_RPartition",
215+
error_kind=ERR_MAGIC,
216+
)
217+
200218
# str.replace(old, new)
201219
method_op(
202220
name="replace",

mypyc/test-data/fixtures/ir.py

+2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ def startswith(self, x: Union[str, Tuple[str, ...]], start: int=..., end: int=..
113113
def endswith(self, x: Union[str, Tuple[str, ...]], start: int=..., end: int=...) -> bool: ...
114114
def replace(self, old: str, new: str, maxcount: int=...) -> str: ...
115115
def encode(self, encoding: str=..., errors: str=...) -> bytes: ...
116+
def partition(self, sep: str, /) -> Tuple[str, str, str]: ...
117+
def rpartition(self, sep: str, /) -> Tuple[str, str, str]: ...
116118
def removeprefix(self, prefix: str, /) -> str: ...
117119
def removesuffix(self, suffix: str, /) -> str: ...
118120

mypyc/test-data/run-strings.test

+20-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ assert remove_prefix_suffix('abc', 'a') == ('bc', 'abc')
7171
assert remove_prefix_suffix('abc', 'c') == ('abc', 'ab')
7272

7373
[case testStringOps]
74-
from typing import List, Optional
74+
from typing import List, Optional, Tuple
75+
from testutil import assertRaises
7576

7677
def do_split(s: str, sep: Optional[str] = None, max_split: Optional[int] = None) -> List[str]:
7778
if sep is not None:
@@ -121,11 +122,27 @@ def test_splitlines() -> None:
121122
assert splitlines(s_text, False) == ["This", "is", "", "some", "long", "text."]
122123
assert splitlines(s_text, True) == ["This\n", "is\n", "\n", "some\n", "long\n", "text.\n"]
123124

125+
s_partition = "Some long text"
126+
127+
def partition(s: str, sep: str) -> Tuple[str, str, str]:
128+
return s.partition(sep)
129+
130+
def rpartition(s: str, sep: str) -> Tuple[str, str, str]:
131+
return s.rpartition(sep)
132+
133+
def test_partition() -> None:
134+
assert partition(s_partition, " ") == ("Some", " ", "long text")
135+
assert partition(s_partition, "Hello") == ("Some long text", "", "")
136+
assert rpartition(s_partition, " ") == ("Some long", " ", "text")
137+
assert rpartition(s_partition, "Hello") == ("", "", "Some long text")
138+
with assertRaises(ValueError, "empty separator"):
139+
partition(s_partition, "")
140+
with assertRaises(ValueError, "empty separator"):
141+
rpartition(s_partition, "")
142+
124143
def getitem(s: str, index: int) -> str:
125144
return s[index]
126145

127-
from testutil import assertRaises
128-
129146
s = "abc"
130147

131148
def test_getitem() -> None:

0 commit comments

Comments
 (0)