Repository navigation
Bug: case=False is not working correctly in the string accessor - #11747
Merged
headtr1ck merged 3 commits intoOct 20, 2026
Merged
Conversation
str.replace ignored case=False when regex=False and returned the input unchanged. str.contains with case=False, regex=False raised AttributeError on object-dtype and StringDType arrays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Novain Shibu <georgeshibu380@gmail.com>
|
Thank you for opening this pull request! It may take us a few days to respond here, so thank you for being patient. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Novain Shibu <georgeshibu380@gmail.com>
headtr1ck
reviewed
Oct 17, 2026
headtr1ck
left a comment
Collaborator
There was a problem hiding this comment.
Couple of minor points but looks good, thanks!
I assume case was only ever supposed to be used for regex, but I guess it doesn't hurt to just support it :)
| the array. Previously, e.g. ``da.cumulative("time").argmax()`` returned indices | ||
| shifted by the number of missing values in front of the array (:issue:`11336`). | ||
| By `Michael Niklas <https://github.com/headtr1ck>`_. | ||
| - ``DataArray.str.replace`` now respects ``case=False`` when ``regex=False``; |
Collaborator
There was a problem hiding this comment.
Suggested change
| - ``DataArray.str.replace`` now respects ``case=False`` when ``regex=False``; | |
| - :py:meth:`DataArray.str.replace` now respects ``case=False`` when ``regex=False``; |
and others as well
| id="StringDType", | ||
| marks=pytest.mark.skipif( | ||
| not hasattr(np, "dtypes") or not hasattr(np.dtypes, "StringDType"), | ||
| reason="requires numpy>=2", |
Collaborator
There was a problem hiding this comment.
Our minimum numpy version is already 2.2, the skip is not required anymore.
| assert_equal(result, xr.DataArray([False, False, True], dims=["x"])) | ||
|
|
||
| result = da.str.replace("o", "_", case=False, regex=False) | ||
| assert list(result.values) == ["F__", "xYz", "f__.__"] |
Collaborator
There was a problem hiding this comment.
Could this test also use assert_equal?
Use :py:meth: roles in the whats-new entry, remove the numpy>=2 skipif (minimum numpy is 2.2), and compare the replace result with assert_equal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Novain Shibu <georgeshibu380@gmail.com>
Contributor
Author
|
Thanks for the review! I’ve made all three changes in 9b28876:
|
headtr1ck
approved these changes
Oct 19, 2026
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.
Description
I found two issues in the string accessor while testing different string dtypes against pandas.
1.
str.replace()ignorescase=Falsewhenregex=FalseFor example, replacing
"HELLO"with"bye"in["Hello World"]should give"bye World"whencase=False. Instead, the original string remains unchanged, with no error.This happens with regular strings, object-dtype arrays, and StringDType arrays. The problem is that the
regex=Falsepath uses Python'sstr.replace(), which does not support case-insensitive replacement.2.
str.contains()crashes withcase=Falseon some dtypesWhen
case=Falseandregex=Falseare used together,str.contains()raises anAttributeErroron object-dtype and StringDType arrays. Normal Unicode string arrays work.The issue comes from passing the pattern, which is a plain string, to
StringAccessoras though it were an array.Proposed fix
replace(), usere.sub()withre.IGNORECASEwhencase=Falseandregex=False. Escape the search pattern so it is treated literally, keep the replacement unchanged so backreferences are not interpreted, and preserve the existingnlimit.contains(), compare the strings element by element usingcasefold(), with.upper()for bytes.whats-new.rst.Tests
I added four tests covering case-insensitive replacement across dtypes and the affected
contains()andreplace()cases for object and StringDType arrays.The tests fail before the fix and pass after it. The 228 existing string-accessor tests also pass before and after the changes (run on 14 October).
I haven't rerun the tests after today's rebase because I don't have a test environment on this laptop. CI will need to confirm the results on the rebased changes.
Related PR
headtr1ck opened #11746 today, which also modifies
contains()andreplace()as part of usingnp.stringsin the string accessor. However, it leaves the affectedcase=Falselogic unchanged, so these bugs remain.Since both PRs touch the same functions, there may be a small conflict or rebase needed, depending on which one merges first. I'm happy to help resolve it.
I found these issues using the same approach as #11722: testing the same inputs across different dtypes and comparing the results with pandas, then investigating the differences.
One related issue I haven't addressed is that
flags=is also ignored whenregex=False.Checklist
whats-new.rstAI Disclosure
Testing: The tests were run before the latest rebase; they have not been rerun afterward.
Tools: Claude helped me investigate the behaviour, reason about the fixes, and develop the tests.
[PR opened by Claude Code on behalf of Novain Shibu]