From 1ef5f557c3512b7f6ddfb7ddc6fa9507573713fe Mon Sep 17 00:00:00 2001 From: Martijn Pieters Date: Sun, 12 Feb 2017 15:10:50 +0000 Subject: [PATCH 1/2] Support __rmod__ for RHS subclasses of str in % string formatting operations. When you use `'%s' % SubClassOfStr()`, where `SubClassOfStr.__rmod__` exists, the reverse operation is ignored as normally such string formatting operations use the `PyUnicode_Format()` fast path. This patch tests for subclasses of `str` first and picks the slow path in that case. Fixes issue28598. --- Lib/test/test_unicode.py | 9 +++++++++ Misc/NEWS | 2 ++ Python/ceval.c | 12 +++++++++--- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index b1f7c8966aa11c..f70504c11afdc0 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -1448,6 +1448,15 @@ def test_formatting_huge_precision(self): 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 diff --git a/Misc/NEWS b/Misc/NEWS index eb870b7d48b76b..0038a126505fde 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ What's New in Python 3.7.0 alpha 1? Core and Builtins ----------------- +- Issue #28598: Support __rmod__ for subclasses of str being called before str.__mod__. + - bpo-29438: Fixed use-after-free problem in key sharing dict. - Issue #29319: Prevent RunMainFromImporter overwriting sys.path[0]. diff --git a/Python/ceval.c b/Python/ceval.c index 58007793bb9de0..871e14a6e8caca 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1355,9 +1355,15 @@ _PyEval_EvalFrameDefault(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); From 7b19b0265145eb3d7017569a2522cbd14a9f6072 Mon Sep 17 00:00:00 2001 From: Martijn Pieters Date: Sun, 12 Feb 2017 17:34:41 +0000 Subject: [PATCH 2/2] Address review comments; reduce negations and credit patch --- Misc/NEWS | 3 ++- Python/ceval.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 0038a126505fde..964ce01c38882e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,7 +10,8 @@ What's New in Python 3.7.0 alpha 1? Core and Builtins ----------------- -- Issue #28598: Support __rmod__ for subclasses of str being called before str.__mod__. +- Issue #28598: Support __rmod__ for subclasses of str being called before + str.__mod__. Patch by Martijn Pieters. - bpo-29438: Fixed use-after-free problem in key sharing dict. diff --git a/Python/ceval.c b/Python/ceval.c index 871e14a6e8caca..b6347e436e0ea1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1356,8 +1356,8 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) PyObject *divisor = POP(); PyObject *dividend = TOP(); PyObject *res; - if (PyUnicode_CheckExact(dividend) && !( - PyUnicode_Check(divisor) && !PyUnicode_CheckExact(divisor))) { + 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); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy