Skip to content

Commit 865c3b2

Browse files
bpo-28029: Make "".replace("", s, n) returning s for any n != 0. (GH-16981)
1 parent 25fc088 commit 865c3b2

File tree

5 files changed

+18
-9
lines changed

5 files changed

+18
-9
lines changed

Doc/whatsnew/3.9.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ Other Language Changes
9999
ignored for empty strings.
100100
(Contributed by Victor Stinner in :issue:`37388`.)
101101

102+
* ``"".replace("", s, n)`` now returns ``s`` instead of an empty string for
103+
all non-zero ``n``. It is now consistent with ``"".replace("", s)``.
104+
There are similar changes for :class:`bytes` and :class:`bytearray` objects.
105+
(Contributed by Serhiy Storchaka in :issue:`28029`.)
106+
102107

103108
New Modules
104109
===========

Lib/test/string_tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ def test_replace(self):
505505
EQ("", "", "replace", "A", "")
506506
EQ("", "", "replace", "A", "A")
507507
EQ("", "", "replace", "", "", 100)
508+
EQ("A", "", "replace", "", "A", 100)
508509
EQ("", "", "replace", "", "", sys.maxsize)
509510

510511
# interleave (from=="", 'to' gets inserted everywhere)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
``"".replace("", s, n)`` now returns ``s`` instead of an empty string for
2+
all non-zero ``n``. There are similar changes for :class:`bytes` and
3+
:class:`bytearray` objects.

Objects/stringlib/transmogrify.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -680,9 +680,13 @@ stringlib_replace(PyObject *self,
680680
const char *to_s, Py_ssize_t to_len,
681681
Py_ssize_t maxcount)
682682
{
683+
if (STRINGLIB_LEN(self) < from_len) {
684+
/* nothing to do; return the original bytes */
685+
return return_self(self);
686+
}
683687
if (maxcount < 0) {
684688
maxcount = PY_SSIZE_T_MAX;
685-
} else if (maxcount == 0 || STRINGLIB_LEN(self) == 0) {
689+
} else if (maxcount == 0) {
686690
/* nothing to do; return the original bytes */
687691
return return_self(self);
688692
}
@@ -699,13 +703,6 @@ stringlib_replace(PyObject *self,
699703
return stringlib_replace_interleave(self, to_s, to_len, maxcount);
700704
}
701705

702-
/* Except for b"".replace(b"", b"A") == b"A" there is no way beyond this */
703-
/* point for an empty self bytes to generate a non-empty bytes */
704-
/* Special case so the remaining code always gets a non-empty bytes */
705-
if (STRINGLIB_LEN(self) == 0) {
706-
return return_self(self);
707-
}
708-
709706
if (to_len == 0) {
710707
/* delete all occurrences of 'from' bytes */
711708
if (from_len == 1) {

Objects/unicodeobject.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10572,9 +10572,12 @@ replace(PyObject *self, PyObject *str1,
1057210572
int mayshrink;
1057310573
Py_UCS4 maxchar, maxchar_str1, maxchar_str2;
1057410574

10575+
if (slen < len1)
10576+
goto nothing;
10577+
1057510578
if (maxcount < 0)
1057610579
maxcount = PY_SSIZE_T_MAX;
10577-
else if (maxcount == 0 || slen == 0)
10580+
else if (maxcount == 0)
1057810581
goto nothing;
1057910582

1058010583
if (str1 == str2)

0 commit comments

Comments
 (0)