cpython (merge 3.5 -> 3.6): Issue #28385: An error message when non-empty format spec is passed to
https://hg.python.org/cpython/rev/0a985f7c6731 changeset: 104829:0a985f7c6731 branch: 3.6 parent: 104826:f1abc92a756a parent: 104828:92cae79fa5d9 user: Serhiy Storchaka <storchaka@gmail.com> date: Sun Oct 30 19:37:46 2016 +0200 summary: Issue #28385: An error message when non-empty format spec is passed to object.__format__ now contains the name of actual type. files: Lib/test/test_builtin.py | 24 ++++++++++------------ Lib/test/test_bytes.py | 9 ++++++++ Objects/typeobject.c | 30 +++++++++------------------ 3 files changed, 30 insertions(+), 33 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -11,6 +11,7 @@ import pickle import platform import random +import re import sys import traceback import types @@ -1447,21 +1448,14 @@ # -------------------------------------------------------------------- # Issue #7994: object.__format__ with a non-empty format string is - # deprecated - def test_deprecated_format_string(obj, fmt_str, should_raise): - if should_raise: - self.assertRaises(TypeError, format, obj, fmt_str) - else: - format(obj, fmt_str) - - fmt_strs = ['', 's'] - + # disallowed class A: def __format__(self, fmt_str): return format('', fmt_str) - for fmt_str in fmt_strs: - test_deprecated_format_string(A(), fmt_str, False) + self.assertEqual(format(A()), '') + self.assertEqual(format(A(), ''), '') + self.assertEqual(format(A(), 's'), '') class B: pass @@ -1470,8 +1464,12 @@ pass for cls in [object, B, C]: - for fmt_str in fmt_strs: - test_deprecated_format_string(cls(), fmt_str, len(fmt_str) != 0) + obj = cls() + self.assertEqual(format(obj), str(obj)) + self.assertEqual(format(obj, ''), str(obj)) + with self.assertRaisesRegex(TypeError, + r'\b%s\b' % re.escape(cls.__name__)): + format(obj, 's') # -------------------------------------------------------------------- # make sure we can take a subclass of str as a format spec diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -1416,6 +1416,15 @@ self.assertEqual(f(b"'"), '''b"'"''') # ''' self.assertEqual(f(b"'\""), r"""b'\'"'""") # ' + @check_bytes_warnings + def test_format(self): + for b in b'abc', bytearray(b'abc'): + self.assertEqual(format(b), str(b)) + self.assertEqual(format(b, ''), str(b)) + with self.assertRaisesRegex(TypeError, + r'\b%s\b' % re.escape(type(b).__name__)): + format(b, 's') + def test_compare_bytes_to_bytearray(self): self.assertEqual(b"abc" == bytes(b"abc"), True) self.assertEqual(b"ab" != bytes(b"abc"), True) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4392,13 +4392,6 @@ "The default implementation does nothing. It may be\n" "overridden to extend subclasses.\n"); -/* - from PEP 3101, this code implements: - - class object: - def __format__(self, format_spec): - return format(str(self), format_spec) -*/ static PyObject * object_format(PyObject *self, PyObject *args) { @@ -4409,22 +4402,19 @@ if (!PyArg_ParseTuple(args, "U:__format__", &format_spec)) return NULL; + /* Issue 7994: If we're converting to a string, we + should reject format specifications */ + if (PyUnicode_GET_LENGTH(format_spec) > 0) { + PyErr_Format(PyExc_TypeError, + "unsupported format string passed to %.200s.__format__", + self->ob_type->tp_name); + return NULL; + } self_as_str = PyObject_Str(self); if (self_as_str != NULL) { - /* Issue 7994: If we're converting to a string, we - should reject format specifications */ - if (PyUnicode_GET_LENGTH(format_spec) > 0) { - PyErr_SetString(PyExc_TypeError, - "non-empty format string passed to object.__format__"); - goto done; - } - result = PyObject_Format(self_as_str, format_spec); - } - -done: - Py_XDECREF(self_as_str); - + Py_DECREF(self_as_str); + } return result; } -- Repository URL: https://hg.python.org/cpython
participants (1)
-
serhiy.storchaka