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

View File

@ -35,9 +35,10 @@ impl WholeStreamCommand for Command {
mod tests {
use super::*;
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,
};
use nu_plugin::row;
use nu_plugin::test_helpers::value::{decimal, int};
use nu_protocol::Value;
@ -54,7 +55,7 @@ mod tests {
description: &'static str,
values: Vec<Value>,
expected_err: Option<ShellError>,
// Order is: avg, min, max
// Order is: average, minimum, maximum, median, summation
expected_res: Vec<Result<Value, ShellError>>,
}
let tt: Vec<TestCase> = vec![
@ -124,17 +125,23 @@ mod tests {
Ok(decimal(-15)),
],
},
// TODO-Uncomment once I figure out how to structure tables
// TestCase {
// description: "Tables",
// values: vec![
// table(&vec![int(3), int(4), int(4)]),
// table(&vec![int(3), int(4), int(4)]),
// table(&vec![int(3), int(4), int(4)]),
// ],
// expected_err: None,
// expected_res: vec![Ok(decimal(-5)), Ok(decimal(-13.5)), Ok(int(10))],
// },
TestCase {
description: "Tables Or Rows",
values: vec![
row!["col1".to_owned() => int(1), "col2".to_owned() => int(5)],
row!["col1".to_owned() => int(2), "col2".to_owned() => int(6)],
row!["col1".to_owned() => int(3), "col2".to_owned() => int(7)],
row!["col1".to_owned() => int(4), "col2".to_owned() => int(8)],
],
expected_err: None,
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
// TestCase {
// description: "Invalid Mixed Values",
@ -144,14 +151,14 @@ mod tests {
// },
];
let test_tag = Tag::unknown();
for tc in tt.iter() {
let tc: &TestCase = tc; // Just for type annotations
let math_functions: Vec<MathFunction> =
vec![average, minimum, maximum, median, summation];
let results = math_functions
.iter()
.map(|mf| mf(&tc.values, &test_tag))
.into_iter()
.map(|mf| calculate(&tc.values, &test_tag, mf))
.collect_vec();
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::prelude::*;
use crate::utils::data_processing::{reducer_for, Reduce};
@ -26,7 +26,7 @@ impl WholeStreamCommand for SubCommand {
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
calculate(
run_with_function(
RunnableContext {
input: args.input,
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::prelude::*;
use crate::utils::data_processing::{reducer_for, Reduce};
@ -30,7 +30,7 @@ impl WholeStreamCommand for SubCommand {
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
calculate(
run_with_function(
RunnableContext {
input: args.input,
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::prelude::*;
use crate::utils::data_processing::{reducer_for, Reduce};
@ -26,7 +26,7 @@ impl WholeStreamCommand for SubCommand {
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
calculate(
run_with_function(
RunnableContext {
input: args.input,
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::prelude::*;
use crate::utils::data_processing::{reducer_for, Reduce};
@ -27,7 +27,7 @@ impl WholeStreamCommand for SubCommand {
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
calculate(
run_with_function(
RunnableContext {
input: args.input,
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 async fn calculate(
pub async fn run_with_function(
RunnableContext {
mut input, name, ..
}: RunnableContext,
mf: MathFunction,
) -> Result<OutputStream, ShellError> {
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()) {
match mf(&values, &name) {
Ok(result) => Ok(OutputStream::one(ReturnSuccess::value(result))),
Err(err) => Err(err),
}
mf(&values, &name)
} else {
// If we are not dealing with Primitives, then perhaps we are dealing with a table
// Create a key for each column name
let mut column_values = IndexMap::new();
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() {
column_values
.entry(key.clone())
@ -44,11 +48,9 @@ pub async fn calculate(
}
}
Ok(OutputStream::one(ReturnSuccess::value(
UntaggedValue::Row(Dictionary {
entries: column_totals,
})
.into_untagged_value(),
)))
Ok(UntaggedValue::Row(Dictionary {
entries: column_totals,
})
.into_untagged_value())
}
}