fix(reader): ArrowReader silently returns an empty dataset for a .parquetbundle path - #431
Open
jcoludar wants to merge 1 commit into
Open
fix(reader): ArrowReader silently returns an empty dataset for a .parquetbundle path#431jcoludar wants to merge 1 commit into
jcoludar wants to merge 1 commit into
Conversation
Every probe in _load_data is an .exists() test with an empty-frame fallback, so ArrowReader(Path) reported 0 proteins / 0 projections / format_version 1 and raised nothing for: - a .parquetbundle FILE (the documented distribution format) - a directory that does not exist - a directory containing no ProtSpace tables The try/except only fires on a read error, and a path that does not exist is never read, so it never triggered. Add _validate_data_path(), called before the try so its ValueError is not re-wrapped. The bundle case names extract_bundle_to_dir() in the message, since that is what the existing callers already do. The check is "at least one core file" rather than "all three": directories carrying only selected_annotations.parquet are legitimate and test_bundle_version.py builds exactly those.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What happened
We handed
ArrowReadera.parquetbundle— the documented distribution format — to inspect a dataset. It returned successfully:No exception, no warning, not even a DEBUG log. We only noticed because the file was 189 KB and "0 proteins" did not square with that.
Why
ArrowReaderexpects a directory of loose.parquetfiles. Every probe in_load_datais an.exists()test with an empty-frame fallback:For a file path,
data.parquetbundle/selected_annotations.parquetnever exists, so all three frames fall back to empty and_build_data_structureiterates zero rows.format_versionis never assigned, soget_format_version()returns its default of 1.The
try/exceptaround the block only fires on a read error. A path that does not exist is never read, so it never triggers.The same silence covers two more inputs:
.parquetbundlefile[][][]['UMAP_2']What this changes
Adds
_validate_data_path(), called as the first statement of_load_data— before thetry, so itsValueErroris not re-wrapped by the handler into a misleading "Error loading Arrow data" message..parquetbundlefile →ValueErrornamingextract_bundle_to_dir(), which is what every existing caller already doesValueErrorFileNotFoundErrorValueErrorThe check is "at least one core file", not "all three". Directories carrying only
selected_annotations.parquetare legitimate, andtest_bundle_version.pybuilds exactly those — requiring all three would break it.Why raise rather than auto-extract
Both existing resolvers already convert bundle → directory before constructing the reader (
main.detect_data_type, anddetect_data_formatinadd_annotation_style.py, which returns"parquet"only forpath.is_dir()), and both raise on bad input. Extracting inside__init__would also mint an uncleanedmkdtempas a hidden side effect of construction. The directory-only contract looks deliberate, so this makes it explicit instead of changing it.Blast radius
Checked every caller. All CLI/dash paths (
app.py,add_annotation_style.py) extract bundles first; the rest construct from a dict and never reach this code. No caller relies on the empty fallback.One behaviour change worth flagging:
main.detect_data_typeaccepts any directory containing any*.parquet, so a directory holding only e.g.statistics.parquetpreviously produced a silent empty viewer and will now raise. That seems like the right outcome, but it is a change.Verification
test_bundle_version.py,test_settings_converter.py,test_display_decode.py,test_bundle_settings.py: 61 passed.ValueError; missing directory →FileNotFoundError; directory with onlyselected_annotations.parquet→ still loads (2 proteins).Related
While tracing this we noticed the same swallow-and-continue shape twice more in this file:
_build_data_structuredoesexcept json.JSONDecodeError: passon a corruptinfo_json(projection parameters vanish silently), and_load_visualization_statelogs a settings-load failure at DEBUG only, invisible at default verbosity.test_settings_converter.pyrecords that the latter has already caused a real regression once — "ArrowReader swallowed, so every legend colour/shape vanished silently". Left alone here to keep this PR to one change; happy to follow up.