Skip to content

Commit 144f619

Browse files
authored
Merge pull request RustPython#4419 from yt2b/implement_float_format_validation
Implement float format validation
2 parents cad2adc + 980e578 commit 144f619

File tree

3 files changed

+25
-18
lines changed

3 files changed

+25
-18
lines changed

common/src/format.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -422,10 +422,11 @@ impl FormatSpec {
422422
}
423423
}
424424

425-
pub fn format_float(&self, num: f64) -> Result<String, &'static str> {
425+
pub fn format_float(&self, num: f64) -> Result<String, String> {
426+
self.validate_format(FormatType::FixedPointLower)?;
426427
let precision = self.precision.unwrap_or(6);
427428
let magnitude = num.abs();
428-
let raw_magnitude_str: Result<String, &'static str> = match self.format_type {
429+
let raw_magnitude_str: Result<String, String> = match self.format_type {
429430
Some(FormatType::FixedPointUpper) => Ok(float_ops::format_fixed(
430431
precision,
431432
magnitude,
@@ -436,17 +437,21 @@ impl FormatSpec {
436437
magnitude,
437438
float_ops::Case::Lower,
438439
)),
439-
Some(FormatType::Decimal) => Err("Unknown format code 'd' for object of type 'float'"),
440-
Some(FormatType::Binary) => Err("Unknown format code 'b' for object of type 'float'"),
441-
Some(FormatType::Octal) => Err("Unknown format code 'o' for object of type 'float'"),
442-
Some(FormatType::HexLower) => Err("Unknown format code 'x' for object of type 'float'"),
443-
Some(FormatType::HexUpper) => Err("Unknown format code 'X' for object of type 'float'"),
444-
Some(FormatType::String) => Err("Unknown format code 's' for object of type 'float'"),
445-
Some(FormatType::Character) => {
446-
Err("Unknown format code 'c' for object of type 'float'")
440+
Some(FormatType::Decimal)
441+
| Some(FormatType::Binary)
442+
| Some(FormatType::Octal)
443+
| Some(FormatType::HexLower)
444+
| Some(FormatType::HexUpper)
445+
| Some(FormatType::String)
446+
| Some(FormatType::Character) => {
447+
let ch = char::from(self.format_type.as_ref().unwrap());
448+
Err(format!(
449+
"Unknown format code '{}' for object of type 'float'",
450+
ch
451+
))
447452
}
448453
Some(FormatType::Number) => {
449-
Err("Format code 'n' for object of type 'float' not implemented yet")
454+
Err("Format code 'n' for object of type 'float' not implemented yet".to_owned())
450455
}
451456
Some(FormatType::GeneralFormatUpper) => {
452457
let precision = if precision == 0 { 1 } else { precision };
@@ -513,6 +518,7 @@ impl FormatSpec {
513518
};
514519
let magnitude_str = self.add_magnitude_separators(raw_magnitude_str?, sign_str);
515520
self.format_sign_and_align(&magnitude_str, sign_str, FormatAlign::Right)
521+
.map_err(|msg| msg.to_owned())
516522
}
517523

518524
#[inline]
@@ -574,7 +580,7 @@ impl FormatSpec {
574580
| Some(FormatType::ExponentUpper)
575581
| Some(FormatType::ExponentLower)
576582
| Some(FormatType::Percentage) => match num.to_f64() {
577-
Some(float) => return self.format_float(float).map_err(|msg| msg.to_owned()),
583+
Some(float) => return self.format_float(float),
578584
_ => Err("Unable to convert int to float".to_owned()),
579585
},
580586
None => self.format_int_radix(magnitude, 10),

extra_tests/snippets/builtin_format.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,5 @@ def test_zero_padding():
6868
assert f"{1234567:.6G}" == "1.23457E+06"
6969
assert_raises(ValueError, "{:,o}".format, 1, _msg="ValueError: Cannot specify ',' with 'o'.")
7070
assert_raises(ValueError, "{:_n}".format, 1, _msg="ValueError: Cannot specify '_' with 'n'.")
71+
assert_raises(ValueError, "{:,o}".format, 1.0, _msg="ValueError: Cannot specify ',' with 'o'.")
72+
assert_raises(ValueError, "{:_n}".format, 1.0, _msg="ValueError: Cannot specify '_' with 'n'.")

vm/src/builtins/float.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,11 @@ fn float_from_string(val: PyObjectRef, vm: &VirtualMachine) -> PyResult<f64> {
189189
impl PyFloat {
190190
#[pymethod(magic)]
191191
fn format(&self, spec: PyStrRef, vm: &VirtualMachine) -> PyResult<String> {
192-
match FormatSpec::parse(spec.as_str())
193-
.and_then(|format_spec| format_spec.format_float(self.value))
194-
{
195-
Ok(string) => Ok(string),
196-
Err(err) => Err(vm.new_value_error(err.to_string())),
197-
}
192+
let format_spec =
193+
FormatSpec::parse(spec.as_str()).map_err(|msg| vm.new_value_error(msg.to_owned()))?;
194+
format_spec
195+
.format_float(self.value)
196+
.map_err(|msg| vm.new_value_error(msg))
198197
}
199198

200199
#[pystaticmethod(magic)]

0 commit comments

Comments
 (0)