diff --git a/flit/__init__.py b/flit/__init__.py index 055cfb99..68768d29 100644 --- a/flit/__init__.py +++ b/flit/__init__.py @@ -26,6 +26,15 @@ def find_python_executable(python: Optional[str] = None) -> str: python = os.environ.get("FLIT_INSTALL_PYTHON") if not python: return sys.executable + if os.path.isdir(python): + # Assume it's a virtual environment and look for the environment's + # Python executable. This is the same behavior used by pip. + # + # Try both Unix and Windows paths in case of odd cases like cygwin. + for exe in ("bin/python", "Scripts/python.exe"): + py = os.path.join(python, exe) + if os.path.exists(py): + return os.path.abspath(py) if os.path.isabs(python): # sys.executable is absolute too return python # get absolute filepath of {python} diff --git a/tests/test_find_python_executable.py b/tests/test_find_python_executable.py index 161dc7a2..b3bf563f 100644 --- a/tests/test_find_python_executable.py +++ b/tests/test_find_python_executable.py @@ -1,6 +1,7 @@ -import os +from os.path import isabs, basename, dirname import re import sys +import venv import pytest @@ -20,7 +21,23 @@ def test_abs(): def test_find_in_path(): - assert os.path.isabs(find_python_executable("python")) + assert isabs(find_python_executable("python")) + + +def test_env(tmp_path): + path = tmp_path / "venv" + venv.create(path) + + executable = find_python_executable(path) + assert basename(dirname(dirname(executable))) == "venv" + + +def test_env_abs(tmp_path, monkeypatch): + path = tmp_path / "venv" + venv.create(path) + + monkeypatch.chdir(tmp_path) + assert isabs(find_python_executable("venv")) @pytest.mark.parametrize("bad_python_name", ["pyhton", "ls", "."])