From d8e582ef6eb19233d24aff86dca8872b972cafe4 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" <69878+youknowone@users.noreply.github.com> Date: Mon, 2 Feb 2026 02:02:12 +0900 Subject: [PATCH] _locale.localeconv (#6941) --- Lib/test/test__locale.py | 2 -- crates/stdlib/src/locale.rs | 40 +++++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/Lib/test/test__locale.py b/Lib/test/test__locale.py index 054a6562f..11b2c9545 100644 --- a/Lib/test/test__locale.py +++ b/Lib/test/test__locale.py @@ -155,7 +155,6 @@ class _LocaleTests(unittest.TestCase): if not tested: self.skipTest('no suitable locales') - @unittest.skipIf(sys.platform in ('darwin', 'win32'), "TODO: RUSTPYTHON thread 'main' (18894384) panicked at crates/stdlib/src/locale.rs:106:14: localeconv always return decodable string: Utf8Error { valid_up_to: 0, error_len: Some(1) }") @unittest.skipIf(support.linked_to_musl(), "musl libc issue, bpo-46390") def test_lc_numeric_localeconv(self): # Test localeconv against known values @@ -269,7 +268,6 @@ class _LocaleTests(unittest.TestCase): if not tested: self.skipTest('no suitable locales') - @unittest.skipIf(sys.platform in ('darwin', 'win32'), "TODO: RUSTPYTHON thread 'main' (18894384) panicked at crates/stdlib/src/locale.rs:106:14: localeconv always return decodable string: Utf8Error { valid_up_to: 0, error_len: Some(1) }") def test_float_parsing(self): # Bug #1391872: Test whether float parsing is okay on European # locales. diff --git a/crates/stdlib/src/locale.rs b/crates/stdlib/src/locale.rs index 98db77d0d..496325b50 100644 --- a/crates/stdlib/src/locale.rs +++ b/crates/stdlib/src/locale.rs @@ -101,10 +101,42 @@ mod _locale { unsafe fn pystr_from_raw_cstr(vm: &VirtualMachine, raw_ptr: *const libc::c_char) -> PyResult { let slice = unsafe { CStr::from_ptr(raw_ptr) }; - let string = slice - .to_str() - .expect("localeconv always return decodable string"); - Ok(vm.new_pyobj(string)) + + // Fast path: ASCII/UTF-8 + if let Ok(s) = slice.to_str() { + return Ok(vm.new_pyobj(s)); + } + + // On Windows, locale strings use the ANSI code page encoding + #[cfg(windows)] + { + use windows_sys::Win32::Globalization::{CP_ACP, MultiByteToWideChar}; + let bytes = slice.to_bytes(); + unsafe { + let len = MultiByteToWideChar( + CP_ACP, + 0, + bytes.as_ptr(), + bytes.len() as i32, + ptr::null_mut(), + 0, + ); + if len > 0 { + let mut wide = vec![0u16; len as usize]; + MultiByteToWideChar( + CP_ACP, + 0, + bytes.as_ptr(), + bytes.len() as i32, + wide.as_mut_ptr(), + len, + ); + return Ok(vm.new_pyobj(String::from_utf16_lossy(&wide))); + } + } + } + + Ok(vm.new_pyobj(String::from_utf8_lossy(slice.to_bytes()).into_owned())) } #[pyattr(name = "Error", once)]