mirror of
https://github.com/nushell/nushell.git
synced 2025-04-14 00:08:20 +02:00
Fix ignore-errors for select (#6896)
* Fix ignore-errors for select * fix Value::List match * fix invalid rows * add tests * fix ListStream match * add one more test for ListStream * add more tests * tweak words
This commit is contained in:
parent
df94052180
commit
c600c1ebe7
@ -23,7 +23,7 @@ impl Command for Select {
|
|||||||
])
|
])
|
||||||
.switch(
|
.switch(
|
||||||
"ignore-errors",
|
"ignore-errors",
|
||||||
"when a column has empty cells, instead of erroring out, replace them with nothing",
|
"when an error occurs, instead of erroring out, suppress the error message",
|
||||||
Some('i'),
|
Some('i'),
|
||||||
)
|
)
|
||||||
.rest(
|
.rest(
|
||||||
@ -51,9 +51,9 @@ impl Command for Select {
|
|||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
let columns: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
let columns: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
|
||||||
let span = call.head;
|
let span = call.head;
|
||||||
let ignore_empty = call.has_flag("ignore-errors");
|
let ignore_errors = call.has_flag("ignore-errors");
|
||||||
|
|
||||||
select(engine_state, span, columns, input, ignore_empty)
|
select(engine_state, span, columns, input, ignore_errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -90,7 +90,7 @@ fn select(
|
|||||||
span: Span,
|
span: Span,
|
||||||
columns: Vec<CellPath>,
|
columns: Vec<CellPath>,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
ignore_empty: bool,
|
ignore_errors: bool,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let mut rows = vec![];
|
let mut rows = vec![];
|
||||||
|
|
||||||
@ -101,6 +101,9 @@ fn select(
|
|||||||
match members.get(0) {
|
match members.get(0) {
|
||||||
Some(PathMember::Int { val, span }) => {
|
Some(PathMember::Int { val, span }) => {
|
||||||
if members.len() > 1 {
|
if members.len() > 1 {
|
||||||
|
if ignore_errors {
|
||||||
|
return Ok(Value::nothing(Span::test_data()).into_pipeline_data());
|
||||||
|
}
|
||||||
return Err(ShellError::GenericError(
|
return Err(ShellError::GenericError(
|
||||||
"Select only allows row numbers for rows".into(),
|
"Select only allows row numbers for rows".into(),
|
||||||
"extra after row number".into(),
|
"extra after row number".into(),
|
||||||
@ -153,24 +156,22 @@ fn select(
|
|||||||
let mut vals = vec![];
|
let mut vals = vec![];
|
||||||
for path in &columns {
|
for path in &columns {
|
||||||
//FIXME: improve implementation to not clone
|
//FIXME: improve implementation to not clone
|
||||||
if ignore_empty {
|
match input_val.clone().follow_cell_path(&path.members, false) {
|
||||||
let fetcher = input_val.clone().follow_cell_path(&path.members, false);
|
Ok(fetcher) => {
|
||||||
|
cols.push(path.into_string().replace('.', "_"));
|
||||||
cols.push(path.into_string().replace('.', "_"));
|
|
||||||
if let Ok(fetcher) = fetcher {
|
|
||||||
vals.push(fetcher);
|
vals.push(fetcher);
|
||||||
if !columns_with_value.contains(&path) {
|
if !columns_with_value.contains(&path) {
|
||||||
columns_with_value.push(path);
|
columns_with_value.push(path);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
vals.push(Value::nothing(span));
|
|
||||||
}
|
}
|
||||||
} else {
|
Err(e) => {
|
||||||
let fetcher =
|
if ignore_errors {
|
||||||
input_val.clone().follow_cell_path(&path.members, false)?;
|
return Ok(
|
||||||
|
Value::nothing(Span::test_data()).into_pipeline_data()
|
||||||
cols.push(path.into_string().replace('.', "_"));
|
);
|
||||||
vals.push(fetcher);
|
}
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,8 +186,10 @@ fn select(
|
|||||||
.into_pipeline_data(engine_state.ctrlc.clone())
|
.into_pipeline_data(engine_state.ctrlc.clone())
|
||||||
.set_metadata(metadata))
|
.set_metadata(metadata))
|
||||||
}
|
}
|
||||||
PipelineData::ListStream(stream, metadata, ..) => Ok(stream
|
PipelineData::ListStream(stream, metadata, ..) => {
|
||||||
.map(move |x| {
|
let mut values = vec![];
|
||||||
|
|
||||||
|
for x in stream {
|
||||||
if !columns.is_empty() {
|
if !columns.is_empty() {
|
||||||
let mut cols = vec![];
|
let mut cols = vec![];
|
||||||
let mut vals = vec![];
|
let mut vals = vec![];
|
||||||
@ -197,19 +200,26 @@ fn select(
|
|||||||
cols.push(path.into_string().replace('.', "_"));
|
cols.push(path.into_string().replace('.', "_"));
|
||||||
vals.push(value);
|
vals.push(value);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(e) => {
|
||||||
cols.push(path.into_string().replace('.', "_"));
|
if ignore_errors {
|
||||||
vals.push(Value::Nothing { span });
|
return Ok(
|
||||||
|
Value::nothing(Span::test_data()).into_pipeline_data()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Record { cols, vals, span }
|
values.push(Value::Record { cols, vals, span });
|
||||||
} else {
|
} else {
|
||||||
x
|
values.push(x);
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.into_pipeline_data(engine_state.ctrlc.clone())
|
|
||||||
.set_metadata(metadata)),
|
Ok(values
|
||||||
|
.into_pipeline_data(engine_state.ctrlc.clone())
|
||||||
|
.set_metadata(metadata))
|
||||||
|
}
|
||||||
PipelineData::Value(v, metadata, ..) => {
|
PipelineData::Value(v, metadata, ..) => {
|
||||||
if !columns.is_empty() {
|
if !columns.is_empty() {
|
||||||
let mut cols = vec![];
|
let mut cols = vec![];
|
||||||
@ -217,10 +227,19 @@ fn select(
|
|||||||
|
|
||||||
for cell_path in columns {
|
for cell_path in columns {
|
||||||
// FIXME: remove clone
|
// FIXME: remove clone
|
||||||
let result = v.clone().follow_cell_path(&cell_path.members, false)?;
|
match v.clone().follow_cell_path(&cell_path.members, false) {
|
||||||
|
Ok(result) => {
|
||||||
|
cols.push(cell_path.into_string().replace('.', "_"));
|
||||||
|
vals.push(result);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
if ignore_errors {
|
||||||
|
return Ok(Value::nothing(Span::test_data()).into_pipeline_data());
|
||||||
|
}
|
||||||
|
|
||||||
cols.push(cell_path.into_string().replace('.', "_"));
|
return Err(e);
|
||||||
vals.push(result);
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::Record { cols, vals, span }
|
Ok(Value::Record { cols, vals, span }
|
||||||
|
@ -169,6 +169,7 @@ fn select_ignores_errors_succesfully1() {
|
|||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
|
assert!(actual.out.is_empty());
|
||||||
assert!(actual.err.is_empty());
|
assert!(actual.err.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,5 +182,87 @@ fn select_ignores_errors_succesfully2() {
|
|||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
|
assert!(actual.out.is_empty());
|
||||||
assert!(actual.err.is_empty());
|
assert!(actual.err.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn select_ignores_errors_succesfull3() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: ".", pipeline(
|
||||||
|
r#"sys | select -i invalid_key"#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert!(actual.out.is_empty());
|
||||||
|
assert!(actual.err.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn select_ignores_errors_succesfully4() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: ".", pipeline(
|
||||||
|
r#"[a b c] | select -i invalid_key"#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert!(actual.out.is_empty());
|
||||||
|
assert!(actual.err.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn select_ignores_errors_successfully5() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: ".", pipeline(
|
||||||
|
r#"[a b c] | select -i 0.0"#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert!(actual.out.is_empty());
|
||||||
|
assert!(actual.err.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn select_ignores_errors_successfully6() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: ".", pipeline(
|
||||||
|
r#""key val\na 1\nb 2\n" | lines | split column -c " " | select -i "100""#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert!(actual.out.is_empty());
|
||||||
|
assert!(actual.err.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn select_failed1() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: ".", pipeline(
|
||||||
|
r#"
|
||||||
|
[{a: 1, b: 2} {a: 3, b: 5} {a: 3}] | select b
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert!(actual.out.is_empty());
|
||||||
|
assert!(actual.err.contains("cannot find column"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn select_failed2() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: ".", pipeline(
|
||||||
|
r#"
|
||||||
|
[{a: 1} {a: 2} {a: 3}] | select b
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert!(actual.out.is_empty());
|
||||||
|
assert!(actual.err.contains("cannot find column"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn select_failed3() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: ".", pipeline(
|
||||||
|
r#""key val\na 1\nb 2\n" | lines | split column -c " " | select "100""#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert!(actual.out.is_empty());
|
||||||
|
assert!(actual.err.contains("cannot find column"));
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user