diff --git a/CHANGELOG.md b/CHANGELOG.md index c7eb7308..36ffea24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Changed * Added scipy to optional dependencies to be compatible with HDMF 4.0. @rly [#261](https://github.com/hdmf-dev/hdmf-zarr/pull/261) +* Added warning in NWBZarrIO if writing file name that does not end in ".nwb.zarr". @stephprince [#265](https://github.com/hdmf-dev/hdmf-zarr/pull/265) ## 0.11.0 (January 17, 2025) diff --git a/src/hdmf_zarr/nwb.py b/src/hdmf_zarr/nwb.py index 97a62573..90079315 100644 --- a/src/hdmf_zarr/nwb.py +++ b/src/hdmf_zarr/nwb.py @@ -1,5 +1,6 @@ """Module with Zarr backend for NWB for integration with PyNWB""" +import warnings from pathlib import Path from .backend import ZarrIO, SUPPORTED_ZARR_STORES @@ -42,6 +43,11 @@ def __init__(self, **kwargs): if mode in io_modes_that_create_file or manager is not None or extensions is not None: load_namespaces = False + if mode in io_modes_that_create_file and not str(path).endswith('.nwb.zarr'): + warnings.warn(f"The file path provided: {path} does not end in '.nwb.zarr'. " + "It is recommended that NWB files using the Zarr backend use " + "the '.nwb.zarr' extension", UserWarning) + if load_namespaces: tm = get_type_map() super().load_namespaces(tm, path, storage_options) diff --git a/tests/unit/test_nwbzarrio.py b/tests/unit/test_nwbzarrio.py index c54d7225..f21fc0e2 100644 --- a/tests/unit/test_nwbzarrio.py +++ b/tests/unit/test_nwbzarrio.py @@ -4,6 +4,9 @@ import shutil from datetime import datetime from dateutil.tz import tzlocal +from pathlib import Path + +from hdmf.testing import TestCase try: from pynwb import NWBFile @@ -14,18 +17,11 @@ @unittest.skipIf(not PYNWB_AVAILABLE, "PyNWB not installed") -class TestNWBZarrIO(unittest.TestCase): +class TestNWBZarrIO(TestCase): def setUp(self): - self.filepath = "test_io.zarr" - - def tearDown(self): - if os.path.exists(self.filepath): - shutil.rmtree(self.filepath) - - def write_test_file(self): - # Create the NWBFile - nwbfile = NWBFile( + self.filepath = "test_io.nwb.zarr" + self.nwbfile = NWBFile( session_description="my first synthetic recording", identifier="EXAMPLE_ID", session_start_time=datetime.now(tzlocal()), @@ -35,11 +31,33 @@ def write_test_file(self): experiment_description="I went on an adventure with thirteen dwarves to reclaim vast treasures.", session_id="LONELYMTN", ) - # Create a device - nwbfile.create_device(name="array", description="the best array", manufacturer="Probe Company 9000") + self.nwbfile.create_device(name="array", description="the best array", manufacturer="Probe Company 9000") + + def tearDown(self): + if os.path.exists(self.filepath): + shutil.rmtree(self.filepath) + + def write_test_file(self): with NWBZarrIO(path=self.filepath, mode="w") as io: - io.write(nwbfile) + io.write(self.nwbfile) + + def test_file_extension_warning(self): + """Test that a warning is raised when the file extension is not .nwb.zarr""" + wrong_filepath = Path(self.filepath).with_suffix('.h5') + + msg = (f"The file path provided: {wrong_filepath} does not end in '.nwb.zarr'. " + "It is recommended that NWB files using the Zarr backend use the '.nwb.zarr' extension") + + with self.assertWarnsWith(UserWarning, msg): + with NWBZarrIO(path=wrong_filepath, mode="w") as io: + io.write(self.nwbfile) + + # should not warn on read or append + with NWBZarrIO(wrong_filepath, 'r') as io: + io.read() + with NWBZarrIO(wrong_filepath, 'a') as io: + io.read() def test_read_nwb(self): """