diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 2212d2323d..339c370088 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -403,7 +403,6 @@ def test_float__format__locale(self): self.assertEqual(locale.format_string('%g', x, grouping=True), format(x, 'n')) self.assertEqual(locale.format_string('%.10g', x, grouping=True), format(x, '.10n')) - @unittest.skip("TODO: RustPython format code n is not integrated with locale") @run_with_locale('LC_NUMERIC', 'en_US.UTF8') def test_int__format__locale(self): # test locale support for __format__ code 'n' for integers diff --git a/common/src/format.rs b/common/src/format.rs index ca994c6dbe..942ecdc90c 100644 --- a/common/src/format.rs +++ b/common/src/format.rs @@ -5,6 +5,9 @@ use num_bigint::{BigInt, Sign}; use num_traits::{cast::ToPrimitive, Signed}; use std::{cmp, str::FromStr}; +pub struct Locale; +pub type LocaleFunc = fn() -> Locale; + trait FormatParse { fn parse(text: &str) -> (Option, &str) where @@ -312,6 +315,7 @@ impl FormatSpec { inter: i32, sep: char, disp_digit_cnt: i32, + locale_info: Option, // will be used to calculate numbers here ) -> String { // Don't add separators to the floating decimal point of numbers let mut parts = magnitude_str.splitn(2, '.'); @@ -391,7 +395,12 @@ impl FormatSpec { } } - fn add_magnitude_separators(&self, magnitude_str: String, prefix: &str) -> String { + fn add_magnitude_separators( + &self, + magnitude_str: String, + prefix: &str, + locale_info: Option, + ) -> String { match &self.grouping_option { Some(fg) => { let sep = match fg { @@ -407,6 +416,7 @@ impl FormatSpec { inter, sep, disp_digit_cnt, + locale_info, ) } None => magnitude_str, @@ -487,7 +497,7 @@ impl FormatSpec { FormatSign::MinusOrSpace => " ", } }; - let magnitude_str = self.add_magnitude_separators(raw_magnitude_str?, sign_str); + let magnitude_str = self.add_magnitude_separators(raw_magnitude_str?, sign_str, None); self.format_sign_and_align( unsafe { &BorrowedStr::from_ascii_unchecked(magnitude_str.as_bytes()) }, sign_str, @@ -503,7 +513,11 @@ impl FormatSpec { } } - pub fn format_int(&self, num: &BigInt) -> Result { + pub fn format_int( + &self, + num: &BigInt, + locale_info: Option, + ) -> Result { self.validate_format(FormatType::Decimal)?; let magnitude = num.abs(); let prefix = if self.alternate_form { @@ -559,7 +573,8 @@ impl FormatSpec { }, }; let sign_prefix = format!("{sign_str}{prefix}"); - let magnitude_str = self.add_magnitude_separators(raw_magnitude_str, &sign_prefix); + let magnitude_str = + self.add_magnitude_separators(raw_magnitude_str, &sign_prefix, locale_info); self.format_sign_and_align( &BorrowedStr::from_bytes(magnitude_str.as_bytes()), &sign_prefix, diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index 07c53a8b1b..376670ebb6 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -568,8 +568,9 @@ impl PyInt { #[pymethod(magic)] fn format(&self, spec: PyStrRef, vm: &VirtualMachine) -> PyResult { + let locale_func = None; // TODO: place proper get_locale_info wrapper FormatSpec::parse(spec.as_str()) - .and_then(|format_spec| format_spec.format_int(&self.value)) + .and_then(|format_spec| format_spec.format_int(&self.value, locale_func)) .map_err(|err| err.into_pyexception(vm)) }