diff --git a/mne_bids/tests/conftest.py b/mne_bids/tests/conftest.py index b774085ee..6dd706cf9 100644 --- a/mne_bids/tests/conftest.py +++ b/mne_bids/tests/conftest.py @@ -33,3 +33,16 @@ def _validate(bids_root): run_subprocess(cmd, shell=shell) return _validate + + +# Deal with: +# Auto-close()ing of figures upon backend switching is deprecated since 3.8 and will +# be removed in 3.10. To suppress this warning, explicitly call plt.close('all') +# first. +@pytest.fixture(autouse=True) +def close_all(): + """Close all matplotlib plots, regardless of test status.""" + import matplotlib.pyplot as plt + + yield + plt.close("all") diff --git a/mne_bids/tests/test_path.py b/mne_bids/tests/test_path.py index 89fc33fb3..945d45736 100644 --- a/mne_bids/tests/test_path.py +++ b/mne_bids/tests/test_path.py @@ -1337,7 +1337,12 @@ def test_find_emptyroom_no_meas_date(tmp_path): write_raw_bids(raw, bids_path, overwrite=True) os.remove(op.join(bids_root, "participants.tsv")) - with pytest.warns(RuntimeWarning, match="Could not retrieve .* date"): + with ( + pytest.warns(RuntimeWarning, match="Could not retrieve .* date"), + pytest.warns(RuntimeWarning, match="participants.tsv file not found"), + pytest.warns(RuntimeWarning, match=r"Did not find any channels\.tsv"), + pytest.warns(RuntimeWarning, match=r"Did not find any meg\.json"), + ): bids_path.find_empty_room() diff --git a/mne_bids/tests/test_read.py b/mne_bids/tests/test_read.py index 46be05053..b5830bc78 100644 --- a/mne_bids/tests/test_read.py +++ b/mne_bids/tests/test_read.py @@ -429,7 +429,11 @@ def test_get_head_mri_trans(tmp_path): t1_bids_path = _bids_path.copy().update( root=tmp_path / "mri_root", task=None, run=None ) - with pytest.warns(RuntimeWarning, match="Did not find any channels.tsv"): + with ( + pytest.warns(RuntimeWarning, match="Did not find any channels.tsv"), + pytest.warns(RuntimeWarning, match=r"Did not find any eeg\.json"), + pytest.warns(RuntimeWarning, match=r"participants\.tsv file not found"), + ): get_head_mri_trans( bids_path=electrophys_bids_path, t1_bids_path=t1_bids_path, @@ -439,25 +443,31 @@ def test_get_head_mri_trans(tmp_path): # bids_path without datatype is deprecated bids_path = electrophys_bids_path.copy().update(datatype=None) - with pytest.raises(FileNotFoundError): # defaut location is all wrong! - with pytest.warns(DeprecationWarning, match="no datatype"): - get_head_mri_trans( - bids_path=bids_path, - t1_bids_path=t1_bids_path, - fs_subject="sample", - fs_subjects_dir=subjects_dir, - ) + # defaut location is all wrong! + with ( + pytest.raises(FileNotFoundError), + pytest.warns(DeprecationWarning, match="did not have a datatype"), + ): + get_head_mri_trans( + bids_path=bids_path, + t1_bids_path=t1_bids_path, + fs_subject="sample", + fs_subjects_dir=subjects_dir, + ) # bids_path without suffix is deprecated bids_path = electrophys_bids_path.copy().update(suffix=None) - with pytest.raises(FileNotFoundError): # defaut location is all wrong! - with pytest.warns(DeprecationWarning, match="no datatype"): - get_head_mri_trans( - bids_path=bids_path, - t1_bids_path=t1_bids_path, - fs_subject="sample", - fs_subjects_dir=subjects_dir, - ) + # defaut location is all wrong! + with ( + pytest.raises(FileNotFoundError), + pytest.warns(DeprecationWarning, match="did not have a suffix"), + ): + get_head_mri_trans( + bids_path=bids_path, + t1_bids_path=t1_bids_path, + fs_subject="sample", + fs_subjects_dir=subjects_dir, + ) # Should fail for an unsupported coordinate frame raw = _read_raw_fif(raw_fname) @@ -791,7 +801,13 @@ def test_handle_chpi_reading(tmp_path): meg_json_data_freq_mismatch["HeadCoilFrequency"][0] = 123 _write_json(meg_json_path, meg_json_data_freq_mismatch, overwrite=True) - with pytest.warns(RuntimeWarning, match="Defaulting to .* mne.Raw object"): + with ( + pytest.warns(RuntimeWarning, match="Defaulting to .* mne.Raw object"), + pytest.warns( + RuntimeWarning, match="This file contains raw Internal Active Shielding" + ), + pytest.warns(RuntimeWarning, match="The unit for channel"), + ): raw_read = read_raw_bids(bids_path) # cHPI "off" according to sidecar, but present in the data @@ -866,8 +882,11 @@ def test_handle_eeg_coords_reading(tmp_path): bids_path, suffix="coordsystem", extension=".json" ) _update_sidecar(coordsystem_fname, "EEGCoordinateSystem", "besa") - with pytest.warns( - RuntimeWarning, match="is not a BIDS-acceptable coordinate frame for EEG" + with ( + pytest.warns( + RuntimeWarning, match="is not a BIDS-acceptable coordinate frame for EEG" + ), + pytest.warns(RuntimeWarning, match="The unit for channel"), ): raw_test = read_raw_bids(bids_path) assert raw_test.info["dig"] is None @@ -938,8 +957,11 @@ def test_handle_ieeg_coords_reading(bids_path, tmp_path): for axis in ["x", "y", "z"]: electrodes_dict[axis] = np.multiply(orig_electrodes_dict[axis], scaling) _to_tsv(electrodes_dict, electrodes_fname) - with pytest.warns( - RuntimeWarning, match="Coordinate unit is not an accepted BIDS unit" + with ( + pytest.warns( + RuntimeWarning, match="Coordinate unit is not an accepted BIDS unit" + ), + pytest.warns(RuntimeWarning, match="The unit for channel"), ): raw_test = read_raw_bids(bids_path=bids_fname, verbose=False) @@ -967,7 +989,10 @@ def test_handle_ieeg_coords_reading(bids_path, tmp_path): _update_sidecar(coordsystem_fname, "iEEGCoordinateSystem", coord_frame) # read in raw file w/ updated coordinate frame # and make sure all digpoints are MRI coordinate frame - with pytest.warns(RuntimeWarning, match="not an MNE-Python coordinate frame"): + with ( + pytest.warns(RuntimeWarning, match="not an MNE-Python coordinate frame"), + pytest.warns(RuntimeWarning, match="The unit for channel"), + ): raw_test = read_raw_bids(bids_path=bids_fname, verbose=False) assert raw_test.info["dig"] is not None @@ -981,8 +1006,11 @@ def test_handle_ieeg_coords_reading(bids_path, tmp_path): if coord_frame in BIDS_TO_MNE_FRAMES: raw_test = read_raw_bids(bids_path=bids_fname, verbose=False) else: - with pytest.warns( - RuntimeWarning, match="not an MNE-Python coordinate frame" + with ( + pytest.warns( + RuntimeWarning, match="not an MNE-Python coordinate frame" + ), + pytest.warns(RuntimeWarning, match="The unit for channel"), ): raw_test = read_raw_bids(bids_path=bids_fname, verbose=False) assert raw_test.info["dig"] is not None @@ -1010,7 +1038,10 @@ def test_handle_ieeg_coords_reading(bids_path, tmp_path): _to_tsv(electrodes_dict, electrodes_fname) # popping off channels should not result in an error # however, a warning will be raised through mne-python - with pytest.warns(RuntimeWarning, match="DigMontage is only a subset of info"): + with ( + pytest.warns(RuntimeWarning, match="DigMontage is only a subset of info"), + pytest.warns(RuntimeWarning, match="The unit for channel"), + ): read_raw_bids(bids_path=bids_fname, verbose=False) # make sure montage is set if there are coordinates w/ 'n/a' @@ -1026,7 +1057,10 @@ def test_handle_ieeg_coords_reading(bids_path, tmp_path): # electrode coordinates should be nan # when coordinate is 'n/a' nan_chs = [electrodes_dict["name"][i] for i in [0, 3]] - with pytest.warns(RuntimeWarning, match="There are channels without locations"): + with ( + pytest.warns(RuntimeWarning, match="There are channels without locations"), + pytest.warns(RuntimeWarning, match="The unit for channel"), + ): raw = read_raw_bids(bids_path=bids_fname, verbose=False) for idx, ch in enumerate(raw.info["chs"]): if ch["ch_name"] in nan_chs: @@ -1155,7 +1189,10 @@ def test_handle_non_mne_channel_type(tmp_path): channels_data["type"][ch_idx] = "FOOBAR" _to_tsv(data=channels_data, fname=channels_tsv_path) - with pytest.warns(RuntimeWarning, match='will be set to "misc"'): + with ( + pytest.warns(RuntimeWarning, match='will be set to "misc"'), + pytest.warns(RuntimeWarning, match="The unit for channel"), + ): raw = read_raw_bids(bids_path) # Should be a 'misc' channel. @@ -1285,10 +1322,13 @@ def test_channels_tsv_raw_mismatch(tmp_path): raw.load_data() raw.save(raw_path, overwrite=True) - with pytest.warns( - RuntimeWarning, - match="number of channels in the channels.tsv sidecar .* " - "does not match the number of channels in the raw data", + with ( + pytest.warns( + RuntimeWarning, + match="number of channels in the channels.tsv sidecar .* " + "does not match the number of channels in the raw data", + ), + pytest.warns(RuntimeWarning, match="Cannot set channel type"), ): read_raw_bids(bids_path) @@ -1299,10 +1339,13 @@ def test_channels_tsv_raw_mismatch(tmp_path): raw.rename_channels({ch_name_orig: ch_name_new}) raw.save(raw_path, overwrite=True) - with pytest.warns( - RuntimeWarning, - match=f"Cannot set channel type for the following channels, as they " - f"are missing in the raw data: {ch_name_orig}", + with ( + pytest.warns( + RuntimeWarning, + match=f"Cannot set channel type for the following channels, as they " + f"are missing in the raw data: {ch_name_orig}", + ), + pytest.warns(RuntimeWarning, match="The number of channels in the channels"), ): read_raw_bids(bids_path) @@ -1318,10 +1361,14 @@ def test_channels_tsv_raw_mismatch(tmp_path): raw.rename_channels({ch_name_orig: ch_name_new}) raw.save(raw_path, overwrite=True) - with pytest.warns( - RuntimeWarning, - match=f'Cannot set "bad" status for the following channels, as ' - f"they are missing in the raw data: {ch_name_orig}", + with ( + pytest.warns( + RuntimeWarning, + match=f'Cannot set "bad" status for the following channels, as ' + f"they are missing in the raw data: {ch_name_orig}", + ), + pytest.warns(RuntimeWarning, match="The number of channels in the channels"), + pytest.warns(RuntimeWarning, match="Cannot set channel type"), ): read_raw_bids(bids_path) @@ -1362,7 +1409,11 @@ def test_file_not_found(tmp_path): bp.update(extension=".fif") _read_raw_fif(raw_fname, verbose=False).save(bp.fpath) - with pytest.warns(RuntimeWarning, match=r"channels\.tsv"): + with ( + pytest.warns(RuntimeWarning, match=r"channels\.tsv"), + pytest.warns(RuntimeWarning, match=r"Did not find any eeg\.json"), + pytest.warns(RuntimeWarning, match=r"participants\.tsv file not found"), + ): read_raw_bids(bp) # smoke test bp.update(task=None) diff --git a/mne_bids/tests/test_write.py b/mne_bids/tests/test_write.py index c4acc6913..263a6549f 100644 --- a/mne_bids/tests/test_write.py +++ b/mne_bids/tests/test_write.py @@ -608,7 +608,10 @@ def test_fif(_bids_validate, tmp_path): assert op.isfile(op.join(bids_dir, sidecar_basename.basename)) bids_path.update(root=bids_root, datatype="eeg") - with pytest.warns(RuntimeWarning, match="Not setting position"): + with ( + pytest.warns(RuntimeWarning, match="Not setting position"), + pytest.warns(RuntimeWarning, match="The unit for channel"), + ): raw2 = read_raw_bids(bids_path=bids_path) os.remove(op.join(bids_root, "test-raw.fif")) @@ -1174,7 +1177,10 @@ def test_ctf(_bids_validate, tmp_path): write_raw_bids(raw, bids_path, overwrite=True) # test overwrite _bids_validate(tmp_path) - with pytest.warns(RuntimeWarning, match="Did not find any events"): + with ( + pytest.warns(RuntimeWarning, match="Did not find any events"), + pytest.warns(RuntimeWarning, match="The unit for channel"), + ): raw = read_raw_bids(bids_path=bids_path, extra_params=dict(clean_names=False)) # test to check that running again with overwrite == False raises an error @@ -1503,11 +1509,7 @@ def test_eegieeg(dir_name, fname, reader, _bids_validate, tmp_path): with pytest.raises( RuntimeError, match="'head' coordinate frame must contain nasion" ): - if warning_to_catch[dir_name] is None: - write_raw_bids(**kwargs) - else: - with pytest.warns(RuntimeWarning, match=warning_to_catch[dir_name]): - write_raw_bids(**kwargs) + write_raw_bids(**kwargs) electrodes_fpath = _find_matching_sidecar( bids_path, suffix="electrodes", extension=".tsv", on_error="ignore" @@ -1866,7 +1868,10 @@ def test_bdf(_bids_validate, tmp_path): # Now read the raw data back from BIDS, with the tampered TSV, to show # that the channels.tsv truly influences how read_raw_bids sets ch_types # in the raw data object - with pytest.warns(RuntimeWarning, match="Fp1 has changed from V .*"): + with ( + pytest.warns(RuntimeWarning, match=r"The unit for channel\(s\) Fp1"), + pytest.warns(RuntimeWarning, match=r"The unit for channel\(s\) Status"), + ): raw = read_raw_bids(bids_path=bids_path) assert coil_type(raw.info, test_ch_idx) == "misc" with pytest.raises(TypeError, match="unexpected keyword argument 'foo'"): @@ -3366,10 +3371,21 @@ def test_convert_eeg_formats(dir_name, format, fname, reader, tmp_path): ): bids_output_path = write_raw_bids(**kwargs) else: - with pytest.warns( - RuntimeWarning, match=f"Converting data files to {format} format" - ): - bids_output_path = write_raw_bids(**kwargs) + if dir_name in ["EEGLAB", "NihonKohden", "curry"]: + with pytest.warns( + RuntimeWarning, match=f"Converting data files to {format} format" + ): + bids_output_path = write_raw_bids(**kwargs) + else: + with ( + pytest.warns( + RuntimeWarning, match=f"Converting data files to {format} format" + ), + pytest.warns( + RuntimeWarning, match="EDF format requires equal-length data blocks" + ), + ): + bids_output_path = write_raw_bids(**kwargs) # channel units should stay the same raw2 = read_raw_bids(bids_output_path, extra_params=dict(preload=True)) diff --git a/pyproject.toml b/pyproject.toml index f8c41521b..43046ea58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,7 +59,7 @@ full = [ ] # Dependencies for running the test infrastructure -test = ["mne_bids[full]", "pytest < 8", "pytest-cov", "pytest-sugar", "ruff"] +test = ["mne_bids[full]", "pytest", "pytest-cov", "pytest-sugar", "ruff"] # Dependencies for building the documentation doc = [