Repository: ioos/compliance-checker
Pull request #1009 (2023-04-14 16:57:12)

Fix numpy deprecations that are errors in 1.24.2
I also run pre-commit on the files I touched so we slowly get them all back into compliance.


Patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 86ec7fa..9c48357 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -34,17 +34,17 @@ repos:
     - id: seed-isort-config
 
 - repo: https://github.com/psf/black
-  rev: 22.12.0
+  rev: 23.3.0
   hooks:
   - id: black
     language_version: python3
 
 - repo: https://github.com/codespell-project/codespell
-  rev: v2.2.2
+  rev: v2.2.4
   hooks:
     - id: codespell
       args:
-        - --ignore-words-list=degreeE,degreee,varn,poit,uint,sur,herat
+        - --ignore-words-list=degreeE,degreee,varn,poit,uint,sur,herat,claus,tung,messsages
       exclude: >
           (?x)^(
               .*\.xml|
diff --git a/compliance_checker/cf/cf_1_6.py b/compliance_checker/cf/cf_1_6.py
index bfe9367..5585dba 100644
--- a/compliance_checker/cf/cf_1_6.py
+++ b/compliance_checker/cf/cf_1_6.py
@@ -14,15 +14,21 @@ from cf_units import Unit
 from compliance_checker import cfutil
 from compliance_checker.base import BaseCheck, BaseNCCheck, Result, TestCtx
 from compliance_checker.cf import util
-from compliance_checker.cf.appendix_d import (dimless_vertical_coordinates_1_6,
-                                              no_missing_terms)
+from compliance_checker.cf.appendix_d import (
+    dimless_vertical_coordinates_1_6,
+    no_missing_terms,
+)
 from compliance_checker.cf.appendix_e import cell_methods16
-from compliance_checker.cf.appendix_f import (grid_mapping_attr_types16,
-                                              grid_mapping_dict16)
-
+from compliance_checker.cf.appendix_f import (
+    grid_mapping_attr_types16,
+    grid_mapping_dict16,
+)
 from compliance_checker.cf.cf_base import CFNCCheck, appendix_a_base
+
+
 logger = logging.getLogger(__name__)
 
+
 class CF1_6Check(CFNCCheck):
     """CF-1.6-specific implementation of CFBaseCheck; supports checking
     netCDF datasets.
@@ -145,14 +151,13 @@ class CF1_6Check(CFNCCheck):
             val = (
                 att.dtype == variable.dtype
             ) or (  # will short-circuit or if first condition is true
-                isinstance(att.dtype, (np.float, np.double, float))
-                and isinstance(variable.dtype, (np.byte, np.short, np.int, int))
+                isinstance(att.dtype, (np.double, float))
+                and isinstance(variable.dtype, (np.byte, np.short, int))
             )
         if not val:
             msgs.append(error_msg)
 
-        return Result(BaseCheck.MEDIUM, val, self.section_titles["8.1"],
-                      msgs)
+        return Result(BaseCheck.MEDIUM, val, self.section_titles["8.1"], msgs)
 
     def check_add_offset_scale_factor_type(self, ds):
         """
@@ -2581,7 +2586,6 @@ class CF1_6Check(CFNCCheck):
                         or var_str == "area"
                         or var_str in getattr(var, "coordinates", "")
                     ):
-
                         valid = True
                     else:
                         valid = False
@@ -2815,11 +2819,14 @@ class CF1_6Check(CFNCCheck):
                 )
                 ret_val.append(result)
 
-            elif (ds.dimensions[
+            elif (
+                ds.dimensions[
                     ds.variables[clim_coord_var.climatology].dimensions[-1]
-                ].size != 2):
+                ].size
+                != 2
+            ):
                 reasoning.append(
-                    "Climatology dimension \"{}\" should only contain two elements".format(
+                    'Climatology dimension "{}" should only contain two elements'.format(
                         ds.variables[clim_coord_var.climatology].name
                     )
                 )
@@ -2908,7 +2915,6 @@ class CF1_6Check(CFNCCheck):
         """
         ret_val = []
         for name, var in ds.variables.items():
-
             add_offset = getattr(var, "add_offset", None)
             scale_factor = getattr(var, "scale_factor", None)
             if not (add_offset or scale_factor):
@@ -2939,7 +2945,7 @@ class CF1_6Check(CFNCCheck):
                 else:
                     # Check variable type is byte, short or int
                     if var.dtype.type not in [
-                        np.int,
+                        int,
                         np.int8,
                         np.int16,
                         np.int32,
@@ -3235,4 +3241,3 @@ class CF1_6Check(CFNCCheck):
                 ret_val.append(result)
 
         return ret_val
-
diff --git a/compliance_checker/cf/cf_1_8.py b/compliance_checker/cf/cf_1_8.py
index 9ba3637..70429e3 100644
--- a/compliance_checker/cf/cf_1_8.py
+++ b/compliance_checker/cf/cf_1_8.py
@@ -1,19 +1,25 @@
-from compliance_checker.base import BaseCheck, TestCtx, Result
-from compliance_checker import MemoizedDataset
-from compliance_checker.cf.cf_1_7 import CF1_7Check
-from netCDF4 import Dataset
-from compliance_checker.base import BaseCheck, BaseNCCheck, Result, TestCtx
+import itertools
+import re
+import warnings
+
+import numpy as np
 import requests
+
 from lxml import etree
-from shapely.geometry import Polygon
-import numpy as np
-import re
+from netCDF4 import Dataset
+from shapely.geometry import (
+    LineString,
+    MultiLineString,
+    MultiPoint,
+    MultiPolygon,
+    Polygon,
+)
+
+from compliance_checker import MemoizedDataset
+from compliance_checker.base import BaseCheck, BaseNCCheck, Result, TestCtx
+from compliance_checker.cf.cf_1_7 import CF1_7Check
 from compliance_checker.cf.util import reference_attr_variables, string_from_var_type
-import itertools
-import warnings
-from shapely.geometry import (MultiPoint, LineString, MultiLineString, Polygon,
-                              MultiPolygon)
-from compliance_checker.cf.util import reference_attr_variables
+
 
 """
 What's new in CF-1.8
@@ -40,11 +46,13 @@ class CF1_8Check(CF1_7Check):
 
     def __init__(self, options=None):
         super(CF1_8Check, self).__init__(options)
-        self.section_titles.update({"2.7":
-                                    "§2.7 Groups",
-                                    "6.1.2":
-                                    "§6.1.2 Taxon Names and Identifiers",
-                                    "7.5": "§7.5 Geometries"})
+        self.section_titles.update(
+            {
+                "2.7": "§2.7 Groups",
+                "6.1.2": "§6.1.2 Taxon Names and Identifiers",
+                "7.5": "§7.5 Geometries",
+            }
+        )
 
     def check_groups(self, ds: MemoizedDataset):
         """
@@ -94,7 +102,6 @@ class CF1_8Check(CF1_7Check):
 
             for attr in ginstance.ncattrs():
                 if attr in CF1_8Check.ROOT_GROUP_ONLY_ATTRS:
-
                     ctx_hi.messages.append(
                         f'§2.7.2 Attribute "{ attr }" MAY ONLY be used in the root group '
                         "and SHALL NOT be duplicated or overridden in child groups."
@@ -103,7 +110,6 @@ class CF1_8Check(CF1_7Check):
                     results.append(ctx_hi.to_result())
 
                 elif attr in CF1_8Check.NON_ROOT_GROUP_OPT:
-
                     ctx_lo.messages.append(
                         f"§2.7.2 Note: attribute '{ attr }' found on non-root group '{ gname }'. "
                         "This is optional for non-root groups. It is allowed in order to provide additional "
@@ -120,7 +126,8 @@ class CF1_8Check(CF1_7Check):
         :returns list: List of error messages
         """
         vars_with_geometry = ds.get_variables_by_attributes(
-                                geometry=lambda g: g is not None)
+            geometry=lambda g: g is not None
+        )
         results = []
         unique_geometry_var_names = {var.geometry for var in vars_with_geometry}
         if unique_geometry_var_names:
@@ -128,8 +135,9 @@ class CF1_8Check(CF1_7Check):
             geom_valid.out_of += 1
         for geometry_var_name in unique_geometry_var_names:
             if geometry_var_name not in ds.variables:
-                geom_valid.messages.append("Cannot find geometry variable "
-                                           f"named {geometry_var_name}")
+                geom_valid.messages.append(
+                    "Cannot find geometry variable " f"named {geometry_var_name}"
+                )
                 results.append(geom_valid.to_result())
                 continue
             else:
@@ -140,15 +148,18 @@ class CF1_8Check(CF1_7Check):
             try:
                 node_coord_var_names = geometry_var.node_coordinates
             except AttributeError as e:
-                geom_valid.messsages.append('Could not find required attribute '
-                                            '"node_coordinates" in geometry '
-                                            f'variable "{geometry_var_name}"')
+                geom_valid.messsages.append(
+                    "Could not find required attribute "
+                    '"node_coordinates" in geometry '
+                    f'variable "{geometry_var_name}"'
+                )
                 results.append(geom_valid.to_result())
             if not isinstance(node_coord_var_names, str):
                 geom_valid.messages.append(
-                                  'Attribute "node_coordinates" in geometry '
-                                  f'variable "{geometry_var_name}" must be '
-                                  'a string')
+                    'Attribute "node_coordinates" in geometry '
+                    f'variable "{geometry_var_name}" must be '
+                    "a string"
+                )
                 results.append(geom_valid.to_result())
                 continue
             split_coord_names = node_coord_var_names.strip().split(" ")
@@ -161,38 +172,42 @@ class CF1_8Check(CF1_7Check):
             # If any variables weren't found, we can't continue
             if not_found_node_vars:
                 geom_valid.messages.append(
-                                  "The following referenced node coordinate"
-                                  "variables for geometry variable"
-                                  f'"{geometry_var_name}" were not found: '
-                                  f'{not_found_node_vars}')
+                    "The following referenced node coordinate"
+                    "variables for geometry variable"
+                    f'"{geometry_var_name}" were not found: '
+                    f"{not_found_node_vars}"
+                )
                 results.append(geom_valid.to_result())
                 continue
                 return error_msgs
 
-            node_count = reference_attr_variables(ds,
-                               getattr(geometry_var, "node_count", None))
+            node_count = reference_attr_variables(
+                ds, getattr(geometry_var, "node_count", None)
+            )
             # multipart lines and polygons only
-            part_node_count = reference_attr_variables(ds,
-                                getattr(geometry_var, "part_node_count", None))
+            part_node_count = reference_attr_variables(
+                ds, getattr(geometry_var, "part_node_count", None)
+            )
             # polygons with interior geometry only
-            interior_ring = reference_attr_variables(ds,
-                               getattr(geometry_var, "interior_ring", None))
+            interior_ring = reference_attr_variables(
+                ds, getattr(geometry_var, "interior_ring", None)
+            )
 
             if geometry_type == "point":
                 geometry = PointGeometry(node_coord_vars, node_count)
             elif geometry_type == "line":
-                geometry = LineGeometry(node_coord_vars, node_count,
-                                        part_node_count)
+                geometry = LineGeometry(node_coord_vars, node_count, part_node_count)
             elif geometry_type == "polygon":
-                geometry = PolygonGeometry(node_coord_vars, node_count,
-                                                    part_node_count,
-                                                    interior_ring)
+                geometry = PolygonGeometry(
+                    node_coord_vars, node_count, part_node_count, interior_ring
+                )
             else:
                 geom_valid.messages.append(
-                                  f'For geometry variable "{geometry_var_name}'
-                                  'the attribute "geometry_type" must exist'
-                                  'and have one of the following values:'
-                                  '"point", "line", "polygon"')
+                    f'For geometry variable "{geometry_var_name}'
+                    'the attribute "geometry_type" must exist'
+                    "and have one of the following values:"
+                    '"point", "line", "polygon"'
+                )
                 results.append(geom_valid.to_result())
                 continue
             # check geometry
@@ -237,10 +252,12 @@ class CF1_8Check(CF1_7Check):
         ret_val = []
         # taxa identification variables
         taxa_name_variables = ds.get_variables_by_attributes(
-                                                          standard_name="biological_taxon_name")
+            standard_name="biological_taxon_name"
+        )
         taxa_lsid_variables = ds.get_variables_by_attributes(
-                                                          standard_name="biological_taxon_identifier")
-        
+            standard_name="biological_taxon_identifier"
+        )
+
         def match_taxa_standard_names(standard_name_string):
             """
             Match variables which are standard_names related to taxa, but
@@ -483,10 +500,10 @@ class GeometryStorage(object):
 
     def _split_mulitpart_geometry(self):
         arr_extents_filt = self.part_node_count[self.part_node_count > 0]
-        splits = np.split(np.vstack(self.coord_vars).T,
-                          arr_extents_filt.cumsum()[:-1])
+        splits = np.split(np.vstack(self.coord_vars).T, arr_extents_filt.cumsum()[:-1])
         return splits
 
+
 class PointGeometry(GeometryStorage):
     """Class for validating Point/MultiPoint geometries"""
 
@@ -499,19 +516,21 @@ class PointGeometry(GeometryStorage):
             expected_node_count = self.node_count
 
         if all(len(cv.dimensions) != 0 for cv in self.coord_vars):
-            same_dim_group = itertools.groupby(self.coord_vars,
-                                            lambda x: x.dimensions)
-            same_dim = (next(same_dim_group, True) and
-                             not next(same_dim_group, False))
+            same_dim_group = itertools.groupby(self.coord_vars, lambda x: x.dimensions)
+            same_dim = next(same_dim_group, True) and not next(same_dim_group, False)
             if not same_dim:
-                self.errors.append("For a point geometry, coordinate "
-                                   "variables must be the same length as "
-                                   "node_count defined, or must be "
-                                   "length 1 if node_count is not set")
+                self.errors.append(
+                    "For a point geometry, coordinate "
+                    "variables must be the same length as "
+                    "node_count defined, or must be "
+                    "length 1 if node_count is not set"
+                )
         return self.errors
 
+
 class LineGeometry(GeometryStorage):
     """Class for validating Line/MultiLine geometries"""
+
     def __init__(self, coord_vars, node_count, part_node_count):
         super().__init__(coord_vars, node_count)
         self.part_node_count = part_node_count
@@ -520,40 +539,46 @@ class LineGeometry(GeometryStorage):
 
     def check_geometry(self):
         geom_errors = []
-        same_dim_group = itertools.groupby(self.coord_vars,
-                                           lambda x: x.dimensions)
-        same_dim = (next(same_dim_group, True) and
-                         not next(same_dim_group, False))
+        same_dim_group = itertools.groupby(self.coord_vars, lambda x: x.dimensions)
+        same_dim = next(same_dim_group, True) and not next(same_dim_group, False)
         if not same_dim:
-            raise IndexError("Coordinate variables must be the same length. "
-                            "If node_count is specified, this value must "
-                            "also sum to the length of the coordinate "
-                            "variables.")
+            raise IndexError(
+                "Coordinate variables must be the same length. "
+                "If node_count is specified, this value must "
+                "also sum to the length of the coordinate "
+                "variables."
+            )
         # if a multipart
         if self.node_count is not None:
             same_length = len(self.coord_vars[0]) == self.node_count[:].sum()
             if not same_length:
-                geom_errors.append("Coordinate variables must be the same "
-                                   "length. If node_count is specified, this "
-                                   "value must also sum to the length of the "
-                                    "coordinate variables.")
+                geom_errors.append(
+                    "Coordinate variables must be the same "
+                    "length. If node_count is specified, this "
+                    "value must also sum to the length of the "
+                    "coordinate variables."
+                )
         if self.part_node_count is not None:
             if not np.issubdtype(self.part_node_count.dtype, np.integer):
-                geom_errors.append("when part_node_count is specified, it must "
-                                   "be an array of integers")
+                geom_errors.append(
+                    "when part_node_count is specified, it must "
+                    "be an array of integers"
+                )
             same_node_count = len(self.coord_vars[0]) == self.node_count[:].sum()
             if not same_node_count:
-                geom_errors.append("The sum of part_node_count must be equal "
-                                   "to the value of node_count")
+                geom_errors.append(
+                    "The sum of part_node_count must be equal "
+                    "to the value of node_count"
+                )
         return geom_errors
 
 
 class PolygonGeometry(LineGeometry):
     """Class for validating Line/MultiLine geometries"""
+
     # TODO/clarify: Should polygons be simple, i.e. non-self intersecting?
     # Presumably
-    def __init__(self, coord_vars, node_count, part_node_count,
-                    interior_ring):
+    def __init__(self, coord_vars, node_count, part_node_count, interior_ring):
         super().__init__(coord_vars, node_count, part_node_count)
         self.part_node_count = part_node_count
         self.interior_ring = interior_ring
@@ -578,7 +603,9 @@ class PolygonGeometry(LineGeometry):
         try:
             polygon = Polygon(transposed_coords.tolist())
         except ValueError:
-            raise ValueError("Polygon contains too few points to perform orientation test")
+            raise ValueError(
+                "Polygon contains too few points to perform orientation test"
+            )
 
         ccw = polygon.exterior.is_ccw
         return not ccw if interior else ccw
@@ -590,8 +617,7 @@ class PolygonGeometry(LineGeometry):
         if messages:
             return messages
         if self.part_node_count is not None:
-            extents = np.concatenate([np.array([0]),
-                                     self.part_node_count[:].cumsum()])
+            extents = np.concatenate([np.array([0]), self.part_node_count[:].cumsum()])
             if self.interior_ring is not None:
                 ring_orientation = self.interior_ring[:].astype(bool)
             else:
@@ -599,8 +625,7 @@ class PolygonGeometry(LineGeometry):
             current_node_count = self.node_count[:].copy()
             node_indexer_len = len(self.part_node_count)
         else:
-            extents = np.concatenate([np.array([0]),
-                                     self.node_count[:].cumsum()])
+            extents = np.concatenate([np.array([0]), self.node_count[:].cumsum()])
             node_indexer_len = len(self.node_count)
             ring_orientation = np.zeros(node_indexer_len, dtype=bool)
         # TODO: is it necessary to check whether part_node_count "consumes"
@@ -608,19 +633,22 @@ class PolygonGeometry(LineGeometry):
         #       a node part of 9, follow by next 3 will consume a node part of
         #       3 after consuming
         for i in range(node_indexer_len):
-            extent_slice = slice(extents[i], extents[i+1])
-            poly_sliced = np.vstack([cv[extent_slice] for cv in
-                                     self.coord_vars]).T
-            pass_orientation = (self.check_polygon_orientation(
-                                            poly_sliced,
-                                            ring_orientation[i]))
+            extent_slice = slice(extents[i], extents[i + 1])
+            poly_sliced = np.vstack([cv[extent_slice] for cv in self.coord_vars]).T
+            pass_orientation = self.check_polygon_orientation(
+                poly_sliced, ring_orientation[i]
+            )
             if not pass_orientation:
-                orient_fix = (("exterior", "counterclockwise")
-                                 if not ring_orientation[i] else
-                               ("interior", "clockwise"))
-                message = (f"An {orient_fix[0]} polygon referred to by "
-                           f"coordinates ({poly_sliced}) must have coordinates "
-                           f"in {orient_fix[1]} order")
+                orient_fix = (
+                    ("exterior", "counterclockwise")
+                    if not ring_orientation[i]
+                    else ("interior", "clockwise")
+                )
+                message = (
+                    f"An {orient_fix[0]} polygon referred to by "
+                    f"coordinates ({poly_sliced}) must have coordinates "
+                    f"in {orient_fix[1]} order"
+                )
                 messages.append(message)
         return messages
 
@@ -735,7 +763,7 @@ class GeometryStorage(object):
     def check_geometry(self):
         invalid_vars = []
         for coord_var in self.coord_vars:
-            if not np.issubdtype(coord_var, np.float):
+            if not np.issubdtype(coord_var, float):
                 invalid_vars.append(coord_var.name)
         # can't continue if the geometry variables are not the correct size
         if invalid_vars:


Test patch:
diff --git a/compliance_checker/tests/test_cf.py b/compliance_checker/tests/test_cf.py
index 90786f8..5321536 100644
--- a/compliance_checker/tests/test_cf.py
+++ b/compliance_checker/tests/test_cf.py
@@ -2,7 +2,9 @@
 # -*- coding: utf-8 -*-
 
 import copy
+import json
 import os
+import re
 import sqlite3
 
 from itertools import chain
@@ -10,10 +12,12 @@ from tempfile import gettempdir
 
 import numpy as np
 import pytest
+import requests_mock
 
 from netCDF4 import Dataset, stringtoarr
 
 from compliance_checker import cfutil
+from compliance_checker.cf.appendix_d import no_missing_terms
 from compliance_checker.cf.cf import (
     CF1_6Check,
     CF1_7Check,
@@ -21,7 +25,6 @@ from compliance_checker.cf.cf import (
     dimless_vertical_coordinates_1_6,
     dimless_vertical_coordinates_1_7,
 )
-from compliance_checker.cf.appendix_d import no_missing_terms
 from compliance_checker.cf.util import (
     StandardNameTable,
     create_cached_data_dir,
@@ -33,11 +36,11 @@ from compliance_checker.cf.util import (
 )
 from compliance_checker.suite import CheckSuite
 from compliance_checker.tests import BaseTestCase
-from compliance_checker.tests.helpers import (MockRaggedArrayRepr,
-                                              MockTimeSeries, MockVariable)
-import requests_mock
-import json
-import re
+from compliance_checker.tests.helpers import (
+    MockRaggedArrayRepr,
+    MockTimeSeries,
+    MockVariable,
+)
 from compliance_checker.tests.resources import STATIC_FILES
 
 
@@ -99,7 +102,7 @@ class TestCF1_6(BaseTestCase):
             "temp",
             np.float64,
             dimensions=("time",),
-            fill_value=np.float(99999999999999999999.0),
+            fill_value=float(99999999999999999999.0),
         )
         temp.coordinates = "sigma noexist"
         ds.createVariable("sigma", np.float64, dimensions=("siglev",))
@@ -171,7 +174,7 @@ class TestCF1_6(BaseTestCase):
             "temp",
             np.float64,
             dimensions=("time",),
-            fill_value=np.float(99999999999999999999.0),
+            fill_value=float(99999999999999999999.0),
         )
 
         # give temp _FillValue as a float, expect good result
@@ -258,7 +261,7 @@ class TestCF1_6(BaseTestCase):
         assert len(results) == 3
         assert scored < out_of
         assert len([r for r in results if r.value[0] < r.value[1]]) == 2
-        assert all(r.name == u"§2.3 Naming Conventions" for r in results)
+        assert all(r.name == "§2.3 Naming Conventions" for r in results)
 
         # another non-compliant dataset
         dataset = self.load_dataset(STATIC_FILES["chap2"])
@@ -267,7 +270,7 @@ class TestCF1_6(BaseTestCase):
         assert len(results) == 3
         assert scored < out_of
         assert len([r for r in results if r.value[0] < r.value[1]]) == 2
-        assert all(r.name == u"§2.3 Naming Conventions" for r in results)
+        assert all(r.name == "§2.3 Naming Conventions" for r in results)
 
     def test_check_names_unique(self):
         """
@@ -286,7 +289,7 @@ class TestCF1_6(BaseTestCase):
         assert result.value == (6, 7)
         assert (
             result.msgs[0]
-            == u"Variables are not case sensitive. Duplicate variables named: not_unique"
+            == "Variables are not case sensitive. Duplicate variables named: not_unique"
         )
 
     def test_check_dimension_names(self):
@@ -300,7 +303,7 @@ class TestCF1_6(BaseTestCase):
 
         dataset = self.load_dataset(STATIC_FILES["chap2"])
         result = self.cf.check_dimension_names(dataset)
-        assert result.msgs[0] == u"no_reason has two or more dimensions named time"
+        assert result.msgs[0] == "no_reason has two or more dimensions named time"
 
     def test_check_dimension_order(self):
         """
@@ -313,7 +316,7 @@ class TestCF1_6(BaseTestCase):
         result = self.cf.check_dimension_order(dataset)
         assert result.value == (5, 6)
         assert result.msgs[0] == (
-            u"really_bad's spatio-temporal dimensions are not in the "
+            "really_bad's spatio-temporal dimensions are not in the "
             "recommended order T, Z, Y, X and/or further dimensions are not "
             "located left of T, Z, Y, X. The dimensions (and their guessed "
             "types) are latitude (Y), power (U) (with U: other/unknown; L: "
@@ -333,7 +336,7 @@ class TestCF1_6(BaseTestCase):
         dataset = self.load_dataset(STATIC_FILES["bad_data_type"])
         result = self.cf.check_fill_value_outside_valid_range(dataset)
         assert result.msgs[0] == (
-            u"salinity:_FillValue (1.0) should be outside the "
+            "salinity:_FillValue (1.0) should be outside the "
             "range specified by valid_min/valid_max (-10, 10)"
         )
 
@@ -341,7 +344,7 @@ class TestCF1_6(BaseTestCase):
         result = self.cf.check_fill_value_outside_valid_range(dataset)
         assert result.value == (1, 2)
         assert result.msgs[0] == (
-            u"wind_speed:_FillValue (12.0) should be outside the "
+            "wind_speed:_FillValue (12.0) should be outside the "
             "range specified by valid_min/valid_max (0.0, 20.0)"
         )
 
@@ -365,7 +368,7 @@ class TestCF1_6(BaseTestCase):
         result = self.cf.check_conventions_version(dataset)
         self.assertFalse(result.value)
         assert result.msgs[0] == (
-            u"§2.6.1 Conventions global attribute does not contain " '"CF-1.6"'
+            "§2.6.1 Conventions global attribute does not contain " '"CF-1.6"'
         )
 
     def test_check_convention_globals(self):
@@ -385,7 +388,7 @@ class TestCF1_6(BaseTestCase):
         assert result.value[0] != result.value[1]
         assert (
             result.msgs[0]
-            == u"§2.6.2 global attribute title should exist and be a non-empty string"
+            == "§2.6.2 global attribute title should exist and be a non-empty string"
         )
 
     def test_check_convention_possibly_var_attrs(self):
@@ -413,7 +416,7 @@ class TestCF1_6(BaseTestCase):
         assert result.value[0] != result.value[1]
         assert (
             result.msgs[0]
-            == u"§2.6.2 references global attribute should be a non-empty string"
+            == "§2.6.2 references global attribute should be a non-empty string"
         )
 
         # load bad_data_type.nc
@@ -427,8 +430,7 @@ class TestCF1_6(BaseTestCase):
 
         assert result.value[0] != result.value[1]
         assert (
-            result.msgs[0]
-            == u"§2.6.2 salinity:institution should be a non-empty string"
+            result.msgs[0] == "§2.6.2 salinity:institution should be a non-empty string"
         )
 
     def test_check_standard_name(self):
@@ -450,7 +452,7 @@ class TestCF1_6(BaseTestCase):
         # 9 vars checked, 8 fail
         assert len(results) == 9
         assert score < out_of
-        assert all(r.name == u"§3.3 Standard Name" for r in results)
+        assert all(r.name == "§3.3 Standard Name" for r in results)
 
         # load different ds --  ll vars pass this check
         dataset = self.load_dataset(STATIC_FILES["reduced_horizontal_grid"])
@@ -506,7 +508,7 @@ class TestCF1_6(BaseTestCase):
         dataset = self.load_dataset(STATIC_FILES["bad_cell_measure2"])
         results = self.cf.check_cell_measures(dataset)
         score, out_of, messages = get_results(results)
-        message = u"Cell measure variable box_area referred to by PS is not present in dataset variables"
+        message = "Cell measure variable box_area referred to by PS is not present in dataset variables"
         assert message in messages
 
     def test_climatology_cell_methods(self):
@@ -562,8 +564,10 @@ class TestCF1_6(BaseTestCase):
         temp.climatology = "clim_bounds"
         results = self.cf.check_climatological_statistics(bad_dim_ds)
         assert results[0].value[0] < results[0].value[1]
-        assert (results[0].msgs[0] == 'Climatology dimension "clim_bounds" '
-                "should only contain two elements")
+        assert (
+            results[0].msgs[0] == 'Climatology dimension "clim_bounds" '
+            "should only contain two elements"
+        )
 
     def test_check_ancillary_variables(self):
         """
@@ -573,15 +577,15 @@ class TestCF1_6(BaseTestCase):
         dataset = self.load_dataset(STATIC_FILES["rutgers"])
         results = self.cf.check_ancillary_variables(dataset)
         result_dict = {result.name: result for result in results}
-        result = result_dict[u"§3.4 Ancillary Data"]
+        result = result_dict["§3.4 Ancillary Data"]
         assert result.value == (2, 2)
 
         dataset = self.load_dataset(STATIC_FILES["bad_reference"])
         results = self.cf.check_ancillary_variables(dataset)
         result_dict = {result.name: result for result in results}
-        result = result_dict[u"§3.4 Ancillary Data"]
+        result = result_dict["§3.4 Ancillary Data"]
         assert result.value == (1, 2)
-        assert u"temp_qc is not a variable in this dataset" == result.msgs[0]
+        assert "temp_qc is not a variable in this dataset" == result.msgs[0]
 
     def test_download_standard_name_table(self):
         """
@@ -666,7 +670,7 @@ class TestCF1_6(BaseTestCase):
         results_list = list(chain(*(r.msgs for r in all_results if r.msgs)))
 
         # check the results only have '§3.1 Units' as the header
-        assert all(r.name == u"§3.1 Units" for r in all_results)
+        assert all(r.name == "§3.1 Units" for r in all_results)
 
         # check that all the expected variables have been hit
         assert all(
@@ -690,7 +694,7 @@ class TestCF1_6(BaseTestCase):
         assert len(results) == 12
         assert scored < out_of
         assert len([r for r in results if r.value[0] < r.value[1]]) == 3
-        assert (r.name == u"§4.1 Latitude Coordinate" for r in results)
+        assert (r.name == "§4.1 Latitude Coordinate" for r in results)
 
         # check with another ds -- all 6 vars checked pass
         dataset = self.load_dataset(STATIC_FILES["rotated_pole_grid"])
@@ -698,7 +702,7 @@ class TestCF1_6(BaseTestCase):
         scored, out_of, messages = get_results(results)
         assert len(results) == 6
         assert scored == out_of
-        assert (r.name == u"§4.1 Latitude Coordinate" for r in results)
+        assert (r.name == "§4.1 Latitude Coordinate" for r in results)
 
         # hack to avoid writing to read-only file
         dataset.variables["rlat"] = MockVariable(dataset.variables["rlat"])
@@ -708,7 +712,7 @@ class TestCF1_6(BaseTestCase):
         rlat.units = "degrees_north"
         results = self.cf.check_latitude(dataset)
         scored, out_of, messages = get_results(results)
-        wrong_format = u"Grid latitude variable '{}' should use degree equivalent units without east or north components. Current units are {}"
+        wrong_format = "Grid latitude variable '{}' should use degree equivalent units without east or north components. Current units are {}"
         self.assertTrue(wrong_format.format(rlat.name, rlat.units) in messages)
         rlat.units = "radians"
         results = self.cf.check_latitude(dataset)
@@ -732,7 +736,7 @@ class TestCF1_6(BaseTestCase):
         assert len(results) == 12
         assert scored < out_of
         assert len([r for r in results if r.value[0] < r.value[1]]) == 3
-        assert all(r.name == u"§4.2 Longitude Coordinate" for r in results)
+        assert all(r.name == "§4.2 Longitude Coordinate" for r in results)
 
         # check different dataset # TODO can be improved for check_latitude too
         dataset = self.load_dataset(STATIC_FILES["rotated_pole_grid"])
@@ -747,7 +751,7 @@ class TestCF1_6(BaseTestCase):
         rlon.units = "degrees_east"
         results = self.cf.check_longitude(dataset)
         scored, out_of, messages = get_results(results)
-        wrong_format = u"Grid longitude variable '{}' should use degree equivalent units without east or north components. Current units are {}"
+        wrong_format = "Grid longitude variable '{}' should use degree equivalent units without east or north components. Current units are {}"
         self.assertTrue(wrong_format.format(rlon.name, rlon.units) in messages)
         rlon.units = "radians"
         results = self.cf.check_longitude(dataset)
@@ -793,14 +797,14 @@ class TestCF1_6(BaseTestCase):
         dataset = self.load_dataset(STATIC_FILES["example-grid"])
         results = self.cf.check_dimensional_vertical_coordinate(dataset)
         assert len(results) == 1
-        assert all(r.name == u"§4.3 Vertical Coordinate" for r in results)
+        assert all(r.name == "§4.3 Vertical Coordinate" for r in results)
 
         # non-compliance -- one check fails
         dataset = self.load_dataset(STATIC_FILES["illegal-vertical"])
         results = self.cf.check_dimensional_vertical_coordinate(dataset)
         scored, out_of, messages = get_results(results)
         assert len(results) == 1
-        assert all(r.name == u"§4.3 Vertical Coordinate" for r in results)
+        assert all(r.name == "§4.3 Vertical Coordinate" for r in results)
         assert scored < out_of
 
     def test_appendix_d(self):
@@ -932,7 +936,7 @@ class TestCF1_6(BaseTestCase):
         # all variables checked (2) pass
         assert len(results) == 2
         assert scored == out_of
-        assert all(r.name == u"§4.3 Vertical Coordinate" for r in results)
+        assert all(r.name == "§4.3 Vertical Coordinate" for r in results)
 
         # Check negative compliance -- 3 out of 4 pass
 
@@ -942,7 +946,7 @@ class TestCF1_6(BaseTestCase):
         assert len(results) == 4
         assert scored <= out_of
         assert len([r for r in results if r.value[0] < r.value[1]]) == 2
-        assert all(r.name == u"§4.3 Vertical Coordinate" for r in results)
+        assert all(r.name == "§4.3 Vertical Coordinate" for r in results)
 
         # test with an invalid formula_terms
         dataset.variables["lev2"] = MockVariable(dataset.variables["lev2"])
@@ -957,7 +961,7 @@ class TestCF1_6(BaseTestCase):
         assert len(results) == 4
         assert scored <= out_of
         assert len([r for r in results if r.value[0] < r.value[1]]) == 2
-        assert all(r.name == u"§4.3 Vertical Coordinate" for r in results)
+        assert all(r.name == "§4.3 Vertical Coordinate" for r in results)
 
     def test_is_time_variable(self):
         var1 = MockVariable()
@@ -1010,7 +1014,7 @@ class TestCF1_6(BaseTestCase):
 
         scored, out_of, messages = get_results(results)
 
-        assert u"time does not have correct time units" in messages
+        assert "time does not have correct time units" in messages
         assert (scored, out_of) == (1, 2)
 
     def test_check_calendar(self):
@@ -1027,7 +1031,7 @@ class TestCF1_6(BaseTestCase):
         scored, out_of, messages = get_results(results)
 
         assert (
-            u"§4.4.1 Variable time should have a valid calendar: 'nope' is not a valid calendar"
+            "§4.4.1 Variable time should have a valid calendar: 'nope' is not a valid calendar"
             in messages
         )
 
@@ -1035,7 +1039,7 @@ class TestCF1_6(BaseTestCase):
         dataset = self.load_dataset(STATIC_FILES["illegal-aux-coords"])
         results = self.cf.check_aux_coordinates(dataset)
         result_dict = {result.name: result for result in results}
-        result = result_dict[u"§5 Coordinate Systems"]
+        result = result_dict["§5 Coordinate Systems"]
         assert result.msgs == []  # shouldn't have any messages
         assert result.value == (4, 4)
 
@@ -1046,7 +1050,7 @@ class TestCF1_6(BaseTestCase):
 
         result_dict = {result.name: result for result in results}
         result = result_dict[
-            u"§5.6 Horizontal Coordinate Reference Systems, Grid Mappings, Projections"
+            "§5.6 Horizontal Coordinate Reference Systems, Grid Mappings, Projections"
         ]
         assert result.value == (2, 2)
         assert (scored, out_of) == (2, 2)
@@ -1066,7 +1070,7 @@ class TestCF1_6(BaseTestCase):
         assert scored < out_of
         assert all(
             r.name
-            == u"§5.6 Horizontal Coordinate Reference Systems, Grid Mappings, Projections"
+            == "§5.6 Horizontal Coordinate Reference Systems, Grid Mappings, Projections"
             for r in results
         )
 
@@ -1076,7 +1080,7 @@ class TestCF1_6(BaseTestCase):
         scored, out_of, messages = get_results(results)
         assert scored == out_of
         assert len(results) == 1
-        assert all(r.name == u"§5.3 Reduced Horizontal Grid" for r in results)
+        assert all(r.name == "§5.3 Reduced Horizontal Grid" for r in results)
 
         # load failing ds -- one variable has failing check
         dataset = self.load_dataset(STATIC_FILES["bad-rhgrid"])
@@ -1085,7 +1089,7 @@ class TestCF1_6(BaseTestCase):
         assert scored != out_of
         assert len(results) == 2
         assert len([r for r in results if r.value[0] < r.value[1]]) == 1
-        assert all(r.name == u"§5.3 Reduced Horizontal Grid" for r in results)
+        assert all(r.name == "§5.3 Reduced Horizontal Grid" for r in results)
 
     def test_check_grid_mapping(self):
         dataset = self.load_dataset(STATIC_FILES["mapping"])
@@ -1099,7 +1103,6 @@ class TestCF1_6(BaseTestCase):
         assert all(r.name == expected_name for r in results.values())
 
     def test_is_geophysical(self):
-
         # check whether string type variable, which are not `cf_role`, are
         # properly processed
         dataset = self.load_dataset(STATIC_FILES["string"])
@@ -1233,7 +1236,7 @@ class TestCF1_6(BaseTestCase):
         assert len(results) == 2
         assert scored < out_of
         assert (
-            u"6.1.1 'Neverland' specified by 'neverland' is not a valid region"
+            "6.1.1 'Neverland' specified by 'neverland' is not a valid region"
             in messages
         )
 
@@ -1243,10 +1246,10 @@ class TestCF1_6(BaseTestCase):
         score, out_of, messages = get_results(results)
 
         msgs = [
-            u"Type of tempvalid_min attribute (int32) does not match variable type (int64)",
-            u"Type of temp:valid_max attribute (int32) does not match variable type (int64)",
-            u"Type of salinityvalid_min attribute (int32) does not match variable type (float64)",
-            u"Type of salinity:valid_max attribute (int32) does not match variable type (float64)",
+            "Type of tempvalid_min attribute (int32) does not match variable type (int64)",
+            "Type of temp:valid_max attribute (int32) does not match variable type (int64)",
+            "Type of salinityvalid_min attribute (int32) does not match variable type (float64)",
+            "Type of salinity:valid_max attribute (int32) does not match variable type (float64)",
         ]
 
         self.assertEqual(len(results), 4)
@@ -1328,7 +1331,7 @@ class TestCF1_6(BaseTestCase):
 
         # only one check run here, so we can directly compare all the values
         assert scored != out_of
-        assert messages[0] == u"'temp' has duplicate axis X defined by [lon_rho, lon_u]"
+        assert messages[0] == "'temp' has duplicate axis X defined by [lon_rho, lon_u]"
 
     def test_check_multi_dimensional_coords(self):
         """
@@ -1342,7 +1345,7 @@ class TestCF1_6(BaseTestCase):
         # 4 variables were checked in this ds, 2 of which passed
         assert len(results) == 4
         assert len([r for r in results if r.value[0] < r.value[1]]) == 2
-        assert all(r.name == u"§5 Coordinate Systems" for r in results)
+        assert all(r.name == "§5 Coordinate Systems" for r in results)
 
     def test_64bit(self):
         dataset = self.load_dataset(STATIC_FILES["ints64"])
@@ -1351,7 +1354,6 @@ class TestCF1_6(BaseTestCase):
         suite.run(dataset, "cf")
 
     def test_variable_feature_check(self):
-
         # non-compliant dataset -- 1/1 fail
         dataset = self.load_dataset(STATIC_FILES["bad-trajectory"])
         results = self.cf.check_variable_features(dataset)
@@ -1359,7 +1361,7 @@ class TestCF1_6(BaseTestCase):
         assert len(results) == 2
         assert scored < out_of
         assert len([r for r in results if r.value[0] < r.value[1]]) == 1
-        assert all(r.name == u"§9.1 Features and feature types" for r in results)
+        assert all(r.name == "§9.1 Features and feature types" for r in results)
 
         # compliant dataset
         dataset = self.load_dataset(STATIC_FILES["trajectory-complete"])
@@ -1388,7 +1390,7 @@ class TestCF1_6(BaseTestCase):
 
         # check the results only have expected headers
         assert set([r.name for r in results]).issubset(
-            set([u"§7.1 Cell Boundaries", u"§7.3 Cell Methods"])
+            set(["§7.1 Cell Boundaries", "§7.3 Cell Methods"])
         )
 
         # check that all the expected variables have been hit
@@ -1420,7 +1422,7 @@ class TestCF1_6(BaseTestCase):
         scored, out_of, messages = get_results(results)
 
         self.assertTrue(
-            u'§7.3.3 The non-standard "comment:" element must come after any standard elements in cell_methods for variable temperature'
+            '§7.3.3 The non-standard "comment:" element must come after any standard elements in cell_methods for variable temperature'
             in messages
         )
 
@@ -1437,7 +1439,7 @@ class TestCF1_6(BaseTestCase):
         results = self.cf.check_cell_methods(nc_obj)
         scored, out_of, messages = get_results(results)
         self.assertTrue(
-            u'§7.3.3 Invalid cell_methods keyword "invalid_keyword:" for variable temperature. Must be one of [interval, comment]'
+            '§7.3.3 Invalid cell_methods keyword "invalid_keyword:" for variable temperature. Must be one of [interval, comment]'
             in messages
         )
 
@@ -1448,7 +1450,7 @@ class TestCF1_6(BaseTestCase):
         results = self.cf.check_cell_methods(nc_obj)
         scored, out_of, messages = get_results(results)
         assert (
-            u"§7.3.3 Parenthetical content inside temperature:cell_methods is not well formed: interval 0.2 m interval: 0.01 degrees"
+            "§7.3.3 Parenthetical content inside temperature:cell_methods is not well formed: interval 0.2 m interval: 0.01 degrees"
             in messages
         )
 
@@ -1497,7 +1499,7 @@ class TestCF1_7(BaseTestCase):
         score, out_of, messages = get_results(result)
         assert score < out_of
         assert len(messages) == 1
-        assert messages[0] == u"actual_range of 'a' must be 2 elements"
+        assert messages[0] == "actual_range of 'a' must be 2 elements"
         dataset.close()
 
         dataset = MockTimeSeries()
@@ -1685,7 +1687,7 @@ class TestCF1_7(BaseTestCase):
         dataset = self.load_dataset(STATIC_FILES["bad_cell_measure2"])
         results = self.cf.check_cell_measures(dataset)
         score, out_of, messages = get_results(results)
-        message = u"Cell measure variable box_area referred to by PS is not present in dataset variables"
+        message = "Cell measure variable box_area referred to by PS is not present in dataset variables"
         assert message in messages
 
     def test_variable_features(self):
@@ -1976,7 +1978,7 @@ class TestCF1_7(BaseTestCase):
         # all variables checked (2) pass
         assert len(results) == 3
         assert scored == out_of
-        assert all(r.name == u"§4.3 Vertical Coordinate" for r in results)
+        assert all(r.name == "§4.3 Vertical Coordinate" for r in results)
 
         # make one variable's computed_standard_name incorrect, one should fail
         dataset.variables["lev"].computed_standard_name = "definitely_not_right"
@@ -1985,7 +1987,7 @@ class TestCF1_7(BaseTestCase):
 
         assert len(results) == 3
         assert scored < out_of
-        assert all(r.name == u"§4.3 Vertical Coordinate" for r in results)
+        assert all(r.name == "§4.3 Vertical Coordinate" for r in results)
 
     def test_check_attr_type(self):
         """
@@ -2018,7 +2020,7 @@ class TestCF1_7(BaseTestCase):
         attr_type = "N"  # should be numeric
         self.assertFalse(self.cf._check_attr_type(att_name, attr_type, attr)[0])
 
-        attr = np.int(64)
+        attr = int(64)
         attr_type = "S"  # should be string
         self.assertFalse(self.cf._check_attr_type(att_name, attr_type, attr)[0])
 
@@ -2174,7 +2176,6 @@ class TestCF1_7(BaseTestCase):
         dataset.close()
 
     def test_check_gmattr_existence_condition_ell_pmerid_hdatum(self):
-
         # test good (all)
         dataset = MockTimeSeries()
         dataset.createVariable("lev", "d")  # dtype=double, dims=1
@@ -2237,7 +2238,7 @@ class TestCF1_7(BaseTestCase):
         self.assertTrue(r[0].msgs)
 
         # set good
-        temp.setncattr("scale_factor", np.float(5))
+        temp.setncattr("scale_factor", float(5))
         r = self.cf.check_add_offset_scale_factor_type(dataset)
         self.assertTrue(r[0].value)
         self.assertFalse(r[0].msgs)
@@ -2249,8 +2250,8 @@ class TestCF1_7(BaseTestCase):
 
         # set same dtype
         dataset = MockTimeSeries()  # time lat lon depth
-        temp = dataset.createVariable("temp", np.int, dimensions=("time",))
-        temp.setncattr("scale_factor", np.int(5))
+        temp = dataset.createVariable("temp", int, dimensions=("time",))
+        temp.setncattr("scale_factor", int(5))
         r = self.cf.check_add_offset_scale_factor_type(dataset)
         self.assertTrue(r[0].value)
         self.assertFalse(r[0].msgs)
@@ -2569,7 +2570,6 @@ class TestCFUtil(BaseTestCase):
         )
 
     def test_is_dataset_valid_ragged_array_repr_featureType(self):
-
         # first test single featureType
 
         # ----- timeseries, indexed ----- #