WIP unused sources warning

This commit is contained in:
Jack O'Connor 2025-06-13 16:17:23 -07:00
parent 5c1ebf902b
commit 3fa6a75f2f
6 changed files with 38 additions and 4 deletions

2
Cargo.lock generated
View file

@ -5084,6 +5084,7 @@ dependencies = [
"futures", "futures",
"indoc", "indoc",
"insta", "insta",
"itertools 0.14.0",
"nanoid", "nanoid",
"owo-colors", "owo-colors",
"reqwest", "reqwest",
@ -5117,6 +5118,7 @@ dependencies = [
"uv-pypi-types", "uv-pypi-types",
"uv-redacted", "uv-redacted",
"uv-types", "uv-types",
"uv-warnings",
"uv-workspace", "uv-workspace",
"walkdir", "walkdir",
"zip", "zip",

View file

@ -35,12 +35,14 @@ uv-platform-tags = { workspace = true }
uv-pypi-types = { workspace = true } uv-pypi-types = { workspace = true }
uv-redacted = { workspace = true } uv-redacted = { workspace = true }
uv-types = { workspace = true } uv-types = { workspace = true }
uv-warnings = { workspace = true }
uv-workspace = { workspace = true } uv-workspace = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }
either = { workspace = true } either = { workspace = true }
fs-err = { workspace = true } fs-err = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
itertools = { workspace = true }
nanoid = { workspace = true } nanoid = { workspace = true }
owo-colors = { workspace = true } owo-colors = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }

View file

@ -1,4 +1,4 @@
use std::collections::BTreeMap; use std::collections::{BTreeMap, BTreeSet};
use std::path::Path; use std::path::Path;
use uv_configuration::SourceStrategy; use uv_configuration::SourceStrategy;
@ -106,6 +106,8 @@ impl BuildRequires {
metadata.name.as_ref(), metadata.name.as_ref(),
project_workspace.project_root(), project_workspace.project_root(),
project_sources, project_sources,
// TODO: make this better lol
&mut BTreeSet::new(),
project_indexes, project_indexes,
extra.as_deref(), extra.as_deref(),
group, group,
@ -178,6 +180,8 @@ impl BuildRequires {
None, None,
workspace.install_path(), workspace.install_path(),
project_sources, project_sources,
// TODO: make this better lol
&mut BTreeSet::new(),
project_indexes, project_indexes,
extra.as_deref(), extra.as_deref(),
group, group,

View file

@ -1,4 +1,4 @@
use std::collections::BTreeMap; use std::collections::{BTreeMap, BTreeSet};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use uv_configuration::SourceStrategy; use uv_configuration::SourceStrategy;
@ -142,6 +142,8 @@ impl SourcedDependencyGroups {
project.project_name(), project.project_name(),
project.root(), project.root(),
project_sources, project_sources,
// TODO: make this better lol
&mut BTreeSet::new(),
project_indexes, project_indexes,
extra, extra,
Some(&group), Some(&group),

View file

@ -1,4 +1,4 @@
use std::collections::BTreeMap; use std::collections::{BTreeMap, BTreeSet};
use std::io; use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -38,6 +38,7 @@ impl LoweredRequirement {
project_name: Option<&'data PackageName>, project_name: Option<&'data PackageName>,
project_dir: &'data Path, project_dir: &'data Path,
project_sources: &'data BTreeMap<PackageName, Sources>, project_sources: &'data BTreeMap<PackageName, Sources>,
project_sources_used: &mut BTreeSet<PackageName>,
project_indexes: &'data [Index], project_indexes: &'data [Index],
extra: Option<&ExtraName>, extra: Option<&ExtraName>,
group: Option<&GroupName>, group: Option<&GroupName>,
@ -47,8 +48,10 @@ impl LoweredRequirement {
) -> impl Iterator<Item = Result<Self, LoweringError>> + use<'data> + 'data { ) -> impl Iterator<Item = Result<Self, LoweringError>> + use<'data> + 'data {
// Identify the source from the `tool.uv.sources` table. // Identify the source from the `tool.uv.sources` table.
let (sources, origin) = if let Some(source) = project_sources.get(&requirement.name) { let (sources, origin) = if let Some(source) = project_sources.get(&requirement.name) {
project_sources_used.insert(requirement.name.clone());
(Some(source), RequirementOrigin::Project) (Some(source), RequirementOrigin::Project)
} else if let Some(source) = workspace.sources().get(&requirement.name) { } else if let Some(source) = workspace.sources().get(&requirement.name) {
// TODO(jack): Track workplace sources used also.
(Some(source), RequirementOrigin::Workspace) (Some(source), RequirementOrigin::Workspace)
} else { } else {
(None, RequirementOrigin::Project) (None, RequirementOrigin::Project)

View file

@ -1,13 +1,15 @@
use std::collections::{BTreeMap, VecDeque}; use std::collections::{BTreeMap, BTreeSet, VecDeque};
use std::path::Path; use std::path::Path;
use std::slice; use std::slice;
use itertools::Itertools;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use uv_configuration::SourceStrategy; use uv_configuration::SourceStrategy;
use uv_distribution_types::{IndexLocations, Requirement}; use uv_distribution_types::{IndexLocations, Requirement};
use uv_normalize::{ExtraName, GroupName, PackageName}; use uv_normalize::{ExtraName, GroupName, PackageName};
use uv_pep508::MarkerTree; use uv_pep508::MarkerTree;
use uv_warnings::warn_user_once;
use uv_workspace::dependency_groups::FlatDependencyGroups; use uv_workspace::dependency_groups::FlatDependencyGroups;
use uv_workspace::pyproject::{Sources, ToolUvSources}; use uv_workspace::pyproject::{Sources, ToolUvSources};
use uv_workspace::{DiscoveryOptions, MemberDiscovery, ProjectWorkspace, WorkspaceCache}; use uv_workspace::{DiscoveryOptions, MemberDiscovery, ProjectWorkspace, WorkspaceCache};
@ -106,6 +108,8 @@ impl RequiresDist {
.unwrap_or(&empty), .unwrap_or(&empty),
SourceStrategy::Disabled => &empty, SourceStrategy::Disabled => &empty,
}; };
// Keep track of which sources we use, so we can print a warning for unused ones.
let mut project_sources_used = BTreeSet::new();
let dependency_groups = FlatDependencyGroups::from_pyproject_toml( let dependency_groups = FlatDependencyGroups::from_pyproject_toml(
project_workspace.current_project().root(), project_workspace.current_project().root(),
@ -133,6 +137,7 @@ impl RequiresDist {
Some(&metadata.name), Some(&metadata.name),
project_workspace.project_root(), project_workspace.project_root(),
project_sources, project_sources,
&mut project_sources_used,
project_indexes, project_indexes,
extra, extra,
Some(&group), Some(&group),
@ -175,6 +180,7 @@ impl RequiresDist {
Some(&metadata.name), Some(&metadata.name),
project_workspace.project_root(), project_workspace.project_root(),
project_sources, project_sources,
&mut project_sources_used,
project_indexes, project_indexes,
extra.as_deref(), extra.as_deref(),
group, group,
@ -194,6 +200,21 @@ impl RequiresDist {
SourceStrategy::Disabled => requires_dist.into_iter().map(Requirement::from).collect(), SourceStrategy::Disabled => requires_dist.into_iter().map(Requirement::from).collect(),
}; };
// Warn if we have any unused project sources.
let mut unused_source_names = Vec::new();
for package_name in project_sources.keys() {
if !project_sources_used.contains(package_name) {
unused_source_names.push(package_name);
}
}
if !unused_source_names.is_empty() {
warn_user_once!(
"some {} don't match a direct dependency and have no effect: {}",
"[tool.uv.sources]".cyan(),
unused_source_names.iter().map(OwoColorize::cyan).join(", "),
);
}
Ok(Self { Ok(Self {
name: metadata.name, name: metadata.name,
requires_dist, requires_dist,