Commit caa41551 authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #28385: An error message when non-empty format spec is passed to

object.__format__ now contains the name of actual type.
parents d7958a71 354ab1ef
...@@ -11,6 +11,7 @@ import os ...@@ -11,6 +11,7 @@ import os
import pickle import pickle
import platform import platform
import random import random
import re
import sys import sys
import traceback import traceback
import types import types
...@@ -1447,21 +1448,14 @@ class BuiltinTest(unittest.TestCase): ...@@ -1447,21 +1448,14 @@ class BuiltinTest(unittest.TestCase):
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Issue #7994: object.__format__ with a non-empty format string is # Issue #7994: object.__format__ with a non-empty format string is
# deprecated # disallowed
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']
class A: class A:
def __format__(self, fmt_str): def __format__(self, fmt_str):
return format('', fmt_str) return format('', fmt_str)
for fmt_str in fmt_strs: self.assertEqual(format(A()), '')
test_deprecated_format_string(A(), fmt_str, False) self.assertEqual(format(A(), ''), '')
self.assertEqual(format(A(), 's'), '')
class B: class B:
pass pass
...@@ -1470,8 +1464,12 @@ class BuiltinTest(unittest.TestCase): ...@@ -1470,8 +1464,12 @@ class BuiltinTest(unittest.TestCase):
pass pass
for cls in [object, B, C]: for cls in [object, B, C]:
for fmt_str in fmt_strs: obj = cls()
test_deprecated_format_string(cls(), fmt_str, len(fmt_str) != 0) 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 # make sure we can take a subclass of str as a format spec
......
...@@ -1416,6 +1416,15 @@ class AssortedBytesTest(unittest.TestCase): ...@@ -1416,6 +1416,15 @@ class AssortedBytesTest(unittest.TestCase):
self.assertEqual(f(b"'"), '''b"'"''') # ''' self.assertEqual(f(b"'"), '''b"'"''') # '''
self.assertEqual(f(b"'\""), r"""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): def test_compare_bytes_to_bytearray(self):
self.assertEqual(b"abc" == bytes(b"abc"), True) self.assertEqual(b"abc" == bytes(b"abc"), True)
self.assertEqual(b"ab" != bytes(b"abc"), True) self.assertEqual(b"ab" != bytes(b"abc"), True)
......
...@@ -4392,13 +4392,6 @@ PyDoc_STRVAR(object_init_subclass_doc, ...@@ -4392,13 +4392,6 @@ PyDoc_STRVAR(object_init_subclass_doc,
"The default implementation does nothing. It may be\n" "The default implementation does nothing. It may be\n"
"overridden to extend subclasses.\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 * static PyObject *
object_format(PyObject *self, PyObject *args) object_format(PyObject *self, PyObject *args)
{ {
...@@ -4409,22 +4402,19 @@ object_format(PyObject *self, PyObject *args) ...@@ -4409,22 +4402,19 @@ object_format(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "U:__format__", &format_spec)) if (!PyArg_ParseTuple(args, "U:__format__", &format_spec))
return NULL; 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); self_as_str = PyObject_Str(self);
if (self_as_str != NULL) { 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); result = PyObject_Format(self_as_str, format_spec);
Py_DECREF(self_as_str);
} }
done:
Py_XDECREF(self_as_str);
return result; return result;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment