Skip to content

test_alt_digits_nl_langinfo fails for locale uk_UA #133740

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
pablogsal opened this issue May 9, 2025 · 23 comments
Closed

test_alt_digits_nl_langinfo fails for locale uk_UA #133740

pablogsal opened this issue May 9, 2025 · 23 comments
Labels
tests Tests in the Lib/test dir type-bug An unexpected behavior, bug, or error

Comments

@pablogsal
Copy link
Member

pablogsal commented May 9, 2025

Bug report

Bug description:

test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) ...
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='sr_YU') ... skipped "no locale 'sr_YU'"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='uk_UA') ... ERROR
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='lzh_TW.UTF-8') ... skipped "no locale 'lzh_TW.UTF-8'"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='shn_MM.UTF-8') ... skipped "no locale 'shn_MM.UTF-8'"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='ar_AE.UTF-8') ... skipped "ALT_DIGITS is not set for locale 'ar_AE.UTF-8' on this platform"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='bn_IN.UTF-8') ... skipped "ALT_DIGITS is not set for locale 'bn_IN.UTF-8' on this platform"
test_era_nl_langinfo (test.test__locale._LocaleTests.test_era_nl_langinfo) ...
  test_era_nl_langinfo (test.test__locale._LocaleTests.test_era_nl_langinfo) (locale='sr_YU') ... skipped "no locale 'sr_YU'"
  test_era_nl_langinfo (test.test__locale._LocaleTests.test_era_nl_langinfo) (locale='lzh_TW.UTF-8') ... skipped "no locale 'lzh_TW.UTF-8'"
  test_era_nl_langinfo (test.test__locale._LocaleTests.test_era_nl_langinfo) (locale='shn_MM.UTF-8') ... skipped "no locale 'shn_MM.UTF-8'"
test_float_parsing (test.test__locale._LocaleTests.test_float_parsing) ... ok
test_lc_numeric_basic (test.test__locale._LocaleTests.test_lc_numeric_basic) ... ok
test_lc_numeric_localeconv (test.test__locale._LocaleTests.test_lc_numeric_localeconv) ... ok
test_lc_numeric_nl_langinfo (test.test__locale._LocaleTests.test_lc_numeric_nl_langinfo) ... ok

======================================================================
ERROR: test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='uk_UA')
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/bb/data/tmp/314/refroot/amd64/opt/bb/lib64/python3.14/test/test__locale.py", line 220, in test_alt_digits_nl_langinfo
    alt_digits = nl_langinfo(locale.ALT_DIGITS)
UnicodeDecodeError: 'locale' codec can't decode byte 0xde in position 4: decoding error

----------------------------------------------------------------------
Ran 6 tests in 0.012s

This is in a Red Hat Enterprise Linux Server release 7.6 (Maipo) machine

CPython versions tested on:

CPython main branch, 3.14

Operating systems tested on:

Linux

Linked PRs

@pablogsal pablogsal added the type-bug An unexpected behavior, bug, or error label May 9, 2025
@pablogsal
Copy link
Member Author

CC @vstinner @serhiy-storchaka

@serhiy-storchaka
Copy link
Member

This is weird. ALT_DIGITS should be empty for uk_UA, as for most locales. Most likely this is a platform bug.

How old is RHELS 7.6? Is it new or ancient? Does the test pass on other versions? What version of libc?

@pablogsal
Copy link
Member Author

pablogsal commented May 9, 2025

Sort of ancient (from 2014) :)

This is the version of glib:

glibc-2.17-260.el7_6.6.x86_64
glibc-2.17-260.el7_6.6.i686

@pablogsal
Copy link
Member Author

pablogsal commented May 9, 2025

Interestingly when I test with this:

#include <stdio.h>
#include <locale.h>
#include <langinfo.h>

int main() {
    // Set the locale to Ukrainian (Ukraine)
    if (setlocale(LC_ALL, "uk_UA") == NULL) {
        perror("Unable to set uk_UA locale");
        return 1;
    }

    // Get ALT_DIGITS using nl_langinfo
#ifdef ALT_DIGITS
    const char *alt_digits = nl_langinfo(ALT_DIGITS);
    printf("ALT_DIGITS for uk_UA: %s\n", alt_digits);
#else
    printf("ALT_DIGITS is not supported on this system.\n");
#endif

    return 0;

I get:

ALT_DIGITS for uk_UA: 0

@pablogsal
Copy link
Member Author

pablogsal commented May 9, 2025

Also tried this:

(refroot)$ cat lol.py
import locale

def get_alt_digits(locale_name):
    try:
        # Set the locale
        locale.setlocale(locale.LC_ALL, locale_name)
        # Get ALT_DIGITS
        alt_digits = locale.nl_langinfo(locale.ALT_DIGITS)
        print(f"ALT_DIGITS for {locale_name}: {alt_digits}")
    except AttributeError:
        print("ALT_DIGITS is not available in this Python implementation.")
    except locale.Error as e:
        print(f"Locale error: {e}")

# Test with Ukrainian locale
get_alt_digits('uk_UA.UTF-8')

This prints:

ALT_DIGITS for uk_UA.UTF-8: 0;січня;лютого;березня;квітня;травня;червня;липня;серпня;вересня;жовтня;листопада;грудня

and with this:

get_alt_digits('uk_UA')

prints

Traceback (most recent call last):
  File "/bb/data/tmp/314/lol.py", line 16, in <module>
    get_alt_digits('uk_UA')
    ~~~~~~~~~~~~~~^^^^^^^^^
  File "/bb/data/tmp/314/lol.py", line 8, in get_alt_digits
    alt_digits = locale.nl_langinfo(locale.ALT_DIGITS)
UnicodeDecodeError: 'locale' codec can't decode byte 0xde in position 4: decoding error

@pablogsal
Copy link
Member Author

Some investigation with gdb:

#0  _locale_nl_langinfo_impl (module=0x7fffefc810d0, item=131119) at /opt/bb/src/python/python3.14/Modules/_localemodule.c:692
692	            result = result != NULL ? result : "";
(gdb) l
687	    for (i = 0; langinfo_constants[i].name; i++) {
688	        if (langinfo_constants[i].value == item) {
689	            /* Check NULL as a workaround for GNU libc's returning NULL
690	               instead of an empty string for nl_langinfo(ERA).  */
691	            const char *result = nl_langinfo(item);
692	            result = result != NULL ? result : "";
693	            char *oldloc = NULL;
694	            if (langinfo_constants[i].category != LC_CTYPE
695	                && !is_all_ascii(result)
696	                && change_locale(langinfo_constants[i].category, &oldloc) < 0)
(gdb) p result
$8 = 0x7ffff59dc244 "0"
(gdb) p item
$9 = 131119
(gdb) n
693	            char *oldloc = NULL;
(gdb)
694	            if (langinfo_constants[i].category != LC_CTYPE
(gdb)
695	                && !is_all_ascii(result)
(gdb)
696	                && change_locale(langinfo_constants[i].category, &oldloc) < 0)
(gdb)
706	            if (item == ALT_DIGITS && *result) {
(gdb) p item == ALT_DIGITS && *result
$10 = 1
(gdb) n
707	                pyresult = decode_strings(result, 100);
(gdb) p result
$11 = 0x7ffff59dc244 "0"
(gdb) p decode_strings(result, 100)
$12 = (PyObject *) 0x0

@picnixz picnixz added the tests Tests in the Lib/test dir label May 9, 2025
@pablogsal
Copy link
Member Author

Looks like this is the problem:

(gdb) p (char*)(nl_langinfo(item))
$6 = 0x7ffff59dc244 "0"

@vstinner
Copy link
Member

vstinner commented May 9, 2025

Related changes:

commit dcc4fb2c9068f60353f0c0978948b7681f7745e6
Author: Serhiy Storchaka <storchaka@gmail.com>
Date:   Mon Oct 21 21:54:12 2024 +0300

    gh-124969: Make locale.nl_langinfo(locale.ALT_DIGITS) returning a string again (GH-125774)
    
    This is a follow up of GH-124974. Only Glibc needed a fix.
    Now the returned value is a string consisting of semicolon-separated
    symbols on all Posix platforms.

commit 21c04e1a972bd1b6285e0ea41fa107d635bbe43a
Author: Serhiy Storchaka <storchaka@gmail.com>
Date:   Wed Oct 9 11:42:08 2024 +0300

    gh-124969: Fix locale.nl_langinfo(locale.ALT_DIGITS) (GH-124974)
    
    Now it returns a tuple of up to 100 strings (an empty tuple on most locales).
    Previously it returned the first item of that tuple or an empty string.

@vstinner
Copy link
Member

vstinner commented May 9, 2025

Looks like this is the problem:
(gdb) p (char*)(nl_langinfo(item))
$6 = 0x7ffff59dc244 "0"

You should look further in the string since glibc uses NUL separator in ALT_DIGITS value.

$ gdb ./python
(gdb) run
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'ja_JP')
'ja_JP'
>>> locale.nl_langinfo(locale.ALT_DIGITS)
^C

(gdb) b decode_strings
(gdb) continue

>>> locale.nl_langinfo(locale.ALT_DIGITS)

Breakpoint 1, decode_strings (result=result@entry=0x7ffff2ae0caa "\241\273", max_count=max_count@entry=100)
    at ./Modules/_localemodule.c:643
643	{

# First
(gdb) p result
$19 = 0x7ffff2ae0caa "\241\273"

# Second
(gdb) p /x result[3]
$26 = 0xb0
(gdb) p /x result[4]
$27 = 0xec
(gdb) p /x result[5]
$28 = 0x0

# Third
(gdb) p /x result[6]
$30 = 0xc6
(gdb) p /x result[7]
$31 = 0xf3
(gdb) p /x result[8]
$32 = 0x0

# ...

(gdb) continue

# nl_langinfo() result in Python:
'〇;一;二;三;四;五;六;七;八;九;十;十一;十二;十三;十四;十五;十六;十七;十八;十九;二十;二十一;二十二;二十三;二十四;二十五;二十六;二十七;二十八;二十九;三十;三十一;三十二;三十三;三十四;三十五;三十六;三十七;三十八;三十九;四十;四十一;四十二;四十三;四十四;四十五;四十六;四十七;四十八;四十九;五十;五十一;五十二;五十三;五十四;五十五;五十六;五十七;五十八;五十九;六十;六十一;六十二;六十三;六十四;六十五;六十六;六十七;六十八;六十九;七十;七十一;七十二;七十三;七十四;七十五;七十六;七十七;七十八;七十九;八十;八十一;八十二;八十三;八十四;八十五;八十六;八十七;八十八;八十九;九十;九十一;九十二;九十三;九十四;九十五;九十六;九十七;九十八;九十九'

@pablogsal
Copy link
Member Author

You should look further in the string since glibc uses NUL separator in ALT_DIGITS value.

Yeah but that's the problem I think: we are passing the 0 directly to decode string, no? Or who you mean by "you" here?

@serhiy-storchaka
Copy link
Member

There was a hack that used ALT_DIGITS for month names in a genitive case. It was removed in https://sourceware.org/git/?p=glibc.git;a=commit;h=86530b9fed4466a7c05e20ec4d5fd89b4dc41fa6 .

Glibc uses null separator instead of ";" for ALT_DIGITS (in violation of Posix). This is why you get "0". Python has a work around this, so it sees the whole thing, including non-ASCII month names.

Binary locale files for the "uk_UA" locale are created using the "KOI8-U" encoding, as specified in localedata/SUPPORTED. But it seems that UTF-8 was used for decoding. Could you please print the results of setlocale(LC_CTYPE, NULL) and setlocale(LC_TIME, NULL)? And the result of nl_langinfo(CODESET) after calling setlocale(LC_CTYPE, setlocale(LC_TIME, NULL))?

@pablogsal
Copy link
Member Author

pablogsal commented May 9, 2025

(gdb) list
641	static PyObject *
642	decode_strings(const char *result, size_t max_count)
643	{
644	    /* Convert a sequence of NUL-separated C strings to a Python string
645	     * containing semicolon separated items. */
646	    size_t i = 0;
647	    size_t count = 0;
648	    for (; count < max_count && result[i]; count++) {
649	        i += strlen(result + i) + 1;
(gdb) x /20 result
0x7ffff59dc244:	0x30	0x00	0xd3	0xa6	0xde	0xce	0xd1	0x00
0x7ffff59dc24c:	0xcc	0xc0	0xd4	0xcf	0xc7	0xcf	0x00	0xc2
0x7ffff59dc254:	0xc5	0xd2	0xc5	0xda
(gdb) p result
$7 = 0x7ffff59dc244 "0"

@pablogsal
Copy link
Member Author

There was a hack that used ALT_DIGITS for month names in a genitive case. It was removed in https://sourceware.org/git/?p=glibc.git;a=commit;h=86530b9fed4466a7c05e20ec4d5fd89b4dc41fa6 .

Glibc uses null separator instead of ";" for ALT_DIGITS (in violation of Posix). This is why you get "0". Python has a work around this, so it sees the whole thing, including non-ASCII month names.

Binary locale files for the "uk_UA" locale are created using the "KOI8-U" encoding, as specified in localedata/SUPPORTED. But it seems that UTF-8 was used for decoding. Could you please print the results of setlocale(LC_CTYPE, NULL) and setlocale(LC_TIME, NULL)? And the result of nl_langinfo(CODESET) after calling setlocale(LC_CTYPE, setlocale(LC_TIME, NULL))?

#include <stdio.h>
#include <locale.h>
#include <langinfo.h>

int main() {
    // Set LC_ALL to uk_UA (should use KOI8-U encoding)
    if (!setlocale(LC_ALL, "uk_UA")) {
        perror("Could not set uk_UA locale");
        return 1;
    }

    // Print current LC_CTYPE and LC_TIME
    const char *ctype_locale = setlocale(LC_CTYPE, NULL);
    const char *time_locale = setlocale(LC_TIME, NULL);

    printf("LC_CTYPE: %s\n", ctype_locale);
    printf("LC_TIME:  %s\n", time_locale);

    // Set LC_CTYPE to LC_TIME
    if (!setlocale(LC_CTYPE, time_locale)) {
        perror("Failed to set LC_CTYPE to LC_TIME value");
        return 1;
    }

    // Print CODESET after changing LC_CTYPE
    const char *codeset = nl_langinfo(CODESET);
    printf("CODESET after setting LC_CTYPE = LC_TIME: %s\n", codeset);

    return 0;
}

gives

LC_CTYPE: uk_UA
LC_TIME:  uk_UA
CODESET after setting LC_CTYPE = LC_TIME: KOI8-U

@vstinner
Copy link
Member

vstinner commented May 9, 2025

Binary locale files for the "uk_UA" locale are created using the "KOI8-U" encoding, as specified in localedata/SUPPORTED. But it seems that UTF-8 was used for decoding.

(gdb) x /20 result
0x7ffff59dc244:	0x30	0x00	0xd3	0xa6	0xde	0xce	0xd1	0x00

It confirms that ALT_DIGITS is encoded to KOI8-U:

$ python
>>> b'\xd3\xa6\xde\xce\xd1\x00'.decode('utf8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xde in position 2: invalid continuation byte

>>> b'\xd3\xa6\xde\xce\xd1\x00'.decode('koi8-u')
'січня\x00'

"січня" means January.

@serhiy-storchaka
Copy link
Member

Now, could you please add print(loc, setlocale(LC_TIME), setlocale(LC_CTYPE)) in test_alt_digits_nl_langinfo? What does it print for uk_UA?

By the way, is Python running with options or environment variables that force PyUnicode_DecodeLocale() to use UTF-8?

@pablogsal
Copy link
Member Author

Now, could you please add print(loc, setlocale(LC_TIME), setlocale(LC_CTYPE)) in test_alt_digits_nl_langinfo? What does it print for uk_UA?

uk_UA uk_UA en_US.UTF-8

By the way, is Python running with options or environment variables that force PyUnicode_DecodeLocale() to use UTF-8?

No, just regular python3.14 -m test test__locale -v no extra env vars

@serhiy-storchaka
Copy link
Member

Thank you, @pablogsal.

Is the LC_ALL category set? What if set the LC_ALL environment variable to an empty string or to "uk_UA" before running the test?

@pablogsal
Copy link
Member Author

pablogsal commented May 10, 2025

Thank you, @pablogsal.

Is the LC_ALL category set?

No:

$ env | grep LC
LC_CTYPE=en_US.UTF-8

What if set the LC_ALL environment variable to an empty string or to "uk_UA" before running the test?

When using an empty string it fails the same:

(refroot)$ export LC_ALL=""
(refroot)$ python3.14 -m test test__locale -m test_alt_digits_nl_langinfo -v
== CPython 3.14.0b1 (main, May 8 2025, 10:45:27) [Clang 20.1.0 ]
== Linux-3.10.0-957.35.2.el7.x86_64-x86_64-with-glibc2.17 little-endian
== Python build: release shared
== cwd: /bb/data/tmp/test_python_worker_193055æ
== CPU count: 15 (process) / 16 (system)
== encodings: locale=UTF-8 FS=utf-8
== resources: all test resources are disabled, use -u option to unskip tests

Using random seed: 2476489759
0:00:00 load avg: 1.42 Run 1 test sequentially in a single process
0:00:00 load avg: 1.42 [1/1] test__locale
test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) ...
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='sr_YU') ... skipped "no locale 'sr_YU'"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='uk_UA') ... ERROR
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='lzh_TW.UTF-8') ... skipped "no locale 'lzh_TW.UTF-8'"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='shn_MM.UTF-8') ... skipped "no locale 'shn_MM.UTF-8'"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='ar_AE.UTF-8') ... skipped "ALT_DIGITS is not set for locale 'ar_AE.UTF-8' on this platform"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='bn_IN.UTF-8') ... skipped "ALT_DIGITS is not set for locale 'bn_IN.UTF-8' on this platform"

======================================================================
ERROR: test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='uk_UA')
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/bb/data/tmp/314/refroot/amd64/opt/bb/lib64/python3.14/test/test__locale.py", line 223, in test_alt_digits_nl_langinfo
    alt_digits = nl_langinfo(locale.ALT_DIGITS)
UnicodeDecodeError: 'locale' codec can't decode byte 0xde in position 4: decoding error

----------------------------------------------------------------------
Ran 1 test in 0.004s

FAILED (errors=1, skipped=5)
test test__locale failed
0:00:00 load avg: 1.42 [1/1/1] test__locale failed (1 error)

== Tests result: FAILURE ==

1 test failed:
    test__locale

Total duration: 47 ms
Total tests: run=1 (filtered) skipped=5
Total test files: run=1/1 (filtered) failed=1
Result: FAILURE

but when using uk_UA it works but because the test never rans:

(refroot)$ export LC_ALL="uk_UA"
(refroot)$ python3.14 -m test test__locale -m test_alt_digits_nl_langinfo -v
== CPython 3.14.0b1 (main, May 8 2025, 10:45:27) [Clang 20.1.0 ]
== Linux-3.10.0-957.35.2.el7.x86_64-x86_64-with-glibc2.17 little-endian
== Python build: release shared
== cwd: /bb/data/tmp/test_python_worker_193989�
== CPU count: 15 (process) / 16 (system)
== encodings: locale=KOI8-U FS=koi8-u
== resources: all test resources are disabled, use -u option to unskip tests

Using random seed: 3307150267
0:00:00 load avg: 1.11 Run 1 test sequentially in a single process
0:00:00 load avg: 1.11 [1/1] test__locale
test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) ...
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='sr_YU') ... skipped "no locale 'sr_YU'"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='lzh_TW.UTF-8') ... skipped "no locale 'lzh_TW.UTF-8'"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='shn_MM.UTF-8') ... skipped "no locale 'shn_MM.UTF-8'"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='ar_AE.UTF-8') ... skipped "ALT_DIGITS is not set for locale 'ar_AE.UTF-8' on this platform"
  test_alt_digits_nl_langinfo (test.test__locale._LocaleTests.test_alt_digits_nl_langinfo) (locale='bn_IN.UTF-8') ... skipped "ALT_DIGITS is not set for locale 'bn_IN.UTF-8' on this platform"

----------------------------------------------------------------------
Ran 1 test in 0.003s

OK (skipped=5)
0:00:00 load avg: 1.11 [1/1] test__locale passed

== Tests result: SUCCESS ==

1 test OK.

Total duration: 40 ms
Total tests: run=1 (filtered) skipped=5
Total test files: run=1/1 (filtered)
Result: SUCCESS

@pablogsal
Copy link
Member Author

@serhiy-storchaka do you have a preference in how we should address this? It's changing the locale when deciding enough?

@serhiy-storchaka
Copy link
Member

I'm out of ideas. For further research, we need to trace which exactly C functions are called and why mbstowcs() (if it was called) fails. I'll try to find a system with such an old glibc.

We could ignore the issue and skip the test for the uk_UA locale with old glibc, as it is a unique hack removed from glibc years ago. But I afraid that it may be a sign that we misunderstand something about locales, and that the code can fail on other locales, maybe for other nl_langinfo items, maybe on other platforms. They can just not be tested.

In long term we should use nl_langinfo_l() on platforms that support it.

@vstinner
Copy link
Member

I can reproduce the issue on RHEL 7.9 with this script:

import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
locale.setlocale(locale.LC_TIME, 'uk_UA')
alt_digits = locale.nl_langinfo(locale.ALT_DIGITS)
for item in alt_digits.split(';'):
  print(repr(item))

Error:

Traceback (most recent call last):
  File "/root/cpython/x.py", line 4, in <module>
    alt_digits = locale.nl_langinfo(locale.ALT_DIGITS)
UnicodeDecodeError: 'locale' codec can't decode byte 0xde in position 4: decoding error

The problem is the !is_all_ascii(result) test before calling change_locale(). The ALT_DIGITS string is separated by NUL characters, the first part is ASCII ("0"), whereas following parts are encoding to KOI8-U encoding.

The following patch fix the issue:

diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c
index ad61839..6f934e3 100644
--- a/Modules/_localemodule.c
+++ b/Modules/_localemodule.c
@@ -692,7 +692,6 @@
             result = result != NULL ? result : "";
             char *oldloc = NULL;
             if (langinfo_constants[i].category != LC_CTYPE
-                && !is_all_ascii(result)
                 && change_locale(langinfo_constants[i].category, &oldloc) < 0)
             {
                 return NULL;

Script output with the patch:

'0'
'січня'
'лютого'
'березня'
'квітня'
'травня'
'червня'
'липня'
'серпня'
'вересня'
'жовтня'
'листопада'
'грудня'

vstinner added a commit to vstinner/cpython that referenced this issue May 21, 2025
Set the LC_CTYPE locale to the LC_TIME locale even if
nl_langinfo(ALT_DIGITS) result is ASCII. The result is a list
separated by NUL characters and the code only checks the first list
item which can be ASCII whereas following items are non-ASCII.

Fix test__locale for the uk_UA locale on RHEL 7.
@serhiy-storchaka
Copy link
Member

Thank you for solving this mystery @vstinner. 👏

vstinner added a commit that referenced this issue May 22, 2025
Set the LC_CTYPE locale to the LC_TIME locale even if
nl_langinfo(ALT_DIGITS) result is ASCII. The result is a list
separated by NUL characters and the code only checks the first list
item which can be ASCII whereas following items are non-ASCII.

Fix test__locale for the uk_UA locale on RHEL 7.

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue May 22, 2025
Set the LC_CTYPE locale to the LC_TIME locale even if
nl_langinfo(ALT_DIGITS) result is ASCII. The result is a list
separated by NUL characters and the code only checks the first list
item which can be ASCII whereas following items are non-ASCII.

Fix test__locale for the uk_UA locale on RHEL 7.
(cherry picked from commit 899c7dc)

Co-authored-by: Victor Stinner <vstinner@python.org>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
vstinner added a commit that referenced this issue May 22, 2025
…4512)

gh-133740: Fix locale.nl_langinfo(ALT_DIGITS) (GH-134468)

Set the LC_CTYPE locale to the LC_TIME locale even if
nl_langinfo(ALT_DIGITS) result is ASCII. The result is a list
separated by NUL characters and the code only checks the first list
item which can be ASCII whereas following items are non-ASCII.

Fix test__locale for the uk_UA locale on RHEL 7.
(cherry picked from commit 899c7dc)

Co-authored-by: Victor Stinner <vstinner@python.org>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
@github-project-automation github-project-automation bot moved this from Todo to Done in Locale issues 🗺 May 25, 2025
@pablogsal
Copy link
Member Author

Thanks @serhiy-storchaka and @vstinner for the fix 🖤

lkollar pushed a commit to lkollar/cpython that referenced this issue May 26, 2025
Set the LC_CTYPE locale to the LC_TIME locale even if
nl_langinfo(ALT_DIGITS) result is ASCII. The result is a list
separated by NUL characters and the code only checks the first list
item which can be ASCII whereas following items are non-ASCII.

Fix test__locale for the uk_UA locale on RHEL 7.

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tests Tests in the Lib/test dir type-bug An unexpected behavior, bug, or error
Projects
Development

No branches or pull requests

4 participants