Skip to content

Commit 53d19f8

Browse files
authored
[ty] Resolving Python path using CONDA_PREFIX variable to support Conda and Pixi (#18267)
1 parent a139965 commit 53d19f8

File tree

4 files changed

+89
-1
lines changed

4 files changed

+89
-1
lines changed

crates/ty/tests/cli.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,83 @@ fn cli_config_args_invalid_option() -> anyhow::Result<()> {
15551555
Ok(())
15561556
}
15571557

1558+
/// The `site-packages` directory is used by ty for external import.
1559+
/// Ty does the following checks to discover the `site-packages` directory in the order:
1560+
/// 1) If `VIRTUAL_ENV` environment variable is set
1561+
/// 2) If `CONDA_PREFIX` environment variable is set
1562+
/// 3) If a `.venv` directory exists at the project root
1563+
///
1564+
/// This test is aiming at validating the logic around `CONDA_PREFIX`.
1565+
///
1566+
/// A conda-like environment file structure is used
1567+
/// We test by first not setting the `CONDA_PREFIX` and expect a fail.
1568+
/// Then we test by setting `CONDA_PREFIX` to `conda-env` and expect a pass.
1569+
///
1570+
/// ├── project
1571+
/// │ └── test.py
1572+
/// └── conda-env
1573+
/// └── lib
1574+
/// └── python3.13
1575+
/// └── site-packages
1576+
/// └── package1
1577+
/// └── __init__.py
1578+
///
1579+
/// test.py imports package1
1580+
/// And the command is run in the `project` directory.
1581+
#[test]
1582+
fn check_conda_prefix_var_to_resolve_path() -> anyhow::Result<()> {
1583+
let conda_package1_path = if cfg!(windows) {
1584+
"conda-env/Lib/site-packages/package1/__init__.py"
1585+
} else {
1586+
"conda-env/lib/python3.13/site-packages/package1/__init__.py"
1587+
};
1588+
1589+
let case = TestCase::with_files([
1590+
(
1591+
"project/test.py",
1592+
r#"
1593+
import package1
1594+
"#,
1595+
),
1596+
(
1597+
conda_package1_path,
1598+
r#"
1599+
"#,
1600+
),
1601+
])?;
1602+
1603+
assert_cmd_snapshot!(case.command().current_dir(case.root().join("project")), @r"
1604+
success: false
1605+
exit_code: 1
1606+
----- stdout -----
1607+
error[unresolved-import]: Cannot resolve imported module `package1`
1608+
--> test.py:2:8
1609+
|
1610+
2 | import package1
1611+
| ^^^^^^^^
1612+
|
1613+
info: make sure your Python environment is properly configured: https://github.com/astral-sh/ty/blob/main/docs/README.md#python-environment
1614+
info: rule `unresolved-import` is enabled by default
1615+
1616+
Found 1 diagnostic
1617+
1618+
----- stderr -----
1619+
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
1620+
");
1621+
1622+
// do command : CONDA_PREFIX=<temp_dir>/conda_env
1623+
assert_cmd_snapshot!(case.command().current_dir(case.root().join("project")).env("CONDA_PREFIX", case.root().join("conda-env")), @r"
1624+
success: true
1625+
exit_code: 0
1626+
----- stdout -----
1627+
All checks passed!
1628+
1629+
----- stderr -----
1630+
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
1631+
");
1632+
Ok(())
1633+
}
1634+
15581635
struct TestCase {
15591636
_temp_dir: TempDir,
15601637
_settings_scope: SettingsBindDropGuard,

crates/ty_project/src/metadata/options.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,11 @@ impl Options {
186186
.ok()
187187
.map(PythonPath::from_virtual_env_var)
188188
})
189+
.or_else(|| {
190+
std::env::var("CONDA_PREFIX")
191+
.ok()
192+
.map(PythonPath::from_conda_prefix_var)
193+
})
189194
.unwrap_or_else(|| PythonPath::Discover(project_root.to_path_buf())),
190195
}
191196
}

crates/ty_python_semantic/src/program.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ impl PythonPath {
202202
Self::SysPrefix(path.into(), SysPrefixPathOrigin::VirtualEnvVar)
203203
}
204204

205+
pub fn from_conda_prefix_var(path: impl Into<SystemPathBuf>) -> Self {
206+
Self::Resolve(path.into(), SysPrefixPathOrigin::CondaPrefixVar)
207+
}
208+
205209
pub fn from_cli_flag(path: SystemPathBuf) -> Self {
206210
Self::Resolve(path, SysPrefixPathOrigin::PythonCliFlag)
207211
}

crates/ty_python_semantic/src/site_packages.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ impl fmt::Display for SysPrefixPath {
580580
pub enum SysPrefixPathOrigin {
581581
PythonCliFlag,
582582
VirtualEnvVar,
583+
CondaPrefixVar,
583584
Derived,
584585
LocalVenv,
585586
}
@@ -590,7 +591,7 @@ impl SysPrefixPathOrigin {
590591
pub(crate) fn must_be_virtual_env(self) -> bool {
591592
match self {
592593
Self::LocalVenv | Self::VirtualEnvVar => true,
593-
Self::PythonCliFlag | Self::Derived => false,
594+
Self::PythonCliFlag | Self::Derived | Self::CondaPrefixVar => false,
594595
}
595596
}
596597
}
@@ -600,6 +601,7 @@ impl Display for SysPrefixPathOrigin {
600601
match self {
601602
Self::PythonCliFlag => f.write_str("`--python` argument"),
602603
Self::VirtualEnvVar => f.write_str("`VIRTUAL_ENV` environment variable"),
604+
Self::CondaPrefixVar => f.write_str("`CONDA_PREFIX` environment variable"),
603605
Self::Derived => f.write_str("derived `sys.prefix` path"),
604606
Self::LocalVenv => f.write_str("local virtual environment"),
605607
}

0 commit comments

Comments
 (0)