Skip to content

Commit 4cde523

Browse files
bpo-38324: Fix test__locale.py Windows failures (GH-20529)
Use wide-char _W_* fields of lconv structure on Windows Remove "ps_AF" from test__locale.known_numerics on Windows (cherry picked from commit f231203) Co-authored-by: TIGirardi <[email protected]>
1 parent d1eb755 commit 4cde523

File tree

4 files changed

+40
-5
lines changed

4 files changed

+40
-5
lines changed

Lib/test/test__locale.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ def accept(loc):
7272
'ps_AF': ('\u066b', '\u066c'),
7373
}
7474

75+
if sys.platform == 'win32':
76+
# ps_AF doesn't work on Windows: see bpo-38324 (msg361830)
77+
del known_numerics['ps_AF']
78+
7579
class _LocaleTests(unittest.TestCase):
7680

7781
def setUp(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Avoid Unicode errors when accessing certain locale data on Windows.

Modules/_localemodule.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ locale_is_ascii(const char *str)
131131
static int
132132
locale_decode_monetary(PyObject *dict, struct lconv *lc)
133133
{
134+
#ifndef MS_WINDOWS
134135
int change_locale;
135136
change_locale = (!locale_is_ascii(lc->int_curr_symbol)
136137
|| !locale_is_ascii(lc->currency_symbol)
@@ -166,12 +167,18 @@ locale_decode_monetary(PyObject *dict, struct lconv *lc)
166167
}
167168
}
168169

170+
#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
171+
#else /* MS_WINDOWS */
172+
/* Use _W_* fields of Windows struct lconv */
173+
#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
174+
#endif /* MS_WINDOWS */
175+
169176
int res = -1;
170177

171178
#define RESULT_STRING(ATTR) \
172179
do { \
173180
PyObject *obj; \
174-
obj = PyUnicode_DecodeLocale(lc->ATTR, NULL); \
181+
obj = GET_LOCALE_STRING(ATTR); \
175182
if (obj == NULL) { \
176183
goto done; \
177184
} \
@@ -187,14 +194,17 @@ locale_decode_monetary(PyObject *dict, struct lconv *lc)
187194
RESULT_STRING(mon_decimal_point);
188195
RESULT_STRING(mon_thousands_sep);
189196
#undef RESULT_STRING
197+
#undef GET_LOCALE_STRING
190198

191199
res = 0;
192200

193201
done:
202+
#ifndef MS_WINDOWS
194203
if (loc != NULL) {
195204
setlocale(LC_CTYPE, oldloc);
196205
}
197206
PyMem_Free(oldloc);
207+
#endif
198208
return res;
199209
}
200210

@@ -230,9 +240,15 @@ PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
230240
Py_DECREF(obj); \
231241
} while (0)
232242

243+
#ifdef MS_WINDOWS
244+
/* Use _W_* fields of Windows struct lconv */
245+
#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
246+
#else
247+
#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
248+
#endif
233249
#define RESULT_STRING(s)\
234250
do { \
235-
x = PyUnicode_DecodeLocale(lc->s, NULL); \
251+
x = GET_LOCALE_STRING(s); \
236252
RESULT(#s, x); \
237253
} while (0)
238254

@@ -261,8 +277,10 @@ PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
261277
RESULT_INT(n_sign_posn);
262278

263279
/* Numeric information: LC_NUMERIC encoding */
264-
PyObject *decimal_point, *thousands_sep;
280+
PyObject *decimal_point = NULL, *thousands_sep = NULL;
265281
if (_Py_GetLocaleconvNumeric(lc, &decimal_point, &thousands_sep) < 0) {
282+
Py_XDECREF(decimal_point);
283+
Py_XDECREF(thousands_sep);
266284
goto failed;
267285
}
268286

@@ -291,6 +309,7 @@ PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
291309
#undef RESULT
292310
#undef RESULT_STRING
293311
#undef RESULT_INT
312+
#undef GET_LOCALE_STRING
294313
}
295314

296315
#if defined(HAVE_WCSCOLL)

Python/fileutils.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,6 +1933,7 @@ _Py_GetLocaleconvNumeric(struct lconv *lc,
19331933
assert(decimal_point != NULL);
19341934
assert(thousands_sep != NULL);
19351935

1936+
#ifndef MS_WINDOWS
19361937
int change_locale = 0;
19371938
if ((strlen(lc->decimal_point) > 1 || ((unsigned char)lc->decimal_point[0]) > 127)) {
19381939
change_locale = 1;
@@ -1971,24 +1972,34 @@ _Py_GetLocaleconvNumeric(struct lconv *lc,
19711972
}
19721973
}
19731974

1975+
#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
1976+
#else /* MS_WINDOWS */
1977+
/* Use _W_* fields of Windows strcut lconv */
1978+
#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
1979+
#endif /* MS_WINDOWS */
1980+
19741981
int res = -1;
19751982

1976-
*decimal_point = PyUnicode_DecodeLocale(lc->decimal_point, NULL);
1983+
*decimal_point = GET_LOCALE_STRING(decimal_point);
19771984
if (*decimal_point == NULL) {
19781985
goto done;
19791986
}
19801987

1981-
*thousands_sep = PyUnicode_DecodeLocale(lc->thousands_sep, NULL);
1988+
*thousands_sep = GET_LOCALE_STRING(thousands_sep);
19821989
if (*thousands_sep == NULL) {
19831990
goto done;
19841991
}
19851992

19861993
res = 0;
19871994

19881995
done:
1996+
#ifndef MS_WINDOWS
19891997
if (loc != NULL) {
19901998
setlocale(LC_CTYPE, oldloc);
19911999
}
19922000
PyMem_Free(oldloc);
2001+
#endif
19932002
return res;
2003+
2004+
#undef GET_LOCALE_STRING
19942005
}

0 commit comments

Comments
 (0)