Uh oh!
There was an error while loading. Please reload this page.
[mypyc] Add support for str.lower() and str.upper() - #20948
Conversation
VaggelisD
commented
Mar 2, 2026
Oops, looks like the APIs I based the PR on are not exported past 3.13+, will need to figure out a solution. The |
| // The _PyUnicode_CheckConsistency definition has been moved to the internal API | ||
| // https://github.com/python/cpython/pull/106398 | ||
| #if defined(Py_DEBUG) && defined(CPY_3_13_FEATURES) |
There was a problem hiding this comment.
That was a mistake afaict, CPY_3_13_FEATURES is defined by us so that'd always evaluate to true
VaggelisD
commented
Mar 2, 2026
I was testing this branch on Python 3.11; For 3.13+ I had to fallback to CPython's generic dispatch for Unicode strings. This introduces the following regression for the latter versions (tested on 3.14)
|
JukkaL
left a comment
There was a problem hiding this comment.
Thanks for the PR! Can you also compare performance against mypyc master, on Python 3.14?
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
JukkaL
commented
Mar 2, 2026
Since |
I applied the inlining and reran the benchmarks:
|
JukkaL
left a comment
There was a problem hiding this comment.
Thanks, looks good! I'm glad that we finally have primitives for these common operations.
Uh oh!
There was an error while loading. Please reload this page.
#21553) 6th PR of #21418. This PR introduces two `i32 -> i32` case-conversion helpers, alongside the existing classifiers. **The constraint to flag**: A single i32 holds one codepoint, but some Unicode case mappings expand to multiple e.g `'ß'.upper()` becomes `'SS'`, `'fi'.upper()` becomes `'FI'` etc. For those inputs the primitive _returns the input unchanged_; This is the same split CPython makes between `Py_UNICODE_TOUPPER` (codepoint) and `str.upper()` (string), with the former returning the **first codepoint** of the expansion. Users needing full Unicode case conversion should call `s.upper()` / `s.lower()` on the string, for which we already have mypyc primitives (#20948). For ASCII benchmarks, the codepoint primitives are ~5x faster than their `str` counterparts, avoiding the 1-char allocation.
Fixesmypyc/mypyc#1088
Follow up on #19375 with full Unicode support:
CPyStr_ChangeCasehelper, parameterized by function pointers_PyUnicode_ToLowerFull/_PyUnicode_ToUpperFullfor Unicode which handle 1-to-N expansion (e.g.,ß→SS); This was a sticky point with the previous PR which relied onPy_UNICODE_TOLOWER/TOUPPER.len * 3UCS-4 buffer for the Unicode path; This is because each Unicode char may be expanded from 1 byte to 3Benchmarks (x10 M calls each)
""(empty)""(empty)