Skip to content

Commit

Permalink
✨ Implemented #14
Browse files Browse the repository at this point in the history
  • Loading branch information
ThatXliner committed May 25, 2024
1 parent 64ac722 commit 228ab0b
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
12 changes: 10 additions & 2 deletions idae/cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""CLI interface."""

import itertools
import platform
import shlex
Expand Down Expand Up @@ -52,7 +53,6 @@ def run( # noqa: PLR0913
ignore_version: Annotated[
bool,
typer.Option(
"--ignore-version",
"-i",
help="Ignore Python version requirements specified in the script",
),
Expand All @@ -71,6 +71,14 @@ def run( # noqa: PLR0913
help="Force idae to use a specific Python version",
),
] = None,
use_latest: Annotated[
bool,
typer.Option(
"-l",
help="Use the latest Python version that satisfies the "
"script's requirements",
),
] = False,
) -> None:
"""Automatically install necessary dependencies to run a Python script.
Expand All @@ -93,7 +101,7 @@ def run( # noqa: PLR0913
executable=sys.executable,
)
if force_version is not None:
python = get_python_or_exit(force_version, console)
python = get_python_or_exit(force_version, console, use_latest)
if pyproject is not None:
script_deps = (
[]
Expand Down
20 changes: 15 additions & 5 deletions idae/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@

if TYPE_CHECKING: # pragma: no cover
from rich.console import Console
from .venv import is_python_cached


def get_python_or_exit(version: str, console: Console) -> findpython.PythonVersion:
def get_python_or_exit(
version: str, console: Console, use_latest: bool,
) -> findpython.PythonVersion:
"""Return a PythonVersion or raise Exit."""
try:
output = get_python(version)
output = get_python(version, use_latest)
except InvalidSpecifier as err:
console.print(f"[red]error: Python version {version} could not be parsed[/red]")
raise typer.Exit(code=1) from err
Expand All @@ -25,7 +28,7 @@ def get_python_or_exit(version: str, console: Console) -> findpython.PythonVersi
return output


def get_python(version: str) -> findpython.PythonVersion | None:
def get_python(version: str, use_latest: bool) -> findpython.PythonVersion | None:
"""Resolve the version string and return a valid Python."""
# Order from latest version to earliest
pythons = {python.version: python for python in findpython.find_all()}
Expand All @@ -36,7 +39,14 @@ def get_python(version: str) -> findpython.PythonVersion | None:
else:
version = f"~={float(version)}"
target = SpecifierSet(version)
cached_candidates = None
uncached_candidates = None
for python_version, python in pythons.items():
if python_version in target:
return python
return None
if use_latest:
return python
if is_python_cached(python.version) and cached_candidates is None:
cached_candidates = python
elif uncached_candidates is None:
uncached_candidates = python
return cached_candidates or uncached_candidates
6 changes: 6 additions & 0 deletions idae/venv.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Utils for venv creation."""

from __future__ import annotations

import platform
Expand Down Expand Up @@ -29,6 +30,11 @@ class Python:
executable: str | PathLike[str]


def is_python_cached(python: str) -> bool:
"""Check if a Python version is cached."""
return (CACHE_DIR / f"{python.version.major}.{python.version.minor}").is_dir()


def get_venv(requirements: list[Requirement], python: Python) -> Path:
"""Create or fetch a cached venv."""
dep_hash = hash_dependencies(requirements)
Expand Down

0 comments on commit 228ab0b

Please sign in to comment.