From 3530553a06ddb8e95544615dee73d73c6ff24acc Mon Sep 17 00:00:00 2001 From: Ivan Habunek Date: Tue, 21 Nov 2023 12:09:10 +0100 Subject: [PATCH] Add --json option to status and thread commands --- tests/test_console.py | 65 ------------------------------------------- toot/api.py | 8 +++--- toot/commands.py | 29 +++++++++---------- toot/console.py | 2 ++ toot/output.py | 4 +-- toot/tui/app.py | 2 +- 6 files changed, 24 insertions(+), 86 deletions(-) diff --git a/tests/test_console.py b/tests/test_console.py index 3b7d5f2..72a114b 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -196,71 +196,6 @@ def test_timeline_with_re(mock_get, monkeypatch, capsys): assert err == "" -@mock.patch('toot.http.get') -def test_thread(mock_get, monkeypatch, capsys): - mock_get.side_effect = [ - MockResponse({ - 'id': '111111111111111111', - 'account': { - 'display_name': 'Frank Zappa', - 'acct': 'fz' - }, - 'created_at': '2017-04-12T15:53:18.174Z', - 'content': "my response in the middle", - 'reblog': None, - 'in_reply_to_id': '111111111111111110', - 'media_attachments': [], - }), - MockResponse({ - 'ancestors': [{ - 'id': '111111111111111110', - 'account': { - 'display_name': 'Frank Zappa', - 'acct': 'fz' - }, - 'created_at': '2017-04-12T15:53:18.174Z', - 'content': "original content", - 'media_attachments': [], - 'reblog': None, - 'in_reply_to_id': None}], - 'descendants': [{ - 'id': '111111111111111112', - 'account': { - 'display_name': 'Frank Zappa', - 'acct': 'fz' - }, - 'created_at': '2017-04-12T15:53:18.174Z', - 'content': "response message", - 'media_attachments': [], - 'reblog': None, - 'in_reply_to_id': '111111111111111111'}], - }), - ] - - console.run_command(app, user, 'thread', ['111111111111111111']) - - calls = [ - mock.call(app, user, '/api/v1/statuses/111111111111111111'), - mock.call(app, user, '/api/v1/statuses/111111111111111111/context'), - ] - mock_get.assert_has_calls(calls, any_order=False) - - out, err = capsys.readouterr() - - assert not err - - # Display order - assert out.index('original content') < out.index('my response in the middle') - assert out.index('my response in the middle') < out.index('response message') - - assert "original content" in out - assert "my response in the middle" in out - assert "response message" in out - assert "Frank Zappa" in out - assert "@fz" in out - assert "111111111111111111" in out - assert "In reply to" in out - @mock.patch('toot.http.get') def test_reblogged_by(mock_get, monkeypatch, capsys): mock_get.return_value = MockResponse([{ diff --git a/toot/api.py b/toot/api.py index cf15bf5..d9a7c18 100644 --- a/toot/api.py +++ b/toot/api.py @@ -296,9 +296,9 @@ def translate(app, user, status_id): return _status_action(app, user, status_id, 'translate') -def context(app, user, status_id): +def context(app, user, status_id) -> Response: url = f"/api/v1/statuses/{status_id}/context" - return http.get(app, user, url).json() + return http.get(app, user, url) def reblogged_by(app, user, status_id): @@ -544,9 +544,9 @@ def verify_credentials(app, user) -> Response: return http.get(app, user, '/api/v1/accounts/verify_credentials') -def single_status(app, user, status_id): +def single_status(app, user, status_id) -> Response: url = f"/api/v1/statuses/{status_id}" - return http.get(app, user, url).json() + return http.get(app, user, url) def get_notifications(app, user, exclude_types=[], limit=20): diff --git a/toot/commands.py b/toot/commands.py index 0fd8307..932aa7f 100644 --- a/toot/commands.py +++ b/toot/commands.py @@ -1,3 +1,4 @@ +from itertools import chain import json import sys import platform @@ -69,25 +70,25 @@ def timeline(app, user, args, generator=None): def status(app, user, args): - status = api.single_status(app, user, args.status_id) - status = from_dict(Status, status) - print_status(status) + response = api.single_status(app, user, args.status_id) + if args.json: + print(response.text) + else: + status = from_dict(Status, response.json()) + print_status(status) def thread(app, user, args): - toot = api.single_status(app, user, args.status_id) - context = api.context(app, user, args.status_id) - thread = [] - for item in context['ancestors']: - thread.append(item) + context_response = api.context(app, user, args.status_id) - thread.append(toot) + if args.json: + print(context_response.text) + else: + toot = api.single_status(app, user, args.status_id).json() + context = context_response.json() - for item in context['descendants']: - thread.append(item) - - statuses = [from_dict(Status, s) for s in thread] - print_timeline(statuses) + statuses = chain(context["ancestors"], [toot], context["descendants"]) + print_timeline(from_dict(Status, s) for s in statuses) def post(app, user, args): diff --git a/toot/console.py b/toot/console.py index 5638502..5f02043 100644 --- a/toot/console.py +++ b/toot/console.py @@ -466,6 +466,7 @@ READ_COMMANDS = [ (["status_id"], { "help": "Show thread for toot.", }), + json_arg, ], require_auth=True, ), @@ -476,6 +477,7 @@ READ_COMMANDS = [ (["status_id"], { "help": "ID of the status to show.", }), + json_arg, ], require_auth=True, ), diff --git a/toot/output.py b/toot/output.py index bf5ee87..d526539 100644 --- a/toot/output.py +++ b/toot/output.py @@ -8,7 +8,7 @@ from toot import settings from toot.utils import get_text, html_to_paragraphs from toot.entities import Account, Instance, Notification, Poll, Status from toot.wcstring import wc_wrap -from typing import List +from typing import Iterable, List from wcwidth import wcswidth @@ -358,7 +358,7 @@ def print_poll(poll: Poll): print_out(poll_footer) -def print_timeline(items: List[Status], width=100): +def print_timeline(items: Iterable[Status], width=100): print_out("─" * width) for item in items: print_status(item, width) diff --git a/toot/tui/app.py b/toot/tui/app.py index b17a444..1e7132a 100644 --- a/toot/tui/app.py +++ b/toot/tui/app.py @@ -251,7 +251,7 @@ class TUI(urwid.Frame): # This is pretty fast, so it's probably ok to block while context is # loaded, can be made async later if needed - context = api.context(self.app, self.user, status.original.id) + context = api.context(self.app, self.user, status.original.id).json() ancestors = [self.make_status(s) for s in context["ancestors"]] descendants = [self.make_status(s) for s in context["descendants"]] statuses = ancestors + [status] + descendants