diff --git a/Cargo.lock b/Cargo.lock index d1a32d60d..59f20a1fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2475,7 +2475,6 @@ dependencies = [ "puffin-resolver", "puffin-traits", "puffin-warnings", - "puffin-workspace", "pypi-types", "pyproject-toml", "regex", @@ -2905,20 +2904,6 @@ dependencies = [ "rustc-hash", ] -[[package]] -name = "puffin-workspace" -version = "0.0.1" -dependencies = [ - "fs-err", - "pep440_rs", - "pep508_rs", - "puffin-normalize", - "pyproject-toml", - "serde", - "thiserror", - "toml_edit", -] - [[package]] name = "pyo3" version = "0.20.2" diff --git a/Cargo.toml b/Cargo.toml index 7c5538f25..00b309429 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -95,7 +95,6 @@ tokio = { version = "1.35.1", features = ["rt-multi-thread"] } tokio-tar = { version = "0.3.1" } tokio-util = { version = "0.7.10", features = ["compat"] } toml = { version = "0.8.8" } -toml_edit = { version = "0.21.0" } tracing = { version = "0.1.40" } tracing-durations-export = { version = "0.2.0", features = ["plot"] } tracing-indicatif = { version = "0.3.6" } diff --git a/crates/puffin-workspace/Cargo.toml b/crates/puffin-workspace/Cargo.toml deleted file mode 100644 index 39266f873..000000000 --- a/crates/puffin-workspace/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "puffin-workspace" -version = "0.0.1" -edition = { workspace = true } -rust-version = { workspace = true } -homepage = { workspace = true } -documentation = { workspace = true } -repository = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[lints] -workspace = true - -[dependencies] -pep440_rs = { path = "../pep440-rs" } -pep508_rs = { path = "../pep508-rs" } -puffin-normalize = { path = "../puffin-normalize" } - -fs-err = { workspace = true } -pyproject-toml = { workspace = true } -serde = { workspace = true } -thiserror = { workspace = true } -toml_edit = { workspace = true, features = ["serde"] } diff --git a/crates/puffin-workspace/src/error.rs b/crates/puffin-workspace/src/error.rs deleted file mode 100644 index 3e46d6891..000000000 --- a/crates/puffin-workspace/src/error.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::io; -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum WorkspaceError { - #[error(transparent)] - IO(#[from] io::Error), - - #[error(transparent)] - InvalidToml(#[from] toml_edit::TomlError), - - #[error(transparent)] - InvalidPyproject(#[from] toml_edit::de::Error), - - #[error(transparent)] - InvalidRequirement(#[from] pep508_rs::Pep508Error), - - #[error("no `[project]` table found in `pyproject.toml`")] - MissingProjectTable, - - #[error("no `[project.dependencies]` array found in `pyproject.toml`")] - MissingProjectDependenciesArray, - - #[error("unable to find package: `{0}`")] - MissingPackage(String), -} diff --git a/crates/puffin-workspace/src/lib.rs b/crates/puffin-workspace/src/lib.rs deleted file mode 100644 index 249d58a51..000000000 --- a/crates/puffin-workspace/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::path::{Path, PathBuf}; - -pub use error::WorkspaceError; -pub use verbatim::VerbatimRequirement; -pub use workspace::Workspace; - -mod error; -mod toml; -mod verbatim; -mod workspace; - -/// Find the closest `pyproject.toml` file to the given path. -pub fn find_pyproject_toml(path: impl AsRef) -> Option { - for directory in path.as_ref().ancestors() { - let pyproject_toml = directory.join("pyproject.toml"); - if pyproject_toml.is_file() { - return Some(pyproject_toml); - } - } - None -} diff --git a/crates/puffin-workspace/src/toml.rs b/crates/puffin-workspace/src/toml.rs deleted file mode 100644 index 405c98cf7..000000000 --- a/crates/puffin-workspace/src/toml.rs +++ /dev/null @@ -1,46 +0,0 @@ -/// Reformat a TOML array to use multiline format. -pub(crate) fn format_multiline_array(dependencies: &mut toml_edit::Array) { - if dependencies.is_empty() { - dependencies.set_trailing(""); - return; - } - - for item in dependencies.iter_mut() { - let decor = item.decor_mut(); - let mut prefix = String::new(); - for comment in find_comments(decor.prefix()).chain(find_comments(decor.suffix())) { - prefix.push_str("\n "); - prefix.push_str(comment); - } - prefix.push_str("\n "); - decor.set_prefix(prefix); - decor.set_suffix(""); - } - - dependencies.set_trailing(&{ - let mut comments = find_comments(Some(dependencies.trailing())).peekable(); - let mut value = String::new(); - if comments.peek().is_some() { - for comment in comments { - value.push_str("\n "); - value.push_str(comment); - } - } - value.push('\n'); - value - }); - - dependencies.set_trailing_comma(true); -} - -/// Return an iterator over the comments in a raw string. -fn find_comments(raw_string: Option<&toml_edit::RawString>) -> impl Iterator { - raw_string - .and_then(toml_edit::RawString::as_str) - .unwrap_or("") - .lines() - .filter_map(|line| { - let line = line.trim(); - line.starts_with('#').then_some(line) - }) -} diff --git a/crates/puffin-workspace/src/verbatim.rs b/crates/puffin-workspace/src/verbatim.rs deleted file mode 100644 index ac1e07897..000000000 --- a/crates/puffin-workspace/src/verbatim.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::str::FromStr; - -use pep508_rs::Requirement; - -#[derive(Debug)] -pub struct VerbatimRequirement<'a> { - /// The name of the requirement as provided by the user. - pub given_name: &'a str, - /// The normalized requirement. - pub requirement: Requirement, -} - -impl<'a> TryFrom<&'a str> for VerbatimRequirement<'a> { - type Error = pep508_rs::Pep508Error; - - fn try_from(s: &'a str) -> Result { - let requirement = Requirement::from_str(s)?; - Ok(Self { - given_name: s, - requirement, - }) - } -} diff --git a/crates/puffin-workspace/src/workspace.rs b/crates/puffin-workspace/src/workspace.rs deleted file mode 100644 index 48098b4e3..000000000 --- a/crates/puffin-workspace/src/workspace.rs +++ /dev/null @@ -1,158 +0,0 @@ -use std::io; -use std::path::Path; -use std::str::FromStr; - -use fs_err as fs; -use pyproject_toml::PyProjectToml; -use toml_edit::Document; - -use pep508_rs::Requirement; -use puffin_normalize::PackageName; - -use crate::toml::format_multiline_array; -use crate::verbatim::VerbatimRequirement; -use crate::WorkspaceError; - -#[derive(Debug)] -pub struct Workspace { - /// The parsed `pyproject.toml`. - #[allow(unused)] - pyproject_toml: PyProjectToml, - - /// The raw document. - document: Document, -} - -impl Workspace { - /// Add a dependency to the workspace. - pub fn add_dependency(&mut self, requirement: &VerbatimRequirement<'_>) { - let Some(project) = self - .document - .get_mut("project") - .map(|project| project.as_table_mut().unwrap()) - else { - // No `project` table. - let mut dependencies = toml_edit::Array::new(); - dependencies.push(requirement.given_name); - format_multiline_array(&mut dependencies); - - let mut project = toml_edit::Table::new(); - project.insert( - "dependencies", - toml_edit::Item::Value(toml_edit::Value::Array(dependencies)), - ); - - self.document - .insert("project", toml_edit::Item::Table(project)); - - return; - }; - - let Some(dependencies) = project - .get_mut("dependencies") - .map(|dependencies| dependencies.as_array_mut().unwrap()) - else { - // No `dependencies` array. - let mut dependencies = toml_edit::Array::new(); - dependencies.push(requirement.given_name); - format_multiline_array(&mut dependencies); - - project.insert( - "dependencies", - toml_edit::Item::Value(toml_edit::Value::Array(dependencies)), - ); - return; - }; - - let index = dependencies.iter().position(|item| { - let Some(item) = item.as_str() else { - return false; - }; - - let Ok(existing) = Requirement::from_str(item) else { - return false; - }; - - requirement.requirement.name == existing.name - }); - - if let Some(index) = index { - dependencies.replace(index, requirement.given_name); - } else { - dependencies.push(requirement.given_name); - } - - format_multiline_array(dependencies); - } - - /// Remove a dependency from the workspace. - pub fn remove_dependency(&mut self, name: &PackageName) -> Result<(), WorkspaceError> { - let Some(project) = self - .document - .get_mut("project") - .map(|project| project.as_table_mut().unwrap()) - else { - return Err(WorkspaceError::MissingProjectTable); - }; - - let Some(dependencies) = project - .get_mut("dependencies") - .map(|dependencies| dependencies.as_array_mut().unwrap()) - else { - return Err(WorkspaceError::MissingProjectDependenciesArray); - }; - - let index = dependencies.iter().position(|item| { - let Some(item) = item.as_str() else { - return false; - }; - - let Ok(existing) = Requirement::from_str(item) else { - return false; - }; - - name == &existing.name - }); - - let Some(index) = index else { - return Err(WorkspaceError::MissingPackage(name.to_string())); - }; - - dependencies.remove(index); - format_multiline_array(dependencies); - - Ok(()) - } - - /// Save the workspace to disk. - pub fn save(&self, path: impl AsRef) -> Result<(), WorkspaceError> { - let file = fs::File::create(path.as_ref())?; - self.write(file) - } - - /// Write the workspace to a writer. - fn write(&self, mut writer: impl io::Write) -> Result<(), WorkspaceError> { - writer.write_all(self.document.to_string().as_bytes())?; - Ok(()) - } -} - -impl TryFrom<&Path> for Workspace { - type Error = WorkspaceError; - - fn try_from(path: &Path) -> Result { - // Read the `pyproject.toml` from disk. - let contents = fs::read_to_string(path)?; - - // Parse the `pyproject.toml` file. - let pyproject_toml = toml_edit::de::from_str::(&contents)?; - - // Parse the raw document. - let document = contents.parse::()?; - - Ok(Self { - pyproject_toml, - document, - }) - } -} diff --git a/crates/puffin/Cargo.toml b/crates/puffin/Cargo.toml index 448c91759..427420406 100644 --- a/crates/puffin/Cargo.toml +++ b/crates/puffin/Cargo.toml @@ -34,7 +34,6 @@ puffin-normalize = { path = "../puffin-normalize" } puffin-resolver = { path = "../puffin-resolver", features = ["clap"] } puffin-traits = { path = "../puffin-traits" } puffin-warnings = { path = "../puffin-warnings" } -puffin-workspace = { path = "../puffin-workspace" } pypi-types = { path = "../pypi-types" } requirements-txt = { path = "../requirements-txt" } diff --git a/crates/puffin/src/commands/add.rs b/crates/puffin/src/commands/add.rs deleted file mode 100644 index 12ae3b5f0..000000000 --- a/crates/puffin/src/commands/add.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::path::PathBuf; - -use anyhow::Result; -use miette::{Diagnostic, IntoDiagnostic}; -use thiserror::Error; -use tracing::info; - -use puffin_workspace::WorkspaceError; - -use crate::commands::ExitStatus; -use crate::printer::Printer; - -/// Add a dependency to the workspace. -#[allow(clippy::unnecessary_wraps)] -pub(crate) fn add(name: &str, _printer: Printer) -> Result { - match add_impl(name) { - Ok(status) => Ok(status), - Err(err) => { - #[allow(clippy::print_stderr)] - { - eprint!("{err:?}"); - } - Ok(ExitStatus::Failure) - } - } -} - -#[derive(Error, Debug, Diagnostic)] -enum AddError { - #[error( - "Could not find a `pyproject.toml` file in the current directory or any of its parents" - )] - #[diagnostic(code(puffin::add::workspace_not_found))] - WorkspaceNotFound, - - #[error("Failed to parse requirement: `{0}`")] - #[diagnostic(code(puffin::add::invalid_requirement))] - InvalidRequirement(String, #[source] pep508_rs::Pep508Error), - - #[error("Failed to parse `pyproject.toml` at: `{0}`")] - #[diagnostic(code(puffin::add::parse))] - ParseError(PathBuf, #[source] WorkspaceError), - - #[error("Failed to write `pyproject.toml` to: `{0}`")] - #[diagnostic(code(puffin::add::write))] - WriteError(PathBuf, #[source] WorkspaceError), -} - -fn add_impl(name: &str) -> miette::Result { - let requirement = puffin_workspace::VerbatimRequirement::try_from(name) - .map_err(|err| AddError::InvalidRequirement(name.to_string(), err))?; - - // Locate the workspace. - let cwd = std::env::current_dir().into_diagnostic()?; - let Some(workspace_root) = puffin_workspace::find_pyproject_toml(cwd) else { - return Err(AddError::WorkspaceNotFound.into()); - }; - - info!("Found workspace at: {}", workspace_root.display()); - - // Parse the manifest. - let mut manifest = puffin_workspace::Workspace::try_from(workspace_root.as_path()) - .map_err(|err| AddError::ParseError(workspace_root.clone(), err))?; - - // Add the dependency. - manifest.add_dependency(&requirement); - - // Write the manifest back to disk. - manifest - .save(&workspace_root) - .map_err(|err| AddError::WriteError(workspace_root.clone(), err))?; - - Ok(ExitStatus::Success) -} diff --git a/crates/puffin/src/commands/mod.rs b/crates/puffin/src/commands/mod.rs index 67e65c345..37f1814f3 100644 --- a/crates/puffin/src/commands/mod.rs +++ b/crates/puffin/src/commands/mod.rs @@ -1,7 +1,6 @@ use std::process::ExitCode; use std::time::Duration; -pub(crate) use add::add; pub(crate) use clean::clean; use distribution_types::InstalledMetadata; pub(crate) use freeze::freeze; @@ -9,17 +8,14 @@ pub(crate) use pip_compile::{extra_name_with_clap_error, pip_compile, Upgrade}; pub(crate) use pip_install::pip_install; pub(crate) use pip_sync::pip_sync; pub(crate) use pip_uninstall::pip_uninstall; -pub(crate) use remove::remove; pub(crate) use venv::venv; -mod add; mod clean; mod freeze; mod pip_compile; mod pip_install; mod pip_sync; mod pip_uninstall; -mod remove; mod reporters; mod venv; diff --git a/crates/puffin/src/commands/remove.rs b/crates/puffin/src/commands/remove.rs deleted file mode 100644 index 3a227fe72..000000000 --- a/crates/puffin/src/commands/remove.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::path::PathBuf; - -use anyhow::Result; -use miette::{Diagnostic, IntoDiagnostic}; -use thiserror::Error; -use tracing::info; - -use puffin_normalize::PackageName; -use puffin_workspace::WorkspaceError; - -use crate::commands::ExitStatus; -use crate::printer::Printer; - -/// Remove a dependency from the workspace. -#[allow(clippy::unnecessary_wraps)] -pub(crate) fn remove(name: &PackageName, _printer: Printer) -> Result { - match remove_impl(name) { - Ok(status) => Ok(status), - Err(err) => { - #[allow(clippy::print_stderr)] - { - eprint!("{err:?}"); - } - Ok(ExitStatus::Failure) - } - } -} - -#[derive(Error, Debug, Diagnostic)] -enum RemoveError { - #[error( - "Could not find a `pyproject.toml` file in the current directory or any of its parents" - )] - #[diagnostic(code(puffin::remove::workspace_not_found))] - WorkspaceNotFound, - - #[error("Failed to parse `pyproject.toml` at: `{0}`")] - #[diagnostic(code(puffin::remove::parse))] - ParseError(PathBuf, #[source] WorkspaceError), - - #[error("Failed to write `pyproject.toml` to: `{0}`")] - #[diagnostic(code(puffin::remove::write))] - WriteError(PathBuf, #[source] WorkspaceError), - - #[error("Failed to remove `{0}` from `pyproject.toml`")] - #[diagnostic(code(puffin::remove::parse))] - RemovalError(String, #[source] WorkspaceError), -} - -fn remove_impl(name: &PackageName) -> miette::Result { - // Locate the workspace. - let cwd = std::env::current_dir().into_diagnostic()?; - let Some(workspace_root) = puffin_workspace::find_pyproject_toml(cwd) else { - return Err(RemoveError::WorkspaceNotFound.into()); - }; - - info!("Found workspace at: {}", workspace_root.display()); - - // Parse the manifest. - let mut manifest = puffin_workspace::Workspace::try_from(workspace_root.as_path()) - .map_err(|err| RemoveError::ParseError(workspace_root.clone(), err))?; - - // Remove the dependency. - manifest - .remove_dependency(name) - .map_err(|err| RemoveError::RemovalError(name.to_string(), err))?; - - // Write the manifest back to disk. - manifest - .save(&workspace_root) - .map_err(|err| RemoveError::WriteError(workspace_root.clone(), err))?; - - Ok(ExitStatus::Success) -} diff --git a/crates/puffin/src/main.rs b/crates/puffin/src/main.rs index 0fca998e2..63a172492 100644 --- a/crates/puffin/src/main.rs +++ b/crates/puffin/src/main.rs @@ -110,12 +110,6 @@ enum Commands { Venv(VenvArgs), /// Clear the cache. Clean(CleanArgs), - /// Add a dependency to the workspace. - #[clap(hide = true)] - Add(AddArgs), - /// Remove a dependency from the workspace. - #[clap(hide = true)] - Remove(RemoveArgs), } #[derive(Args)] @@ -878,8 +872,6 @@ async fn run() -> Result { ) .await } - Commands::Add(args) => commands::add(&args.name, printer), - Commands::Remove(args) => commands::remove(&args.name, printer), } } diff --git a/crates/puffin/tests/add.rs b/crates/puffin/tests/add.rs deleted file mode 100644 index c29c3b2a9..000000000 --- a/crates/puffin/tests/add.rs +++ /dev/null @@ -1,168 +0,0 @@ -use std::process::Command; - -use anyhow::Result; -use assert_fs::prelude::*; - -use crate::common::{get_bin, puffin_snapshot}; - -mod common; - -#[test] -fn missing_pyproject_toml() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - - puffin_snapshot!(Command::new(get_bin()) - .arg("add") - .arg("flask") - .current_dir(&temp_dir), @r###" - success: false - exit_code: 1 - ----- stdout ----- - - ----- stderr ----- - puffin::add::workspace_not_found - - × Could not find a `pyproject.toml` file in the current directory or any of - │ its parents - "###); - - pyproject_toml.assert(predicates::path::missing()); - - Ok(()) -} - -#[test] -fn missing_project_table() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - pyproject_toml.touch()?; - - puffin_snapshot!(Command::new(get_bin()) - .arg("add") - .arg("flask") - .current_dir(&temp_dir), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - "###); - - pyproject_toml.assert( - r#"[project] -dependencies = [ - "flask", -] -"#, - ); - - Ok(()) -} - -#[test] -fn missing_dependencies_array() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - pyproject_toml.touch()?; - pyproject_toml.write_str( - r#"[project] -name = "project" -"#, - )?; - - puffin_snapshot!(Command::new(get_bin()) - .arg("add") - .arg("flask") - .current_dir(&temp_dir), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - "###); - - pyproject_toml.assert( - r#"[project] -name = "project" -dependencies = [ - "flask", -] -"#, - ); - - Ok(()) -} - -#[test] -fn replace_dependency() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - pyproject_toml.touch()?; - pyproject_toml.write_str( - r#"[project] -name = "project" -dependencies = [ - "flask==1.0.0", -] -"#, - )?; - - puffin_snapshot!(Command::new(get_bin()) - .arg("add") - .arg("flask==2.0.0") - .current_dir(&temp_dir), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - "###); - - pyproject_toml.assert( - r#"[project] -name = "project" -dependencies = [ - "flask==2.0.0", -] -"#, - ); - - Ok(()) -} - -#[test] -fn reformat_array() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - pyproject_toml.touch()?; - pyproject_toml.write_str( - r#"[project] -name = "project" -dependencies = ["flask==1.0.0"] -"#, - )?; - - puffin_snapshot!(Command::new(get_bin()) - .arg("add") - .arg("requests") - .current_dir(&temp_dir), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - "###); - - pyproject_toml.assert( - r#"[project] -name = "project" -dependencies = [ - "flask==1.0.0", - "requests", -] -"#, - ); - - Ok(()) -} diff --git a/crates/puffin/tests/remove.rs b/crates/puffin/tests/remove.rs deleted file mode 100644 index 840161a62..000000000 --- a/crates/puffin/tests/remove.rs +++ /dev/null @@ -1,281 +0,0 @@ -use std::process::Command; - -use anyhow::Result; -use assert_fs::prelude::*; - -use crate::common::{get_bin, puffin_snapshot}; - -mod common; - -#[test] -fn missing_pyproject_toml() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - - puffin_snapshot!(Command::new(get_bin()) - .arg("remove") - .arg("flask") - .current_dir(&temp_dir), @r###" - success: false - exit_code: 1 - ----- stdout ----- - - ----- stderr ----- - puffin::remove::workspace_not_found - - × Could not find a `pyproject.toml` file in the current directory or any of - │ its parents - "###); - - pyproject_toml.assert(predicates::path::missing()); - - Ok(()) -} - -#[test] -fn missing_project_table() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - pyproject_toml.touch()?; - - puffin_snapshot!(Command::new(get_bin()) - .arg("remove") - .arg("flask") - .current_dir(&temp_dir), @r###" - success: false - exit_code: 1 - ----- stdout ----- - - ----- stderr ----- - puffin::remove::parse - - × Failed to remove `flask` from `pyproject.toml` - ╰─▶ no `[project]` table found in `pyproject.toml` - "###); - - pyproject_toml.assert(predicates::str::is_empty()); - - Ok(()) -} - -#[test] -fn missing_dependencies_array() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - pyproject_toml.touch()?; - pyproject_toml.write_str( - r#"[project] -name = "project" -"#, - )?; - - puffin_snapshot!(Command::new(get_bin()) - .arg("remove") - .arg("flask") - .current_dir(&temp_dir), @r###" - success: false - exit_code: 1 - ----- stdout ----- - - ----- stderr ----- - puffin::remove::parse - - × Failed to remove `flask` from `pyproject.toml` - ╰─▶ no `[project.dependencies]` array found in `pyproject.toml` - "###); - - pyproject_toml.assert( - r#"[project] -name = "project" -"#, - ); - - Ok(()) -} - -#[test] -fn missing_dependency() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - pyproject_toml.touch()?; - pyproject_toml.write_str( - r#"[project] -name = "project" -dependencies = [ - "flask==1.0.0", -] -"#, - )?; - - puffin_snapshot!(Command::new(get_bin()) - .arg("remove") - .arg("requests") - .current_dir(&temp_dir), @r###" - success: false - exit_code: 1 - ----- stdout ----- - - ----- stderr ----- - puffin::remove::parse - - × Failed to remove `requests` from `pyproject.toml` - ╰─▶ unable to find package: `requests` - "###); - - pyproject_toml.assert( - r#"[project] -name = "project" -dependencies = [ - "flask==1.0.0", -] -"#, - ); - - Ok(()) -} - -#[test] -fn remove_dependency() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - pyproject_toml.touch()?; - pyproject_toml.write_str( - r#"[project] -name = "project" -dependencies = [ - "flask==1.0.0", - "requests", -] -"#, - )?; - - puffin_snapshot!(Command::new(get_bin()) - .arg("remove") - .arg("flask") - .current_dir(&temp_dir), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - "###); - - pyproject_toml.assert( - r#"[project] -name = "project" -dependencies = [ - "requests", -] -"#, - ); - - Ok(()) -} - -#[test] -fn empty_array() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - pyproject_toml.touch()?; - pyproject_toml.write_str( - r#"[project] -name = "project" -dependencies = [ - "requests", -] -"#, - )?; - - puffin_snapshot!(Command::new(get_bin()) - .arg("remove") - .arg("requests") - .current_dir(&temp_dir), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - "###); - - pyproject_toml.assert( - r#"[project] -name = "project" -dependencies = [] -"#, - ); - - Ok(()) -} - -#[test] -fn normalize_name() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - pyproject_toml.touch()?; - pyproject_toml.write_str( - r#"[project] -name = "project" -dependencies = [ - "flask==1.0.0", - "requests", -] -"#, - )?; - - puffin_snapshot!(Command::new(get_bin()) - .arg("remove") - .arg("Flask") - .current_dir(&temp_dir), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - "###); - - pyproject_toml.assert( - r#"[project] -name = "project" -dependencies = [ - "requests", -] -"#, - ); - - Ok(()) -} - -#[test] -fn reformat_array() -> Result<()> { - let temp_dir = assert_fs::TempDir::new()?; - let pyproject_toml = temp_dir.child("pyproject.toml"); - pyproject_toml.touch()?; - pyproject_toml.write_str( - r#"[project] -name = "project" -dependencies = ["flask==1.0.0", "requests"] -"#, - )?; - - puffin_snapshot!(Command::new(get_bin()) - .arg("remove") - .arg("requests") - .current_dir(&temp_dir), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - "###); - - pyproject_toml.assert( - r#"[project] -name = "project" -dependencies = [ - "flask==1.0.0", -] -"#, - ); - - Ok(()) -}