mirror of
https://github.com/HKUDS/CLI-Anything.git
synced 2026-10-31 02:42:19 +08:00
fix(calibre): make books list columns dynamic from returned fields
- Render the books list table dynamically based on actual fields returned by list_books() so the displayed columns match --fields without showing always-empty Formats column by default. - Add E2E test verifying list_books honors a custom fields list. Addresses reviewer feedback on PR #223 (Formats column always empty). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
yuhao
co-authored by
Copilot
parent
dfc361325f
commit
6229641a37
@@ -264,15 +264,20 @@ def books_list(ctx, search, sort, limit, fields):
|
||||
if not book_list:
|
||||
click.echo(" No books found.")
|
||||
else:
|
||||
click.echo(f" {'ID':<5} {'Title':<40} {'Authors':<30} {'Formats'}")
|
||||
click.echo(f" {'─'*5} {'─'*40} {'─'*30} {'─'*20}")
|
||||
# Determine columns from actual returned fields (id is always first)
|
||||
actual_fields = list(book_list[0].keys())
|
||||
non_id_fields = [f for f in actual_fields if f != "id"]
|
||||
|
||||
# Build header dynamically
|
||||
header = f" {'ID':<5} " + " ".join(f"{f.capitalize():<30}" for f in non_id_fields)
|
||||
sep = f" {'─'*5} " + " ".join(f"{'─'*30}" for _ in non_id_fields)
|
||||
click.echo(header)
|
||||
click.echo(sep)
|
||||
for b in book_list:
|
||||
click.echo(
|
||||
f" {b.get('id', ''):<5} "
|
||||
f"{str(b.get('title', ''))[:40]:<40} "
|
||||
f"{str(b.get('authors', ''))[:30]:<30} "
|
||||
f"{b.get('formats', '')}"
|
||||
row = f" {b.get('id', ''):<5} " + " ".join(
|
||||
f"{str(b.get(f, ''))[:30]:<30}" for f in non_id_fields
|
||||
)
|
||||
click.echo(row)
|
||||
|
||||
|
||||
@books.command("search")
|
||||
|
||||
@@ -199,6 +199,21 @@ class TestLibraryOperations(CalibreTestMixin, unittest.TestCase):
|
||||
self.assertIn("title", book)
|
||||
print(f"\n list_books[0]: {book}")
|
||||
|
||||
def test_list_books_custom_fields(self):
|
||||
"""list_books with explicit fields returns exactly those fields per book."""
|
||||
from cli_anything.calibre.core.library import list_books
|
||||
requested = ["id", "title", "tags"]
|
||||
books = list_books(self.lib_dir, fields=requested)
|
||||
self.assertGreater(len(books), 0)
|
||||
book = books[0]
|
||||
# Requested fields must be present
|
||||
for field in requested:
|
||||
self.assertIn(field, book, f"Missing field: {field}")
|
||||
# Non-requested fields must be absent
|
||||
for field in ("authors", "series", "rating"):
|
||||
self.assertNotIn(field, book, f"Unexpected field: {field}")
|
||||
print(f"\n list_books(fields={requested})[0]: {book}")
|
||||
|
||||
def test_search_books(self):
|
||||
from cli_anything.calibre.core.library import search_books
|
||||
ids = search_books(self.lib_dir, "title:Foundation")
|
||||
|
||||
Reference in New Issue
Block a user