[Python-checkins] bpo-28029: Make "".replace("", s, n) returning s for any n != 0. (GH-16981)

Serhiy Storchaka webhook-mailer at python.org
Wed Oct 30 06:03:57 EDT 2019


https://github.com/python/cpython/commit/865c3b257fe38154a4320c7ee6afb416f665b9c2
commit: 865c3b257fe38154a4320c7ee6afb416f665b9c2
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2019-10-30T12:03:53+02:00
summary:

bpo-28029: Make "".replace("", s, n) returning s for any n != 0. (GH-16981)

files:
A Misc/NEWS.d/next/Core and Builtins/2019-10-29-09-38-54.bpo-28029.AmRMEF.rst
M Doc/whatsnew/3.9.rst
M Lib/test/string_tests.py
M Objects/stringlib/transmogrify.h
M Objects/unicodeobject.c

diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst
index bca222955668d..d41e70808d6e1 100644
--- a/Doc/whatsnew/3.9.rst
+++ b/Doc/whatsnew/3.9.rst
@@ -99,6 +99,11 @@ Other Language Changes
   ignored for empty strings.
   (Contributed by Victor Stinner in :issue:`37388`.)
 
+* ``"".replace("", s, n)`` now returns ``s`` instead of an empty string for
+  all non-zero ``n``.  It is now consistent with ``"".replace("", s)``.
+  There are similar changes for :class:`bytes` and :class:`bytearray` objects.
+  (Contributed by Serhiy Storchaka in :issue:`28029`.)
+
 
 New Modules
 ===========
diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py
index 38da941f7f50e..948e2a3c3c56b 100644
--- a/Lib/test/string_tests.py
+++ b/Lib/test/string_tests.py
@@ -505,6 +505,7 @@ def test_replace(self):
         EQ("", "", "replace", "A", "")
         EQ("", "", "replace", "A", "A")
         EQ("", "", "replace", "", "", 100)
+        EQ("A", "", "replace", "", "A", 100)
         EQ("", "", "replace", "", "", sys.maxsize)
 
         # interleave (from=="", 'to' gets inserted everywhere)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-10-29-09-38-54.bpo-28029.AmRMEF.rst b/Misc/NEWS.d/next/Core and Builtins/2019-10-29-09-38-54.bpo-28029.AmRMEF.rst
new file mode 100644
index 0000000000000..420e53aec9be0
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-10-29-09-38-54.bpo-28029.AmRMEF.rst	
@@ -0,0 +1,3 @@
+``"".replace("", s, n)`` now returns ``s`` instead of an empty string for
+all non-zero ``n``.  There are similar changes for :class:`bytes` and
+:class:`bytearray` objects.
diff --git a/Objects/stringlib/transmogrify.h b/Objects/stringlib/transmogrify.h
index 9506019d5af2b..e1165ea38e825 100644
--- a/Objects/stringlib/transmogrify.h
+++ b/Objects/stringlib/transmogrify.h
@@ -680,9 +680,13 @@ stringlib_replace(PyObject *self,
                   const char *to_s, Py_ssize_t to_len,
                   Py_ssize_t maxcount)
 {
+    if (STRINGLIB_LEN(self) < from_len) {
+        /* nothing to do; return the original bytes */
+        return return_self(self);
+    }
     if (maxcount < 0) {
         maxcount = PY_SSIZE_T_MAX;
-    } else if (maxcount == 0 || STRINGLIB_LEN(self) == 0) {
+    } else if (maxcount == 0) {
         /* nothing to do; return the original bytes */
         return return_self(self);
     }
@@ -699,13 +703,6 @@ stringlib_replace(PyObject *self,
         return stringlib_replace_interleave(self, to_s, to_len, maxcount);
     }
 
-    /* Except for b"".replace(b"", b"A") == b"A" there is no way beyond this */
-    /* point for an empty self bytes to generate a non-empty bytes */
-    /* Special case so the remaining code always gets a non-empty bytes */
-    if (STRINGLIB_LEN(self) == 0) {
-        return return_self(self);
-    }
-
     if (to_len == 0) {
         /* delete all occurrences of 'from' bytes */
         if (from_len == 1) {
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 2d60627b19193..5ae0af8ea336a 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -10572,9 +10572,12 @@ replace(PyObject *self, PyObject *str1,
     int mayshrink;
     Py_UCS4 maxchar, maxchar_str1, maxchar_str2;
 
+    if (slen < len1)
+        goto nothing;
+
     if (maxcount < 0)
         maxcount = PY_SSIZE_T_MAX;
-    else if (maxcount == 0 || slen == 0)
+    else if (maxcount == 0)
         goto nothing;
 
     if (str1 == str2)



More information about the Python-checkins mailing list