Skip to content

Commit c35cfe5

Browse files
larsonersnwnde
authored andcommitted
MAINT: Check for shadowing and mutable defaults (mne-tools#12380)
1 parent 51979cb commit c35cfe5

File tree

41 files changed

+126
-87
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+126
-87
lines changed

doc/changes/devel/12380.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix bug where :func:`mne.preprocessing.compute_proj_ecg` and :func:`mne.preprocessing.compute_proj_eog` could modify the default ``reject`` and ``flat`` arguments on multiple calls based on channel types present, by `Eric Larson`_.

doc/conf.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,10 @@ def reset_warnings(gallery_conf, fname):
13441344
r"ast\.NameConstant is deprecated and will be removed in Python 3\.14",
13451345
# pooch
13461346
r"Python 3\.14 will, by default, filter extracted tar archives.*",
1347+
# seaborn
1348+
r"DataFrameGroupBy\.apply operated on the grouping columns.*",
1349+
# pandas
1350+
r"\nPyarrow will become a required dependency of pandas.*",
13471351
):
13481352
warnings.filterwarnings( # deal with other modules having bad imports
13491353
"ignore", message=".*%s.*" % key, category=DeprecationWarning
@@ -1382,6 +1386,7 @@ def reset_warnings(gallery_conf, fname):
13821386
r"iteritems is deprecated.*Use \.items instead\.",
13831387
"is_categorical_dtype is deprecated.*",
13841388
"The default of observed=False.*",
1389+
"When grouping with a length-1 list-like.*",
13851390
):
13861391
warnings.filterwarnings(
13871392
"ignore",

environment.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ dependencies:
66
- pip
77
- numpy
88
- scipy
9+
- openblas!=0.3.26 # until https://github.com/conda-forge/scipy-feedstock/pull/268 lands
910
- matplotlib
1011
- tqdm
1112
- pooch>=1.5

examples/time_frequency/time_frequency_erds.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
# %%
5151
# First, we load and preprocess the data. We use runs 6, 10, and 14 from
5252
# subject 1 (these runs contains hand and feet motor imagery).
53+
5354
fnames = eegbci.load_data(subject=1, runs=(6, 10, 14))
5455
raw = concatenate_raws([read_raw_edf(f, preload=True) for f in fnames])
5556

@@ -59,6 +60,7 @@
5960

6061
# %%
6162
# Now we can create 5-second epochs around events of interest.
63+
6264
tmin, tmax = -1, 4
6365
event_ids = dict(hands=2, feet=3) # map event IDs to tasks
6466

mne/_fiff/open.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ def show_fiff(
268268
return out
269269

270270

271-
def _find_type(value, fmts=["FIFF_"], exclude=["FIFF_UNIT"]):
271+
def _find_type(value, fmts=("FIFF_",), exclude=("FIFF_UNIT",)):
272272
"""Find matching values."""
273273
value = int(value)
274274
vals = [

mne/_fiff/pick.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ def channel_type(info, idx):
259259

260260

261261
@verbose
262-
def pick_channels(ch_names, include, exclude=[], ordered=None, *, verbose=None):
262+
def pick_channels(ch_names, include, exclude=(), ordered=None, *, verbose=None):
263263
"""Pick channels by names.
264264
265265
Returns the indices of ``ch_names`` in ``include`` but not in ``exclude``.
@@ -706,7 +706,7 @@ def _has_kit_refs(info, picks):
706706

707707
@verbose
708708
def pick_channels_forward(
709-
orig, include=[], exclude=[], ordered=None, copy=True, *, verbose=None
709+
orig, include=(), exclude=(), ordered=None, copy=True, *, verbose=None
710710
):
711711
"""Pick channels from forward operator.
712712
@@ -797,8 +797,8 @@ def pick_types_forward(
797797
seeg=False,
798798
ecog=False,
799799
dbs=False,
800-
include=[],
801-
exclude=[],
800+
include=(),
801+
exclude=(),
802802
):
803803
"""Pick by channel type and names from a forward operator.
804804
@@ -893,7 +893,7 @@ def channel_indices_by_type(info, picks=None):
893893

894894
@verbose
895895
def pick_channels_cov(
896-
orig, include=[], exclude="bads", ordered=None, copy=True, *, verbose=None
896+
orig, include=(), exclude="bads", ordered=None, copy=True, *, verbose=None
897897
):
898898
"""Pick channels from covariance matrix.
899899

mne/channels/tests/test_channels.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,8 @@ def test_1020_selection():
438438
raw = raw.rename_channels(dict(zip(raw.ch_names, montage.ch_names)))
439439
raw.set_montage(montage)
440440

441-
for input in ("a_string", 100, raw, [1, 2]):
442-
pytest.raises(TypeError, make_1020_channel_selections, input)
441+
for input_ in ("a_string", 100, raw, [1, 2]):
442+
pytest.raises(TypeError, make_1020_channel_selections, input_)
443443

444444
sels = make_1020_channel_selections(raw.info)
445445
# are all frontal channels placed before all occipital channels?

mne/commands/mne_setup_source_space.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def run():
120120
subjects_dir = options.subjects_dir
121121
spacing = options.spacing
122122
ico = options.ico
123-
oct = options.oct
123+
oct_ = options.oct
124124
surface = options.surface
125125
n_jobs = options.n_jobs
126126
add_dist = options.add_dist
@@ -130,20 +130,22 @@ def run():
130130
overwrite = True if options.overwrite is not None else False
131131

132132
# Parse source spacing option
133-
spacing_options = [ico, oct, spacing]
133+
spacing_options = [ico, oct_, spacing]
134134
n_options = len([x for x in spacing_options if x is not None])
135+
use_spacing = "oct6"
135136
if n_options > 1:
136137
raise ValueError("Only one spacing option can be set at the same time")
137138
elif n_options == 0:
138139
# Default to oct6
139-
use_spacing = "oct6"
140+
pass
140141
elif n_options == 1:
141142
if ico is not None:
142143
use_spacing = "ico" + str(ico)
143-
elif oct is not None:
144-
use_spacing = "oct" + str(oct)
144+
elif oct_ is not None:
145+
use_spacing = "oct" + str(oct_)
145146
elif spacing is not None:
146147
use_spacing = spacing
148+
del ico, oct_, spacing
147149
# Generate filename
148150
if fname is None:
149151
if subject_to is None:

mne/cov.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ def __iadd__(self, cov):
310310
def plot(
311311
self,
312312
info,
313-
exclude=[],
313+
exclude=(),
314314
colorbar=True,
315315
proj=False,
316316
show_svd=True,

mne/datasets/sleep_physionet/tests/test_physionet.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ def _check_mocked_function_calls(mocked_func, call_fname_hash_pairs, base_path):
4646
# order.
4747
for idx, current in enumerate(call_fname_hash_pairs):
4848
_, call_kwargs = mocked_func.call_args_list[idx]
49-
hash_type, hash = call_kwargs["known_hash"].split(":")
49+
hash_type, hash_ = call_kwargs["known_hash"].split(":")
5050
assert call_kwargs["url"] == _get_expected_url(current["name"]), idx
5151
assert Path(call_kwargs["path"], call_kwargs["fname"]) == _get_expected_path(
5252
base_path, current["name"]
5353
)
54-
assert hash == current["hash"]
54+
assert hash_ == current["hash"]
5555
assert hash_type == "sha1"
5656

5757

mne/decoding/tests/test_ssd.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020

2121
def simulate_data(
22-
freqs_sig=[9, 12],
22+
freqs_sig=(9, 12),
2323
n_trials=100,
2424
n_channels=20,
2525
n_samples=500,

mne/epochs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3662,7 +3662,7 @@ def _is_good(
36623662
reject,
36633663
flat,
36643664
full_report=False,
3665-
ignore_chs=[],
3665+
ignore_chs=(),
36663666
verbose=None,
36673667
):
36683668
"""Test if data segment e is good according to reject and flat.
@@ -4631,7 +4631,7 @@ def make_fixed_length_epochs(
46314631
reject_by_annotation=True,
46324632
proj=True,
46334633
overlap=0.0,
4634-
id=1,
4634+
id=1, # noqa: A002
46354635
verbose=None,
46364636
):
46374637
"""Divide continuous raw data into equal-sized consecutive epochs.

mne/event.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,13 @@ def shift_time_events(events, ids, tshift, sfreq):
925925

926926
@fill_doc
927927
def make_fixed_length_events(
928-
raw, id=1, start=0, stop=None, duration=1.0, first_samp=True, overlap=0.0
928+
raw,
929+
id=1, # noqa: A002
930+
start=0,
931+
stop=None,
932+
duration=1.0,
933+
first_samp=True,
934+
overlap=0.0,
929935
):
930936
"""Make a set of :term:`events` separated by a fixed duration.
931937

mne/evoked.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ def plot_topo(
549549
scalings=None,
550550
title=None,
551551
proj=False,
552-
vline=[0.0],
552+
vline=(0.0,),
553553
fig_background=None,
554554
merge_grads=False,
555555
legend=True,

mne/export/_export.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ def _infer_check_export_fmt(fmt, fname, supported_formats):
211211

212212
if fmt not in supported_formats:
213213
supported = []
214-
for format, extensions in supported_formats.items():
214+
for supp_format, extensions in supported_formats.items():
215215
ext_str = ", ".join(f"*.{ext}" for ext in extensions)
216-
supported.append(f"{format} ({ext_str})")
216+
supported.append(f"{supp_format} ({ext_str})")
217217

218218
supported_str = ", ".join(supported)
219219
raise ValueError(

mne/gui/_coreg.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,7 +1907,7 @@ def _configure_dock(self):
19071907
func=self._save_trans,
19081908
tooltip="Save the transform file to disk",
19091909
layout=save_trans_layout,
1910-
filter="Head->MRI transformation (*-trans.fif *_trans.fif)",
1910+
filter_="Head->MRI transformation (*-trans.fif *_trans.fif)",
19111911
initial_directory=str(Path(self._info_file).parent),
19121912
)
19131913
self._widgets["load_trans"] = self._renderer._dock_add_file_button(
@@ -1916,7 +1916,7 @@ def _configure_dock(self):
19161916
func=self._load_trans,
19171917
tooltip="Load the transform file from disk",
19181918
layout=save_trans_layout,
1919-
filter="Head->MRI transformation (*-trans.fif *_trans.fif)",
1919+
filter_="Head->MRI transformation (*-trans.fif *_trans.fif)",
19201920
initial_directory=str(Path(self._info_file).parent),
19211921
)
19221922
self._renderer._layout_add_widget(trans_layout, save_trans_layout)

mne/inverse_sparse/mxne_optim.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ def __call__(self, x): # noqa: D105
799799
else:
800800
return np.hstack([x @ op for op in self.ops]) / np.sqrt(self.n_dicts)
801801

802-
def norm(self, z, ord=2):
802+
def norm(self, z, ord=2): # noqa: A002
803803
"""Squared L2 norm if ord == 2 and L1 norm if order == 1."""
804804
if ord not in (1, 2):
805805
raise ValueError(

mne/io/bti/bti.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def __init__(self, target):
7878
def __enter__(self): # noqa: D105
7979
return self.target
8080

81-
def __exit__(self, type, value, tb): # noqa: D105
81+
def __exit__(self, exception_type, value, tb): # noqa: D105
8282
pass
8383

8484

mne/io/curry/curry.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,10 @@ def _read_curry_parameters(fname):
197197
if any(var_name in line for var_name in var_names):
198198
key, val = line.replace(" ", "").replace("\n", "").split("=")
199199
param_dict[key.lower().replace("_", "")] = val
200-
for type in CHANTYPES:
201-
if "DEVICE_PARAMETERS" + CHANTYPES[type] + " START" in line:
200+
for key, type_ in CHANTYPES.items():
201+
if f"DEVICE_PARAMETERS{type_} START" in line:
202202
data_unit = next(fid)
203-
unit_dict[type] = (
203+
unit_dict[key] = (
204204
data_unit.replace(" ", "").replace("\n", "").split("=")[-1]
205205
)
206206

mne/io/edf/edf.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1454,7 +1454,9 @@ def _read_gdf_header(fname, exclude, include=None):
14541454

14551455

14561456
def _check_stim_channel(
1457-
stim_channel, ch_names, tal_ch_names=["EDF Annotations", "BDF Annotations"]
1457+
stim_channel,
1458+
ch_names,
1459+
tal_ch_names=("EDF Annotations", "BDF Annotations"),
14581460
):
14591461
"""Check that the stimulus channel exists in the current datafile."""
14601462
DEFAULT_STIM_CH_NAMES = ["status", "trigger"]

mne/io/fieldtrip/tests/helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ def get_epochs(system):
185185
else:
186186
event_id = [int(cfg_local["eventvalue"])]
187187

188-
event_id = [id for id in event_id if id in events[:, 2]]
188+
event_id = [id_ for id_ in event_id if id_ in events[:, 2]]
189189

190190
epochs = mne.Epochs(
191191
raw_data,

mne/io/fieldtrip/tests/test_fieldtrip.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -253,19 +253,19 @@ def test_one_channel_elec_bug(version):
253253
@pytest.mark.filterwarnings("ignore:.*parse meas date.*:RuntimeWarning")
254254
@pytest.mark.filterwarnings("ignore:.*number of bytes.*:RuntimeWarning")
255255
@pytest.mark.parametrize("version", all_versions)
256-
@pytest.mark.parametrize("type", ["averaged", "epoched", "raw"])
257-
def test_throw_exception_on_cellarray(version, type):
256+
@pytest.mark.parametrize("type_", ["averaged", "epoched", "raw"])
257+
def test_throw_exception_on_cellarray(version, type_):
258258
"""Test for a meaningful exception when the data is a cell array."""
259-
fname = get_data_paths("cellarray") / f"{type}_{version}.mat"
259+
fname = get_data_paths("cellarray") / f"{type_}_{version}.mat"
260260
info = get_raw_info("CNT")
261261
with pytest.raises(
262262
RuntimeError, match="Loading of data in cell arrays " "is not supported"
263263
):
264-
if type == "averaged":
264+
if type_ == "averaged":
265265
mne.read_evoked_fieldtrip(fname, info)
266-
elif type == "epoched":
266+
elif type_ == "epoched":
267267
mne.read_epochs_fieldtrip(fname, info)
268-
elif type == "raw":
268+
elif type_ == "raw":
269269
mne.io.read_raw_fieldtrip(fname, info)
270270

271271

mne/preprocessing/nirs/_tddr.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ def _TDDR(signal, sample_rate):
111111
tune = 4.685
112112
D = np.sqrt(np.finfo(signal.dtype).eps)
113113
mu = np.inf
114-
iter = 0
115114

116115
# Step 1. Compute temporal derivative of the signal
117116
deriv = np.diff(signal_low)
@@ -120,8 +119,7 @@ def _TDDR(signal, sample_rate):
120119
w = np.ones(deriv.shape)
121120

122121
# Step 3. Iterative estimation of robust weights
123-
while iter < 50:
124-
iter = iter + 1
122+
for _ in range(50):
125123
mu0 = mu
126124

127125
# Step 3a. Estimate weighted mean

mne/preprocessing/ssp.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from .._fiff.reference import make_eeg_average_ref_proj
1414
from ..epochs import Epochs
1515
from ..proj import compute_proj_epochs, compute_proj_evoked
16-
from ..utils import logger, verbose, warn
16+
from ..utils import _validate_type, logger, verbose, warn
1717
from .ecg import find_ecg_events
1818
from .eog import find_eog_events
1919

@@ -112,7 +112,10 @@ def _compute_exg_proj(
112112
my_info["bads"] += bads
113113

114114
# Handler rejection parameters
115+
_validate_type(reject, (None, dict), "reject")
116+
_validate_type(flat, (None, dict), "flat")
115117
if reject is not None: # make sure they didn't pass None
118+
reject = reject.copy() # must make a copy or we modify default!
116119
if (
117120
len(
118121
pick_types(
@@ -170,6 +173,7 @@ def _compute_exg_proj(
170173
):
171174
_safe_del_key(reject, "eog")
172175
if flat is not None: # make sure they didn't pass None
176+
flat = flat.copy()
173177
if (
174178
len(
175179
pick_types(
@@ -300,9 +304,9 @@ def compute_proj_ecg(
300304
filter_length="10s",
301305
n_jobs=None,
302306
ch_name=None,
303-
reject=dict(grad=2000e-13, mag=3000e-15, eeg=50e-6, eog=250e-6),
307+
reject=dict(grad=2000e-13, mag=3000e-15, eeg=50e-6, eog=250e-6), # noqa: B006
304308
flat=None,
305-
bads=[],
309+
bads=(),
306310
avg_ref=False,
307311
no_proj=False,
308312
event_id=999,
@@ -461,9 +465,9 @@ def compute_proj_eog(
461465
average=True,
462466
filter_length="10s",
463467
n_jobs=None,
464-
reject=dict(grad=2000e-13, mag=3000e-15, eeg=500e-6, eog=np.inf),
468+
reject=dict(grad=2000e-13, mag=3000e-15, eeg=500e-6, eog=np.inf), # noqa: B006
465469
flat=None,
466-
bads=[],
470+
bads=(),
467471
avg_ref=False,
468472
no_proj=False,
469473
event_id=998,

0 commit comments

Comments
 (0)