Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions insto/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import asyncio
import contextlib
import getpass
import importlib.util
import logging
import os
import shlex
Expand All @@ -38,6 +39,7 @@

from insto import __version__
from insto._redact import redact_secrets
from insto.backends import AIOGRAPI_INSTALL_HINT
from insto.commands import ( # noqa: F401 — importing registers all commands
COMMANDS,
CommandUsageError,
Expand Down Expand Up @@ -77,6 +79,11 @@
SETUP_HINT = "no HIKERAPI_TOKEN configured. Run `insto setup` to create one."


def _is_aiograpi_installed() -> bool:
"""Return whether the optional aiograpi backend dependency is importable."""
return importlib.util.find_spec("aiograpi") is not None


# ---------------------------------------------------------------------------
# Logging
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -348,6 +355,8 @@ def _run_setup_non_interactive(*, out: IO[str] | None = None) -> int:
if backend not in {BACKEND_HIKERAPI, BACKEND_AIOGRAPI}:
print(f"--non-interactive: unknown backend {backend!r}", file=sys.stderr)
return 2
if backend == BACKEND_AIOGRAPI and not _is_aiograpi_installed():
print(AIOGRAPI_INSTALL_HINT, file=stream)

token = os.environ.get("HIKERAPI_TOKEN") or (existing.hiker_token if existing else None)
proxy = os.environ.get("HIKERAPI_PROXY") or (existing.hiker_proxy if existing else None)
Expand Down Expand Up @@ -451,6 +460,8 @@ def _run_setup(
if backend not in {BACKEND_HIKERAPI, BACKEND_AIOGRAPI}:
print(f"unknown backend {backend!r}; falling back to hikerapi", file=stream)
backend = BACKEND_HIKERAPI
if backend == BACKEND_AIOGRAPI and not _is_aiograpi_installed():
print(AIOGRAPI_INSTALL_HINT, file=stream)

token_default = existing.hiker_token if existing else None
if backend == BACKEND_HIKERAPI:
Expand Down
56 changes: 55 additions & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,16 @@
@pytest.fixture(autouse=True)
def _isolated_home(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Iterator[Path]:
monkeypatch.setenv(cfgmod.CONFIG_HOME_ENV, str(tmp_path / ".insto"))
for var in (cfgmod.ENV_TOKEN, cfgmod.ENV_PROXY, cfgmod.ENV_OUTPUT_DIR, cfgmod.ENV_DB_PATH):
for var in (
"INSTO_BACKEND",
cfgmod.ENV_TOKEN,
cfgmod.ENV_PROXY,
cfgmod.ENV_OUTPUT_DIR,
cfgmod.ENV_DB_PATH,
cfgmod.ENV_AIOGRAPI_USERNAME,
cfgmod.ENV_AIOGRAPI_PASSWORD,
cfgmod.ENV_AIOGRAPI_TOTP,
):
monkeypatch.delenv(var, raising=False)
yield tmp_path
# Detach our log handlers to not bleed across tests.
Expand Down Expand Up @@ -300,6 +309,34 @@ def prompt(text: str) -> str:
assert "https://hikerapi.com/tokens" in token_prompt


def test_setup_aiograpi_warns_when_optional_dependency_missing(
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str],
) -> None:
monkeypatch.setattr(cli_mod, "_is_aiograpi_installed", lambda: False)

rc = _run_setup(
prompt=_scripted_prompt(
[
"aiograpi",
"instag",
"secret",
"",
"",
"",
"",
]
)
)

assert rc == 0
out = capsys.readouterr().out
assert "aiograpi backend requested" in out
assert "pipx inject insto aiograpi" in out
assert "insto[aiograpi]" in out
assert load_config().backend == "aiograpi"


def test_setup_writes_hikerapi_backend_and_section() -> None:
rc = _run_setup(prompt=_scripted_prompt(["", "tok-1234567890", "", "", ""]))

Expand Down Expand Up @@ -610,3 +647,20 @@ def test_setup_non_interactive_missing_token_fails(capsys: pytest.CaptureFixture
rc = cli_mod.main(["setup", "--non-interactive"]) # no token in env or config
assert rc == 2
assert "HIKERAPI_TOKEN" in capsys.readouterr().err


def test_setup_non_interactive_aiograpi_warns_when_optional_dependency_missing(
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str],
) -> None:
monkeypatch.setattr(cli_mod, "_is_aiograpi_installed", lambda: False)
monkeypatch.setenv("INSTO_BACKEND", "aiograpi")
monkeypatch.setenv("AIOGRAPI_USERNAME", "instag")
monkeypatch.setenv("AIOGRAPI_PASSWORD", "secret")

rc = cli_mod.main(["setup", "--non-interactive"])

assert rc == 0
out = capsys.readouterr().out
assert "pipx inject insto aiograpi" in out
assert load_config().backend == "aiograpi"