diff --git a/vm/src/anystr.rs b/vm/src/anystr.rs index 4cd7a8f76..0611950ef 100644 --- a/vm/src/anystr.rs +++ b/vm/src/anystr.rs @@ -1,9 +1,9 @@ use crate::{ - builtins::PyIntRef, + builtins::{PyIntRef, PyTupleRef}, cformat::CFormatString, - function::{single_or_tuple_any, OptionalOption}, + function::OptionalOption, protocol::PyIterIter, - AsObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine, + AsObject, PyObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine, }; use num_traits::{cast::ToPrimitive, sign::Signed}; use std::str::FromStr; @@ -441,3 +441,33 @@ pub trait AnyStr<'s>: 's { .format(vm, values) } } + +/// Tests that the predicate is True on a single value, or if the value is a tuple a tuple, then +/// test that any of the values contained within the tuples satisfies the predicate. Type parameter +/// T specifies the type that is expected, if the input value is not of that type or a tuple of +/// values of that type, then a TypeError is raised. +pub fn single_or_tuple_any( + obj: PyObjectRef, + predicate: &F, + message: &M, + vm: &VirtualMachine, +) -> PyResult +where + T: TryFromObject, + F: Fn(&T) -> PyResult, + M: Fn(&PyObject) -> String, +{ + match T::try_from_object(vm, obj.clone()) { + Ok(single) => (predicate)(&single), + Err(_) => { + let tuple = PyTupleRef::try_from_object(vm, obj.clone()) + .map_err(|_| vm.new_type_error((message)(&obj)))?; + for obj in &tuple { + if single_or_tuple_any(obj.clone(), predicate, message, vm)? { + return Ok(true); + } + } + Ok(false) + } + } +} diff --git a/vm/src/function/mod.rs b/vm/src/function/mod.rs index 76f203c10..92c97ddfa 100644 --- a/vm/src/function/mod.rs +++ b/vm/src/function/mod.rs @@ -16,37 +16,3 @@ pub use builtin::{IntoPyNativeFunc, OwnedParam, PyNativeFunc, RefParam}; pub use either::Either; pub use number::{ArgIntoBool, ArgIntoComplex, ArgIntoFloat}; pub use protocol::{ArgCallable, ArgIterable, ArgMapping, ArgSequence}; - -use crate::{ - builtins::PyTupleRef, convert::TryFromObject, PyObject, PyObjectRef, PyResult, VirtualMachine, -}; - -/// Tests that the predicate is True on a single value, or if the value is a tuple a tuple, then -/// test that any of the values contained within the tuples satisfies the predicate. Type parameter -/// T specifies the type that is expected, if the input value is not of that type or a tuple of -/// values of that type, then a TypeError is raised. -pub fn single_or_tuple_any( - obj: PyObjectRef, - predicate: &F, - message: &M, - vm: &VirtualMachine, -) -> PyResult -where - T: TryFromObject, - F: Fn(&T) -> PyResult, - M: Fn(&PyObject) -> String, -{ - match T::try_from_object(vm, obj.clone()) { - Ok(single) => (predicate)(&single), - Err(_) => { - let tuple = PyTupleRef::try_from_object(vm, obj.clone()) - .map_err(|_| vm.new_type_error((message)(&obj)))?; - for obj in &tuple { - if single_or_tuple_any(obj.clone(), predicate, message, vm)? { - return Ok(true); - } - } - Ok(false) - } - } -}