Skip to content

Commit a9d2d14

Browse files
authored
[mypyc] Add librt.strings.isalpha codepoint primitive (#21521)
4th PR of #21418 This is 5x faster than `str.isalpha()` for ASCII.
1 parent 9b96cbe commit a9d2d14

6 files changed

Lines changed: 36 additions & 1 deletion

File tree

‎mypy/typeshed/stubs/librt/librt/strings.pyi‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,4 @@ def read_f64_be(b: bytes, index: i64, /) -> float: ...
4646
def isspace(c: i32, /) -> bool: ...
4747
def isdigit(c: i32, /) -> bool: ...
4848
def isalnum(c: i32, /) -> bool: ...
49+
def isalpha(c: i32, /) -> bool: ...

‎mypyc/lib-rt/codepoint_extra_ops.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,8 @@ static inline bool LibRTStrings_IsAlnum(int32_t c) {
2121
return c >= 0 && Py_UNICODE_ISALNUM((Py_UCS4)c);
2222
}
2323

24+
static inline bool LibRTStrings_IsAlpha(int32_t c) {
25+
return c >= 0 && Py_UNICODE_ISALPHA((Py_UCS4)c);
26+
}
27+
2428
#endif // MYPYC_CODEPOINT_EXTRA_OPS_H

‎mypyc/lib-rt/strings/librt_strings.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,7 @@ cp_parse_i32(PyObject *arg, int32_t *out) {
11931193
DEFINE_CP_BOOL_WRAPPER(isspace, LibRTStrings_IsSpace)
11941194
DEFINE_CP_BOOL_WRAPPER(isdigit, LibRTStrings_IsDigit)
11951195
DEFINE_CP_BOOL_WRAPPER(isalnum, LibRTStrings_IsAlnum)
1196+
DEFINE_CP_BOOL_WRAPPER(isalpha, LibRTStrings_IsAlpha)
11961197

11971198
static PyMethodDef librt_strings_module_methods[] = {
11981199
{"write_i16_le", (PyCFunction) write_i16_le, METH_FASTCALL,
@@ -1264,6 +1265,9 @@ static PyMethodDef librt_strings_module_methods[] = {
12641265
{"isalnum", cp_isalnum, METH_O,
12651266
PyDoc_STR("Test whether a codepoint (i32) is alphanumeric.")
12661267
},
1268+
{"isalpha", cp_isalpha, METH_O,
1269+
PyDoc_STR("Test whether a codepoint (i32) is a Unicode letter.")
1270+
},
12671271
{NULL, NULL, 0, NULL}
12681272
};
12691273

‎mypyc/primitives/librt_strings_ops.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,12 @@
422422
error_kind=ERR_NEVER,
423423
dependencies=[LIBRT_STRINGS, CODEPOINT_EXTRA_OPS],
424424
)
425+
426+
function_op(
427+
name="librt.strings.isalpha",
428+
arg_types=[int32_rprimitive],
429+
return_type=bool_rprimitive,
430+
c_function_name="LibRTStrings_IsAlpha",
431+
error_kind=ERR_NEVER,
432+
dependencies=[LIBRT_STRINGS, CODEPOINT_EXTRA_OPS],
433+
)

‎mypyc/test-data/irbuild-librt-strings.test‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,17 @@ def is_an(c):
373373
L0:
374374
r0 = LibRTStrings_IsAlnum(c)
375375
return r0
376+
377+
[case testLibrtStringsIsAlphaIR]
378+
from librt.strings import isalpha
379+
from mypy_extensions import i32
380+
381+
def is_a(c: i32) -> bool:
382+
return isalpha(c)
383+
[out]
384+
def is_a(c):
385+
c :: i32
386+
r0 :: bool
387+
L0:
388+
r0 = LibRTStrings_IsAlpha(c)
389+
return r0

‎mypyc/test-data/run-librt-strings.test‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1443,7 +1443,7 @@ def test_new_without_init_is_usable() -> None:
14431443
[case testLibrtStringsCodepointClassifiers_librt]
14441444
from typing import Any
14451445
from mypy_extensions import i32
1446-
from librt.strings import isspace, isdigit, isalnum
1446+
from librt.strings import isspace, isdigit, isalnum, isalpha
14471447

14481448
from testutil import assertRaises
14491449

@@ -1454,6 +1454,7 @@ def test_codepoint_classifiers() -> None:
14541454
assert not isspace(bad)
14551455
assert not isdigit(bad)
14561456
assert not isalnum(bad)
1457+
assert not isalpha(bad)
14571458
# Verify each codepoint primitive agrees with the matching str method
14581459
# across all Unicode codepoints, including the ord(chr(i)) round-trip.
14591460
# Any forces generic dispatch on the str side.
@@ -1464,6 +1465,7 @@ def test_codepoint_classifiers() -> None:
14641465
assert isspace(o) == isspace(i) == a.isspace()
14651466
assert isdigit(o) == isdigit(i) == a.isdigit()
14661467
assert isalnum(o) == isalnum(i) == a.isalnum()
1468+
assert isalpha(o) == isalpha(i) == a.isalpha()
14671469

14681470

14691471
def test_codepoint_classifiers_via_any() -> None:
@@ -1473,6 +1475,7 @@ def test_codepoint_classifiers_via_any() -> None:
14731475
(isspace, " ", "a"),
14741476
(isdigit, "5", "a"),
14751477
(isalnum, "A", " "),
1478+
(isalpha, "A", " "),
14761479
):
14771480
f: Any = fn
14781481
assert f(ord(true_input)) is True

0 commit comments

Comments
 (0)