Add --json option to tag commands

This commit is contained in:
Ivan Habunek 2023-12-12 09:45:57 +01:00
parent 63691a3637
commit c7e01c77f2
No known key found for this signature in database
GPG Key ID: F5F0623FF5EBCB3D
6 changed files with 132 additions and 48 deletions

View File

@ -1,9 +1,10 @@
0.40.0:
date: TBA
changes:
- "BREAKING: Remove deprecated `--disable-https` option for `login` and `login_cli`, pass the base URL instead"
- "Migrate to `click` for commandline arguments. BC should be mostly preserved, please report any issues."
- "Add shell completion, see: https://toot.bezdomni.net/shell_completion.html"
- "Remove deprecated `--disable-https` option for `login` and `login_cli`, pass the base URL instead"
- "Add `--json` option to tag commands"
0.39.0:
date: 2023-11-23

View File

@ -130,39 +130,6 @@ def test_search_hashtag_json(app, user, run):
assert h3["name"] == "hashtag_z"
def test_tags(run, base_url):
result = run(cli.tags_followed)
assert result.exit_code == 0
assert result.stdout.strip() == "You're not following any hashtags."
result = run(cli.tags_follow, "foo")
assert result.exit_code == 0
assert result.stdout.strip() == "✓ You are now following #foo"
result = run(cli.tags_followed)
assert result.exit_code == 0
assert result.stdout.strip() == f"* #foo\t{base_url}/tags/foo"
result = run(cli.tags_follow, "bar")
assert result.exit_code == 0
assert result.stdout.strip() == "✓ You are now following #bar"
result = run(cli.tags_followed)
assert result.exit_code == 0
assert result.stdout.strip() == "\n".join([
f"* #bar\t{base_url}/tags/bar",
f"* #foo\t{base_url}/tags/foo",
])
result = run(cli.tags_unfollow, "foo")
assert result.exit_code == 0
assert result.stdout.strip() == "✓ You are no longer following #foo"
result = run(cli.tags_followed)
assert result.exit_code == 0
assert result.stdout.strip() == f"* #bar\t{base_url}/tags/bar"
def test_status(app, user, run):
uuid = str(uuid4())
status_id = api.post_status(app, user, uuid).json()["id"]

View File

@ -0,0 +1,84 @@
from toot import cli
from toot.entities import Tag, from_dict, from_dict_list
def test_tags(run, base_url):
result = run(cli.tags)
assert result.exit_code == 0
assert result.stdout.strip() == "You're not following any hashtags."
result = run(cli.tags, "follow", "foo")
assert result.exit_code == 0
assert result.stdout.strip() == "✓ You are now following #foo"
result = run(cli.tags)
assert result.exit_code == 0
assert result.stdout.strip() == f"* #foo\t{base_url}/tags/foo"
result = run(cli.tags, "follow", "bar")
assert result.exit_code == 0
assert result.stdout.strip() == "✓ You are now following #bar"
result = run(cli.tags)
assert result.exit_code == 0
assert result.stdout.strip() == "\n".join([
f"* #bar\t{base_url}/tags/bar",
f"* #foo\t{base_url}/tags/foo",
])
result = run(cli.tags, "unfollow", "foo")
assert result.exit_code == 0
assert result.stdout.strip() == "✓ You are no longer following #foo"
result = run(cli.tags)
assert result.exit_code == 0
assert result.stdout.strip() == f"* #bar\t{base_url}/tags/bar"
result = run(cli.tags, "unfollow", "bar")
assert result.exit_code == 0
assert result.stdout.strip() == "✓ You are no longer following #bar"
result = run(cli.tags)
assert result.exit_code == 0
assert result.stdout.strip() == "You're not following any hashtags."
def test_tags_json(run_json):
result = run_json(cli.tags, "--json")
assert result == []
result = run_json(cli.tags, "follow", "foo", "--json")
tag = from_dict(Tag, result)
assert tag.name == "foo"
assert tag.following is True
result = run_json(cli.tags, "--json")
[tag] = from_dict_list(Tag, result)
assert tag.name == "foo"
assert tag.following is True
result = run_json(cli.tags, "follow", "bar", "--json")
tag = from_dict(Tag, result)
assert tag.name == "bar"
assert tag.following is True
result = run_json(cli.tags, "--json")
tags = from_dict_list(Tag, result)
[bar, foo] = sorted(tags, key=lambda t: t.name)
assert foo.name == "foo"
assert foo.following is True
assert bar.name == "bar"
assert bar.following is True
result = run_json(cli.tags, "unfollow", "foo", "--json")
tag = from_dict(Tag, result)
assert tag.name == "foo"
assert tag.following is False
result = run_json(cli.tags, "unfollow", "bar", "--json")
tag = from_dict(Tag, result)
assert tag.name == "bar"
assert tag.following is False
result = run_json(cli.tags, "--json")
assert result == []

View File

@ -48,9 +48,9 @@ def _status_action(app, user, status_id, action, data=None) -> Response:
return http.post(app, user, url, data=data)
def _tag_action(app, user, tag_name, action):
def _tag_action(app, user, tag_name, action) -> Response:
url = f"/api/v1/tags/{tag_name}/{action}"
return http.post(app, user, url).json()
return http.post(app, user, url)
def create_app(base_url):
@ -499,11 +499,11 @@ def unfollow(app, user, account):
return _account_action(app, user, account, 'unfollow')
def follow_tag(app, user, tag_name):
def follow_tag(app, user, tag_name) -> Response:
return _tag_action(app, user, tag_name, 'follow')
def unfollow_tag(app, user, tag_name):
def unfollow_tag(app, user, tag_name) -> Response:
return _tag_action(app, user, tag_name, 'unfollow')

View File

@ -1,39 +1,52 @@
import click
import json as pyjson
from toot import api
from toot.cli.base import cli, pass_context, Context
from toot.cli.base import cli, pass_context, json_option, Context
from toot.output import print_tag_list, print_warning
@cli.group(invoke_without_command=True)
@json_option
@click.pass_context
def tags(ctx: click.Context):
def tags(ctx: click.Context, json):
"""List, follow, and unfollow tags
When invoked without a command, lists followed tags."""
if ctx.invoked_subcommand is None:
response = api.followed_tags(ctx.obj.app, ctx.obj.user)
print_tag_list(response)
tags = api.followed_tags(ctx.obj.app, ctx.obj.user)
if json:
click.echo(pyjson.dumps(tags))
else:
print_tag_list(tags)
@tags.command()
@click.argument("tag")
@json_option
@pass_context
def follow(ctx: Context, tag: str):
def follow(ctx: Context, tag: str, json: bool):
"""Follow a hashtag"""
tag = tag.lstrip("#")
api.follow_tag(ctx.app, ctx.user, tag)
click.secho(f"✓ You are now following #{tag}", fg="green")
response = api.follow_tag(ctx.app, ctx.user, tag)
if json:
click.echo(response.text)
else:
click.secho(f"✓ You are now following #{tag}", fg="green")
@tags.command()
@click.argument("tag")
@json_option
@pass_context
def unfollow(ctx: Context, tag: str):
def unfollow(ctx: Context, tag: str, json: bool):
"""Unfollow a hashtag"""
tag = tag.lstrip("#")
api.unfollow_tag(ctx.app, ctx.user, tag)
click.secho(f"✓ You are no longer following #{tag}", fg="green")
response = api.unfollow_tag(ctx.app, ctx.user, tag)
if json:
click.echo(response.text)
else:
click.secho(f"✓ You are no longer following #{tag}", fg="green")
# -- Deprecated commands -------------------------------------------------------

View File

@ -409,6 +409,25 @@ class Relationship:
note: str
@dataclass
class TagHistory:
day: str
uses: str
accounts: str
@dataclass
class Tag:
"""
Represents a hashtag used within the content of a status.
https://docs.joinmastodon.org/entities/Tag/
"""
name: str
url: str
history: List[TagHistory]
following: Optional[bool]
# Generic data class instance
T = TypeVar("T")