Skip to content

Force GC in WSIReader tests to suppress ResourceWarning for unclosed files#8919

Open
vishnukannaujia wants to merge 2 commits into
Project-MONAI:devfrom
vishnukannaujia:5461-wsireader-close-file-handles
Open

Force GC in WSIReader tests to suppress ResourceWarning for unclosed files#8919
vishnukannaujia wants to merge 2 commits into
Project-MONAI:devfrom
vishnukannaujia:5461-wsireader-close-file-handles

Conversation

@vishnukannaujia

Copy link
Copy Markdown

Fixes #5461.

Summary

WSI reader tests emit ResourceWarning: unclosed file <_io.FileIO ...> / BufferedReader for the temp TIFF inputs they exercise (e.g. the CMU-1 generic TIFF). Investigation:

  • Every direct reader.read(...) call site in tests/utils/enums/test_wsireader.py already either uses with reader.read(...) as obj: or explicitly calls obj.close() on the returned WSI object. Those sites are not the leak.
  • The remaining leak comes from LoadImage.__call__ in monai/transforms/io/array.py (around L256–289), which does:
    img = reader.read(filename)
    img_array, meta_data = reader.get_data(img)
    # ... img_array is wrapped into MetaTensor and returned
    # the reader-returned `img` is never closed
    The two test_with_dataloader* tests in this module use LoadImaged(reader=WSIReader, backend=..., ...) and inherit that leak. The temp TIFF handles only get closed when the garbage collector eventually runs, frequently after Python has already emitted the warning.

This PR keeps the fix at test-hygiene scope: add gc.collect() to tearDown of the shared WSIReaderTests.Tests base class. Each of TiffFile.__del__ / OpenSlide.__del__ / CuImage.__del__ closes the underlying file descriptor, so running gc explicitly at the end of every test invokes those finalizers deterministically and eliminates the warning.

Why not change LoadImage / BaseWSIReader

A reader-level or LoadImage-level fix is feasible (e.g. closing img after get_data returns) but is broader in scope, affects all readers, and would need to land alongside changes to the public contract of BaseWSIReader.read (currently documented to return an open WSI object). Happy to follow up with that if a maintainer prefers; this PR was scoped narrowly to the test symptom that the issue raises.

Verify

python -m pytest tests/utils/enums/test_wsireader.py -W error::ResourceWarning -v

Expected: tests pass and no ResourceWarning escalations.

…files

The WSI reader tests emit ResourceWarning ("unclosed file <_io.FileIO ...>"
/ BufferedReader) for the temp TIFFs they exercise (e.g. the CMU-1 generic
TIFF). All direct `reader.read(...)` call sites in this test module already
either use `with` or call `obj.close()` explicitly, so they are not the
leak source.

The remaining leak comes from `LoadImage.__call__`, which calls
`reader.read(filename)` and `reader.get_data(img)`, then returns
`img_array` while letting the reader-returned `img` (the backend handle)
fall out of scope without `close()`. The two `test_with_dataloader*` tests
in this module reach `LoadImage` via `LoadImaged(reader=WSIReader, ...)`
and inherit that leak, so the temp TIFF handles are only closed when the
garbage collector eventually runs - frequently after the warning has
already been emitted.

Add `gc.collect()` to `tearDown` of the shared `WSIReaderTests.Tests`
base class. Each of `TiffFile.__del__` / `OpenSlide.__del__` /
`CuImage.__del__` closes the underlying file descriptor, so running gc
explicitly at the end of every test invokes those finalizers
deterministically and eliminates the warning. This is a focused
test-hygiene change with no impact on production code paths.

Fixes Project-MONAI#5461.

Signed-off-by: Vishnu Kannaujia <vishnu.kannaujia@gmail.com>
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 64ef9daa-33ce-4c2a-82ee-844ba123cee3

📥 Commits

Reviewing files that changed from the base of the PR and between 28feec3 and 63e0e5a.

📒 Files selected for processing (1)
  • tests/utils/enums/test_wsireader.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/utils/enums/test_wsireader.py

📝 Walkthrough

Walkthrough

Adds import gc to tests/utils/enums/test_wsireader.py and introduces a tearDown method on the WSIReaderTests.Tests class that calls gc.collect() after each test. This forces deterministic garbage collection to close any backend WSI file handles (TIFF, OpenSlide, cuCIM) that remain open at test teardown, suppressing ResourceWarning emissions about unclosed files.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title accurately and concisely describes the main change: adding gc.collect() to WSIReader tests to suppress ResourceWarning for unclosed files.
Description check ✅ Passed Description is comprehensive, includes issue reference, clear explanation of the problem and solution, and explains why alternative approaches were not taken.
Linked Issues check ✅ Passed PR directly addresses issue #5461 by eliminating ResourceWarning emissions in WSIReader tests through deterministic garbage collection in tearDown.
Out of Scope Changes check ✅ Passed Changes are limited to test hygiene (adding gc.collect() to tearDown). No production code modifications or changes to public APIs.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/utils/enums/test_wsireader.py (1)

478-486: ⚡ Quick win

Add a Google-style docstring to tearDown.

Line 478 introduces a new definition without a docstring, which violates the file-level Python guideline.

Suggested patch
         def tearDown(self):
+            """Run deterministic cleanup after each test.
+
+            Args:
+                None.
+
+            Returns:
+                None.
+
+            Raises:
+                None.
+            """
             # Force deterministic cleanup of any backend WSI handles that may have
             # leaked through `LoadImage` (which calls `reader.read` and discards the
             # returned object after `get_data`). Without this, the temp TIFFs used
             # by these tests can survive past test teardown long enough for the
             # interpreter to emit ResourceWarning ("unclosed file ..."). Running gc
             # here invokes `TiffFile.__del__` / `OpenSlide.__del__` / `CuImage.__del__`,
             # all of which close the underlying handle.
             gc.collect()

As per coding guidelines, “Docstrings should be present for all definition which describe each variable, return value, and raised exception in the appropriate section of the Google-style of docstrings.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/utils/enums/test_wsireader.py` around lines 478 - 486, The tearDown
method is missing a Google-style docstring, which violates the file-level Python
guideline. Add a proper Google-style docstring to the tearDown method that
describes its purpose. The existing inline comment explaining the deterministic
cleanup and garbage collection behavior should be converted into the docstring
following Google style conventions, including a summary line describing what the
method does. Reference the tearDown method definition when making this change.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/utils/enums/test_wsireader.py`:
- Around line 478-486: The tearDown method is missing a Google-style docstring,
which violates the file-level Python guideline. Add a proper Google-style
docstring to the tearDown method that describes its purpose. The existing inline
comment explaining the deterministic cleanup and garbage collection behavior
should be converted into the docstring following Google style conventions,
including a summary line describing what the method does. Reference the tearDown
method definition when making this change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f8548496-0b87-42ea-84e4-9275d35f9113

📥 Commits

Reviewing files that changed from the base of the PR and between eccefc5 and 28feec3.

📒 Files selected for processing (1)
  • tests/utils/enums/test_wsireader.py

Convert the inline comment on the new ``tearDown`` into a Google-style
docstring so the method satisfies the repository's docstring guideline,
without changing behavior.

Signed-off-by: Vishnu Kannaujia <vishnu.kannaujia@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tests.test_wsireader unclosed file

1 participant