Skip to content

Commit 575dea9

Browse files
committed
Review feedback
1 parent 70e522b commit 575dea9

File tree

4 files changed

+72
-13
lines changed

4 files changed

+72
-13
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ruff/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ colored = { workspace = true }
4848
filetime = { workspace = true }
4949
globwalk = { workspace = true }
5050
ignore = { workspace = true }
51+
indexmap = { workspace = true }
5152
is-macro = { workspace = true }
5253
itertools = { workspace = true }
5354
jiff = { workspace = true }

crates/ruff/src/commands/analyze_graph.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::args::{AnalyzeGraphArgs, ConfigArguments};
22
use crate::resolve::resolve;
33
use crate::{ExitStatus, resolve_default_files};
44
use anyhow::Result;
5+
use indexmap::IndexSet;
56
use log::{debug, warn};
67
use path_absolutize::CWD;
78
use ruff_db::system::{SystemPath, SystemPathBuf};
@@ -11,7 +12,7 @@ use ruff_linter::source_kind::SourceKind;
1112
use ruff_linter::{warn_user, warn_user_once};
1213
use ruff_python_ast::{PySourceType, SourceType};
1314
use ruff_workspace::resolver::{ResolvedFile, match_exclusion, python_files_in_path};
14-
use rustc_hash::FxHashMap;
15+
use rustc_hash::{FxBuildHasher, FxHashMap};
1516
use std::io::Write;
1617
use std::path::{Path, PathBuf};
1718
use std::sync::{Arc, Mutex};
@@ -59,17 +60,13 @@ pub(crate) fn analyze_graph(
5960
})
6061
.collect::<FxHashMap<_, _>>();
6162

62-
// Create a database from the source roots, combining detected package roots with configured
63-
// `src` paths.
64-
let mut src_roots: Vec<SystemPathBuf> = package_roots
65-
.values()
66-
.filter_map(|package| package.as_deref())
67-
.filter_map(|package| package.parent())
68-
.map(Path::to_path_buf)
69-
.filter_map(|path| SystemPathBuf::from_path_buf(path).ok())
70-
.collect();
71-
72-
// Add configured `src` paths, filtering to only include existing directories.
63+
// Create a database from the source roots, combining configured `src` paths with detected
64+
// package roots. Configured paths are added first so they take precedence, and duplicates
65+
// are removed.
66+
let mut src_roots: IndexSet<SystemPathBuf, FxBuildHasher> = IndexSet::default();
67+
68+
// Add configured `src` paths first (for precedence), filtering to only include existing
69+
// directories.
7370
src_roots.extend(
7471
pyproject_config
7572
.settings
@@ -80,8 +77,17 @@ pub(crate) fn analyze_graph(
8077
.filter_map(|path| SystemPathBuf::from_path_buf(path.clone()).ok()),
8178
);
8279

80+
// Add detected package roots.
81+
src_roots.extend(
82+
package_roots
83+
.values()
84+
.filter_map(|package| package.as_deref())
85+
.filter_map(|path| path.parent())
86+
.filter_map(|path| SystemPathBuf::from_path_buf(path.to_path_buf()).ok()),
87+
);
88+
8389
let db = ModuleDb::from_src_roots(
84-
src_roots,
90+
src_roots.into_iter().collect(),
8591
pyproject_config
8692
.settings
8793
.analyze

crates/ruff/tests/analyze_graph.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,57 @@ fn src_option() -> Result<()> {
778778
Ok(())
779779
}
780780

781+
/// Test that glob patterns in `src` are expanded.
782+
#[test]
783+
fn src_glob_expansion() -> Result<()> {
784+
let tempdir = TempDir::new()?;
785+
let root = ChildPath::new(tempdir.path());
786+
787+
// Create multiple lib directories with packages.
788+
root.child("libs")
789+
.child("lib_a")
790+
.child("pkg_a")
791+
.child("__init__.py")
792+
.write_str("def func_a(): pass")?;
793+
root.child("libs")
794+
.child("lib_b")
795+
.child("pkg_b")
796+
.child("__init__.py")
797+
.write_str("def func_b(): pass")?;
798+
799+
// Create an app that imports from both packages.
800+
root.child("app").child("__init__.py").write_str("")?;
801+
root.child("app")
802+
.child("main.py")
803+
.write_str("from pkg_a import func_a\nfrom pkg_b import func_b")?;
804+
805+
// Use a glob pattern to include all lib directories.
806+
root.child("ruff.toml").write_str(indoc::indoc! {r#"
807+
src = ["libs/*"]
808+
"#})?;
809+
810+
insta::with_settings!({
811+
filters => INSTA_FILTERS.to_vec(),
812+
}, {
813+
assert_cmd_snapshot!(command().arg("app").current_dir(&root), @r#"
814+
success: true
815+
exit_code: 0
816+
----- stdout -----
817+
{
818+
"app/__init__.py": [],
819+
"app/main.py": [
820+
"libs/lib_a/pkg_a/__init__.py",
821+
"libs/lib_b/pkg_b/__init__.py"
822+
]
823+
}
824+
825+
----- stderr -----
826+
"#);
827+
});
828+
829+
Ok(())
830+
}
831+
781832
#[test]
782833
fn notebook_with_magic() -> Result<()> {
783834
let tempdir = TempDir::new()?;

0 commit comments

Comments
 (0)