From fe4eccaba8aed11d752c53928923faea0f56ba7c Mon Sep 17 00:00:00 2001 From: Martin Yeo Date: Wed, 20 Sep 2023 18:04:29 +0100 Subject: [PATCH 1/5] Docs page on filtering warnings. --- .../src/further_topics/filtering_warnings.rst | 268 ++++++++++++++++++ docs/src/userguide/index.rst | 1 + 2 files changed, 269 insertions(+) create mode 100644 docs/src/further_topics/filtering_warnings.rst diff --git a/docs/src/further_topics/filtering_warnings.rst b/docs/src/further_topics/filtering_warnings.rst new file mode 100644 index 0000000000..6fae37b8c5 --- /dev/null +++ b/docs/src/further_topics/filtering_warnings.rst @@ -0,0 +1,268 @@ +.. _filtering-warnings: + +================== +Filtering Warnings +================== + +Since Iris cannot predict your specific needs, it by default raises Warnings +for anything that might be a problem for **any** user, and is designed to work with +you to ``ignore`` Warnings which you do not find helpful. + +.. testsetup:: filtering_warnings + + import sys + import warnings + + import iris.coord_systems + import iris.exceptions + + # Make sure doctests actually see Warnings that are raised. + warnings.filterwarnings("default") + sys.stderr = sys.stdout + + geog_cs_globe = iris.coord_systems.GeogCS(6400000) + orthographic_coord_system = iris.coord_systems.Orthographic( + longitude_of_projection_origin=0, + latitude_of_projection_origin=0, + ellipsoid=geog_cs_globe, + ) + + + def my_operation(): + geog_cs_globe.inverse_flattening = 0.1 + _ = orthographic_coord_system.as_cartopy_crs() + +Here is a hypothetical operation - ``my_operation()`` - which raises two +Warnings: + +.. doctest:: filtering_warnings + + >>> my_operation() + ... + /net/home/h01/myeo/repos/iris/lib/iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) + /net/home/h01/myeo/repos/iris/lib/iris/coord_systems.py:821: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. + warnings.warn( + +Warnings can be suppressed using the Python warnings filter with the ``ignore`` +action. Detailed information is available in the Python documentation: +:external+python:mod:`warnings`. + +The key points are: + +- :ref:`When`: a warnings filter can be applied + either from the command line or from within Python. +- :ref:`What`: a warnings filter accepts + various arguments to specify which Warnings are being filtered. Both broad + and narrow filters are possible. + +.. _warning-filter-application: + +**When** a Warnings Filter can be Applied +----------------------------------------- + +- **Command line:** setting the :external+python:envvar:`PYTHONWARNINGS` + environment variable. +- **Command line:** the `python -W `_ + command line argument. +- **Within Python:** use :func:`warnings.filterwarnings` . + +The :ref:`warning-filter-specificity` section demonstrates using +:func:`warnings.filterwarnings`, and shows the equivalent **command line** +approaches. + + +.. _warning-filter-specificity: + +**What** Warnings will be Filtered +---------------------------------- + +.. note:: + + For all of these examples we are using the + :class:`~warnings.catch_warnings` context manager to ensure any changes to + settings are temporary. + + This should always work fine for the ``ignore`` + warning filter action, but note that some of the other actions + may not behave correctly with all Iris operations, as + :class:`~warnings.catch_warnings` is not thread-safe (e.g. using the + ``once`` action may cause 1 warning per chunk of lazy data). + +Specific Warnings +~~~~~~~~~~~~~~~~~ + +**When you do not want a specific warning, but still want all others.** + +You can target specific Warning messages, e.g. + +.. doctest:: filtering_warnings + + >>> with warnings.catch_warnings(): + ... warnings.filterwarnings("ignore", message="Discarding false_easting") + ... my_operation() + ... + /net/home/h01/myeo/repos/iris/lib/iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) + +:: + + python -W ignore:"Discarding false_easting" + export PYTHONWARNINGS=ignore:"Discarding false_easting" + +---- + +Or you can target Warnings raised by specific lines of specific modules, e.g. + +.. doctest:: filtering_warnings + + >>> with warnings.catch_warnings(): + ... warnings.filterwarnings("ignore", module="iris.coord_systems", lineno=454) + ... my_operation() + ... + /net/home/h01/myeo/repos/iris/lib/iris/coord_systems.py:821: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. + warnings.warn( + +:: + + python -W ignore:::iris.coord_systems:454 + export PYTHONWARNINGS=ignore:::iris.coord_systems:454 + + +Warnings from a Common Source +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**When you do not want ANY warnings raised by a module, or collection of +modules.** + +E.g. filtering the ``coord_systems`` module: + +.. doctest:: filtering_warnings + + >>> with warnings.catch_warnings(): + ... warnings.filterwarnings("ignore", module="iris.coord_systems") + ... my_operation() + +:: + + python -W ignore:::iris.coord_systems + export PYTHONWARNINGS=ignore:::iris.coord_systems + +---- + +It also works to ``ignore`` all warnings from ``iris`` as a whole: + +.. doctest:: filtering_warnings + + >>> with warnings.catch_warnings(): + ... warnings.filterwarnings("ignore", module="iris") + ... my_operation() + +:: + + python -W ignore:::iris + export PYTHONWARNINGS=ignore:::iris + +Warnings of a Common Type +~~~~~~~~~~~~~~~~~~~~~~~~~ + +**When you do not want any Warnings of the same nature, from anywhere in the +code you are calling.** + +The below example will ``ignore`` any +:class:`~iris.exceptions.IrisDefaultingWarning` that gets raised by *any* +module during execution: + +.. doctest:: filtering_warnings + + >>> with warnings.catch_warnings(): + ... warnings.filterwarnings( + ... "ignore", + ... category=iris.exceptions.IrisDefaultingWarning + ... ) + ... my_operation() + ... + /net/home/h01/myeo/repos/iris/lib/iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) + +:: + + export PYTHONWARNINGS=ignore::iris.exceptions.IrisDefaultingWarning + +This example is not possible using ``python -W`` on the command line, which +can only handle the built-in Warning categories +(`cpython#66733`_). + +---- + +Using :class:`~iris.exceptions.IrisUserWarning` in the filter will ``ignore`` +both Warnings, since :class:`~iris.exceptions.IrisDefaultingWarning` subclasses +:class:`~iris.exceptions.IrisUserWarning` : + +.. doctest:: filtering_warnings + + >>> with warnings.catch_warnings(): + ... warnings.filterwarnings( + ... "ignore", + ... category=iris.exceptions.IrisUserWarning + ... ) + ... my_operation() + +:: + + export PYTHONWARNINGS=ignore::iris.exceptions.IrisUserWarning + +This example is not possible using ``python -W`` on the command line, which +can only handle the built-in Warning categories +(`cpython#66733`_). + +---- + +There are several built-in Python warning categories that can be used here +(:class:`DeprecationWarning` being a popular example, see +:external+python:mod:`warnings` for more). Since Iris has +so many different warnings that might be raised, Iris subclasses +:class:`UserWarning` to :class:`~iris.exceptions.IrisUserWarning`, which itself +has **many** specialised subclasses. These subclasses exist to give you more +granularity in your warning filtering; you can see the full list by +searching the :mod:`iris.exceptions` page for ``warning`` . + +.. attention:: + + If you have ideas for adding/altering Iris' warning categories, please + :ref:`get in touch`! The categories exist to + make your life easier, and it is simple to make modifications. + + +More Detail +----------- + +Different people use Iris for very different purposes, from quick file +visualisation to extract-transform-load to statistical analysis. These +contrasting priorities mean disagreement on which Iris problems can be ignored +and which are critically important. + +For problems that prevent Iris functioning: **Concrete Exceptions** are raised, which +stop code from running any further - no debate here. For less catastrophic +problems: **Warnings** are raised, +which notify you (in ``stderr``) but allow code to continue running. The Warnings are +there because Iris may **OR may not** function in the way you expect, +depending on what you need - e.g. a problem might prevent data being saved to +NetCDF, but statistical analysis will still work fine. + +Examples of Iris Warnings +~~~~~~~~~~~~~~~~~~~~~~~~~ + +- If you attempt to plot un-bounded point data as a ``pcolormesh``: Iris will + guess appropriate bounds around each point so that quadrilaterals can be + plotted. This permanently modifies the relevant coordinates, so the you are + warned in case downstream operations assume un-bounded coordinates. +- If you load a NetCDF file where a CF variable references another variable - + e.g. ``my_var:coordinates = "depth_var" ;`` - but the referenced variable + (``depth_var``) is not in the file: Iris will still construct + its data model, but without this reference relationship. You are warned since + the file includes an error and the loaded result might therefore not be as + expected. + + +.. _cpython#66733: https://github.com/python/cpython/issues/66733 diff --git a/docs/src/userguide/index.rst b/docs/src/userguide/index.rst index 771aa450a3..c87323da8e 100644 --- a/docs/src/userguide/index.rst +++ b/docs/src/userguide/index.rst @@ -42,6 +42,7 @@ they may serve as a useful reference for future exploration. :maxdepth: 2 :caption: Further Topics + ../further_topics/filtering_warnings ../further_topics/metadata ../further_topics/lenient_metadata ../further_topics/lenient_maths From 64240f15859a326a42cd0f924afb01f5deacefb9 Mon Sep 17 00:00:00 2001 From: Martin Yeo Date: Thu, 21 Sep 2023 18:11:11 +0100 Subject: [PATCH 2/5] What's New entry. --- docs/src/whatsnew/latest.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index 4c732c43df..8cf829e1c3 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -72,7 +72,8 @@ This document explains the changes made to Iris for this release 📚 Documentation ================ -#. N/A +#. `@trexfeathers`_ documented the intended use of warnings filtering with + Iris. See :ref:`filtering-warnings`. (:pull:`5509`) 💼 Internal From 39cb4e11a5a822eb7333edcb6346164e21123dd0 Mon Sep 17 00:00:00 2001 From: Martin Yeo Date: Thu, 21 Sep 2023 18:42:04 +0100 Subject: [PATCH 3/5] Warnings doctest relative path. --- .../src/further_topics/filtering_warnings.rst | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/docs/src/further_topics/filtering_warnings.rst b/docs/src/further_topics/filtering_warnings.rst index 6fae37b8c5..c7672eb5d5 100644 --- a/docs/src/further_topics/filtering_warnings.rst +++ b/docs/src/further_topics/filtering_warnings.rst @@ -10,15 +10,23 @@ you to ``ignore`` Warnings which you do not find helpful. .. testsetup:: filtering_warnings + from pathlib import Path import sys import warnings + import iris import iris.coord_systems import iris.exceptions - # Make sure doctests actually see Warnings that are raised. + # Hack to ensure doctests actually see Warnings that are raised, and that + # they have a relative path (so a test pass is not machine-dependent). warnings.filterwarnings("default") - sys.stderr = sys.stdout + IRIS_FILE = Path(iris.__file__) + def custom_warn(message, category, filename, lineno, file=None, line=None): + filepath = Path(filename) + filename = str(filepath.relative_to(IRIS_FILE.parents[1])) + sys.stdout.write(warnings.formatwarning(message, category, filename, lineno)) + warnings.showwarning = custom_warn geog_cs_globe = iris.coord_systems.GeogCS(6400000) orthographic_coord_system = iris.coord_systems.Orthographic( @@ -39,9 +47,9 @@ Warnings: >>> my_operation() ... - /net/home/h01/myeo/repos/iris/lib/iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) - /net/home/h01/myeo/repos/iris/lib/iris/coord_systems.py:821: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. + iris/coord_systems.py:821: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. warnings.warn( Warnings can be suppressed using the Python warnings filter with the ``ignore`` @@ -102,7 +110,7 @@ You can target specific Warning messages, e.g. ... warnings.filterwarnings("ignore", message="Discarding false_easting") ... my_operation() ... - /net/home/h01/myeo/repos/iris/lib/iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) :: @@ -120,7 +128,7 @@ Or you can target Warnings raised by specific lines of specific modules, e.g. ... warnings.filterwarnings("ignore", module="iris.coord_systems", lineno=454) ... my_operation() ... - /net/home/h01/myeo/repos/iris/lib/iris/coord_systems.py:821: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. + iris/coord_systems.py:821: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy. warnings.warn( :: @@ -182,7 +190,7 @@ module during execution: ... ) ... my_operation() ... - /net/home/h01/myeo/repos/iris/lib/iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. + iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) :: @@ -265,4 +273,9 @@ Examples of Iris Warnings expected. +.. testcleanup:: filtering_warnings + + warnings.filterwarnings("ignore") + + .. _cpython#66733: https://github.com/python/cpython/issues/66733 From b20af2e0f54b7a4344b21a64c62cea4aeb5c17c0 Mon Sep 17 00:00:00 2001 From: Martin Yeo Date: Fri, 22 Sep 2023 10:48:58 +0100 Subject: [PATCH 4/5] Corrections to command line warning filtering. --- .../src/further_topics/filtering_warnings.rst | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/docs/src/further_topics/filtering_warnings.rst b/docs/src/further_topics/filtering_warnings.rst index c7672eb5d5..725a1d96af 100644 --- a/docs/src/further_topics/filtering_warnings.rst +++ b/docs/src/further_topics/filtering_warnings.rst @@ -136,7 +136,6 @@ Or you can target Warnings raised by specific lines of specific modules, e.g. python -W ignore:::iris.coord_systems:454 export PYTHONWARNINGS=ignore:::iris.coord_systems:454 - Warnings from a Common Source ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -158,7 +157,9 @@ E.g. filtering the ``coord_systems`` module: ---- -It also works to ``ignore`` all warnings from ``iris`` as a whole: +If using :func:`warnings.filterwarnings` , you can also use partial +definitions. The below example ``ignore``s all Warnings from ``iris`` as a +whole. .. doctest:: filtering_warnings @@ -166,10 +167,7 @@ It also works to ``ignore`` all warnings from ``iris`` as a whole: ... warnings.filterwarnings("ignore", module="iris") ... my_operation() -:: - - python -W ignore:::iris - export PYTHONWARNINGS=ignore:::iris +The above 'partial' filter is not available with the command line approaches. Warnings of a Common Type ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -193,14 +191,6 @@ module during execution: iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance. warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning) -:: - - export PYTHONWARNINGS=ignore::iris.exceptions.IrisDefaultingWarning - -This example is not possible using ``python -W`` on the command line, which -can only handle the built-in Warning categories -(`cpython#66733`_). - ---- Using :class:`~iris.exceptions.IrisUserWarning` in the filter will ``ignore`` @@ -216,13 +206,13 @@ both Warnings, since :class:`~iris.exceptions.IrisDefaultingWarning` subclasses ... ) ... my_operation() -:: +---- - export PYTHONWARNINGS=ignore::iris.exceptions.IrisUserWarning +The command line approaches can only handle the built-in Warning +categories (`cpython#66733`_):: -This example is not possible using ``python -W`` on the command line, which -can only handle the built-in Warning categories -(`cpython#66733`_). + python -W ignore::UserWarning + export PYTHONWARNINGS=ignore::UserWarning ---- From 026615668063f9cea26601ea87a20d891feb8fbd Mon Sep 17 00:00:00 2001 From: Martin Yeo Date: Fri, 22 Sep 2023 10:50:11 +0100 Subject: [PATCH 5/5] Typo. --- docs/src/further_topics/filtering_warnings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/further_topics/filtering_warnings.rst b/docs/src/further_topics/filtering_warnings.rst index 725a1d96af..689ea69a52 100644 --- a/docs/src/further_topics/filtering_warnings.rst +++ b/docs/src/further_topics/filtering_warnings.rst @@ -158,7 +158,7 @@ E.g. filtering the ``coord_systems`` module: ---- If using :func:`warnings.filterwarnings` , you can also use partial -definitions. The below example ``ignore``s all Warnings from ``iris`` as a +definitions. The below example will ``ignore`` all Warnings from ``iris`` as a whole. .. doctest:: filtering_warnings