diff --git a/CHANGELOG.md b/CHANGELOG.md index d6eab03c0..87470dae4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - The validation methods have been updated with multiple breaking changes. @stephprince [#1911](https://github.com/NeurodataWithoutBorders/pynwb/pull/1911) - The behavior of `pynwb.validate(io=...)` now matches the behavior of `pynwb.validate(path=...)`. In previous pynwb versions, `pynwb.validate(io=...)` did not use the cached namespaces during validation. To obtain the same behavior as in previous versions, you can update the function call to `pynwb.validate(io=..., use_cached_namespaces=False)` - `pynwb.validate` will return only a list of validation errors instead of a tuple: (list of validation_errors, status code) + - the `pynwb.validate(path=...)` argument has been added as a replacement for `pynwb.validate(paths=[...])`, which will be deprecated in a future major release [#2024](https://github.com/NeurodataWithoutBorders/pynwb/pull/2024) - The validate module has been renamed to `validation.py`. The validate method can be imported using `import pynwb; pynwb.validate` or `from pynwb import validate` diff --git a/src/pynwb/validation.py b/src/pynwb/validation.py index d2fb5cb17..cc40ba166 100644 --- a/src/pynwb/validation.py +++ b/src/pynwb/validation.py @@ -5,7 +5,7 @@ from hdmf.spec import NamespaceCatalog from hdmf.build import BuildManager, TypeMap -from hdmf.utils import docval, getargs, AllowPositional +from hdmf.utils import docval, getargs, popargs, AllowPositional from hdmf.backends.io import HDMFIO from hdmf.validate import ValidatorMap @@ -97,6 +97,13 @@ def get_cached_namespaces_to_validate(path: Optional[str] = None, "doc": "A specific namespace to validate against.", "default": None, }, # Argument order is for back-compatability + { + "name": "paths", + "type": list, + "doc": ("List of NWB file paths. This argument will be deprecated in PyNWB 4.0. " + "Use 'path' instead."), + "default": None, + }, { "name": "path", "type": (str, Path), @@ -134,6 +141,29 @@ def validate(**kwargs): compliance with the schema and compliance of data with NWB best practices. """ + paths, path = popargs("paths", "path", kwargs) + + if paths is not None: + warn("The 'paths' argument will be deprecated in PyNWB 4.0 " + "Use 'path' instead. To migrate, call this function separately for " + "each path instead of passing a list.", + DeprecationWarning) + + if path is not None: + raise ValueError("Both 'paths' and 'path' were specified. " + "Please choose only one.") + + validation_errors = [] + for p in paths: + validation_errors += _validate_single_file(path=p, **kwargs) + else: + validation_errors = _validate_single_file(path=path, **kwargs) + + return validation_errors + + +def _validate_single_file(**kwargs): + io, path, use_cached_namespaces, namespace, verbose, driver = getargs( "io", "path", "use_cached_namespaces", "namespace", "verbose", "driver", kwargs ) diff --git a/tests/validation/test_validate.py b/tests/validation/test_validate.py index dc1be008c..ad4960ed4 100644 --- a/tests/validation/test_validate.py +++ b/tests/validation/test_validate.py @@ -332,3 +332,22 @@ def test_validate_io_and_path_same(self): # remove path from error messages since it will not be included in io outputs self.assertEqual(str(e_io.exception), str(e_path.exception)) + + def test_validate_paths_deprecation(self): + """Test paths argument deprecation warning.""" + + # test deprecation warning for 'paths' argument + msg = ("The 'paths' argument will be deprecated in PyNWB 4.0 " + "Use 'path' instead. To migrate, call this function separately for " + "each path instead of passing a list.") + with self.assertWarnsWith(DeprecationWarning, msg): + results = validate(paths=['tests/back_compat/1.1.2_nwbfile.nwb', + 'tests/back_compat/2.1.0_nwbfile_with_extension.nwb'],) + self.assertEqual(results, []) + + # test specifying both 'paths' and 'path' arguments + expected_error = "Both 'paths' and 'path' were specified. Please choose only one." + with self.assertWarnsWith(DeprecationWarning, msg): + with self.assertRaisesWith(ValueError, expected_error): + validate(paths=['tests/back_compat/1.0.2_nwbfile.nwb'], + path='tests/back_compat/1.0.2_nwbfile.nwb')