From ef770992796f7d992cdc8aa171da1ee582d7f600 Mon Sep 17 00:00:00 2001 From: prsabahrami Date: Wed, 22 Jan 2025 00:26:12 -0500 Subject: [PATCH] replace `optional_features` with `extras` --- .github/workflows/rust-compile.yml | 89 +------------------ crates/rattler_conda_types/Cargo.toml | 2 +- .../rattler_conda_types/src/match_spec/mod.rs | 12 +-- .../src/match_spec/parse.rs | 16 ++-- crates/rattler_solve/Cargo.toml | 2 +- crates/rattler_solve/src/resolvo/mod.rs | 6 +- crates/rattler_solve/tests/backends.rs | 48 +++++----- .../noarch/repodata.json | 6 +- 8 files changed, 48 insertions(+), 133 deletions(-) diff --git a/.github/workflows/rust-compile.yml b/.github/workflows/rust-compile.yml index 01a00afb7..5b43f11f5 100644 --- a/.github/workflows/rust-compile.yml +++ b/.github/workflows/rust-compile.yml @@ -146,7 +146,7 @@ jobs: run: > cargo nextest run --workspace - --features ${{ env.DEFAULT_FEATURES }} + --features ${{ env.DEFAULT_FEATURES }} extras --target ${{ matrix.target }} ${{ steps.build-options.outputs.CARGO_BUILD_OPTIONS}} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}} @@ -154,89 +154,4 @@ jobs: - name: Run doctests if: ${{ !matrix.skip-tests }} run: > - cargo test --doc - - test-experimental: - name: Test Experimental Features (${{ matrix.name }}) - runs-on: ${{ matrix.os }} - needs: [ format_and_lint ] - strategy: - fail-fast: false - matrix: - include: - - { name: "Linux-x86_64", target: x86_64-unknown-linux-musl, os: ubuntu-22.04 } - - { name: "Linux-aarch64", target: aarch64-unknown-linux-musl, os: ubuntu-latest, skip-tests: true } - - { name: "Linux-arm", target: arm-unknown-linux-musleabi, os: ubuntu-latest, use-cross: true, skip-tests: true } - - # - { name: "Linux-mips", target: mips-unknown-linux-musl, os: ubuntu-latest, use-cross: true, skip-tests: true } - # - { name: "Linux-mipsel", target: mipsel-unknown-linux-musl, os: ubuntu-latest, use-cross: true, skip-tests: true } - # - { name: "Linux-mips64", target: mips64-unknown-linux-muslabi64, os: ubuntu-latest, use-cross: true, skip-tests: true } - # - { name: "Linux-mips64el", target: mips64el-unknown-linux-muslabi64, os: ubuntu-latest, use-cross: true, skip-tests: true } - -# - { name: "Linux-powerpc", target: powerpc-unknown-linux-gnu, os: ubuntu-latest, use-cross: true, skip-tests: true } - - { name: "Linux-powerpc64", target: powerpc64-unknown-linux-gnu, os: ubuntu-latest, use-cross: true, skip-tests: true } - - { name: "Linux-powerpc64le", target: powerpc64le-unknown-linux-gnu, os: ubuntu-latest, use-cross: true, skip-tests: true } - - - { name: "Linux-s390x", target: s390x-unknown-linux-gnu, os: ubuntu-latest, use-cross: true, skip-tests: true } - - - { name: "macOS-x86_64", target: x86_64-apple-darwin, os: macOS-latest } - - { name: "macOS-aarch64", target: aarch64-apple-darwin, os: macOS-latest, skip-tests: true } - - - { name: "Windows-x86_64", target: x86_64-pc-windows-msvc, os: windows-latest } - - { name: "Windows-aarch64", target: aarch64-pc-windows-msvc, os: windows-latest, skip-tests: true } - feature-set: - - "optional_features" - - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Install Rust toolchain - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - target: ${{ matrix.target }} - components: rustfmt - cache: false - - - uses: taiki-e/setup-cross-toolchain-action@v1 - if: matrix.target != 'x86_64-unknown-linux-musl' - with: - target: ${{ matrix.target }} - - - if: matrix.target == 'x86_64-unknown-linux-musl' - run: | - sudo apt install musl-tools gcc g++ - sudo ln -s /usr/bin/musl-gcc /usr/bin/musl-g++ - - - uses: Swatinem/rust-cache@v2 - - - name: Install cargo nextest - if: ${{ !matrix.skip-tests }} - uses: taiki-e/install-action@v2 - with: - tool: cargo-nextest - - - name: Use rustls on musl targets. - id: build-options - if: contains(matrix.target, '-musl') || startsWith(matrix.target, 'powerpc') || startsWith(matrix.target, 's390x') - run: | - echo "CARGO_BUILD_OPTIONS=${CARGO_BUILD_OPTIONS} --no-default-features --features rustls-tls" >> $GITHUB_OUTPUT - - - name: Run feature-specific tests - if: ${{ !matrix.skip-tests }} - run: > - cargo nextest run - --workspace - --features ${{ matrix.feature-set }} - --target ${{ matrix.target }} - ${{ steps.build-options.outputs.CARGO_BUILD_OPTIONS}} - "optional_" - - - name: Run feature-specific doctests - if: ${{ !matrix.skip-tests }} - run: > - cargo test --doc - --features ${{ matrix.feature-set }} - --target ${{ matrix.target }} - ${{ steps.build-options.outputs.CARGO_BUILD_OPTIONS}} + cargo test --doc \ No newline at end of file diff --git a/crates/rattler_conda_types/Cargo.toml b/crates/rattler_conda_types/Cargo.toml index 0d8da2ff0..2a9b3559f 100644 --- a/crates/rattler_conda_types/Cargo.toml +++ b/crates/rattler_conda_types/Cargo.toml @@ -12,7 +12,7 @@ readme.workspace = true [features] default = ["rayon"] -optional_features = [] +extras = [] [dependencies] chrono = { workspace = true } diff --git a/crates/rattler_conda_types/src/match_spec/mod.rs b/crates/rattler_conda_types/src/match_spec/mod.rs index c21c7df3c..1e2f3b6ac 100644 --- a/crates/rattler_conda_types/src/match_spec/mod.rs +++ b/crates/rattler_conda_types/src/match_spec/mod.rs @@ -137,7 +137,7 @@ pub struct MatchSpec { /// Match the specific filename of the package pub file_name: Option, /// The selected optional features of the package - pub optional_features: Option>, + pub extras: Option>, /// The channel of the package pub channel: Option>, /// The subdir of the channel @@ -176,7 +176,7 @@ impl Display for MatchSpec { None => write!(f, "*")?, } - match &self.optional_features { + match &self.extras { Some(dependencies) => { write!(f, "[")?; write!(f, "{}", dependencies.iter().format(", "))?; @@ -233,7 +233,7 @@ impl MatchSpec { build: self.build, build_number: self.build_number, file_name: self.file_name, - optional_features: self.optional_features, + extras: self.extras, channel: self.channel, subdir: self.subdir, namespace: self.namespace, @@ -279,7 +279,7 @@ pub struct NamelessMatchSpec { /// Match the specific filename of the package pub file_name: Option, /// The selected optional features of the package - pub optional_features: Option>, + pub extras: Option>, /// The channel of the package #[serde(deserialize_with = "deserialize_channel", default)] pub channel: Option>, @@ -333,7 +333,7 @@ impl From for NamelessMatchSpec { build: spec.build, build_number: spec.build_number, file_name: spec.file_name, - optional_features: spec.optional_features, + extras: spec.extras, channel: spec.channel, subdir: spec.subdir, namespace: spec.namespace, @@ -353,7 +353,7 @@ impl MatchSpec { build: spec.build, build_number: spec.build_number, file_name: spec.file_name, - optional_features: spec.optional_features, + extras: spec.extras, channel: spec.channel, subdir: spec.subdir, namespace: spec.namespace, diff --git a/crates/rattler_conda_types/src/match_spec/parse.rs b/crates/rattler_conda_types/src/match_spec/parse.rs index fd4cd09b3..57c519449 100644 --- a/crates/rattler_conda_types/src/match_spec/parse.rs +++ b/crates/rattler_conda_types/src/match_spec/parse.rs @@ -227,9 +227,9 @@ fn strip_brackets(input: &str) -> Result<(Cow<'_, str>, BracketVec<'_>), ParseMa } } -#[cfg(feature = "optional_features")] +#[cfg(feature = "extras")] /// Parses a list of optional dependencies from a string `[feat1, feat2, feat3]`. -pub fn parse_optional_features(input: &str) -> Result, ParseMatchSpecError> { +pub fn parse_extras(input: &str) -> Result, ParseMatchSpecError> { use nom::combinator::map; fn parse_features(input: &str) -> IResult<&str, Vec> { @@ -272,16 +272,16 @@ fn parse_bracket_vec_into_components( "version" => match_spec.version = Some(VersionSpec::from_str(value, strictness)?), "build" => match_spec.build = Some(StringMatcher::from_str(value)?), "build_number" => match_spec.build_number = Some(BuildNumberSpec::from_str(value)?), - "optional_features" => { + "extras" => { // Optional features are still experimental - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] { - match_spec.optional_features = Some(parse_optional_features(value)?); + match_spec.extras = Some(parse_extras(value)?); } - #[cfg(not(feature = "optional_features"))] + #[cfg(not(feature = "extras"))] { return Err(ParseMatchSpecError::InvalidBracketKey( - "optional_features".to_string(), + "extras".to_string(), )); } } @@ -1379,7 +1379,7 @@ mod tests { build: "py27_0*".parse().ok(), build_number: Some(BuildNumberSpec::from_str(">=6").unwrap()), file_name: Some("foo-1.0-py27_0.tar.bz2".to_string()), - optional_features: None, + extras: None, channel: Some( Channel::from_str("conda-forge", &channel_config()) .map(Arc::new) diff --git a/crates/rattler_solve/Cargo.toml b/crates/rattler_solve/Cargo.toml index 85be7e10e..14c9d3324 100644 --- a/crates/rattler_solve/Cargo.toml +++ b/crates/rattler_solve/Cargo.toml @@ -44,7 +44,7 @@ url = { workspace = true } default = ["resolvo"] libsolv_c = ["rattler_libsolv_c", "libc"] resolvo = ["dep:resolvo", "dep:futures"] -optional_features = [] +extras = [] [[bench]] name = "bench" diff --git a/crates/rattler_solve/src/resolvo/mod.rs b/crates/rattler_solve/src/resolvo/mod.rs index 38ab82616..b8076c24a 100644 --- a/crates/rattler_solve/src/resolvo/mod.rs +++ b/crates/rattler_solve/src/resolvo/mod.rs @@ -679,7 +679,7 @@ impl<'a> DependencyProvider for CondaDependencyProvider<'a> { subdir: Some(record.package_record.subdir.clone()), md5: record.package_record.md5, sha256: record.package_record.sha256, - optional_features: None, + extras: None, ..Default::default() }; @@ -841,7 +841,7 @@ impl super::SolverImpl for Solver { let root_requirements = task.specs.iter().flat_map(|spec| { let (name, nameless_spec) = spec.clone().into_nameless(); - let features = &spec.optional_features; + let features = &spec.extras; let name = name.expect("cannot use matchspec without a name"); let name_id = provider.pool.intern_package_name(name.as_normalized()); let mut reqs = vec![provider @@ -940,7 +940,7 @@ fn parse_match_spec( let (name, spec) = match_spec.into_nameless(); let mut version_set_ids = vec![]; - if let Some(ref features) = spec.optional_features { + if let Some(ref features) = spec.extras { let spec_with_feature: SolverMatchSpec<'_> = spec.clone().into(); for feature in features { diff --git a/crates/rattler_solve/tests/backends.rs b/crates/rattler_solve/tests/backends.rs index 432a6d615..6677af948 100644 --- a/crates/rattler_solve/tests/backends.rs +++ b/crates/rattler_solve/tests/backends.rs @@ -46,7 +46,7 @@ fn dummy_channel_json_path() -> String { ) } -#[cfg(feature = "optional_features")] +#[cfg(feature = "extras")] fn dummy_channel_with_optional_dependencies_json_path() -> String { format!( "{}/{}", @@ -724,7 +724,7 @@ mod resolvo { GenericVirtualPackage, SimpleSolveTask, SolveError, Version, }; - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] use super::dummy_channel_with_optional_dependencies_json_path; solver_backend_tests!(rattler_solve::resolvo::Solver); @@ -971,7 +971,7 @@ mod resolvo { insta::assert_snapshot!(result.unwrap_err()); } - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] /// Installs `foo` while enabling a single optional dependency `[with-latest-bors]`. /// This should pull in `bors >=2.0`. #[test] @@ -979,7 +979,7 @@ mod resolvo { let mut result = solve::( &[dummy_channel_with_optional_dependencies_json_path()], SimpleSolveTask { - specs: &["foo[optional_features=[with-latest-bors]]"], + specs: &["foo[extras=[with-latest-bors]]"], ..SimpleSolveTask::default() }, ) @@ -1012,14 +1012,14 @@ mod resolvo { ); } - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] /// Installs `cuda-version` with `[with-cudadev]` which depends on `"foo >=4.0.2", "bar >=1.2.3"`. #[test] fn test_solve_dummy_repo_optional_depends_cuda_dev_resolvo() { let mut result = solve::( &[dummy_channel_with_optional_dependencies_json_path()], SimpleSolveTask { - specs: &["cuda-version[optional_features=[with-cudadev]]"], + specs: &["cuda-version[extras=[with-cudadev]]"], ..SimpleSolveTask::default() }, ) @@ -1062,7 +1062,7 @@ mod resolvo { ); } - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] /// Attempts to enable two optional features that conflict: `[with-oldbors,with-latest-bors]`. /// This should fail because one requests `bors <2.0` and the other requests `bors >=2.0`. #[test] @@ -1070,7 +1070,7 @@ mod resolvo { let result = solve::( &[dummy_channel_with_optional_dependencies_json_path()], SimpleSolveTask { - specs: &["foo[optional_features=[with-oldbors,with-latest-bors]]"], + specs: &["foo[extras=[with-oldbors,with-latest-bors]]"], ..SimpleSolveTask::default() }, ); @@ -1078,7 +1078,7 @@ mod resolvo { insta::assert_snapshot!(result.unwrap_err()); } - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] /// Enables multiple optional dependencies in the same spec (like `[with-baz2,with-bar]`). /// This should pull in `baz >=2.0` and `bar >=1.2.3` if both can coexist. #[test] @@ -1086,7 +1086,7 @@ mod resolvo { let mut result = solve::( &[dummy_channel_with_optional_dependencies_json_path()], SimpleSolveTask { - specs: &["foo[optional_features=[with-baz2,with-bar]]"], + specs: &["foo[extras=[with-baz2,with-bar]]"], ..SimpleSolveTask::default() }, ) @@ -1127,14 +1127,14 @@ mod resolvo { ); } - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] /// Should install xfoo with the feature with-issue717 which requires `with-issue717[with-bors21]` hence pulling in bors 2.1 as well #[test] fn test_solve_dummy_repo_optional_depends_xfoo_optional_depends_with_features() { let mut result = solve::( &[dummy_channel_with_optional_dependencies_json_path()], SimpleSolveTask { - specs: &["xfoo[optional_features=[with-issue717]]"], + specs: &["xfoo[extras=[with-issue717]]"], ..SimpleSolveTask::default() }, ) @@ -1180,14 +1180,14 @@ mod resolvo { ); } - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] /// Tests what happens when a feature depends on the base package but with another feature enabled #[test] fn test_solve_dummy_repo_optional_depends_recursive_feature() { let result = solve::( &[dummy_channel_with_optional_dependencies_json_path()], SimpleSolveTask { - specs: &["foo[optional_features=[with-recursive]]"], + specs: &["foo[extras=[with-recursive]]"], ..SimpleSolveTask::default() }, ); @@ -1196,14 +1196,14 @@ mod resolvo { insta::assert_snapshot!(result.unwrap_err()); } - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] /// Tests that an optional dependency can restrict the highest version of a base dependency #[test] fn test_solve_dummy_repo_optional_depends_version_restriction() { let result = solve::( &[dummy_channel_with_optional_dependencies_json_path()], SimpleSolveTask { - specs: &["foo[optional_features=[with-version-restrict]]"], + specs: &["foo[extras=[with-version-restrict]]"], ..SimpleSolveTask::default() }, ) @@ -1223,14 +1223,14 @@ mod resolvo { ); } - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] /// Tests what happens if a feature introduces a dependency on the base package itself #[test] fn test_solve_dummy_repo_optional_depends_self_dependency() { let mut result = solve::( &[dummy_channel_with_optional_dependencies_json_path()], SimpleSolveTask { - specs: &["foo[optional_features=[with-self]]"], + specs: &["foo[extras=[with-self]]"], ..SimpleSolveTask::default() }, ) @@ -1255,14 +1255,14 @@ mod resolvo { ); } - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] /// Tests what happens if there are two packages for foo but only the package with the lower version has the package that is requested #[test] fn test_solve_dummy_repo_optional_depends_feature_only_in_older() { let mut result = solve::( &[dummy_channel_with_optional_dependencies_json_path()], SimpleSolveTask { - specs: &["foo[optional_features=[legacy-only]]"], + specs: &["foo[extras=[legacy-only]]"], ..SimpleSolveTask::default() }, ) @@ -1295,14 +1295,14 @@ mod resolvo { ); } - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] /// Test what happens if a feature is requested that doesn't exist #[test] fn test_solve_dummy_repo_optional_depends_nonexistent_feature() { let result = solve::( &[dummy_channel_with_optional_dependencies_json_path()], SimpleSolveTask { - specs: &["foo[optional_features=[does-not-exist]]"], + specs: &["foo[extras=[does-not-exist]]"], ..SimpleSolveTask::default() }, ); @@ -1313,14 +1313,14 @@ mod resolvo { ); } - #[cfg(feature = "optional_features")] + #[cfg(feature = "extras")] /// Test what happens when the only package that provides a certain feature cannot be selected due to a conflict #[test] fn test_solve_dummy_repo_optional_depends_feature_conflict() { let result = solve::( &[dummy_channel_with_optional_dependencies_json_path()], SimpleSolveTask { - specs: &["foo[optional_features=[with-bar]]", "foo>=4.0"], + specs: &["foo[extras=[with-bar]]", "foo>=4.0"], ..SimpleSolveTask::default() }, ); diff --git a/test-data/channels/dummy-optional-dependencies/noarch/repodata.json b/test-data/channels/dummy-optional-dependencies/noarch/repodata.json index b6ac0fcf5..2c85b7ceb 100644 --- a/test-data/channels/dummy-optional-dependencies/noarch/repodata.json +++ b/test-data/channels/dummy-optional-dependencies/noarch/repodata.json @@ -51,7 +51,7 @@ "bar >=1.0" ], "with-recursive": [ - "foo[optional_features=[with-bar]]" + "foo[extras=[with-bar]]" ], "with-self": [ "foo >=2.0" @@ -351,7 +351,7 @@ "build_number": 0, "depends": [], "constrains": [ - "ray[version=>=2.9.0, optional_features=[default,data]]" + "ray[version=>=2.9.0, extras=[default,data]]" ], "license": "MIT", "license_family": "MIT", @@ -402,7 +402,7 @@ "version": "2", "optional_depends": { "with-issue717": [ - "issue_717[version=>=2.1, optional_features=[with-bors21]]" + "issue_717[version=>=2.1, extras=[with-bors21]]" ] } },