Issue 1787 (#1827)

This commit is contained in:
Alexander James 2020-05-23 18:08:39 -06:00 committed by GitHub
parent 460daf029b
commit aadbcf5ce8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 227 additions and 10 deletions

View File

@ -2,9 +2,11 @@ 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};
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value}; use nu_protocol::{Dictionary, ReturnSuccess, ReturnValue, Signature, UntaggedValue, Value};
use num_traits::identities::Zero; use num_traits::identities::Zero;
use indexmap::map::IndexMap;
pub struct Sum; pub struct Sum;
impl WholeStreamCommand for Sum { impl WholeStreamCommand for Sum {
@ -54,13 +56,40 @@ impl WholeStreamCommand for Sum {
fn sum(RunnableContext { mut input, .. }: RunnableContext) -> Result<OutputStream, ShellError> { fn sum(RunnableContext { mut input, .. }: RunnableContext) -> Result<OutputStream, ShellError> {
let stream = async_stream! { let stream = async_stream! {
let mut values = input.drain_vec().await; let mut values: Vec<Value> = input.drain_vec().await;
let action = reducer_for(Reduce::Sum); let action = reducer_for(Reduce::Sum);
match action(Value::zero(), values) { if values.iter().all(|v| if let UntaggedValue::Primitive(_) = v.value {true} else {false}) {
Ok(total) => yield ReturnSuccess::value(total), let total = action(Value::zero(), values)?;
yield ReturnSuccess::value(total)
} else {
let mut column_values = IndexMap::new();
for value in values {
match value.value {
UntaggedValue::Row(row_dict) => {
for (key, value) in row_dict.entries.iter() {
column_values
.entry(key.clone())
.and_modify(|v: &mut Vec<Value>| v.push(value.clone()))
.or_insert(vec![value.clone()]);
}
},
table => {},
};
}
let mut column_totals = IndexMap::new();
for (col_name, col_vals) in column_values {
let sum = action(Value::zero(), col_vals);
match sum {
Ok(value) => {
column_totals.insert(col_name, value);
},
Err(err) => yield Err(err), Err(err) => yield Err(err),
};
}
yield ReturnSuccess::value(
UntaggedValue::Row(Dictionary {entries: column_totals}).into_untagged_value())
} }
}; };

View File

@ -198,9 +198,20 @@ pub fn evaluate(
} }
pub fn sum(data: Vec<Value>) -> Result<Value, ShellError> { pub fn sum(data: Vec<Value>) -> Result<Value, ShellError> {
Ok(data let mut acc = Value::zero();
.into_iter() for value in data {
.fold(Value::zero(), |acc: Value, value| acc + value)) match value.value {
UntaggedValue::Primitive(_) => acc = acc + value,
_ => {
return Err(ShellError::labeled_error(
"Attempted to compute the sum of a value that cannot be summed.",
"value appears here",
value.tag.span,
))
}
}
}
Ok(acc)
} }
fn formula( fn formula(

View File

@ -1,6 +1,7 @@
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed; use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
use nu_test_support::playground::Playground; use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline}; use nu_test_support::{nu, pipeline};
use std::str::FromStr;
#[test] #[test]
fn all() { fn all() {
@ -60,3 +61,52 @@ fn outputs_zero_with_no_input() {
assert_eq!(actual.out, "0"); assert_eq!(actual.out, "0");
}) })
} }
#[test]
fn compute_sum_of_individual_row() -> Result<(), String> {
let answers_for_columns = [
("cpu", 88.257434),
("mem", 3032375296.),
("virtual", 102579965952.),
];
for (column_name, expected_value) in answers_for_columns.iter() {
let actual = nu!(
cwd: "tests/fixtures/formats/",
format!("open sample-ps-output.json | select {} | sum | get {}", column_name, column_name)
);
let result =
f64::from_str(&actual.out).map_err(|_| String::from("Failed to parse float."))?;
assert_eq!(result, *expected_value);
}
Ok(())
}
#[test]
fn compute_sum_of_table() -> Result<(), String> {
let answers_for_columns = [
("cpu", 88.257434),
("mem", 3032375296.),
("virtual", 102579965952.),
];
for (column_name, expected_value) in answers_for_columns.iter() {
let actual = nu!(
cwd: "tests/fixtures/formats/",
format!("open sample-ps-output.json | select cpu mem virtual | sum | get {}", column_name)
);
let result =
f64::from_str(&actual.out).map_err(|_| String::from("Failed to parse float."))?;
assert_eq!(result, *expected_value);
}
Ok(())
}
#[test]
fn sum_of_a_row_containing_a_table_is_an_error() {
let actual = nu!(
cwd: "tests/fixtures/formats/",
"open sample-sys-output.json | sum"
);
assert!(actual
.err
.contains("Attempted to compute the sum of a value that cannot be summed."));
}

View File

@ -531,7 +531,8 @@ impl std::ops::Add for Value {
UntaggedValue::from(left.add(right)).into_value(tag) UntaggedValue::from(left.add(right)).into_value(tag)
} }
(_, _) => unimplemented!("Internal error: can't add non-primitives."), (_, _) => UntaggedValue::Error(ShellError::unimplemented("Can't add non-primitives."))
.into_value(tag),
} }
} }
} }

View File

@ -0,0 +1 @@
[{"pid":10390,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":132112384,"virtual":4989624320},{"pid":10461,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":126992384,"virtual":4995346432},{"pid":10530,"name":"kworker/6:1-events","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":10593,"name":"kworker/1:1-mm_percpu_wq","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":10650,"name":"chrome","status":"Sleeping","cpu":8.026974,"mem":262434816,"virtual":5217419264},{"pid":10803,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":48173056,"virtual":542531584},{"pid":11191,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":124092416,"virtual":4975763456},{"pid":11210,"name":"kworker/7:0-events","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":11254,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":113070080,"virtual":4971659264},{"pid":11279,"name":"kworker/u16:0-events_unbound","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":11476,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":88993792,"virtual":4937097216},{"pid":12755,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":163397632,"virtual":5034328064},{"pid":12772,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":113561600,"virtual":4985073664},{"pid":14351,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":111861760,"virtual":4962754560},{"pid":17818,"name":"udisksd","status":"Sleeping","cpu":0.0,"mem":14409728,"virtual":402935808},{"pid":17815,"name":".gvfs-udisks2-v","status":"Sleeping","cpu":0.0,"mem":16199680,"virtual":585306112},{"pid":17831,"name":".gvfs-mtp-volum","status":"Sleeping","cpu":0.0,"mem":6393856,"virtual":454680576},{"pid":17836,"name":".gvfs-gphoto2-v","status":"Sleeping","cpu":0.0,"mem":7110656,"virtual":456966144},{"pid":17841,"name":".gvfs-afc-volum","status":"Sleeping","cpu":0.0,"mem":8585216,"virtual":537448448},{"pid":17846,"name":".gvfsd-trash-wr","status":"Sleeping","cpu":0.0,"mem":12767232,"virtual":577998848},{"pid":17856,"name":".gvfsd-network-","status":"Sleeping","cpu":0.0,"mem":13295616,"virtual":654110720},{"pid":17862,"name":".gvfsd-dnssd-wr","status":"Sleeping","cpu":0.0,"mem":7639040,"virtual":533233664},{"pid":17869,"name":"dconf-service","status":"Sleeping","cpu":0.0,"mem":5365760,"virtual":158957568},{"pid":18153,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":183738368,"virtual":5128962048},{"pid":23033,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":166035456,"virtual":5074878464},{"pid":24101,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":101224448,"virtual":4956262400},{"pid":24832,"name":"kworker/7:2-events","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":24912,"name":"kworker/5:2-events_power_efficient","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":25228,"name":"kworker/4:3-events","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":25678,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":117522432,"virtual":4970983424},{"pid":25706,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":30760960,"virtual":528375808},{"pid":26080,"name":"kworker/1:0-events","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":26818,"name":"kworker/2:0-events","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":26827,"name":"kworker/6:2-mm_percpu_wq","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":26832,"name":"kworker/0:2-mm_percpu_wq","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":26843,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":116621312,"virtual":4982403072},{"pid":27163,"name":"kworker/3:2-events","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":27800,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":128200704,"virtual":4965363712},{"pid":27820,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":54960128,"virtual":4895596544},{"pid":27898,"name":"kworker/3:0-mm_percpu_wq","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":27977,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":141930496,"virtual":4982546432},{"pid":28035,"name":"kworker/u16:1-events_unbound","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":28104,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":126853120,"virtual":5003902976},{"pid":28158,"name":"nu","status":"Sleeping","cpu":0.0,"mem":27344896,"virtual":870764544},{"pid":28236,"name":"chrome","status":"Sleeping","cpu":0.0,"mem":450560000,"virtual":5389582336},{"pid":29186,"name":"kworker/5:0-events","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":30140,"name":"kworker/u16:2-events_unbound","status":"Idle","cpu":0.0,"mem":0,"virtual":0},{"pid":30142,"name":"nu_plugin_core_","status":"Zombie","cpu":0.0,"mem":0,"virtual":0},{"pid":30356,"name":"sh","status":"Sleeping","cpu":0.0,"mem":3743744,"virtual":224092160},{"pid":30360,"name":"nu_plugin_core_ps","status":"Sleeping","cpu":80.23046000000001,"mem":6422528,"virtual":633016320}]

View File

@ -0,0 +1,125 @@
{
"host": {
"name": "Linux",
"release": "5.4.33",
"version": "#1-NixOS SMP Fri Apr 17 08:50:26 UTC 2020",
"hostname": "nixos",
"arch": "x86_64",
"uptime": 105126,
"sessions": [
"alexj"
]
},
"cpu": {
"cores": 8,
"current ghz": 2.4200000000000004,
"min ghz": 0.39999999999999997,
"max ghz": 3.4000000000000004
},
"disks": [
{
"device": "/dev/disk/by-uuid/e9adff48-c37b-4631-b98b-eaec9b410ba3",
"type": "ext4",
"mount": "/",
"total": 483445473280,
"used": 121866776576,
"free": 336949624832
},
{
"device": "/dev/disk/by-uuid/e9adff48-c37b-4631-b98b-eaec9b410ba3",
"type": "ext4",
"mount": "/nix/store",
"total": 483445473280,
"used": 121866776576,
"free": 336949624832
},
{
"device": "/dev/sda3",
"type": "vfat",
"mount": "/boot",
"total": 534757376,
"used": 72650752,
"free": 462106624
}
],
"mem": {
"total": 16256524000,
"free": 3082268000,
"swap total": 18874344000,
"swap free": 18874344000
},
"temp": [
{
"unit": "iwlwifi_1",
"temp": 42.0
},
{
"unit": "acpitz",
"temp": 53.00000000000001,
"critical": 103.0
},
{
"unit": "coretemp",
"label": "Core 1",
"temp": 52.00000000000001,
"high": 100.0,
"critical": 100.0
},
{
"unit": "coretemp",
"label": "Core 2",
"temp": 52.00000000000001,
"high": 100.0,
"critical": 100.0
},
{
"unit": "coretemp",
"label": "Package id 0",
"temp": 52.00000000000001,
"high": 100.0,
"critical": 100.0
},
{
"unit": "coretemp",
"label": "Core 3",
"temp": 51.00000000000001,
"high": 100.0,
"critical": 100.0
},
{
"unit": "coretemp",
"label": "Core 0",
"temp": 51.00000000000001,
"high": 100.0,
"critical": 100.0
},
{
"unit": "pch_skylake",
"temp": 48.00000000000001
}
],
"net": [
{
"name": "wlp2s0",
"sent": 387642399,
"recv": 15324719784
},
{
"name": "lo",
"sent": 2667,
"recv": 2667
},
{
"name": "vboxnet0",
"sent": 0,
"recv": 0
}
],
"battery": [
{
"vendor": "ASUSTeK",
"model": "ASUS Battery",
"cycles": 445
}
]
}