From b1361d5cfcd390e5b23c0d84d3cef664c41bc96e Mon Sep 17 00:00:00 2001 From: Noah <33094578+coolreader18@users.noreply.github.com> Date: Wed, 27 Jan 2021 16:04:26 -0600 Subject: [PATCH] Don't error on a non-dict map for cformat --- vm/src/builtins/tuple.rs | 4 ---- vm/src/cformat.rs | 52 +++++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/vm/src/builtins/tuple.rs b/vm/src/builtins/tuple.rs index c4614881f7..e22484bb4c 100644 --- a/vm/src/builtins/tuple.rs +++ b/vm/src/builtins/tuple.rs @@ -82,10 +82,6 @@ impl PyTupleRef { } } -pub(crate) fn get_value(obj: &PyObjectRef) -> &[PyObjectRef] { - obj.payload::().unwrap().borrow_value() -} - #[pyimpl(flags(BASETYPE), with(Hashable, Comparable, Iterable))] impl PyTuple { /// Creating a new tuple with given boxed slice. diff --git a/vm/src/cformat.rs b/vm/src/cformat.rs index 0fbd78dad6..6f2b8a24f3 100644 --- a/vm/src/cformat.rs +++ b/vm/src/cformat.rs @@ -652,11 +652,16 @@ impl CFormatBytes { let (num_specifiers, mapping_required) = check_specifiers(self.parts.as_slice(), vm)?; let mut result = vec![]; + let is_mapping = values_obj.class().has_attr("__getitem__") + && !values_obj.isinstance(&vm.ctx.types.tuple_type) + && !values_obj.isinstance(&vm.ctx.types.str_type); + if num_specifiers == 0 { // literal only - return if values_obj.isinstance(&vm.ctx.types.dict_type) - || (values_obj.isinstance(&vm.ctx.types.tuple_type) - && tuple::get_value(&values_obj).is_empty()) + return if is_mapping + || values_obj + .payload::() + .map_or(false, |e| e.borrow_value().is_empty()) { for (_, part) in &mut self.parts { match part { @@ -674,7 +679,7 @@ impl CFormatBytes { if mapping_required { // dict - return if values_obj.isinstance(&vm.ctx.types.dict_type) { + return if is_mapping { for (_, part) in &mut self.parts { match part { CFormatPart::Literal(literal) => result.append(literal), @@ -695,15 +700,12 @@ impl CFormatBytes { } // tuple - let values; - let vec; - let mut value_iter = if values_obj.isinstance(&vm.ctx.types.tuple_type) { - values = tuple::get_value(&values_obj); - values.iter() + let values = if let Some(tup) = values_obj.payload_if_subclass::(vm) { + tup.borrow_value() } else { - vec = vec![values_obj]; - vec.iter() + std::slice::from_ref(&values_obj) }; + let mut value_iter = values.iter(); for (_, part) in &mut self.parts { match part { @@ -725,7 +727,7 @@ impl CFormatBytes { } // check that all arguments were converted - if value_iter.next().is_some() { + if value_iter.next().is_some() && !is_mapping { Err(vm .new_type_error("not all arguments converted during string formatting".to_owned())) } else { @@ -802,11 +804,16 @@ impl CFormatString { let (num_specifiers, mapping_required) = check_specifiers(self.parts.as_slice(), vm)?; let mut result = String::new(); + let is_mapping = values_obj.class().has_attr("__getitem__") + && !values_obj.isinstance(&vm.ctx.types.tuple_type) + && !values_obj.isinstance(&vm.ctx.types.str_type); + if num_specifiers == 0 { // literal only - return if values_obj.isinstance(&vm.ctx.types.dict_type) - || (values_obj.isinstance(&vm.ctx.types.tuple_type) - && tuple::get_value(&values_obj).is_empty()) + return if is_mapping + || values_obj + .payload::() + .map_or(false, |e| e.borrow_value().is_empty()) { for (_, part) in &self.parts { match part { @@ -824,7 +831,7 @@ impl CFormatString { if mapping_required { // dict - return if values_obj.isinstance(&vm.ctx.types.dict_type) { + return if is_mapping { for (_, part) in &self.parts { match part { CFormatPart::Literal(literal) => result.push_str(&literal), @@ -845,15 +852,12 @@ impl CFormatString { } // tuple - let values; - let vec; - let mut value_iter = if values_obj.isinstance(&vm.ctx.types.tuple_type) { - values = tuple::get_value(&values_obj); - values.iter() + let values = if let Some(tup) = values_obj.payload_if_subclass::(vm) { + tup.borrow_value() } else { - vec = vec![values_obj]; - vec.iter() + std::slice::from_ref(&values_obj) }; + let mut value_iter = values.iter(); for (_, part) in &mut self.parts { match part { @@ -875,7 +879,7 @@ impl CFormatString { } // check that all arguments were converted - if value_iter.next().is_some() { + if value_iter.next().is_some() && !is_mapping { Err(vm .new_type_error("not all arguments converted during string formatting".to_owned())) } else {