Refactor out RunnableContext from calculate (#2037)

This commit is contained in:
Arash Outadi 2020-06-23 11:24:33 -07:00 committed by GitHub
parent 053bd926ec
commit 1420cbafe4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 47 additions and 38 deletions

View File

@ -1,4 +1,4 @@
use crate::commands::math::utils::calculate; use crate::commands::math::utils::run_with_function;
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::data_processing::{reducer_for, Reduce}; use crate::utils::data_processing::{reducer_for, Reduce};
@ -30,7 +30,7 @@ impl WholeStreamCommand for SubCommand {
args: CommandArgs, args: CommandArgs,
registry: &CommandRegistry, registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
calculate( run_with_function(
RunnableContext { RunnableContext {
input: args.input, input: args.input,
registry: registry.clone(), registry: registry.clone(),

View File

@ -35,9 +35,10 @@ impl WholeStreamCommand for Command {
mod tests { mod tests {
use super::*; use super::*;
use crate::commands::math::{ use crate::commands::math::{
avg::average, max::maximum, median::median, min::minimum, sum::summation, avg::average, max::maximum, median::median, min::minimum, sum::summation, utils::calculate,
utils::MathFunction, utils::MathFunction,
}; };
use nu_plugin::row;
use nu_plugin::test_helpers::value::{decimal, int}; use nu_plugin::test_helpers::value::{decimal, int};
use nu_protocol::Value; use nu_protocol::Value;
@ -54,7 +55,7 @@ mod tests {
description: &'static str, description: &'static str,
values: Vec<Value>, values: Vec<Value>,
expected_err: Option<ShellError>, expected_err: Option<ShellError>,
// Order is: avg, min, max // Order is: average, minimum, maximum, median, summation
expected_res: Vec<Result<Value, ShellError>>, expected_res: Vec<Result<Value, ShellError>>,
} }
let tt: Vec<TestCase> = vec![ let tt: Vec<TestCase> = vec![
@ -124,17 +125,23 @@ mod tests {
Ok(decimal(-15)), Ok(decimal(-15)),
], ],
}, },
// TODO-Uncomment once I figure out how to structure tables TestCase {
// TestCase { description: "Tables Or Rows",
// description: "Tables", values: vec![
// values: vec![ row!["col1".to_owned() => int(1), "col2".to_owned() => int(5)],
// table(&vec![int(3), int(4), int(4)]), row!["col1".to_owned() => int(2), "col2".to_owned() => int(6)],
// table(&vec![int(3), int(4), int(4)]), row!["col1".to_owned() => int(3), "col2".to_owned() => int(7)],
// table(&vec![int(3), int(4), int(4)]), row!["col1".to_owned() => int(4), "col2".to_owned() => int(8)],
// ], ],
// expected_err: None, expected_err: None,
// expected_res: vec![Ok(decimal(-5)), Ok(decimal(-13.5)), Ok(int(10))], expected_res: vec![
// }, Ok(row!["col1".to_owned() => decimal(2.5), "col2".to_owned() => decimal(6.5)]),
Ok(row!["col1".to_owned() => int(1), "col2".to_owned() => int(5)]),
Ok(row!["col1".to_owned() => int(4), "col2".to_owned() => int(8)]),
Ok(row!["col1".to_owned() => decimal(2.5), "col2".to_owned() => decimal(6.5)]),
Ok(row!["col1".to_owned() => int(10), "col2".to_owned() => int(26)]),
],
},
// TODO-Uncomment once Issue: https://github.com/nushell/nushell/issues/1883 is resolved // TODO-Uncomment once Issue: https://github.com/nushell/nushell/issues/1883 is resolved
// TestCase { // TestCase {
// description: "Invalid Mixed Values", // description: "Invalid Mixed Values",
@ -144,14 +151,14 @@ mod tests {
// }, // },
]; ];
let test_tag = Tag::unknown(); let test_tag = Tag::unknown();
for tc in tt.iter() { for tc in tt.iter() {
let tc: &TestCase = tc; // Just for type annotations let tc: &TestCase = tc; // Just for type annotations
let math_functions: Vec<MathFunction> = let math_functions: Vec<MathFunction> =
vec![average, minimum, maximum, median, summation]; vec![average, minimum, maximum, median, summation];
let results = math_functions let results = math_functions
.iter() .into_iter()
.map(|mf| mf(&tc.values, &test_tag)) .map(|mf| calculate(&tc.values, &test_tag, mf))
.collect_vec(); .collect_vec();
if tc.expected_err.is_some() { if tc.expected_err.is_some() {

View File

@ -1,4 +1,4 @@
use crate::commands::math::utils::calculate; use crate::commands::math::utils::run_with_function;
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::data_processing::{reducer_for, Reduce}; use crate::utils::data_processing::{reducer_for, Reduce};
@ -26,7 +26,7 @@ impl WholeStreamCommand for SubCommand {
args: CommandArgs, args: CommandArgs,
registry: &CommandRegistry, registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
calculate( run_with_function(
RunnableContext { RunnableContext {
input: args.input, input: args.input,
registry: registry.clone(), registry: registry.clone(),

View File

@ -1,4 +1,4 @@
use crate::commands::math::utils::calculate; use crate::commands::math::utils::run_with_function;
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::data_processing::{reducer_for, Reduce}; use crate::utils::data_processing::{reducer_for, Reduce};
@ -30,7 +30,7 @@ impl WholeStreamCommand for SubCommand {
args: CommandArgs, args: CommandArgs,
registry: &CommandRegistry, registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
calculate( run_with_function(
RunnableContext { RunnableContext {
input: args.input, input: args.input,
registry: registry.clone(), registry: registry.clone(),

View File

@ -1,4 +1,4 @@
use crate::commands::math::utils::calculate; use crate::commands::math::utils::run_with_function;
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::data_processing::{reducer_for, Reduce}; use crate::utils::data_processing::{reducer_for, Reduce};
@ -26,7 +26,7 @@ impl WholeStreamCommand for SubCommand {
args: CommandArgs, args: CommandArgs,
registry: &CommandRegistry, registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
calculate( run_with_function(
RunnableContext { RunnableContext {
input: args.input, input: args.input,
registry: registry.clone(), registry: registry.clone(),

View File

@ -1,4 +1,4 @@
use crate::commands::math::utils::calculate; use crate::commands::math::utils::run_with_function;
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::data_processing::{reducer_for, Reduce}; use crate::utils::data_processing::{reducer_for, Reduce};
@ -27,7 +27,7 @@ impl WholeStreamCommand for SubCommand {
args: CommandArgs, args: CommandArgs,
registry: &CommandRegistry, registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
calculate( run_with_function(
RunnableContext { RunnableContext {
input: args.input, input: args.input,
registry: registry.clone(), registry: registry.clone(),

View File

@ -6,25 +6,29 @@ use indexmap::map::IndexMap;
pub type MathFunction = fn(values: &[Value], tag: &Tag) -> Result<Value, ShellError>; pub type MathFunction = fn(values: &[Value], tag: &Tag) -> Result<Value, ShellError>;
pub async fn calculate( pub async fn run_with_function(
RunnableContext { RunnableContext {
mut input, name, .. mut input, name, ..
}: RunnableContext, }: RunnableContext,
mf: MathFunction, mf: MathFunction,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let values: Vec<Value> = input.drain_vec().await; let values: Vec<Value> = input.drain_vec().await;
let res = calculate(&values, &name, mf);
match res {
Ok(v) => Ok(OutputStream::one(ReturnSuccess::value(v))),
Err(e) => Err(e),
}
}
pub fn calculate(values: &[Value], name: &Tag, mf: MathFunction) -> Result<Value, ShellError> {
if values.iter().all(|v| v.is_primitive()) { if values.iter().all(|v| v.is_primitive()) {
match mf(&values, &name) { mf(&values, &name)
Ok(result) => Ok(OutputStream::one(ReturnSuccess::value(result))),
Err(err) => Err(err),
}
} else { } else {
// If we are not dealing with Primitives, then perhaps we are dealing with a table // If we are not dealing with Primitives, then perhaps we are dealing with a table
// Create a key for each column name // Create a key for each column name
let mut column_values = IndexMap::new(); let mut column_values = IndexMap::new();
for value in values { for value in values {
if let UntaggedValue::Row(row_dict) = value.value { if let UntaggedValue::Row(row_dict) = &value.value {
for (key, value) in row_dict.entries.iter() { for (key, value) in row_dict.entries.iter() {
column_values column_values
.entry(key.clone()) .entry(key.clone())
@ -44,11 +48,9 @@ pub async fn calculate(
} }
} }
Ok(OutputStream::one(ReturnSuccess::value( Ok(UntaggedValue::Row(Dictionary {
UntaggedValue::Row(Dictionary { entries: column_totals,
entries: column_totals, })
}) .into_untagged_value())
.into_untagged_value(),
)))
} }
} }