Skip to content

gh-161970: Rename UserString.replace() parameter maxsplit to count - #161971

Open
Broyojo wants to merge 2 commits into
python:mainfrom
Broyojo:gh-161970-userstring-replace-count
Open

Broyojo wants to merge 2 commits into
python:mainfrom
Broyojo:gh-161970-userstring-replace-count

Conversation

@Broyojo

@Broyojo Broyojo commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

collections.UserString.replace() called its third parameter maxsplit, so UserString('aa').replace('a', 'b', count=1) raised TypeError even though str.replace() has accepted count as a keyword since 3.13. This renames it to count to match str.replace().

The existing test_count_keyword in Lib/test/string_tests.py called replace on str literals, so it never ran against UserString (or bytes/bytearray). It now goes through checkequal, which exercises every type that shares these tests.

Compatibility: a caller passing maxsplit= by keyword now gets TypeError. That name was never documented and str.replace() never accepted it, and I found no callers in the stdlib.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-14T00:28:09.854564Z 9d45abf PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@aisk

aisk commented Nov 14, 2026 •

Copy link
Copy Markdown
Member

The change LGTM. Maybe we can just deprecate the maxsplit parameter and add a new count, so we don't break existing code. But this sounds more like a bug, and I guess few users rely on this, so I'm not sure which way is better.

BTW I read your article on HN about your Lean formalization of Python, which is very interesting!

@Broyojo

Broyojo commented Nov 14, 2026

Copy link
Copy Markdown
Contributor Author

Thanks! I went with a plain rename because maxsplit was never documented and str.replace() never accepted it, and I couldn't find callers that pass it by keyword. But I'm happy to switch to a deprecation if a core dev prefers that.

@picnixz

picnixz commented Nov 14, 2026

Copy link
Copy Markdown
Member
  1. Can you quickly browser public repos to see if maxsplit is used here?
  2. In hashlib, I added a true deprecation period for misnamed parameters so I think we can also do it (and add a regression test for it). We can have a 2-years deprecation period insteaad of a 5 years though.

@picnixz

picnixz commented Nov 14, 2026 •

Copy link
Copy Markdown
Member

Thanks! I went with a plain rename because maxsplit was never documented

It was documented implicitly by saying it's compatible with str, meaning that people would either use a positional argument or use a wrong keyword (and would in this case switch to that in their code). Let's not break them. Can you also check what typeshed does?

…ead of removing it

Keep accepting the old keyword name for a deprecation period instead of
breaking callers that pass maxsplit= (typeshed spells the parameter
maxsplit). Passing maxsplit= now emits a DeprecationWarning and is slated
for removal in Python 3.18; passing both count and maxsplit raises
TypeError. This mirrors the deprecation of the 'string' keyword parameter
in hashlib (pythongh-134978), with a two-year period.
@Broyojo

Broyojo commented Nov 14, 2026

Copy link
Copy Markdown
Contributor Author

Typeshed spells the parameter maxsplit (maxsplit: SupportsIndex = -1), so type-checked code may well pass it by keyword. A GitHub code search found only definitions of maxsplit, in vendored copies of Python 2's UserString.py (and of collections/__init__.py) and in ctypesgen's copy and the bindings it generates, and no calls that pass maxsplit=. I've pushed a commit that keeps maxsplit= working with a DeprecationWarning, slated for removal in Python 3.18, following the hashlib string= deprecation (gh-134978), with a regression test; passing both count and maxsplit raises TypeError.

@Broyojo
Broyojo requested a review from AA-Turner as a code owner November 14, 2026 18:29
@read-the-docs-community

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants