diff --git a/crates/pixi_manifest/src/lib.rs b/crates/pixi_manifest/src/lib.rs index 12f1b7964..72a2cfa51 100644 --- a/crates/pixi_manifest/src/lib.rs +++ b/crates/pixi_manifest/src/lib.rs @@ -35,7 +35,7 @@ pub use features_ext::FeaturesExt; pub use has_features_iter::HasFeaturesIter; pub use has_manifest_ref::HasManifestRef; use itertools::Itertools; -pub use manifests::{Manifest, ManifestKind, PackageManifest, WorkspaceManifest}; +pub use manifests::{Manifest, ManifestKind, ManifestSource, PackageManifest, WorkspaceManifest}; use miette::Diagnostic; pub use preview::{KnownPreviewFeature, Preview, PreviewFeature}; pub use pypi::pypi_requirement::PyPiRequirement; @@ -76,11 +76,13 @@ pub enum DependencyOverwriteBehavior { } pub enum PypiDependencyLocation { - // The [pypi-dependencies] or [tool.pixi.pypi-dependencies] table - Pixi, - // The [project.optional-dependencies] table in a 'pyproject.toml' manifest + /// [pypi-dependencies] in pixi.toml or [tool.pixi.pypi-dependencies] in pyproject.toml + PixiPypiDependencies, + /// [project.dependencies] in pyproject.toml + Dependencies, + /// [project.optional-dependencies] table in pyproject.toml OptionalDependencies, - // The [dependency-groups] table in a 'pyproject.toml' manifest + /// [dependency-groups] in pyproject.toml DependencyGroups, } diff --git a/crates/pixi_manifest/src/manifests/source.rs b/crates/pixi_manifest/src/manifests/source.rs index 123ffe12a..d3d317f59 100644 --- a/crates/pixi_manifest/src/manifests/source.rs +++ b/crates/pixi_manifest/src/manifests/source.rs @@ -56,7 +56,14 @@ impl ManifestSource { } } - fn manifest(&mut self) -> &mut TomlDocument { + fn manifest_mut(&mut self) -> &mut TomlDocument { + match self { + ManifestSource::PyProjectToml(document) => document, + ManifestSource::PixiToml(document) => document, + } + } + + fn manifest(&self) -> &TomlDocument { match self { ManifestSource::PyProjectToml(document) => document, ManifestSource::PixiToml(document) => document, @@ -80,8 +87,8 @@ impl ManifestSource { .with_feature_name(Some(feature_name)) .with_table(table); - self.manifest() - .get_or_insert_toml_array(table_name.to_string().as_str(), array_name) + self.manifest_mut() + .get_or_insert_toml_array_mut(table_name.to_string().as_str(), array_name) } fn as_table_mut(&mut self) -> &mut Table { @@ -105,7 +112,9 @@ impl ManifestSource { // arrays let remove_requirement = |source: &mut ManifestSource, table, array_name| -> Result<(), TomlError> { - let array = source.manifest().get_toml_array(table, array_name)?; + let array = source + .manifest_mut() + .get_mut_toml_array(table, array_name)?; if let Some(array) = array { array.retain(|x| { let req: pep508_rs::Requirement = x @@ -118,7 +127,7 @@ impl ManifestSource { }); if array.is_empty() { source - .manifest() + .manifest_mut() .get_or_insert_nested_table(table)? .remove(array_name); } @@ -146,7 +155,7 @@ impl ManifestSource { .with_platform(platform.as_ref()) .with_table(Some(consts::PYPI_DEPENDENCIES)); - self.manifest() + self.manifest_mut() .get_or_insert_nested_table(table_name.to_string().as_str()) .map(|t| t.remove(dep.as_source()))?; Ok(()) @@ -169,7 +178,7 @@ impl ManifestSource { .with_platform(platform.as_ref()) .with_table(Some(spec_type.name())); - self.manifest() + self.manifest_mut() .get_or_insert_nested_table(table_name.to_string().as_str()) .map(|t| t.remove(dep.as_source()))?; Ok(()) @@ -186,21 +195,16 @@ impl ManifestSource { platform: Option, feature_name: &FeatureName, ) -> Result<(), TomlError> { - // let dependency_table = - // self.get_or_insert_toml_table(platform, feature_name, spec_type.name())?; - let dependency_table = TableName::new() .with_prefix(self.table_prefix()) .with_platform(platform.as_ref()) .with_feature_name(Some(feature_name)) .with_table(Some(spec_type.name())); - self.manifest() + self.manifest_mut() .get_or_insert_nested_table(dependency_table.to_string().as_str()) .map(|t| t.insert(name.as_normalized(), Item::Value(spec.to_toml_value())))?; - // dependency_table.insert(name.as_normalized(), - // Item::Value(spec.to_toml_value())); Ok(()) } @@ -234,7 +238,7 @@ impl ManifestSource { // - When a specific platform is requested, as markers are not supported (https://github.com/prefix-dev/pixi/issues/2149) // - When an editable install is requested if matches!(self, ManifestSource::PixiToml(_)) - || matches!(location, Some(PypiDependencyLocation::Pixi)) + || matches!(location, Some(PypiDependencyLocation::PixiPypiDependencies)) || platform.is_some() || editable.is_some_and(|e| e) { @@ -250,7 +254,7 @@ impl ManifestSource { .with_feature_name(Some(feature_name)) .with_table(Some(consts::PYPI_DEPENDENCIES)); - self.manifest() + self.manifest_mut() .get_or_insert_nested_table(dependency_table.to_string().as_str())? .insert( requirement.name.as_ref(), @@ -266,12 +270,14 @@ impl ManifestSource { let add_requirement = |source: &mut ManifestSource, table, array| -> Result<(), TomlError> { source - .manifest() - .get_or_insert_toml_array(table, array)? + .manifest_mut() + .get_or_insert_toml_array_mut(table, array)? .push(requirement.to_string()); Ok(()) }; - if feature_name.is_default() { + if feature_name.is_default() + || matches!(location, Some(PypiDependencyLocation::Dependencies)) + { add_requirement(self, "project", "dependencies")? } else if matches!(location, Some(PypiDependencyLocation::OptionalDependencies)) { add_requirement( @@ -285,6 +291,79 @@ impl ManifestSource { Ok(()) } + /// Determines the location of a PyPi dependency within the manifest. + /// + /// This method checks various sections of the manifest to locate the specified + /// PyPi dependency. It searches in the following order: + /// 1. `pypi-dependencies` table in the manifest. + /// 2. `project.dependencies` array in the manifest. + /// 3. `project.optional-dependencies` array in the manifest. + /// 4. `dependency-groups` array in the manifest. + /// + /// # Arguments + /// + /// * `dep` - The name of the PyPi package to locate. + /// * `platform` - An optional platform specification. + /// * `feature_name` - The name of the feature to which the dependency belongs. + /// + /// # Returns + /// + /// An `Option` containing the `PypiDependencyLocation` if the dependency is found, + /// or `None` if it is not found in any of the checked sections. + pub fn pypi_dependency_location( + &self, + package_name: &PyPiPackageName, + platform: Option, + feature_name: &FeatureName, + ) -> Option { + // For both 'pyproject.toml' and 'pixi.toml' manifest, + // try and to get `pypi-dependency` + let table_name = TableName::new() + .with_prefix(self.table_prefix()) + .with_feature_name(Some(feature_name)) + .with_platform(platform.as_ref()) + .with_table(Some(consts::PYPI_DEPENDENCIES)); + + let pypi_dependency_table = self + .manifest() + .get_nested_table(table_name.to_string().as_str()) + .ok(); + + if pypi_dependency_table + .and_then(|table| table.get(package_name.as_source())) + .is_some() + { + return Some(PypiDependencyLocation::PixiPypiDependencies); + } + + if self + .manifest() + .get_toml_array("project", "dependencies") + .is_ok() + { + return Some(PypiDependencyLocation::Dependencies); + } + let name = feature_name.to_string(); + + if self + .manifest() + .get_toml_array("project.optional-dependencies", &name) + .is_ok() + { + return Some(PypiDependencyLocation::OptionalDependencies); + } + + if self + .manifest() + .get_toml_array("dependency-groups", &name) + .is_ok() + { + return Some(PypiDependencyLocation::DependencyGroups); + } + + None + } + /// Removes a task from the TOML manifest pub fn remove_task( &mut self, @@ -301,7 +380,7 @@ impl ManifestSource { .with_feature_name(Some(feature_name)) .with_table(Some("tasks")); - self.manifest() + self.manifest_mut() .get_or_insert_nested_table(task_table.to_string().as_str())? .remove(name); @@ -323,7 +402,7 @@ impl ManifestSource { .with_feature_name(Some(feature_name)) .with_table(Some("tasks")); - self.manifest() + self.manifest_mut() .get_or_insert_nested_table(task_table.to_string().as_str())? .insert(name, task.into()); @@ -363,7 +442,7 @@ impl ManifestSource { .with_table(Some("environments")); // Get the environment table - self.manifest() + self.manifest_mut() .get_or_insert_nested_table(env_table.to_string().as_str())? .insert(&name.into(), item); @@ -379,7 +458,7 @@ impl ManifestSource { .with_table(Some("environments")); Ok(self - .manifest() + .manifest_mut() .get_or_insert_nested_table(env_table.to_string().as_str())? .remove(name) .is_some()) diff --git a/crates/pixi_manifest/src/target.rs b/crates/pixi_manifest/src/target.rs index 139523901..f8f38697c 100644 --- a/crates/pixi_manifest/src/target.rs +++ b/crates/pixi_manifest/src/target.rs @@ -237,16 +237,16 @@ impl WorkspaceTarget { ) -> Result { if self.has_pypi_dependency(requirement, false) { match dependency_overwrite_behavior { - DependencyOverwriteBehavior::OverwriteIfExplicit - if requirement.version_or_url.is_none() => - { - return Ok(false) + DependencyOverwriteBehavior::OverwriteIfExplicit => { + if requirement.version_or_url.is_none() { + return Ok(false); + } } DependencyOverwriteBehavior::IgnoreDuplicate => return Ok(false), DependencyOverwriteBehavior::Error => { return Err(DependencyError::Duplicate(requirement.name.to_string())); } - _ => {} + DependencyOverwriteBehavior::Overwrite => {} } } diff --git a/crates/pixi_manifest/src/toml/document.rs b/crates/pixi_manifest/src/toml/document.rs index 84128969a..2cda247cc 100644 --- a/crates/pixi_manifest/src/toml/document.rs +++ b/crates/pixi_manifest/src/toml/document.rs @@ -36,6 +36,26 @@ impl TomlDocument { self.0.entry(key).or_insert(item) } + /// Retrieve a reference to a target table `table_name` + /// in dotted form (e.g. `table1.table2`) from the root of the document. + pub fn get_nested_table<'a>( + &'a self, + table_name: &str, + ) -> Result<&'a dyn TableLike, TomlError> { + let parts: Vec<&str> = table_name.split('.').collect(); + + let mut current_table = self.0.as_table() as &dyn TableLike; + + for part in parts { + current_table = current_table + .get(part) + .ok_or_else(|| TomlError::table_error(part, table_name))? + .as_table_like() + .ok_or_else(|| TomlError::table_error(part, table_name))?; + } + Ok(current_table) + } + /// Retrieve a mutable reference to a target table `table_name` /// in dotted form (e.g. `table1.table2`) from the root of the document. /// If the table is not found, it is inserted into the document. @@ -108,7 +128,7 @@ impl TomlDocument { /// in table `table_name` in dotted form (e.g. `table1.table2.array`). /// /// If the array is not found, it is inserted into the document. - pub fn get_or_insert_toml_array<'a>( + pub fn get_or_insert_toml_array_mut<'a>( &'a mut self, table_name: &str, array_name: &str, @@ -124,7 +144,7 @@ impl TomlDocument { /// in table `table_name` in dotted form (e.g. `table1.table2.array`). /// /// If the array is not found, returns None. - pub fn get_toml_array<'a>( + pub fn get_mut_toml_array<'a>( &'a mut self, table_name: &str, array_name: &str, @@ -135,6 +155,22 @@ impl TomlDocument { .and_then(|a| a.as_array_mut()); Ok(array) } + + /// Retrieves a reference to a target array `array_name` + /// in table `table_name` in dotted form (e.g. `table1.table2.array`). + /// + /// If the array is not found, returns None. + pub fn get_toml_array<'a>( + &'a self, + table_name: &str, + array_name: &str, + ) -> Result, TomlError> { + let array = self + .get_nested_table(table_name)? + .get(array_name) + .and_then(|a| a.as_array()); + Ok(array) + } } #[cfg(test)] diff --git a/src/cli/add.rs b/src/cli/add.rs index 5315700d4..259ec5139 100644 --- a/src/cli/add.rs +++ b/src/cli/add.rs @@ -109,7 +109,11 @@ pub async fn execute(args: Args) -> miette::Result<()> { } DependencyType::PypiDependency => { let match_specs = IndexMap::default(); - let pypi_deps = dependency_config.pypi_deps(&project)?; + let pypi_deps = dependency_config + .pypi_deps(&project)? + .into_iter() + .map(|(name, req)| (name, (req, None))) + .collect(); (match_specs, pypi_deps) } }; @@ -124,7 +128,6 @@ pub async fn execute(args: Args) -> miette::Result<()> { &args.dependency_config.feature, &args.dependency_config.platforms, args.editable, - &None, dry_run, ) .await?; diff --git a/src/cli/upgrade.rs b/src/cli/upgrade.rs index d4c7f5333..179ee7834 100644 --- a/src/cli/upgrade.rs +++ b/src/cli/upgrade.rs @@ -1,6 +1,7 @@ use std::cmp::Ordering; use crate::cli::cli_config::ProjectConfig; +use crate::project::{MatchSpecs, PypiDeps}; use crate::Project; use clap::Parser; use fancy_display::FancyDisplay; @@ -65,19 +66,63 @@ pub async fn execute(args: Args) -> miette::Result<()> { ) }; - // TODO: Also support build and host + let (match_specs, pypi_deps) = parse_specs(feature, &args, &project)?; + + let update_deps = project + .update_dependencies( + match_specs, + pypi_deps, + &args.prefix_update_config, + &args.specs.feature, + &[], + false, + args.dry_run, + ) + .await?; + + // Is there something to report? + if let Some(update_deps) = update_deps { + let diff = update_deps.lock_file_diff; + // Format as json? + if args.json { + let json_diff = LockFileJsonDiff::new(&project, diff); + let json = serde_json::to_string_pretty(&json_diff).expect("failed to convert to json"); + println!("{}", json); + } else { + diff.print() + .into_diagnostic() + .context("failed to print lock-file diff")?; + } + } else { + eprintln!( + "{}All packages are already up-to-date", + console::style(console::Emoji("✔ ", "")).green() + ); + } + + Project::warn_on_discovered_from_env(args.project_config.manifest_path.as_deref()); + Ok(()) +} + +/// Parses the specifications for dependencies from the given feature, arguments, and project. +/// +/// This function processes the dependencies and PyPi dependencies specified in the feature, +/// filters them based on the provided arguments, and returns the resulting match specifications +/// and PyPi dependencies. +fn parse_specs( + feature: &pixi_manifest::Feature, + args: &Args, + project: &Project, +) -> miette::Result<(MatchSpecs, PypiDeps)> { let spec_type = SpecType::Run; let match_spec_iter = feature .dependencies(spec_type, None) .into_iter() .flat_map(|deps| deps.into_owned()); - let pypi_deps_iter = feature .pypi_dependencies(None) .into_iter() .flat_map(|deps| deps.into_owned()); - - // If the user specified a package name, check to see if it is even there. if let Some(package_names) = &args.specs.packages { let available_packages = match_spec_iter .clone() @@ -93,7 +138,6 @@ pub async fn execute(args: Args) -> miette::Result<()> { ensure_package_exists(package, &available_packages)? } } - let match_specs = match_spec_iter // Don't upgrade excluded packages .filter(|(name, _)| match &args.specs.exclude { @@ -151,8 +195,23 @@ pub async fn execute(args: Args) -> miette::Result<()> { None } }) + // Only upgrade in pyproject.toml if it is explicitly mentioned in `tool.pixi.dependencies.python` + .filter(|(name, _)| { + if name.as_normalized() == "python" { + if let pixi_manifest::ManifestSource::PyProjectToml(document) = + project.manifest.document.clone() + { + if document + .get_nested_table("[tool.pixi.dependencies.python]") + .is_err() + { + return false; + } + } + } + true + }) .collect(); - let pypi_deps = pypi_deps_iter // Don't upgrade excluded packages .filter(|(name, _)| match &args.specs.exclude { @@ -191,43 +250,17 @@ pub async fn execute(args: Args) -> miette::Result<()> { )), _ => None, }) + .map(|(name, req)| { + let location = project.manifest.document.pypi_dependency_location( + &name, + None, // TODO: add support for platforms + &args.specs.feature, + ); + (name, (req, location)) + }) .collect(); - let update_deps = project - .update_dependencies( - match_specs, - pypi_deps, - &args.prefix_update_config, - &args.specs.feature, - &[], - false, - &None, - args.dry_run, - ) - .await?; - - // Is there something to report? - if let Some(update_deps) = update_deps { - let diff = update_deps.lock_file_diff; - // Format as json? - if args.json { - let json_diff = LockFileJsonDiff::new(&project, diff); - let json = serde_json::to_string_pretty(&json_diff).expect("failed to convert to json"); - println!("{}", json); - } else { - diff.print() - .into_diagnostic() - .context("failed to print lock-file diff")?; - } - } else { - eprintln!( - "{}All packages are already up-to-date", - console::style(console::Emoji("✔ ", "")).green() - ); - } - - Project::warn_on_discovered_from_env(args.project_config.manifest_path.as_deref()); - Ok(()) + Ok((match_specs, pypi_deps)) } /// Ensures the existence of the specified package diff --git a/src/global/project/manifest.rs b/src/global/project/manifest.rs index 84b956dc2..5974b0c64 100644 --- a/src/global/project/manifest.rs +++ b/src/global/project/manifest.rs @@ -92,7 +92,7 @@ impl Manifest { // Update self.document let channels_array = self .document - .get_or_insert_toml_array(&format!("envs.{env_name}"), "channels")?; + .get_or_insert_toml_array_mut(&format!("envs.{env_name}"), "channels")?; for channel in channels { channels_array.push(channel.as_str()); } diff --git a/src/project/mod.rs b/src/project/mod.rs index 4804a9514..f1e2f0df7 100644 --- a/src/project/mod.rs +++ b/src/project/mod.rs @@ -154,6 +154,13 @@ impl Borrow for Project { } } +pub type PypiDeps = indexmap::IndexMap< + PyPiPackageName, + (Requirement, Option), +>; + +pub type MatchSpecs = indexmap::IndexMap; + impl Project { /// Constructs a new instance from an internal manifest representation pub(crate) fn from_manifest(manifest: Manifest) -> Self { @@ -660,13 +667,12 @@ impl Project { #[allow(clippy::too_many_arguments)] pub async fn update_dependencies( &mut self, - match_specs: IndexMap, - pypi_deps: IndexMap, + match_specs: MatchSpecs, + pypi_deps: PypiDeps, prefix_update_config: &PrefixUpdateConfig, feature_name: &FeatureName, platforms: &[Platform], editable: bool, - location: &Option, dry_run: bool, ) -> Result, miette::Error> { let mut conda_specs_to_add_constraints_for = IndexMap::new(); @@ -691,18 +697,18 @@ impl Project { } } - for (name, spec) in pypi_deps { + for (name, (spec, location)) in pypi_deps { let added = self.manifest.add_pep508_dependency( &spec, platforms, feature_name, Some(editable), DependencyOverwriteBehavior::Overwrite, - location, + &location, )?; if added { if spec.version_or_url.is_none() { - pypi_specs_to_add_constraints_for.insert(name.clone(), spec); + pypi_specs_to_add_constraints_for.insert(name.clone(), (spec, location)); } pypi_packages.insert(name.as_normalized().clone()); } @@ -793,7 +799,6 @@ impl Project { feature_name, platforms, editable, - location, )?; implicit_constraints.extend(pypi_constraints); } @@ -841,7 +846,7 @@ impl Project { fn unlock_packages( &self, lock_file: &LockFile, - conda_packages: HashSet, + conda_packages: HashSet, pypi_packages: HashSet, affected_environments: HashSet<(&str, Platform)>, ) -> LockFile { @@ -931,16 +936,17 @@ impl Project { /// Update the pypi specs of newly added packages based on the contents of /// the updated lock-file. - #[allow(clippy::too_many_arguments)] fn update_pypi_specs_from_lock_file( &mut self, updated_lock_file: &LockFile, - pypi_specs_to_add_constraints_for: IndexMap, + pypi_specs_to_add_constraints_for: IndexMap< + PyPiPackageName, + (Requirement, Option), + >, affect_environment_and_platforms: Vec<(String, Platform)>, feature_name: &FeatureName, platforms: &[Platform], editable: bool, - location: &Option, ) -> miette::Result> { let mut implicit_constraints = HashMap::new(); @@ -962,7 +968,7 @@ impl Project { let pinning_strategy = self.config().pinning_strategy.unwrap_or_default(); // Determine the versions of the packages in the lock-file - for (name, req) in pypi_specs_to_add_constraints_for { + for (name, (req, location)) in pypi_specs_to_add_constraints_for { let version_constraint = pinning_strategy.determine_version_constraint( pypi_records .iter() @@ -991,7 +997,7 @@ impl Project { feature_name, Some(editable), DependencyOverwriteBehavior::Overwrite, - location, + &location, )?; } } diff --git a/tests/integration_python/common.py b/tests/integration_python/common.py index 6ffc30bc1..efb7aba23 100644 --- a/tests/integration_python/common.py +++ b/tests/integration_python/common.py @@ -7,6 +7,16 @@ PIXI_VERSION = "0.39.0" +ALL_PLATFORMS = '["linux-64", "osx-64", "win-64", "linux-ppc64le", "linux-aarch64"]' + +EMPTY_BOILERPLATE_PROJECT = f""" +[project] +name = "test" +channels = [] +platforms = {ALL_PLATFORMS} +""" + + class ExitCode(IntEnum): SUCCESS = 0 FAILURE = 1 diff --git a/tests/integration_python/test_main_cli.py b/tests/integration_python/test_main_cli.py index b6312432e..682fd7f20 100644 --- a/tests/integration_python/test_main_cli.py +++ b/tests/integration_python/test_main_cli.py @@ -1,6 +1,7 @@ import os from pathlib import Path -from .common import verify_cli_command, ExitCode, PIXI_VERSION + +from .common import verify_cli_command, ExitCode, PIXI_VERSION, ALL_PLATFORMS import tomllib import json import pytest @@ -541,6 +542,63 @@ def test_upgrade_pypi_and_conda_package(pixi: Path, tmp_pixi_workspace: Path) -> assert numpy_conda != "1.*" +@pytest.mark.slow +def test_upgrade_dependency_location_pixi(pixi: Path, tmp_path: Path) -> None: + # Test based on https://github.com/prefix-dev/pixi/issues/2470 + # Making sure pixi places the upgraded package in the correct location + manifest_path = tmp_path / "pyproject.toml" + pyproject = f""" +[project] +name = "test-upgrade" +dependencies = ["numpy==1.*"] +requires-python = "==3.13" + +[project.optional-dependencies] +cli = ["rich==12"] + +[dependency-groups] +test = ["pytest==6"] + +[tool.pixi.project] +channels = ["conda-forge"] +platforms = {ALL_PLATFORMS} + +[tool.pixi.pypi-dependencies] +polars = "==0.*" + +[tool.pixi.environments] +test = ["test"] + """ + + manifest_path.write_text(pyproject) + + # Upgrade numpy, both conda and pypi should be upgraded + verify_cli_command( + [pixi, "upgrade", "--manifest-path", manifest_path], + stderr_contains=["polars"], + ) + parsed_manifest = tomllib.loads(manifest_path.read_text()) + + # Check that `requrires-python` is the same + assert parsed_manifest["project"]["requires-python"] == "==3.13" + + # Check that `tool.pixi.dependencies.python` isn't added + assert "python" not in parsed_manifest.get("tool", {}).get("pixi", {}).get("dependencies", {}) + + # Check that project.dependencies are upgraded + project_dependencies = parsed_manifest["project"]["dependencies"] + numpy_pypi = project_dependencies[0] + assert "numpy" in numpy_pypi + assert "==1.*" not in numpy_pypi + assert "polars" not in project_dependencies + + # Check that the pypi-dependencies are upgraded + pypi_dependencies = parsed_manifest["tool"]["pixi"]["pypi-dependencies"] + polars_pypi = pypi_dependencies["polars"] + assert polars_pypi != "==0.*" + assert "numpy" not in pypi_dependencies + + def test_upgrade_keep_info( pixi: Path, tmp_pixi_workspace: Path, multiple_versions_channel_1: str ) -> None: diff --git a/tests/integration_python/test_run_cli.py b/tests/integration_python/test_run_cli.py index 606aca7c3..28a9cc7af 100644 --- a/tests/integration_python/test_run_cli.py +++ b/tests/integration_python/test_run_cli.py @@ -1,18 +1,9 @@ import json from pathlib import Path -from .common import verify_cli_command, ExitCode, default_env_path +from .common import EMPTY_BOILERPLATE_PROJECT, verify_cli_command, ExitCode, default_env_path import tempfile import os -ALL_PLATFORMS = '["linux-64", "osx-64", "win-64", "linux-ppc64le", "linux-aarch64"]' - -EMPTY_BOILERPLATE_PROJECT = f""" -[project] -name = "test" -channels = [] -platforms = {ALL_PLATFORMS} -""" - def test_run_in_shell_environment(pixi: Path, tmp_pixi_workspace: Path) -> None: manifest = tmp_pixi_workspace.joinpath("pixi.toml")