]> granicus.if.org Git - python/commitdiff
Added test cases for string.Formatter subclassing.
authorEric Smith <eric@trueblade.com>
Fri, 31 Aug 2007 01:14:01 +0000 (01:14 +0000)
committerEric Smith <eric@trueblade.com>
Fri, 31 Aug 2007 01:14:01 +0000 (01:14 +0000)
Made format_spec parameter to builtin format optional, defaults to
empty string.  Added test cases.

Lib/test/test_builtin.py
Lib/test/test_string.py
Python/bltinmodule.c

index e5957ae0d77315e5828bce33013f68d8e7753a96..1a9781b7d79aca176035e51b6878c1ecc3ee4286 100644 (file)
@@ -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(), "")
index 1706d2a4a3a8b6e3d837c012569ec4bf78c65129..3ecc4d80635a2bc3622ffa859762c9dd59dc2b6c 100644 (file)
@@ -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'
 
index b0b85ba0d9467e9894d1daeb432d8634eeb00014..d32b0099471b621d79a65623eca5e80d4e002216 100644 (file)
@@ -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)