Deserialization and outputstream math commands (#3315)

* Output error when ls into a file without permission

* math sqrt

* added test to check fails when ls into prohibited dir

* fix lint

* math sqrt with tests and doc

* trigger wasm build

* Update filesystem_shell.rs

* converted math commands to outputstream and new method for arg evaluation

* fmt

* clippy

Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
This commit is contained in:
Luccas Mateus 2021-04-14 15:18:37 -03:00 committed by GitHub
parent a148c640b2
commit 004230d02d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 78 additions and 93 deletions

View File

@ -18,7 +18,7 @@ impl WholeStreamCommand for SubCommand {
"Returns absolute values of a list of numbers" "Returns absolute values of a list of numbers"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let mapped = args.input.map(move |val| match val.value { let mapped = args.input.map(move |val| match val.value {
UntaggedValue::Primitive(Primitive::Int(val)) => { UntaggedValue::Primitive(Primitive::Int(val)) => {
UntaggedValue::int(val.magnitude().clone()).into() UntaggedValue::int(val.magnitude().clone()).into()
@ -31,7 +31,7 @@ impl WholeStreamCommand for SubCommand {
} }
other => abs_default(other), other => abs_default(other),
}); });
Ok(ActionStream::from_input(mapped)) Ok(mapped.to_output_stream())
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -27,7 +27,7 @@ impl WholeStreamCommand for SubCommand {
"Finds the average of a list of numbers or tables" "Finds the average of a list of numbers or tables"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, average) run_with_function(args, average)
} }

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Applies the ceil function to a list of numbers" "Applies the ceil function to a list of numbers"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let input = args.input; let input = args.input;
run_with_numerical_functions_on_stream(input, ceil_big_int, ceil_big_decimal, ceil_default) run_with_numerical_functions_on_stream(input, ceil_big_int, ceil_big_decimal, ceil_default)

View File

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue}; use nu_protocol::{Signature, UntaggedValue};
pub struct Command; pub struct Command;
@ -18,10 +18,10 @@ impl WholeStreamCommand for Command {
"Use mathematical functions as aggregate functions on a list of numbers or tables." "Use mathematical functions as aggregate functions on a list of numbers or tables."
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(ActionStream::one(Ok(ReturnSuccess::Value( Ok(OutputStream::one(
UntaggedValue::string(get_full_help(&Command, &args.scope)).into_value(Tag::unknown()), UntaggedValue::string(get_full_help(&Command, &args.scope)).into_value(Tag::unknown()),
)))) ))
} }
} }

View File

@ -1,16 +1,11 @@
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged; use nu_source::Tagged;
pub struct SubCommand; pub struct SubCommand;
#[derive(Deserialize)]
pub struct SubCommandArgs {
expression: Option<Tagged<String>>,
}
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"math eval" "math eval"
@ -28,7 +23,7 @@ impl WholeStreamCommand for SubCommand {
) )
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
eval(args) eval(args)
} }
@ -45,13 +40,15 @@ impl WholeStreamCommand for SubCommand {
} }
} }
pub fn eval(args: CommandArgs) -> Result<ActionStream, ShellError> { pub fn eval(args: CommandArgs) -> Result<OutputStream, ShellError> {
let name = args.call_info.name_tag.span; let args = args.evaluate_once()?;
let (SubCommandArgs { expression }, input) = args.process()?; let expression: Option<Result<Tagged<String>, ShellError>> = args.opt(0);
let name = args.call_info.name_tag.clone();
let input = args.input;
if let Some(string) = expression { if let Some(Ok(string)) = expression {
match parse(&string, &string.tag) { match parse(&string, &string.tag) {
Ok(value) => Ok(ActionStream::one(ReturnSuccess::value(value))), Ok(value) => Ok(OutputStream::one(value)),
Err(err) => Err(ShellError::labeled_error( Err(err) => Err(ShellError::labeled_error(
"Math evaluation error", "Math evaluation error",
err, err,
@ -59,12 +56,12 @@ pub fn eval(args: CommandArgs) -> Result<ActionStream, ShellError> {
)), )),
} }
} else { } else {
Ok(input let mapped: Result<Vec<_>, _> = input
.map(move |x| { .map(move |x| {
if let Some(Tagged { if let Some(Ok(Tagged {
tag, tag,
item: expression, item: expression,
}) = &expression })) = &expression
{ {
UntaggedValue::string(expression).into_value(tag) UntaggedValue::string(expression).into_value(tag)
} else { } else {
@ -74,7 +71,7 @@ pub fn eval(args: CommandArgs) -> Result<ActionStream, ShellError> {
.map(move |input| { .map(move |input| {
if let Ok(string) = input.as_string() { if let Ok(string) = input.as_string() {
match parse(&string, &input.tag) { match parse(&string, &input.tag) {
Ok(value) => ReturnSuccess::value(value), Ok(value) => Ok(value),
Err(err) => Err(ShellError::labeled_error( Err(err) => Err(ShellError::labeled_error(
"Math evaluation error", "Math evaluation error",
err, err,
@ -85,11 +82,15 @@ pub fn eval(args: CommandArgs) -> Result<ActionStream, ShellError> {
Err(ShellError::labeled_error( Err(ShellError::labeled_error(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
name, name.clone(),
)) ))
} }
}) })
.to_action_stream()) .collect();
match mapped {
Ok(values) => Ok(OutputStream::from(values)),
Err(e) => Err(e),
}
} }
} }

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Applies the floor function to a list of numbers" "Applies the floor function to a list of numbers"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
let input = args.input; let input = args.input;
run_with_numerical_functions_on_stream( run_with_numerical_functions_on_stream(

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Finds the maximum within a list of numbers or tables" "Finds the maximum within a list of numbers or tables"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, maximum) run_with_function(args, maximum)
} }

View File

@ -24,7 +24,7 @@ impl WholeStreamCommand for SubCommand {
"Gets the median of a list of numbers" "Gets the median of a list of numbers"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, median) run_with_function(args, median)
} }

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Finds the minimum within a list of numbers or tables" "Finds the minimum within a list of numbers or tables"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, minimum) run_with_function(args, minimum)
} }

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Gets the most frequent element(s) from a list of numbers or tables" "Gets the most frequent element(s) from a list of numbers or tables"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, mode) run_with_function(args, mode)
} }

View File

@ -20,7 +20,7 @@ impl WholeStreamCommand for SubCommand {
"Finds the product of a list of numbers or tables" "Finds the product of a list of numbers or tables"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, product) run_with_function(args, product)
} }

View File

@ -6,11 +6,6 @@ use nu_source::Tagged;
pub struct SubCommand; pub struct SubCommand;
#[derive(Deserialize)]
struct Arguments {
precision: Option<Tagged<i64>>,
}
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"math round" "math round"
@ -29,7 +24,7 @@ impl WholeStreamCommand for SubCommand {
"Applies the round function to a list of numbers" "Applies the round function to a list of numbers"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
operate(args) operate(args)
} }
@ -57,16 +52,23 @@ impl WholeStreamCommand for SubCommand {
} }
} }
fn operate(args: CommandArgs) -> Result<ActionStream, ShellError> { fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> {
let (Arguments { precision }, input) = args.process()?; let args = args.evaluate_once()?;
let precision = precision.map(|p| p.item).unwrap_or(0); let precision: Option<Result<Tagged<i16>, ShellError>> = args.get_flag("precision");
let input = args.input;
let precision = if let Some(precision) = precision {
precision?.item
} else {
0
};
let mapped = input.map(move |val| match val.value { let mapped = input.map(move |val| match val.value {
UntaggedValue::Primitive(Primitive::Int(val)) => round_big_int(val), UntaggedValue::Primitive(Primitive::Int(val)) => round_big_int(val),
UntaggedValue::Primitive(Primitive::Decimal(val)) => round_big_decimal(val, precision), UntaggedValue::Primitive(Primitive::Decimal(val)) => {
round_big_decimal(val, precision.into())
}
other => round_default(other), other => round_default(other),
}); });
Ok(ActionStream::from_input(mapped)) Ok(mapped.to_output_stream())
} }
fn round_big_int(val: BigInt) -> Value { fn round_big_int(val: BigInt) -> Value {

View File

@ -18,7 +18,7 @@ impl WholeStreamCommand for SubCommand {
"Applies the square root function to a list of numbers" "Applies the square root function to a list of numbers"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(operate(args)) Ok(operate(args))
} }
@ -34,13 +34,13 @@ impl WholeStreamCommand for SubCommand {
} }
} }
fn operate(args: CommandArgs) -> ActionStream { fn operate(args: CommandArgs) -> OutputStream {
let mapped = args.input.map(move |val| match val.value { let mapped = args.input.map(move |val| match val.value {
UntaggedValue::Primitive(Primitive::Int(val)) => sqrt_big_decimal(BigDecimal::from(val)), UntaggedValue::Primitive(Primitive::Int(val)) => sqrt_big_decimal(BigDecimal::from(val)),
UntaggedValue::Primitive(Primitive::Decimal(val)) => sqrt_big_decimal(val), UntaggedValue::Primitive(Primitive::Decimal(val)) => sqrt_big_decimal(val),
other => sqrt_default(other), other => sqrt_default(other),
}); });
ActionStream::from_input(mapped) mapped.to_output_stream()
} }
fn sqrt_big_decimal(val: BigDecimal) -> Value { fn sqrt_big_decimal(val: BigDecimal) -> Value {

View File

@ -2,17 +2,11 @@ use super::variance::compute_variance as variance;
use crate::prelude::*; use crate::prelude::*;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Dictionary, Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; use nu_protocol::{Dictionary, Primitive, Signature, UntaggedValue, Value};
use nu_source::Tagged;
use std::str::FromStr; use std::str::FromStr;
pub struct SubCommand; pub struct SubCommand;
#[derive(Deserialize)]
struct Arguments {
sample: Tagged<bool>,
}
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"math stddev" "math stddev"
@ -30,13 +24,14 @@ impl WholeStreamCommand for SubCommand {
"Finds the stddev of a list of numbers or tables" "Finds the stddev of a list of numbers or tables"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut args = raw_args.evaluate_once()?;
let sample: bool = args.has_flag("sample");
let values: Vec<Value> = args.input.drain_vec();
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (Arguments { sample }, mut input) = args.process()?;
let values: Vec<Value> = input.drain_vec(); let n = if sample {
let n = if let Tagged { item: true, .. } = sample {
values.len() - 1 values.len() - 1
} else { } else {
values.len() values.len()
@ -81,13 +76,11 @@ impl WholeStreamCommand for SubCommand {
}?; }?;
if res.value.is_table() { if res.value.is_table() {
Ok(ActionStream::from( Ok(OutputStream::from(
res.table_entries() res.table_entries().cloned().collect::<Vec<_>>(),
.map(|v| ReturnSuccess::value(v.clone()))
.collect::<Vec<_>>(),
)) ))
} else { } else {
Ok(ActionStream::one(ReturnSuccess::value(res))) Ok(OutputStream::one(res))
} }
} }

View File

@ -21,7 +21,7 @@ impl WholeStreamCommand for SubCommand {
"Finds the sum of a list of numbers or tables" "Finds the sum of a list of numbers or tables"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
run_with_function(args, summation) run_with_function(args, summation)
} }

View File

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Dictionary, Primitive, ReturnSuccess, UntaggedValue, Value}; use nu_protocol::{Dictionary, Primitive, UntaggedValue, Value};
use indexmap::map::IndexMap; use indexmap::map::IndexMap;
@ -9,7 +9,7 @@ pub type MathFunction = fn(values: &[Value], tag: &Tag) -> Result<Value, ShellEr
pub fn run_with_function( pub fn run_with_function(
args: impl Into<RunnableContext>, args: impl Into<RunnableContext>,
mf: MathFunction, mf: MathFunction,
) -> Result<ActionStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let RunnableContext { let RunnableContext {
mut input, mut input,
call_info, call_info,
@ -23,13 +23,11 @@ pub fn run_with_function(
match res { match res {
Ok(v) => { Ok(v) => {
if v.value.is_table() { if v.value.is_table() {
Ok(ActionStream::from( Ok(OutputStream::from(
v.table_entries() v.table_entries().cloned().collect::<Vec<_>>(),
.map(|v| ReturnSuccess::value(v.clone()))
.collect::<Vec<_>>(),
)) ))
} else { } else {
Ok(ActionStream::one(ReturnSuccess::value(v))) Ok(OutputStream::one(v))
} }
} }
Err(e) => Err(e), Err(e) => Err(e),
@ -47,13 +45,13 @@ pub fn run_with_numerical_functions_on_stream(
int_function: IntFunction, int_function: IntFunction,
decimal_function: DecimalFunction, decimal_function: DecimalFunction,
default_function: DefaultFunction, default_function: DefaultFunction,
) -> Result<ActionStream, ShellError> { ) -> Result<OutputStream, ShellError> {
let mapped = input.map(move |val| match val.value { let mapped = input.map(move |val| match val.value {
UntaggedValue::Primitive(Primitive::Int(val)) => int_function(val), UntaggedValue::Primitive(Primitive::Int(val)) => int_function(val),
UntaggedValue::Primitive(Primitive::Decimal(val)) => decimal_function(val), UntaggedValue::Primitive(Primitive::Decimal(val)) => decimal_function(val),
other => default_function(other), other => default_function(other),
}); });
Ok(ActionStream::from_input(mapped)) Ok(mapped.to_output_stream())
} }
pub fn calculate(values: &[Value], name: &Tag, mf: MathFunction) -> Result<Value, ShellError> { pub fn calculate(values: &[Value], name: &Tag, mf: MathFunction) -> Result<Value, ShellError> {

View File

@ -3,18 +3,10 @@ use bigdecimal::FromPrimitive;
use nu_data::value::compute_values; use nu_data::value::compute_values;
use nu_engine::WholeStreamCommand; use nu_engine::WholeStreamCommand;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ use nu_protocol::{hir::Operator, Dictionary, Primitive, Signature, UntaggedValue, Value};
hir::Operator, Dictionary, Primitive, ReturnSuccess, Signature, UntaggedValue, Value,
};
use nu_source::Tagged;
pub struct SubCommand; pub struct SubCommand;
#[derive(Deserialize)]
struct Arguments {
sample: Tagged<bool>,
}
impl WholeStreamCommand for SubCommand { impl WholeStreamCommand for SubCommand {
fn name(&self) -> &str { fn name(&self) -> &str {
"math variance" "math variance"
@ -28,13 +20,14 @@ impl WholeStreamCommand for SubCommand {
"Finds the variance of a list of numbers or tables" "Finds the variance of a list of numbers or tables"
} }
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> { fn run(&self, raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut args = raw_args.evaluate_once()?;
let sample: bool = args.has_flag("sample");
let values: Vec<Value> = args.input.drain_vec();
let name = args.call_info.name_tag.clone(); let name = args.call_info.name_tag.clone();
let (Arguments { sample }, mut input) = args.process()?;
let values: Vec<Value> = input.drain_vec(); let n = if sample {
let n = if let Tagged { item: true, .. } = sample {
values.len() - 1 values.len() - 1
} else { } else {
values.len() values.len()
@ -79,13 +72,11 @@ impl WholeStreamCommand for SubCommand {
}?; }?;
if res.value.is_table() { if res.value.is_table() {
Ok(ActionStream::from( Ok(OutputStream::from(
res.table_entries() res.table_entries().cloned().collect::<Vec<_>>(),
.map(|v| ReturnSuccess::value(v.clone()))
.collect::<Vec<_>>(),
)) ))
} else { } else {
Ok(ActionStream::one(ReturnSuccess::value(res))) Ok(OutputStream::one(res))
} }
} }