Skip to content

Commit

Permalink
Add a custom suggestion for dotenv
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Sep 30, 2024
1 parent 66d7ec5 commit c7ca1a2
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 14 deletions.
12 changes: 11 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ uv-cache-info = { path = "crates/uv-cache-info" }
uv-cli = { path = "crates/uv-cli" }
uv-client = { path = "crates/uv-client" }
uv-configuration = { path = "crates/uv-configuration" }
uv-console = { path = "crates/uv-console" }
uv-dispatch = { path = "crates/uv-dispatch" }
uv-distribution = { path = "crates/uv-distribution" }
uv-extract = { path = "crates/uv-extract" }
Expand Down
12 changes: 12 additions & 0 deletions crates/uv-console/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "uv-console"
version = "0.0.1"
edition = "2021"
description = "Utilities for interacting with the terminal"

[lints]
workspace = true

[dependencies]
ctrlc = { workspace = true }
console = { workspace = true }
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use anyhow::Result;
use console::{style, Key, Term};

/// Prompt the user for confirmation in the given [`Term`].
///
/// This is a slimmed-down version of `dialoguer::Confirm`, with the post-confirmation report
/// enabled.
pub(crate) fn confirm(message: &str, term: &Term, default: bool) -> Result<bool> {
pub fn confirm(message: &str, term: &Term, default: bool) -> std::io::Result<bool> {
// Set the Ctrl-C handler to exit the process.
let result = ctrlc::set_handler(move || {
let term = Term::stderr();
Expand All @@ -26,7 +25,7 @@ pub(crate) fn confirm(message: &str, term: &Term, default: bool) -> Result<bool>
// If multiple handlers were set, we assume that the existing handler is our
// confirmation handler, and continue.
}
Err(e) => return Err(e.into()),
Err(err) => return Err(std::io::Error::new(std::io::ErrorKind::Other, err)),
}

let prompt = format!(
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-requirements/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pypi-types = { workspace = true }
requirements-txt = { workspace = true, features = ["http"] }
uv-client = { workspace = true }
uv-configuration = { workspace = true }
uv-console = { workspace = true }
uv-distribution = { workspace = true }
uv-fs = { workspace = true }
uv-git = { workspace = true }
Expand All @@ -33,7 +34,6 @@ uv-workspace = { workspace = true }
anyhow = { workspace = true }
configparser = { workspace = true }
console = { workspace = true }
ctrlc = { workspace = true }
fs-err = { workspace = true, features = ["tokio"] }
futures = { workspace = true }
rustc-hash = { workspace = true }
Expand Down
1 change: 0 additions & 1 deletion crates/uv-requirements/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ pub use crate::sources::*;
pub use crate::specification::*;
pub use crate::unnamed::*;

mod confirm;
mod lookahead;
mod source_tree;
mod sources;
Expand Down
6 changes: 2 additions & 4 deletions crates/uv-requirements/src/sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ use console::Term;
use uv_fs::Simplified;
use uv_warnings::warn_user;

use crate::confirm;

#[derive(Debug, Clone)]
pub enum RequirementsSource {
/// A package was provided on the command line (e.g., `pip install flask`).
Expand Down Expand Up @@ -96,7 +94,7 @@ impl RequirementsSource {
let prompt = format!(
"`{name}` looks like a local requirements file but was passed as a package name. Did you mean `-r {name}`?"
);
let confirmation = confirm::confirm(&prompt, &term, true).unwrap();
let confirmation = uv_console::confirm(&prompt, &term, true).unwrap();
if confirmation {
return Self::from_requirements_file(name.into());
}
Expand All @@ -113,7 +111,7 @@ impl RequirementsSource {
let prompt = format!(
"`{name}` looks like a local metadata file but was passed as a package name. Did you mean `-r {name}`?"
);
let confirmation = confirm::confirm(&prompt, &term, true).unwrap();
let confirmation = uv_console::confirm(&prompt, &term, true).unwrap();
if confirmation {
return Self::from_requirements_file(name.into());
}
Expand Down
2 changes: 2 additions & 0 deletions crates/uv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ uv-cache-info = { workspace = true }
uv-cli = { workspace = true }
uv-client = { workspace = true }
uv-configuration = { workspace = true }
uv-console = { workspace = true }
uv-dispatch = { workspace = true }
uv-distribution = { workspace = true }
uv-extract = { workspace = true }
Expand Down Expand Up @@ -57,6 +58,7 @@ axoupdater = { workspace = true, features = [
"tokio",
], optional = true }
clap = { workspace = true, features = ["derive", "string", "wrap_help"] }
console = { workspace = true }
ctrlc = { workspace = true }
flate2 = { workspace = true, default-features = false }
fs-err = { workspace = true, features = ["tokio"] }
Expand Down
40 changes: 36 additions & 4 deletions crates/uv/src/commands/project/add.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::collections::hash_map::Entry;
use std::fmt::Write;
use std::path::{Path, PathBuf};

use anyhow::{bail, Context, Result};
use console::Term;
use itertools::Itertools;
use owo_colors::OwoColorize;
use rustc_hash::{FxBuildHasher, FxHashMap};
use std::collections::hash_map::Entry;
use std::fmt::Write;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::LazyLock;
use tracing::debug;

use cache_key::RepositoryUrl;
Expand Down Expand Up @@ -48,6 +50,19 @@ use crate::commands::{pip, project, ExitStatus, SharedState};
use crate::printer::Printer;
use crate::settings::{ResolverInstallerSettings, ResolverInstallerSettingsRef};

static CORRECTIONS: LazyLock<FxHashMap<PackageName, PackageName>> = LazyLock::new(|| {
FxHashMap::from_iter(
[("dotenv", "python-dotenv"), ("sklearn", "scikit-learn")]
.iter()
.map(|(k, v)| {
(
PackageName::from_str(k).unwrap(),
PackageName::from_str(v).unwrap(),
)
}),
)
});

/// Add one or more packages to the project requirements.
#[allow(clippy::fn_params_excessive_bools)]
pub(crate) async fn add(
Expand Down Expand Up @@ -371,6 +386,23 @@ pub(crate) async fn add(
}?;
let mut edits = Vec::<DependencyEdit>::with_capacity(requirements.len());
for mut requirement in requirements {
// If the user requested a package that is often confused for another package, prompt them.
if let Some(correction) = CORRECTIONS.get(&requirement.name) {
let term = Term::stderr();
if term.is_term() {
let prompt = format!(
"`{}` is often confused for `{}`. Did you mean `{}`?",
requirement.name.cyan(),
correction.cyan(),
format!("uv add {}", correction).green()
);
let confirmation = uv_console::confirm(&prompt, &term, true).unwrap();
if confirmation {
requirement.name = correction.clone();
}
}
}

// Add the specified extras.
requirement.extras.extend(extras.iter().cloned());
requirement.extras.sort_unstable();
Expand Down

0 comments on commit c7ca1a2

Please sign in to comment.