Skip to content

Commit 6bed838

Browse files
committed
fix localeconv
1 parent 153b0da commit 6bed838

File tree

2 files changed

+36
-6
lines changed

2 files changed

+36
-6
lines changed

Lib/test/test__locale.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ def test_lc_numeric_nl_langinfo(self):
155155
if not tested:
156156
self.skipTest('no suitable locales')
157157

158-
@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) }")
159158
@unittest.skipIf(support.linked_to_musl(), "musl libc issue, bpo-46390")
160159
def test_lc_numeric_localeconv(self):
161160
# Test localeconv against known values
@@ -269,7 +268,6 @@ def test_era_nl_langinfo(self):
269268
if not tested:
270269
self.skipTest('no suitable locales')
271270

272-
@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) }")
273271
def test_float_parsing(self):
274272
# Bug #1391872: Test whether float parsing is okay on European
275273
# locales.

crates/stdlib/src/locale.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,42 @@ mod _locale {
101101

102102
unsafe fn pystr_from_raw_cstr(vm: &VirtualMachine, raw_ptr: *const libc::c_char) -> PyResult {
103103
let slice = unsafe { CStr::from_ptr(raw_ptr) };
104-
let string = slice
105-
.to_str()
106-
.expect("localeconv always return decodable string");
107-
Ok(vm.new_pyobj(string))
104+
105+
// Fast path: ASCII/UTF-8
106+
if let Ok(s) = slice.to_str() {
107+
return Ok(vm.new_pyobj(s));
108+
}
109+
110+
// On Windows, locale strings use the ANSI code page encoding
111+
#[cfg(windows)]
112+
{
113+
use windows_sys::Win32::Globalization::{CP_ACP, MultiByteToWideChar};
114+
let bytes = slice.to_bytes();
115+
unsafe {
116+
let len = MultiByteToWideChar(
117+
CP_ACP,
118+
0,
119+
bytes.as_ptr(),
120+
bytes.len() as i32,
121+
ptr::null_mut(),
122+
0,
123+
);
124+
if len > 0 {
125+
let mut wide = vec![0u16; len as usize];
126+
MultiByteToWideChar(
127+
CP_ACP,
128+
0,
129+
bytes.as_ptr(),
130+
bytes.len() as i32,
131+
wide.as_mut_ptr(),
132+
len,
133+
);
134+
return Ok(vm.new_pyobj(String::from_utf16_lossy(&wide)));
135+
}
136+
}
137+
}
138+
139+
Ok(vm.new_pyobj(String::from_utf8_lossy(slice.to_bytes()).into_owned()))
108140
}
109141

110142
#[pyattr(name = "Error", once)]

0 commit comments

Comments
 (0)