]> granicus.if.org Git - python/commitdiff
Issue #13706: Fix format(int, "n") for locale with non-ASCII thousands separator
authorVictor Stinner <victor.stinner@haypocalc.com>
Thu, 23 Feb 2012 23:37:51 +0000 (00:37 +0100)
committerVictor Stinner <victor.stinner@haypocalc.com>
Thu, 23 Feb 2012 23:37:51 +0000 (00:37 +0100)
 * Decode thousands separator and decimal point using PyUnicode_DecodeLocale()
   (from the locale encoding), instead of decoding them implicitly from latin1
 * Remove _PyUnicode_InsertThousandsGroupingLocale(), it was not used
 * Change _PyUnicode_InsertThousandsGrouping() API to return the maximum
   character if unicode is NULL
 * Replace MIN/MAX macros by Py_MIN/Py_MAX
 * stringlib/undef.h undefines STRINGLIB_IS_UNICODE
 * stringlib/localeutil.h only supports Unicode

12 files changed:
Include/unicodeobject.h
Lib/test/test_format.py
Objects/stringlib/asciilib.h
Objects/stringlib/localeutil.h
Objects/stringlib/stringdefs.h
Objects/stringlib/ucs1lib.h
Objects/stringlib/ucs2lib.h
Objects/stringlib/ucs4lib.h
Objects/stringlib/undef.h
Objects/stringlib/unicodedefs.h
Objects/unicodeobject.c
Python/formatter_unicode.c

index 6d580f482129b24d6db6ef1bace2cfe712d5d711..465d87b6f267de00c94c0530aee4af575c028f0b 100644 (file)
@@ -1936,32 +1936,20 @@ PyAPI_FUNC(PyObject *) _PyUnicode_XStrip(
     );
 #endif
 
-/* Using the current locale, insert the thousands grouping
-   into the string pointed to by buffer.  For the argument descriptions,
-   see Objects/stringlib/localeutil.h */
-
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(Py_ssize_t) _PyUnicode_InsertThousandsGroupingLocale(Py_UNICODE *buffer,
-                                                   Py_ssize_t n_buffer,
-                                                   Py_UNICODE *digits,
-                                                   Py_ssize_t n_digits,
-                                                   Py_ssize_t min_width);
-#endif
-
 /* Using explicit passed-in values, insert the thousands grouping
    into the string pointed to by buffer.  For the argument descriptions,
    see Objects/stringlib/localeutil.h */
 #ifndef Py_LIMITED_API
 PyAPI_FUNC(Py_ssize_t) _PyUnicode_InsertThousandsGrouping(
     PyObject *unicode,
-    int kind,
-    void *buffer,
+    Py_ssize_t index,
     Py_ssize_t n_buffer,
     void *digits,
     Py_ssize_t n_digits,
     Py_ssize_t min_width,
     const char *grouping,
-    const char *thousands_sep);
+    PyObject *thousands_sep,
+    Py_UCS4 *maxchar);
 #endif
 /* === Characters Type APIs =============================================== */
 
index 7345b30c054d2787a1b81c6947ac210beb147124..70e748f2c345d462e3502d5f4adde377754b916d 100644 (file)
@@ -1,4 +1,5 @@
 from test.support import verbose, TestFailed
+import locale
 import sys
 import test.support as support
 import unittest
@@ -282,6 +283,20 @@ class FormatTest(unittest.TestCase):
         self.assertEqual(format(1+2j, "\u2007^8"), "\u2007(1+2j)\u2007")
         self.assertEqual(format(0j, "\u2007^4"), "\u20070j\u2007")
 
+    def test_locale(self):
+        try:
+            oldloc = locale.setlocale(locale.LC_ALL, '')
+        except locale.Error as err:
+            self.skipTest("Cannot set locale: {}".format(err))
+        try:
+            sep = locale.localeconv()['thousands_sep']
+            text = format(123456789, "n")
+            self.assertIn(sep, text)
+            self.assertEqual(text.replace(sep, ''), '123456789')
+        finally:
+            locale.setlocale(locale.LC_ALL, oldloc)
+
+
 
 def test_main():
     support.run_unittest(FormatTest)
index ae68e3c89f00db2f8d114d03d6fde13935dbab8e..fa481c08efb3f76f6b529c57eb39658acf79d72a 100644 (file)
 #define STRINGLIB_RESIZE         not_supported
 #define STRINGLIB_CHECK          PyUnicode_Check
 #define STRINGLIB_CHECK_EXACT    PyUnicode_CheckExact
-#define STRINGLIB_GROUPING       _PyUnicode_InsertThousandsGrouping
-#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale
 
 #define STRINGLIB_TOSTR          PyObject_Str
 #define STRINGLIB_TOASCII        PyObject_ASCII
 
 #define _Py_InsertThousandsGrouping _PyUnicode_ascii_InsertThousandsGrouping
-#define _Py_InsertThousandsGroupingLocale _PyUnicode_ascii_InsertThousandsGroupingLocale
 
index ddce69d4558cd4da4208f22809c6f524ca5cb593..28c87c8f832cb96613de7703aa4f46f8aaea0af0 100644 (file)
@@ -2,8 +2,9 @@
 
 #include <locale.h>
 
-#define MAX(x, y) ((x) < (y) ? (y) : (x))
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#ifndef STRINGLIB_IS_UNICODE
+#   error "localeutil is specific to Unicode"
+#endif
 
 typedef struct {
     const char *grouping;
@@ -46,7 +47,7 @@ STRINGLIB(GroupGenerator_next)(STRINGLIB(GroupGenerator) *self)
    are optional, depending on when we're called. */
 static void
 STRINGLIB(fill)(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end,
-     Py_ssize_t n_chars, Py_ssize_t n_zeros, const char* thousands_sep,
+     Py_ssize_t n_chars, Py_ssize_t n_zeros, STRINGLIB_CHAR* thousands_sep,
      Py_ssize_t thousands_sep_len)
 {
     Py_ssize_t i;
@@ -55,15 +56,8 @@ STRINGLIB(fill)(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end,
         *buffer_end -= thousands_sep_len;
 
         /* Copy the thousands_sep chars into the buffer. */
-#if STRINGLIB_IS_UNICODE
-        /* Convert from the char's of the thousands_sep from
-           the locale into unicode. */
-        for (i = 0; i < thousands_sep_len; ++i)
-            (*buffer_end)[i] = thousands_sep[i];
-#else
-        /* No conversion, just memcpy the thousands_sep. */
-        memcpy(*buffer_end, thousands_sep, thousands_sep_len);
-#endif
+        memcpy(*buffer_end, thousands_sep,
+               thousands_sep_len * STRINGLIB_SIZEOF_CHAR);
     }
 
     *buffer_end -= n_chars;
@@ -76,7 +70,7 @@ STRINGLIB(fill)(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end,
 }
 
 /**
- * _Py_InsertThousandsGrouping:
+ * InsertThousandsGrouping:
  * @buffer: A pointer to the start of a string.
  * @n_buffer: Number of characters in @buffer.
  * @digits: A pointer to the digits we're reading from. If count
@@ -106,13 +100,15 @@ STRINGLIB(fill)(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end,
     _insert_thousands_sep().
  **/
 Py_ssize_t
-_Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer,
-                            Py_ssize_t n_buffer,
-                            STRINGLIB_CHAR *digits,
-                            Py_ssize_t n_digits,
-                            Py_ssize_t min_width,
-                            const char *grouping,
-                            const char *thousands_sep)
+STRINGLIB(InsertThousandsGrouping)(
+    STRINGLIB_CHAR *buffer,
+    Py_ssize_t n_buffer,
+    STRINGLIB_CHAR *digits,
+    Py_ssize_t n_digits,
+    Py_ssize_t min_width,
+    const char *grouping,
+    STRINGLIB_CHAR *thousands_sep,
+    Py_ssize_t thousands_sep_len)
 {
     Py_ssize_t count = 0;
     Py_ssize_t n_zeros;
@@ -124,7 +120,6 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer,
     STRINGLIB_CHAR *digits_end = NULL;
     Py_ssize_t l;
     Py_ssize_t n_chars;
-    Py_ssize_t thousands_sep_len = strlen(thousands_sep);
     Py_ssize_t remaining = n_digits; /* Number of chars remaining to
                                         be looked at */
     /* A generator that returns all of the grouping widths, until it
@@ -138,9 +133,9 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer,
     }
 
     while ((l = STRINGLIB(GroupGenerator_next)(&groupgen)) > 0) {
-        l = MIN(l, MAX(MAX(remaining, min_width), 1));
-        n_zeros = MAX(0, l - remaining);
-        n_chars = MAX(0, MIN(remaining, l));
+        l = Py_MIN(l, Py_MAX(Py_MAX(remaining, min_width), 1));
+        n_zeros = Py_MAX(0, l - remaining);
+        n_chars = Py_MAX(0, Py_MIN(remaining, l));
 
         /* Use n_zero zero's and n_chars chars */
 
@@ -168,9 +163,9 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer,
     if (!loop_broken) {
         /* We left the loop without using a break statement. */
 
-        l = MAX(MAX(remaining, min_width), 1);
-        n_zeros = MAX(0, l - remaining);
-        n_chars = MAX(0, MIN(remaining, l));
+        l = Py_MAX(Py_MAX(remaining, min_width), 1);
+        n_zeros = Py_MAX(0, l - remaining);
+        n_chars = Py_MAX(0, Py_MIN(remaining, l));
 
         /* Use n_zero zero's and n_chars chars */
         count += (use_separator ? thousands_sep_len : 0) + n_zeros + n_chars;
@@ -183,25 +178,3 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer,
     return count;
 }
 
-/**
- * _Py_InsertThousandsGroupingLocale:
- * @buffer: A pointer to the start of a string.
- * @n_digits: The number of digits in the string, in which we want
- *            to put the grouping chars.
- *
- * Reads thee current locale and calls _Py_InsertThousandsGrouping().
- **/
-Py_ssize_t
-_Py_InsertThousandsGroupingLocale(STRINGLIB_CHAR *buffer,
-                                  Py_ssize_t n_buffer,
-                                  STRINGLIB_CHAR *digits,
-                                  Py_ssize_t n_digits,
-                                  Py_ssize_t min_width)
-{
-        struct lconv *locale_data = localeconv();
-        const char *grouping = locale_data->grouping;
-        const char *thousands_sep = locale_data->thousands_sep;
-
-        return _Py_InsertThousandsGrouping(buffer, n_buffer, digits, n_digits,
-                                           min_width, grouping, thousands_sep);
-}
index fec9f189a1f71055eca7b4907f3715ddffbe6557..7bb91a7a5b7a4bde51c69b3b7f423663afeff2d9 100644 (file)
@@ -25,7 +25,5 @@
 #define STRINGLIB_CHECK          PyBytes_Check
 #define STRINGLIB_CHECK_EXACT    PyBytes_CheckExact
 #define STRINGLIB_TOSTR          PyObject_Str
-#define STRINGLIB_GROUPING       _PyBytes_InsertThousandsGrouping
-#define STRINGLIB_GROUPING_LOCALE _PyBytes_InsertThousandsGroupingLocale
 #define STRINGLIB_TOASCII        PyObject_Repr
 #endif /* !STRINGLIB_STRINGDEFS_H */
index 42b9d91c53942e132b702f1da7828e42644fb455..ed2b0a3023f950869a1f4dde05e6a2d0730c0a93 100644 (file)
 #define STRINGLIB_RESIZE         not_supported
 #define STRINGLIB_CHECK          PyUnicode_Check
 #define STRINGLIB_CHECK_EXACT    PyUnicode_CheckExact
-#define STRINGLIB_GROUPING       _PyUnicode_InsertThousandsGrouping
-#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale
 
 #define STRINGLIB_TOSTR          PyObject_Str
 #define STRINGLIB_TOASCII        PyObject_ASCII
 
 #define _Py_InsertThousandsGrouping _PyUnicode_ucs1_InsertThousandsGrouping
-#define _Py_InsertThousandsGroupingLocale _PyUnicode_ucs1_InsertThousandsGroupingLocale
 
 
index 611e741ca3fe31ea09c3f17d5b50d9bc3843396c..a50890588717a468479b90a520a2cb768f2e2aae 100644 (file)
 #define STRINGLIB_RESIZE         not_supported
 #define STRINGLIB_CHECK          PyUnicode_Check
 #define STRINGLIB_CHECK_EXACT    PyUnicode_CheckExact
-#define STRINGLIB_GROUPING       _PyUnicode_InsertThousandsGrouping
-#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale
 
 #define STRINGLIB_TOSTR          PyObject_Str
 #define STRINGLIB_TOASCII        PyObject_ASCII
 
 #define _Py_InsertThousandsGrouping _PyUnicode_ucs2_InsertThousandsGrouping
-#define _Py_InsertThousandsGroupingLocale _PyUnicode_ucs2_InsertThousandsGroupingLocale
 
index 330b29257bc3962bcc2f193a2e9dfeaf40f654b6..eda0feb7d4250bb5f7714bf4bac67b3390e4e003 100644 (file)
 #define STRINGLIB_RESIZE         not_supported
 #define STRINGLIB_CHECK          PyUnicode_Check
 #define STRINGLIB_CHECK_EXACT    PyUnicode_CheckExact
-#define STRINGLIB_GROUPING       _PyUnicode_InsertThousandsGrouping
-#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale
 
 #define STRINGLIB_TOSTR          PyObject_Str
 #define STRINGLIB_TOASCII        PyObject_ASCII
 
 #define _Py_InsertThousandsGrouping _PyUnicode_ucs4_InsertThousandsGrouping
-#define _Py_InsertThousandsGroupingLocale _PyUnicode_ucs4_InsertThousandsGroupingLocale
 
index fd87e56d360af3922803301986854fc02a8e2734..9310204178eb745e794fc8701a0fbddbf5696158 100644 (file)
@@ -7,5 +7,5 @@
 #undef  STRINGLIB_NEW
 #undef  STRINGLIB_RESIZE
 #undef  _Py_InsertThousandsGrouping
-#undef  _Py_InsertThousandsGroupingLocale
+#undef STRINGLIB_IS_UNICODE
 
index 3ccc57ed9b92af8a49c00f306a8656bf40c0ccae..f16f21e60c385cccce255414f5091eef228b8c65 100644 (file)
@@ -24,8 +24,6 @@
 #define STRINGLIB_RESIZE         PyUnicode_Resize
 #define STRINGLIB_CHECK          PyUnicode_Check
 #define STRINGLIB_CHECK_EXACT    PyUnicode_CheckExact
-#define STRINGLIB_GROUPING       _PyUnicode_InsertThousandsGrouping
-#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale
 
 #if PY_VERSION_HEX < 0x03000000
 #define STRINGLIB_TOSTR          PyObject_Unicode
index 01748be3e8f8b9eeb79ed5638f074d6382e0dc96..2841b07e8ae3783542ee5af43b5791cef44492ff 100644 (file)
@@ -9151,34 +9151,75 @@ any_find_slice(int direction, PyObject* s1, PyObject* s2,
 }
 
 Py_ssize_t
-_PyUnicode_InsertThousandsGrouping(PyObject *unicode, int kind, void *data,
-                                   Py_ssize_t n_buffer,
-                                   void *digits, Py_ssize_t n_digits,
-                                   Py_ssize_t min_width,
-                                   const char *grouping,
-                                   const char *thousands_sep)
-{
+_PyUnicode_InsertThousandsGrouping(
+    PyObject *unicode, Py_ssize_t index,
+    Py_ssize_t n_buffer,
+    void *digits, Py_ssize_t n_digits,
+    Py_ssize_t min_width,
+    const char *grouping, PyObject *thousands_sep,
+    Py_UCS4 *maxchar)
+{
+    unsigned int kind, thousands_sep_kind;
+    void *data, *thousands_sep_data;
+    Py_ssize_t thousands_sep_len;
+    Py_ssize_t len;
+
+    if (unicode != NULL) {
+        kind = PyUnicode_KIND(unicode);
+        data = PyUnicode_DATA(unicode) + index * kind;
+    }
+    else {
+        kind = PyUnicode_1BYTE_KIND;
+        data = NULL;
+    }
+    thousands_sep_kind = PyUnicode_KIND(thousands_sep);
+    thousands_sep_data = PyUnicode_DATA(thousands_sep);
+    thousands_sep_len = PyUnicode_GET_LENGTH(thousands_sep);
+    if (unicode != NULL && thousands_sep_kind != kind) {
+        thousands_sep_data = _PyUnicode_AsKind(thousands_sep, kind);
+        if (!thousands_sep_data)
+            return -1;
+    }
+
     switch (kind) {
     case PyUnicode_1BYTE_KIND:
         if (unicode != NULL && PyUnicode_IS_ASCII(unicode))
-            return _PyUnicode_ascii_InsertThousandsGrouping(
+            len = asciilib_InsertThousandsGrouping(
                 (Py_UCS1*)data, n_buffer, (Py_UCS1*)digits, n_digits,
-                min_width, grouping, thousands_sep);
+                min_width, grouping,
+                thousands_sep_data, thousands_sep_len);
         else
-            return _PyUnicode_ucs1_InsertThousandsGrouping(
+            len = ucs1lib_InsertThousandsGrouping(
                 (Py_UCS1*)data, n_buffer, (Py_UCS1*)digits, n_digits,
-                min_width, grouping, thousands_sep);
+                min_width, grouping,
+                thousands_sep_data, thousands_sep_len);
+        break;
     case PyUnicode_2BYTE_KIND:
-        return _PyUnicode_ucs2_InsertThousandsGrouping(
+        len = ucs2lib_InsertThousandsGrouping(
             (Py_UCS2*)data, n_buffer, (Py_UCS2*)digits, n_digits,
-            min_width, grouping, thousands_sep);
+            min_width, grouping,
+            thousands_sep_data, thousands_sep_len);
+        break;
     case PyUnicode_4BYTE_KIND:
-        return _PyUnicode_ucs4_InsertThousandsGrouping(
+        len = ucs4lib_InsertThousandsGrouping(
             (Py_UCS4*)data, n_buffer, (Py_UCS4*)digits, n_digits,
-            min_width, grouping, thousands_sep);
+            min_width, grouping,
+            thousands_sep_data, thousands_sep_len);
+        break;
+    default:
+        assert(0);
+        return -1;
     }
-    assert(0);
-    return -1;
+    if (unicode != NULL && thousands_sep_kind != kind)
+        PyMem_Free(thousands_sep_data);
+    if (unicode == NULL) {
+        *maxchar = 127;
+        if (len != n_digits) {
+            *maxchar = Py_MAX(*maxchar,
+                              PyUnicode_MAX_CHAR_VALUE(thousands_sep));
+        }
+    }
+    return len;
 }
 
 
index ed716a5b971747b78b0db243d21c4512c0196d49..94f8047e18cf9b6d16f05eb0600052b7639e02ef 100644 (file)
@@ -346,11 +346,13 @@ fill_padding(PyObject *s, Py_ssize_t start, Py_ssize_t nchars,
    before and including the decimal. Note that locales only support
    8-bit chars, not unicode. */
 typedef struct {
-    char *decimal_point;
-    char *thousands_sep;
-    char *grouping;
+    PyObject *decimal_point;
+    PyObject *thousands_sep;
+    const char *grouping;
 } LocaleInfo;
 
+#define STATIC_LOCALE_INFO_INIT {0, 0, 0}
+
 /* describes the layout for an integer, see the comment in
    calc_number_widths() for details */
 typedef struct {
@@ -415,7 +417,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
                    Py_UCS4 sign_char, PyObject *number, Py_ssize_t n_start,
                    Py_ssize_t n_end, Py_ssize_t n_remainder,
                    int has_decimal, const LocaleInfo *locale,
-                   const InternalFormatSpec *format)
+                   const InternalFormatSpec *format, Py_UCS4 *maxchar)
 {
     Py_ssize_t n_non_digit_non_padding;
     Py_ssize_t n_padding;
@@ -423,7 +425,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
     spec->n_digits = n_end - n_start - n_remainder - (has_decimal?1:0);
     spec->n_lpadding = 0;
     spec->n_prefix = n_prefix;
-    spec->n_decimal = has_decimal ? strlen(locale->decimal_point) : 0;
+    spec->n_decimal = has_decimal ? PyUnicode_GET_LENGTH(locale->decimal_point) : 0;
     spec->n_remainder = n_remainder;
     spec->n_spadding = 0;
     spec->n_rpadding = 0;
@@ -484,11 +486,15 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
            to special case it because the grouping code always wants
            to have at least one character. */
         spec->n_grouped_digits = 0;
-    else
+    else {
+        Py_UCS4 grouping_maxchar;
         spec->n_grouped_digits = _PyUnicode_InsertThousandsGrouping(
-            NULL, PyUnicode_1BYTE_KIND, NULL, 0, NULL,
+            NULL, 0,
+            0, NULL,
             spec->n_digits, spec->n_min_width,
-            locale->grouping, locale->thousands_sep);
+            locale->grouping, locale->thousands_sep, &grouping_maxchar);
+        *maxchar = Py_MAX(*maxchar, grouping_maxchar);
+    }
 
     /* Given the desired width and the total of digit and non-digit
        space we consume, see if we need any padding. format->width can
@@ -519,6 +525,10 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
             break;
         }
     }
+
+    if (spec->n_lpadding || spec->n_spadding || spec->n_rpadding)
+        *maxchar = Py_MAX(*maxchar, format->fill_char);
+
     return spec->n_lpadding + spec->n_sign + spec->n_prefix +
         spec->n_spadding + spec->n_grouped_digits + spec->n_decimal +
         spec->n_remainder + spec->n_rpadding;
@@ -587,12 +597,11 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec,
         r =
 #endif
             _PyUnicode_InsertThousandsGrouping(
-                out, kind,
-                (char*)data + kind * pos,
+                out, pos,
                 spec->n_grouped_digits,
                 pdigits + kind * d_pos,
                 spec->n_digits, spec->n_min_width,
-                locale->grouping, locale->thousands_sep);
+                locale->grouping, locale->thousands_sep, NULL);
 #ifndef NDEBUG
         assert(r == spec->n_grouped_digits);
 #endif
@@ -615,10 +624,8 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec,
     pos += spec->n_grouped_digits;
 
     if (spec->n_decimal) {
-        Py_ssize_t t;
-        for (t = 0; t < spec->n_decimal; ++t)
-            PyUnicode_WRITE(kind, data, pos + t,
-                            locale->decimal_point[t]);
+        if (PyUnicode_CopyCharacters(out, pos, locale->decimal_point, 0, spec->n_decimal) < 0)
+            return -1;
         pos += spec->n_decimal;
         d_pos += 1;
     }
@@ -643,32 +650,60 @@ static char no_grouping[1] = {CHAR_MAX};
    grouping description, either for the current locale if type is
    LT_CURRENT_LOCALE, a hard-coded locale if LT_DEFAULT_LOCALE, or
    none if LT_NO_LOCALE. */
-static void
+static int
 get_locale_info(int type, LocaleInfo *locale_info)
 {
     switch (type) {
     case LT_CURRENT_LOCALE: {
         struct lconv *locale_data = localeconv();
-        locale_info->decimal_point = locale_data->decimal_point;
-        locale_info->thousands_sep = locale_data->thousands_sep;
+        locale_info->decimal_point = PyUnicode_DecodeLocale(
+                                         locale_data->decimal_point,
+                                         NULL);
+        if (locale_info->decimal_point == NULL)
+            return -1;
+        locale_info->thousands_sep = PyUnicode_DecodeLocale(
+                                         locale_data->thousands_sep,
+                                         NULL);
+        if (locale_info->thousands_sep == NULL) {
+            Py_DECREF(locale_info->decimal_point);
+            return -1;
+        }
         locale_info->grouping = locale_data->grouping;
         break;
     }
     case LT_DEFAULT_LOCALE:
-        locale_info->decimal_point = ".";
-        locale_info->thousands_sep = ",";
+        locale_info->decimal_point = PyUnicode_FromOrdinal('.');
+        locale_info->thousands_sep = PyUnicode_FromOrdinal(',');
+        if (!locale_info->decimal_point || !locale_info->thousands_sep) {
+            Py_XDECREF(locale_info->decimal_point);
+            Py_XDECREF(locale_info->thousands_sep);
+            return -1;
+        }
         locale_info->grouping = "\3"; /* Group every 3 characters.  The
                                          (implicit) trailing 0 means repeat
                                          infinitely. */
         break;
     case LT_NO_LOCALE:
-        locale_info->decimal_point = ".";
-        locale_info->thousands_sep = "";
+        locale_info->decimal_point = PyUnicode_FromOrdinal('.');
+        locale_info->thousands_sep = PyUnicode_New(0, 0);
+        if (!locale_info->decimal_point || !locale_info->thousands_sep) {
+            Py_XDECREF(locale_info->decimal_point);
+            Py_XDECREF(locale_info->thousands_sep);
+            return -1;
+        }
         locale_info->grouping = no_grouping;
         break;
     default:
         assert(0);
     }
+    return 0;
+}
+
+static void
+free_locale_info(LocaleInfo *locale_info)
+{
+    Py_XDECREF(locale_info->decimal_point);
+    Py_XDECREF(locale_info->thousands_sep);
 }
 
 /************************************************************************/
@@ -769,7 +804,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,
 
     /* Locale settings, either from the actual locale or
        from a hard-code pseudo-locale */
-    LocaleInfo locale;
+    LocaleInfo locale = STATIC_LOCALE_INFO_INIT;
 
     /* no precision allowed on integers */
     if (format->precision != -1) {
@@ -868,18 +903,17 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,
     }
 
     /* Determine the grouping, separator, and decimal point, if any. */
-    get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
-                    (format->thousands_separators ?
-                     LT_DEFAULT_LOCALE :
-                     LT_NO_LOCALE),
-                    &locale);
+    if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
+                        (format->thousands_separators ?
+                         LT_DEFAULT_LOCALE :
+                         LT_NO_LOCALE),
+                        &locale) == -1)
+        goto done;
 
     /* Calculate how much memory we'll need. */
     n_total = calc_number_widths(&spec, n_prefix, sign_char, tmp, inumeric_chars,
-                                 inumeric_chars + n_digits, n_remainder, 0, &locale, format);
-
-    if (spec.n_lpadding || spec.n_spadding || spec.n_rpadding)
-        maxchar = Py_MAX(maxchar, format->fill_char);
+                                 inumeric_chars + n_digits, n_remainder, 0,
+                                 &locale, format, &maxchar);
 
     /* Allocate the memory. */
     result = PyUnicode_New(n_total, maxchar);
@@ -897,6 +931,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,
 
 done:
     Py_XDECREF(tmp);
+    free_locale_info(&locale);
     assert(!result || _PyUnicode_CheckConsistency(result, 1));
     return result;
 }
@@ -938,7 +973,7 @@ format_float_internal(PyObject *value,
 
     /* Locale settings, either from the actual locale or
        from a hard-code pseudo-locale */
-    LocaleInfo locale;
+    LocaleInfo locale = STATIC_LOCALE_INFO_INIT;
 
     if (format->alternate)
         flags |= Py_DTSF_ALT;
@@ -1009,19 +1044,17 @@ format_float_internal(PyObject *value,
     parse_number(unicode_tmp, index, index + n_digits, &n_remainder, &has_decimal);
 
     /* Determine the grouping, separator, and decimal point, if any. */
-    get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
-                    (format->thousands_separators ?
-                     LT_DEFAULT_LOCALE :
-                     LT_NO_LOCALE),
-                    &locale);
+    if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
+                        (format->thousands_separators ?
+                         LT_DEFAULT_LOCALE :
+                         LT_NO_LOCALE),
+                        &locale) == -1)
+        goto done;
 
     /* Calculate how much memory we'll need. */
     n_total = calc_number_widths(&spec, 0, sign_char, unicode_tmp, index,
                                  index + n_digits, n_remainder, has_decimal,
-                                 &locale, format);
-
-    if (spec.n_lpadding || spec.n_spadding || spec.n_rpadding)
-        maxchar = Py_MAX(maxchar, format->fill_char);
+                                 &locale, format, &maxchar);
 
     /* Allocate the memory. */
     result = PyUnicode_New(n_total, maxchar);
@@ -1040,6 +1073,7 @@ format_float_internal(PyObject *value,
 done:
     PyMem_Free(buf);
     Py_DECREF(unicode_tmp);
+    free_locale_info(&locale);
     assert(!result || _PyUnicode_CheckConsistency(result, 1));
     return result;
 }
@@ -1094,7 +1128,7 @@ format_complex_internal(PyObject *value,
 
     /* Locale settings, either from the actual locale or
        from a hard-code pseudo-locale */
-    LocaleInfo locale;
+    LocaleInfo locale = STATIC_LOCALE_INFO_INIT;
 
     /* Zero padding is not allowed. */
     if (format->fill_char == '0') {
@@ -1190,11 +1224,12 @@ format_complex_internal(PyObject *value,
                  &n_im_remainder, &im_has_decimal);
 
     /* Determine the grouping, separator, and decimal point, if any. */
-    get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
-                    (format->thousands_separators ?
-                     LT_DEFAULT_LOCALE :
-                     LT_NO_LOCALE),
-                    &locale);
+    if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
+                        (format->thousands_separators ?
+                         LT_DEFAULT_LOCALE :
+                         LT_NO_LOCALE),
+                        &locale) == -1)
+        goto done;
 
     /* Turn off any padding. We'll do it later after we've composed
        the numbers without padding. */
@@ -1205,7 +1240,8 @@ format_complex_internal(PyObject *value,
     /* Calculate how much memory we'll need. */
     n_re_total = calc_number_widths(&re_spec, 0, re_sign_char, re_unicode_tmp,
                                     i_re, i_re + n_re_digits, n_re_remainder,
-                                    re_has_decimal, &locale, &tmp_format);
+                                    re_has_decimal, &locale, &tmp_format,
+                                    &maxchar);
 
     /* Same formatting, but always include a sign, unless the real part is
      * going to be omitted, in which case we use whatever sign convention was
@@ -1214,7 +1250,8 @@ format_complex_internal(PyObject *value,
         tmp_format.sign = '+';
     n_im_total = calc_number_widths(&im_spec, 0, im_sign_char, im_unicode_tmp,
                                     i_im, i_im + n_im_digits, n_im_remainder,
-                                    im_has_decimal, &locale, &tmp_format);
+                                    im_has_decimal, &locale, &tmp_format,
+                                    &maxchar);
 
     if (skip_re)
         n_re_total = 0;
@@ -1223,9 +1260,7 @@ format_complex_internal(PyObject *value,
     calc_padding(n_re_total + n_im_total + 1 + add_parens * 2,
                  format->width, format->align, &lpad, &rpad, &total);
 
-    if (re_spec.n_lpadding || re_spec.n_spadding || re_spec.n_rpadding
-        || im_spec.n_lpadding || im_spec.n_spadding || im_spec.n_rpadding
-        || lpad || rpad)
+    if (lpad || rpad)
         maxchar = Py_MAX(maxchar, format->fill_char);
 
     result = PyUnicode_New(total, maxchar);
@@ -1275,6 +1310,7 @@ done:
     PyMem_Free(im_buf);
     Py_XDECREF(re_unicode_tmp);
     Py_XDECREF(im_unicode_tmp);
+    free_locale_info(&locale);
     assert(!result || _PyUnicode_CheckConsistency(result, 1));
     return result;
 }