Skip to content

Commit c17ff5c

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 3fc7080 commit c17ff5c

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
@@ -144,6 +144,7 @@ locale_is_ascii(const char *str)
144144
static int
145145
locale_decode_monetary(PyObject *dict, struct lconv *lc)
146146
{
147+
#ifndef MS_WINDOWS
147148
int change_locale;
148149
change_locale = (!locale_is_ascii(lc->int_curr_symbol)
149150
|| !locale_is_ascii(lc->currency_symbol)
@@ -179,12 +180,18 @@ locale_decode_monetary(PyObject *dict, struct lconv *lc)
179180
}
180181
}
181182

183+
#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
184+
#else /* MS_WINDOWS */
185+
/* Use _W_* fields of Windows struct lconv */
186+
#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
187+
#endif /* MS_WINDOWS */
188+
182189
int res = -1;
183190

184191
#define RESULT_STRING(ATTR) \
185192
do { \
186193
PyObject *obj; \
187-
obj = PyUnicode_DecodeLocale(lc->ATTR, NULL); \
194+
obj = GET_LOCALE_STRING(ATTR); \
188195
if (obj == NULL) { \
189196
goto done; \
190197
} \
@@ -200,14 +207,17 @@ locale_decode_monetary(PyObject *dict, struct lconv *lc)
200207
RESULT_STRING(mon_decimal_point);
201208
RESULT_STRING(mon_thousands_sep);
202209
#undef RESULT_STRING
210+
#undef GET_LOCALE_STRING
203211

204212
res = 0;
205213

206214
done:
215+
#ifndef MS_WINDOWS
207216
if (loc != NULL) {
208217
setlocale(LC_CTYPE, oldloc);
209218
}
210219
PyMem_Free(oldloc);
220+
#endif
211221
return res;
212222
}
213223

@@ -243,9 +253,15 @@ PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
243253
Py_DECREF(obj); \
244254
} while (0)
245255

256+
#ifdef MS_WINDOWS
257+
/* Use _W_* fields of Windows struct lconv */
258+
#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
259+
#else
260+
#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
261+
#endif
246262
#define RESULT_STRING(s)\
247263
do { \
248-
x = PyUnicode_DecodeLocale(lc->s, NULL); \
264+
x = GET_LOCALE_STRING(s); \
249265
RESULT(#s, x); \
250266
} while (0)
251267

@@ -274,8 +290,10 @@ PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
274290
RESULT_INT(n_sign_posn);
275291

276292
/* Numeric information: LC_NUMERIC encoding */
277-
PyObject *decimal_point, *thousands_sep;
293+
PyObject *decimal_point = NULL, *thousands_sep = NULL;
278294
if (_Py_GetLocaleconvNumeric(lc, &decimal_point, &thousands_sep) < 0) {
295+
Py_XDECREF(decimal_point);
296+
Py_XDECREF(thousands_sep);
279297
goto failed;
280298
}
281299

@@ -304,6 +322,7 @@ PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
304322
#undef RESULT
305323
#undef RESULT_STRING
306324
#undef RESULT_INT
325+
#undef GET_LOCALE_STRING
307326
}
308327

309328
#if defined(HAVE_WCSCOLL)

Python/fileutils.c

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

2035+
#ifndef MS_WINDOWS
20352036
int change_locale = 0;
20362037
if ((strlen(lc->decimal_point) > 1 || ((unsigned char)lc->decimal_point[0]) > 127)) {
20372038
change_locale = 1;
@@ -2070,24 +2071,34 @@ _Py_GetLocaleconvNumeric(struct lconv *lc,
20702071
}
20712072
}
20722073

2074+
#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
2075+
#else /* MS_WINDOWS */
2076+
/* Use _W_* fields of Windows strcut lconv */
2077+
#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
2078+
#endif /* MS_WINDOWS */
2079+
20732080
int res = -1;
20742081

2075-
*decimal_point = PyUnicode_DecodeLocale(lc->decimal_point, NULL);
2082+
*decimal_point = GET_LOCALE_STRING(decimal_point);
20762083
if (*decimal_point == NULL) {
20772084
goto done;
20782085
}
20792086

2080-
*thousands_sep = PyUnicode_DecodeLocale(lc->thousands_sep, NULL);
2087+
*thousands_sep = GET_LOCALE_STRING(thousands_sep);
20812088
if (*thousands_sep == NULL) {
20822089
goto done;
20832090
}
20842091

20852092
res = 0;
20862093

20872094
done:
2095+
#ifndef MS_WINDOWS
20882096
if (loc != NULL) {
20892097
setlocale(LC_CTYPE, oldloc);
20902098
}
20912099
PyMem_Free(oldloc);
2100+
#endif
20922101
return res;
2102+
2103+
#undef GET_LOCALE_STRING
20932104
}

0 commit comments

Comments
 (0)