Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Lib/test/test__locale.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ def accept(loc):
'ps_AF': ('\u066b', '\u066c'),
}

if sys.platform == 'win32':
# ps_AF doesn't work on Windows: see bpo-38324 (msg361830)
del known_numerics['ps_AF']

class _LocaleTests(unittest.TestCase):

def setUp(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Avoid Unicode errors when accessing certain locale data on Windows.
25 changes: 22 additions & 3 deletions Modules/_localemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ locale_is_ascii(const char *str)
static int
locale_decode_monetary(PyObject *dict, struct lconv *lc)
{
#ifndef MS_WINDOWS
int change_locale;
change_locale = (!locale_is_ascii(lc->int_curr_symbol)
|| !locale_is_ascii(lc->currency_symbol)
Expand Down Expand Up @@ -166,12 +167,18 @@ locale_decode_monetary(PyObject *dict, struct lconv *lc)
}
}

#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
#else /* MS_WINDOWS */
/* Use _W_* fields of Windows struct lconv */
#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
#endif /* MS_WINDOWS */

int res = -1;

#define RESULT_STRING(ATTR) \
do { \
PyObject *obj; \
obj = PyUnicode_DecodeLocale(lc->ATTR, NULL); \
obj = GET_LOCALE_STRING(ATTR); \
if (obj == NULL) { \
goto done; \
} \
Expand All @@ -187,14 +194,17 @@ locale_decode_monetary(PyObject *dict, struct lconv *lc)
RESULT_STRING(mon_decimal_point);
RESULT_STRING(mon_thousands_sep);
#undef RESULT_STRING
#undef GET_LOCALE_STRING

res = 0;

done:
#ifndef MS_WINDOWS
if (loc != NULL) {
setlocale(LC_CTYPE, oldloc);
}
PyMem_Free(oldloc);
#endif
return res;
}

Expand Down Expand Up @@ -230,9 +240,15 @@ PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
Py_DECREF(obj); \
} while (0)

#ifdef MS_WINDOWS
/* Use _W_* fields of Windows struct lconv */
#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
#else
#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
#endif
#define RESULT_STRING(s)\
do { \
x = PyUnicode_DecodeLocale(lc->s, NULL); \
x = GET_LOCALE_STRING(s); \
RESULT(#s, x); \
} while (0)

Expand Down Expand Up @@ -261,8 +277,10 @@ PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
RESULT_INT(n_sign_posn);

/* Numeric information: LC_NUMERIC encoding */
PyObject *decimal_point, *thousands_sep;
PyObject *decimal_point = NULL, *thousands_sep = NULL;
if (_Py_GetLocaleconvNumeric(lc, &decimal_point, &thousands_sep) < 0) {
Py_XDECREF(decimal_point);
Py_XDECREF(thousands_sep);
goto failed;
}

Expand Down Expand Up @@ -291,6 +309,7 @@ PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
#undef RESULT
#undef RESULT_STRING
#undef RESULT_INT
#undef GET_LOCALE_STRING
}

#if defined(HAVE_WCSCOLL)
Expand Down
15 changes: 13 additions & 2 deletions Python/fileutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1933,6 +1933,7 @@ _Py_GetLocaleconvNumeric(struct lconv *lc,
assert(decimal_point != NULL);
assert(thousands_sep != NULL);

#ifndef MS_WINDOWS
int change_locale = 0;
if ((strlen(lc->decimal_point) > 1 || ((unsigned char)lc->decimal_point[0]) > 127)) {
change_locale = 1;
Expand Down Expand Up @@ -1971,24 +1972,34 @@ _Py_GetLocaleconvNumeric(struct lconv *lc,
}
}

#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
#else /* MS_WINDOWS */
/* Use _W_* fields of Windows strcut lconv */
#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
#endif /* MS_WINDOWS */

int res = -1;

*decimal_point = PyUnicode_DecodeLocale(lc->decimal_point, NULL);
*decimal_point = GET_LOCALE_STRING(decimal_point);
if (*decimal_point == NULL) {
goto done;
}

*thousands_sep = PyUnicode_DecodeLocale(lc->thousands_sep, NULL);
*thousands_sep = GET_LOCALE_STRING(thousands_sep);
if (*thousands_sep == NULL) {
goto done;
}

res = 0;

done:
#ifndef MS_WINDOWS
if (loc != NULL) {
setlocale(LC_CTYPE, oldloc);
}
PyMem_Free(oldloc);
#endif
return res;

#undef GET_LOCALE_STRING
}