From 5d9ee44cec19a58cc98b08acde381c159ded826c Mon Sep 17 00:00:00 2001 From: Ivan Habunek Date: Wed, 29 Nov 2023 07:21:03 +0100 Subject: [PATCH] Migrate list commands --- tests/integration/test_lists.py | 97 ++++++++++++++++------------- toot/cli/__init__.py | 1 + toot/cli/lists.py | 104 ++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 41 deletions(-) create mode 100644 toot/cli/lists.py diff --git a/tests/integration/test_lists.py b/tests/integration/test_lists.py index 740eebe..171176e 100644 --- a/tests/integration/test_lists.py +++ b/tests/integration/test_lists.py @@ -1,71 +1,86 @@ -import pytest +from toot import cli from tests.integration.conftest import register_account -pytest.skip("TODO", allow_module_level=True) - def test_lists_empty(run): - out = run("lists") - assert out == "You have no lists defined." + result = run(cli.lists) + assert result.exit_code == 0 + assert result.stdout.strip() == "You have no lists defined." def test_list_create_delete(run): - out = run("list_create", "banana") - assert out == '✓ List "banana" created.' + result = run(cli.list_create, "banana") + assert result.exit_code == 0 + assert result.stdout.strip() == '✓ List "banana" created.' - out = run("lists") - assert "banana" in out + result = run(cli.lists) + assert result.exit_code == 0 + assert "banana" in result.stdout - out = run("list_create", "mango") - assert out == '✓ List "mango" created.' + result = run(cli.list_create, "mango") + assert result.exit_code == 0 + assert result.stdout.strip() == '✓ List "mango" created.' - out = run("lists") - assert "banana" in out - assert "mango" in out + result = run(cli.lists) + assert result.exit_code == 0 + assert "banana" in result.stdout + assert "mango" in result.stdout - out = run("list_delete", "banana") - assert out == '✓ List "banana" deleted.' + result = run(cli.list_delete, "banana") + assert result.exit_code == 0 + assert result.stdout.strip() == '✓ List "banana" deleted.' - out = run("lists") - assert "banana" not in out - assert "mango" in out + result = run(cli.lists) + assert result.exit_code == 0 + assert "banana" not in result.stdout + assert "mango" in result.stdout - out = run("list_delete", "mango") - assert out == '✓ List "mango" deleted.' + result = run(cli.list_delete, "mango") + assert result.exit_code == 0 + assert result.stdout.strip() == '✓ List "mango" deleted.' - out = run("lists") - assert out == "You have no lists defined." + result = run(cli.lists) + assert result.exit_code == 0 + assert result.stdout.strip() == "You have no lists defined." - out = run("list_delete", "mango") - assert out == "List not found" + result = run(cli.list_delete, "mango") + assert result.exit_code == 1 + assert result.stderr.strip() == "Error: List not found" def test_list_add_remove(run, app): acc = register_account(app) - run("list_create", "foo") + run(cli.list_create, "foo") - out = run("list_add", "foo", acc.username) - assert out == f"You must follow @{acc.username} before adding this account to a list." + result = run(cli.list_add, "foo", acc.username) + assert result.exit_code == 1 + assert result.stderr.strip() == f"Error: You must follow @{acc.username} before adding this account to a list." - run("follow", acc.username) + run(cli.follow, acc.username) - out = run("list_add", "foo", acc.username) - assert out == f'✓ Added account "{acc.username}"' + result = run(cli.list_add, "foo", acc.username) + assert result.exit_code == 0 + assert result.stdout.strip() == f'✓ Added account "{acc.username}"' - out = run("list_accounts", "foo") - assert acc.username in out + result = run(cli.list_accounts, "foo") + assert result.exit_code == 0 + assert acc.username in result.stdout # Account doesn't exist - out = run("list_add", "foo", "does_not_exist") - assert out == "Account not found" + result = run(cli.list_add, "foo", "does_not_exist") + assert result.exit_code == 1 + assert result.stderr.strip() == "Error: Account not found" # List doesn't exist - out = run("list_add", "does_not_exist", acc.username) - assert out == "List not found" + result = run(cli.list_add, "does_not_exist", acc.username) + assert result.exit_code == 1 + assert result.stderr.strip() == "Error: List not found" - out = run("list_remove", "foo", acc.username) - assert out == f'✓ Removed account "{acc.username}"' + result = run(cli.list_remove, "foo", acc.username) + assert result.exit_code == 0 + assert result.stdout.strip() == f'✓ Removed account "{acc.username}"' - out = run("list_accounts", "foo") - assert out == "This list has no accounts." + result = run(cli.list_accounts, "foo") + assert result.exit_code == 0 + assert result.stdout.strip() == "This list has no accounts." diff --git a/toot/cli/__init__.py b/toot/cli/__init__.py index 2e9efcf..c1d4a3b 100644 --- a/toot/cli/__init__.py +++ b/toot/cli/__init__.py @@ -1,6 +1,7 @@ from toot.cli.base import cli, Context # noqa from toot.cli.accounts import * +from toot.cli.lists import * from toot.cli.post import * from toot.cli.read import * from toot.cli.statuses import * diff --git a/toot/cli/lists.py b/toot/cli/lists.py new file mode 100644 index 0000000..089a2fa --- /dev/null +++ b/toot/cli/lists.py @@ -0,0 +1,104 @@ +import click + +from toot import api +from toot.cli.base import Context, cli, pass_context +from toot.output import print_list_accounts, print_lists + + +@cli.command() +@pass_context +def lists(ctx: Context): + """List all lists""" + lists = api.get_lists(ctx.app, ctx.user) + + if lists: + print_lists(lists) + else: + click.echo("You have no lists defined.") + + +@cli.command(name="list_accounts") +@click.argument("title", required=False) +@click.option("--id", help="List ID if not title is given") +@pass_context +def list_accounts(ctx: Context, title: str, id: str): + """List the accounts in a list""" + list_id = _get_list_id(ctx, title, id) + response = api.get_list_accounts(ctx.app, ctx.user, list_id) + print_list_accounts(response) + + +@cli.command(name="list_create") +@click.argument("title") +@click.option( + "--replies-policy", + type=click.Choice(["followed", "list", "none"]), + default="none", + help="Replies policy" +) +@pass_context +def list_create(ctx: Context, title: str, replies_policy: str): + """Create a list""" + api.create_list(ctx.app, ctx.user, title=title, replies_policy=replies_policy) + click.secho(f"✓ List \"{title}\" created.", fg="green") + + +@cli.command(name="list_delete") +@click.argument("title", required=False) +@click.option("--id", help="List ID if not title is given") +@pass_context +def list_delete(ctx: Context, title: str, id: str): + """Delete a list""" + list_id = _get_list_id(ctx, title, id) + api.delete_list(ctx.app, ctx.user, list_id) + click.secho(f"✓ List \"{title if title else id}\" deleted.", fg="green") + + +@cli.command(name="list_add") +@click.argument("title", required=False) +@click.argument("account") +@click.option("--id", help="List ID if not title is given") +@pass_context +def list_add(ctx: Context, title: str, account: str, id: str): + """Add an account to a list""" + list_id = _get_list_id(ctx, title, id) + found_account = api.find_account(ctx.app, ctx.user, account) + + try: + api.add_accounts_to_list(ctx.app, ctx.user, list_id, [found_account["id"]]) + except Exception: + # if we failed to add the account, try to give a + # more specific error message than "record not found" + my_accounts = api.followers(ctx.app, ctx.user, found_account["id"]) + found = False + if my_accounts: + for my_account in my_accounts: + if my_account["id"] == found_account["id"]: + found = True + break + if found is False: + raise click.ClickException(f"You must follow @{account} before adding this account to a list.") + raise + + click.secho(f"✓ Added account \"{account}\"", fg="green") + + +@cli.command(name="list_remove") +@click.argument("title", required=False) +@click.argument("account") +@click.option("--id", help="List ID if not title is given") +@pass_context +def list_remove(ctx: Context, title: str, account: str, id: str): + """Remove an account from a list""" + list_id = _get_list_id(ctx, title, id) + found_account = api.find_account(ctx.app, ctx.user, account) + api.remove_accounts_from_list(ctx.app, ctx.user, list_id, [found_account["id"]]) + click.secho(f"✓ Removed account \"{account}\"", fg="green") + + +def _get_list_id(ctx: Context, title, list_id): + if not list_id: + list_id = api.find_list_id(ctx.app, ctx.user, title) + if not list_id: + raise click.ClickException("List not found") + return list_id