Skip to content

Commit 80ba461

Browse files
authored
Add test to enforce keyword arguments (#1664)
1 parent a6281e2 commit 80ba461

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

src/neuroconv/datainterfaces/ophys/miniscope/miniscopeimagingdatainterface.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ def add_to_nwbfile(
433433
self,
434434
nwbfile: NWBFile,
435435
metadata: dict | None = None,
436+
*args, # TODO: change to * (keyword only) on or after August 2026
436437
photon_series_type: Literal["TwoPhotonSeries", "OnePhotonSeries"] = "OnePhotonSeries",
437438
**kwargs,
438439
):
@@ -441,6 +442,33 @@ def add_to_nwbfile(
441442
442443
This method adds the Miniscope device and then delegates to the parent class.
443444
"""
445+
# Handle deprecated positional arguments
446+
if args:
447+
import warnings
448+
449+
parameter_names = [
450+
"photon_series_type",
451+
]
452+
num_positional_args_before_args = 2 # nwbfile, metadata
453+
if len(args) > len(parameter_names):
454+
raise TypeError(
455+
f"add_to_nwbfile() takes at most {len(parameter_names) + num_positional_args_before_args} positional arguments but "
456+
f"{len(args) + num_positional_args_before_args} were given. "
457+
"Note: Positional arguments are deprecated and will be removed on or after August 2026. "
458+
"Please use keyword arguments."
459+
)
460+
positional_values = dict(zip(parameter_names, args))
461+
passed_as_positional = list(positional_values.keys())
462+
warnings.warn(
463+
"Passing arguments positionally to MiniscopeImagingInterface.add_to_nwbfile() is deprecated "
464+
"and will be removed on or after August 2026. "
465+
f"The following arguments were passed positionally: {passed_as_positional}. "
466+
"Please use keyword arguments instead.",
467+
FutureWarning,
468+
stacklevel=2,
469+
)
470+
photon_series_type = positional_values.get("photon_series_type", photon_series_type)
471+
444472
from ndx_miniscope.utils import add_miniscope_device
445473

446474
# Add Miniscope device - required for proper ndx_miniscope.Miniscope device type
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""Tests to enforce keyword-only argument conventions for add_to_nwbfile methods.
2+
3+
These tests ensure that all interface add_to_nwbfile methods enforce keyword-only arguments
4+
after nwbfile and metadata. Only nwbfile and metadata should be positional.
5+
6+
During the deprecation period (before August 2026), methods use *args with FutureWarning.
7+
After the deprecation period, methods should use bare * for keyword-only enforcement.
8+
9+
See the developer style guide for details on the convention.
10+
"""
11+
12+
import inspect
13+
14+
import pytest
15+
16+
from neuroconv.datainterfaces import interface_list
17+
18+
19+
@pytest.mark.parametrize(
20+
"interface_class",
21+
interface_list,
22+
ids=lambda cls: cls.__name__,
23+
)
24+
def test_add_to_nwbfile_only_nwbfile_metadata_positional(interface_class):
25+
"""Only nwbfile and metadata should be positional in add_to_nwbfile."""
26+
if "add_to_nwbfile" not in interface_class.__dict__:
27+
pytest.skip(f"{interface_class.__name__} does not override add_to_nwbfile")
28+
29+
add_to_nwbfile_method = getattr(interface_class, "add_to_nwbfile")
30+
sig = inspect.signature(add_to_nwbfile_method)
31+
32+
# No add_to_nwbfile uses POSITIONAL_ONLY (/), so POSITIONAL_OR_KEYWORD means "can be passed positionally"
33+
can_be_passed_positionally = lambda param: param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
34+
positional_params = {name for name, param in sig.parameters.items() if can_be_passed_positionally(param)}
35+
36+
allowed_positional_params = {"self", "nwbfile", "metadata"}
37+
assert positional_params == allowed_positional_params, (
38+
f"{interface_class.__name__}.add_to_nwbfile() positional parameters are {positional_params}, "
39+
f"expected {allowed_positional_params}. "
40+
f"All other parameters should be keyword-only (use * or *args)."
41+
)

0 commit comments

Comments
 (0)