From c8b48499403949c438cd71572e628ee26d27bef2 Mon Sep 17 00:00:00 2001 From: nichmor Date: Tue, 10 Sep 2024 15:26:18 +0300 Subject: [PATCH] feat: refactor manifest into more generic approach (#2015) Co-authored-by: Hofer-Julian <30049909+Hofer-Julian@users.noreply.github.com> --- crates/pixi_manifest/src/feature.rs | 2 +- crates/pixi_manifest/src/lib.rs | 5 +- .../src/{ => manifests}/manifest.rs | 8 +- crates/pixi_manifest/src/manifests/mod.rs | 77 ++++ .../src/{document.rs => manifests/project.rs} | 406 +++++++++++------- ...fests__manifest__tests__add_channels.snap} | 3 +- ...sts__manifest__tests__add_dependency.snap} | 3 +- ...manifests__manifest__tests__add_task.snap} | 3 +- ...ts__manifest__tests__test_remove_bar.snap} | 3 +- ...ts__manifest__tests__test_remove_baz.snap} | 3 +- ...s__manifest__tests__test_remove_fooz.snap} | 3 +- ..._tests__test_remove_pypi_feature_dep.snap} | 3 +- ..._test_remove_pypi_feature_target_dep.snap} | 3 +- ...anifest__tests__test_remove_pypi_jax.snap} | 3 +- ...st__tests__test_remove_pypi_requests.snap} | 3 +- ...st__tests__test_remove_pypi_xpackage.snap} | 3 +- ...ect__tests__get_or_insert_toml_table.snap} | 3 +- ...ts__project__tests__nameless_to_toml.snap} | 3 +- ...ests__test_add_environment_pixi.toml.snap} | 3 +- ..._test_add_environment_pyproject.toml.snap} | 3 +- ...s__test_remove_environment_pixi.toml.snap} | 3 +- ...st_remove_environment_pyproject.toml.snap} | 3 +- crates/pixi_manifest/src/pyproject.rs | 3 +- crates/pixi_manifest/src/target.rs | 2 +- 24 files changed, 350 insertions(+), 204 deletions(-) rename crates/pixi_manifest/src/{ => manifests}/manifest.rs (99%) create mode 100644 crates/pixi_manifest/src/manifests/mod.rs rename crates/pixi_manifest/src/{document.rs => manifests/project.rs} (60%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__manifest__tests__add_channels.snap => manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_channels.snap} (81%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__manifest__tests__add_dependency.snap => manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_dependency.snap} (83%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__manifest__tests__add_task.snap => manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_task.snap} (87%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__manifest__tests__test_remove_bar.snap => manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_bar.snap} (83%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__manifest__tests__test_remove_baz.snap => manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_baz.snap} (82%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__manifest__tests__test_remove_fooz.snap => manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_fooz.snap} (83%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__manifest__tests__test_remove_pypi_feature_dep.snap => manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_feature_dep.snap} (88%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__manifest__tests__test_remove_pypi_feature_target_dep.snap => manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_feature_target_dep.snap} (87%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__manifest__tests__test_remove_pypi_jax.snap => manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_jax.snap} (88%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__manifest__tests__test_remove_pypi_requests.snap => manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_requests.snap} (88%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__manifest__tests__test_remove_pypi_xpackage.snap => manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_xpackage.snap} (88%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__document__tests__get_or_insert_toml_table.snap => manifests/snapshots/pixi_manifest__manifests__project__tests__get_or_insert_toml_table.snap} (81%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__document__tests__nameless_to_toml.snap => manifests/snapshots/pixi_manifest__manifests__project__tests__nameless_to_toml.snap} (82%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__document__tests__test_add_environment_pixi.toml.snap => manifests/snapshots/pixi_manifest__manifests__project__tests__test_add_environment_pixi.toml.snap} (81%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__document__tests__test_add_environment_pyproject.toml.snap => manifests/snapshots/pixi_manifest__manifests__project__tests__test_add_environment_pyproject.toml.snap} (82%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__document__tests__test_remove_environment_pixi.toml.snap => manifests/snapshots/pixi_manifest__manifests__project__tests__test_remove_environment_pixi.toml.snap} (52%) rename crates/pixi_manifest/src/{snapshots/pixi_manifest__document__tests__test_remove_environment_pyproject.toml.snap => manifests/snapshots/pixi_manifest__manifests__project__tests__test_remove_environment_pyproject.toml.snap} (55%) diff --git a/crates/pixi_manifest/src/feature.rs b/crates/pixi_manifest/src/feature.rs index d9bfd22e0..4107ee8f2 100644 --- a/crates/pixi_manifest/src/feature.rs +++ b/crates/pixi_manifest/src/feature.rs @@ -377,7 +377,7 @@ mod tests { use assert_matches::assert_matches; use super::*; - use crate::manifest::Manifest; + use crate::manifests::manifest::Manifest; #[test] fn test_dependencies_borrowed() { diff --git a/crates/pixi_manifest/src/lib.rs b/crates/pixi_manifest/src/lib.rs index a537e0482..09d0ff64b 100644 --- a/crates/pixi_manifest/src/lib.rs +++ b/crates/pixi_manifest/src/lib.rs @@ -1,7 +1,6 @@ mod activation; pub(crate) mod channel; mod dependencies; -mod document; mod environment; mod environments; mod error; @@ -9,7 +8,7 @@ mod feature; mod features_ext; mod has_features_iter; mod has_manifest_ref; -mod manifest; +mod manifests; mod metadata; mod parsed_manifest; pub mod pypi; @@ -24,7 +23,7 @@ mod validation; pub use dependencies::{CondaDependencies, Dependencies, PyPiDependencies}; -pub use manifest::{Manifest, ManifestKind}; +pub use manifests::manifest::{Manifest, ManifestKind}; pub use crate::environments::Environments; pub use crate::parsed_manifest::ParsedManifest; diff --git a/crates/pixi_manifest/src/manifest.rs b/crates/pixi_manifest/src/manifests/manifest.rs similarity index 99% rename from crates/pixi_manifest/src/manifest.rs rename to crates/pixi_manifest/src/manifests/manifest.rs index 59dbe3d68..c53625364 100644 --- a/crates/pixi_manifest/src/manifest.rs +++ b/crates/pixi_manifest/src/manifests/manifest.rs @@ -17,8 +17,8 @@ use toml_edit::DocumentMut; use crate::{ consts, - document::ManifestSource, error::{DependencyError, TomlError, UnknownFeature}, + manifests::{ManifestSource, TomlManifest}, pypi::PyPiPackageName, pyproject::PyProjectManifest, to_options, DependencyOverwriteBehavior, Environment, EnvironmentName, Feature, FeatureName, @@ -122,8 +122,8 @@ impl Manifest { manifest.validate(NamedSource::new(file_name, contents.to_owned()), root)?; let source = match manifest_kind { - ManifestKind::Pixi => ManifestSource::PixiToml(document), - ManifestKind::Pyproject => ManifestSource::PyProjectToml(document), + ManifestKind::Pixi => ManifestSource::PixiToml(TomlManifest::new(document)), + ManifestKind::Pyproject => ManifestSource::PyProjectToml(TomlManifest::new(document)), }; Ok(Self { @@ -707,7 +707,7 @@ mod tests { use tempfile::tempdir; use super::*; - use crate::{channel::PrioritizedChannel, manifest::Manifest}; + use crate::channel::PrioritizedChannel; use glob::glob; const PROJECT_BOILERPLATE: &str = r#" diff --git a/crates/pixi_manifest/src/manifests/mod.rs b/crates/pixi_manifest/src/manifests/mod.rs new file mode 100644 index 000000000..cb9a28cae --- /dev/null +++ b/crates/pixi_manifest/src/manifests/mod.rs @@ -0,0 +1,77 @@ +use toml_edit::{self, Array, Item, Table, Value}; + +pub mod project; + +pub mod manifest; + +pub use project::ManifestSource; + +use crate::error::TomlError; + +/// Represents a wrapper around a TOML document. +/// This struct is exposed to other crates +/// to allow for easy manipulation of the TOML document. +#[derive(Debug, Clone, Default)] +pub struct TomlManifest(toml_edit::DocumentMut); + +impl TomlManifest { + /// Create a new `TomlManifest` from a `toml_edit::DocumentMut` document. + pub fn new(document: toml_edit::DocumentMut) -> Self { + Self(document) + } + + /// 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. + fn get_or_insert_nested_table<'a>( + &'a mut self, + table_name: &str, + ) -> Result<&'a mut Table, TomlError> { + let parts: Vec<&str> = table_name.split('.').collect(); + + let mut current_table = self.0.as_table_mut(); + + for part in parts { + let entry = current_table.entry(part); + let item = entry.or_insert(Item::Table(Table::new())); + current_table = item + .as_table_mut() + .ok_or_else(|| TomlError::table_error(part, table_name))?; + // Avoid creating empty tables + current_table.set_implicit(true); + } + Ok(current_table) + } + + /// Retrieves a mutable 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, it is inserted into the document. + pub fn get_or_insert_toml_array<'a>( + &'a mut self, + table_name: &str, + array_name: &str, + ) -> Result<&'a mut Array, TomlError> { + self.get_or_insert_nested_table(table_name)? + .entry(array_name) + .or_insert(Item::Value(Value::Array(Array::new()))) + .as_array_mut() + .ok_or_else(|| TomlError::array_error(array_name, table_name.to_string().as_str())) + } + + /// Retrieves a mutable 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 mut self, + table_name: &str, + array_name: &str, + ) -> Result, TomlError> { + let array = self + .get_or_insert_nested_table(table_name)? + .get_mut(array_name) + .and_then(|a| a.as_array_mut()); + Ok(array) + } +} diff --git a/crates/pixi_manifest/src/document.rs b/crates/pixi_manifest/src/manifests/project.rs similarity index 60% rename from crates/pixi_manifest/src/document.rs rename to crates/pixi_manifest/src/manifests/project.rs index 0d142f87c..c24da83f8 100644 --- a/crates/pixi_manifest/src/document.rs +++ b/crates/pixi_manifest/src/manifests/project.rs @@ -1,24 +1,113 @@ -use std::fmt; +use std::fmt::{self, Display, Formatter}; use pixi_spec::PixiSpec; use rattler_conda_types::{PackageName, Platform}; use toml_edit::{value, Array, Item, Table, Value}; -use super::{consts, error::TomlError, pypi::PyPiPackageName, PyPiRequirement}; +use super::TomlManifest; +use crate::{consts, error::TomlError, pypi::PyPiPackageName, PyPiRequirement}; use crate::{consts::PYPROJECT_PIXI_PREFIX, FeatureName, SpecType, Task}; +/// Struct that is used to access a table in `pixi.toml` or `pyproject.toml`. +pub struct TableName<'a> { + prefix: Option<&'static str>, + platform: Option<&'a Platform>, + feature_name: Option<&'a FeatureName>, + table: Option<&'a str>, +} + +impl Display for TableName<'_> { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self.to_toml_table_name()) + } +} + +impl<'a> TableName<'a> { + /// Create a new `TableName` with default values. + pub fn new() -> Self { + Self { + prefix: None, + platform: None, + feature_name: None, + table: None, + } + } + + /// Set the prefix of the table. + pub fn with_prefix(mut self, prefix: Option<&'static str>) -> Self { + self.prefix = prefix; + self + } + + /// Set the platform of the table. + pub fn with_platform(mut self, platform: Option<&'a Platform>) -> Self { + self.platform = platform; + self + } + + /// Set the feature name of the table. + pub fn with_feature_name(mut self, feature_name: Option<&'a FeatureName>) -> Self { + self.feature_name = feature_name; + self + } + + /// Set the optional and custom table name. + pub fn with_table(mut self, table: Option<&'static str>) -> Self { + self.table = table; + self + } +} + +impl TableName<'_> { + /// Returns the name of the table in dotted form (e.g. `table1.table2.array`). + /// It is composed of + /// - the 'tool.pixi' prefix if the manifest is a 'pyproject.toml' file + /// - the feature if it is not the default feature + /// - the platform if it is not `None` + /// - the name of a nested TOML table if it is not `None` + fn to_toml_table_name(&self) -> String { + let mut parts = Vec::new(); + + if self.prefix.is_some() { + parts.push(self.prefix.unwrap()); + } + + if self + .feature_name + .as_ref() + .is_some_and(|feature_name| !feature_name.is_default()) + { + parts.push("feature"); + parts.push( + self.feature_name + .as_ref() + .expect("we already verified") + .as_str(), + ); + } + if let Some(platform) = self.platform { + parts.push("target"); + parts.push(platform.as_str()); + } + if let Some(table) = self.table { + parts.push(table); + } + parts.join(".") + } +} + /// Discriminates between a 'pixi.toml' and a 'pyproject.toml' manifest #[derive(Debug, Clone)] pub enum ManifestSource { - PyProjectToml(toml_edit::DocumentMut), - PixiToml(toml_edit::DocumentMut), + PyProjectToml(TomlManifest), + PixiToml(TomlManifest), } impl fmt::Display for ManifestSource { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - ManifestSource::PyProjectToml(document) => write!(f, "{}", document), - ManifestSource::PixiToml(document) => write!(f, "{}", document), + ManifestSource::PyProjectToml(document) => write!(f, "{}", document.0), + ManifestSource::PixiToml(document) => write!(f, "{}", document.0), } } } @@ -27,13 +116,13 @@ impl ManifestSource { /// Returns a new empty pixi manifest. #[cfg(test)] fn empty_pixi() -> Self { - ManifestSource::PixiToml(toml_edit::DocumentMut::new()) + ManifestSource::PixiToml(TomlManifest::default()) } /// Returns a new empty pyproject manifest. #[cfg(test)] fn empty_pyproject() -> Self { - ManifestSource::PyProjectToml(toml_edit::DocumentMut::new()) + ManifestSource::PyProjectToml(TomlManifest::default()) } /// Returns the file name of the manifest @@ -45,102 +134,18 @@ impl ManifestSource { } } - /// Returns the a nested path. It is composed of - /// - the 'tool.pixi' prefix if the manifest is a 'pyproject.toml' file - /// - the feature if it is not the default feature - /// - the platform if it is not `None` - /// - the name of a nested TOML table if it is not `None` - fn get_nested_toml_table_name( - &self, - feature_name: &FeatureName, - platform: Option, - table: Option<&str>, - ) -> String { - let mut parts = Vec::new(); - if let ManifestSource::PyProjectToml(_) = self { - parts.push(PYPROJECT_PIXI_PREFIX); - } - if !feature_name.is_default() { - parts.push("feature"); - parts.push(feature_name.as_str()); - } - if let Some(platform) = platform { - parts.push("target"); - parts.push(platform.as_str()); - } - if let Some(table) = table { - parts.push(table); + fn table_prefix(&self) -> Option<&'static str> { + match self { + ManifestSource::PyProjectToml(_) => Some(PYPROJECT_PIXI_PREFIX), + ManifestSource::PixiToml(_) => None, } - parts.join(".") - } - - /// Retrieve a mutable reference to a target table `table_name` - /// for a specific platform and feature. - /// If the table is not found, it is inserted into the document. - fn get_or_insert_toml_table<'a>( - &'a mut self, - platform: Option, - feature: &FeatureName, - table_name: &str, - ) -> Result<&'a mut Table, TomlError> { - let table_name: String = - self.get_nested_toml_table_name(feature, platform, Some(table_name)); - self.get_or_insert_nested_table(&table_name) } - /// 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. - fn get_or_insert_nested_table<'a>( - &'a mut self, - table_name: &str, - ) -> Result<&'a mut Table, TomlError> { - let parts: Vec<&str> = table_name.split('.').collect(); - - let mut current_table = self.as_table_mut(); - - for part in parts { - let entry = current_table.entry(part); - let item = entry.or_insert(Item::Table(Table::new())); - current_table = item - .as_table_mut() - .ok_or_else(|| TomlError::table_error(part, table_name))?; - // Avoid creating empty tables - current_table.set_implicit(true); + fn manifest(&mut self) -> &mut TomlManifest { + match self { + ManifestSource::PyProjectToml(document) => document, + ManifestSource::PixiToml(document) => document, } - Ok(current_table) - } - - /// Retrieves a mutable 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, it is inserted into the document. - fn get_or_insert_toml_array<'a>( - &'a mut self, - table_name: &str, - array_name: &str, - ) -> Result<&'a mut Array, TomlError> { - self.get_or_insert_nested_table(table_name)? - .entry(array_name) - .or_insert(Item::Value(Value::Array(Array::new()))) - .as_array_mut() - .ok_or_else(|| TomlError::array_error(array_name, table_name)) - } - - /// Retrieves a mutable 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. - fn get_toml_array<'a>( - &'a mut self, - table_name: &str, - array_name: &str, - ) -> Result, TomlError> { - let array = self - .get_or_insert_nested_table(table_name)? - .get_mut(array_name) - .and_then(|a| a.as_array_mut()); - Ok(array) } /// Returns a mutable reference to the specified array either in project or @@ -154,14 +159,20 @@ impl ManifestSource { FeatureName::Default => Some("project"), FeatureName::Named(_) => None, }; - let table_name = self.get_nested_toml_table_name(feature_name, None, table); - self.get_or_insert_toml_array(&table_name, array_name) + + let table_name = TableName::new() + .with_prefix(self.table_prefix()) + .with_feature_name(Some(feature_name)) + .with_table(table); + + self.manifest() + .get_or_insert_toml_array(table_name.to_string().as_str(), array_name) } fn as_table_mut(&mut self) -> &mut Table { match self { - ManifestSource::PyProjectToml(document) => document.as_table_mut(), - ManifestSource::PixiToml(document) => document.as_table_mut(), + ManifestSource::PyProjectToml(document) => document.0.as_table_mut(), + ManifestSource::PixiToml(document) => document.0.as_table_mut(), } } @@ -179,11 +190,11 @@ impl ManifestSource { // arrays let array = match self { ManifestSource::PyProjectToml(_) if feature_name.is_default() => { - self.get_toml_array("project", "dependencies")? - } - ManifestSource::PyProjectToml(_) => { - self.get_toml_array("project.optional-dependencies", &feature_name.to_string())? + self.manifest().get_toml_array("project", "dependencies")? } + ManifestSource::PyProjectToml(_) => self + .manifest() + .get_toml_array("project.optional-dependencies", &feature_name.to_string())?, _ => None, }; if let Some(array) = array { @@ -200,7 +211,15 @@ impl ManifestSource { // For both 'pyproject.toml' and 'pixi.toml' manifest, // try and remove the dependency from pixi native tables - self.get_or_insert_toml_table(platform, feature_name, consts::PYPI_DEPENDENCIES) + + 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)); + + self.manifest() + .get_or_insert_nested_table(table_name.to_string().as_str()) .map(|t| t.remove(dep.as_source()))?; Ok(()) } @@ -216,7 +235,14 @@ impl ManifestSource { platform: Option, feature_name: &FeatureName, ) -> Result<(), TomlError> { - self.get_or_insert_toml_table(platform, feature_name, spec_type.name()) + let table_name = TableName::new() + .with_prefix(self.table_prefix()) + .with_feature_name(Some(feature_name)) + .with_platform(platform.as_ref()) + .with_table(Some(spec_type.name())); + + self.manifest() + .get_or_insert_nested_table(table_name.to_string().as_str()) .map(|t| t.remove(dep.as_source()))?; Ok(()) } @@ -232,9 +258,20 @@ impl ManifestSource { platform: Option, feature_name: &FeatureName, ) -> Result<(), TomlError> { - let dependency_table = - self.get_or_insert_toml_table(platform, feature_name, spec_type.name())?; - dependency_table.insert(name.as_normalized(), Item::Value(spec.to_toml_value())); + // 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() + .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(()) } @@ -259,10 +296,12 @@ impl ManifestSource { feature_name, )?; if let FeatureName::Named(name) = feature_name { - self.get_or_insert_toml_array("project.optional-dependencies", name)? + self.manifest() + .get_or_insert_toml_array("project.optional-dependencies", name)? .push(requirement.to_string()) } else { - self.get_or_insert_toml_array("project", "dependencies")? + self.manifest() + .get_or_insert_toml_array("project", "dependencies")? .push(requirement.to_string()) } } @@ -273,7 +312,14 @@ impl ManifestSource { pypi_requirement.set_editable(editable); } - self.get_or_insert_toml_table(platform, feature_name, consts::PYPI_DEPENDENCIES)? + let dependency_table = TableName::new() + .with_prefix(self.table_prefix()) + .with_platform(platform.as_ref()) + .with_feature_name(Some(feature_name)) + .with_table(Some(consts::PYPI_DEPENDENCIES)); + + self.manifest() + .get_or_insert_nested_table(dependency_table.to_string().as_str())? .insert( requirement.name.as_ref(), Item::Value(pypi_requirement.into()), @@ -293,7 +339,14 @@ impl ManifestSource { // Get the task table either from the target platform or the default tasks. // If it does not exist in TOML, consider this ok as we want to remove it // anyways - self.get_or_insert_toml_table(platform, feature_name, "tasks")? + let task_table = TableName::new() + .with_prefix(self.table_prefix()) + .with_platform(platform.as_ref()) + .with_feature_name(Some(feature_name)) + .with_table(Some("tasks")); + + self.manifest() + .get_or_insert_nested_table(task_table.to_string().as_str())? .remove(name); Ok(()) @@ -308,7 +361,14 @@ impl ManifestSource { feature_name: &FeatureName, ) -> Result<(), TomlError> { // Get the task table either from the target platform or the default tasks. - self.get_or_insert_toml_table(platform, feature_name, "tasks")? + let task_table = TableName::new() + .with_prefix(self.table_prefix()) + .with_platform(platform.as_ref()) + .with_feature_name(Some(feature_name)) + .with_table(Some("tasks")); + + self.manifest() + .get_or_insert_nested_table(task_table.to_string().as_str())? .insert(name, task.into()); Ok(()) @@ -341,8 +401,14 @@ impl ManifestSource { ))) }; + let env_table = TableName::new() + .with_prefix(self.table_prefix()) + .with_feature_name(Some(&FeatureName::Default)) + .with_table(Some("environments")); + // Get the environment table - self.get_or_insert_toml_table(None, &FeatureName::Default, "environments")? + self.manifest() + .get_or_insert_nested_table(env_table.to_string().as_str())? .insert(&name.into(), item); Ok(()) @@ -351,8 +417,14 @@ impl ManifestSource { /// Removes an environment from the manifest. Returns `true` if the /// environment was removed. pub fn remove_environment(&mut self, name: &str) -> Result { + let env_table = TableName::new() + .with_prefix(self.table_prefix()) + .with_feature_name(Some(&FeatureName::Default)) + .with_table(Some("environments")); + Ok(self - .get_or_insert_toml_table(None, &FeatureName::Default, "environments")? + .manifest() + .get_or_insert_nested_table(env_table.to_string().as_str())? .remove(name) .is_some()) } @@ -377,7 +449,7 @@ mod tests { use rstest::rstest; use super::*; - use crate::manifest::Manifest; + use crate::manifests::manifest::Manifest; const PROJECT_BOILERPLATE: &str = r#" [project] @@ -419,74 +491,88 @@ mod tests { #[test] fn test_get_or_insert_toml_table() { let mut manifest = Manifest::from_str(Path::new("pixi.toml"), PROJECT_BOILERPLATE).unwrap(); + let task_table = TableName::new() + .with_feature_name(Some(&FeatureName::Default)) + .with_table(Some("tasks")); + let _ = manifest .document - .get_or_insert_toml_table(None, &FeatureName::Default, "tasks") + .manifest() + .get_or_insert_nested_table(task_table.to_string().as_str()) .map(|t| t.set_implicit(false)); + + let linux_task_table = TableName::new() + .with_feature_name(Some(&FeatureName::Default)) + .with_platform(Some(&Platform::Linux64)) + .with_table(Some("tasks")); + let _ = manifest .document - .get_or_insert_toml_table(Some(Platform::Linux64), &FeatureName::Default, "tasks") + .manifest() + .get_or_insert_nested_table(linux_task_table.to_string().as_str()) .map(|t| t.set_implicit(false)); + + let feature_name = FeatureName::Named("test".to_string()); + + let named_feature_task = TableName::new() + .with_feature_name(Some(&feature_name)) + .with_table(Some("tasks")); + let _ = manifest .document - .get_or_insert_toml_table(None, &FeatureName::Named("test".to_string()), "tasks") + .manifest() + .get_or_insert_nested_table(named_feature_task.to_string().as_str()) .map(|t| t.set_implicit(false)); + + let named_feature_linux_task = TableName::new() + .with_feature_name(Some(&feature_name)) + .with_platform(Some(&Platform::Linux64)) + .with_table(Some("tasks")); + let _ = manifest .document - .get_or_insert_toml_table( - Some(Platform::Linux64), - &FeatureName::Named("test".to_string()), - "tasks", - ) + .manifest() + .get_or_insert_nested_table(named_feature_linux_task.to_string().as_str()) .map(|t| t.set_implicit(false)); assert_snapshot!(manifest.document.to_string()); } #[test] fn test_get_nested_toml_table_name() { - let file_contents = r#" -[project] -name = "foo" -version = "0.1.0" -description = "foo description" -channels = [] -platforms = ["linux-64", "win-64"] - - "#; - - let manifest = Manifest::from_str(Path::new("pixi.toml"), file_contents).unwrap(); // Test all different options for the feature name and platform assert_eq!( "dependencies".to_string(), - manifest.document.get_nested_toml_table_name( - &FeatureName::Default, - None, - Some("dependencies") - ) + TableName::new() + .with_feature_name(Some(&FeatureName::Default)) + .with_table(Some("dependencies")) + .to_string() ); + assert_eq!( "target.linux-64.dependencies".to_string(), - manifest.document.get_nested_toml_table_name( - &FeatureName::Default, - Some(Platform::Linux64), - Some("dependencies") - ) + TableName::new() + .with_feature_name(Some(&FeatureName::Default)) + .with_platform(Some(&Platform::Linux64)) + .with_table(Some("dependencies")) + .to_string() ); + + let feature_name = FeatureName::Named("test".to_string()); assert_eq!( "feature.test.dependencies".to_string(), - manifest.document.get_nested_toml_table_name( - &FeatureName::Named("test".to_string()), - None, - Some("dependencies") - ) + TableName::new() + .with_feature_name(Some(&feature_name)) + .with_table(Some("dependencies")) + .to_string() ); + assert_eq!( "feature.test.target.linux-64.dependencies".to_string(), - manifest.document.get_nested_toml_table_name( - &FeatureName::Named("test".to_string()), - Some(Platform::Linux64), - Some("dependencies") - ) + TableName::new() + .with_feature_name(Some(&feature_name)) + .with_platform(Some(&Platform::Linux64)) + .with_table(Some("dependencies")) + .to_string() ); } diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__add_channels.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_channels.snap similarity index 81% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__add_channels.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_channels.snap index 533b8cb1d..3ed74d356 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__add_channels.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_channels.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/manifest.rs -assertion_line: 1479 +source: crates/pixi_manifest/src/manifests/manifest.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__add_dependency.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_dependency.snap similarity index 83% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__add_dependency.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_dependency.snap index 212c5b705..b0f345ae3 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__add_dependency.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_dependency.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/manifest.rs -assertion_line: 1951 +source: crates/pixi_manifest/src/manifests/manifest.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__add_task.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_task.snap similarity index 87% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__add_task.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_task.snap index c18b512c9..d12c2b389 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__add_task.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__add_task.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/manifest.rs -assertion_line: 1830 +source: crates/pixi_manifest/src/manifests/manifest.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_bar.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_bar.snap similarity index 83% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_bar.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_bar.snap index c0ce07037..f1ee1e06a 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_bar.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_bar.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/manifest.rs -assertion_line: 914 +source: crates/pixi_manifest/src/manifests/manifest.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_baz.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_baz.snap similarity index 82% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_baz.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_baz.snap index 7d934b7cf..2dd40e107 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_baz.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_baz.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/manifest.rs -assertion_line: 914 +source: crates/pixi_manifest/src/manifests/manifest.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_fooz.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_fooz.snap similarity index 83% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_fooz.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_fooz.snap index 0c08912d9..ce555acad 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_fooz.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_fooz.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/manifest.rs -assertion_line: 914 +source: crates/pixi_manifest/src/manifests/manifest.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_feature_dep.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_feature_dep.snap similarity index 88% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_feature_dep.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_feature_dep.snap index 9e93971f3..8202c1e1f 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_feature_dep.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_feature_dep.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/manifest.rs -assertion_line: 966 +source: crates/pixi_manifest/src/manifests/manifest.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_feature_target_dep.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_feature_target_dep.snap similarity index 87% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_feature_target_dep.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_feature_target_dep.snap index a85b41e29..671126d00 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_feature_target_dep.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_feature_target_dep.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/manifest.rs -assertion_line: 966 +source: crates/pixi_manifest/src/manifests/manifest.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_jax.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_jax.snap similarity index 88% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_jax.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_jax.snap index 73d0b269a..b9a9ed4d2 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_jax.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_jax.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/manifest.rs -assertion_line: 966 +source: crates/pixi_manifest/src/manifests/manifest.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_requests.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_requests.snap similarity index 88% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_requests.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_requests.snap index 04f20fc3b..ea240a694 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_requests.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_requests.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/manifest.rs -assertion_line: 966 +source: crates/pixi_manifest/src/manifests/manifest.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_xpackage.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_xpackage.snap similarity index 88% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_xpackage.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_xpackage.snap index bcc48fa3d..3449e13ac 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__manifest__tests__test_remove_pypi_xpackage.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__manifest__tests__test_remove_pypi_xpackage.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/manifest.rs -assertion_line: 966 +source: crates/pixi_manifest/src/manifests/manifest.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__get_or_insert_toml_table.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__get_or_insert_toml_table.snap similarity index 81% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__get_or_insert_toml_table.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__get_or_insert_toml_table.snap index 6a04552ef..1c3496b3d 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__get_or_insert_toml_table.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__get_or_insert_toml_table.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/document.rs -assertion_line: 518 +source: crates/pixi_manifest/src/manifests/project.rs expression: manifest.document.to_string() --- [project] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__nameless_to_toml.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__nameless_to_toml.snap similarity index 82% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__nameless_to_toml.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__nameless_to_toml.snap index 4dad7609d..3bbe1c518 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__nameless_to_toml.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__nameless_to_toml.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/document.rs -assertion_line: 408 +source: crates/pixi_manifest/src/manifests/project.rs expression: table --- "rattler >=1" = ">=1" diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_add_environment_pixi.toml.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_add_environment_pixi.toml.snap similarity index 81% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_add_environment_pixi.toml.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_add_environment_pixi.toml.snap index 60ad228df..de74f69c1 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_add_environment_pixi.toml.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_add_environment_pixi.toml.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/document.rs -assertion_line: 604 +source: crates/pixi_manifest/src/manifests/project.rs expression: source.to_string() --- [environments] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_add_environment_pyproject.toml.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_add_environment_pyproject.toml.snap similarity index 82% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_add_environment_pyproject.toml.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_add_environment_pyproject.toml.snap index 2a92c1a2f..2f7e10267 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_add_environment_pyproject.toml.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_add_environment_pyproject.toml.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/document.rs -assertion_line: 604 +source: crates/pixi_manifest/src/manifests/project.rs expression: source.to_string() --- [tool.pixi.environments] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_remove_environment_pixi.toml.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_remove_environment_pixi.toml.snap similarity index 52% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_remove_environment_pixi.toml.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_remove_environment_pixi.toml.snap index ef888e22a..1aab14d74 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_remove_environment_pixi.toml.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_remove_environment_pixi.toml.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/document.rs -assertion_line: 626 +source: crates/pixi_manifest/src/manifests/project.rs expression: source.to_string() --- [environments] diff --git a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_remove_environment_pyproject.toml.snap b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_remove_environment_pyproject.toml.snap similarity index 55% rename from crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_remove_environment_pyproject.toml.snap rename to crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_remove_environment_pyproject.toml.snap index cec4face7..230896be9 100644 --- a/crates/pixi_manifest/src/snapshots/pixi_manifest__document__tests__test_remove_environment_pyproject.toml.snap +++ b/crates/pixi_manifest/src/manifests/snapshots/pixi_manifest__manifests__project__tests__test_remove_environment_pyproject.toml.snap @@ -1,6 +1,5 @@ --- -source: crates/pixi_manifest/src/document.rs -assertion_line: 626 +source: crates/pixi_manifest/src/manifests/project.rs expression: source.to_string() --- [tool.pixi.environments] diff --git a/crates/pixi_manifest/src/pyproject.rs b/crates/pixi_manifest/src/pyproject.rs index 91479e60b..4923d4ebf 100644 --- a/crates/pixi_manifest/src/pyproject.rs +++ b/crates/pixi_manifest/src/pyproject.rs @@ -350,7 +350,8 @@ mod tests { use rattler_conda_types::{ParseStrictness, VersionSpec}; use crate::{ - manifest::Manifest, pypi::PyPiPackageName, DependencyOverwriteBehavior, FeatureName, + manifests::manifest::Manifest, pypi::PyPiPackageName, DependencyOverwriteBehavior, + FeatureName, }; const PYPROJECT_FULL: &str = r#" diff --git a/crates/pixi_manifest/src/target.rs b/crates/pixi_manifest/src/target.rs index 020c770db..04ba84d35 100644 --- a/crates/pixi_manifest/src/target.rs +++ b/crates/pixi_manifest/src/target.rs @@ -553,7 +553,7 @@ mod tests { use insta::assert_snapshot; use itertools::Itertools; - use crate::manifest::Manifest; + use crate::manifests::manifest::Manifest; #[test] fn test_targets_overwrite_order() {