File tree Expand file tree Collapse file tree 3 files changed +21
-3
lines changed Expand file tree Collapse file tree 3 files changed +21
-3
lines changed Original file line number Diff line number Diff line change @@ -1424,6 +1424,15 @@ def test_formatting_huge_precision(self):
1424
1424
with self .assertRaises (ValueError ):
1425
1425
result = format_string % 2.34
1426
1426
1427
+ def test_issue28598_strsubclass_rhs (self ):
1428
+ # A subclass of str with an __rmod__ method should be able to hook
1429
+ # into the % operator
1430
+ class SubclassedStr (str ):
1431
+ def __rmod__ (self , other ):
1432
+ return 'Success, self.__rmod__({!r}) was called' .format (other )
1433
+ self .assertEqual ('lhs %% %r' % SubclassedStr ('rhs' ),
1434
+ "Success, self.__rmod__('lhs %% %r') was called" )
1435
+
1427
1436
@support .cpython_only
1428
1437
def test_formatting_huge_precision_c_limits (self ):
1429
1438
from _testcapi import INT_MAX
Original file line number Diff line number Diff line change @@ -10,6 +10,9 @@ Release date: XXXX-XX-XX
10
10
Core and Builtins
11
11
-----------------
12
12
13
+ - Issue #28598: Support __rmod__ for subclasses of str being called before
14
+ str.__mod__. Patch by Martijn Pieters.
15
+
13
16
- bpo-29602: Fix incorrect handling of signed zeros in complex constructor for
14
17
complex subclasses and for inputs having a __complex__ method. Patch
15
18
by Serhiy Storchaka.
Original file line number Diff line number Diff line change @@ -1545,9 +1545,15 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
1545
1545
TARGET (BINARY_MODULO ) {
1546
1546
PyObject * divisor = POP ();
1547
1547
PyObject * dividend = TOP ();
1548
- PyObject * res = PyUnicode_CheckExact (dividend ) ?
1549
- PyUnicode_Format (dividend , divisor ) :
1550
- PyNumber_Remainder (dividend , divisor );
1548
+ PyObject * res ;
1549
+ if (PyUnicode_CheckExact (dividend ) && (
1550
+ !PyUnicode_Check (divisor ) || PyUnicode_CheckExact (divisor ))) {
1551
+ /* fast path; string formatting, but not if the RHS is a str subclass
1552
+ (see issue28598) */
1553
+ res = PyUnicode_Format (dividend , divisor );
1554
+ } else {
1555
+ res = PyNumber_Remainder (dividend , divisor );
1556
+ }
1551
1557
Py_DECREF (divisor );
1552
1558
Py_DECREF (dividend );
1553
1559
SET_TOP (res );
You can’t perform that action at this time.
0 commit comments