ruff/python/ruff/__main__.py
Jason R. Coombs 42b655b24f
Locate ruff executable in 'bin' directory as installed by 'pip install --target'. (#11450)
Fixes #11246

## Summary

This change adds an intermediate additional search path for
`find_ruff_bin`.

I would have added this path as the last one, except that the last one
is the one reported to the user, so I made this one second to last.

## Test Plan

It's shown to work with this command:

```
 ~ @ pip-run git+https://github.com/jaraco/ruff@feature/honor-install-target-bin -- -m ruff --version
ruff 0.4.4
```

I tried running the same command on Windows, which should work in
theory, but building ruff from source on Windows is complicated. Even
after installing Rust, ruff fails to build when `libmimalloc-sys` fails
to build because `gcc` isn't installed (and the error message points to
a [broken
anchor](https://github.com/rust-lang/cc-rs#compile-time-requirements)).
I was really hoping Rust would get us away from the Windows as
second-class-citizen model :(.
2024-05-16 16:07:22 +00:00

47 lines
1.3 KiB
Python

import os
import sys
import sysconfig
def find_ruff_bin() -> str:
"""Return the ruff binary path."""
ruff_exe = "ruff" + sysconfig.get_config_var("EXE")
scripts_path = os.path.join(sysconfig.get_path("scripts"), ruff_exe)
if os.path.isfile(scripts_path):
return scripts_path
if sys.version_info >= (3, 10):
user_scheme = sysconfig.get_preferred_scheme("user")
elif os.name == "nt":
user_scheme = "nt_user"
elif sys.platform == "darwin" and sys._framework:
user_scheme = "osx_framework_user"
else:
user_scheme = "posix_user"
user_path = os.path.join(
sysconfig.get_path("scripts", scheme=user_scheme), ruff_exe
)
if os.path.isfile(user_path):
return user_path
# Search in `bin` adjacent to package root (as created by `pip install --target`).
pkg_root = os.path.dirname(os.path.dirname(__file__))
target_path = os.path.join(pkg_root, "bin", ruff_exe)
if os.path.isfile(target_path):
return target_path
raise FileNotFoundError(scripts_path)
if __name__ == "__main__":
ruff = os.fsdecode(find_ruff_bin())
if sys.platform == "win32":
import subprocess
completed_process = subprocess.run([ruff, *sys.argv[1:]])
sys.exit(completed_process.returncode)
else:
os.execvp(ruff, [ruff, *sys.argv[1:]])