]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Changed some ValueError's to KeyError and IndexError.
authorEric Smith <eric@trueblade.com>
Tue, 4 Sep 2007 23:04:22 +0000 (23:04 +0000)
committerEric Smith <eric@trueblade.com>
Tue, 4 Sep 2007 23:04:22 +0000 (23:04 +0000)
Corrected code for invalid conversion specifier.
Added tests to verify.

Modified string.Formatter to correctly expand format_spec's,
and added a limit to recursion depth.  Added _vformat()
method to support both of these.

Lib/string.py
Lib/test/test_unicode.py
Objects/stringlib/string_format.h

index 9b00a62e88b33ff9e18aef482ecf7c1d9b7e1fc1..03179fbb44a23d662483efdf0814799ef8ca1818 100644 (file)
@@ -202,6 +202,13 @@ class Formatter:
 
     def vformat(self, format_string, args, kwargs):
         used_args = set()
+        result = self._vformat(format_string, args, kwargs, used_args, 2)
+        self.check_unused_args(used_args, args, kwargs)
+        return result
+
+    def _vformat(self, format_string, args, kwargs, used_args, recursion_depth):
+        if recursion_depth < 0:
+            raise ValueError('Max string recursion exceeded')
         result = []
         for literal_text, field_name, format_spec, conversion in \
                 self.parse(format_string):
@@ -223,10 +230,13 @@ class Formatter:
                 # do any conversion on the resulting object
                 obj = self.convert_field(obj, conversion)
 
+                # expand the format spec, if needed
+                format_spec = self._vformat(format_spec, args, kwargs,
+                                            used_args, recursion_depth-1)
+
                 # format the object and append to the result
                 result.append(self.format_field(obj, format_spec))
 
-        self.check_unused_args(used_args, args, kwargs)
         return ''.join(result)
 
 
@@ -251,9 +261,9 @@ class Formatter:
             return repr(value)
         elif conversion == 's':
             return str(value)
-        else:
-            assert conversion is None
+        elif conversion is None:
             return value
+        raise ValueError("Unknown converion specifier {0!s}".format(conversion))
 
 
     # returns an iterable that contains tuples of the form:
index 52b7b4fff861ef0118287fe9e1bbb0f52ba0745f..64cca3f18fd0a187f197510bfd669888405dc614 100644 (file)
@@ -542,29 +542,30 @@ class UnicodeTest(
         self.assertRaises(ValueError, 'a}'.format)
         self.assertRaises(ValueError, '{a'.format)
         self.assertRaises(ValueError, '}a'.format)
-        self.assertRaises(ValueError, '{0}'.format)
-        self.assertRaises(ValueError, '{1}'.format, 'abc')
-        self.assertRaises(ValueError, '{x}'.format)
+        self.assertRaises(IndexError, '{0}'.format)
+        self.assertRaises(IndexError, '{1}'.format, 'abc')
+        self.assertRaises(KeyError,   '{x}'.format)
         self.assertRaises(ValueError, "}{".format)
         self.assertRaises(ValueError, "{".format)
         self.assertRaises(ValueError, "}".format)
         self.assertRaises(ValueError, "abc{0:{}".format)
         self.assertRaises(ValueError, "{0".format)
-        self.assertRaises(ValueError, "{0.}".format)
-        self.assertRaises(ValueError, "{0[}".format)
+        self.assertRaises(IndexError, "{0.}".format)
+        self.assertRaises(ValueError, "{0.}".format, 0)
+        self.assertRaises(IndexError, "{0[}".format)
         self.assertRaises(ValueError, "{0[}".format, [])
-        self.assertRaises(ValueError, "{0]}".format)
-        self.assertRaises(ValueError, "{0.[]}".format)
+        self.assertRaises(KeyError,   "{0]}".format)
+        self.assertRaises(ValueError, "{0.[]}".format, 0)
         self.assertRaises(ValueError, "{0..foo}".format, 0)
-        self.assertRaises(ValueError, "{0[0}".format)
-        self.assertRaises(ValueError, "{0[0:foo}".format)
-        self.assertRaises(ValueError, "{c]}".format)
-        self.assertRaises(ValueError, "{{ {{{0}}".format)
-        self.assertRaises(ValueError, "{0}}".format)
-        self.assertRaises(ValueError, "{foo}".format, bar=3)
+        self.assertRaises(ValueError, "{0[0}".format, 0)
+        self.assertRaises(ValueError, "{0[0:foo}".format, 0)
+        self.assertRaises(KeyError,   "{c]}".format)
+        self.assertRaises(ValueError, "{{ {{{0}}".format, 0)
+        self.assertRaises(ValueError, "{0}}".format, 0)
+        self.assertRaises(KeyError,   "{foo}".format, bar=3)
         self.assertRaises(ValueError, "{0!x}".format, 3)
-        self.assertRaises(ValueError, "{0!}".format)
-        self.assertRaises(ValueError, "{0!rs}".format)
+        self.assertRaises(ValueError, "{0!}".format, 0)
+        self.assertRaises(ValueError, "{0!rs}".format, 0)
         self.assertRaises(ValueError, "{!}".format)
         self.assertRaises(ValueError, "{:}".format)
         self.assertRaises(ValueError, "{:s}".format)
index de700f618bd4326804ed2a8b8d9112d86e700dc4..ea8b0e72f6a577461a290dce32e1ab0dc7869c21 100644 (file)
@@ -414,8 +414,7 @@ get_field_object(SubString *input, PyObject *args, PyObject *kwargs)
         if (key == NULL)
             goto error;
         if ((kwargs == NULL) || (obj = PyDict_GetItem(kwargs, key)) == NULL) {
-            PyErr_SetString(PyExc_ValueError, "Keyword argument not found "
-                            "in format string");
+            PyErr_SetObject(PyExc_KeyError, key);
             Py_DECREF(key);
             goto error;
         }
@@ -425,12 +424,8 @@ get_field_object(SubString *input, PyObject *args, PyObject *kwargs)
     else {
         /* look up in args */
         obj = PySequence_GetItem(args, index);
-        if (obj == NULL) {
-            /* translate IndexError to a ValueError */
-            PyErr_SetString(PyExc_ValueError, "Not enough positional arguments "
-                            "in format string");
+        if (obj == NULL)
             goto error;
-        }
     }
 
     /* iterate over the rest of the field_name */