]> granicus.if.org Git - python/commitdiff
bpo-28598: Support __rmod__ for RHS subclasses of str in % string formatting operatio...
authorMartijn Pieters <github.com@zopatista.com>
Mon, 27 Feb 2017 16:07:27 +0000 (16:07 +0000)
committerBerker Peksag <berker.peksag@gmail.com>
Mon, 27 Feb 2017 16:07:27 +0000 (19:07 +0300)
Lib/test/test_unicode.py
Misc/NEWS
Python/ceval.c

index 3136ea1a1bad3eea9c60fc486ea5a7822b002cde..9dbded2d99c5309cc3a8ed32b38ea63de35f44e1 100644 (file)
@@ -1424,6 +1424,15 @@ class UnicodeTest(string_tests.CommonTest,
         with self.assertRaises(ValueError):
             result = format_string % 2.34
 
+    def test_issue28598_strsubclass_rhs(self):
+        # A subclass of str with an __rmod__ method should be able to hook
+        # into the % operator
+        class SubclassedStr(str):
+            def __rmod__(self, other):
+                return 'Success, self.__rmod__({!r}) was called'.format(other)
+        self.assertEqual('lhs %% %r' % SubclassedStr('rhs'),
+                         "Success, self.__rmod__('lhs %% %r') was called")
+
     @support.cpython_only
     def test_formatting_huge_precision_c_limits(self):
         from _testcapi import INT_MAX
index 635f413dc74be89296278c4df99a1989d7140469..fd25a5f325077e28ed8fa7335d1d2f7fa4054fbf 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Release date: XXXX-XX-XX
 Core and Builtins
 -----------------
 
+- Issue #28598: Support __rmod__ for subclasses of str being called before
+  str.__mod__.  Patch by Martijn Pieters.
+
 - bpo-29602: Fix incorrect handling of signed zeros in complex constructor for
   complex subclasses and for inputs having a __complex__ method. Patch
   by Serhiy Storchaka.
index 7b405188d38c662696fcd1638bac05767a8b698f..d3239089284c481065df9209e95695f780f43cc7 100644 (file)
@@ -1545,9 +1545,15 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
         TARGET(BINARY_MODULO) {
             PyObject *divisor = POP();
             PyObject *dividend = TOP();
-            PyObject *res = PyUnicode_CheckExact(dividend) ?
-                PyUnicode_Format(dividend, divisor) :
-                PyNumber_Remainder(dividend, divisor);
+            PyObject *res;
+            if (PyUnicode_CheckExact(dividend) && (
+                  !PyUnicode_Check(divisor) || PyUnicode_CheckExact(divisor))) {
+              /* fast path; string formatting, but not if the RHS is a str subclass
+                 (see issue28598) */
+              res = PyUnicode_Format(dividend, divisor);
+            } else {
+              res = PyNumber_Remainder(dividend, divisor);
+            }
             Py_DECREF(divisor);
             Py_DECREF(dividend);
             SET_TOP(res);