[Python-checkins] r54079 - sandbox/trunk/pep3101/test_simpleformat.py sandbox/trunk/pep3101/unicodeformat.c

eric.smith python-checkins at python.org
Fri Mar 2 13:07:41 CET 2007


Author: eric.smith
Date: Fri Mar  2 13:07:39 2007
New Revision: 54079

Modified:
   sandbox/trunk/pep3101/test_simpleformat.py
   sandbox/trunk/pep3101/unicodeformat.c
Log:
Completed implementation for string and repr formatting.  Removed 'DUMMY_FORMATTING' define, so that we can incrementally add and test formatting for various types.  Fixed parsing of internal format specifiers, it now no longer caches the length.  Added unit tests for strings and repr.

Modified: sandbox/trunk/pep3101/test_simpleformat.py
==============================================================================
--- sandbox/trunk/pep3101/test_simpleformat.py	(original)
+++ sandbox/trunk/pep3101/test_simpleformat.py	Fri Mar  2 13:07:39 2007
@@ -1,4 +1,3 @@
-
 import unittest
 from test import test_support
 
@@ -12,111 +11,134 @@
 
 
 class FormatTest(unittest.TestCase):
-   # All tests run through these functions. They can be
-   # overridden to change the class of string being tested
-   # and the function being used.
-   def formatEquals(self, result, text, *args, **kwargs):
-       text = str(text)
-       result = str(result)
-       val = pep3101.format(text, *args, **kwargs)
-       self.assertEquals(val, result)
-
-   def formatRaises(self, exc, text, *args, **kwargs):
-       exc = exc or Exception #StringFormat.FormatError
-       text = str(text)
-       #prevState = StringFormat.strict_format_errors
-       #StringFormat.strict_format_errors = True
-       try:
-           self.assertRaises(exc,
-                             lambda: pep3101.format(
-                                 text, *args, **kwargs))
-       finally:
-           pass
-           #StringFormat.strict_format_errors = prevState
-
-
-   def test_basic(self):
-       # directly from the pep intro
-       self.formatEquals(
+    # All tests run through these functions. They can be
+    # overridden to change the class of string being tested
+    # and the function being used.
+    def formatEquals(self, result, text, *args, **kwargs):
+        text = str(text)
+        result = str(result)
+        val = pep3101.format(text, *args, **kwargs)
+        self.assertEquals(val, result)
+
+    def formatRaises(self, exc, text, *args, **kwargs):
+        exc = exc or Exception #StringFormat.FormatError
+        text = str(text)
+        #prevState = StringFormat.strict_format_errors
+        #StringFormat.strict_format_errors = True
+        try:
+            self.assertRaises(exc,
+                              lambda: pep3101.format(
+                                text, *args, **kwargs))
+        finally:
+            pass
+            #StringFormat.strict_format_errors = prevState
+
+
+    def test_basic(self):
+        # directly from the pep intro
+        self.formatEquals(
            "My name is Fred",
            "My name is {0}", "Fred")
-       self.formatEquals(
+        self.formatEquals(
            "My name is Fred :-{}",
            "My name is {0} :-{{}}", "Fred")
-       self.formatEquals("abc", "{0:}", "abc")  # is this allowed?
+        self.formatEquals("abc", "{0:}", "abc")  # is this allowed?
 
-   def test_missingargs(self):
-       #self.formatRaises(None, "Doesn't use all {0} args", 42, 24)
-       self.formatRaises(ValueError, "There is no {4} arg", 42, 24)
-       self.formatRaises(ValueError, "There question is {when}", who=True)
-
-   def test_attributes(self):
-       class Container(object):
-           one, _two, four4 = 1, 2, 4
-           def __getattr__(self, name):
-               if name == "five": return 5
-               raise TypeError("Never do this")
-       self.formatEquals(
+    def test_missingargs(self):
+        #self.formatRaises(None, "Doesn't use all {0} args", 42, 24)
+        self.formatRaises(ValueError, "There is no {4} arg", 42, 24)
+        self.formatRaises(ValueError, "There question is {when}", who=True)
+
+    def test_attributes(self):
+        class Container(object):
+            one, _two, four4 = 1, 2, 4
+            def __getattr__(self, name):
+                if name == "five": return 5
+                raise TypeError("Never do this")
+        self.formatEquals(
            "Count with me; 1 4",
            "Count with me; {0.one} {1.four4}",
            Container, Container, item=Container)
-       self.formatRaises(ValueError,
+        self.formatRaises(ValueError,
            "Count with me; {0.one} {item._two} {1.four4}",
            Container, Container, item=Container)
-       self.formatEquals(
+        self.formatEquals(
            "Count with me; 1 2 4",
            "Count with me; {0.one} {item._two} {1.four4}",
            Container, Container, item=Container, _flags=dict(allow_leading_under=1))
-       self.formatEquals(
+        self.formatEquals(
            "Five is 5", "Five is {c.five}", c=Container())
-       self.formatRaises(AttributeError,
+        self.formatRaises(AttributeError,
            "Missing {0.rabbit} lookup", Container)
-       self.formatRaises(TypeError,
+        self.formatRaises(TypeError,
            "Forbidden {0.secret} lookup", Container())
 
-   def test_items(self):
-       d = dict(val="value", sum=1)
-       t = tuple(("apple", "ball", "cat"))
-       self.formatEquals(
+    def test_items(self):
+        d = dict(val="value", sum=1)
+        t = tuple(("apple", "ball", "cat"))
+        self.formatEquals(
            "The value of apple",
            "The {0[val]} of {t[0]}", d, t=t)
-       # Decided against negative indices for now
-       #self.formatEquals(
-       #    "The shiny red ball",
-       #    "The shiny red {0[-2]}", t)
-
-   def test_formatlookup(self):
-       self.formatEquals("32_0>4d", "{0:{1}}", 32, "0>4d")
-       self.formatEquals("32_*>4d", "{0:{1}{2}4{3}}", 32, "*", ">", "d")
-
-   def test_specifiers(self):
-       self.formatEquals("97_c", "{0:c}", ord("a"))
-       self.formatEquals("8_08b", "{0:08b}", 8)
-       self.formatEquals("8_ >3d", "{0: >3d}", 8)
-       self.formatEquals("0.1515_.0%", "{0:.0%}", .1515)
-
-   def test_custom_format(self):
-       class Custom(object):
-           def __format__(self, specifiers):
-               return specifiers
-       custom = Custom()
-       self.formatEquals("magic", "{0:magic}", custom)
-       self.formatEquals("custom", "{0:{1}}", custom, "custom")
-
-   def test_syntaxerror(self):
-       self.assertRaises(Exception, "}{", True)
-       self.assertRaises(Exception, "{0", True)
-       self.assertRaises(Exception, "{0.[]}", True)
-       self.assertRaises(Exception, "{0[0}", True)
-       self.assertRaises(Exception, "{0[0:foo}", True)
-       self.assertRaises(Exception, "{c]}", True)
-       self.assertRaises(Exception, "{{1}}", True, 0)
-       self.assertRaises(Exception, "{{ {{{0}}", True)
-       self.assertRaises(Exception, "{0}}", True)
+        # Decided against negative indices for now
+        #self.formatEquals(
+        #    "The shiny red ball",
+        #    "The shiny red {0[-2]}", t)
+
+    def test_formatlookup(self):
+        self.formatEquals("32_0>4d", "{0:{1}}", 32, "0>4d")
+        self.formatEquals("32_*>4d", "{0:{1}{2}4{3}}", 32, "*", ">", "d")
+
+    def test_specifiers(self):
+        self.formatEquals("97_c", "{0:c}", ord("a"))
+        self.formatEquals("8_08b", "{0:08b}", 8)
+        self.formatEquals("8_ >3d", "{0: >3d}", 8)
+        self.formatEquals("0.1515_.0%", "{0:.0%}", .1515)
+
+    def test_string_specifiers(self):
+        self.formatEquals("abc", "{0:.3s}", "abc")
+
+        self.formatEquals("ab", "{0:.3s}", "ab")
+
+        self.formatEquals("abc", "{0:.3s}", "abcdef")
+        self.formatEquals("resultx", "{0:x<7s}", "result")
+        self.formatEquals("result ", "{0: <7s}", "result")
+        self.formatEquals("result ", "{0:<7s}", "result")
+        self.formatEquals(" result", "{0:>7s}", "result")
+
+    def test_repr_specifiers(self):
+        self.formatEquals("3", "{0:r}", 3)
+        self.formatEquals("3.141", "{0:5r}", 3.141592654)
+
+        # I'm not sure this is a good test, since the quoting might change
+        self.formatEquals("'abcdefg'", "{0:r}", "abcdefg")
+        self.formatEquals("'abcdefg", "{0:8r}", "abcdefg")
+
+    def test_missing_type_specifier(self):
+        # make sure floats use 'g', ints and longs 'd', and everything else 's'
+        pass
+
+    def test_custom_format(self):
+        class Custom(object):
+            def __format__(self, specifiers):
+                return specifiers
+        custom = Custom()
+        self.formatEquals("magic", "{0:magic}", custom)
+        self.formatEquals("custom", "{0:{1}}", custom, "custom")
+
+    def test_syntaxerror(self):
+        self.assertRaises(Exception, "}{", True)
+        self.assertRaises(Exception, "{0", True)
+        self.assertRaises(Exception, "{0.[]}", True)
+        self.assertRaises(Exception, "{0[0}", True)
+        self.assertRaises(Exception, "{0[0:foo}", True)
+        self.assertRaises(Exception, "{c]}", True)
+        self.assertRaises(Exception, "{{1}}", True, 0)
+        self.assertRaises(Exception, "{{ {{{0}}", True)
+        self.assertRaises(Exception, "{0}}", True)
 
 
 def test_main():
-   test_support.run_unittest(FormatTest)
+    test_support.run_unittest(FormatTest)
 
 if __name__ == "__main__":
-   test_main()
+    test_main()

Modified: sandbox/trunk/pep3101/unicodeformat.c
==============================================================================
--- sandbox/trunk/pep3101/unicodeformat.c	(original)
+++ sandbox/trunk/pep3101/unicodeformat.c	Fri Mar  2 13:07:39 2007
@@ -158,6 +158,22 @@
 recurse_format(FmtState *fs);
 
 /************************************************************************/
+/**************************  Utility  functions  ************************/
+/************************************************************************/
+
+/* XXX probably a better way to do this.  can't use memset, though,
+   because of Unicode and char* support */
+Py_LOCAL_INLINE(void)
+charset(CH_TYPE* dst, CH_TYPE ch, Py_ssize_t len)
+{
+    CH_TYPE* end = dst + len;
+    for(; dst < end; dst++) {
+        *dst = ch;
+    }
+}
+
+
+/************************************************************************/
 /***********      Error handling and exception generation  **************/
 /************************************************************************/
 
@@ -295,9 +311,6 @@
     get_integer_index consumes 0 or more decimal digit characters
     from a format string, updates *result with the corresponding
     positive integer, and returns the number of digits consumed.
-
-    if the isargument parameter is true, it will remove the
-    integer from the arguments bitset.
 */
 static int
 get_integer_index(FmtState *fs, Py_ssize_t *result)
@@ -598,11 +611,9 @@
 
     The two main subfunctions of render_field are caller_render (which
     calls the object-supplied __format__ hook), and internal_render, which
-    renders objects which don't have format hoohs.
+    renders objects which don't have format hooks.
 */
 
-#if !DUMMY_FORMATTING
-
 typedef struct {
     CH_TYPE fill_char;
     CH_TYPE align;
@@ -610,7 +621,7 @@
     Py_ssize_t width;
     Py_ssize_t precision;
     CH_TYPE type;
-} DefaultFormat;
+} InternalFormatSpec;
 
 /* returns true if this character is a specifier alignment token */
 Py_LOCAL_INLINE(int)
@@ -636,16 +647,22 @@
     }
 }
 
+
+/* a convenience function to return the length of a substring */
+Py_LOCAL_INLINE(int)
+spec_len(SubString* spec)
+{
+    return spec->end - spec->ptr;
+}
+
 /*
     parse the default specification
 */
 
 static int
-parse_internal_render(FmtState *fs, DefaultFormat *format)
+parse_internal_render_format_spec(FmtState *fs, InternalFormatSpec *format)
 {
-    Py_ssize_t index = 0;
     Py_ssize_t specified_width;
-    Py_ssize_t remaining;
     SubString *spec = &fs->fmtstr;
 
     format->fill_char = '\0';
@@ -655,44 +672,38 @@
     format->precision = -1;
     format->type = '\0';
 
-    /* cache the length, since that's convenient */
-    Py_ssize_t spec_len = spec->end - spec->ptr;
-
     /* If the second char is an alignment token,
        then parse the fill char */
-    if (spec_len >= 2 && alignment_token(spec->ptr[1])) {
+    if (spec_len(spec) >= 2 && alignment_token(spec->ptr[1])) {
         format->align = spec->ptr[1];
         format->fill_char = spec->ptr[0];
-        index = 2;
-    } else if (spec_len >= 1 && alignment_token(spec->ptr[0])) {
+        spec->ptr += 2;
+    } else if (spec_len(spec) >= 1 && alignment_token(spec->ptr[0])) {
         format->align = spec->ptr[0];
-        index = 1;
+        spec->ptr++;
     }
 
     /* Parse the various sign options */
-    if (index < spec_len && sign_element(spec->ptr[index])) {
-        format->sign = spec->ptr[index];
-        index++;
-        if (index < spec_len && spec->ptr[index] == ')') {
-            index++;
+    if (spec_len(spec) >= 1 && sign_element(spec->ptr[0])) {
+        format->sign = spec->ptr[0];
+        spec->ptr++;
+        if (spec_len(spec) >= 1 && spec->ptr[0] == ')') {
+            spec->ptr++;
         }
     }
 
     /* The special case for 0-padding (backwards compat) */
     if (format->fill_char == '\0' &&
-             index < spec_len && spec->ptr[index] == '0') {
+            spec_len(spec) >= 1 && spec->ptr[0] == '0') {
         format->fill_char = '0';
         if (format->align == '\0') {
             format->align = '=';
         }
-        index++;
+        spec->ptr++;
     }
 
     specified_width = get_integer_index(fs, &format->width);
 
-    /* recalculate the length, since the pointers may have just changed */
-    spec_len = spec->end - spec->ptr;
-
     /* if specified_width is 0, we didn't consume any characters for
        the width. in that case, reset the width to -1, because
        get_integer_index() will have set it to zero */
@@ -701,33 +712,86 @@
     }
 
     /* Parse field precision */
-    if (index < spec_len && spec->ptr[index] == '.') {
-        index++;
+    if (spec_len(spec) && spec->ptr[0] == '.') {
+        spec->ptr++;
 
         specified_width = get_integer_index(fs, &format->precision);
 
-        /* recalculate the length, since the pointers may have just changed */
-        spec_len = spec->end - spec->ptr;
-
-        /* again, check if any characters specified */
+        /* not having a precision after a dot is an error */
         if (specified_width <= 0) {
-            format->precision = -1;
+            SetError(fs, "Missing precision");
+            return 0;
         }
+
     }
 
     /* Finally, parse the type field */
 
-    remaining = spec_len - index;
-    if (remaining > 1) {
+    if (spec_len(spec) > 1) {
         /* invalid conversion spec */
         SetError(fs, "Invalid conversion specification");
         return 0;
     }
 
-    if (remaining == 1) {
-        format->type = spec->ptr[index];
+    if (spec_len(spec) == 1) {
+        format->type = spec->ptr[0];
+        spec->ptr++;
     }
 
+    /* XXX do some consistency checking, like "=" can only be on
+       signed numbers. or leave that to the individual converers? */
+
+    return 1;
+}
+
+
+/* used to output simple strings, only supports a maximum width and
+   total field alignment */
+static int
+output_string_chars(FmtState *fs, CH_TYPE *src, Py_ssize_t len, const InternalFormatSpec *format)
+{
+    Py_ssize_t ok;
+    Py_ssize_t width; /* total field width */
+    CH_TYPE *dst;
+
+    /* if precision is specified, output no more that format.precision
+       characters */
+    if (format->precision >= 0 && len >= format->precision) {
+        len = format->precision;
+    }
+
+    if (format->width >= 0) {
+        width = format->width;
+    } else {
+        /* not specified, use all of the chars and no more */
+        width = len;
+    }
+
+    /* reserve all the space we'll need */
+    if (output_allocate(fs, width, &dst) == 0)
+        return 0;
+
+    /* now write into that space */
+
+    /* if right aligning, increment the destination allow space on the left */
+    memcpy(dst + (format->align == '>' ? (width - len) : 0), src, len * sizeof(CH_TYPE));
+
+    /* do any padding */
+    if (len != width) {
+        CH_TYPE fill_char = format->fill_char;
+        if (fill_char == '\0') {
+            /* use the default, if not specified */
+            fill_char = ' ';
+        }
+
+        if (format->align == '>') {
+            /* right align, pad on left */
+            charset(dst, fill_char, width - len);
+        } else {
+            /* left align, pad on right */
+            charset(dst + len, fill_char, width - len);
+        }
+    }
     return 1;
 }
 
@@ -735,141 +799,190 @@
 /*
     Our internal conversion functions have this signature.
 
-    returns the number of characters written, or -1 if error
+    returns 0 on failure, else 1
 */
-/* XXX obviously wrong, but just a placeholder currently */
-typedef Py_ssize_t
-(*ConversionFunction)(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format);
+typedef int
+(*ConversionFunction)(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format);
+
+/* XXX delete this when all internal conversions are implemented */
+static int
+convert_DUMMY(PyObject *fieldobj, FmtState *fs)
+{
+    PyObject *myobj;
+    int ok;
+
+    /* Test implementation, only at top level */
+    CH_TYPE under = '_';
+
+    myobj = STROBJ_STR(fieldobj);
+    if (myobj == NULL)
+        return 0;
+    ok = output_data(fs, STROBJ_AS_PTR(myobj),
+                         STROBJ_GET_SIZE(myobj));
+    Py_DECREF(myobj);
+    if (!ok)
+        return 0;
+    if (fs->fieldspec.ptr != fs->fieldspec.end) {
+        if (!output_data(fs, &under, 1))
+            return 0;
+        if (!output_data(fs, fs->fieldspec.ptr,
+                             fs->fieldspec.end - fs->fieldspec.ptr))
+            return 0;
+    }
+    return 1;
+}
 
 /* conversion functions */
-static Py_ssize_t
-convert_binary(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_binary(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_char(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_char(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_decimal(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_decimal(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
+#if 0
+    PyObject *intobj;
+    PyObject *strobj;
+    CH_TYPE* src;
+    Py_ssize_t len;
+    int negative = 0;
+    int ok;
+
+
+    intobj = PyIntObject(fieldobj);
+    if (intobj == NULL)
+        return 0;
+
+    strobj = STROBJ_STR(intobj);
+    Py_DECREF(intobj);
+
+    /* see if we're negative.  we know src must point to at least one
+       character, so skip that check */
+    src = STROBJ_AS_PTR(strobj);
+    len = STROBJ_GET_SIZE(strobj);
+    if (src[0] == '-') {
+        /* remember that we're negative, and skip the char */
+        negative = 1;
+        src++;
+        len--;
+    }
+
+    ok = output_string_chars(fs, src, len, format);
+    Py_DECREF(strobj);
+
+    return ok;
+#endif
 }
 
-static Py_ssize_t
-convert_exponent(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_exponent(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_exponentUC(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_exponentUC(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_fixed(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_fixed(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_fixedUC(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_fixedUC(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_general(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_general(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_generalUC(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_generalUC(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_number(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_number(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_octal(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_octal(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_repr(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_repr(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
     int ok;
-    PyObject *s;
-    PyObject *r;
-    Py_ssize_t len;
+    PyObject *strobj;
+    PyObject *reprobj;
 
-    r = PyObject_Repr(fieldobj);
-    if (r == NULL)
+    reprobj = PyObject_Repr(fieldobj);
+    if (reprobj == NULL)
         return 0;
 
-    s = STROBJ_STR(r);
-    Py_DECREF(r);
+    strobj = STROBJ_STR(reprobj);
+    Py_DECREF(reprobj);
 
-    len = STROBJ_GET_SIZE(s);
-    ok = output_data(fs, STROBJ_AS_PTR(s), len);
-    Py_DECREF(s);
+    ok = output_string_chars(fs, STROBJ_AS_PTR(strobj), STROBJ_GET_SIZE(strobj), format);
+    Py_DECREF(strobj);
 
-    return ok ? len : -1;
+    return ok;
 }
 
-static Py_ssize_t
-convert_string(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_string(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    PyObject *myobj;
-    Py_ssize_t ok;
-    Py_ssize_t len;
-    CH_TYPE *dst;
+    PyObject *strobj;
+    int ok;
 
-    myobj = STROBJ_STR(fieldobj);
-    if (myobj == NULL)
-        return -1;
+    strobj = STROBJ_STR(fieldobj);
+    if (strobj == NULL)
+        return 0;
 
-    len = STROBJ_GET_SIZE(myobj);
+    ok = output_string_chars(fs, STROBJ_AS_PTR(strobj), STROBJ_GET_SIZE(strobj), format);
+    Py_DECREF(strobj);
 
-    /* reserve all the space we'll need */
-    ok = output_allocate(fs, len, &dst);
-    if (ok) {
-        memcpy(dst, STROBJ_AS_PTR(myobj), len * sizeof(CH_TYPE));
-    }
-    Py_DECREF(myobj);
-
-    return ok ? len : -1;
+    return ok;
 }
 
-static Py_ssize_t
-convert_hex(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_hex(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_hexUC(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_hexUC(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
-static Py_ssize_t
-convert_percentage(PyObject *fieldobj, FmtState *fs, const DefaultFormat *format)
+static int
+convert_percentage(PyObject *fieldobj, FmtState *fs, const InternalFormatSpec *format)
 {
-    return -1;
+    return convert_DUMMY(fieldobj, fs);
 }
 
 /* returns a pointer to our conversion function, or NULL if invalid */
@@ -900,46 +1013,16 @@
         return NULL;
     }
 }
-#endif
 
 /*
     internal_render -- "Then a miracle occurs"
 */
 static int internal_render(FmtState *fs, PyObject *fieldobj)
 {
-#if DUMMY_FORMATTING == 1
-    PyObject *myobj;
-    int ok;
-
-    /* Test implementation, only at top level */
-    CH_TYPE under = '_';
-
-    myobj = STROBJ_STR(fieldobj);
-    if (myobj == NULL)
-        return 0;
-    ok = output_data(fs, STROBJ_AS_PTR(myobj),
-                         STROBJ_GET_SIZE(myobj));
-    Py_DECREF(myobj);
-    if (!ok)
-        return 0;
-    if (fs->fieldspec.ptr != fs->fieldspec.end) {
-        if (!output_data(fs, &under, 1))
-            return 0;
-        if (!output_data(fs, fs->fieldspec.ptr,
-                             fs->fieldspec.end - fs->fieldspec.ptr))
-            return 0;
-    }
-#else
-
-    Py_ssize_t len;
-    Py_ssize_t padding;
-    DefaultFormat format;
+    InternalFormatSpec format;
     ConversionFunction conversion;
-    CH_TYPE sign = '\0';
-    CH_TYPE prefix;
-    CH_TYPE suffix;
 
-    if (!parse_internal_render(fs, &format)) {
+    if (!parse_internal_render_format_spec(fs, &format)) {
         return 0;
     }
 
@@ -955,8 +1038,9 @@
         }
     }
 
-    /* handle conversion functions that logically map to
-       other conversion functions? */
+    /* XXX handle conversion functions that logically map to
+       other conversion functions? percent is the only one, and I'm not wild
+       about having percent at all*/
 
     conversion = conversion_function(format.type);
     if (conversion == NULL) {
@@ -964,14 +1048,10 @@
         return 0;
     }
 
-    /* convert to a string first */
-    /* get the length written so that we can fixup
-       inside the buffer, as needed */
-    len = conversion(fieldobj, fs, &format);
-    if (len < 0)
-        return 0;
+    /* do the conversion, writing into the output string */
+    return conversion(fieldobj, fs, &format);
 
-    /* we wrote "len" bytes.  see what fixups need to be done */
+#if 0
 
     /* Handle the sign logic */
     prefix = '\0';
@@ -1008,8 +1088,8 @@
                     }
     }
 
-#endif
     return 1;
+#endif
 }
 
 /*


More information about the Python-checkins mailing list