From 4d775000f01ed9591bb84eb08064b38056e267be Mon Sep 17 00:00:00 2001 From: CodyCBakerPhD Date: Fri, 6 Sep 2024 15:20:28 -0400 Subject: [PATCH 1/5] remove past PyNWB version references --- CHANGELOG.md | 1 + src/nwbinspector/_dandi_inspection.py | 1 - src/nwbinspector/_nwb_inspection.py | 64 +++++++++++---------------- src/nwbinspector/checks/_images.py | 64 +++++++++++++-------------- tests/unit_tests/test_icephys.py | 15 ------- tests/unit_tests/test_images.py | 14 ------ tests/unit_tests/test_tables.py | 53 ++++++++++++---------- tests/unit_tests/test_time_series.py | 28 ------------ 8 files changed, 87 insertions(+), 153 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f12a2f34..d771deaf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Improvements * Removed the `robust_ros3_read` utility helper. [#506](https://github.com/NeurodataWithoutBorders/nwbinspector/pull/506) +* Cleaned old references to non-recent PyNWB and HDMF versions. Current policy is that latest NWB Inspector releases should only support compatibility with latest PyNWB and HDMF. [#](https://github.com/NeurodataWithoutBorders/nwbinspector/pull/) diff --git a/src/nwbinspector/_dandi_inspection.py b/src/nwbinspector/_dandi_inspection.py index bdda537a3..1e70cae43 100644 --- a/src/nwbinspector/_dandi_inspection.py +++ b/src/nwbinspector/_dandi_inspection.py @@ -246,7 +246,6 @@ def inspect_url( with pynwb.NWBHDF5IO(file=file) as io: if skip_validate is False: validation_errors = pynwb.validate(io=io) - for validation_error in validation_errors: yield InspectorMessage( message=validation_error.reason, diff --git a/src/nwbinspector/_nwb_inspection.py b/src/nwbinspector/_nwb_inspection.py index b119c7ebb..b3b1fdd19 100644 --- a/src/nwbinspector/_nwb_inspection.py +++ b/src/nwbinspector/_nwb_inspection.py @@ -10,7 +10,6 @@ import pynwb from natsort import natsorted -from packaging.version import Version from tqdm import tqdm from . import available_checks, configure_checks @@ -20,7 +19,6 @@ OptionalListOfStrings, PathType, calculate_number_of_cpu, - get_package_version, ) @@ -73,8 +71,8 @@ def inspect_all( all available CPUs minus x. Set to 1 (also the default) to disable. skip_validate : bool, optional - Skip the PyNWB validation step. This may be desired for older NWBFiles (< schema version v2.10). - The default is False, which is also recommended. + Skip the PyNWB validation step. + The default is False, which is recommended. progress_bar : bool, optional Display a progress bar while scanning NWBFiles. Defaults to True. @@ -232,8 +230,8 @@ def inspect_nwbfile( nwbfile_path : FilePathType Path to the NWB file on disk or on S3. skip_validate : bool - Skip the PyNWB validation step. This may be desired for older NWBFiles (< schema version v2.10). - The default is False, which is also recommended. + Skip the PyNWB validation step. + The default is False, which is recommended. checks : list, optional List of checks to run. config : dict @@ -269,7 +267,7 @@ def inspect_nwbfile( filterwarnings(action="ignore", message="No cached namespaces found in .*") filterwarnings(action="ignore", message="Ignoring cached namespace .*") - if not skip_validate and get_package_version("pynwb") >= Version("2.2.0"): + if not skip_validate: validation_error_list, _ = pynwb.validate(paths=[nwbfile_path]) for validation_namespace_errors in validation_error_list: for validation_error in validation_namespace_errors: @@ -281,38 +279,26 @@ def inspect_nwbfile( file_path=nwbfile_path, ) - with pynwb.NWBHDF5IO(path=nwbfile_path, mode="r", load_namespaces=True) as io: - if not skip_validate and get_package_version("pynwb") < Version("2.2.0"): - validation_errors = pynwb.validate(io=io) - for validation_error in validation_errors: - yield InspectorMessage( - message=validation_error.reason, - importance=Importance.PYNWB_VALIDATION, - check_function_name=validation_error.name, - location=validation_error.location, - file_path=nwbfile_path, - ) + try: + in_memory_nwbfile = io.read() - try: - in_memory_nwbfile = io.read() - - for inspector_message in inspect_nwbfile_object( - nwbfile_object=in_memory_nwbfile, - checks=checks, - config=config, - ignore=ignore, - select=select, - importance_threshold=importance_threshold, - ): - inspector_message.file_path = nwbfile_path - yield inspector_message - except Exception as exception: - yield InspectorMessage( - message=traceback.format_exc(), - importance=Importance.ERROR, - check_function_name=f"During io.read() - {type(exception)}: {str(exception)}", - file_path=nwbfile_path, - ) + for inspector_message in inspect_nwbfile_object( + nwbfile_object=in_memory_nwbfile, + checks=checks, + config=config, + ignore=ignore, + select=select, + importance_threshold=importance_threshold, + ): + inspector_message.file_path = nwbfile_path + yield inspector_message + except Exception as exception: + yield InspectorMessage( + message=traceback.format_exc(), + importance=Importance.ERROR, + check_function_name=f"During io.read() - {type(exception)}: {str(exception)}", + file_path=nwbfile_path, + ) # TODO: deprecate once subject types and dandi schemas have been extended @@ -321,7 +307,7 @@ def _intercept_in_vitro_protein(nwbfile_object: pynwb.NWBFile, checks: Optional[ If the special 'protein' subject_id is specified, return a truncated list of checks to run. This is a temporary method for allowing upload of certain in vitro data to DANDI and - is expected to replaced in future versions. + is expected to be replaced in future versions. """ subject_related_check_names = [ "check_subject_exists", diff --git a/src/nwbinspector/checks/_images.py b/src/nwbinspector/checks/_images.py index 50692c135..a68f375e7 100644 --- a/src/nwbinspector/checks/_images.py +++ b/src/nwbinspector/checks/_images.py @@ -1,38 +1,36 @@ """Checks specific to the Images neurodata type.""" -from packaging.version import Version +from pynwb.base import Images from pynwb.image import IndexSeries from .._registration import Importance, InspectorMessage, register_check -from ..utils import get_package_version - -# The Images neurodata type was unavailable prior to PyNWB v.2.1.0 -if get_package_version(name="pynwb") >= Version("2.1.0"): - from pynwb.base import Images - - @register_check(importance=Importance.BEST_PRACTICE_VIOLATION, neurodata_type=Images) - def check_order_of_images_unique(images: Images): - """Check that all the values in the order_of_images field of an Images object are unique.""" - if images.order_of_images is None: - return - if not len(set(images.order_of_images)) == len(images.order_of_images): - return InspectorMessage(message="order_of_images should have unique values.") - - @register_check(importance=Importance.BEST_PRACTICE_VIOLATION, neurodata_type=Images) - def check_order_of_images_len(images: Images): - """Check that all the values in the order_of_images field of an Images object are unique.""" - if images.order_of_images is None: - return - if not len(images.order_of_images) == len(images.images): - return InspectorMessage( - message=f"Length of order_of_images ({len(images.order_of_images)}) does not match the number of " - f"images ({len(images.images)})." - ) - - @register_check(importance=Importance.BEST_PRACTICE_VIOLATION, neurodata_type=IndexSeries) - def check_index_series_points_to_image(index_series: IndexSeries): - if index_series.indexed_timeseries is not None: - return InspectorMessage( - message="Pointing an IndexSeries to a TimeSeries will be deprecated. Please point to an Images " - "container instead." - ) + + +@register_check(importance=Importance.BEST_PRACTICE_VIOLATION, neurodata_type=Images) +def check_order_of_images_unique(images: Images): + """Check that all the values in the order_of_images field of an Images object are unique.""" + if images.order_of_images is None: + return + if not len(set(images.order_of_images)) == len(images.order_of_images): + return InspectorMessage(message="order_of_images should have unique values.") + + +@register_check(importance=Importance.BEST_PRACTICE_VIOLATION, neurodata_type=Images) +def check_order_of_images_len(images: Images): + """Check that all the values in the order_of_images field of an Images object are unique.""" + if images.order_of_images is None: + return + if not len(images.order_of_images) == len(images.images): + return InspectorMessage( + message=f"Length of order_of_images ({len(images.order_of_images)}) does not match the number of " + f"images ({len(images.images)})." + ) + + +@register_check(importance=Importance.BEST_PRACTICE_VIOLATION, neurodata_type=IndexSeries) +def check_index_series_points_to_image(index_series: IndexSeries): + if index_series.indexed_timeseries is not None: + return InspectorMessage( + message="Pointing an IndexSeries to a TimeSeries will be deprecated. Please point to an Images " + "container instead." + ) diff --git a/tests/unit_tests/test_icephys.py b/tests/unit_tests/test_icephys.py index b5caddbbc..8e78a4d1c 100644 --- a/tests/unit_tests/test_icephys.py +++ b/tests/unit_tests/test_icephys.py @@ -1,24 +1,16 @@ -import pytest -from packaging.version import Version from pynwb.device import Device from pynwb.icephys import IntracellularElectrode from nwbinspector import Importance, InspectorMessage from nwbinspector.checks import check_intracellular_electrode_cell_id_exists -from nwbinspector.utils import get_package_version -PYNWB_VERSION_LOWER_2_1_0 = get_package_version(name="pynwb") < Version("2.1.0") -PYNWB_VERSION_LOWER_SKIP_REASON = "This test requires PyNWB>=2.1.0" - -@pytest.mark.skipif(PYNWB_VERSION_LOWER_2_1_0, reason=PYNWB_VERSION_LOWER_SKIP_REASON) def test_pass_check_intracellular_electrode_cell_id_exists(): device = Device(name="device") ielec = IntracellularElectrode(name="ielec", cell_id="123", device=device, description="an intracellular electrode") assert check_intracellular_electrode_cell_id_exists(ielec) is None -@pytest.mark.skipif(PYNWB_VERSION_LOWER_2_1_0, reason=PYNWB_VERSION_LOWER_SKIP_REASON) def test_fail_check_intracellular_electrode_cell_id_exists(): device = Device(name="device") ielec = IntracellularElectrode(name="ielec", device=device, description="an intracellular electrode") @@ -30,10 +22,3 @@ def test_fail_check_intracellular_electrode_cell_id_exists(): object_name="ielec", location="/", ) - - -@pytest.mark.skipif(not PYNWB_VERSION_LOWER_2_1_0, reason="This test requires PyNWB<2.1.0") -def test_skip_check_for_lower_versions(): - device = Device(name="device") - ielec = IntracellularElectrode(name="ielec", device=device, description="an intracellular electrode") - assert check_intracellular_electrode_cell_id_exists(ielec) is None diff --git a/tests/unit_tests/test_images.py b/tests/unit_tests/test_images.py index 6cc8db61a..01cf49990 100644 --- a/tests/unit_tests/test_images.py +++ b/tests/unit_tests/test_images.py @@ -1,6 +1,4 @@ import numpy as np -import pytest -from packaging.version import Version from pynwb import TimeSeries from pynwb.image import GrayscaleImage, IndexSeries @@ -10,15 +8,8 @@ check_order_of_images_len, check_order_of_images_unique, ) -from nwbinspector.utils import get_package_version -HAVE_IMAGES = get_package_version(name="pynwb") >= Version("2.1.0") -skip_reason = "You must have PyNWB>=v2.1.0 to run these tests!" -if HAVE_IMAGES: - from pynwb.base import ImageReferences, Images - -@pytest.mark.skipif(not HAVE_IMAGES, reason=skip_reason) def test_check_order_of_images_unique(): imgs = [GrayscaleImage(name=f"image{i}", data=np.random.randn(10, 10)) for i in range(5)] img_refs = ImageReferences(name="order_of_images", data=imgs + [imgs[0]]) @@ -34,7 +25,6 @@ def test_check_order_of_images_unique(): ) -@pytest.mark.skipif(not HAVE_IMAGES, reason=skip_reason) def test_pass_check_order_of_images_unique(): imgs = [GrayscaleImage(name=f"image{i}", data=np.random.randn(10, 10)) for i in range(5)] img_refs = ImageReferences(name="order_of_images", data=imgs) @@ -43,7 +33,6 @@ def test_pass_check_order_of_images_unique(): assert check_order_of_images_unique(images) is None -@pytest.mark.skipif(not HAVE_IMAGES, reason=skip_reason) def test_check_order_of_images_len(): imgs = [GrayscaleImage(name=f"image{i}", data=np.random.randn(10, 10)) for i in range(5)] img_refs = ImageReferences(name="order_of_images", data=imgs + [imgs[0]]) @@ -59,7 +48,6 @@ def test_check_order_of_images_len(): ) -@pytest.mark.skipif(not HAVE_IMAGES, reason=skip_reason) def test_pass_check_order_of_images_len(): imgs = [GrayscaleImage(name=f"image{i}", data=np.random.randn(10, 10)) for i in range(5)] img_refs = ImageReferences(name="order_of_images", data=imgs) @@ -68,7 +56,6 @@ def test_pass_check_order_of_images_len(): assert check_order_of_images_len(images) is None -@pytest.mark.skipif(not HAVE_IMAGES, reason=skip_reason) def test_pass_check_index_series_points_to_image(): gs_img = GrayscaleImage( name="random grayscale", @@ -95,7 +82,6 @@ def test_pass_check_index_series_points_to_image(): assert check_index_series_points_to_image(idx_series) is None -@pytest.mark.skipif(not HAVE_IMAGES, reason=skip_reason) def test_fail_check_index_series_points_to_image(): time_series = TimeSeries( name="TimeSeries", diff --git a/tests/unit_tests/test_tables.py b/tests/unit_tests/test_tables.py index 094a77533..fd9a5798e 100644 --- a/tests/unit_tests/test_tables.py +++ b/tests/unit_tests/test_tables.py @@ -4,7 +4,6 @@ import numpy as np from hdmf.common import DynamicTable, DynamicTableRegion -from packaging import version from pynwb.file import Device, ElectrodeGroup, ElectrodeTable, TimeIntervals, Units from nwbinspector import Importance, InspectorMessage @@ -20,7 +19,6 @@ check_time_interval_time_columns, check_time_intervals_stop_after_start, ) -from nwbinspector.utils import get_package_version class TestCheckDynamicTableRegion(TestCase): @@ -32,6 +30,7 @@ def setUp(self): def test_check_dynamic_table_region_data_validity_lt_zero(self): dynamic_table_region = DynamicTableRegion(name="dyn_tab", description="desc", data=[-1, 0], table=self.table) + assert check_dynamic_table_region_data_validity(dynamic_table_region) == InspectorMessage( message="Some elements of dyn_tab are out of range because they are less than 0.", importance=Importance.CRITICAL, @@ -43,6 +42,7 @@ def test_check_dynamic_table_region_data_validity_lt_zero(self): def test_check_dynamic_table_region_data_validity_gt_len(self): dynamic_table_region = DynamicTableRegion(name="dyn_tab", description="desc", data=[0, 20], table=self.table) + assert check_dynamic_table_region_data_validity(dynamic_table_region) == InspectorMessage( message=( "Some elements of dyn_tab are out of range because they are greater than the length of the target " @@ -57,6 +57,7 @@ def test_check_dynamic_table_region_data_validity_gt_len(self): def test_pass_check_dynamic_table_region_data(self): dynamic_table_region = DynamicTableRegion(name="dyn_tab", description="desc", data=[0, 1, 2], table=self.table) + assert check_dynamic_table_region_data_validity(dynamic_table_region) is None @@ -64,6 +65,7 @@ def test_check_empty_table_with_data(): table = DynamicTable(name="test_table", description="") table.add_column(name="test_column", description="") table.add_row(test_column=1) + assert check_empty_table(table=table) is None @@ -108,6 +110,7 @@ def test_check_time_intervals_stop_after_start(): time_intervals = TimeIntervals(name="test_table", description="desc") time_intervals.add_row(start_time=2.0, stop_time=1.5) time_intervals.add_row(start_time=3.0, stop_time=1.5) + assert check_time_intervals_stop_after_start(time_intervals) == InspectorMessage( message=( "stop_times should be greater than start_times. Make sure the stop times are with respect to the " @@ -125,6 +128,7 @@ def test_pass_check_time_intervals_stop_after_start(): time_intervals = TimeIntervals(name="test_table", description="desc") time_intervals.add_row(start_time=2.0, stop_time=2.5) time_intervals.add_row(start_time=3.0, stop_time=3.5) + assert check_time_intervals_stop_after_start(time_intervals) is None @@ -136,30 +140,35 @@ def test_non_binary_pass(self): self.table.add_column(name="test_col", description="") for x in [1.0, 2.0, 3.0]: self.table.add_row(test_col=x) + assert check_column_binary_capability(table=self.table) is None def test_array_of_non_binary_pass(self): self.table.add_column(name="test_col", description="") for x in [[1.0, 2.0], [2.0, 3.0], [1.0, 2.0]]: self.table.add_row(test_col=x) + assert check_column_binary_capability(table=self.table) is None def test_jagged_array_of_non_binary_pass(self): self.table.add_column(name="test_col", description="", index=True) for x in [[1.0, 2.0], [1.0, 2.0, 3.0], [1.0, 2.0]]: self.table.add_row(test_col=x) + assert check_column_binary_capability(table=self.table) is None def test_no_saved_bytes_pass(self): self.table.add_column(name="test_col", description="") for x in np.array([1, 0, 1, 0], dtype="uint8"): self.table.add_row(test_col=x) + assert check_column_binary_capability(table=self.table) is None def test_binary_floats_fail(self): self.table.add_column(name="test_col", description="") for x in [1.0, 0.0, 1.0, 0.0, 1.0]: self.table.add_row(test_col=x) + assert check_column_binary_capability(table=self.table) == [ InspectorMessage( message=( @@ -182,6 +191,7 @@ def test_binary_int_fail(self): platform_saved_bytes = "15.00B" else: platform_saved_bytes = "35.00B" + assert check_column_binary_capability(table=self.table) == [ InspectorMessage( message=( @@ -234,6 +244,7 @@ def test_check_single_row_pass(): table.add_column(name="test_column", description="") table.add_row(test_column=1) table.add_row(test_column=2) + assert check_single_row(table=table) is None @@ -242,6 +253,7 @@ def test_check_single_row_ignore_units(): name="Units", ) # default name when building through nwbfile table.add_unit(spike_times=[1, 2, 3]) + assert check_single_row(table=table) is None @@ -249,27 +261,12 @@ def test_check_single_row_ignore_electrodes(): table = ElectrodeTable( name="electrodes", ) # default name when building through nwbfile - if get_package_version(name="pynwb") >= version.Version("2.1.0"): - table.add_row( - location="unknown", - group=ElectrodeGroup( - name="test_group", description="", device=Device(name="test_device"), location="unknown" - ), - group_name="test_group", - ) - else: - table.add_row( - x=np.nan, - y=np.nan, - z=np.nan, - imp=np.nan, - location="unknown", - filtering="unknown", - group=ElectrodeGroup( - name="test_group", description="", device=Device(name="test_device"), location="unknown" - ), - group_name="test_group", - ) + table.add_row( + location="unknown", + group=ElectrodeGroup(name="test_group", description="", device=Device(name="test_device"), location="unknown"), + group_name="test_group", + ) + assert check_single_row(table=table) is None @@ -277,6 +274,7 @@ def test_check_single_row_fail(): table = DynamicTable(name="test_table", description="") table.add_column(name="test_column", description="") table.add_row(test_column=1) + assert check_single_row(table=table) == InspectorMessage( message="This table has only a single row; it may be better represented by another data type.", importance=Importance.BEST_PRACTICE_SUGGESTION, @@ -291,6 +289,7 @@ def test_check_table_values_for_dict_non_str(): table = DynamicTable(name="test_table", description="") table.add_column(name="test_column", description="") table.add_row(test_column=123) + assert check_table_values_for_dict(table=table) is None @@ -298,6 +297,7 @@ def test_check_table_values_for_dict_pass(): table = DynamicTable(name="test_table", description="") table.add_column(name="test_column", description="") table.add_row(test_column="123") + assert check_table_values_for_dict(table=table) is None @@ -305,6 +305,7 @@ def test_check_table_values_for_dict_fail(): table = DynamicTable(name="test_table", description="") table.add_column(name="test_column", description="") table.add_row(test_column=str(dict(a=1))) + assert check_table_values_for_dict(table=table)[0] == InspectorMessage( message=( "The column 'test_column' contains a string value that contains a dictionary! Please unpack " @@ -322,6 +323,7 @@ def test_check_table_values_for_dict_json_case_fail(): table = DynamicTable(name="test_table", description="") table.add_column(name="test_column", description="") table.add_row(test_column=json.dumps(dict(a=1))) + assert check_table_values_for_dict(table=table) == [ InspectorMessage( message=( @@ -343,6 +345,7 @@ def test_check_col_not_nan_pass(): for name in ["test_column_not_nan", "test_column_string"]: table.add_column(name=name, description="") table.add_row(test_column_not_nan=1.0, test_column_string="abc") + assert check_col_not_nan(table=table) is None @@ -355,6 +358,7 @@ def test_check_col_not_nan_fail(): table.add_row( test_column_not_nan_1=1.0, test_column_nan_1=np.nan, test_integer_type=1, test_column_nan_2=np.nan ) + assert check_col_not_nan(table=table) == [ InspectorMessage( message="Column 'test_column_nan_1' might have all NaN values. Consider removing it from the table.", @@ -386,6 +390,7 @@ def test_check_col_not_nan_fail_span_all_data(): table.add_row( test_column_not_nan_1=1.0, test_column_nan_1=np.nan, test_integer_type=1, test_column_nan_2=np.nan ) + assert check_col_not_nan(table=table) == [ InspectorMessage( message="Column 'test_column_nan_1' has all NaN values. Consider removing it from the table.", @@ -410,6 +415,7 @@ def test_check_col_not_nan_fail_span_all_data(): def test_fail_check_ids_unique(): dt = DynamicTable(name="test_table", description="test", id=[0, 0, 1, 1]) + assert check_ids_unique(dt) == InspectorMessage( message="This table has ids that are not unique.", importance=Importance.CRITICAL, @@ -423,6 +429,7 @@ def test_fail_check_ids_unique(): def test_pass_check_ids_unique(): dt = DynamicTable(name="test_table", description="test", id=[0, 1]) + assert check_ids_unique(dt) is None diff --git a/tests/unit_tests/test_time_series.py b/tests/unit_tests/test_time_series.py index 231179036..429b8048d 100644 --- a/tests/unit_tests/test_time_series.py +++ b/tests/unit_tests/test_time_series.py @@ -1,8 +1,6 @@ import h5py import numpy as np import pynwb -import pytest -from packaging import version from nwbinspector import Importance, InspectorMessage from nwbinspector.checks import ( @@ -17,7 +15,6 @@ check_timestamps_without_nans, ) from nwbinspector.testing import check_streaming_tests_enabled, make_minimal_nwbfile -from nwbinspector.utils import get_package_version STREAMING_TESTS_ENABLED, DISABLED_STREAMING_TESTS_REASON = check_streaming_tests_enabled() @@ -353,31 +350,6 @@ def test_check_unknown_resolution_pass(): assert check_resolution(time_series) is None -# TODO: remove test when past version HDMF/PyNWB testing is removed -@pytest.mark.skipif( - not STREAMING_TESTS_ENABLED or get_package_version("hdmf") >= version.parse("3.3.1"), - reason=f"{DISABLED_STREAMING_TESTS_REASON or ''}. Also needs 'hdmf<3.3.1'.", -) -def test_check_none_matnwb_resolution_pass(): - """ - Special test on the original problematic file found at - - https://dandiarchive.org/dandiset/000065/draft/files?location=sub-Kibbles%2F - - produced with MatNWB, when read with PyNWB~=2.0.1 and HDMF<=3.2.1 contains a resolution value of None. - """ - with pynwb.NWBHDF5IO( - path="https://dandiarchive.s3.amazonaws.com/blobs/da5/107/da510761-653e-4b81-a330-9cdae4838180", - mode="r", - load_namespaces=True, - driver="ros3", - ) as io: - nwbfile = io.read() - time_series = nwbfile.processing["video_files"]["video"]["20170203_KIB_01_s1.1.h264"] - - assert check_resolution(time_series=time_series) is None - - def test_check_resolution_fail(): time_series = pynwb.TimeSeries(name="test", unit="test", data=[1, 2, 3], timestamps=[1, 2, 3], resolution=-2.0) assert check_resolution(time_series) == InspectorMessage( From effc057c1244e2a88e0ee5e3f7f86fa5a95b29dd Mon Sep 17 00:00:00 2001 From: CodyCBakerPhD Date: Fri, 6 Sep 2024 15:26:26 -0400 Subject: [PATCH 2/5] explictly pin lower bound --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 53f62a427..b7e024f8f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -pynwb +pynwb>=2.8 # NWB Inspector should always be used with most recent minor versions of PyNWB hdmf-zarr fsspec s3fs From e31911033c960bf246001f23bfc6abf88a86964e Mon Sep 17 00:00:00 2001 From: CodyCBakerPhD Date: Fri, 6 Sep 2024 15:29:26 -0400 Subject: [PATCH 3/5] restore accidental context removal --- src/nwbinspector/_nwb_inspection.py | 41 +++++++++++++++-------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/nwbinspector/_nwb_inspection.py b/src/nwbinspector/_nwb_inspection.py index b3b1fdd19..38a30d984 100644 --- a/src/nwbinspector/_nwb_inspection.py +++ b/src/nwbinspector/_nwb_inspection.py @@ -279,26 +279,27 @@ def inspect_nwbfile( file_path=nwbfile_path, ) - try: - in_memory_nwbfile = io.read() - - for inspector_message in inspect_nwbfile_object( - nwbfile_object=in_memory_nwbfile, - checks=checks, - config=config, - ignore=ignore, - select=select, - importance_threshold=importance_threshold, - ): - inspector_message.file_path = nwbfile_path - yield inspector_message - except Exception as exception: - yield InspectorMessage( - message=traceback.format_exc(), - importance=Importance.ERROR, - check_function_name=f"During io.read() - {type(exception)}: {str(exception)}", - file_path=nwbfile_path, - ) + with pynwb.NWBHDF5IO(path=nwbfile_path, mode="r", load_namespaces=True) as io: + try: + in_memory_nwbfile = io.read() + + for inspector_message in inspect_nwbfile_object( + nwbfile_object=in_memory_nwbfile, + checks=checks, + config=config, + ignore=ignore, + select=select, + importance_threshold=importance_threshold, + ): + inspector_message.file_path = nwbfile_path + yield inspector_message + except Exception as exception: + yield InspectorMessage( + message=traceback.format_exc(), + importance=Importance.ERROR, + check_function_name=f"During io.read() - {type(exception)}: {str(exception)}", + file_path=nwbfile_path, + ) # TODO: deprecate once subject types and dandi schemas have been extended From b9327ac4ded1d64732ab148c991387f24ea51a35 Mon Sep 17 00:00:00 2001 From: CodyCBakerPhD Date: Fri, 6 Sep 2024 15:36:54 -0400 Subject: [PATCH 4/5] fix image test import --- tests/unit_tests/test_images.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit_tests/test_images.py b/tests/unit_tests/test_images.py index 01cf49990..4551fa989 100644 --- a/tests/unit_tests/test_images.py +++ b/tests/unit_tests/test_images.py @@ -1,5 +1,6 @@ import numpy as np from pynwb import TimeSeries +from pynwb.base import ImageReferences, Images from pynwb.image import GrayscaleImage, IndexSeries from nwbinspector import Importance, InspectorMessage From 124e40b884a5893809618176dd7512fa912228c3 Mon Sep 17 00:00:00 2001 From: Cody Baker <51133164+CodyCBakerPhD@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:11:59 -0400 Subject: [PATCH 5/5] Update CHANGELOG.md Co-authored-by: Steph Prince <40640337+stephprince@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b1606832..3201d8943 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ ### Improvements * Removed the `robust_ros3_read` utility helper. [#506](https://github.com/NeurodataWithoutBorders/nwbinspector/pull/506) -* Cleaned old references to non-recent PyNWB and HDMF versions. Current policy is that latest NWB Inspector releases should only support compatibility with latest PyNWB and HDMF. [#](https://github.com/NeurodataWithoutBorders/nwbinspector/pull/) +* Cleaned old references to non-recent PyNWB and HDMF versions. Current policy is that latest NWB Inspector releases should only support compatibility with latest PyNWB and HDMF. [#510](https://github.com/NeurodataWithoutBorders/nwbinspector/pull/510) # v0.5.2