Skip to content

Commit 2c6c3e7

Browse files
mmlbnatelustMichaReiser
authored
[ty] Search PYTHONPATH to find modules (#20441)
Co-authored-by: Nate Lust <[email protected]> Co-authored-by: Micha Reiser <[email protected]>
1 parent 3ffe56d commit 2c6c3e7

File tree

2 files changed

+84
-4
lines changed

2 files changed

+84
-4
lines changed

crates/ty/tests/cli/python_environment.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,3 +1875,56 @@ fn default_root_python_package_pyi() -> anyhow::Result<()> {
18751875

18761876
Ok(())
18771877
}
1878+
1879+
#[test]
1880+
fn pythonpath_is_respected() -> anyhow::Result<()> {
1881+
let case = CliTest::with_files([
1882+
("src/bar/baz.py", "it = 42"),
1883+
(
1884+
"src/foo.py",
1885+
r#"
1886+
import baz
1887+
print(f"{baz.it}")
1888+
"#,
1889+
),
1890+
])?;
1891+
1892+
assert_cmd_snapshot!(case.command(),
1893+
@r#"
1894+
success: false
1895+
exit_code: 1
1896+
----- stdout -----
1897+
error[unresolved-import]: Cannot resolve imported module `baz`
1898+
--> src/foo.py:2:8
1899+
|
1900+
2 | import baz
1901+
| ^^^
1902+
3 | print(f"{baz.it}")
1903+
|
1904+
info: Searched in the following paths during module resolution:
1905+
info: 1. <temp_dir>/ (first-party code)
1906+
info: 2. <temp_dir>/src (first-party code)
1907+
info: 3. vendored://stdlib (stdlib typeshed stubs vendored by ty)
1908+
info: make sure your Python environment is properly configured: https://docs.astral.sh/ty/modules/#python-environment
1909+
info: rule `unresolved-import` is enabled by default
1910+
1911+
Found 1 diagnostic
1912+
1913+
----- stderr -----
1914+
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
1915+
"#);
1916+
1917+
assert_cmd_snapshot!(case.command()
1918+
.env("PYTHONPATH", case.root().join("src/bar")),
1919+
@r#"
1920+
success: true
1921+
exit_code: 0
1922+
----- stdout -----
1923+
All checks passed!
1924+
1925+
----- stderr -----
1926+
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
1927+
"#);
1928+
1929+
Ok(())
1930+
}

crates/ty_project/src/metadata/options.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -295,14 +295,41 @@ impl Options {
295295
roots
296296
};
297297

298-
let settings = SearchPathSettings {
299-
extra_paths: environment
298+
// collect the existing site packages
299+
let mut extra_paths: Vec<SystemPathBuf> = Vec::new();
300+
301+
// read all the paths off the PYTHONPATH environment variable, check
302+
// they exist as a directory, and add them to the vec of extra_paths
303+
// as they should be checked before site-packages just like python
304+
// interpreter does
305+
if let Ok(python_path) = system.env_var("PYTHONPATH") {
306+
for path in python_path.split(':') {
307+
let possible_path = SystemPath::absolute(path, system.current_directory());
308+
309+
if system.is_directory(&possible_path) {
310+
tracing::debug!(
311+
"Adding `{possible_path}` from the `PYTHONPATH` environment variable to `extra_paths`"
312+
);
313+
extra_paths.push(possible_path);
314+
} else {
315+
tracing::debug!(
316+
"Skipping `{possible_path}` listed in `PYTHONPATH` because the path doesn't exist or isn't a directory"
317+
);
318+
}
319+
}
320+
}
321+
322+
extra_paths.extend(
323+
environment
300324
.extra_paths
301325
.as_deref()
302326
.unwrap_or_default()
303327
.iter()
304-
.map(|path| path.absolute(project_root, system))
305-
.collect(),
328+
.map(|path| path.absolute(project_root, system)),
329+
);
330+
331+
let settings = SearchPathSettings {
332+
extra_paths,
306333
src_roots,
307334
custom_typeshed: environment
308335
.typeshed

0 commit comments

Comments
 (0)