Skip to content

Commit 61faa2a

Browse files
ysheikh2claude
andcommitted
Add a failing test for a library checked in its importer's environment
A library with its own config and Python environment, installed editable into an app's environment, is checked with its own config in file mode and the language server. Its third-party imports then resolve in its own environment, so the app sees two copies of the same class (#3556). The test sets up an app and a library, each with its own site-package path containing a `dep` module, and expects no errors. It fails today. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 413a7ef commit 61faa2a

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

‎pyrefly/lib/test/state.rs‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use crate::config::error_kind::ErrorKind;
4646
use crate::config::error_kind::Severity;
4747
use crate::config::finder::ConfigFinder;
4848
use crate::error::error::print_errors;
49+
use crate::lsp::non_wasm::module_helpers::handle_from_module_path;
4950
use crate::lsp::non_wasm::server::resolve_export_location;
5051
use crate::module::bundled::BundledStub;
5152
use crate::module::bundled::set_readonly;
@@ -1605,3 +1606,53 @@ fn test_stdlib_cached_on_recheck() {
16051606
);
16061607
state.commit_transaction(t2, None);
16071608
}
1609+
1610+
/// A library with its own config and environment, found through an app's site-package path,
1611+
/// is checked in the app's environment, so both see the same `dep`. On its own, it keeps its
1612+
/// own environment.
1613+
/// See https://github.com/facebook/pyrefly/issues/3556.
1614+
#[test]
1615+
fn test_library_imported_from_another_environment() {
1616+
let temp_dir = TempDir::new().unwrap();
1617+
let root = temp_dir.path();
1618+
for dir in ["app", "app_env", "lib", "lib_env"] {
1619+
fs::create_dir_all(root.join(dir)).unwrap();
1620+
}
1621+
fs::write(
1622+
root.join("app/pyrefly.toml"),
1623+
"site-package-path = [\"../app_env\", \"../lib\"]\nskip-interpreter-query = true\n",
1624+
)
1625+
.unwrap();
1626+
fs::write(
1627+
root.join("lib/pyrefly.toml"),
1628+
"site-package-path = [\"../lib_env\"]\nskip-interpreter-query = true\n",
1629+
)
1630+
.unwrap();
1631+
fs::write(root.join("app_env/dep.py"), "class C: ...\n").unwrap();
1632+
fs::write(root.join("lib_env/dep.py"), "class C: ...\n").unwrap();
1633+
fs::write(
1634+
root.join("lib/mylib.py"),
1635+
"import dep\ndef f(x: dep.C) -> None: ...\n",
1636+
)
1637+
.unwrap();
1638+
fs::write(
1639+
root.join("app/main.py"),
1640+
"import dep\nimport mylib\nmylib.f(dep.C())\n",
1641+
)
1642+
.unwrap();
1643+
1644+
let state = State::new(default_config_finder(None), TEST_THREAD_COUNT);
1645+
let main = handle_from_module_path(&state, ModulePath::filesystem(root.join("app/main.py")));
1646+
let mylib = handle_from_module_path(&state, ModulePath::filesystem(root.join("lib/mylib.py")));
1647+
let mut transaction = state.new_transaction(Require::Exports, None);
1648+
transaction.run(&[main.dupe(), mylib.dupe()], Require::Everything, None);
1649+
let errors = transaction
1650+
.get_errors([&main, &mylib])
1651+
.collect_display_errors();
1652+
assert!(errors.is_empty(), "expected no errors, got {errors:?}");
1653+
let lib_dep = transaction
1654+
.import_handle(&mylib, ModuleName::from_str("dep"), None)
1655+
.finding()
1656+
.unwrap();
1657+
assert_eq!(lib_dep.path().as_path(), root.join("lib_env/dep.py"));
1658+
}

0 commit comments

Comments
 (0)