Repository: ioos/compliance-checker
Pull request #811 (2020-05-15 20:25:47)

NDBC and GTS Ingest alterations
Always "fail" the GTS ingest check so that users are informed of
which variables have qualified versus which ones have not.
Adjust unit tests accordingly.

Addresses #759 (most recent comments)


Patch:
diff --git a/compliance_checker/ioos.py b/compliance_checker/ioos.py
index 75c8715..cd7694c 100644
--- a/compliance_checker/ioos.py
+++ b/compliance_checker/ioos.py
@@ -1195,8 +1195,7 @@ class IOOS1_2Check(IOOSNCCheck):
 
     def check_gts_ingest_requirements(self, ds):
         """
-        If a dataset is flagged for gts_ingest, check which variables
-        qualify for ingest.
+        Check which variables qualify for ingest.
 
         According to https://ioos.github.io/ioos-metadata/ioos-metadata-profile-v1-2.html#requirements-for-ioos-dataset-gts-ingest,
         the gts_ingest is "required, if applicable". Any variables which a user
@@ -1206,6 +1205,10 @@ class IOOS1_2Check(IOOSNCCheck):
           - have an ancillary variable reqpresenting QARTOD aggregate flags
           - have a valid udunits units attribute (already checked)
 
+        This check will always fail so as to notify the user which variables
+        qualified/did not qualify for ingest.
+        https://github.com/ioos/compliance-checker/issues/759#issuecomment-629454412
+
         Parameters
         ----------
         ds (netCDF4.Dataset): open Dataset
@@ -1217,50 +1220,39 @@ class IOOS1_2Check(IOOSNCCheck):
 
         # is dataset properly flagged for ingest?
         glb_gts_attr = getattr(ds, "gts_ingest", None)
-        if glb_gts_attr and (glb_gts_attr == "true" or glb_gts_attr == "false"):
-            do_gts = True if glb_gts_attr == "true" else False
-        else:
-            do_gts = False
 
         # check variables
         all_passed_ingest_reqs = True  # default
-        var_failed_ingest_msg = None
-        var_passed_ingest_msg = None
+        var_failed_ingest_msg = "The following variables did not qualify for NDBC/GTS Ingest: {}\n"
+        var_passed_ingest_msg = "The following variables qualified for NDBC/GTS Ingest: {}\n"
 
-        if do_gts:  # execute if dataset flagged for ingest
-
-            var_passed_ingest_reqs = set()
-            for v in ds.get_variables_by_attributes(gts_ingest=lambda x: x == "true"):
-                var_passed_ingest_reqs.add(
-                    (v.name, self._var_qualifies_for_gts_ingest(ds, v))
-                )
-
-            all_passed_ingest_reqs = all(map(lambda x: x[1], var_passed_ingest_reqs))
-            if not all_passed_ingest_reqs:
-                _var_failed = map(
-                    lambda y: y[0], filter(lambda x: not x[1], var_passed_ingest_reqs)
-                )
-                _var_passed = map(
-                    lambda y: y[0], filter(lambda x: x[1], var_passed_ingest_reqs)
-                )
+        var_passed_ingest_reqs = set()
+        for v in ds.get_variables_by_attributes(gts_ingest=lambda x: x == "true"):
+            var_passed_ingest_reqs.add(
+                (v.name, self._var_qualifies_for_gts_ingest(ds, v))
+            )
 
-                var_failed_ingest_msg = (
-                    "The following variables did not "
-                    "qualify for NDBC/GTS Ingest: {}".format(", ".join(_var_failed),)
-                )
+        # always show which variables have passed
+        _var_passed = map(
+            lambda y: y[0], filter(lambda x: x[1], var_passed_ingest_reqs)
+        )
 
-                var_passed_ingest_msg = (
-                    "The following variables qualified "
-                    "for NDBC/GTS Ingest: {}\n".format(", ".join(_var_passed))
-                )
+        all_passed_ingest_reqs = all(map(lambda x: x[1], var_passed_ingest_reqs))
+        if not all_passed_ingest_reqs:
+            _var_failed = map(
+                lambda y: y[0], filter(lambda x: not x[1], var_passed_ingest_reqs)
+            )
 
         return Result(
             BaseCheck.HIGH,
-            all_passed_ingest_reqs,
+            False, # always fail
             "NDBC/GTS Ingest Requirements",
-            None
+            [var_passed_ingest_msg.format(", ".join(_var_passed))]
             if all_passed_ingest_reqs
-            else [var_passed_ingest_msg, var_failed_ingest_msg],
+            else [
+                var_passed_ingest_msg.format(", ".join(_var_passed)),
+                var_failed_ingest_msg.format(", ".join(_var_failed))
+            ]
         )
 
     def check_instrument_variables(self, ds):


Test patch:
diff --git a/compliance_checker/tests/test_ioos_profile.py b/compliance_checker/tests/test_ioos_profile.py
index 29a629d..f0616a2 100644
--- a/compliance_checker/tests/test_ioos_profile.py
+++ b/compliance_checker/tests/test_ioos_profile.py
@@ -478,14 +478,18 @@ class TestIOOS1_2(BaseTestCase):
     def test_check_gts_ingest_requirements(self):
         ds = MockTimeSeries()  # time, lat, lon, depth
 
+        # NOTE: this check will always have a "failing" result; see
+        # https://github.com/ioos/compliance-checker/issues/759#issuecomment-625356938
+        # and subsequent discussion
+
         # no gts_ingest_requirements, should pass
         result = self.ioos.check_gts_ingest_requirements(ds)
-        self.assertTrue(result.value)
+        self.assertFalse(result.value)
 
         # flag for ingest, no variables flagged - default pass
         ds.setncattr("gts_ingest", "true")
         result = self.ioos.check_gts_ingest_requirements(ds)
-        self.assertTrue(result.value)
+        self.assertFalse(result.value)
 
         # give one variable the gts_ingest attribute
         # no standard_name or ancillary vars, should fail
@@ -498,6 +502,7 @@ class TestIOOS1_2(BaseTestCase):
         ds.variables["time"].setncattr("standard_name", "time")
         result = self.ioos.check_gts_ingest_requirements(ds)
         self.assertFalse(result.value)
+        self.assertIn('The following variables did not qualify for NDBC/GTS Ingest: time\n', result.msgs) 
 
         # set ancillary var with bad standard name
         tmp = ds.createVariable("tmp", np.byte, ("time",))
@@ -505,18 +510,21 @@ class TestIOOS1_2(BaseTestCase):
         ds.variables["time"].setncattr("ancillary_variables", "tmp")
         result = self.ioos.check_gts_ingest_requirements(ds)
         self.assertFalse(result.value)
+        self.assertIn('The following variables did not qualify for NDBC/GTS Ingest: time\n', result.msgs) 
 
         # good ancillary var standard name, time units are bad
         tmp.setncattr("standard_name", "aggregate_quality_flag")
         ds.variables["time"].setncattr("units", "bad since bad")
         result = self.ioos.check_gts_ingest_requirements(ds)
         self.assertFalse(result.value)
+        self.assertIn('The following variables did not qualify for NDBC/GTS Ingest: time\n', result.msgs) 
 
         # good ancillary var stdname, good units, pass
         tmp.setncattr("standard_name", "aggregate_quality_flag")
         ds.variables["time"].setncattr("units", "seconds since 1970-01-01T00:00:00Z")
         result = self.ioos.check_gts_ingest_requirements(ds)
-        self.assertTrue(result.value)
+        self.assertFalse(result.value)
+        self.assertIn('The following variables qualified for NDBC/GTS Ingest: time\n', result.msgs) 
 
     def test_check_instrument_variables(self):