mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
Issue #28385: An error message when non-empty format spec is passed to
object.__format__ now contains the name of actual type.
This commit is contained in:
parent
c9b750d249
commit
d1af5effc2
3 changed files with 29 additions and 32 deletions
|
@ -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):
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# 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):
|
||||||
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
|
||||||
|
|
|
@ -1259,6 +1259,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)
|
||||||
|
|
|
@ -4318,13 +4318,6 @@ PyDoc_STRVAR(object_subclasshook_doc,
|
||||||
"NotImplemented, the normal algorithm is used. Otherwise, it\n"
|
"NotImplemented, the normal algorithm is used. Otherwise, it\n"
|
||||||
"overrides the normal algorithm (and the outcome is cached).\n");
|
"overrides the normal algorithm (and the outcome is cached).\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)
|
||||||
{
|
{
|
||||||
|
@ -4335,22 +4328,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue