From ddc00014be30a3e1872c59b3fa569bf247d28021 Mon Sep 17 00:00:00 2001 From: Artemiy Date: Sun, 25 Dec 2022 00:12:09 +0300 Subject: [PATCH] To toml fix (#7597) # Description Fixes #7510 . Remove support for tables from `to toml` command and update description. Previously, as indicated in #7510 , a table could be converted to toml and would result in this invalid toml: ![image](https://user-images.githubusercontent.com/17511668/209443930-c3dd3a3f-5ffd-4273-9c10-acbb345c788e.png) This commit removes functionality of serializing tables and now `to toml` produces an error: ![image](https://user-images.githubusercontent.com/17511668/209443975-be119465-8946-4644-8994-489ca94f6006.png) The `from toml` command already acknowledges the fact that toml can contain only records as indicated in its signature ![image](https://user-images.githubusercontent.com/17511668/209443995-1590d044-a790-4be3-a967-b26292a6e70c.png) Now help of `to toml` reflects this feature of format as well: ![image](https://user-images.githubusercontent.com/17511668/209444014-7cfe8f8e-ad8a-4845-a151-24df6b99a1a2.png) Additionally new tests were created for `to toml` command. See `crates\nu-command\tests\format_conversions\toml.rs`. Also removed undocumented behavior that would accept and validate a string as toml: ![image](https://user-images.githubusercontent.com/17511668/209449482-5d876074-fc5b-4b21-b8a5-64e643a50083.png) # User-Facing Changes - Serializing tables to toml now produces error instead of invalid toml - Updated `to toml` help - Remove undocumented "validation" (not really user-facing) # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - [x] `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - [x] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - [x] `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --- crates/nu-command/src/formats/to/toml.rs | 54 ++---------- .../tests/format_conversions/toml.rs | 88 ++++++++++++++++++- 2 files changed, 92 insertions(+), 50 deletions(-) diff --git a/crates/nu-command/src/formats/to/toml.rs b/crates/nu-command/src/formats/to/toml.rs index 2e643c5a5..aa3abee6e 100644 --- a/crates/nu-command/src/formats/to/toml.rs +++ b/crates/nu-command/src/formats/to/toml.rs @@ -14,19 +14,19 @@ impl Command for ToToml { fn signature(&self) -> Signature { Signature::build("to toml") - .input_output_types(vec![(Type::Any, Type::String)]) + .input_output_types(vec![(Type::Record(vec![]), Type::String)]) .category(Category::Formats) } fn usage(&self) -> &str { - "Convert table into .toml text" + "Convert record into .toml text" } fn examples(&self) -> Vec { vec![Example { - description: "Outputs an TOML string representing the contents of this table", - example: r#"[[foo bar]; ["1" "2"]] | to toml"#, - result: Some(Value::test_string("bar = \"2\"\nfoo = \"1\"\n")), + description: "Outputs an TOML string representing the contents of this record", + example: r#"{foo: 1 bar: 'qwe'} | to toml"#, + result: Some(Value::test_string("bar = \"qwe\"\nfoo = 1\n")), }] } @@ -127,26 +127,6 @@ fn value_to_toml_value( ) -> Result { match v { Value::Record { .. } => helper(engine_state, v), - Value::List { ref vals, span } => match &vals[..] { - [Value::Record { .. }, _end @ ..] => helper(engine_state, v), - _ => Err(ShellError::UnsupportedInput( - "Expected a table with TOML-compatible structure".to_string(), - "value originates from here".into(), - head, - *span, - )), - }, - Value::String { val, span } => { - // Attempt to de-serialize the String - toml::de::from_str(val).map_err(|_| { - ShellError::UnsupportedInput( - "unable to de-serialize string to TOML".into(), - format!("input: '{:?}'", val), - head, - *span, - ) - }) - } // Propagate existing errors Value::Error { error } => Err(error.clone()), _ => Err(ShellError::UnsupportedInput( @@ -225,30 +205,6 @@ mod tests { toml::Value::String("array".to_owned()) ])) ); - // TOML string - let tv = value_to_toml_value( - &engine_state, - &Value::test_string( - r#" - title = "TOML Example" - - [owner] - name = "Tom Preston-Werner" - dob = 1979-05-27T07:32:00-08:00 # First class dates - - [dependencies] - rustyline = "4.1.0" - sysinfo = "0.8.4" - chrono = { version = "0.4.23", features = ["serde"] } - "#, - ), - Span::test_data(), - ) - .expect("Expected Ok from valid TOML string"); - assert_eq!( - tv.get("title").unwrap(), - &toml::Value::String("TOML Example".to_owned()) - ); // // Negative Tests // diff --git a/crates/nu-command/tests/format_conversions/toml.rs b/crates/nu-command/tests/format_conversions/toml.rs index cffeed1c2..a23a78b51 100644 --- a/crates/nu-command/tests/format_conversions/toml.rs +++ b/crates/nu-command/tests/format_conversions/toml.rs @@ -1,7 +1,93 @@ use nu_test_support::{nu, pipeline}; #[test] -fn table_to_toml_text_and_from_toml_text_back_into_table() { +fn record_map_to_toml() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + {a: 1 b: 2 c: 'qwe'} + | to toml + | from toml + | $in == {a: 1 b: 2 c: 'qwe'} + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn nested_records_to_toml() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + {a: {a: a b: b} c: 1} + | to toml + | from toml + | $in == {a: {a: a b: b} c: 1} + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn records_with_tables_to_toml() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + {a: [[a b]; [1 2] [3 4]] b: [[c d e]; [1 2 3]]} + | to toml + | from toml + | $in == {a: [[a b]; [1 2] [3 4]] b: [[c d e]; [1 2 3]]} + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn nested_tables_to_toml() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + {c: [[f g]; [[[h k]; [1 2] [3 4]] 1]]} + | to toml + | from toml + | $in == {c: [[f g]; [[[h k]; [1 2] [3 4]] 1]]} + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn table_to_toml_fails() { + // Tables cant be represented in toml + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + try { [[a b]; [1 2] [5 6]] | to toml | false } catch { true } + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn string_to_toml_fails() { + // Strings are not a top-level toml structure + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + try { 'not a valid toml' | to toml | false } catch { true } + "# + )); + + assert_eq!(actual.out, "true"); +} + +#[test] +fn big_record_to_toml_text_and_from_toml_text_back_into_record() { let actual = nu!( cwd: "tests/fixtures/formats", pipeline( r#"