forked from extern/nushell
21b84a6d65
This is a follow up from https://github.com/nushell/nushell/pull/7540. Please provide feedback if you have the time! ## Summary This PR lets you use `?` to indicate that a member in a cell path is optional and Nushell should return `null` if that member cannot be accessed. Unlike the previous PR, `?` is now a _postfix_ modifier for cell path members. A cell path of `.foo?.bar` means that `foo` is optional and `bar` is not. `?` does _not_ suppress all errors; it is intended to help in situations where data has "holes", i.e. the data types are correct but something is missing. Type mismatches (like trying to do a string path access on a date) will still fail. ### Record Examples ```bash { foo: 123 }.foo # returns 123 { foo: 123 }.bar # errors { foo: 123 }.bar? # returns null { foo: 123 } | get bar # errors { foo: 123 } | get bar? # returns null { foo: 123 }.bar.baz # errors { foo: 123 }.bar?.baz # errors because `baz` is not present on the result from `bar?` { foo: 123 }.bar.baz? # errors { foo: 123 }.bar?.baz? # returns null ``` ### List Examples ``` 〉[{foo: 1} {foo: 2} {}].foo Error: nu:🐚:column_not_found × Cannot find column ╭─[entry #30:1:1] 1 │ [{foo: 1} {foo: 2} {}].foo · ─┬ ─┬─ · │ ╰── cannot find column 'foo' · ╰── value originates here ╰──── 〉[{foo: 1} {foo: 2} {}].foo? ╭───┬───╮ │ 0 │ 1 │ │ 1 │ 2 │ │ 2 │ │ ╰───┴───╯ 〉[{foo: 1} {foo: 2} {}].foo?.2 | describe nothing 〉[a b c].4? | describe nothing 〉[{foo: 1} {foo: 2} {}] | where foo? == 1 ╭───┬─────╮ │ # │ foo │ ├───┼─────┤ │ 0 │ 1 │ ╰───┴─────╯ ``` # Breaking changes 1. Column names with `?` in them now need to be quoted. 2. The `-i`/`--ignore-errors` flag has been removed from `get` and `select` 1. After this PR, most `get` error handling can be done with `?` and/or `try`/`catch`. 4. Cell path accesses like this no longer work without a `?`: ```bash 〉[{a:1 b:2} {a:3}].b.0 2 ``` We had some clever code that was able to recognize that since we only want row `0`, it's OK if other rows are missing column `b`. I removed that because it's tricky to maintain, and now that query needs to be written like: ```bash 〉[{a:1 b:2} {a:3}].b?.0 2 ``` I think the regression is acceptable for now. I plan to do more work in the future to enable streaming of cell path accesses, and when that happens I'll be able to make `.b.0` work again.
80 lines
2.9 KiB
Rust
80 lines
2.9 KiB
Rust
use nu_test_support::{nu, pipeline};
|
|
|
|
#[test]
|
|
fn cal_full_year() {
|
|
let actual = nu!(
|
|
cwd: ".", pipeline(
|
|
r#"
|
|
cal -y --full-year 2010 | first | to json -r
|
|
"#
|
|
));
|
|
|
|
let first_week_2010_json = r#"{"year": 2010,"sunday": null,"monday": null,"tuesday": null,"wednesday": null,"thursday": null,"friday": 1,"saturday": 2}"#;
|
|
|
|
assert_eq!(actual.out, first_week_2010_json);
|
|
}
|
|
|
|
#[test]
|
|
fn cal_february_2020_leap_year() {
|
|
let actual = nu!(
|
|
cwd: ".", pipeline(
|
|
r#"
|
|
cal -ym --full-year 2020 --month-names | where month == "february" | to json -r
|
|
"#
|
|
));
|
|
|
|
let cal_february_json = r#"[{"year": 2020,"month": "february","sunday": null,"monday": null,"tuesday": null,"wednesday": null,"thursday": null,"friday": null,"saturday": 1},{"year": 2020,"month": "february","sunday": 2,"monday": 3,"tuesday": 4,"wednesday": 5,"thursday": 6,"friday": 7,"saturday": 8},{"year": 2020,"month": "february","sunday": 9,"monday": 10,"tuesday": 11,"wednesday": 12,"thursday": 13,"friday": 14,"saturday": 15},{"year": 2020,"month": "february","sunday": 16,"monday": 17,"tuesday": 18,"wednesday": 19,"thursday": 20,"friday": 21,"saturday": 22},{"year": 2020,"month": "february","sunday": 23,"monday": 24,"tuesday": 25,"wednesday": 26,"thursday": 27,"friday": 28,"saturday": 29}]"#;
|
|
|
|
assert_eq!(actual.out, cal_february_json);
|
|
}
|
|
|
|
#[test]
|
|
fn cal_friday_the_thirteenths_in_2015() {
|
|
let actual = nu!(
|
|
cwd: ".", pipeline(
|
|
r#"
|
|
cal --full-year 2015 | default friday 0 | where friday == 13 | length
|
|
"#
|
|
));
|
|
|
|
assert!(actual.out.contains('3'));
|
|
}
|
|
|
|
#[test]
|
|
fn cal_rows_in_2020() {
|
|
let actual = nu!(
|
|
cwd: ".", pipeline(
|
|
r#"
|
|
cal --full-year 2020 | length
|
|
"#
|
|
));
|
|
|
|
assert!(actual.out.contains("62"));
|
|
}
|
|
|
|
#[test]
|
|
fn cal_week_day_start_monday() {
|
|
let actual = nu!(
|
|
cwd: ".", pipeline(
|
|
r#"
|
|
cal --full-year 2020 -m --month-names --week-start monday | where month == january | to json -r
|
|
"#
|
|
));
|
|
|
|
let cal_january_json = r#"[{"month": "january","monday": null,"tuesday": null,"wednesday": 1,"thursday": 2,"friday": 3,"saturday": 4,"sunday": 5},{"month": "january","monday": 6,"tuesday": 7,"wednesday": 8,"thursday": 9,"friday": 10,"saturday": 11,"sunday": 12},{"month": "january","monday": 13,"tuesday": 14,"wednesday": 15,"thursday": 16,"friday": 17,"saturday": 18,"sunday": 19},{"month": "january","monday": 20,"tuesday": 21,"wednesday": 22,"thursday": 23,"friday": 24,"saturday": 25,"sunday": 26},{"month": "january","monday": 27,"tuesday": 28,"wednesday": 29,"thursday": 30,"friday": 31,"saturday": null,"sunday": null}]"#;
|
|
|
|
assert_eq!(actual.out, cal_january_json);
|
|
}
|
|
|
|
#[test]
|
|
fn cal_sees_pipeline_year() {
|
|
let actual = nu!(
|
|
cwd: ".", pipeline(
|
|
r#"
|
|
cal --full-year 1020 | get monday | first 4 | to json -r
|
|
"#
|
|
));
|
|
|
|
assert_eq!(actual.out, "[null,3,10,17]");
|
|
}
|