mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-11 06:08:34 +00:00
Update --python
to accept paths to executables in virtual environments (#17954)
## Summary Updates the `--python` flag to accept Python executables in virtual environments. Notably, we do not query the executable and it _must_ be in a canonical location in a virtual environment. This is pretty naive, but solves for the trivial case of `ty check --python .venv/bin/python3` which will be a common mistake (and `ty check --python $(which python)`) I explored this while trying to understand Python discovery in ty in service of https://github.com/astral-sh/ty/issues/272, I'm not attached to it, but figure it's worth sharing. As an alternative, we can add more variants to the `SearchPathValidationError` and just improve the _error_ message, i.e., by hinting that this looks like a virtual environment and suggesting the concrete alternative path they should provide. We'll probably want to do that for some other cases anyway (e.g., `3.13` as described in the linked issue) This functionality is also briefly mentioned in https://github.com/astral-sh/ty/issues/193 Closes https://github.com/astral-sh/ty/issues/318 ## Test Plan e.g., ``` uv run ty check --python .venv/bin/python3 ``` needs test coverage still
This commit is contained in:
parent
d545b5bfd2
commit
6b64630635
5 changed files with 56 additions and 14 deletions
|
@ -247,6 +247,33 @@ impl SearchPaths {
|
|||
.and_then(|env| env.site_packages_directories(system))?
|
||||
}
|
||||
|
||||
PythonPath::Resolve(target, origin) => {
|
||||
tracing::debug!("Resolving {origin}: {target}");
|
||||
|
||||
let root = system
|
||||
// If given a file, assume it's a Python executable, e.g., `.venv/bin/python3`,
|
||||
// and search for a virtual environment in the root directory. Ideally, we'd
|
||||
// invoke the target to determine `sys.prefix` here, but that's more complicated
|
||||
// and may be deferred to uv.
|
||||
.is_file(target)
|
||||
.then(|| target.as_path())
|
||||
.take_if(|target| {
|
||||
// Avoid using the target if it doesn't look like a Python executable, e.g.,
|
||||
// to deny cases like `.venv/bin/foo`
|
||||
target
|
||||
.file_name()
|
||||
.is_some_and(|name| name.starts_with("python"))
|
||||
})
|
||||
.and_then(SystemPath::parent)
|
||||
.and_then(SystemPath::parent)
|
||||
// If not a file, use the path as given and allow let `PythonEnvironment::new`
|
||||
// handle the error.
|
||||
.unwrap_or(target);
|
||||
|
||||
PythonEnvironment::new(root, *origin, system)
|
||||
.and_then(|venv| venv.site_packages_directories(system))?
|
||||
}
|
||||
|
||||
PythonPath::Discover(root) => {
|
||||
tracing::debug!("Discovering virtual environment in `{root}`");
|
||||
let virtual_env_path = discover_venv_in(db.system(), root);
|
||||
|
|
|
@ -145,6 +145,9 @@ pub enum PythonPath {
|
|||
/// [`sys.prefix`]: https://docs.python.org/3/library/sys.html#sys.prefix
|
||||
SysPrefix(SystemPathBuf, SysPrefixPathOrigin),
|
||||
|
||||
/// Resolve a path to an executable (or environment directory) into a usable environment.
|
||||
Resolve(SystemPathBuf, SysPrefixPathOrigin),
|
||||
|
||||
/// Tries to discover a virtual environment in the given path.
|
||||
Discover(SystemPathBuf),
|
||||
|
||||
|
@ -161,6 +164,6 @@ impl PythonPath {
|
|||
}
|
||||
|
||||
pub fn from_cli_flag(path: SystemPathBuf) -> Self {
|
||||
Self::SysPrefix(path, SysPrefixPathOrigin::PythonCliFlag)
|
||||
Self::Resolve(path, SysPrefixPathOrigin::PythonCliFlag)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue