chore: bring the test suite up to ruff's standards

Mostly automatic: empty f-strings, unused imports, formatting. The manual half
was duplicated import blocks stranded mid-file and `== None` assertions, which
become `is None` here because they compare plain attributes -- unlike the
identical rule in filters/book.py, where they build SQL.

Two unused variables are the tests never checking the disk in either
delete_files direction. Left in place under a noqa so the gap stays visible.
This commit is contained in:
2026-08-17 20:56:24 -04:00
parent 0c25f63600
commit 5ec5a4d334
15 changed files with 232 additions and 116 deletions
+43 -34
View File
@@ -1,6 +1,7 @@
import pytest
from httpx import AsyncClient
from pathlib import Path
from litestar.status_codes import HTTP_400_BAD_REQUEST
@pytest.mark.parametrize(
@@ -218,7 +219,9 @@ async def test_list_books_by_id(populated_authenticated_client: AsyncClient) ->
compare a bigint primary key against them. Nothing called it until a screen needed
to fetch a handful of books by id.
"""
response = await populated_authenticated_client.get("/books?ids=1&ids=2&pageSize=10")
response = await populated_authenticated_client.get(
"/books?ids=1&ids=2&pageSize=10"
)
assert response.status_code == 200
assert sorted(book["id"] for book in response.json()["items"]) == [1, 2]
@@ -228,7 +231,7 @@ async def test_get_book_by_id(populated_authenticated_client: AsyncClient) -> No
"""Test retrieving a specific book by ID."""
# Retrieve the book
response = await populated_authenticated_client.get(f"/books/1")
response = await populated_authenticated_client.get("/books/1")
assert response.status_code == 200
book_data = response.json()
@@ -300,13 +303,13 @@ async def test_delete_book_metadata_only(
# Delete book without deleting files
response = await populated_authenticated_client.delete(
f"/books?book_ids=3&delete_files=false&library_id=1"
"/books?book_ids=3&delete_files=false&library_id=1"
)
assert response.status_code == 204
# Verify book is deleted
get_response = await populated_authenticated_client.get(f"/books/3")
get_response = await populated_authenticated_client.get("/books/3")
assert get_response.status_code == 404
@@ -317,7 +320,7 @@ async def test_delete_book_with_files(
# Delete book and files
response = await populated_authenticated_client.delete(
f"/books?book_ids=3&delete_files=true&library_id=1"
"/books?book_ids=3&delete_files=true&library_id=1"
)
assert response.status_code == 204
@@ -330,7 +333,7 @@ async def test_delete_specific_book_files(
# Delete specific file
response = await populated_authenticated_client.delete(
f"/books/1/files?file_ids=1",
"/books/1/files?file_ids=1",
)
assert response.status_code == 204
@@ -347,7 +350,7 @@ async def test_update_reading_progress(
}
response = await populated_authenticated_client.post(
f"/books/progress/1",
"/books/progress/1",
json=progress_data,
)
@@ -423,7 +426,9 @@ async def test_create_books_groups_formats_within_one_folder(
) -> None:
"""Picking a book's own folder yields one book with both formats, not two books."""
epub = Path("tests/data_files/Metamorphosis - Franz Kafka.epub").read_bytes()
pdf = Path("tests/data_files/Calculus Made Easy - Silvanus Thompson.pdf").read_bytes()
pdf = Path(
"tests/data_files/Calculus Made Easy - Silvanus Thompson.pdf"
).read_bytes()
files = [
("files", ("Metamorphosis/Metamorphosis.epub", epub, "application/epub+zip")),
@@ -534,7 +539,9 @@ class TestDuplicateHandling:
"files",
(
"war.epub",
Path("tests/data_files/The Art of War - Sun Tzu.epub").read_bytes(),
Path(
"tests/data_files/The Art of War - Sun Tzu.epub"
).read_bytes(),
"application/epub+zip",
),
)
@@ -550,7 +557,9 @@ class TestDuplicateHandling:
"files",
(
"war.epub",
Path("tests/data_files/The Art of War - Sun Tzu.epub").read_bytes(),
Path(
"tests/data_files/The Art of War - Sun Tzu.epub"
).read_bytes(),
"application/epub+zip",
),
)
@@ -736,7 +745,9 @@ class TestDuplicateBooks:
assert len(merged["files"]) == 2
# The folded record is gone, and the group it formed with it.
assert (await authenticated_client.get(f"/books/{fold['id']}")).status_code == 404
assert (
await authenticated_client.get(f"/books/{fold['id']}")
).status_code == 404
groups = await authenticated_client.get("/books/duplicate-books?library_id=1")
assert groups.json() == []
@@ -786,16 +797,6 @@ class TestDuplicateBooks:
# async def test_edit_book_metadata(authenticated_client: AsyncClient) -> None:
# raise NotImplementedError()
import pytest
import aiofiles
from httpx import AsyncClient
from pathlib import Path
from litestar.status_codes import HTTP_400_BAD_REQUEST
import pytest
from httpx import AsyncClient
from datetime import date
class TestMetadataUpdates:
@pytest.mark.parametrize(
@@ -849,8 +850,10 @@ class TestMetadataUpdates:
(
"authors", # Update with new authors
["New Author 1", "New Author 2"],
lambda data: {a["name"] for a in data["authors"]}
== {"New Author 1", "New Author 2"},
lambda data: (
{a["name"] for a in data["authors"]}
== {"New Author 1", "New Author 2"}
),
),
(
"authors", # Clear authors
@@ -860,8 +863,9 @@ class TestMetadataUpdates:
(
"tags", # Update with new tags
["Tag 1", "Tag 2", "Tag 3"],
lambda data: {t["name"] for t in data["tags"]}
== {"Tag 1", "Tag 2", "Tag 3"},
lambda data: (
{t["name"] for t in data["tags"]} == {"Tag 1", "Tag 2", "Tag 3"}
),
),
(
"tags", # Clear tags
@@ -881,8 +885,10 @@ class TestMetadataUpdates:
(
"identifiers", # Update with new identifiers
{"isbn-13": "978-1234567890", "doi": "10.example/id"},
lambda data: data["identifiers"]
== {"isbn-13": "978-1234567890", "doi": "10.example/id"},
lambda data: (
data["identifiers"]
== {"isbn-13": "978-1234567890", "doi": "10.example/id"}
),
),
(
"identifiers", # Clear identifiers
@@ -1053,7 +1059,7 @@ class TestMetadataUpdates:
result = response.json()
assert result[updated_field] == None
assert result[updated_field] is None
@pytest.mark.parametrize(
("updated_field"),
@@ -1215,7 +1221,9 @@ class TestFileManagement:
pytest.skip("Book has no files")
file_id = book_data["files"][0]["id"]
filename = book_data["files"][0].get("path")
# TODO: this test asserts only the 204 and never checks the disk, so the flag it is
# named for is untested. See TODO.md; drop the noqa when the assertion lands.
filename = book_data["files"][0].get("path") # noqa: F841
# Remove file without deleting from filesystem
response = await populated_authenticated_client.delete(
@@ -1240,7 +1248,8 @@ class TestFileManagement:
book_data = add_response.json()
file_id = book_data["files"][-1]["id"]
file_path = book_data["files"][-1].get("path")
# TODO: as above -- the file is never checked for removal from disk.
file_path = book_data["files"][-1].get("path") # noqa: F841
# Remove file with deletion from filesystem
response = await populated_authenticated_client.delete(
@@ -1295,7 +1304,9 @@ class TestUnnameableFormats:
self, authenticated_client: AsyncClient
) -> None:
response = await authenticated_client.post(
"/books?library_id=1", files=self.upload("Dune.mobi"), data={"library_id": 1}
"/books?library_id=1",
files=self.upload("Dune.mobi"),
data={"library_id": 1},
)
assert response.status_code == 201
@@ -1323,9 +1334,7 @@ class TestUnnameableFormats:
assert detail.status_code == 200
assert detail.json()["files"][0]["content_type"] is None
async def test_the_file_downloads(
self, authenticated_client: AsyncClient
) -> None:
async def test_the_file_downloads(self, authenticated_client: AsyncClient) -> None:
"""Litestar supplies its own media type when the row carries none."""
created = await authenticated_client.post(
"/books?library_id=1",
@@ -1,4 +1,3 @@
import pytest
from httpx import AsyncClient
@@ -200,7 +199,6 @@ async def test_remove_books_from_shelf(
"/books", params={"shelves": shelf_id}
)
assert books_response.status_code == 200
assert books_response.json()["total"] == 2
@@ -42,7 +42,9 @@ def fx_source(tmp_path: Path) -> Path:
cover=True,
formats={"EPUB": EPUB},
)
fixture.add_book(2, "The Art of War", authors=["Sun Tzu"], formats={"EPUB": OTHER_EPUB})
fixture.add_book(
2, "The Art of War", authors=["Sun Tzu"], formats={"EPUB": OTHER_EPUB}
)
fixture.add_book(3, "Metadata Only", authors=["Nobody"])
return fixture.commit()
@@ -95,7 +97,8 @@ async def test_an_uploaded_library_imports(
authenticated_client: AsyncClient, source: Path, tmp_path: Path
) -> None:
status, job = await upload(
authenticated_client, zip_of(source, tmp_path / "out", prefix="Calibre Library/")
authenticated_client,
zip_of(source, tmp_path / "out", prefix="Calibre Library/"),
)
assert status == 202
@@ -278,7 +281,9 @@ async def test_a_second_copy_is_counted_as_a_possible_duplicate(
padded.write_bytes(EPUB.read_bytes() + b"\0" * 64)
fixture = CalibreFixture(tmp_path / "calibre")
fixture.add_book(1, "The Metamorphosis", authors=["Franz Kafka"], formats={"EPUB": EPUB})
fixture.add_book(
1, "The Metamorphosis", authors=["Franz Kafka"], formats={"EPUB": EPUB}
)
fixture.add_book(
2, "The Metamorphosis", authors=["Franz Kafka"], formats={"EPUB": padded}
)
+12 -3
View File
@@ -8,7 +8,9 @@ from pathlib import Path
# Known KOReader hashes for test files
TEST_FILES = {
"Moby Dick; Or, The Whale - Herman Melville.epub": {
"path": Path("tests/data_files/Moby Dick; Or, The Whale - Herman Melville.epub"),
"path": Path(
"tests/data_files/Moby Dick; Or, The Whale - Herman Melville.epub"
),
"hash": "ceeef909ec65653ba77e1380dff998fb",
"content_type": "application/epub+zip",
},
@@ -59,7 +61,9 @@ async def test_add_file_to_book_generates_correct_hash(
first_book = TEST_FILES["Moby Dick; Or, The Whale - Herman Melville.epub"]
first_content = first_book["path"].read_bytes()
files = [("files", (first_book["path"].name, first_content, first_book["content_type"]))]
files = [
("files", (first_book["path"].name, first_content, first_book["content_type"]))
]
data = {"library_id": "1"}
create_response = await authenticated_client.post(
@@ -75,7 +79,12 @@ async def test_add_file_to_book_generates_correct_hash(
second_book = TEST_FILES["Calculus Made Easy - Silvanus Thompson.pdf"]
second_content = second_book["path"].read_bytes()
add_files = [("data", (second_book["path"].name, second_content, second_book["content_type"]))]
add_files = [
(
"data",
(second_book["path"].name, second_content, second_book["content_type"]),
)
]
add_response = await authenticated_client.post(
f"/books/{book_id}/files",
+1 -1
View File
@@ -40,5 +40,5 @@ async def test_create_library(
assert result["name"] == "Test Library"
assert result["root_path"] == f"{tmp_path}/books"
assert result["path_template"] == "{author}/{title}"
assert result["read_only"] == False
assert result["read_only"] is False
assert result["description"] is None