Skip to content

Commit

Permalink
Remove uses of logging.warn (#5488)
Browse files Browse the repository at this point in the history
* Align UGRID CF warnings with other CF warnings.

* Replace remaining uses of logging warnings.

* Assert for UserWarnings

* Better test variable names.

* What's New entry.

---------

Co-authored-by: Henry Wright <84939917+HGWright@users.noreply.github.com>
  • Loading branch information
trexfeathers and HGWright committed Sep 14, 2023
1 parent 8b336e9 commit c53481e
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 115 deletions.
4 changes: 4 additions & 0 deletions docs/src/whatsnew/latest.rst
Expand Up @@ -79,10 +79,14 @@ This document explains the changes made to Iris for this release
working properly. (Main pull request: :pull:`5437`, more detail:
:pull:`5430`, :pull:`5431`, :pull:`5432`, :pull:`5434`, :pull:`5436`)

#. `@trexfeathers`_ replaced all uses of the ``logging.WARNING`` level, in
favour of using Python warnings, following team agreement. (:pull:`5488`)

#. `@trexfeathers`_ adapted benchmarking to work with ASV ``>=v0.6`` by no
longer using the ``--strict`` argument. (:pull:`5496`)



.. comment
Whatsnew author names (@github name) in alphabetical order. Note that,
core dev names are automatically included by the common_links.inc:
Expand Down
54 changes: 13 additions & 41 deletions lib/iris/experimental/ugrid/cf.py
Expand Up @@ -10,15 +10,11 @@
Eventual destination: :mod:`iris.fileformats.cf`.
"""
import logging
import warnings

from ...config import get_logger
from ...fileformats import cf
from .mesh import Connectivity

# Configure the logger.
logger = get_logger(__name__, propagate=True, handler=False)


class CFUGridConnectivityVariable(cf.CFVariable):
"""
Expand Down Expand Up @@ -50,8 +46,6 @@ class CFUGridConnectivityVariable(cf.CFVariable):
def identify(cls, variables, ignore=None, target=None, warn=True):
result = {}
ignore, target = cls._identify_common(variables, ignore, target)
# TODO: reconsider logging level when we have consistent practice.
log_level = logging.WARNING if warn else logging.DEBUG

# Identify all CF-UGRID connectivity variables.
for nc_var_name, nc_var in target.items():
Expand All @@ -70,11 +64,8 @@ def identify(cls, variables, ignore=None, target=None, warn=True):
f"{name}, referenced by netCDF variable "
f"{nc_var_name}"
)
logger.log(
level=log_level,
msg=message,
extra=dict(cls=cls.__name__),
)
if warn:
warnings.warn(message)
else:
# Restrict to non-string type i.e. not a
# CFLabelVariable.
Expand All @@ -88,11 +79,8 @@ def identify(cls, variables, ignore=None, target=None, warn=True):
f"as a CF-UGRID connectivity - is a "
f"CF-netCDF label variable."
)
logger.log(
level=log_level,
msg=message,
extra=dict(cls=cls.__name__),
)
if warn:
warnings.warn(message)

return result

Expand Down Expand Up @@ -131,8 +119,6 @@ class CFUGridAuxiliaryCoordinateVariable(cf.CFVariable):
def identify(cls, variables, ignore=None, target=None, warn=True):
result = {}
ignore, target = cls._identify_common(variables, ignore, target)
# TODO: reconsider logging level when we have consistent practice.
log_level = logging.WARNING if warn else logging.DEBUG

# Identify any CF-UGRID-relevant auxiliary coordinate variables.
for nc_var_name, nc_var in target.items():
Expand All @@ -149,11 +135,8 @@ def identify(cls, variables, ignore=None, target=None, warn=True):
f"variable {name}, referenced by netCDF "
f"variable {nc_var_name}"
)
logger.log(
level=log_level,
msg=message,
extra=dict(cls=cls.__name__),
)
if warn:
warnings.warn(message)
else:
# Restrict to non-string type i.e. not a
# CFLabelVariable.
Expand All @@ -170,11 +153,8 @@ def identify(cls, variables, ignore=None, target=None, warn=True):
f"auxiliary coordinate - is a "
f"CF-netCDF label variable."
)
logger.log(
level=log_level,
msg=message,
extra=dict(cls=cls.__name__),
)
if warn:
warnings.warn(message)

return result

Expand Down Expand Up @@ -205,8 +185,6 @@ class CFUGridMeshVariable(cf.CFVariable):
def identify(cls, variables, ignore=None, target=None, warn=True):
result = {}
ignore, target = cls._identify_common(variables, ignore, target)
# TODO: reconsider logging level when we have consistent practice.
log_level = logging.WARNING if warn else logging.DEBUG

# Identify all CF-UGRID mesh variables.
all_vars = target == variables
Expand All @@ -232,11 +210,8 @@ def identify(cls, variables, ignore=None, target=None, warn=True):
f"Missing CF-UGRID mesh variable {name}, "
f"referenced by netCDF variable {nc_var_name}"
)
logger.log(
level=log_level,
msg=message,
extra=dict(cls=cls.__name__),
)
if warn:
warnings.warn(message)
else:
# Restrict to non-string type i.e. not a
# CFLabelVariable.
Expand All @@ -250,11 +225,8 @@ def identify(cls, variables, ignore=None, target=None, warn=True):
f"CF-UGRID mesh - is a CF-netCDF label "
f"variable."
)
logger.log(
level=log_level,
msg=message,
extra=dict(cls=cls.__name__),
)
if warn:
warnings.warn(message)

return result

Expand Down
10 changes: 4 additions & 6 deletions lib/iris/experimental/ugrid/load.py
Expand Up @@ -15,6 +15,7 @@
from itertools import groupby
from pathlib import Path
import threading
import warnings

from ...config import get_logger
from ...coords import AuxCoord
Expand Down Expand Up @@ -350,8 +351,7 @@ def _build_mesh(cf, mesh_var, file_path):
)
if cf_role_message:
cf_role_message += " Correcting to 'mesh_topology'."
# TODO: reconsider logging level when we have consistent practice.
logger.warning(cf_role_message, extra=dict(cls=None))
warnings.warn(cf_role_message)

if hasattr(mesh_var, "volume_node_connectivity"):
topology_dimension = 3
Expand All @@ -369,8 +369,7 @@ def _build_mesh(cf, mesh_var, file_path):
f" : *Assuming* topology_dimension={topology_dimension}"
", consistent with the attached connectivities."
)
# TODO: reconsider logging level when we have consistent practice.
logger.warning(msg, extra=dict(cls=None))
warnings.warn(msg)
else:
quoted_topology_dimension = mesh_var.topology_dimension
if quoted_topology_dimension != topology_dimension:
Expand All @@ -382,8 +381,7 @@ def _build_mesh(cf, mesh_var, file_path):
f"{quoted_topology_dimension}"
" -- ignoring this as it is inconsistent."
)
# TODO: reconsider logging level when we have consistent practice.
logger.warning(msg=msg, extra=dict(cls=None))
warnings.warn(msg)

node_dimension = None
edge_dimension = getattr(mesh_var, "edge_dimension", None)
Expand Down
19 changes: 10 additions & 9 deletions lib/iris/tests/integration/experimental/test_ugrid_load.py
Expand Up @@ -16,8 +16,9 @@

from collections.abc import Iterable

import pytest

from iris import Constraint, load
from iris.experimental.ugrid import logger
from iris.experimental.ugrid.load import (
PARSE_UGRID_ON_LOAD,
load_mesh,
Expand Down Expand Up @@ -168,8 +169,8 @@ def create_synthetic_file(self, **create_kwargs):

def test_mesh_bad_topology_dimension(self):
# Check that the load generates a suitable warning.
log_regex = r"topology_dimension.* ignoring"
with self.assertLogs(logger, level="WARNING", msg_regex=log_regex):
warn_regex = r"topology_dimension.* ignoring"
with pytest.warns(UserWarning, match=warn_regex):
template = "minimal_bad_topology_dim"
dim_line = "mesh_var:topology_dimension = 1 ;" # which is wrong !
cube = self.create_synthetic_test_cube(
Expand All @@ -181,8 +182,8 @@ def test_mesh_bad_topology_dimension(self):

def test_mesh_no_topology_dimension(self):
# Check that the load generates a suitable warning.
log_regex = r"Mesh variable.* has no 'topology_dimension'"
with self.assertLogs(logger, level="WARNING", msg_regex=log_regex):
warn_regex = r"Mesh variable.* has no 'topology_dimension'"
with pytest.warns(UserWarning, match=warn_regex):
template = "minimal_bad_topology_dim"
dim_line = "" # don't create ANY topology_dimension property
cube = self.create_synthetic_test_cube(
Expand All @@ -194,8 +195,8 @@ def test_mesh_no_topology_dimension(self):

def test_mesh_bad_cf_role(self):
# Check that the load generates a suitable warning.
log_regex = r"inappropriate cf_role"
with self.assertLogs(logger, level="WARNING", msg_regex=log_regex):
warn_regex = r"inappropriate cf_role"
with pytest.warns(UserWarning, match=warn_regex):
template = "minimal_bad_mesh_cf_role"
dim_line = 'mesh_var:cf_role = "foo" ;'
_ = self.create_synthetic_test_cube(
Expand All @@ -204,8 +205,8 @@ def test_mesh_bad_cf_role(self):

def test_mesh_no_cf_role(self):
# Check that the load generates a suitable warning.
log_regex = r"no cf_role attribute"
with self.assertLogs(logger, level="WARNING", msg_regex=log_regex):
warn_regex = r"no cf_role attribute"
with pytest.warns(UserWarning, match=warn_regex):
template = "minimal_bad_mesh_cf_role"
dim_line = ""
_ = self.create_synthetic_test_cube(
Expand Down
Expand Up @@ -14,12 +14,13 @@
# importing anything else.
import iris.tests as tests # isort:skip

import re
import warnings

import numpy as np
import pytest

from iris.experimental.ugrid.cf import (
CFUGridAuxiliaryCoordinateVariable,
logger,
)
from iris.experimental.ugrid.cf import CFUGridAuxiliaryCoordinateVariable
from iris.tests.unit.experimental.ugrid.cf.test_CFUGridReader import (
netcdf_ugrid_variable,
)
Expand Down Expand Up @@ -213,26 +214,30 @@ def test_warn(self):
"ref_source": ref_source,
}

# The warn kwarg and expected corresponding log level.
warn_and_level = {True: "WARNING", False: "DEBUG"}
def operation(warn: bool):
warnings.warn("emit at least 1 warning")
result = CFUGridAuxiliaryCoordinateVariable.identify(
vars_all, warn=warn
)
self.assertDictEqual({}, result)

# Missing warning.
log_regex = rf"Missing CF-netCDF auxiliary coordinate variable {subject_name}.*"
for warn, level in warn_and_level.items():
with self.assertLogs(logger, level=level, msg_regex=log_regex):
result = CFUGridAuxiliaryCoordinateVariable.identify(
vars_all, warn=warn
)
self.assertDictEqual({}, result)
warn_regex = rf"Missing CF-netCDF auxiliary coordinate variable {subject_name}.*"
with pytest.warns(UserWarning, match=warn_regex):
operation(warn=True)
with pytest.warns() as record:
operation(warn=False)
warn_list = [str(w.message) for w in record]
assert list(filter(re.compile(warn_regex).match, warn_list)) == []

# String variable warning.
log_regex = r".*is a CF-netCDF label variable.*"
for warn, level in warn_and_level.items():
with self.assertLogs(logger, level=level, msg_regex=log_regex):
vars_all[subject_name] = netcdf_ugrid_variable(
subject_name, "", np.bytes_
)
result = CFUGridAuxiliaryCoordinateVariable.identify(
vars_all, warn=warn
)
self.assertDictEqual({}, result)
warn_regex = r".*is a CF-netCDF label variable.*"
vars_all[subject_name] = netcdf_ugrid_variable(
subject_name, "", np.bytes_
)
with pytest.warns(UserWarning, match=warn_regex):
operation(warn=True)
with pytest.warns() as record:
operation(warn=False)
warn_list = [str(w.message) for w in record]
assert list(filter(re.compile(warn_regex).match, warn_list)) == []
Expand Up @@ -14,9 +14,13 @@
# importing anything else.
import iris.tests as tests # isort:skip

import re
import warnings

import numpy as np
import pytest

from iris.experimental.ugrid.cf import CFUGridConnectivityVariable, logger
from iris.experimental.ugrid.cf import CFUGridConnectivityVariable
from iris.experimental.ugrid.mesh import Connectivity
from iris.tests.unit.experimental.ugrid.cf.test_CFUGridReader import (
netcdf_ugrid_variable,
Expand Down Expand Up @@ -199,26 +203,30 @@ def test_warn(self):
"ref_source": ref_source,
}

# The warn kwarg and expected corresponding log level.
warn_and_level = {True: "WARNING", False: "DEBUG"}
def operation(warn: bool):
warnings.warn("emit at least 1 warning")
result = CFUGridConnectivityVariable.identify(vars_all, warn=warn)
self.assertDictEqual({}, result)

# Missing warning.
log_regex = rf"Missing CF-UGRID connectivity variable {subject_name}.*"
for warn, level in warn_and_level.items():
with self.assertLogs(logger, level=level, msg_regex=log_regex):
result = CFUGridConnectivityVariable.identify(
vars_all, warn=warn
)
self.assertDictEqual({}, result)
warn_regex = (
rf"Missing CF-UGRID connectivity variable {subject_name}.*"
)
with pytest.warns(UserWarning, match=warn_regex):
operation(warn=True)
with pytest.warns() as record:
operation(warn=False)
warn_list = [str(w.message) for w in record]
assert list(filter(re.compile(warn_regex).match, warn_list)) == []

# String variable warning.
log_regex = r".*is a CF-netCDF label variable.*"
for warn, level in warn_and_level.items():
with self.assertLogs(logger, level=level, msg_regex=log_regex):
vars_all[subject_name] = netcdf_ugrid_variable(
subject_name, "", np.bytes_
)
result = CFUGridConnectivityVariable.identify(
vars_all, warn=warn
)
self.assertDictEqual({}, result)
warn_regex = r".*is a CF-netCDF label variable.*"
vars_all[subject_name] = netcdf_ugrid_variable(
subject_name, "", np.bytes_
)
with pytest.warns(UserWarning, match=warn_regex):
operation(warn=True)
with pytest.warns() as record:
operation(warn=False)
warn_list = [str(w.message) for w in record]
assert list(filter(re.compile(warn_regex).match, warn_list)) == []

0 comments on commit c53481e

Please sign in to comment.