Conversation
The isdigit/isalpha/isalnum/isspace/isupper/islower descriptions in RFC
0006 and the 2026-02 Expression Language spec did not say which
character-class convention applies, and implementations diverged:
openjd-rs used Rust char predicates, making isdigit ASCII-only while
isalnum was Unicode-wide, so isdigit('\u0663') and isalnum('\u0663')
disagreed (openjd-rs issue #309).
Clarify that these functions have exactly the semantics of the Python
str methods of the same name over the Unicode Character Database,
document the cased-character rule for isupper/islower and the
isalnum-vs-isalpha/isdigit relationship, and add a conformance test
covering Unicode inputs where the conventions differ.
Signed-off-by: Mark <399551+mwiebe@users.noreply.github.com>
Follow-up to the character classification clarification: the title and capitalize descriptions had the same ambiguity, and implementations diverged the same way (word boundaries by alphanumeric-ness instead of cased-ness, uppercase instead of titlecase mappings, no Final_Sigma context rule). Clarify both function rows and the section note in RFC 0006 and the 2026-02 Expression Language spec, and extend the Unicode conformance test with title/capitalize cases covering digit word boundaries, titlecase digraph mappings, sharp-s expansion, and final sigma. Signed-off-by: Mark <399551+mwiebe@users.noreply.github.com>
leongdl
approved these changes
Aug 26, 2026
leongdl
added a commit
to leongdl/openjd-specifications
that referenced
this pull request
Sep 14, 2026
Both fixtures were parked in EXPR/jobs/proposed/ pending spec decisions. Both
decisions have landed, so they move up into jobs/ where the runner discovers
them.
center("hi", 7): section 2.2.4 does not say which side of an odd pad takes the
extra space. OpenJobDescription#177 settles ambiguities of this kind by matching Python, so the
fixture's CPython expectation (" hi ", extra space left) is now the rule
rather than a strawman.
isdigit over non-ASCII decimal digits: the classification functions carry
Python str semantics, and openjd-rs#341 implemented that from CPython-generated
tables, so the Unicode expectation now holds.
Fixture changes made while promoting:
- Rewrite both headers: drop the PARKED framing and the 2026-08 divergence
tables, and state the spec rule, the inputs, and what a wrong implementation
prints.
- Write the digits as \u0663 and \u0969 escapes so the file stays ASCII. The
runner reads fixtures with the locale encoding, which mojibakes a UTF-8
literal on Windows. Same reason OpenJobDescription#177 uses escapes.
- Bracket the isdigit assertions, matching the sibling
expr2.2.4--string-classification fixture. The runner matches output as a
substring, so an unbracketed value is a weaker assertion.
- Delete proposed/README-func-lib.md. Nothing is left parked in it: the
repr_py fixture was promoted on OpenJobDescription#162.
Signed-off-by: David Leong <116610336+leongdl@users.noreply.github.com>
leongdl
added a commit
to leongdl/openjd-specifications
that referenced
this pull request
Sep 14, 2026
Both fixtures were parked in EXPR/jobs/proposed/ pending spec decisions. Both
decisions have landed, so they move up into jobs/ where the runner discovers
them.
center("hi", 7): section 2.2.4 does not say which side of an odd pad takes the
extra space. OpenJobDescription#177 settles ambiguities of this kind by matching Python, so the
fixture's CPython expectation (" hi ", extra space left) is now the rule
rather than a strawman.
isdigit over non-ASCII decimal digits: the classification functions carry
Python str semantics, and openjd-rs#341 implemented that from CPython-generated
tables, so the Unicode expectation now holds.
Fixture changes made while promoting:
- Rewrite both headers: drop the PARKED framing and the 2026-08 divergence
tables, and state the spec rule, the inputs, and what a wrong implementation
prints.
- Write the digits as \u0663 and \u0969 escapes so the file stays ASCII. The
runner reads fixtures with the locale encoding, which mojibakes a UTF-8
literal on Windows. Same reason OpenJobDescription#177 uses escapes.
- Bracket the isdigit assertions, matching the sibling
expr2.2.4--string-classification fixture. The runner matches output as a
substring, so an unbracketed value is a weaker assertion.
- Delete proposed/README-func-lib.md. Nothing is left parked in it: the
repr_py fixture was promoted on OpenJobDescription#162.
Signed-off-by: David Leong <116610336+leongdl@users.noreply.github.com>
leongdl
added a commit
that referenced
this pull request
Sep 15, 2026
* test: Add expected-failure function-library fixtures (parked in proposed/)
Three parked fixtures with dual-implementation observations: center() odd-padding and ASCII-only isdigit() are spec gaps where BOTH implementations agree (no divergence - the spec should document the de facto behaviour), and repr_py raw-newline emission is a bug in BOTH implementations per the explicit spec text. Details in proposed/README.md. Companion to conformance-func-lib-gaps.
Review: quorum-review fixes — corrected the center-odd-padding entry on
the measured facts: CPython's str.center('hi',7) is ' hi ' (extra
space LEFT, verified by execution), current openjd-rs matches CPython
(re-verified against an upstream/main build this session), and the
Python CLI is now the right-heavy outlier — the fixture's committed
expectation is the de facto answer and the earlier README/header claims
were wrong. isdigit reframed as spec ambiguity with NO divergence between
the openjd implementations (both ASCII-only; the divergence is vs host
CPython). repr_py attribution corrected to BOTH implementations.
Kind-level proposed/ placement with a family-named README
(README-func-lib.md) to avoid add/add conflicts with co-located
expected-failures PRs.
Signed-off-by: David Leong <116610336+leongdl@users.noreply.github.com>
* test: Drop the repr_py fixture, promoted on #162
openjd-rs#374 landed the repr_py escaping fix, so
expr2.2.6--repr-py-newline-roundtrip passes and no longer belongs in
proposed/. It is promoted to EXPR/jobs/ on #162 alongside its
WRAP_ACTIONS twin, where the two land together and the control run
against a pre-fix binary is recorded.
Removing it here so the two copies do not collide when both merge. Its
README section goes with it.
The other two fixtures on this branch are untouched and still parked:
both are spec decisions, not implementation bugs.
Signed-off-by: David Leong <116610336+leongdl@users.noreply.github.com>
* test: Promote the center and isdigit function-library fixtures
Both fixtures were parked in EXPR/jobs/proposed/ pending spec decisions. Both
decisions have landed, so they move up into jobs/ where the runner discovers
them.
center("hi", 7): section 2.2.4 does not say which side of an odd pad takes the
extra space. #177 settles ambiguities of this kind by matching Python, so the
fixture's CPython expectation (" hi ", extra space left) is now the rule
rather than a strawman.
isdigit over non-ASCII decimal digits: the classification functions carry
Python str semantics, and openjd-rs#341 implemented that from CPython-generated
tables, so the Unicode expectation now holds.
Fixture changes made while promoting:
- Rewrite both headers: drop the PARKED framing and the 2026-08 divergence
tables, and state the spec rule, the inputs, and what a wrong implementation
prints.
- Write the digits as \u0663 and \u0969 escapes so the file stays ASCII. The
runner reads fixtures with the locale encoding, which mojibakes a UTF-8
literal on Windows. Same reason #177 uses escapes.
- Bracket the isdigit assertions, matching the sibling
expr2.2.4--string-classification fixture. The runner matches output as a
substring, so an unbracketed value is a weaker assertion.
- Delete proposed/README-func-lib.md. Nothing is left parked in it: the
repr_py fixture was promoted on #162.
Signed-off-by: David Leong <116610336+leongdl@users.noreply.github.com>
---------
Signed-off-by: David Leong <116610336+leongdl@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix: Specify Python str semantics for character classification functions
Description of the change. What is being added or fixed?
RFC 0006 and the 2026-02 Expression Language spec describe
isdigit,isalpha,isalnum,isspace,isupper, andislowerwith one-linesummaries ("True if all characters are digits...") that don't say which
character-class convention applies. Every language draws different lines
through Unicode — Rust's
Alphabeticproperty is a superset of Python'sL*categories, Rust has no notion ofNumeric_Type, and so on — soimplementations diverged: openjd-rs used Rust's
charpredicates, whichmade
isdigitASCII-only whileisalnumwas Unicode-wide, and the twocontradicted each other for characters like
'٣'(U+0663 ARABIC-INDICDIGIT THREE). Reported as
openjd-rs#309.
This PR:
exactly the semantics of the Python
strmethods of the same name overthe Unicode Character Database, with the specific Unicode properties named
per function.
isalnumis strictly broader thanisalpha OR isdigit(Numeric_Type=Numeric characters like½), and thecased-character rule for
isupper/islower(uncased characters areignored; titlecase characters are cased but neither upper nor lower).
implementations aren't broken by UCD updates.
expr2.2.4--string-classification-unicode) with21 assertions on characters where the conventions differ, using
\uXXXXescapes so the file stays ASCII. The test fails against openjd-rs
mainand passes against the fix in the companion PR.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.