diff --git a/tests/snippets/builtin_format.py b/tests/snippets/builtin_format.py index 039c61121..9465faa65 100644 --- a/tests/snippets/builtin_format.py +++ b/tests/snippets/builtin_format.py @@ -12,3 +12,9 @@ class BadFormat: def __format__(self, spec): return 42 assert_raises(TypeError, format, BadFormat()) + +def test_zero_padding(): + i = 1 + assert f'{i:04d}' == '0001' + +test_zero_padding() diff --git a/vm/src/format.rs b/vm/src/format.rs index e76e8c97f..37b737d72 100644 --- a/vm/src/format.rs +++ b/vm/src/format.rs @@ -181,11 +181,11 @@ fn parse_alternate_form(text: &str) -> (bool, &str) { } } -fn parse_zero(text: &str) -> &str { +fn parse_zero(text: &str) -> (bool, &str) { let mut chars = text.chars(); match chars.next() { - Some('0') => chars.as_str(), - _ => text, + Some('0') => (true, chars.as_str()), + _ => (false, text), } } @@ -235,15 +235,20 @@ fn parse_format_type(text: &str) -> (Option, &str) { fn parse_format_spec(text: &str) -> FormatSpec { let (preconversor, after_preconversor) = parse_preconversor(text); - let (fill, align, after_align) = parse_fill_and_align(after_preconversor); + 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 after_zero = parse_zero(after_alternate_form); + let (zero, after_zero) = parse_zero(after_alternate_form); 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 (format_type, _) = parse_format_type(after_precision); + if zero && fill.is_none() { + fill.replace('0'); + align = align.or(Some(FormatAlign::AfterSign)); + } + FormatSpec { preconversor, fill, diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index 4c42de58c..5ff1424f3 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -1326,9 +1326,7 @@ fn try_update_quantity_from_tuple( Ok(tuple_index) } } - None => { - Err(vm.new_type_error("not enough arguments for format string".to_string())) - } + None => Err(vm.new_type_error("not enough arguments for format string".to_string())), } } _ => Ok(tuple_index), diff --git a/vm/src/stdlib/ast.rs b/vm/src/stdlib/ast.rs index cea1674c4..32986a24c 100644 --- a/vm/src/stdlib/ast.rs +++ b/vm/src/stdlib/ast.rs @@ -620,12 +620,8 @@ fn comprehension_to_ast( fn string_to_ast(vm: &VirtualMachine, string: &ast::StringGroup) -> PyResult { let string = match string { - ast::StringGroup::Constant { value } => { - node!(vm, Str, { s => vm.ctx.new_str(value.clone()) }) - } - ast::StringGroup::FormattedValue { value, .. } => { - node!(vm, FormattedValue, { value => expression_to_ast(vm, value)? }) - } + ast::StringGroup::Constant { value } => node!(vm, Str, { s => vm.ctx.new_str(value.clone()) }), + ast::StringGroup::FormattedValue { value, .. } => node!(vm, FormattedValue, { value => expression_to_ast(vm, value)? }), ast::StringGroup::Joined { values } => { let py_values = map_ast(string_to_ast, vm, &values)?; node!(vm, JoinedStr, { values => py_values }) diff --git a/vm/src/stdlib/unicodedata.rs b/vm/src/stdlib/unicodedata.rs index b1e75730b..5c0eeb155 100644 --- a/vm/src/stdlib/unicodedata.rs +++ b/vm/src/stdlib/unicodedata.rs @@ -54,9 +54,7 @@ fn name( } else { match default { OptionalArg::Present(obj) => Ok(obj), - OptionalArg::Missing => { - Err(vm.new_value_error("character name not found!".to_string())) - } + OptionalArg::Missing => Err(vm.new_value_error("character name not found!".to_string())), } } } diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index f5878d7fb..9bdf39803 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -137,7 +137,7 @@ fn browser_request_animation_frame(func: PyCallable, vm: &VirtualMachine) -> PyR let closure = f.borrow_mut().take(); drop(closure); - }) as Box)); + }) as Box)); let id = window() .request_animation_frame(&js_sys::Function::from(