From e77f97a487be7337f0cbf2060f8d71abbc946855 Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Thu, 7 Dec 2023 11:19:15 +0100 Subject: [PATCH] fix: skip serializing default fields (#401) * fix: skip serializing default fields * fix: small test issue --- src/recipe/parser.rs | 5 ++-- src/recipe/parser/about.rs | 15 ++++++++++++ src/recipe/parser/build.rs | 9 ++++++++ src/recipe/parser/package.rs | 1 + src/recipe/parser/script.rs | 9 ++++++++ src/recipe/parser/source.rs | 21 +++++++++++++++++ src/recipe/parser/test.rs | 18 +++++++++++++++ ...uild__recipe__parser__tests__it_works.snap | 1 - ...recipe__parser__tests__jinja_sequence.snap | 23 ------------------- ...recipe__parser__tests__recipe_windows.snap | 1 - ...d__metadata__test__read_full_recipe-2.snap | 17 -------------- ...ild__metadata__test__read_full_recipe.snap | 11 --------- test-data/rendered_recipes/curl_recipe.yaml | 19 --------------- test-data/rendered_recipes/rich_recipe.yaml | 12 ---------- 14 files changed, 76 insertions(+), 86 deletions(-) diff --git a/src/recipe/parser.rs b/src/recipe/parser.rs index d6dd9569..a674ebd1 100644 --- a/src/recipe/parser.rs +++ b/src/recipe/parser.rs @@ -44,12 +44,14 @@ use super::custom_yaml::Node; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Recipe { package: Package, + #[serde(default, skip_serializing_if = "Vec::is_empty")] source: Vec, build: Build, requirements: Requirements, + #[serde(default, skip_serializing_if = "Test::is_default")] test: Test, + #[serde(default, skip_serializing_if = "About::is_default")] about: About, - extra: (), } impl Recipe { @@ -175,7 +177,6 @@ impl Recipe { requirements, test, about, - extra: (), }; Ok(recipe) diff --git a/src/recipe/parser/about.rs b/src/recipe/parser/about.rs index 29f3a8a2..6746e09e 100644 --- a/src/recipe/parser/about.rs +++ b/src/recipe/parser/about.rs @@ -21,19 +21,34 @@ use crate::{ /// About information. #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct About { + #[serde(skip_serializing_if = "Option::is_none")] homepage: Option, + #[serde(skip_serializing_if = "Option::is_none")] repository: Option, + #[serde(skip_serializing_if = "Option::is_none")] documentation: Option, + #[serde(skip_serializing_if = "Option::is_none")] license: Option, + #[serde(skip_serializing_if = "Option::is_none")] license_family: Option, + #[serde(default, skip_serializing_if = "Vec::is_empty")] license_files: Vec, + #[serde(skip_serializing_if = "Option::is_none")] license_url: Option, + #[serde(skip_serializing_if = "Option::is_none")] summary: Option, + #[serde(skip_serializing_if = "Option::is_none")] description: Option, + #[serde(skip_serializing_if = "Option::is_none")] prelink_message: Option, } impl About { + /// Returns true if the about has its default configuration. + pub fn is_default(&self) -> bool { + self == &Self::default() + } + /// Get the homepage. pub const fn homepage(&self) -> Option<&Url> { self.homepage.as_ref() diff --git a/src/recipe/parser/build.rs b/src/recipe/parser/build.rs index ba834e56..be621c00 100644 --- a/src/recipe/parser/build.rs +++ b/src/recipe/parser/build.rs @@ -15,6 +15,11 @@ use crate::{ }, }; +/// A helper method to skip serializing the `skip` field if it's false. +fn should_not_serialize_skip(skip: &bool) -> bool { + !skip +} + /// The build options contain information about how to build the package and some additional /// metadata about the package. #[derive(Debug, Clone, Default, Serialize, Deserialize)] @@ -23,13 +28,17 @@ pub struct Build { pub(super) number: u64, /// The build string is usually set automatically as the hash of the variant configuration. /// It's possible to override this by setting it manually, but not recommended. + #[serde(default, skip_serializing_if = "Option::is_none")] pub(super) string: Option, /// List of conditions under which to skip the build of the package. + #[serde(default, skip_serializing_if = "should_not_serialize_skip")] pub(super) skip: bool, /// The build script can be either a list of commands or a path to a script. By /// default, the build script is set to `build.sh` or `build.bat` on Unix and Windows respectively. + #[serde(default, skip_serializing_if = "Script::is_default")] pub(super) script: Script, /// A noarch package runs on any platform. It can be either a python package or a generic package. + #[serde(default, skip_serializing_if = "NoArchType::is_none")] pub(super) noarch: NoArchType, /// Python specific build configuration #[serde(default, skip_serializing_if = "Python::is_default")] diff --git a/src/recipe/parser/package.rs b/src/recipe/parser/package.rs index 4aa9a633..b064b717 100644 --- a/src/recipe/parser/package.rs +++ b/src/recipe/parser/package.rs @@ -89,6 +89,7 @@ impl TryConvertNode for RenderedMappingNode { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct OutputPackage { name: PackageName, + #[serde(skip_serializing_if = "Option::is_none")] version: Option, } diff --git a/src/recipe/parser/script.rs b/src/recipe/parser/script.rs index 92b749eb..d49e41ae 100644 --- a/src/recipe/parser/script.rs +++ b/src/recipe/parser/script.rs @@ -162,6 +162,15 @@ impl Script { pub fn secrets(&self) -> &[String] { self.secrets.as_slice() } + + /// Returns true if the script references the default build script and has no additional + /// configuration. + pub fn is_default(&self) -> bool { + self.content.is_default() + && self.interpreter.is_none() + && self.env.is_empty() + && self.secrets.is_empty() + } } impl From for Script { diff --git a/src/recipe/parser/source.rs b/src/recipe/parser/source.rs index 2566f51f..921ea5c7 100644 --- a/src/recipe/parser/source.rs +++ b/src/recipe/parser/source.rs @@ -102,15 +102,24 @@ pub struct GitSource { #[serde(default)] rev: String, /// Optionally a depth to clone the repository, defaults to `None` + #[serde(skip_serializing_if = "Option::is_none")] depth: Option, /// Optionally patches to apply to the source code + #[serde(default, skip_serializing_if = "Vec::is_empty")] patches: Vec, /// Optionally a folder name under the `work` directory to place the source code + #[serde(skip_serializing_if = "Option::is_none")] folder: Option, /// Optionally request the lfs pull in git source + #[serde(skip_serializing_if = "should_not_serialize_lfs")] lfs: bool, } +/// A helper method to skip serializing the lfs flag if it is false. +fn should_not_serialize_lfs(lfs: &bool) -> bool { + !lfs +} + impl GitSource { #[cfg(test)] pub fn create( @@ -283,10 +292,13 @@ pub struct UrlSource { md5: Option, /// Optionally a file name to rename the downloaded file (does not apply to archives) + #[serde(skip_serializing_if = "Option::is_none")] file_name: Option, /// Patches to apply to the source code + #[serde(default, skip_serializing_if = "Vec::is_empty")] patches: Vec, /// Optionally a folder name under the `work` directory to place the source code + #[serde(skip_serializing_if = "Option::is_none")] folder: Option, } @@ -401,15 +413,24 @@ pub struct PathSource { /// Path to the local source code path: PathBuf, /// Patches to apply to the source code + #[serde(default, skip_serializing_if = "Vec::is_empty")] patches: Vec, /// Optionally a folder name under the `work` directory to place the source code + #[serde(skip_serializing_if = "Option::is_none")] folder: Option, /// Optionally a file name to rename the file to + #[serde(skip_serializing_if = "Option::is_none")] file_name: Option, /// Whether to use the `.gitignore` file in the source directory. Defaults to `true`. + #[serde(skip_serializing_if = "should_not_serialize_use_gitignore")] use_gitignore: bool, } +/// Helper method to skip serializing the use_gitignore flag if it is true. +fn should_not_serialize_use_gitignore(use_gitignore: &bool) -> bool { + *use_gitignore +} + impl PathSource { /// Get the path. pub const fn path(&self) -> &PathBuf { diff --git a/src/recipe/parser/test.rs b/src/recipe/parser/test.rs index 38807670..02a8735c 100644 --- a/src/recipe/parser/test.rs +++ b/src/recipe/parser/test.rs @@ -12,32 +12,50 @@ use crate::{ #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] pub struct Test { /// Try importing a python module as a sanity check + #[serde(default, skip_serializing_if = "Vec::is_empty")] imports: Vec, /// Run a list of given commands + #[serde(default, skip_serializing_if = "Vec::is_empty")] commands: Vec, /// Extra requirements to be installed at test time + #[serde(default, skip_serializing_if = "Vec::is_empty")] requires: Vec, /// Extra files to be copied to the test environment from the source dir (can be globs) + #[serde(default, skip_serializing_if = "Vec::is_empty")] source_files: Vec, /// Extra files to be copied to the test environment from the build dir (can be globs) + #[serde(default, skip_serializing_if = "Vec::is_empty")] files: Vec, /// All new test section + #[serde(skip_serializing_if = "Option::is_none")] package_contents: Option, } +impl Test { + /// Returns true if the test has its default configuration. + pub fn is_default(&self) -> bool { + self == &Self::default() + } +} + #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] /// PackageContent pub struct PackageContent { /// file paths, direct and/or globs + #[serde(default, skip_serializing_if = "Vec::is_empty")] files: Vec, /// checks existence of package init in env python site packages dir /// eg: mamba.api -> ${SITE_PACKAGES}/mamba/api/__init__.py + #[serde(default, skip_serializing_if = "Vec::is_empty")] site_packages: Vec, /// search for binary in prefix path: eg, %PREFIX%/bin/mamba + #[serde(default, skip_serializing_if = "Vec::is_empty")] bins: Vec, /// check for dynamic or static library file path + #[serde(default, skip_serializing_if = "Vec::is_empty")] libs: Vec, /// check if include path contains the file, direct or glob? + #[serde(default, skip_serializing_if = "Vec::is_empty")] includes: Vec, } diff --git a/src/recipe/snapshots/rattler_build__recipe__parser__tests__it_works.snap b/src/recipe/snapshots/rattler_build__recipe__parser__tests__it_works.snap index 76a59dc3..4095685a 100644 --- a/src/recipe/snapshots/rattler_build__recipe__parser__tests__it_works.snap +++ b/src/recipe/snapshots/rattler_build__recipe__parser__tests__it_works.snap @@ -357,5 +357,4 @@ Recipe { ), prelink_message: None, }, - extra: (), } diff --git a/src/recipe/snapshots/rattler_build__recipe__parser__tests__jinja_sequence.snap b/src/recipe/snapshots/rattler_build__recipe__parser__tests__jinja_sequence.snap index 2989afcf..d6844ba6 100644 --- a/src/recipe/snapshots/rattler_build__recipe__parser__tests__jinja_sequence.snap +++ b/src/recipe/snapshots/rattler_build__recipe__parser__tests__jinja_sequence.snap @@ -5,32 +5,9 @@ expression: recipe package: name: blib version: 0.1.0 -source: [] build: number: 0 - string: ~ - skip: false script: - test succeeded - noarch: false requirements: {} -test: - imports: [] - commands: [] - requires: [] - source_files: [] - files: [] - package_contents: ~ -about: - homepage: ~ - repository: ~ - documentation: ~ - license: ~ - license_family: ~ - license_files: [] - license_url: ~ - summary: ~ - description: ~ - prelink_message: ~ -extra: ~ diff --git a/src/recipe/snapshots/rattler_build__recipe__parser__tests__recipe_windows.snap b/src/recipe/snapshots/rattler_build__recipe__parser__tests__recipe_windows.snap index d347805a..5db3ab5b 100644 --- a/src/recipe/snapshots/rattler_build__recipe__parser__tests__recipe_windows.snap +++ b/src/recipe/snapshots/rattler_build__recipe__parser__tests__recipe_windows.snap @@ -337,5 +337,4 @@ Recipe { ), prelink_message: None, }, - extra: (), } diff --git a/src/snapshots/rattler_build__metadata__test__read_full_recipe-2.snap b/src/snapshots/rattler_build__metadata__test__read_full_recipe-2.snap index 7706f0b7..4e8a44bf 100644 --- a/src/snapshots/rattler_build__metadata__test__read_full_recipe-2.snap +++ b/src/snapshots/rattler_build__metadata__test__read_full_recipe-2.snap @@ -9,15 +9,9 @@ recipe: source: - url: "http://curl.haxx.se/download/curl-8.0.1.tar.bz2" sha256: 9b6b1e96b748d04b968786b6bdf407aa5c75ab53a3d37c1c8c81cdb736555ccf - file_name: ~ - patches: [] - folder: ~ build: number: 0 string: h60d57d3_0 - skip: false - script: [] - noarch: false requirements: build: - __COMPILER c @@ -25,26 +19,15 @@ recipe: - perl - pkg-config - libtool - test: - imports: [] - commands: [] - requires: [] - source_files: [] - files: [] - package_contents: ~ about: homepage: "http://curl.haxx.se/" repository: "https://github.com/curl/curl" documentation: "https://curl.haxx.se/docs/" license: curl - license_family: ~ license_files: - COPYING - license_url: ~ summary: tool and library for transferring data with URL syntax description: "Curl is an open source command line tool and library for transferring data\nwith URL syntax. It is used in command lines or scripts to transfer data." - prelink_message: ~ - extra: ~ build_configuration: target_platform: osx-arm64 host_platform: osx-arm64 diff --git a/src/snapshots/rattler_build__metadata__test__read_full_recipe.snap b/src/snapshots/rattler_build__metadata__test__read_full_recipe.snap index 40a3b2da..8d9a098d 100644 --- a/src/snapshots/rattler_build__metadata__test__read_full_recipe.snap +++ b/src/snapshots/rattler_build__metadata__test__read_full_recipe.snap @@ -9,13 +9,9 @@ recipe: source: - url: "https://pypi.io/packages/source/r/rich/rich-13.4.2.tar.gz" sha256: d653d6bccede5844304c605d5aac802c7cf9621efd700b46c7ec2b51ea914898 - file_name: ~ - patches: [] - folder: ~ build: number: 0 string: pyh4616a5c_0 - skip: false script: - python -m pip install . -vv --no-deps --no-build-isolation noarch: python @@ -36,22 +32,15 @@ recipe: - pip check requires: - pip - source_files: [] - files: [] - package_contents: ~ about: homepage: "https://github.com/Textualize/rich" repository: "https://github.com/Textualize/rich" documentation: "https://rich.readthedocs.io/" license: MIT - license_family: ~ license_files: - LICENSE - license_url: ~ summary: "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" description: "Rich is a Python library for rich text and beautiful formatting in the terminal.\n\nThe Rich API makes it easy to add color and style to terminal output. Rich\ncan also render pretty tables, progress bars, markdown, syntax highlighted\nsource code, tracebacks, and more — out of the box." - prelink_message: ~ - extra: ~ build_configuration: target_platform: noarch host_platform: osx-arm64 diff --git a/test-data/rendered_recipes/curl_recipe.yaml b/test-data/rendered_recipes/curl_recipe.yaml index ca074a9e..0592b0de 100644 --- a/test-data/rendered_recipes/curl_recipe.yaml +++ b/test-data/rendered_recipes/curl_recipe.yaml @@ -5,15 +5,9 @@ recipe: source: - url: http://curl.haxx.se/download/curl-8.0.1.tar.bz2 sha256: 9b6b1e96b748d04b968786b6bdf407aa5c75ab53a3d37c1c8c81cdb736555ccf - file_name: null - patches: [] - folder: null build: number: 0 string: h60d57d3_0 - skip: false - script: [] - noarch: false requirements: build: - __COMPILER c @@ -21,30 +15,17 @@ recipe: - perl - pkg-config - libtool - host: [] - run: [] - run_constrained: [] - test: - imports: [] - commands: [] - requires: [] - source_files: [] - files: [] about: homepage: http://curl.haxx.se/ repository: https://github.com/curl/curl documentation: https://curl.haxx.se/docs/ license: curl - license_family: null license_files: - COPYING - license_url: null summary: tool and library for transferring data with URL syntax description: |- Curl is an open source command line tool and library for transferring data with URL syntax. It is used in command lines or scripts to transfer data. - prelink_message: null - extra: null build_configuration: target_platform: osx-arm64 host_platform: osx-arm64 diff --git a/test-data/rendered_recipes/rich_recipe.yaml b/test-data/rendered_recipes/rich_recipe.yaml index 5ad6c679..57cec86c 100644 --- a/test-data/rendered_recipes/rich_recipe.yaml +++ b/test-data/rendered_recipes/rich_recipe.yaml @@ -5,18 +5,13 @@ recipe: source: - url: https://pypi.io/packages/source/r/rich/rich-13.4.2.tar.gz sha256: d653d6bccede5844304c605d5aac802c7cf9621efd700b46c7ec2b51ea914898 - file_name: null - patches: [] - folder: null build: number: 0 string: pyh4616a5c_0 - skip: false script: - python -m pip install . -vv --no-deps --no-build-isolation noarch: python requirements: - build: [] host: - pip - poetry-core >=1.0.0 @@ -26,7 +21,6 @@ recipe: - pygments >=2.13.0,<3.0.0 - python ==3.10 - typing_extensions >=4.0.0,<5.0.0 - run_constrained: [] test: imports: - rich @@ -34,17 +28,13 @@ recipe: - pip check requires: - pip - source_files: [] - files: [] about: homepage: https://github.com/Textualize/rich repository: https://github.com/Textualize/rich documentation: https://rich.readthedocs.io/ license: MIT - license_family: null license_files: - LICENSE - license_url: null summary: Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal description: |- Rich is a Python library for rich text and beautiful formatting in the terminal. @@ -52,8 +42,6 @@ recipe: The Rich API makes it easy to add color and style to terminal output. Rich can also render pretty tables, progress bars, markdown, syntax highlighted source code, tracebacks, and more — out of the box. - prelink_message: null - extra: null build_configuration: target_platform: noarch host_platform: osx-arm64