Move venv command to miette (#162)

This commit is contained in:
Charlie Marsh 2023-10-22 00:17:16 -04:00 committed by GitHub
parent 370771b28c
commit 9bcc7fe77a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 62 additions and 19 deletions

View file

@ -38,11 +38,11 @@ enum AddError {
InvalidRequirement(String, #[source] pep508_rs::Pep508Error),
#[error("Failed to parse `pyproject.toml` at: `{0}`")]
#[diagnostic(code(puffin::add::parse_error))]
#[diagnostic(code(puffin::add::parse))]
ParseError(PathBuf, #[source] WorkspaceError),
#[error("Failed to write `pyproject.toml` to: `{0}`")]
#[diagnostic(code(puffin::add::write_error))]
#[diagnostic(code(puffin::add::write))]
WriteError(PathBuf, #[source] WorkspaceError),
}

View file

@ -34,15 +34,15 @@ enum RemoveError {
WorkspaceNotFound,
#[error("Failed to parse `pyproject.toml` at: `{0}`")]
#[diagnostic(code(puffin::remove::parse_error))]
#[diagnostic(code(puffin::remove::parse))]
ParseError(PathBuf, #[source] WorkspaceError),
#[error("Failed to write `pyproject.toml` to: `{0}`")]
#[diagnostic(code(puffin::remove::write_error))]
#[diagnostic(code(puffin::remove::write))]
WriteError(PathBuf, #[source] WorkspaceError),
#[error("Failed to remove `{0}` from `pyproject.toml`")]
#[diagnostic(code(puffin::remove::parse_error))]
#[diagnostic(code(puffin::remove::parse))]
RemovalError(String, #[source] WorkspaceError),
}

View file

@ -3,43 +3,86 @@ use std::path::Path;
use anyhow::Result;
use colored::Colorize;
use fs_err::tokio as fs;
use fs_err as fs;
use miette::{Diagnostic, IntoDiagnostic};
use thiserror::Error;
use crate::commands::ExitStatus;
use crate::printer::Printer;
/// Create a virtual environment.
pub(crate) async fn venv(
#[allow(clippy::unnecessary_wraps)]
pub(crate) fn venv(
path: &Path,
base_python: Option<&Path>,
printer: Printer,
) -> Result<ExitStatus> {
match venv_impl(path, base_python, printer) {
Ok(status) => Ok(status),
Err(err) => {
#[allow(clippy::print_stderr)]
{
eprint!("{err:?}");
}
Ok(ExitStatus::Failure)
}
}
}
#[derive(Error, Debug, Diagnostic)]
enum VenvError {
#[error("Unable to find a Python interpreter")]
#[diagnostic(code(puffin::venv::python_not_found))]
PythonNotFound,
#[error("Failed to extract Python interpreter info")]
#[diagnostic(code(puffin::venv::interpreter))]
InterpreterError(#[source] gourgeist::Error),
#[error("Failed to create virtual environment")]
#[diagnostic(code(puffin::venv::creation))]
CreationError(#[source] gourgeist::Error),
}
/// Create a virtual environment.
fn venv_impl(
path: &Path,
base_python: Option<&Path>,
mut printer: Printer,
) -> Result<ExitStatus> {
) -> miette::Result<ExitStatus> {
// Locate the Python interpreter.
// TODO(charlie): Look at how Maturin discovers and ranks all the available Python interpreters.
let base_python = if let Some(base_python) = base_python {
base_python.to_path_buf()
} else {
which::which("python3").or_else(|_| which::which("python"))?
which::which("python3")
.or_else(|_| which::which("python"))
.map_err(|_| VenvError::PythonNotFound)?
};
let interpreter_info = gourgeist::get_interpreter_info(&base_python)?;
let interpreter_info =
gourgeist::get_interpreter_info(&base_python).map_err(VenvError::InterpreterError)?;
writeln!(
printer,
"Using Python interpreter: {}",
format!("{}", base_python.display()).cyan()
)?;
)
.into_diagnostic()?;
// If the path already exists, remove it.
fs::remove_file(path).await.ok();
fs::remove_dir_all(path).await.ok();
fs::remove_file(path).ok();
fs::remove_dir_all(path).ok();
writeln!(
printer,
"Creating virtual environment at: {}",
format!("{}", path.display()).cyan()
)?;
)
.into_diagnostic()?;
// Create the virtual environment.
gourgeist::create_venv(path, &base_python, &interpreter_info, true)?;
gourgeist::create_venv(path, &base_python, &interpreter_info, true)
.map_err(VenvError::CreationError)?;
Ok(ExitStatus::Success)
}

View file

@ -187,7 +187,7 @@ async fn main() -> ExitCode {
}
Commands::Clean => commands::clean(cache_dir, printer),
Commands::Freeze => commands::freeze(cache_dir, printer),
Commands::Venv(args) => commands::venv(&args.name, args.python.as_deref(), printer).await,
Commands::Venv(args) => commands::venv(&args.name, args.python.as_deref(), printer),
Commands::Add(args) => commands::add(&args.name, printer),
Commands::Remove(args) => commands::remove(&args.name, printer),
};

View file

@ -11,7 +11,7 @@ exit_code: 1
----- stdout -----
----- stderr -----
puffin::remove::parse_error
puffin::remove::parse
× Failed to remove `flask` from `pyproject.toml`
╰─▶ no `[project.dependencies]` array found in `pyproject.toml`

View file

@ -11,7 +11,7 @@ exit_code: 1
----- stdout -----
----- stderr -----
puffin::remove::parse_error
puffin::remove::parse
× Failed to remove `requests` from `pyproject.toml`
╰─▶ unable to find package: `requests`

View file

@ -11,7 +11,7 @@ exit_code: 1
----- stdout -----
----- stderr -----
puffin::remove::parse_error
puffin::remove::parse
× Failed to remove `flask` from `pyproject.toml`
╰─▶ no `[project]` table found in `pyproject.toml`