Merged overloaded commands (#9860)

- fixes #9807

# Description

This pull request merges all overloaded dfr commands into one command:

eager:
dfr first -> eager/first.rs
dfr last -> eager/last.rs
dfr into-nu -> eager/to_nu.rs (merged)

lazy:
dfr min -> expressions/expressions_macro.rs lazy_expressions_macro
dfr max -> expressions/expressions_macro.rs lazy_expressions_macro
dfr sum -> expressions/expressions_macro.rs lazy_expressions_macro
dfr mean -> expressions/expressions_macro.rs lazy_expressions_macro
dfr std -> expressions/expressions_macro.rs lazy_expressions_macro
dfr var   -> expressions/expressions_macro.rs lazy_expressions_macro

series:
dfr n-unique -> series/n_unique.rs
dfr is-not-null -> series/masks/is_not_null.rs
dfr is-null -> series/masks/is_null.rs

# User-Facing Changes
No user facing changes

---------

Co-authored-by: Jack Wright <jack.wright@disqo.com>
This commit is contained in:
Jack Wright 2023-07-31 05:34:12 -07:00 committed by GitHub
parent ba0f069c31
commit 87abfee268
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 731 additions and 493 deletions

View file

@ -1,4 +1,4 @@
use super::super::values::{Column, NuDataFrame};
use super::super::values::{Column, NuDataFrame, NuExpression};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
@ -15,7 +15,7 @@ impl Command for FirstDF {
}
fn usage(&self) -> &str {
"Show only the first number of rows."
"Show only the first number of rows or create a first expression"
}
fn signature(&self) -> Signature {
@ -25,10 +25,16 @@ impl Command for FirstDF {
SyntaxShape::Int,
"starting from the front, the number of rows to return",
)
.input_output_type(
.input_output_types(vec![
(
Type::Custom("expression".into()),
Type::Custom("expression".into()),
),
(
Type::Custom("dataframe".into()),
Type::Custom("dataframe".into()),
)
),
])
.category(Category::Custom("dataframe".into()))
}
@ -64,6 +70,11 @@ impl Command for FirstDF {
.into_value(Span::test_data()),
),
},
Example {
description: "Creates a first expression from a column",
example: "dfr col a | dfr first",
result: None,
},
]
}
@ -74,8 +85,19 @@ impl Command for FirstDF {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let value = input.into_value(call.head);
if NuDataFrame::can_downcast(&value) {
let df = NuDataFrame::try_from_value(value)?;
command(engine_state, stack, call, df)
} else {
let expr = NuExpression::try_from_value(value)?;
let expr: NuExpression = expr.into_polars().first().into();
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
}
}
}
@ -97,11 +119,25 @@ fn command(
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::super::super::test_dataframe::{build_test_engine_state, test_dataframe_example};
use super::*;
use crate::dataframe::lazy::aggregate::LazyAggregate;
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(FirstDF {})])
fn test_examples_dataframe() {
let mut engine_state = build_test_engine_state(vec![Box::new(FirstDF {})]);
test_dataframe_example(&mut engine_state, &FirstDF.examples()[0]);
test_dataframe_example(&mut engine_state, &FirstDF.examples()[1]);
}
#[test]
fn test_examples_expression() {
let mut engine_state = build_test_engine_state(vec![
Box::new(FirstDF {}),
Box::new(LazyAggregate {}),
Box::new(ToLazyGroupBy {}),
]);
test_dataframe_example(&mut engine_state, &FirstDF.examples()[2]);
}
}

View file

@ -1,4 +1,4 @@
use super::super::values::{utils::DEFAULT_ROWS, Column, NuDataFrame};
use super::super::values::{utils::DEFAULT_ROWS, Column, NuDataFrame, NuExpression};
use nu_engine::CallExt;
use nu_protocol::{
ast::Call,
@ -21,15 +21,22 @@ impl Command for LastDF {
fn signature(&self) -> Signature {
Signature::build(self.name())
.optional("rows", SyntaxShape::Int, "Number of rows for tail")
.input_output_type(
.input_output_types(vec![
(
Type::Custom("expression".into()),
Type::Custom("expression".into()),
),
(
Type::Custom("dataframe".into()),
Type::Custom("dataframe".into()),
)
),
])
.category(Category::Custom("dataframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
vec![
Example {
description: "Create new dataframe with last rows",
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr last 1",
result: Some(
@ -40,7 +47,13 @@ impl Command for LastDF {
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
},
Example {
description: "Creates a last expression from a column",
example: "dfr col a | dfr last",
result: None,
},
]
}
fn run(
@ -50,8 +63,19 @@ impl Command for LastDF {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let value = input.into_value(call.head);
if NuDataFrame::can_downcast(&value) {
let df = NuDataFrame::try_from_value(value)?;
command(engine_state, stack, call, df)
} else {
let expr = NuExpression::try_from_value(value)?;
let expr: NuExpression = expr.into_polars().last().into();
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
}
}
}
@ -73,11 +97,24 @@ fn command(
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::super::super::test_dataframe::{build_test_engine_state, test_dataframe_example};
use super::*;
use crate::dataframe::lazy::aggregate::LazyAggregate;
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(LastDF {})])
fn test_examples_dataframe() {
let mut engine_state = build_test_engine_state(vec![Box::new(LastDF {})]);
test_dataframe_example(&mut engine_state, &LastDF.examples()[0]);
}
#[test]
fn test_examples_expression() {
let mut engine_state = build_test_engine_state(vec![
Box::new(LastDF {}),
Box::new(LazyAggregate {}),
Box::new(ToLazyGroupBy {}),
]);
test_dataframe_example(&mut engine_state, &LastDF.examples()[1]);
}
}

View file

@ -1,7 +1,7 @@
/// Definition of multiple Expression commands using a macro rule
/// All of these expressions have an identical body and only require
/// to have a change in the name, description and expression function
use crate::dataframe::values::{Column, NuDataFrame, NuExpression};
use crate::dataframe::values::{Column, NuDataFrame, NuExpression, NuLazyFrame};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
@ -134,6 +134,186 @@ macro_rules! expr_command {
};
}
// The structs defined in this file are structs that form part of other commands
// since they share a similar name
macro_rules! lazy_expr_command {
($command: ident, $name: expr, $desc: expr, $examples: expr, $func: ident, $test: ident) => {
#[derive(Clone)]
pub struct $command;
impl Command for $command {
fn name(&self) -> &str {
$name
}
fn usage(&self) -> &str {
$desc
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_types(vec![
(
Type::Custom("expression".into()),
Type::Custom("expression".into()),
),
(
Type::Custom("dataframe".into()),
Type::Custom("dataframe".into()),
),
])
.category(Category::Custom("expression".into()))
}
fn examples(&self) -> Vec<Example> {
$examples
}
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let value = input.into_value(call.head);
if NuDataFrame::can_downcast(&value) {
let lazy = NuLazyFrame::try_from_value(value)?;
let lazy = NuLazyFrame::new(lazy.from_eager, lazy.into_polars().$func());
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
} else {
let expr = NuExpression::try_from_value(value)?;
let expr: NuExpression = expr.into_polars().$func().into();
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
}
}
}
#[cfg(test)]
mod $test {
use super::super::super::test_dataframe::{
build_test_engine_state, test_dataframe_example,
};
use super::*;
use crate::dataframe::lazy::aggregate::LazyAggregate;
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
#[test]
fn test_examples_dataframe() {
// the first example should be a for the dataframe case
let example = &$command.examples()[0];
let mut engine_state = build_test_engine_state(vec![Box::new($command {})]);
test_dataframe_example(&mut engine_state, &example)
}
#[test]
fn test_examples_expressions() {
// the second example should be a for the dataframe case
let example = &$command.examples()[1];
let mut engine_state = build_test_engine_state(vec![
Box::new($command {}),
Box::new(LazyAggregate {}),
Box::new(ToLazyGroupBy {}),
]);
test_dataframe_example(&mut engine_state, &example)
}
}
};
($command: ident, $name: expr, $desc: expr, $examples: expr, $func: ident, $test: ident, $ddof: expr) => {
#[derive(Clone)]
pub struct $command;
impl Command for $command {
fn name(&self) -> &str {
$name
}
fn usage(&self) -> &str {
$desc
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_types(vec![
(
Type::Custom("expression".into()),
Type::Custom("expression".into()),
),
(
Type::Custom("dataframe".into()),
Type::Custom("dataframe".into()),
),
])
.category(Category::Custom("expression".into()))
}
fn examples(&self) -> Vec<Example> {
$examples
}
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let value = input.into_value(call.head);
if NuDataFrame::can_downcast(&value) {
let lazy = NuLazyFrame::try_from_value(value)?;
let lazy = NuLazyFrame::new(lazy.from_eager, lazy.into_polars().$func($ddof));
Ok(PipelineData::Value(lazy.into_value(call.head)?, None))
} else {
let expr = NuExpression::try_from_value(value)?;
let expr: NuExpression = expr.into_polars().$func($ddof).into();
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
}
}
}
#[cfg(test)]
mod $test {
use super::super::super::test_dataframe::{
build_test_engine_state, test_dataframe_example,
};
use super::*;
use crate::dataframe::lazy::aggregate::LazyAggregate;
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
#[test]
fn test_examples_dataframe() {
// the first example should be a for the dataframe case
let example = &$command.examples()[0];
let mut engine_state = build_test_engine_state(vec![Box::new($command {})]);
test_dataframe_example(&mut engine_state, &example)
}
#[test]
fn test_examples_expressions() {
// the second example should be a for the dataframe case
let example = &$command.examples()[1];
let mut engine_state = build_test_engine_state(vec![
Box::new($command {}),
Box::new(LazyAggregate {}),
Box::new(ToLazyGroupBy {}),
]);
test_dataframe_example(&mut engine_state, &example)
}
}
};
}
// ExprList command
// Expands to a command definition for a list expression
expr_command!(
@ -209,81 +389,6 @@ expr_command!(
test_count
);
// ExprFirst command
// Expands to a command definition for a count expression
expr_command!(
ExprFirst,
"dfr first",
"creates a first expression",
vec![Example {
description: "Creates a first expression from a column",
example: "dfr col a | dfr first",
result: None,
},],
first,
test_first
);
// ExprLast command
// Expands to a command definition for a count expression
expr_command!(
ExprLast,
"dfr last",
"creates a last expression",
vec![Example {
description: "Creates a last expression from a column",
example: "dfr col a | dfr last",
result: None,
},],
last,
test_last
);
// ExprNUnique command
// Expands to a command definition for a n-unique expression
expr_command!(
ExprNUnique,
"dfr n-unique",
"creates a n-unique expression",
vec![Example {
description: "Creates a is n-unique expression from a column",
example: "dfr col a | dfr n-unique",
result: None,
},],
n_unique,
test_nunique
);
// ExprIsNotNull command
// Expands to a command definition for a n-unique expression
expr_command!(
ExprIsNotNull,
"dfr is-not-null",
"creates a is not null expression",
vec![Example {
description: "Creates a is not null expression from a column",
example: "dfr col a | dfr is-not-null",
result: None,
},],
is_not_null,
test_is_not_null
);
// ExprIsNull command
// Expands to a command definition for a n-unique expression
expr_command!(
ExprIsNull,
"dfr is-null",
"creates a is null expression",
vec![Example {
description: "Creates a is null expression from a column",
example: "dfr col a | dfr is-null",
result: None,
},],
is_null,
test_is_null
);
// ExprNot command
// Expands to a command definition for a not expression
expr_command!(
@ -301,11 +406,24 @@ expr_command!(
// ExprMax command
// Expands to a command definition for max aggregation
expr_command!(
lazy_expr_command!(
ExprMax,
"dfr max",
"Creates a max expression",
vec![Example {
"Creates a max expression or aggregates columns to their max value",
vec![
Example {
description: "Max value from columns in a dataframe",
example: "[[a b]; [6 2] [1 4] [4 1]] | dfr into-df | dfr max",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(6)],),
Column::new("b".to_string(), vec![Value::test_int(4)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Max aggregation for a group-by",
example: r#"[[a b]; [one 2] [one 4] [two 1]]
| dfr into-df
@ -325,18 +443,32 @@ expr_command!(
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
},
],
max,
test_max
);
// ExprMin command
// Expands to a command definition for min aggregation
expr_command!(
lazy_expr_command!(
ExprMin,
"dfr min",
"Creates a min expression",
vec![Example {
"Creates a min expression or aggregates columns to their min value",
vec![
Example {
description: "Min value from columns in a dataframe",
example: "[[a b]; [6 2] [1 4] [4 1]] | dfr into-df | dfr min",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(1)],),
Column::new("b".to_string(), vec![Value::test_int(1)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Min aggregation for a group-by",
example: r#"[[a b]; [one 2] [one 4] [two 1]]
| dfr into-df
@ -356,18 +488,32 @@ expr_command!(
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
},
],
min,
test_min
);
// ExprSum command
// Expands to a command definition for sum aggregation
expr_command!(
lazy_expr_command!(
ExprSum,
"dfr sum",
"Creates a sum expression for an aggregation",
vec![Example {
"Creates a sum expression for an aggregation or aggregates columns to their sum value",
vec![
Example {
description: "Sums all columns in a dataframe",
example: "[[a b]; [6 2] [1 4] [4 1]] | dfr into-df | dfr sum",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(11)],),
Column::new("b".to_string(), vec![Value::test_int(7)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Sum aggregation for a group-by",
example: r#"[[a b]; [one 2] [one 4] [two 1]]
| dfr into-df
@ -387,18 +533,32 @@ expr_command!(
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
},
],
sum,
test_sum
);
// ExprMean command
// Expands to a command definition for mean aggregation
expr_command!(
lazy_expr_command!(
ExprMean,
"dfr mean",
"Creates a mean expression for an aggregation",
vec![Example {
"Creates a mean expression for an aggregation or aggregates columns to their mean value",
vec![
Example {
description: "Mean value from columns in a dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr into-df | dfr mean",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_float(4.0)],),
Column::new("b".to_string(), vec![Value::test_float(2.0)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Mean aggregation for a group-by",
example: r#"[[a b]; [one 2] [one 4] [two 1]]
| dfr into-df
@ -418,7 +578,8 @@ expr_command!(
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
},
],
mean,
test_mean
);
@ -456,11 +617,24 @@ expr_command!(
// ExprStd command
// Expands to a command definition for std aggregation
expr_command!(
lazy_expr_command!(
ExprStd,
"dfr std",
"Creates a std expression for an aggregation",
vec![Example {
"Creates a std expression for an aggregation of std value from columns in a dataframe",
vec![
Example {
description: "Std value from columns in a dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr into-df | dfr std",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_float(2.0)],),
Column::new("b".to_string(), vec![Value::test_float(0.0)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Std aggregation for a group-by",
example: r#"[[a b]; [one 2] [one 2] [two 1] [two 1]]
| dfr into-df
@ -480,19 +654,34 @@ expr_command!(
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
},
],
std,
test_std,
0
1
);
// ExprVar command
// Expands to a command definition for var aggregation
expr_command!(
lazy_expr_command!(
ExprVar,
"dfr var",
"Create a var expression for an aggregation",
vec![Example {
vec![
Example {
description:
"Var value from columns in a dataframe or aggregates columns to their var value",
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr into-df | dfr var",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_float(4.0)],),
Column::new("b".to_string(), vec![Value::test_float(0.0)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},
Example {
description: "Var aggregation for a group-by",
example: r#"[[a b]; [one 2] [one 2] [two 1] [two 1]]
| dfr into-df
@ -512,8 +701,9 @@ expr_command!(
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
},
],
var,
test_var,
0
1
);

View file

@ -50,12 +50,7 @@ pub fn add_expressions(working_set: &mut StateWorkingSet) {
ExprFlatten,
ExprExplode,
ExprCount,
ExprFirst,
ExprLast,
ExprNUnique,
ExprIsIn,
ExprIsNotNull,
ExprIsNull,
ExprNot,
ExprMax,
ExprMin,

View file

@ -157,94 +157,6 @@ lazy_command!(
test_cache
);
// LazyMax command
// Expands to a command definition for max aggregation
lazy_command!(
LazyMax,
"dfr max",
"Aggregates columns to their max value",
vec![Example {
description: "Max value from columns in a dataframe",
example: "[[a b]; [6 2] [1 4] [4 1]] | dfr into-df | dfr max",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(6)],),
Column::new("b".to_string(), vec![Value::test_int(4)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
max,
test_max
);
// LazyMin command
// Expands to a command definition for min aggregation
lazy_command!(
LazyMin,
"dfr min",
"Aggregates columns to their min value",
vec![Example {
description: "Min value from columns in a dataframe",
example: "[[a b]; [6 2] [1 4] [4 1]] | dfr into-df | dfr min",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(1)],),
Column::new("b".to_string(), vec![Value::test_int(1)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
min,
test_min
);
// LazySum command
// Expands to a command definition for sum aggregation
lazy_command!(
LazySum,
"dfr sum",
"Aggregates columns to their sum value",
vec![Example {
description: "Sums all columns in a dataframe",
example: "[[a b]; [6 2] [1 4] [4 1]] | dfr into-df | dfr sum",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_int(11)],),
Column::new("b".to_string(), vec![Value::test_int(7)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
sum,
test_sum
);
// LazyMean command
// Expands to a command definition for mean aggregation
lazy_command!(
LazyMean,
"dfr mean",
"Aggregates columns to their mean value",
vec![Example {
description: "Mean value from columns in a dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr into-df | dfr mean",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_float(4.0)],),
Column::new("b".to_string(), vec![Value::test_float(2.0)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
mean,
test_mean
);
// LazyMedian command
// Expands to a command definition for median aggregation
lazy_command!(
@ -266,49 +178,3 @@ lazy_command!(
median,
test_median
);
// LazyStd command
// Expands to a command definition for std aggregation
lazy_command!(
LazyStd,
"dfr std",
"Aggregates columns to their std value",
vec![Example {
description: "Std value from columns in a dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr into-df | dfr std",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_float(2.0)],),
Column::new("b".to_string(), vec![Value::test_float(0.0)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
std,
test_std,
1
);
// LazyVar command
// Expands to a command definition for var aggregation
lazy_command!(
LazyVar,
"dfr var",
"Aggregates columns to their var value",
vec![Example {
description: "Var value from columns in a dataframe",
example: "[[a b]; [6 2] [4 2] [2 2]] | dfr into-df | dfr var",
result: Some(
NuDataFrame::try_from_columns(vec![
Column::new("a".to_string(), vec![Value::test_float(4.0)],),
Column::new("b".to_string(), vec![Value::test_float(0.0)],),
])
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
},],
var,
test_var,
1
);

View file

@ -49,13 +49,7 @@ pub fn add_lazy_decls(working_set: &mut StateWorkingSet) {
LazyFilter,
LazyJoin,
LazyQuantile,
LazyMax,
LazyMin,
LazySum,
LazyMean,
LazyMedian,
LazyStd,
LazyVar,
LazyReverse,
LazySelect,
LazySortBy,

View file

@ -1,4 +1,4 @@
use super::super::super::values::{Column, NuDataFrame};
use super::super::super::values::{Column, NuDataFrame, NuExpression};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
@ -20,15 +20,22 @@ impl Command for IsNotNull {
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_type(
.input_output_types(vec![
(
Type::Custom("expression".into()),
Type::Custom("expression".into()),
),
(
Type::Custom("dataframe".into()),
Type::Custom("dataframe".into()),
)
),
])
.category(Category::Custom("dataframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
vec![
Example {
description: "Create mask where values are not null",
example: r#"let s = ([5 6 0 8] | dfr into-df);
let res = ($s / $s);
@ -46,7 +53,13 @@ impl Command for IsNotNull {
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
},
Example {
description: "Creates a is not null expression from a column",
example: "dfr col a | dfr is-not-null",
result: None,
},
]
}
fn run(
@ -56,8 +69,19 @@ impl Command for IsNotNull {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let value = input.into_value(call.head);
if NuDataFrame::can_downcast(&value) {
let df = NuDataFrame::try_from_value(value)?;
command(engine_state, stack, call, df)
} else {
let expr = NuExpression::try_from_value(value)?;
let expr: NuExpression = expr.into_polars().is_not_null().into();
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
}
}
}
@ -76,11 +100,24 @@ fn command(
#[cfg(test)]
mod test {
use super::super::super::super::test_dataframe::test_dataframe;
use super::*;
use crate::dataframe::lazy::aggregate::LazyAggregate;
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
use crate::dataframe::test_dataframe::{build_test_engine_state, test_dataframe_example};
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(IsNotNull {})])
fn test_examples_dataframe() {
let mut engine_state = build_test_engine_state(vec![Box::new(IsNotNull {})]);
test_dataframe_example(&mut engine_state, &IsNotNull.examples()[0]);
}
#[test]
fn test_examples_expression() {
let mut engine_state = build_test_engine_state(vec![
Box::new(IsNotNull {}),
Box::new(LazyAggregate {}),
Box::new(ToLazyGroupBy {}),
]);
test_dataframe_example(&mut engine_state, &IsNotNull.examples()[1]);
}
}

View file

@ -1,4 +1,4 @@
use super::super::super::values::{Column, NuDataFrame};
use super::super::super::values::{Column, NuDataFrame, NuExpression};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
@ -20,15 +20,22 @@ impl Command for IsNull {
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_type(
.input_output_types(vec![
(
Type::Custom("expression".into()),
Type::Custom("expression".into()),
),
(
Type::Custom("dataframe".into()),
Type::Custom("dataframe".into()),
)
),
])
.category(Category::Custom("dataframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
vec![
Example {
description: "Create mask where values are null",
example: r#"let s = ([5 6 0 8] | dfr into-df);
let res = ($s / $s);
@ -46,7 +53,13 @@ impl Command for IsNull {
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
},
Example {
description: "Creates a is null expression from a column",
example: "dfr col a | dfr is-null",
result: None,
},
]
}
fn run(
@ -56,8 +69,19 @@ impl Command for IsNull {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let value = input.into_value(call.head);
if NuDataFrame::can_downcast(&value) {
let df = NuDataFrame::try_from_value(value)?;
command(engine_state, stack, call, df)
} else {
let expr = NuExpression::try_from_value(value)?;
let expr: NuExpression = expr.into_polars().is_null().into();
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
}
}
}
@ -76,11 +100,24 @@ fn command(
#[cfg(test)]
mod test {
use super::super::super::super::test_dataframe::test_dataframe;
use super::*;
use crate::dataframe::lazy::aggregate::LazyAggregate;
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
use crate::dataframe::test_dataframe::{build_test_engine_state, test_dataframe_example};
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(IsNull {})])
fn test_examples_dataframe() {
let mut engine_state = build_test_engine_state(vec![Box::new(IsNull {})]);
test_dataframe_example(&mut engine_state, &IsNull.examples()[0]);
}
#[test]
fn test_examples_expression() {
let mut engine_state = build_test_engine_state(vec![
Box::new(IsNull {}),
Box::new(LazyAggregate {}),
Box::new(ToLazyGroupBy {}),
]);
test_dataframe_example(&mut engine_state, &IsNull.examples()[1]);
}
}

View file

@ -1,4 +1,4 @@
use super::super::values::{Column, NuDataFrame};
use super::super::values::{Column, NuDataFrame, NuExpression};
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
@ -19,15 +19,22 @@ impl Command for NUnique {
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_type(
.input_output_types(vec![
(
Type::Custom("expression".into()),
Type::Custom("expression".into()),
),
(
Type::Custom("dataframe".into()),
Type::Custom("dataframe".into()),
)
),
])
.category(Category::Custom("dataframe".into()))
}
fn examples(&self) -> Vec<Example> {
vec![Example {
vec![
Example {
description: "Counts unique values",
example: "[1 1 2 2 3 3 4] | dfr into-df | dfr n-unique",
result: Some(
@ -38,7 +45,13 @@ impl Command for NUnique {
.expect("simple df for test should not fail")
.into_value(Span::test_data()),
),
}]
},
Example {
description: "Creates a is n-unique expression from a column",
example: "dfr col a | dfr n-unique",
result: None,
},
]
}
fn run(
@ -48,8 +61,19 @@ impl Command for NUnique {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let df = NuDataFrame::try_from_pipeline(input, call.head)?;
let value = input.into_value(call.head);
if NuDataFrame::can_downcast(&value) {
let df = NuDataFrame::try_from_value(value)?;
command(engine_state, stack, call, df)
} else {
let expr = NuExpression::try_from_value(value)?;
let expr: NuExpression = expr.into_polars().n_unique().into();
Ok(PipelineData::Value(
NuExpression::into_value(expr, call.head),
None,
))
}
}
}
@ -77,11 +101,24 @@ fn command(
#[cfg(test)]
mod test {
use super::super::super::test_dataframe::test_dataframe;
use super::super::super::test_dataframe::{build_test_engine_state, test_dataframe_example};
use super::*;
use crate::dataframe::lazy::aggregate::LazyAggregate;
use crate::dataframe::lazy::groupby::ToLazyGroupBy;
#[test]
fn test_examples() {
test_dataframe(vec![Box::new(NUnique {})])
fn test_examples_dataframe() {
let mut engine_state = build_test_engine_state(vec![Box::new(NUnique {})]);
test_dataframe_example(&mut engine_state, &NUnique.examples()[0]);
}
#[test]
fn test_examples_expression() {
let mut engine_state = build_test_engine_state(vec![
Box::new(NUnique {}),
Box::new(LazyAggregate {}),
Box::new(ToLazyGroupBy {}),
]);
test_dataframe_example(&mut engine_state, &NUnique.examples()[1]);
}
}

View file

@ -2,7 +2,7 @@ use nu_engine::eval_block;
use nu_parser::parse;
use nu_protocol::{
engine::{Command, EngineState, Stack, StateWorkingSet},
PipelineData, Span,
Example, PipelineData, Span,
};
use super::eager::ToDataFrame;
@ -17,6 +17,14 @@ pub fn test_dataframe(cmds: Vec<Box<dyn Command + 'static>>) {
// The first element in the cmds vector must be the one tested
let examples = cmds[0].examples();
let mut engine_state = build_test_engine_state(cmds.clone());
for example in examples {
test_dataframe_example(&mut engine_state, &example);
}
}
pub fn build_test_engine_state(cmds: Vec<Box<dyn Command + 'static>>) -> Box<EngineState> {
let mut engine_state = Box::new(EngineState::new());
let delta = {
@ -41,11 +49,15 @@ pub fn test_dataframe(cmds: Vec<Box<dyn Command + 'static>>) {
.merge_delta(delta)
.expect("Error merging delta");
for example in examples {
engine_state
}
pub fn test_dataframe_example(engine_state: &mut Box<EngineState>, example: &Example) {
// Skip tests that don't have results to compare to
if example.result.is_none() {
continue;
return;
}
let start = std::time::Instant::now();
let (block, delta) = {
@ -83,12 +95,9 @@ pub fn test_dataframe(cmds: Vec<Box<dyn Command + 'static>>) {
// Note. Value implements PartialEq for Bool, Int, Float, String and Block
// If the command you are testing requires to compare another case, then
// you need to define its equality in the Value struct
if let Some(expected) = example.result {
if let Some(expected) = example.result.clone() {
if result != expected {
panic!(
"the example result is different to expected value: {result:?} != {expected:?}"
)
}
panic!("the example result is different to expected value: {result:?} != {expected:?}")
}
}
}