From 81936699c8c556db29c24a86dfa411189270233f Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Fri, 31 Aug 2007 01:14:01 +0000 Subject: Added test cases for string.Formatter subclassing. Made format_spec parameter to builtin format optional, defaults to empty string. Added test cases. --- Lib/test/test_builtin.py | 23 +++++++++++++++-------- Lib/test/test_string.py | 38 ++++++++++++++++++++++++++++++++++++++ Python/bltinmodule.c | 35 +++++++++++++++++++++++------------ 3 files changed, 76 insertions(+), 20 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index e5957ae..1a9781b 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -532,15 +532,22 @@ class BuiltinTest(unittest.TestCase): self.assertEqual(format(3, ''), '3') 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) - self.assertEqual(format(17**13, ""), str(17**13)) - self.assertEqual(format(1.0, ""), str(1.0)) - self.assertEqual(format(3.1415e104, ""), str(3.1415e104)) - self.assertEqual(format(-3.1415e104, ""), str(-3.1415e104)) - self.assertEqual(format(3.1415e-104, ""), str(3.1415e-104)) - self.assertEqual(format(-3.1415e-104, ""), str(-3.1415e-104)) - self.assertEqual(format(object, ""), str(object)) - self.assertEqual(format(None, ""), str(None)) + empty_format_spec(17**13) + empty_format_spec(1.0) + empty_format_spec(3.1415e104) + empty_format_spec(-3.1415e104) + empty_format_spec(3.1415e-104) + empty_format_spec(-3.1415e-104) + empty_format_spec(object) + empty_format_spec(None) # TypeError because self.__format__ returns the wrong type self.assertRaises(TypeError, format, H(), "") diff --git a/Lib/test/test_string.py b/Lib/test/test_string.py index 1706d2a..3ecc4d8 100644 --- a/Lib/test/test_string.py +++ b/Lib/test/test_string.py @@ -23,6 +23,7 @@ class ModuleTest(unittest.TestCase): self.assertEqual(fmt.format("foo{1}{0}-{1}", "bar", 6), "foo6bar-6") self.assertEqual(fmt.format("-{arg!r}-", arg='test'), "-'test'-") + # override get_value ############################################ class NamespaceFormatter(string.Formatter): def __init__(self, namespace={}): string.Formatter.__init__(self) @@ -42,6 +43,43 @@ class ModuleTest(unittest.TestCase): 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): 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' diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index b0b85ba..d32b009 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -280,25 +280,32 @@ builtin_format(PyObject *self, PyObject *args) { static PyObject * format_str = NULL; PyObject *value; - PyObject *spec; + PyObject *spec = NULL; PyObject *meth; - PyObject *result; + PyObject *empty = NULL; + PyObject *result = NULL; /* Initialize cached value */ if (format_str == NULL) { /* Initialize static variable needed by _PyType_Lookup */ format_str = PyUnicode_FromString("__format__"); if (format_str == NULL) - return NULL; + goto done; } - if (!PyArg_ParseTuple(args, "OO:format", &value, &spec)) - return NULL; + if (!PyArg_ParseTuple(args, "O|O:format", &value, &spec)) + 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 */ if (Py_Type(value)->tp_dict == NULL) if (PyType_Ready(Py_Type(value)) < 0) - return NULL; + goto done; /* Find the (unbound!) __format__ method (a borrowed reference) */ meth = _PyType_Lookup(Py_Type(value), format_str); @@ -306,27 +313,31 @@ builtin_format(PyObject *self, PyObject *args) PyErr_Format(PyExc_TypeError, "Type %.100s doesn't define __format__", Py_Type(value)->tp_name); - return NULL; + goto done; } /* And call it, binding it to the value */ result = PyObject_CallFunctionObjArgs(meth, value, spec, NULL); - if (result && !PyUnicode_Check(result)) { + if (result && !PyUnicode_Check(result)) { PyErr_SetString(PyExc_TypeError, "__format__ method did not return string"); Py_DECREF(result); - return NULL; + result = NULL; + goto done; } +done: + Py_XDECREF(empty); return result; } - PyDoc_STRVAR(format_doc, -"format(value, format_spec) -> string\n\ +"format(value[, format_spec]) -> string\n\ \n\ -Returns value.__format__(format_spec)."); +Returns value.__format__(format_spec)\n\ +format_spec defaults to \"\""); + static PyObject * builtin_chr8(PyObject *self, PyObject *args) -- cgit v0.12