diff --git a/src/reader/_cli.py b/src/reader/_cli.py index 0c7c5ee2..e19c3763 100644 --- a/src/reader/_cli.py +++ b/src/reader/_cli.py @@ -1,4 +1,5 @@ import functools +import json import logging import os.path import shutil @@ -9,6 +10,7 @@ import click import reader +from reader._hash_utils import _json_default from . import make_reader from . import StorageError @@ -376,25 +378,38 @@ def list_cmd(): @list_cmd.command() +@click.option( + '--json', + 'json_output', + is_flag=True, + help='Output as JSON.', +) @pass_reader -def feeds(reader): +def feeds(reader, json_output): """List all the feeds.""" for feed in reader.get_feeds(): - click.echo(feed.url) + if json_output: + click.echo(json.dumps(feed, default=_json_default)) + else: + click.echo(feed.url) @list_cmd.command() +@click.option( + '--json', + 'json_output', + is_flag=True, + help='Output as JSON.', +) @pass_reader -def entries(reader): - """List all the entries. - - Outputs one line per entry in the following format: - - - - """ +def entries(reader, json_output): + """List all the entries.""" for entry in reader.get_entries(): - click.echo(f"{entry.feed.url} {entry.link or entry.id}") + if json_output: + entry = entry._replace(_sequence=None) + click.echo(json.dumps(entry, default=_json_default)) + else: + click.echo(f"{entry.feed.url} {entry.link or entry.id}") @cli.group() diff --git a/tests/test_cli.py b/tests/test_cli.py index aef2a667..58c8ca81 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,3 +1,4 @@ +import json as _json import logging import os import pathlib @@ -66,7 +67,7 @@ def test_cli(db_path, data_dir, monkeypatch): expected = {'url_base': url_base, 'rel_base': rel_base} exec(data_dir.joinpath(feed_filename + '.py').read_text(), expected) - runner = CliRunner(catch_exceptions=False) + runner = CliRunner() # remove deprecated catch_exceptions argument def invoke(*args): return runner.invoke(cli, ('--db', db_path, '--feed-root', '') + args) @@ -116,6 +117,19 @@ def invoke(*args): (feed_path, e.link or e.id) for e in expected['entries'] } + result = invoke('list', 'feeds', '--json') + assert result.exit_code == 0 + feeds = list(map(_json.loads, result.output.splitlines())) + assert len(feeds) == 1 + assert feeds[0]['url'] == feed_path + + result = invoke('list', 'entries', '--json') + assert result.exit_code == 0 + entries_data = list(map(_json.loads, result.output.splitlines())) + assert { + (item['feed']['url'], item['link'] or item['id']) for item in entries_data + } == {(feed_path, e.link or e.id) for e in expected['entries']} + result = invoke('search', 'status') assert result.exit_code == 0 assert 'search: disabled' in result.output @@ -174,7 +188,7 @@ def raise_exception_plugin(thing): def test_cli_plugin(db_path, monkeypatch, tests_dir): monkeypatch.syspath_prepend(tests_dir) - runner = CliRunner() + runner = CliRunner(catch_exceptions=False) with pytest.raises(PluginError): result = runner.invoke(