From 1c2b01f8943db9b70ac9cdeaaba890541bb249f4 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sat, 1 Feb 2020 00:06:17 +0900 Subject: [PATCH] parse_number can raise error about length --- Lib/test/test_types.py | 3 ++- vm/src/format.rs | 28 +++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 12d8b289d9..260720b574 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -563,7 +563,8 @@ def test(f, format_spec, result): test(12345.6, "1=20", '111111111111112345.6') test(12345.6, "*=20", '*************12345.6') - @unittest.skip("TODO: RUSTPYTHON") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_format_spec_errors(self): # int, float, and string all share the same format spec # mini-language parser. diff --git a/vm/src/format.rs b/vm/src/format.rs index e9fee7ed8e..91c023a784 100644 --- a/vm/src/format.rs +++ b/vm/src/format.rs @@ -155,16 +155,17 @@ fn parse_fill_and_align(text: &str) -> (Option, Option, &str) } } -fn parse_number(text: &str) -> (Option, &str) { +fn parse_number(text: &str) -> Result<(Option, &str), &'static str> { let num_digits: usize = get_num_digits(text); if num_digits == 0 { - return (None, text); + return Ok((None, text)); + } + if let Ok(num) = text[..num_digits].parse::() { + Ok((Some(num), &text[num_digits..])) + } else { + // NOTE: this condition is different from CPython + Err("Too many decimal digits in format string") } - // This should never fail - ( - Some(text[..num_digits].parse::().unwrap()), - &text[num_digits..], - ) } fn parse_sign(text: &str) -> (Option, &str) { @@ -193,11 +194,11 @@ fn parse_zero(text: &str) -> (bool, &str) { } } -fn parse_precision(text: &str) -> (Option, &str) { +fn parse_precision(text: &str) -> Result<(Option, &str), &'static str> { let mut chars = text.chars(); - match chars.next() { + Ok(match chars.next() { Some('.') => { - let (size, remaining) = parse_number(&chars.as_str()); + let (size, remaining) = parse_number(&chars.as_str())?; if size.is_some() { (size, remaining) } else { @@ -205,7 +206,7 @@ fn parse_precision(text: &str) -> (Option, &str) { } } _ => (None, text), - } + }) } fn parse_grouping_option(text: &str) -> (Option, &str) { @@ -239,14 +240,15 @@ fn parse_format_type(text: &str) -> (Option, &str) { } fn parse_format_spec(text: &str) -> Result { + // get_integer in CPython let (preconversor, after_preconversor) = parse_preconversor(text); let (mut fill, mut align, after_align) = parse_fill_and_align(after_preconversor); let (sign, after_sign) = parse_sign(after_align); let (alternate_form, after_alternate_form) = parse_alternate_form(after_sign); let (zero, after_zero) = parse_zero(after_alternate_form); - let (width, after_width) = parse_number(after_zero); + let (width, after_width) = parse_number(after_zero)?; let (grouping_option, after_grouping_option) = parse_grouping_option(after_width); - let (precision, after_precision) = parse_precision(after_grouping_option); + let (precision, after_precision) = parse_precision(after_grouping_option)?; let (format_type, after_format_type) = parse_format_type(after_precision); if !after_format_type.is_empty() { return Err("Invalid format specifier");