GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Fix title() and capitalize() by joshuamegnauth54 · Pull Request #7717 · RustPython/RustPython

Conversation

@joshuamegnauth54

@joshuamegnauth54 joshuamegnauth54 commented Apr 28, 2026 •
edited by coderabbitai Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

I fixed title() and capitalize() as well as enabled their respective tests. I fixed both by following CPython's logic closely, including implementing a workaround for sigma.

Besides that, I removed an unneeded dependency (unicode-casing) by using icu4x instead. This helps with consistency and removes outdated Unicode tables from the final RustPython binary.

Summary by CodeRabbit

  • Bug Fixes

    • Improved Unicode string case behavior (capitalize, title, istitle), including correct handling of Greek sigma, Turkish dotted I, German ß, combining marks, emoji-leading text, and preservation of invalid bytes.
  • Chores

    • Switched to ICU-based Unicode libraries and added a formatting/helper dependency.
  • Refactor

    • Reworked titlecasing and ASCII-bytes logic for clarity and reuse.
  • Tests

    • Enabled and expanded Unicode title/capitalize tests covering multiple edge cases.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@coderabbitai

coderabbitai Bot commented Apr 28, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 80cb2aad-e0ff-4825-b958-db496724819d

📥 Commits

Reviewing files that changed from the base of the PR and between cbce58c and ce75f32.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • Lib/test/test_str.py is excluded by !Lib/**
📒 Files selected for processing (6)
  • Cargo.toml
  • crates/vm/Cargo.toml
  • crates/vm/src/builtins/str.rs
  • crates/vm/src/bytes_inner.rs
  • crates/vm/src/utils.rs
  • extra_tests/snippets/builtin_str.py
✅ Files skipped from review due to trivial changes (1)
  • extra_tests/snippets/builtin_str.py
🚧 Files skipped from review as they are similar to previous changes (5)
  • crates/vm/src/utils.rs
  • Cargo.toml
  • crates/vm/Cargo.toml
  • crates/vm/src/builtins/str.rs
  • crates/vm/src/bytes_inner.rs

📝 Walkthrough

Walkthrough

Replaces unicode-casing with ICU crates and writeable; rewrites PyStr casing methods (capitalize, title, istitle) to use ICU titlecasing and Unicode property checks; extracts an ASCII title helper for bytes; adds a Vec-backed fmt::Write helper; enables/extends related string tests.

Changes

Unicode casing & string title/capitalize overhaul

Layer / File(s) Summary
Dependencies
Cargo.toml, crates/vm/Cargo.toml
workspace and crates/vm manifests updated: removed unicode-casing, added icu_casemap, icu_locale, icu_normalizer, icu_properties, and writeable; reordered related entries.
Imports / Traits
crates/vm/src/builtins/str.rs
Updated casing-related imports to use ICU casemap/locale, Unicode property groups, and Writeable; removed prior unicode_casing imports.
Infrastructure
crates/vm/src/utils.rs
Added pub(crate) struct VecFmtWriter(pub Vec<u8>) and impl fmt::Write to allow writing UTF-8 text into a Vec<u8>.
Bytes Helpers
crates/vm/src/bytes_inner.rs
Introduced pub(crate) fn title_ascii(bytes: &[u8]) -> Vec<u8>; PyBytesInner::title now delegates to this ASCII-only helper.
Capitalize (UTF-8)
crates/vm/src/builtins/str.rs
PyStr::capitalize UTF-8 path uses titlecase_first (ICU via Writeable) then lowercase_or_sigma for remaining characters.
Capitalize (WTF-8)
crates/vm/src/builtins/str.rs
PyStr::capitalize WTF-8 path processes valid UTF-8 chunks with ICU, preserves invalid bytes between chunks.
Title dispatch
crates/vm/src/builtins/str.rs
PyStr::title dispatches: ASCII -> title_ascii, UTF-8 -> titlecase_string, WTF-8 -> chunked titlecase_string preserving invalid bytes.
istitle update
crates/vm/src/builtins/str.rs
PyStr::istitle now checks GeneralCategoryGroup::TitlecaseLetter (and uppercase) for titlecase eligibility.
Helpers
crates/vm/src/builtins/str.rs
Added titlecase_first, titlecase_string, lowercase_or_sigma, and handle_capital_sigma implementing ICU-backed title behavior and sigma selection.
Tests
extra_tests/snippets/builtin_str.py
Enabled "DZ".title() == "Dz" and added str.capitalize() assertions for \"ßello\", \"İstanbul\", \"a\u0301bc\", \"ΣΙΓΜΑ\", \"😀hello\", and \"élan\".

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant PyStr
  participant ICU
  participant Props
  participant Bytes
  Caller->>PyStr: call .capitalize() / .title() / .istitle()
  PyStr->>ICU: titlecase_string / titlecase_first (language-aware mapping)
  PyStr->>Props: query GeneralCategory / TitlecaseLetter (sigma/context checks)
  ICU-->>PyStr: mapped titlecase segments (Writeable output)
  PyStr->>PyStr: lowercase_or_sigma / handle_capital_sigma adjustments
  PyStr->>Bytes: title_ascii for ASCII-only fast path or bytes chunks
  Bytes-->>PyStr: ASCII-chunk results
  PyStr-->>Caller: return final cased string (WTF-8: preserve invalid bytes)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • RustPython/RustPython#7559: Modifies Unicode-aware casing in crates/vm/src/builtins/str.rs, related to casing logic changes.
  • RustPython/RustPython#7748: Adjusts titlecasing behavior in crates/vm/src/builtins/str.rs.
  • RustPython/RustPython#7555: Prior ICU migration work touching workspace/crate dependencies and casing logic.

Suggested reviewers

  • ShaharNaveh
  • youknowone

Poem

A rabbit found a casing clue,
Swapped crates and stitched bytes true,
Sigma learned its contextual tune,
Vecs wrote letters by the moon,
Hooray — the strings now wake anew! 🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly reflects the main changes: fixes to str.title() and str.capitalize() implementations with ICU-based titlecasing integration.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
  • X
  • Mastodon
  • Reddit
  • LinkedIn

Comment @coderabbitai help to get the list of available commands and usage tips.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@joshuamegnauth54 joshuamegnauth54 changed the title Titlecase fixes Fix title() and capitalize() May 2, 2026
@joshuamegnauth54
joshuamegnauth54 marked this pull request as ready for review May 2, 2026 00:53
@joshuamegnauth54
joshuamegnauth54 force-pushed the titlecase-fixes branch from c533354 to 873c42b Compare May 2, 2026 00:53
@github-actions

github-actions Bot commented May 2, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

[x] test: cpython/Lib/test/test_str.py (TODO: 8)
[x] test: cpython/Lib/test/test_fstring.py (TODO: 19)
[x] test: cpython/Lib/test/test_string_literals.py (TODO: 4)

dependencies:

dependent tests: (no tests depend on str)

Legend:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

ShaharNaveh
ShaharNaveh requested changes May 2, 2026
View reviewed changes

@ShaharNaveh ShaharNaveh left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM!

ty:)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/test/string_tests.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@joshuamegnauth54
joshuamegnauth54 force-pushed the titlecase-fixes branch from 873c42b to 109a290 Compare May 3, 2026 22:18
@ShaharNaveh

ShaharNaveh commented May 4, 2026

Copy link
Copy Markdown
Contributor

@joshuamegnauth54 can you please fix the merge conflicts?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@youknowone
youknowone enabled auto-merge (squash) May 4, 2026 11:47
auto-merge was automatically disabled May 4, 2026 17:10

Head branch was pushed to by a user without write access

@joshuamegnauth54
joshuamegnauth54 force-pushed the titlecase-fixes branch from 109a290 to cbce58c Compare May 4, 2026 17:10
@joshuamegnauth54

joshuamegnauth54 commented May 4, 2026

Copy link
Copy Markdown
Contributor Author

Fixed and also I fixed a small clippy lint that I introduced. I'm not sure why it didn't trigger earlier, but one of my helpers should have been pub(crate) instead of just pub.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ShaharNaveh

ShaharNaveh commented May 4, 2026

Copy link
Copy Markdown
Contributor

Fixed and also I fixed a small clippy lint that I introduced. I'm not sure why it didn't trigger earlier, but one of my helpers should have been pub(crate) instead of just pub.

That's because we have added a new lint for that at #7762 :)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

ShaharNaveh
ShaharNaveh approved these changes May 4, 2026
View reviewed changes

@ShaharNaveh ShaharNaveh left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!
tysm:)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@joshuamegnauth54 joshuamegnauth54 mentioned this pull request May 4, 2026
Use icu4x for casefold() #7780
Merged
@youknowone
youknowone enabled auto-merge (squash) May 6, 2026 11:39
@youknowone

youknowone commented May 6, 2026

Copy link
Copy Markdown
Member

I am sorry, I merged another PR first and it made conflict. Could you resolve conflict? I will merge it immediately

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

auto-merge was automatically disabled May 6, 2026 18:19

Head branch was pushed to by a user without write access

@joshuamegnauth54
joshuamegnauth54 force-pushed the titlecase-fixes branch from cbce58c to 114fc53 Compare May 6, 2026 18:19
@joshuamegnauth54

joshuamegnauth54 commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

Fixed and force pushed. 😁

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

ShaharNaveh
ShaharNaveh approved these changes May 7, 2026
View reviewed changes

@ShaharNaveh ShaharNaveh left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!
ty:)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@youknowone
youknowone enabled auto-merge (squash) May 9, 2026 15:32
joshuamegnauth54 added 4 commits May 10, 2026 00:47
@joshuamegnauth54 @youknowone
PyBytes.title should be ASCII-only.
9d8d34e
@joshuamegnauth54 @youknowone
Use icu_casemap over unicode-casing for titles
edc87f2
`icu_casemap` is consistently maintained, official, and tracks the
latest Unicode versions. RustPython is also using other `icu4x` crates,
so using `icu_casemap` is more consistent.

As with islower and isupper, tracking the latest Unicode version is
important because character definitions shift over time which causes
discrepancies between RustPython and CPython.

This commit fixes title().
@joshuamegnauth54 @youknowone
Use icu_casemap for capitalize()
58d8b7c
I dropped unicode-casing because it's cleaner to use icu4x for
everything. `icu4x` will also stay up to date whereas unicode-casing
will need to be periodically updated with new Unicode tables. Dropping
unicode-casing also removes some binary bloat due to the tables.

`capitalize()` mimics CPython behavior more closely now as well.
Notably, I implemented CPython's sigma edge case handler.
@joshuamegnauth54 @youknowone
Match CPython's title() exactly
ce75f32
@youknowone
youknowone force-pushed the titlecase-fixes branch from 114fc53 to ce75f32 Compare May 9, 2026 16:10
@youknowone
youknowone merged commit 108461f into RustPython:main May 9, 2026
26 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@joshuamegnauth54
joshuamegnauth54 deleted the titlecase-fixes branch May 13, 2026 01:24
joshuamegnauth54 added a commit to joshuamegnauth54/RustPython that referenced this pull request May 13, 2026
@joshuamegnauth54
Fix swapcase()
e4ba68f
The tests for swapcase() were failing for two reasons. The first is
'𐐧' casing which should be fixed with modern Unicode tables. The second
failure is due to CPython's sigma override, which I implemented in
PR RustPython#7717.
@coderabbitai coderabbitai Bot mentioned this pull request May 13, 2026
Fix swapcase() #7788
Merged
joshuamegnauth54 added a commit to joshuamegnauth54/RustPython that referenced this pull request May 13, 2026
@joshuamegnauth54
Fix swapcase()
b7ad7c4
The tests for swapcase() were failing for two reasons. The first is
'𐐧' casing which should be fixed with modern Unicode tables. The second
failure is due to CPython's sigma override, which I implemented in
PR RustPython#7717.
youknowone pushed a commit that referenced this pull request May 13, 2026
@joshuamegnauth54
Fix swapcase() (#7788)
ef375be
The tests for swapcase() were failing for two reasons. The first is
'𐐧' casing which should be fixed with modern Unicode tables. The second
failure is due to CPython's sigma override, which I implemented in
PR #7717.
@coderabbitai coderabbitai Bot mentioned this pull request Jul 8, 2026
Complete rustpython-unicode isolation: case mapping, casing predicates, sre parity #8237
Merged
youknowone pushed a commit that referenced this pull request Sep 16, 2026
@joshuamegnauth54
Fix title() and capitalize() (#7717)
c9d2a92
* PyBytes.title should be ASCII-only.

* Use icu_casemap over unicode-casing for titles

`icu_casemap` is consistently maintained, official, and tracks the
latest Unicode versions. RustPython is also using other `icu4x` crates,
so using `icu_casemap` is more consistent.

As with islower and isupper, tracking the latest Unicode version is
important because character definitions shift over time which causes
discrepancies between RustPython and CPython.

This commit fixes title().

* Use icu_casemap for capitalize()

I dropped unicode-casing because it's cleaner to use icu4x for
everything. `icu4x` will also stay up to date whereas unicode-casing
will need to be periodically updated with new Unicode tables. Dropping
unicode-casing also removes some binary bloat due to the tables.

`capitalize()` mimics CPython behavior more closely now as well.
Notably, I implemented CPython's sigma edge case handler.

* Match CPython's title() exactly
youknowone pushed a commit that referenced this pull request Sep 16, 2026
@joshuamegnauth54
Fix swapcase() (#7788)
e59f2a7
The tests for swapcase() were failing for two reasons. The first is
'𐐧' casing which should be fixed with modern Unicode tables. The second
failure is due to CPython's sigma override, which I implemented in
PR #7717.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@ShaharNaveh ShaharNaveh ShaharNaveh approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@joshuamegnauth54 @ShaharNaveh @youknowone
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.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.