From ece74250fb9d5acfe1d6d48148997fa748151a34 Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Sun, 7 Jun 2026 10:46:09 -0700 Subject: [PATCH] =?UTF-8?q?art=5Fapply:=20statvfs=20pre-flight=20is=20POSI?= =?UTF-8?q?X-only=20=E2=80=94=20Windows=20has=20no=20os.statvfs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Boulder's lock-in question caught it: the read-only pre-flight called os.statvfs unconditionally, which doesn't exist on Windows, and the AttributeError wasn't covered by the except OSError — the whole cover-art apply would have crashed for every Windows install (docker images are Linux, so the reporter was fine; the maintainer wasn't). getattr-guarded now: no statvfs -> skip the pre-flight, per-file EROFS detection (errno is cross-platform) still active. Test pins the no-statvfs path. --- core/metadata/art_apply.py | 7 +++++-- tests/test_art_apply.py | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/core/metadata/art_apply.py b/core/metadata/art_apply.py index fe79d266..faac0b7d 100644 --- a/core/metadata/art_apply.py +++ b/core/metadata/art_apply.py @@ -126,10 +126,13 @@ def apply_art_to_album_files( # Pre-flight: if the mount is read-only, every save below would fail with # EROFS one by one (Tim's report: a wall of per-file warnings and a 777 # chmod that couldn't help). statvfs asks the kernel without writing. + # POSIX-only — Windows has no os.statvfs (and no ':ro' bind mounts); + # there we skip straight to the per-file path, same as before this fix. probe_dir = folder or (os.path.dirname(paths[0]) if paths else None) - if probe_dir: + _statvfs = getattr(os, "statvfs", None) + if probe_dir and _statvfs is not None: try: - if os.statvfs(probe_dir).f_flag & os.ST_RDONLY: + if _statvfs(probe_dir).f_flag & getattr(os, "ST_RDONLY", 1): logger.warning( "Art apply skipped: %s is on a READ-ONLY filesystem " "(docker ':ro' volume mount — chmod cannot fix this)", diff --git a/tests/test_art_apply.py b/tests/test_art_apply.py index a7661ef3..4169eab9 100644 --- a/tests/test_art_apply.py +++ b/tests/test_art_apply.py @@ -203,3 +203,22 @@ def test_apply_normal_failure_not_flagged_read_only(tmp_path, monkeypatch): assert res['read_only_fs'] is False # EACCES is chmod-able, EROFS is not assert res['failed'] == 1 + + +def test_apply_works_without_statvfs_windows(tmp_path, monkeypatch): + """Windows has no os.statvfs — the pre-flight must vanish gracefully, + not crash the apply (Boulder runs on Windows).""" + f = tmp_path / 'a.mp3' + f.write_bytes(b'') + saved = [] + audio = SimpleNamespace(pictures=[], tags=None, add_tags=lambda: None, + save=lambda: saved.append(True)) + monkeypatch.setattr(aa, 'get_mutagen_symbols', lambda: _fake_symbols(audio)) + monkeypatch.setattr(aa, 'embed_album_art_metadata', lambda *a, **k: True) + monkeypatch.setattr(aa, 'download_cover_art', lambda *a, **k: None) + monkeypatch.delattr(aa.os, 'statvfs', raising=False) + + res = aa.apply_art_to_album_files([str(f)], {}, {}, folder=str(tmp_path)) + + assert res['embedded'] == 1 and saved == [True] + assert res['read_only_fs'] is False