Fail the same way on JSON of an unexpected shape

json.loads succeeding does not mean the result is a list of objects with an
id. A dict, an entry without an id, or a scalar raised TypeError or KeyError,
which escaped unhandled and defeated the point of the change. Both cases now
raise DaemonError, and the original exception is chained so the cause is
visible.
This commit is contained in:
Maxim Shulga committed 2026-08-02 17:33:45 -07:00
1 parent b75863ba51
commit 2e18a774f2
2 files changed
+32 -1

No files matched your search

+10 -1
View File
@@ -281,9 +281,18 @@ class SeafileClient:
try: try:
libraries = json.loads(out.decode()) libraries = json.loads(out.decode())
except (UnicodeDecodeError, ValueError) as err: except (UnicodeDecodeError, ValueError) as err:
raise DaemonError(f"Cannot read the library list from seaf-cli: {err}") raise DaemonError(
f"Cannot read the library list from seaf-cli: {err}"
) from err
# Valid JSON is not necessarily the expected shape, and an unexpected
# one must fail the same way rather than as a bare TypeError.
try:
return {lib["id"] for lib in libraries} return {lib["id"] for lib in libraries}
except (KeyError, TypeError) as err:
raise DaemonError(
f"Unexpected library list from seaf-cli: {err}"
) from err
def configure(self, args: argparse.Namespace, check_for_daemon: bool = True): def configure(self, args: argparse.Namespace, check_for_daemon: bool = True):
need_restart = False need_restart = False
+22
View File
@@ -213,3 +213,25 @@ def test_local_libraries_reports_a_failed_command(client, monkeypatch):
run_returning(monkeypatch, b"", returncode=1) run_returning(monkeypatch, b"", returncode=1)
with pytest.raises(DaemonError): with pytest.raises(DaemonError):
client.get_local_libraries() client.get_local_libraries()
@pytest.mark.parametrize("payload", [
b'{"name": "Docs"}', # an object where a list is expected
b'[{"name": "Docs"}]', # an entry with no id
b'["Docs"]', # entries that are not objects
b'[null]',
b'null',
b'42',
])
def test_local_libraries_reports_unexpected_json_shapes(client, monkeypatch, payload):
"""Valid JSON of the wrong shape must not escape as a raw TypeError."""
run_returning(monkeypatch, payload)
with pytest.raises(DaemonError):
client.get_local_libraries()
def test_local_libraries_error_keeps_the_original_cause(client, monkeypatch):
run_returning(monkeypatch, b"not json at all")
with pytest.raises(DaemonError) as err:
client.get_local_libraries()
assert err.value.__cause__ is not None