Skip to content

Commit

Permalink
feat(bootstrap): ratchet the base Python detection effort level up to…
Browse files Browse the repository at this point in the history
… an 11/10
  • Loading branch information
achidlow committed Dec 16, 2022
1 parent df304c9 commit 687667c
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 8 deletions.
37 changes: 35 additions & 2 deletions src/algokit/core/bootstrap.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import platform
import sys
from pathlib import Path
from shutil import copyfile, which
Expand Down Expand Up @@ -126,5 +127,37 @@ def _get_python_paths() -> Iterator[str]:
for python_name in ("python3", "python"):
if python_path := which(python_name):
yield python_path
# need to resolve symlinks in (expected case) of algokit executing in a venv
yield str(Path(sys.executable).resolve())
python_base_path = _get_base_python_path()
if python_base_path is not None:
yield python_base_path


def _get_base_python_path() -> str | None:
this_python: str | None = sys.executable
if not this_python:
# Not: can be empty or None... yikes! unlikely though
# https://docs.python.org/3.10/library/sys.html#sys.executable
return None
# not in venv... not recommended to install algokit this way, but okay
if sys.prefix == sys.base_prefix:
return this_python
this_python_path = Path(this_python)
# try resolving symlink, this should be default on *nix
try:
if this_python_path.is_symlink():
return str(this_python_path.resolve())
except (OSError, RuntimeError):
pass
# otherwise, try getting an internal value which should be set when running in a .venv
# this will be the value of `home = <path>` in pyvenv.cfg if it exists
if base_home := getattr(sys, "_home", None):
base_home_path = Path(base_home)
is_windows = platform.system() == "Windows"
for name in ("python", "python3", f"python3.{sys.version_info.minor}"):
candidate_path = base_home_path / name
if is_windows:
candidate_path = candidate_path.with_suffix(".exe")
if candidate_path.is_file():
return str(candidate_path)
# give up, we tried...
return this_python
33 changes: 27 additions & 6 deletions tests/bootstrap/test_bootstrap_poetry.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import sys
from pathlib import Path
from unittest.mock import MagicMock

import pytest
Expand All @@ -11,7 +10,14 @@
from utils.proc_mock import ProcMock


python_base_executable = str(Path(sys.executable).resolve())
@pytest.fixture(scope="module")
def python_base_executable() -> str:
from algokit.core.bootstrap import _get_base_python_path

value = _get_base_python_path()
if value is None:
pytest.fail("Python base detection failed, this should work (even in CI)")
return value


@pytest.fixture()
Expand All @@ -28,6 +34,12 @@ def which(cmd: str) -> str | None:
return mock


def test_base_python_path(python_base_executable: str):
"""When running in a venv (expected test mode), we should be able to resolve to base python.
Otherwise, they should be the same"""
assert (python_base_executable == sys.executable) == (sys.prefix == sys.base_prefix)


def test_bootstrap_poetry_with_poetry(proc_mock: ProcMock):
result = invoke("bootstrap poetry")

Expand Down Expand Up @@ -75,7 +87,10 @@ def test_bootstrap_poetry_without_poetry_failed_poetry_path(proc_mock: ProcMock)
indirect=["system_python_paths"],
)
def test_bootstrap_poetry_without_poetry_or_pipx_path(
request: FixtureRequest, proc_mock: ProcMock, system_python_paths: MagicMock
request: FixtureRequest,
proc_mock: ProcMock,
system_python_paths: MagicMock,
python_base_executable: str,
):
proc_mock.should_fail_on("poetry --version")
proc_mock.should_fail_on("pipx --version")
Expand All @@ -87,7 +102,9 @@ def test_bootstrap_poetry_without_poetry_or_pipx_path(


def test_bootstrap_poetry_without_poetry_or_pipx_path_failed_install(
proc_mock: ProcMock, system_python_paths: MagicMock
proc_mock: ProcMock,
system_python_paths: MagicMock,
python_base_executable: str,
):
proc_mock.should_fail_on("poetry --version")
proc_mock.should_fail_on("pipx --version")
Expand All @@ -100,7 +117,9 @@ def test_bootstrap_poetry_without_poetry_or_pipx_path_failed_install(


def test_bootstrap_poetry_without_poetry_or_pipx_path_failed_poetry_path(
proc_mock: ProcMock, system_python_paths: MagicMock
proc_mock: ProcMock,
system_python_paths: MagicMock,
python_base_executable: str,
):
proc_mock.should_fail_on("poetry --version")
proc_mock.should_fail_on("pipx --version")
Expand All @@ -113,7 +132,9 @@ def test_bootstrap_poetry_without_poetry_or_pipx_path_failed_poetry_path(


def test_bootstrap_poetry_without_poetry_or_pipx_path_or_pipx_module(
proc_mock: ProcMock, system_python_paths: MagicMock
proc_mock: ProcMock,
system_python_paths: MagicMock,
python_base_executable: str,
):
proc_mock.should_fail_on("poetry --version")
proc_mock.should_fail_on("pipx --version")
Expand Down

0 comments on commit 687667c

Please sign in to comment.