Repository: ioos/compliance-checker
Pull request #916 (2022-04-08 18:08:53)

Adds checks for .nc filename extensions

codecov[bot]: # [Codecov](https://codecov.io/gh/ioos/compliance-checker/pull/916?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ioos) Report
> Merging [#916](https://codecov.io/gh/ioos/compliance-checker/pull/916?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ioos) (76ad3f0) into [master](https://codecov.io/gh/ioos/compliance-checker/commit/0d59ff5788b215c5d7bd5d2853530c269b56a0a1?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ioos) (0d59ff5) will **increase** coverage by `0.03%`.
> The diff coverage is `50.00%`.

```diff
@@            Coverage Diff             @@
##           master     #916      +/-   ##
==========================================
+ Coverage   78.45%   78.49%   +0.03%     
==========================================
  Files          23       23              
  Lines        5218     5217       -1     
  Branches     1297     1295       -2     
==========================================
+ Hits         4094     4095       +1     
+ Misses        833      832       -1     
+ Partials      291      290       -1     
```


| [Impacted Files](https://codecov.io/gh/ioos/compliance-checker/pull/916?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ioos) | Coverage Δ | |
|---|---|---|
| [compliance\_checker/cf/cf\_1\_6.py](https://codecov.io/gh/ioos/compliance-checker/pull/916/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ioos#diff-Y29tcGxpYW5jZV9jaGVja2VyL2NmL2NmXzFfNi5weQ==) | `88.20% <50.00%> (+0.38%)` | :arrow_up: |
| [compliance\_checker/suite.py](https://codecov.io/gh/ioos/compliance-checker/pull/916/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ioos#diff-Y29tcGxpYW5jZV9jaGVja2VyL3N1aXRlLnB5) | `81.23% <0.00%> (-0.45%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/ioos/compliance-checker/pull/916?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ioos).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ioos)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/ioos/compliance-checker/pull/916?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ioos). Last update [0d59ff5...76ad3f0](https://codecov.io/gh/ioos/compliance-checker/pull/916?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ioos). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ioos).


Patch:
diff --git a/compliance_checker/cf/cf_1_6.py b/compliance_checker/cf/cf_1_6.py
index ffc43ea..65f929a 100644
--- a/compliance_checker/cf/cf_1_6.py
+++ b/compliance_checker/cf/cf_1_6.py
@@ -49,6 +49,13 @@ class CF1_6Check(CFNCCheck):
     ###############################################################################
     # Chapter 2: NetCDF Files and Components
     ###############################################################################
+    def check_filename(self, ds):
+        """Checks that the filename ends with .nc"""
+        # IMPLEMENTS CONFORMANCE 2.1
+        filename_suffix = TestCtx(BaseCheck.HIGH, self.section_titles["2.1"])
+        filename_suffix.assert_true(ds.filepath().endswith("nc"),
+                        f'Dataset path {ds.filepath} must end with ".nc"')
+        return filename_suffix.to_result()
 
     def check_data_types(self, ds):
         """
diff --git a/compliance_checker/cf/cf_base.py b/compliance_checker/cf/cf_base.py
index ab6ebf2..2af6376 100644
--- a/compliance_checker/cf/cf_base.py
+++ b/compliance_checker/cf/cf_base.py
@@ -57,6 +57,7 @@ class CFBaseCheck(BaseCheck):
         self._std_names = util.StandardNameTable()
 
         self.section_titles = {  # dict of section headers shared by grouped checks
+            "2.1": "§2.1 Filename",
             "2.2": "§2.2 Data Types",
             "2.3": "§2.3 Naming Conventions",
             "2.4": "§2.4 Dimensions",


Test patch:
diff --git a/compliance_checker/tests/helpers.py b/compliance_checker/tests/helpers.py
index 19ecd56..8725df8 100644
--- a/compliance_checker/tests/helpers.py
+++ b/compliance_checker/tests/helpers.py
@@ -8,13 +8,16 @@ class MockNetCDF(Dataset):
     Wrapper object around NetCDF Dataset to write data only to memory.
     """
 
-    def __init__(self):
+    def __init__(self, filename=None):
         # taken from test/tst_diskless.py NetCDF library
         # even though we aren't persisting data to disk, the constructor
         # requires a filename not currently in use by another Dataset object..
-        tmp_filename = tempfile.NamedTemporaryFile(suffix=".nc", delete=True).name
+        if filename is None:
+            temp_filename = tempfile.NamedTemporaryFile(suffix=".nc", delete=True).name
+        else:
+            temp_filename = filename
         super(MockNetCDF, self).__init__(
-            tmp_filename, "w", diskless=True, persist=False
+            temp_filename, "w", diskless=True, persist=False
         )
 
 
@@ -24,11 +27,12 @@ class MockTimeSeries(MockNetCDF):
     variables defined
     """
 
-    def __init__(self, default_fill_value=None):
-        super(MockTimeSeries, self).__init__()
+    def __init__(self, filename=None, default_fill_value=None):
+        super(MockTimeSeries, self).__init__(filename)
         self.createDimension("time", 500)
         for v in ("time", "lon", "lat", "depth"):
-            self.createVariable(v, "d", ("time",), fill_value=default_fill_value)
+            self.createVariable(v, "d", ("time",),
+                                fill_value=default_fill_value)
 
         # give some applicable units
         self.variables["time"].units = "seconds since 2019-04-11T00:00:00"
diff --git a/compliance_checker/tests/test_cf.py b/compliance_checker/tests/test_cf.py
index 1ef2d22..090d884 100644
--- a/compliance_checker/tests/test_cf.py
+++ b/compliance_checker/tests/test_cf.py
@@ -90,6 +90,15 @@ class TestCF1_6(BaseTestCase):
         self.addCleanup(nc.close)
         return nc
 
+    def test_extension(self):
+        # TEST CONFORMANCE 2.1
+        ds = MockTimeSeries()
+        result = self.cf.check_filename(ds)
+        assert result.value[0] == result.value[1]
+        ds = MockTimeSeries("filename.notncending")
+        result = self.cf.check_filename(ds)
+        assert result.value[0] != result.value[1]
+
     def test_coord_data_vars(self):
         """Check that coordinate data variables are properly handled"""
         ds = MockTimeSeries()