diff --git a/pyPRMS/metadata/metadata.py b/pyPRMS/metadata/metadata.py index e095115..50390f3 100644 --- a/pyPRMS/metadata/metadata.py +++ b/pyPRMS/metadata/metadata.py @@ -117,8 +117,12 @@ def __filter_by_version(self, elem: xmlET.Element, name: str, meta_dict[name] = {} - try: - var_version = Version(elem.attrib.get('version')) + # Missing version/deprecated attributes are checked explicitly: + # relying on Version(None) to raise is fragile (packaging < 26.3 + # raised TypeError, packaging >= 26.3 raises InvalidVersion). + version_attr = elem.attrib.get('version') + if version_attr is not None: + var_version = Version(version_attr) if var_version > req_version: if self.__verbose: # pragma: no cover @@ -126,11 +130,10 @@ def __filter_by_version(self, elem: xmlET.Element, name: str, del meta_dict[name] return True meta_dict[name]['version'] = str(var_version) - except TypeError: - pass - try: - depr_version = Version(elem.attrib.get('deprecated')) + depr_attr = elem.attrib.get('deprecated') + if depr_attr is not None: + depr_version = Version(depr_attr) if depr_version <= req_version: if self.__verbose: # pragma: no cover @@ -138,8 +141,6 @@ def __filter_by_version(self, elem: xmlET.Element, name: str, del meta_dict[name] return True meta_dict[name]['deprecated'] = depr_version - except TypeError: - pass return False diff --git a/pyproject.toml b/pyproject.toml index 1f665dd..682a984 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ dependencies = ["cartopy", "netCDF4!=1.7.4", "networkx>=2", "numpy", + "packaging", "pandas", "pyproj", "rich", diff --git a/tests/func/test_MetaData.py b/tests/func/test_MetaData.py index 5caaf7d..07316b7 100644 --- a/tests/func/test_MetaData.py +++ b/tests/func/test_MetaData.py @@ -26,3 +26,16 @@ def test_metadata_version5(self): def test_metadata_version4(self): prms_meta = MetaData(version='4', verbose=True).metadata assert prms_meta['parameters'].get('soilzone_aet_flag', None) is None + + def test_metadata_no_version_attributes(self): + """Entries lacking version/deprecated XML attributes are retained. + + Regression test: packaging >= 26.3 raises InvalidVersion instead of + TypeError for Version(None), which crashed MetaData for any element + without these attributes. + """ + prms_meta = MetaData(version='5.2.1.1', verbose=True).metadata + # cascade_flag has neither a version nor a deprecated attribute + assert 'cascade_flag' in prms_meta['control'] + # nhruOutON_OFF has only a deprecated attribute + assert 'nhruOutON_OFF' in prms_meta['control']