Skip to content

Commit 5bf6fef

Browse files
author
Maximilien Chaumon
committed
add test
1 parent b25881c commit 5bf6fef

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

mne_bids/tests/test_path.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,86 @@ def test_find_matching_paths(return_bids_test_dir):
12381238
bids_path_01.fpath.unlink() # clean up created file
12391239

12401240

1241+
def test_return_root_paths_entity_aware(tmp_path):
1242+
"""Test that `_return_root_paths` respects `entities['subject']` and
1243+
returns only paths under that subject when provided.
1244+
1245+
This validates the entity-aware optimization added to reduce filesystem
1246+
scanning when the subject (and optionally session) is known.
1247+
"""
1248+
from mne_bids.path import _return_root_paths
1249+
1250+
root = tmp_path / "bids"
1251+
# Create two subjects each with meg and eeg directories and a file
1252+
for subj in ("subjA", "subjB"):
1253+
for dtype in ("meg", "eeg"):
1254+
p = BIDSPath(subject=subj, session="sesA", datatype=dtype, root=root)
1255+
p.mkdir(exist_ok=True)
1256+
# create a predictable dummy data file so glob matches reliably
1257+
ext = "fif" if dtype == "meg" else "edf"
1258+
fname = f"sub-{subj}_ses-sesA_{dtype}.{ext}"
1259+
(p.directory / fname).touch()
1260+
1261+
# Full scan (no entities) should return files for both subjects
1262+
# Pass root as string to match how glob.iglob expects root_dir
1263+
root_str = str(root)
1264+
# ensure directories exist
1265+
assert (root / "sub-subjA").exists()
1266+
all_paths = _return_root_paths(root_str, datatype=("meg", "eeg"), ignore_json=True)
1267+
assert len(all_paths) >= 2
1268+
1269+
# Entity-aware scan for subjA should only return files under sub-subjA
1270+
subj_paths = _return_root_paths(root_str, datatype=("meg", "eeg"), ignore_json=True, entities={"subject": "subjA"})
1271+
assert len(subj_paths) < len(all_paths)
1272+
assert all("sub-subjA" in str(p) for p in subj_paths)
1273+
1274+
1275+
def test_return_root_paths_monkeypatched_glob(monkeypatch):
1276+
"""Unit test for `_return_root_paths` that monkeypatches glob.iglob.
1277+
1278+
This avoids relying on filesystem behavior and asserts that the
1279+
function converts strings returned by glob.iglob into Path objects and
1280+
applies the `ignore_json` filter correctly.
1281+
"""
1282+
from mne_bids.path import _return_root_paths
1283+
1284+
fake_root = "/fake/root"
1285+
1286+
# Simulate iglob returning a mix of json and data files (relative paths)
1287+
fake_results = [
1288+
"sub-subjA/ses-sesA/meg/sub-subjA_ses-sesA_meg.fif",
1289+
"sub-subjA/ses-sesA/meg/sub-subjA_ses-sesA_meg.json",
1290+
"sub-subjB/ses-sesA/eeg/sub-subjB_ses-sesA_eeg.edf",
1291+
]
1292+
1293+
def fake_iglob(pattern, root_dir=None, recursive=False):
1294+
# ensure pattern was constructed as relative to root
1295+
assert str(root_dir) == fake_root
1296+
return iter(fake_results)
1297+
1298+
# monkeypatch glob.iglob to return our fake results
1299+
monkeypatch.setattr("glob.iglob", fake_iglob)
1300+
1301+
# monkeypatch _filter_paths_optimized to avoid filesystem checks
1302+
from mne_bids import path as mb_path
1303+
1304+
def fake_filter(paths, ignore_json):
1305+
# convert returned strings into Path objects rooted at fake_root
1306+
return [Path(fake_root, p) for p in fake_results if (not ignore_json) or (not p.endswith('.json'))]
1307+
1308+
monkeypatch.setattr(mb_path, "_filter_paths_optimized", fake_filter)
1309+
1310+
# ignore_json=True should filter out the .json entry
1311+
paths = _return_root_paths(fake_root, datatype=("meg", "eeg"), ignore_json=True, entities={"subject": "subjA"})
1312+
assert all(isinstance(p, Path) for p in paths)
1313+
# only the .fif entry for subjA should remain
1314+
assert any(p.suffix == ".fif" and "sub-subjA" in str(p) for p in paths)
1315+
1316+
# ignore_json=False should include the .json entry
1317+
paths_all = _return_root_paths(fake_root, datatype=("meg", "eeg"), ignore_json=False, entities={"subject": "subjA"})
1318+
assert any(str(p).endswith(".json") for p in paths_all)
1319+
1320+
12411321
@pytest.mark.filterwarnings(warning_str["meas_date_set_to_none"])
12421322
@pytest.mark.filterwarnings(warning_str["channel_unit_changed"])
12431323
@testing.requires_testing_data

0 commit comments

Comments
 (0)