Support superscript decimal point and fraction slash in exponents (#2250) - #2330
Conversation
…recco#2250) Unit strings could not use a superscript decimal point (`⋅`, U+22C5) or fraction slash (`⸍`, U+2E0D) in exponents, so `gr⁰⋅³³³` and `gr¹⸍³` raised UndefinedUnitError even though ordinary superscripts (`gr²`) worked. Map `⋅` to `.` and `⸍` to `/` and extend the superscript exponent regex to accept them; the existing `**(...)` wrapping keeps the fraction correctly parenthesized (`gr¹⸍³` -> `gr**(1/3)`). The multiplication interpunct `·` (U+00B7) is a distinct character and is unaffected. Adds tests.
Merging this PR will improve performance by 23.22%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | WallTime | test_load_definitions_stage_1[True] |
184.1 µs | 146.1 µs | +26.01% |
| ⚡ | WallTime | test_import |
323.9 ms | 268.8 ms | +20.49% |
Tip
Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.
Comparing apoorvdarshan:superscript-decimal-fraction-exponents-2250 (61643f5) with master (5d9c534)
Footnotes
-
448 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
Closes #2250.
Problem
Unit strings using a superscript decimal point (
⋅, U+22C5) or a superscript fraction slash (⸍, U+2E0D) inside an exponent raiseUndefinedUnitError, even though ordinary superscript exponents already work:Fix
As suggested by @andrewgsavage in the issue, this extends the existing superscript handling in
string_preprocessor(pint/util.py):_pretty_tablenow maps⋅→.(decimal point) and⸍→/(fraction slash)._pretty_exp_renow accepts⋅as a decimal separator and⸍as a fraction separator within a superscript exponent.Because the exponent is already wrapped as
**(...), the fraction stays correctly parenthesized:·(U+00B7, the multiplication interpunct) is a distinct character from⋅(U+22C5) and is unaffected —kg·m/s²still parses askilogram * meter / second ** 2.Testing
TestStringProcessor::test_superscriptcovering the existing forms (gr²,gr⁻³), the interpunct-is-multiplication case (kg·m), and the two new separators. It fails onmainand passes with this change.pytest-benchmark):1636 passed, no regressions.ruff check/ruff format --checkclean;CHANGESupdated.Disclosure: this change was prepared with the assistance of an AI tool (Claude Code). I reproduced the issue, implemented and verified the fix and tests, ran the suite and linters, and take responsibility for the contribution and will respond to review feedback personally.