From 23064171451d09bacc7bcc7d660f850e3279b4cc Mon Sep 17 00:00:00 2001 From: DavHau Date: Fri, 17 Nov 2023 17:56:07 +0700 Subject: [PATCH] api/flake/list_history: init Add an api endpoint to list the history of clan flakes that have been interacted with Also add `clan flake list` --- pkgs/clan-cli/clan_cli/flakes/__init__.py | 3 ++ pkgs/clan-cli/clan_cli/flakes/list_history.py | 33 +++++++++++++++++++ pkgs/clan-cli/clan_cli/webui/routers/flake.py | 6 ++++ pkgs/clan-cli/tests/test_flake_api.py | 24 ++++++++++++++ pkgs/clan-cli/tests/test_flakes_cli.py | 19 +++++++++++ 5 files changed, 85 insertions(+) create mode 100644 pkgs/clan-cli/clan_cli/flakes/list_history.py diff --git a/pkgs/clan-cli/clan_cli/flakes/__init__.py b/pkgs/clan-cli/clan_cli/flakes/__init__.py index 2c9c82c08..8c36f76e7 100644 --- a/pkgs/clan-cli/clan_cli/flakes/__init__.py +++ b/pkgs/clan-cli/clan_cli/flakes/__init__.py @@ -2,6 +2,7 @@ import argparse from clan_cli.flakes.add import register_add_parser +from clan_cli.flakes.list_history import register_list_parser from .create import register_create_parser @@ -18,3 +19,5 @@ def register_parser(parser: argparse.ArgumentParser) -> None: register_create_parser(create_parser) add_parser = subparser.add_parser("add", help="Add a clan flake") register_add_parser(add_parser) + list_parser = subparser.add_parser("list", help="List clan flakes") + register_list_parser(list_parser) diff --git a/pkgs/clan-cli/clan_cli/flakes/list_history.py b/pkgs/clan-cli/clan_cli/flakes/list_history.py new file mode 100644 index 000000000..ff2bab0b9 --- /dev/null +++ b/pkgs/clan-cli/clan_cli/flakes/list_history.py @@ -0,0 +1,33 @@ +# !/usr/bin/env python3 +import argparse +from pathlib import Path + +from pydantic import AnyUrl +from pydantic.tools import parse_obj_as + +from clan_cli.dirs import user_history_file + +DEFAULT_URL: AnyUrl = parse_obj_as( + AnyUrl, + "git+https://git.clan.lol/clan/clan-core?new-clan", +) + + +def list_history() -> list[Path]: + user_history_file().parent.mkdir(parents=True, exist_ok=True) + if not user_history_file().exists(): + return [] + # read path lines from history file + with open(user_history_file(), "r") as f: + lines = f.readlines() + return [Path(line.strip()) for line in lines] + + +def list_history_command(args: argparse.Namespace) -> None: + for path in list_history(): + print(path) + + +# takes a (sub)parser and configures it +def register_list_parser(parser: argparse.ArgumentParser) -> None: + parser.set_defaults(func=list_history_command) diff --git a/pkgs/clan-cli/clan_cli/webui/routers/flake.py b/pkgs/clan-cli/clan_cli/webui/routers/flake.py index babf1c5c2..b1c2dbb56 100644 --- a/pkgs/clan-cli/clan_cli/webui/routers/flake.py +++ b/pkgs/clan-cli/clan_cli/webui/routers/flake.py @@ -6,6 +6,7 @@ from typing import Annotated from fastapi import APIRouter, Body, HTTPException, status from pydantic import AnyUrl +from clan_cli import flakes from clan_cli.webui.api_inputs import ( FlakeCreateInput, ) @@ -50,6 +51,11 @@ async def add_flake(flake_dir: Path) -> None: await add.add_flake(flake_dir) +@router.get("/api/flake/list_history", tags=[Tags.flake]) +async def list_flakes() -> list[Path]: + return flakes.list_history.list_history() + + # TODO: Check for directory traversal @router.get("/api/flake/attrs", tags=[Tags.flake]) async def inspect_flake_attrs(url: AnyUrl | Path) -> FlakeAttrResponse: diff --git a/pkgs/clan-cli/tests/test_flake_api.py b/pkgs/clan-cli/tests/test_flake_api.py index 0d598a19d..ba6efc4e9 100644 --- a/pkgs/clan-cli/tests/test_flake_api.py +++ b/pkgs/clan-cli/tests/test_flake_api.py @@ -23,6 +23,30 @@ def test_flake_add( assert open(user_history_file()).read().strip() == str(test_flake.path) +def test_flake_list( + api: TestClient, test_flake: FlakeForTest, temporary_home: Path +) -> None: + response = api.get( + "/api/flake/list_history", + ) + assert response.status_code == 200, response.text + assert response.json() == [] + + # add the test_flake + response = api.put( + f"/api/flake/add?flake_dir={str(test_flake.path)}", + json={}, + ) + assert response.status_code == 200, response.text + + # list the flakes again + response = api.get( + "/api/flake/list_history", + ) + assert response.status_code == 200, response.text + assert response.json() == [str(test_flake.path)] + + @pytest.mark.impure def test_inspect_ok(api: TestClient, test_flake_with_core: FlakeForTest) -> None: params = {"url": str(test_flake_with_core.path)} diff --git a/pkgs/clan-cli/tests/test_flakes_cli.py b/pkgs/clan-cli/tests/test_flakes_cli.py index 8cb33dc63..e0f198e20 100644 --- a/pkgs/clan-cli/tests/test_flakes_cli.py +++ b/pkgs/clan-cli/tests/test_flakes_cli.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING from cli import Cli from fixtures_flakes import FlakeForTest +from pytest import CaptureFixture from clan_cli.dirs import user_history_file @@ -24,3 +25,21 @@ def test_flakes_add( history_file = user_history_file() assert history_file.exists() assert open(history_file).read().strip() == str(test_flake.path) + + +def test_flakes_list( + capsys: CaptureFixture, + test_flake: FlakeForTest, +) -> None: + cli = Cli() + cmd = [ + "flakes", + "list", + ] + + cli.run(cmd) + assert str(test_flake.path) not in capsys.readouterr().out + + cli.run(["flakes", "add", str(test_flake.path)]) + cli.run(cmd) + assert str(test_flake.path) in capsys.readouterr().out