Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 109 additions & 1 deletion crates/pyrefly_build/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,15 +269,25 @@ pub trait SourceDbQuerier: Send + Sync + fmt::Debug {

#[derive(Debug, PartialEq, Eq, Deserialize, Clone)]
pub(crate) struct PythonLibraryManifest {
#[serde(default)]
pub deps: SmallSet<Target>,
pub srcs: SmallMap<ModuleName, Vec1<InternedPath>>,
#[serde(default)]
pub relative_to: Option<PathBuf>,
#[serde(flatten)]
pub sys_info: SysInfo,
#[serde(default)]
pub buildfile_path: PathBuf,
#[serde(default, skip)]
pub packages: SmallMap<ModuleName, Vec1<InternedPath>>,
/// Per-target override of the top-level `root`. Used for both absolutizing
/// `srcs` paths and as the import resolution root for files in this target.
#[serde(default)]
pub root: Option<PathBuf>,
/// Per-target config overrides stored as raw JSON to avoid a circular
/// dependency between `pyrefly_build` and `pyrefly_config`.
#[serde(default)]
pub config: Option<serde_json::Value>,
}

impl PythonLibraryManifest {
Expand Down Expand Up @@ -410,7 +420,8 @@ impl TargetManifestDatabase {
TargetManifest::Alias { .. } => continue,
TargetManifest::Library(lib) => {
lib.replace_alias_deps(&aliases);
lib.rewrite_relative_to_root(&self.root);
let root = lib.root.clone().unwrap_or_else(|| self.root.clone());
lib.rewrite_relative_to_root(&root);
}
}
}
Expand Down Expand Up @@ -728,6 +739,8 @@ mod tests {
sys_info: SysInfo::new(PythonVersion::new(3, 12, 0), PythonPlatform::linux()),
buildfile_path: PathBuf::from(buildfile),
packages: map_implicit_packages(implicit_packages, None),
root: None,
config: None,
})
}
}
Expand All @@ -748,6 +761,8 @@ mod tests {
sys_info: SysInfo::new(PythonVersion::new(3, 12, 0), PythonPlatform::linux()),
buildfile_path: PathBuf::from(root).join(buildfile),
packages: map_implicit_packages(inits, Some(root)),
root: None,
config: None,
}
}
}
Expand Down Expand Up @@ -1392,4 +1407,97 @@ mod tests {
manifest.packages.keys().collect::<Vec<_>>()
);
}

#[test]
fn test_per_target_config_and_root() {
let json = r#"
{
"db": {
"//pkg:basic": {
"srcs": {
"foo": ["foo.py"]
},
"root": "/src/Package",
"config": {
"preset": "basic",
"errors": { "missing-import": "warn" }
},
"python_version": "3.12",
"python_platform": "linux"
},
"//pkg:strict": {
"srcs": {
"bar": ["bar.py"]
},
"root": "/src/Package",
"config": {
"preset": "strict"
},
"python_version": "3.12",
"python_platform": "linux"
}
},
"root": "/src"
}
"#;
let parsed: TargetManifestDatabase = serde_json::from_str(json).unwrap();

let (db, _) = parsed.produce_map();

let basic = db
.get(&Target::from_string("//pkg:basic".to_owned()))
.unwrap();
assert_eq!(basic.root, Some(PathBuf::from("/src/Package")));
assert!(basic.config.is_some());
// Paths should be absolutized against per-target root, not top-level root
assert_eq!(
basic
.srcs
.get(&ModuleName::from_str("foo"))
.unwrap()
.first(),
&InternedPath::new(PathBuf::from("/src/Package/foo.py"))
);

let strict = db
.get(&Target::from_string("//pkg:strict".to_owned()))
.unwrap();
assert_eq!(strict.root, Some(PathBuf::from("/src/Package")));
assert!(strict.config.is_some());
assert_eq!(
strict
.srcs
.get(&ModuleName::from_str("bar"))
.unwrap()
.first(),
&InternedPath::new(PathBuf::from("/src/Package/bar.py"))
);
}

#[test]
fn test_optional_deps_and_buildfile_path() {
let json = r#"
{
"db": {
"//pkg:minimal": {
"srcs": {
"main": ["main.py"]
},
"python_version": "3.12",
"python_platform": "linux"
}
},
"root": "/src"
}
"#;
let parsed: TargetManifestDatabase = serde_json::from_str(json).unwrap();
let (db, _) = parsed.produce_map();
let minimal = db
.get(&Target::from_string("//pkg:minimal".to_owned()))
.unwrap();
assert!(minimal.deps.is_empty());
assert_eq!(minimal.buildfile_path, PathBuf::from("/src"));
assert!(minimal.config.is_none());
assert!(minimal.root.is_none());
}
}
8 changes: 8 additions & 0 deletions crates/pyrefly_build/src/source_db/buck_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,14 @@ impl SourceDatabase for BuckCheckSourceDatabase {
fn get_generated_files(&self) -> SmallSet<InternedPath> {
SmallSet::new()
}

fn get_target_config_raw(&self, _: Option<&Path>) -> Option<serde_json::Value> {
None
}

fn get_target_root(&self, _: Option<&Path>) -> Option<PathBuf> {
None
}
}

impl BuckCheckSourceDatabase {
Expand Down
9 changes: 9 additions & 0 deletions crates/pyrefly_build/src/source_db/map_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use std::ops::Deref;
use std::ops::DerefMut;
use std::path::Path;
use std::path::PathBuf;

use dupe::Dupe as _;
use pyrefly_python::module_name::ModuleName;
Expand Down Expand Up @@ -112,4 +113,12 @@ impl SourceDatabase for MapDatabase {
fn get_generated_files(&self) -> SmallSet<InternedPath> {
SmallSet::new()
}

fn get_target_config_raw(&self, _: Option<&Path>) -> Option<serde_json::Value> {
None
}

fn get_target_root(&self, _: Option<&Path>) -> Option<PathBuf> {
None
}
}
4 changes: 4 additions & 0 deletions crates/pyrefly_build/src/source_db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,8 @@ pub trait SourceDatabase: Send + Sync + fmt::Debug {
fn get_target(&self, origin: Option<&Path>) -> Option<Target>;
/// Get any generated files for which we might have to override the config finder.
fn get_generated_files(&self) -> SmallSet<InternedPath>;
/// Get the raw JSON config overrides for the target that owns the given file.
fn get_target_config_raw(&self, origin: Option<&Path>) -> Option<serde_json::Value>;
/// Get the per-target root for the target that owns the given file.
fn get_target_root(&self, origin: Option<&Path>) -> Option<PathBuf>;
}
Loading
Loading