mirror of
https://github.com/python/cpython.git
synced 2025-09-09 18:32:22 +00:00
Added test cases for string.Formatter subclassing.
Made format_spec parameter to builtin format optional, defaults to empty string. Added test cases.
This commit is contained in:
parent
231ff0ec11
commit
81936699c8
3 changed files with 76 additions and 20 deletions
|
@ -532,15 +532,22 @@ class BuiltinTest(unittest.TestCase):
|
||||||
self.assertEqual(format(3, ''), '3')
|
self.assertEqual(format(3, ''), '3')
|
||||||
self.assertEqual(format(A(3), 'spec'), '3spec')
|
self.assertEqual(format(A(3), 'spec'), '3spec')
|
||||||
|
|
||||||
|
def empty_format_spec(value):
|
||||||
|
# test that:
|
||||||
|
# format(x, '') == str(x)
|
||||||
|
# format(x) == str(x)
|
||||||
|
self.assertEqual(format(value, ""), str(value))
|
||||||
|
self.assertEqual(format(value), str(value))
|
||||||
|
|
||||||
# for builtin types, format(x, "") == str(x)
|
# for builtin types, format(x, "") == str(x)
|
||||||
self.assertEqual(format(17**13, ""), str(17**13))
|
empty_format_spec(17**13)
|
||||||
self.assertEqual(format(1.0, ""), str(1.0))
|
empty_format_spec(1.0)
|
||||||
self.assertEqual(format(3.1415e104, ""), str(3.1415e104))
|
empty_format_spec(3.1415e104)
|
||||||
self.assertEqual(format(-3.1415e104, ""), str(-3.1415e104))
|
empty_format_spec(-3.1415e104)
|
||||||
self.assertEqual(format(3.1415e-104, ""), str(3.1415e-104))
|
empty_format_spec(3.1415e-104)
|
||||||
self.assertEqual(format(-3.1415e-104, ""), str(-3.1415e-104))
|
empty_format_spec(-3.1415e-104)
|
||||||
self.assertEqual(format(object, ""), str(object))
|
empty_format_spec(object)
|
||||||
self.assertEqual(format(None, ""), str(None))
|
empty_format_spec(None)
|
||||||
|
|
||||||
# TypeError because self.__format__ returns the wrong type
|
# TypeError because self.__format__ returns the wrong type
|
||||||
self.assertRaises(TypeError, format, H(), "")
|
self.assertRaises(TypeError, format, H(), "")
|
||||||
|
|
|
@ -23,6 +23,7 @@ class ModuleTest(unittest.TestCase):
|
||||||
self.assertEqual(fmt.format("foo{1}{0}-{1}", "bar", 6), "foo6bar-6")
|
self.assertEqual(fmt.format("foo{1}{0}-{1}", "bar", 6), "foo6bar-6")
|
||||||
self.assertEqual(fmt.format("-{arg!r}-", arg='test'), "-'test'-")
|
self.assertEqual(fmt.format("-{arg!r}-", arg='test'), "-'test'-")
|
||||||
|
|
||||||
|
# override get_value ############################################
|
||||||
class NamespaceFormatter(string.Formatter):
|
class NamespaceFormatter(string.Formatter):
|
||||||
def __init__(self, namespace={}):
|
def __init__(self, namespace={}):
|
||||||
string.Formatter.__init__(self)
|
string.Formatter.__init__(self)
|
||||||
|
@ -42,6 +43,43 @@ class ModuleTest(unittest.TestCase):
|
||||||
self.assertEqual(fmt.format("{greeting}, world!"), 'hello, world!')
|
self.assertEqual(fmt.format("{greeting}, world!"), 'hello, world!')
|
||||||
|
|
||||||
|
|
||||||
|
# override format_field #########################################
|
||||||
|
class CallFormatter(string.Formatter):
|
||||||
|
def format_field(self, value, format_spec):
|
||||||
|
return format(value(), format_spec)
|
||||||
|
|
||||||
|
fmt = CallFormatter()
|
||||||
|
self.assertEqual(fmt.format('*{0}*', lambda : 'result'), '*result*')
|
||||||
|
|
||||||
|
|
||||||
|
# override convert_field ########################################
|
||||||
|
class XFormatter(string.Formatter):
|
||||||
|
def convert_field(self, value, conversion):
|
||||||
|
if conversion == 'x':
|
||||||
|
return None
|
||||||
|
return super(XFormatter, self).convert_field(value, conversion)
|
||||||
|
|
||||||
|
fmt = XFormatter()
|
||||||
|
self.assertEqual(fmt.format("{0!r}:{0!x}", 'foo', 'foo'), "'foo':None")
|
||||||
|
|
||||||
|
|
||||||
|
# override parse ################################################
|
||||||
|
class BarFormatter(string.Formatter):
|
||||||
|
# returns an iterable that contains tuples of the form:
|
||||||
|
# (literal_text, field_name, format_spec, conversion)
|
||||||
|
def parse(self, format_string):
|
||||||
|
for field in format_string.split('|'):
|
||||||
|
if field[0] == '+':
|
||||||
|
# it's markup
|
||||||
|
field_name, _, format_spec = field[1:].partition(':')
|
||||||
|
yield '', field_name, format_spec, None
|
||||||
|
else:
|
||||||
|
yield field, None, None, None
|
||||||
|
|
||||||
|
fmt = BarFormatter()
|
||||||
|
self.assertEqual(fmt.format('*|+0:^10s|*', 'foo'), '* foo *')
|
||||||
|
|
||||||
|
|
||||||
def test_maketrans(self):
|
def test_maketrans(self):
|
||||||
transtable = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377'
|
transtable = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377'
|
||||||
|
|
||||||
|
|
|
@ -280,25 +280,32 @@ builtin_format(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
static PyObject * format_str = NULL;
|
static PyObject * format_str = NULL;
|
||||||
PyObject *value;
|
PyObject *value;
|
||||||
PyObject *spec;
|
PyObject *spec = NULL;
|
||||||
PyObject *meth;
|
PyObject *meth;
|
||||||
PyObject *result;
|
PyObject *empty = NULL;
|
||||||
|
PyObject *result = NULL;
|
||||||
|
|
||||||
/* Initialize cached value */
|
/* Initialize cached value */
|
||||||
if (format_str == NULL) {
|
if (format_str == NULL) {
|
||||||
/* Initialize static variable needed by _PyType_Lookup */
|
/* Initialize static variable needed by _PyType_Lookup */
|
||||||
format_str = PyUnicode_FromString("__format__");
|
format_str = PyUnicode_FromString("__format__");
|
||||||
if (format_str == NULL)
|
if (format_str == NULL)
|
||||||
return NULL;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "OO:format", &value, &spec))
|
if (!PyArg_ParseTuple(args, "O|O:format", &value, &spec))
|
||||||
return NULL;
|
goto done;
|
||||||
|
|
||||||
|
/* initialize the default value */
|
||||||
|
if (spec == NULL) {
|
||||||
|
empty = PyUnicode_FromUnicode(NULL, 0);
|
||||||
|
spec = empty;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure the type is initialized. float gets initialized late */
|
/* Make sure the type is initialized. float gets initialized late */
|
||||||
if (Py_Type(value)->tp_dict == NULL)
|
if (Py_Type(value)->tp_dict == NULL)
|
||||||
if (PyType_Ready(Py_Type(value)) < 0)
|
if (PyType_Ready(Py_Type(value)) < 0)
|
||||||
return NULL;
|
goto done;
|
||||||
|
|
||||||
/* Find the (unbound!) __format__ method (a borrowed reference) */
|
/* Find the (unbound!) __format__ method (a borrowed reference) */
|
||||||
meth = _PyType_Lookup(Py_Type(value), format_str);
|
meth = _PyType_Lookup(Py_Type(value), format_str);
|
||||||
|
@ -306,27 +313,31 @@ builtin_format(PyObject *self, PyObject *args)
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"Type %.100s doesn't define __format__",
|
"Type %.100s doesn't define __format__",
|
||||||
Py_Type(value)->tp_name);
|
Py_Type(value)->tp_name);
|
||||||
return NULL;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And call it, binding it to the value */
|
/* And call it, binding it to the value */
|
||||||
result = PyObject_CallFunctionObjArgs(meth, value, spec, NULL);
|
result = PyObject_CallFunctionObjArgs(meth, value, spec, NULL);
|
||||||
|
|
||||||
if (result && !PyUnicode_Check(result)) {
|
if (result && !PyUnicode_Check(result)) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"__format__ method did not return string");
|
"__format__ method did not return string");
|
||||||
Py_DECREF(result);
|
Py_DECREF(result);
|
||||||
return NULL;
|
result = NULL;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
Py_XDECREF(empty);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(format_doc,
|
PyDoc_STRVAR(format_doc,
|
||||||
"format(value, format_spec) -> string\n\
|
"format(value[, format_spec]) -> string\n\
|
||||||
\n\
|
\n\
|
||||||
Returns value.__format__(format_spec).");
|
Returns value.__format__(format_spec)\n\
|
||||||
|
format_spec defaults to \"\"");
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
builtin_chr8(PyObject *self, PyObject *args)
|
builtin_chr8(PyObject *self, PyObject *args)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue