From 94e08537bc7dd7b3c131c8f756afc1d9025ff499 Mon Sep 17 00:00:00 2001 From: Jonas Boos Date: Sun, 10 May 2026 19:30:46 +0000 Subject: [PATCH] TST: Surface worker thread exceptions in download_test_pdfs Previously, `download_test_pdfs()` called `concurrent.futures.wait(futures)` but never iterated the returned futures or called `.result()` on them. Any exception raised in a worker thread was silently captured, causing confusing downstream FileNotFoundError when tests tried to open missing files. Replace `wait()` with `as_completed()` + `.result()` so that download failures are surfaced immediately at the source. Also fix a race condition this exposed: multiple threads could race on `cache_dir.mkdir()`, raising `FileExistsError` when the directory was created by another thread between the `exists()` check and the `mkdir()` call. Use `mkdir(exist_ok=True)` instead of the check-then-create pattern. Closes #3728 --- tests/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/__init__.py b/tests/__init__.py index a922bd78a3..db7f85e0f0 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -61,8 +61,7 @@ def get_data_from_url(*, url: Optional[str] = None, name: str) -> bytes: cache_dir = Path("tests", "pdf_cache").resolve() else: cache_dir = Path(__file__).parent / "pdf_cache" - if not cache_dir.exists(): - cache_dir.mkdir() + cache_dir.mkdir(exist_ok=True) cache_path = cache_dir / name if url is not None: @@ -134,7 +133,8 @@ def download_test_pdfs() -> None: executor.submit(get_data_from_url, url=pdf["url"], name=pdf["local_filename"]) for pdf in pdfs ] - concurrent.futures.wait(futures) + for future in concurrent.futures.as_completed(futures): + future.result() # re-raises any exception from the worker thread class PILContext: