From 957da049abd6589ce7810afc5ac9f5da2c247880 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 12 Nov 2025 21:02:22 +0000 Subject: [PATCH] Add HINT validation result for dandiset.yaml in BIDS datasets When BIDS validator encounters dandiset.yaml (not part of BIDS spec), now: - Keeps the existing ERROR about the file not matching BIDS patterns - Adds a new HINT level validation result suggesting to create/update .bidsignore Includes test to verify both ERROR and HINT are generated Co-authored-by: yarikoptic <39889+yarikoptic@users.noreply.github.com> --- dandi/tests/test_validate.py | 20 ++++++++++++++++++++ dandi/validate.py | 26 ++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/dandi/tests/test_validate.py b/dandi/tests/test_validate.py index 5b240eff8..45be0abac 100644 --- a/dandi/tests/test_validate.py +++ b/dandi/tests/test_validate.py @@ -120,6 +120,26 @@ def mock_bids_validate(*args: Any, **kwargs: Any) -> list[ValidationResult]: f"BIDS specification." ) + # Check that there is also a HINT about .bidsignore + validation_hints = [ + r + for r in validation_results + if r.severity is not None and r.severity == Severity.HINT + ] + + # Assert that there is at least one hint + assert len(validation_hints) >= 1 + + # Find the hint about .bidsignore for dandiset.yaml + bidsignore_hint = next( + (h for h in validation_hints if h.id == "DANDI.BIDSIGNORE_DANDISET_YAML"), + None, + ) + assert bidsignore_hint is not None + assert bidsignore_hint.message is not None + assert ".bidsignore" in bidsignore_hint.message + assert dandiset_metadata_file in bidsignore_hint.message + def test_validate_bids_onefile(bids_error_examples: Path, tmp_path: Path) -> None: """ diff --git a/dandi/validate.py b/dandi/validate.py index e67dfb383..7b9e7581b 100644 --- a/dandi/validate.py +++ b/dandi/validate.py @@ -188,12 +188,14 @@ def validate( if r_id not in df_result_ids: # If the error is about the dandiset metadata file, modify # the message in the validation to give the context of DANDI - if ( + # and add a HINT to suggest adding to .bidsignore + is_dandiset_yaml_error = ( r.path is not None and r.dataset_path is not None and r.path.relative_to(r.dataset_path).as_posix() == dandiset_metadata_file - ): + ) + if is_dandiset_yaml_error: r.message = ( f"The dandiset metadata file, `{dandiset_metadata_file}`, " f"is not a part of BIDS specification. Please include a " @@ -205,3 +207,23 @@ def validate( df_results.append(r) df_result_ids.add(r_id) yield r + + # After yielding the error for dandiset.yaml, also yield a HINT + if is_dandiset_yaml_error: + hint = ValidationResult( + id="DANDI.BIDSIGNORE_DANDISET_YAML", + origin=ORIGIN_VALIDATION_DANDI_LAYOUT, + severity=Severity.HINT, + scope=Scope.DATASET, + path=r.dataset_path, + dataset_path=r.dataset_path, + dandiset_path=dandiset_path, + message=( + f"Consider creating or updating a `.bidsignore` file " + f"in the root of your BIDS dataset to ignore " + f"`{dandiset_metadata_file}`. " + f"Add the following line to `.bidsignore`:\n" + f"{dandiset_metadata_file}" + ), + ) + yield hint