mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
fix windows locale
This commit is contained in:
1
Lib/test/test_locale.py
vendored
1
Lib/test/test_locale.py
vendored
@@ -511,7 +511,6 @@ class TestRealLocales(unittest.TestCase):
|
||||
self.skipTest(f"setlocale(LC_CTYPE, {loc!r}) failed: {exc!r}")
|
||||
self.assertEqual(loc, locale.getlocale(locale.LC_CTYPE))
|
||||
|
||||
@unittest.expectedFailureIfWindows('TODO: RUSTPYTHON; Error not raised')
|
||||
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
|
||||
def test_setlocale_long_encoding(self):
|
||||
with self.assertRaises(locale.Error):
|
||||
|
||||
@@ -198,6 +198,34 @@ mod _locale {
|
||||
locale: OptionalArg<Option<PyStrRef>>,
|
||||
}
|
||||
|
||||
/// Maximum code page encoding name length on Windows
|
||||
#[cfg(windows)]
|
||||
const MAX_CP_LEN: usize = 15;
|
||||
|
||||
/// Check if the encoding part of a locale string is too long (Windows only)
|
||||
#[cfg(windows)]
|
||||
fn check_locale_name(locale: &str) -> bool {
|
||||
if let Some(dot_pos) = locale.find('.') {
|
||||
let encoding_part = &locale[dot_pos + 1..];
|
||||
// Find the end of encoding (could be followed by '@' modifier)
|
||||
let encoding_len = encoding_part.find('@').unwrap_or(encoding_part.len());
|
||||
encoding_len <= MAX_CP_LEN
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Check locale names for LC_ALL (handles semicolon-separated locales)
|
||||
#[cfg(windows)]
|
||||
fn check_locale_name_all(locale: &str) -> bool {
|
||||
for part in locale.split(';') {
|
||||
if !check_locale_name(part) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn setlocale(args: LocaleArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let error = error(vm);
|
||||
@@ -208,6 +236,21 @@ mod _locale {
|
||||
let result = match args.locale.flatten() {
|
||||
None => libc::setlocale(args.category, ptr::null()),
|
||||
Some(locale) => {
|
||||
// On Windows, validate encoding name length
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let valid = if args.category == LC_ALL {
|
||||
check_locale_name_all(locale.as_str())
|
||||
} else {
|
||||
check_locale_name(locale.as_str())
|
||||
};
|
||||
if !valid {
|
||||
return Err(vm.new_exception_msg(
|
||||
error,
|
||||
String::from("unsupported locale setting"),
|
||||
));
|
||||
}
|
||||
}
|
||||
let c_locale: CString =
|
||||
CString::new(locale.as_str()).map_err(|e| e.to_pyexception(vm))?;
|
||||
libc::setlocale(args.category, c_locale.as_ptr())
|
||||
|
||||
Reference in New Issue
Block a user