mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:44:56 +00:00
[ty] distinguish base conda from child conda (#19990)
This is a port of the logic in https://github.com/astral-sh/uv/pull/7691 The basic idea is we use CONDA_DEFAULT_ENV as a signal for whether CONDA_PREFIX is just the ambient system conda install, or the user has explicitly activated a custom one. If the former, then the conda is treated like a system install (having lowest priority). If the latter, the conda is treated like an activated venv (having priority over everything but an Actual activated venv). Fixes https://github.com/astral-sh/ty/issues/611
This commit is contained in:
parent
276405b44e
commit
1d2128f918
3 changed files with 567 additions and 34 deletions
|
@ -900,18 +900,58 @@ fn defaults_to_a_new_python_version() -> anyhow::Result<()> {
|
||||||
/// The `site-packages` directory is used by ty for external import.
|
/// The `site-packages` directory is used by ty for external import.
|
||||||
/// Ty does the following checks to discover the `site-packages` directory in the order:
|
/// Ty does the following checks to discover the `site-packages` directory in the order:
|
||||||
/// 1) If `VIRTUAL_ENV` environment variable is set
|
/// 1) If `VIRTUAL_ENV` environment variable is set
|
||||||
/// 2) If `CONDA_PREFIX` environment variable is set
|
/// 2) If `CONDA_PREFIX` environment variable is set (and .filename != `CONDA_DEFAULT_ENV`)
|
||||||
/// 3) If a `.venv` directory exists at the project root
|
/// 3) If a `.venv` directory exists at the project root
|
||||||
|
/// 4) If `CONDA_PREFIX` environment variable is set (and .filename == `CONDA_DEFAULT_ENV`)
|
||||||
///
|
///
|
||||||
/// This test is aiming at validating the logic around `CONDA_PREFIX`.
|
/// This test (and the next one) is aiming at validating the logic around these cases.
|
||||||
///
|
///
|
||||||
/// A conda-like environment file structure is used
|
/// To do this we create a program that has these 4 imports:
|
||||||
/// We test by first not setting the `CONDA_PREFIX` and expect a fail.
|
///
|
||||||
/// Then we test by setting `CONDA_PREFIX` to `conda-env` and expect a pass.
|
/// ```python
|
||||||
|
/// from package1 import ActiveVenv
|
||||||
|
/// from package1 import ChildConda
|
||||||
|
/// from package1 import WorkingVenv
|
||||||
|
/// from package1 import BaseConda
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// We then create 4 different copies of package1. Each copy defines all of these
|
||||||
|
/// classes... except the one that describes it. Therefore we know we got e.g.
|
||||||
|
/// the working venv if we get a diagnostic like this:
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// Unresolved import
|
||||||
|
/// 4 | from package1 import WorkingVenv
|
||||||
|
/// | ^^^^^^^^^^^
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This test uses a directory structure as follows:
|
||||||
///
|
///
|
||||||
/// ├── project
|
/// ├── project
|
||||||
/// │ └── test.py
|
/// │ ├── test.py
|
||||||
/// └── conda-env
|
/// │ └── .venv
|
||||||
|
/// │ ├── pyvenv.cfg
|
||||||
|
/// │ └── lib
|
||||||
|
/// │ └── python3.13
|
||||||
|
/// │ └── site-packages
|
||||||
|
/// │ └── package1
|
||||||
|
/// │ └── __init__.py
|
||||||
|
/// ├── myvenv
|
||||||
|
/// │ ├── pyvenv.cfg
|
||||||
|
/// │ └── lib
|
||||||
|
/// │ └── python3.13
|
||||||
|
/// │ └── site-packages
|
||||||
|
/// │ └── package1
|
||||||
|
/// │ └── __init__.py
|
||||||
|
/// ├── conda-env
|
||||||
|
/// │ └── lib
|
||||||
|
/// │ └── python3.13
|
||||||
|
/// │ └── site-packages
|
||||||
|
/// │ └── package1
|
||||||
|
/// │ └── __init__.py
|
||||||
|
/// └── conda
|
||||||
|
/// └── envs
|
||||||
|
/// └── base
|
||||||
/// └── lib
|
/// └── lib
|
||||||
/// └── python3.13
|
/// └── python3.13
|
||||||
/// └── site-packages
|
/// └── site-packages
|
||||||
|
@ -921,38 +961,104 @@ fn defaults_to_a_new_python_version() -> anyhow::Result<()> {
|
||||||
/// test.py imports package1
|
/// test.py imports package1
|
||||||
/// And the command is run in the `child` directory.
|
/// And the command is run in the `child` directory.
|
||||||
#[test]
|
#[test]
|
||||||
fn check_conda_prefix_var_to_resolve_path() -> anyhow::Result<()> {
|
fn check_venv_resolution_with_working_venv() -> anyhow::Result<()> {
|
||||||
let conda_package1_path = if cfg!(windows) {
|
let child_conda_package1_path = if cfg!(windows) {
|
||||||
"conda-env/Lib/site-packages/package1/__init__.py"
|
"conda-env/Lib/site-packages/package1/__init__.py"
|
||||||
} else {
|
} else {
|
||||||
"conda-env/lib/python3.13/site-packages/package1/__init__.py"
|
"conda-env/lib/python3.13/site-packages/package1/__init__.py"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let base_conda_package1_path = if cfg!(windows) {
|
||||||
|
"conda/envs/base/Lib/site-packages/package1/__init__.py"
|
||||||
|
} else {
|
||||||
|
"conda/envs/base/lib/python3.13/site-packages/package1/__init__.py"
|
||||||
|
};
|
||||||
|
|
||||||
|
let working_venv_package1_path = if cfg!(windows) {
|
||||||
|
"project/.venv/Lib/site-packages/package1/__init__.py"
|
||||||
|
} else {
|
||||||
|
"project/.venv/lib/python3.13/site-packages/package1/__init__.py"
|
||||||
|
};
|
||||||
|
|
||||||
|
let active_venv_package1_path = if cfg!(windows) {
|
||||||
|
"myvenv/Lib/site-packages/package1/__init__.py"
|
||||||
|
} else {
|
||||||
|
"myvenv/lib/python3.13/site-packages/package1/__init__.py"
|
||||||
|
};
|
||||||
|
|
||||||
let case = CliTest::with_files([
|
let case = CliTest::with_files([
|
||||||
(
|
(
|
||||||
"project/test.py",
|
"project/test.py",
|
||||||
r#"
|
r#"
|
||||||
import package1
|
from package1 import ActiveVenv
|
||||||
|
from package1 import ChildConda
|
||||||
|
from package1 import WorkingVenv
|
||||||
|
from package1 import BaseConda
|
||||||
"#,
|
"#,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
conda_package1_path,
|
"project/.venv/pyvenv.cfg",
|
||||||
r#"
|
r#"
|
||||||
|
home = ./
|
||||||
|
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"myvenv/pyvenv.cfg",
|
||||||
|
r#"
|
||||||
|
home = ./
|
||||||
|
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
active_venv_package1_path,
|
||||||
|
r#"
|
||||||
|
class ChildConda: ...
|
||||||
|
class WorkingVenv: ...
|
||||||
|
class BaseConda: ...
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
child_conda_package1_path,
|
||||||
|
r#"
|
||||||
|
class ActiveVenv: ...
|
||||||
|
class WorkingVenv: ...
|
||||||
|
class BaseConda: ...
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
working_venv_package1_path,
|
||||||
|
r#"
|
||||||
|
class ActiveVenv: ...
|
||||||
|
class ChildConda: ...
|
||||||
|
class BaseConda: ...
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
base_conda_package1_path,
|
||||||
|
r#"
|
||||||
|
class ActiveVenv: ...
|
||||||
|
class ChildConda: ...
|
||||||
|
class WorkingVenv: ...
|
||||||
"#,
|
"#,
|
||||||
),
|
),
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
assert_cmd_snapshot!(case.command().current_dir(case.root().join("project")), @r"
|
// Run with nothing set, should find the working venv
|
||||||
|
assert_cmd_snapshot!(case.command()
|
||||||
|
.current_dir(case.root().join("project")), @r"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 1
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
error[unresolved-import]: Cannot resolve imported module `package1`
|
error[unresolved-import]: Module `package1` has no member `WorkingVenv`
|
||||||
--> test.py:2:8
|
--> test.py:4:22
|
||||||
|
|
|
|
||||||
2 | import package1
|
2 | from package1 import ActiveVenv
|
||||||
| ^^^^^^^^
|
3 | from package1 import ChildConda
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
5 | from package1 import BaseConda
|
||||||
|
|
|
|
||||||
info: make sure your Python environment is properly configured: https://docs.astral.sh/ty/modules/#python-environment
|
|
||||||
info: rule `unresolved-import` is enabled by default
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
Found 1 diagnostic
|
Found 1 diagnostic
|
||||||
|
@ -961,12 +1067,373 @@ fn check_conda_prefix_var_to_resolve_path() -> anyhow::Result<()> {
|
||||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
");
|
");
|
||||||
|
|
||||||
// do command : CONDA_PREFIX=<temp_dir>/conda_env
|
// Run with VIRTUAL_ENV set, should find the active venv
|
||||||
assert_cmd_snapshot!(case.command().current_dir(case.root().join("project")).env("CONDA_PREFIX", case.root().join("conda-env")), @r"
|
assert_cmd_snapshot!(case.command()
|
||||||
success: true
|
.current_dir(case.root().join("project"))
|
||||||
exit_code: 0
|
.env("VIRTUAL_ENV", case.root().join("myvenv")), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
All checks passed!
|
error[unresolved-import]: Module `package1` has no member `ActiveVenv`
|
||||||
|
--> test.py:2:22
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
|
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
Found 1 diagnostic
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
|
");
|
||||||
|
|
||||||
|
// run with CONDA_PREFIX set, should find the child conda
|
||||||
|
assert_cmd_snapshot!(case.command()
|
||||||
|
.current_dir(case.root().join("project"))
|
||||||
|
.env("CONDA_PREFIX", case.root().join("conda-env")), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
error[unresolved-import]: Module `package1` has no member `ChildConda`
|
||||||
|
--> test.py:3:22
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
5 | from package1 import BaseConda
|
||||||
|
|
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
Found 1 diagnostic
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
|
");
|
||||||
|
|
||||||
|
// run with CONDA_PREFIX and CONDA_DEFAULT_ENV set (unequal), should find child conda
|
||||||
|
assert_cmd_snapshot!(case.command()
|
||||||
|
.current_dir(case.root().join("project"))
|
||||||
|
.env("CONDA_PREFIX", case.root().join("conda-env"))
|
||||||
|
.env("CONDA_DEFAULT_ENV", "base"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
error[unresolved-import]: Module `package1` has no member `ChildConda`
|
||||||
|
--> test.py:3:22
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
5 | from package1 import BaseConda
|
||||||
|
|
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
Found 1 diagnostic
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
|
");
|
||||||
|
|
||||||
|
// run with CONDA_PREFIX and CONDA_DEFAULT_ENV (unequal) and VIRTUAL_ENV set,
|
||||||
|
// should find child active venv
|
||||||
|
assert_cmd_snapshot!(case.command()
|
||||||
|
.current_dir(case.root().join("project"))
|
||||||
|
.env("CONDA_PREFIX", case.root().join("conda-env"))
|
||||||
|
.env("CONDA_DEFAULT_ENV", "base")
|
||||||
|
.env("VIRTUAL_ENV", case.root().join("myvenv")), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
error[unresolved-import]: Module `package1` has no member `ActiveVenv`
|
||||||
|
--> test.py:2:22
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
|
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
Found 1 diagnostic
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
|
");
|
||||||
|
|
||||||
|
// run with CONDA_PREFIX and CONDA_DEFAULT_ENV (equal!) set, should find working venv
|
||||||
|
assert_cmd_snapshot!(case.command()
|
||||||
|
.current_dir(case.root().join("project"))
|
||||||
|
.env("CONDA_PREFIX", case.root().join("conda/envs/base"))
|
||||||
|
.env("CONDA_DEFAULT_ENV", "base"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
error[unresolved-import]: Module `package1` has no member `WorkingVenv`
|
||||||
|
--> test.py:4:22
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
5 | from package1 import BaseConda
|
||||||
|
|
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
Found 1 diagnostic
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
|
");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The exact same test as above, but without a working venv
|
||||||
|
///
|
||||||
|
/// In this case the Base Conda should be a possible outcome.
|
||||||
|
#[test]
|
||||||
|
fn check_venv_resolution_without_working_venv() -> anyhow::Result<()> {
|
||||||
|
let child_conda_package1_path = if cfg!(windows) {
|
||||||
|
"conda-env/Lib/site-packages/package1/__init__.py"
|
||||||
|
} else {
|
||||||
|
"conda-env/lib/python3.13/site-packages/package1/__init__.py"
|
||||||
|
};
|
||||||
|
|
||||||
|
let base_conda_package1_path = if cfg!(windows) {
|
||||||
|
"conda/envs/base/Lib/site-packages/package1/__init__.py"
|
||||||
|
} else {
|
||||||
|
"conda/envs/base/lib/python3.13/site-packages/package1/__init__.py"
|
||||||
|
};
|
||||||
|
|
||||||
|
let active_venv_package1_path = if cfg!(windows) {
|
||||||
|
"myvenv/Lib/site-packages/package1/__init__.py"
|
||||||
|
} else {
|
||||||
|
"myvenv/lib/python3.13/site-packages/package1/__init__.py"
|
||||||
|
};
|
||||||
|
|
||||||
|
let case = CliTest::with_files([
|
||||||
|
(
|
||||||
|
"project/test.py",
|
||||||
|
r#"
|
||||||
|
from package1 import ActiveVenv
|
||||||
|
from package1 import ChildConda
|
||||||
|
from package1 import WorkingVenv
|
||||||
|
from package1 import BaseConda
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"myvenv/pyvenv.cfg",
|
||||||
|
r#"
|
||||||
|
home = ./
|
||||||
|
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
active_venv_package1_path,
|
||||||
|
r#"
|
||||||
|
class ChildConda: ...
|
||||||
|
class WorkingVenv: ...
|
||||||
|
class BaseConda: ...
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
child_conda_package1_path,
|
||||||
|
r#"
|
||||||
|
class ActiveVenv: ...
|
||||||
|
class WorkingVenv: ...
|
||||||
|
class BaseConda: ...
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
base_conda_package1_path,
|
||||||
|
r#"
|
||||||
|
class ActiveVenv: ...
|
||||||
|
class ChildConda: ...
|
||||||
|
class WorkingVenv: ...
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
])?;
|
||||||
|
|
||||||
|
// Run with nothing set, should fail to find anything
|
||||||
|
assert_cmd_snapshot!(case.command()
|
||||||
|
.current_dir(case.root().join("project")), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
error[unresolved-import]: Cannot resolve imported module `package1`
|
||||||
|
--> test.py:2:6
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
| ^^^^^^^^
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
|
|
||||||
|
info: make sure your Python environment is properly configured: https://docs.astral.sh/ty/modules/#python-environment
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
error[unresolved-import]: Cannot resolve imported module `package1`
|
||||||
|
--> test.py:3:6
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
| ^^^^^^^^
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
5 | from package1 import BaseConda
|
||||||
|
|
|
||||||
|
info: make sure your Python environment is properly configured: https://docs.astral.sh/ty/modules/#python-environment
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
error[unresolved-import]: Cannot resolve imported module `package1`
|
||||||
|
--> test.py:4:6
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
| ^^^^^^^^
|
||||||
|
5 | from package1 import BaseConda
|
||||||
|
|
|
||||||
|
info: make sure your Python environment is properly configured: https://docs.astral.sh/ty/modules/#python-environment
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
error[unresolved-import]: Cannot resolve imported module `package1`
|
||||||
|
--> test.py:5:6
|
||||||
|
|
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
5 | from package1 import BaseConda
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
info: make sure your Python environment is properly configured: https://docs.astral.sh/ty/modules/#python-environment
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
Found 4 diagnostics
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
|
");
|
||||||
|
|
||||||
|
// Run with VIRTUAL_ENV set, should find the active venv
|
||||||
|
assert_cmd_snapshot!(case.command()
|
||||||
|
.current_dir(case.root().join("project"))
|
||||||
|
.env("VIRTUAL_ENV", case.root().join("myvenv")), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
error[unresolved-import]: Module `package1` has no member `ActiveVenv`
|
||||||
|
--> test.py:2:22
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
|
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
Found 1 diagnostic
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
|
");
|
||||||
|
|
||||||
|
// run with CONDA_PREFIX set, should find the child conda
|
||||||
|
assert_cmd_snapshot!(case.command()
|
||||||
|
.current_dir(case.root().join("project"))
|
||||||
|
.env("CONDA_PREFIX", case.root().join("conda-env")), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
error[unresolved-import]: Module `package1` has no member `ChildConda`
|
||||||
|
--> test.py:3:22
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
5 | from package1 import BaseConda
|
||||||
|
|
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
Found 1 diagnostic
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
|
");
|
||||||
|
|
||||||
|
// run with CONDA_PREFIX and CONDA_DEFAULT_ENV set (unequal), should find child conda
|
||||||
|
assert_cmd_snapshot!(case.command()
|
||||||
|
.current_dir(case.root().join("project"))
|
||||||
|
.env("CONDA_PREFIX", case.root().join("conda-env"))
|
||||||
|
.env("CONDA_DEFAULT_ENV", "base"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
error[unresolved-import]: Module `package1` has no member `ChildConda`
|
||||||
|
--> test.py:3:22
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
5 | from package1 import BaseConda
|
||||||
|
|
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
Found 1 diagnostic
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
|
");
|
||||||
|
|
||||||
|
// run with CONDA_PREFIX and CONDA_DEFAULT_ENV (unequal) and VIRTUAL_ENV set,
|
||||||
|
// should find child active venv
|
||||||
|
assert_cmd_snapshot!(case.command()
|
||||||
|
.current_dir(case.root().join("project"))
|
||||||
|
.env("CONDA_PREFIX", case.root().join("conda-env"))
|
||||||
|
.env("CONDA_DEFAULT_ENV", "base")
|
||||||
|
.env("VIRTUAL_ENV", case.root().join("myvenv")), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
error[unresolved-import]: Module `package1` has no member `ActiveVenv`
|
||||||
|
--> test.py:2:22
|
||||||
|
|
|
||||||
|
2 | from package1 import ActiveVenv
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
|
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
Found 1 diagnostic
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
|
");
|
||||||
|
|
||||||
|
// run with CONDA_PREFIX and CONDA_DEFAULT_ENV (equal!) set, should find base conda
|
||||||
|
assert_cmd_snapshot!(case.command()
|
||||||
|
.current_dir(case.root().join("project"))
|
||||||
|
.env("CONDA_PREFIX", case.root().join("conda/envs/base"))
|
||||||
|
.env("CONDA_DEFAULT_ENV", "base"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
error[unresolved-import]: Module `package1` has no member `BaseConda`
|
||||||
|
--> test.py:5:22
|
||||||
|
|
|
||||||
|
3 | from package1 import ChildConda
|
||||||
|
4 | from package1 import WorkingVenv
|
||||||
|
5 | from package1 import BaseConda
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
info: rule `unresolved-import` is enabled by default
|
||||||
|
|
||||||
|
Found 1 diagnostic
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||||
|
|
|
@ -139,6 +139,12 @@ pub enum PythonEnvironment {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PythonEnvironment {
|
impl PythonEnvironment {
|
||||||
|
/// Discover the python environment using the following priorities:
|
||||||
|
///
|
||||||
|
/// 1. activated virtual environment
|
||||||
|
/// 2. conda (child)
|
||||||
|
/// 3. working dir virtual environment
|
||||||
|
/// 4. conda (base)
|
||||||
pub fn discover(
|
pub fn discover(
|
||||||
project_root: &SystemPath,
|
project_root: &SystemPath,
|
||||||
system: &dyn System,
|
system: &dyn System,
|
||||||
|
@ -161,12 +167,8 @@ impl PythonEnvironment {
|
||||||
.map(Some);
|
.map(Some);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(conda_env) = system.env_var(EnvVars::CONDA_PREFIX) {
|
if let Some(conda_env) = conda_environment_from_env(system, CondaEnvironmentKind::Child) {
|
||||||
return resolve_environment(
|
return resolve_environment(system, &conda_env, SysPrefixPathOrigin::CondaPrefixVar)
|
||||||
system,
|
|
||||||
SystemPath::new(&conda_env),
|
|
||||||
SysPrefixPathOrigin::CondaPrefixVar,
|
|
||||||
)
|
|
||||||
.map(Some);
|
.map(Some);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,6 +192,11 @@ impl PythonEnvironment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(conda_env) = conda_environment_from_env(system, CondaEnvironmentKind::Base) {
|
||||||
|
return resolve_environment(system, &conda_env, SysPrefixPathOrigin::CondaPrefixVar)
|
||||||
|
.map(Some);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,6 +596,62 @@ System stdlib will not be used for module definitions.",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Different kinds of conda environment
|
||||||
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
pub(crate) enum CondaEnvironmentKind {
|
||||||
|
/// The base Conda environment; treated like a system Python environment.
|
||||||
|
Base,
|
||||||
|
/// Any other Conda environment; treated like a virtual environment.
|
||||||
|
Child,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CondaEnvironmentKind {
|
||||||
|
/// Compute the kind of `CONDA_PREFIX` we have.
|
||||||
|
///
|
||||||
|
/// When the base environment is used, `CONDA_DEFAULT_ENV` will be set to a name, i.e., `base` or
|
||||||
|
/// `root` which does not match the prefix, e.g. `/usr/local` instead of
|
||||||
|
/// `/usr/local/conda/envs/<name>`.
|
||||||
|
fn from_prefix_path(system: &dyn System, path: &SystemPath) -> Self {
|
||||||
|
// If we cannot read `CONDA_DEFAULT_ENV`, there's no way to know if the base environment
|
||||||
|
let Ok(default_env) = system.env_var(EnvVars::CONDA_DEFAULT_ENV) else {
|
||||||
|
return CondaEnvironmentKind::Child;
|
||||||
|
};
|
||||||
|
|
||||||
|
// These are the expected names for the base environment
|
||||||
|
if default_env != "base" && default_env != "root" {
|
||||||
|
return CondaEnvironmentKind::Child;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(name) = path.file_name() else {
|
||||||
|
return CondaEnvironmentKind::Child;
|
||||||
|
};
|
||||||
|
|
||||||
|
if name == default_env {
|
||||||
|
CondaEnvironmentKind::Base
|
||||||
|
} else {
|
||||||
|
CondaEnvironmentKind::Child
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read `CONDA_PREFIX` and confirm that it has the expected kind
|
||||||
|
pub(crate) fn conda_environment_from_env(
|
||||||
|
system: &dyn System,
|
||||||
|
kind: CondaEnvironmentKind,
|
||||||
|
) -> Option<SystemPathBuf> {
|
||||||
|
let dir = system
|
||||||
|
.env_var(EnvVars::CONDA_PREFIX)
|
||||||
|
.ok()
|
||||||
|
.filter(|value| !value.is_empty())?;
|
||||||
|
let path = SystemPathBuf::from(dir);
|
||||||
|
|
||||||
|
if kind != CondaEnvironmentKind::from_prefix_path(system, &path) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(path)
|
||||||
|
}
|
||||||
|
|
||||||
/// A parser for `pyvenv.cfg` files: metadata files for virtual environments.
|
/// A parser for `pyvenv.cfg` files: metadata files for virtual environments.
|
||||||
///
|
///
|
||||||
/// Note that a `pyvenv.cfg` file *looks* like a `.ini` file, but actually isn't valid `.ini` syntax!
|
/// Note that a `pyvenv.cfg` file *looks* like a `.ini` file, but actually isn't valid `.ini` syntax!
|
||||||
|
|
|
@ -42,6 +42,9 @@ impl EnvVars {
|
||||||
/// Used to detect an activated virtual environment.
|
/// Used to detect an activated virtual environment.
|
||||||
pub const VIRTUAL_ENV: &'static str = "VIRTUAL_ENV";
|
pub const VIRTUAL_ENV: &'static str = "VIRTUAL_ENV";
|
||||||
|
|
||||||
|
/// Used to determine if an active Conda environment is the base environment or not.
|
||||||
|
pub const CONDA_DEFAULT_ENV: &'static str = "CONDA_DEFAULT_ENV";
|
||||||
|
|
||||||
/// Used to detect an activated Conda environment location.
|
/// Used to detect an activated Conda environment location.
|
||||||
/// If both `VIRTUAL_ENV` and `CONDA_PREFIX` are present, `VIRTUAL_ENV` will be preferred.
|
/// If both `VIRTUAL_ENV` and `CONDA_PREFIX` are present, `VIRTUAL_ENV` will be preferred.
|
||||||
pub const CONDA_PREFIX: &'static str = "CONDA_PREFIX";
|
pub const CONDA_PREFIX: &'static str = "CONDA_PREFIX";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue