From 2f9edbac5acc936254072c3250ece714833c03cf Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 30 Jan 2025 01:00:06 -0500 Subject: [PATCH 1/5] ci: Re-enable testing with optimizations enabled Also, skip a few tests that only work with docstrings enabled. Fixes #10312 --- .github/workflows/tests.yml | 4 ++++ lib/matplotlib/tests/test_artist.py | 7 +++++- lib/matplotlib/tests/test_matplotlib.py | 2 ++ lib/matplotlib/tests/test_preprocess_data.py | 24 ++++++++++++-------- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7a197a9d4aa8..0359f9119ac7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -60,6 +60,7 @@ jobs: extra-requirements: '-r requirements/testing/extra.txt' # https://github.com/matplotlib/matplotlib/issues/29844 pygobject-ver: '<3.52.0' + python-optimize: 'true' - os: ubuntu-22.04-arm python-version: '3.12' # https://github.com/matplotlib/matplotlib/issues/29844 @@ -334,6 +335,9 @@ jobs: if [[ "${{ matrix.python-version }}" == '3.13t' ]]; then export PYTHON_GIL=0 fi + if [[ "${{ matrix.python-optimize }}" == 'true' ]]; then + export PYTHONOPTIMIZE=2 + fi pytest -rfEsXR -n auto \ --maxfail=50 --timeout=300 --durations=25 \ --cov-report=xml --cov=lib --log-level=DEBUG --color=yes diff --git a/lib/matplotlib/tests/test_artist.py b/lib/matplotlib/tests/test_artist.py index 5c8141e40741..e8f0c1269169 100644 --- a/lib/matplotlib/tests/test_artist.py +++ b/lib/matplotlib/tests/test_artist.py @@ -1,5 +1,6 @@ import io from itertools import chain +import sys import numpy as np @@ -256,7 +257,9 @@ def test_setp(): # Check *file* argument sio = io.StringIO() plt.setp(lines1, 'zorder', file=sio) - assert sio.getvalue() == ' zorder: float\n' + # With optimization, docstrings are stripped so the automated types don't work. + expected = 'unknown' if sys.flags.optimize >= 2 else 'float' + assert sio.getvalue() == f' zorder: {expected}\n' def test_None_zorder(): @@ -361,6 +364,8 @@ def set_myparam2(self, val): assert 'myparam2' in MyArtist2.set.__doc__ +@pytest.mark.skipif(sys.flags.optimize >= 2, + reason='Python optimization is enabled and docstrings are stripped') def test_set_is_overwritten(): """set() defined in Artist subclasses should not be overwritten.""" class MyArtist3(martist.Artist): diff --git a/lib/matplotlib/tests/test_matplotlib.py b/lib/matplotlib/tests/test_matplotlib.py index 37b41fafdb78..500c343186e9 100644 --- a/lib/matplotlib/tests/test_matplotlib.py +++ b/lib/matplotlib/tests/test_matplotlib.py @@ -44,6 +44,8 @@ def test_importable_with_no_home(tmp_path): env={**os.environ, "MPLCONFIGDIR": str(tmp_path)}, check=True) +@pytest.mark.skipif(sys.flags.optimize >= 2, + reason='Python optimization is enabled and docstrings are stripped') def test_use_doc_standard_backends(): """ Test that the standard backends mentioned in the docstring of diff --git a/lib/matplotlib/tests/test_preprocess_data.py b/lib/matplotlib/tests/test_preprocess_data.py index c983d78786e1..f74c2a8f55a6 100644 --- a/lib/matplotlib/tests/test_preprocess_data.py +++ b/lib/matplotlib/tests/test_preprocess_data.py @@ -39,23 +39,25 @@ def func_no_ax_args(*args, **kwargs): pass # this has "enough" information to do all the replaces _preprocess_data(replace_names=["x", "y"])(func_args) - # no positional_parameter_names but needed due to replaces - with pytest.raises(AssertionError): - # z is unknown - _preprocess_data(replace_names=["x", "y", "z"])(func_args) - # no replacements at all -> all ok... _preprocess_data(replace_names=[], label_namer=None)(func) _preprocess_data(replace_names=[], label_namer=None)(func_args) _preprocess_data(replace_names=[], label_namer=None)(func_kwargs) _preprocess_data(replace_names=[], label_namer=None)(func_no_ax_args) - # label namer is unknown - with pytest.raises(AssertionError): - _preprocess_data(label_namer="z")(func) + # No asserts with optimizations. + if sys.flags.optimize < 1: + # no positional_parameter_names but needed due to replaces + with pytest.raises(AssertionError): + # z is unknown + _preprocess_data(replace_names=["x", "y", "z"])(func_args) + + # label namer is unknown + with pytest.raises(AssertionError): + _preprocess_data(label_namer="z")(func) - with pytest.raises(AssertionError): - _preprocess_data(label_namer="z")(func_args) + with pytest.raises(AssertionError): + _preprocess_data(label_namer="z")(func_args) @pytest.mark.parametrize('func', all_funcs, ids=all_func_ids) @@ -193,6 +195,8 @@ def func(ax, x, y, z=1): func(None, "a", "b", "z", "z", data=data) +@pytest.mark.skipif(sys.flags.optimize >= 2, + reason='Python optimization is enabled and docstrings are stripped') def test_docstring_addition(): @_preprocess_data() def funcy(ax, *args, **kwargs): From 8902fda4a99b0038b3e8a28bc4ba2d5e231e94fc Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 30 Jan 2025 01:00:57 -0500 Subject: [PATCH 2/5] ci: Fix testing without LTO The jobs matrix doesn't set any environment variables, so the without-LTO job just set `CFLAGS` in the matrix, which was never used for anything as intended. --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0359f9119ac7..bbaf1bf2ac75 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -56,7 +56,7 @@ jobs: pygobject-ver: '<3.52.0' - os: ubuntu-22.04 python-version: '3.11' - CFLAGS: "-fno-lto" # Ensure that disabling LTO works. + lto: "--config-settings=setup-args=-Db_lto=false" # Ensure that disabling LTO works. extra-requirements: '-r requirements/testing/extra.txt' # https://github.com/matplotlib/matplotlib/issues/29844 pygobject-ver: '<3.52.0' @@ -318,7 +318,7 @@ jobs: fi python -m pip install --no-deps --no-build-isolation --verbose \ - --config-settings=setup-args="-DrcParams-backend=Agg" \ + --config-settings=setup-args="-DrcParams-backend=Agg" ${{ matrix.lto }} \ --editable .[dev] if [[ "${{ runner.os }}" != 'macOS' ]]; then From 0a002a9c23dc89ec153cb14f1d2421066def267d Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 11 Feb 2025 03:23:45 -0500 Subject: [PATCH 3/5] TST: Ensure pytest assertion rewriting occurs in subprocesses This means that: 1. assertion failures look a little better 2. assertions actually happen if optimization is enabled --- lib/matplotlib/testing/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/matplotlib/testing/__init__.py b/lib/matplotlib/testing/__init__.py index d6affb1b039f..0b7b309144b1 100644 --- a/lib/matplotlib/testing/__init__.py +++ b/lib/matplotlib/testing/__init__.py @@ -129,6 +129,8 @@ def subprocess_run_helper(func, *args, timeout, extra_env=None): [ sys.executable, "-c", + f"import pytest;" + f"pytest.register_assert_rewrite({module!r});" f"import importlib.util;" f"_spec = importlib.util.spec_from_file_location({module!r}, {file!r});" f"_module = importlib.util.module_from_spec(_spec);" From 77f76b45932f176b664944739fc0c345a1c3f92e Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 11 Feb 2025 04:01:59 -0500 Subject: [PATCH 4/5] TST: debug results --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bbaf1bf2ac75..ea5e11e2e27b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -338,7 +338,7 @@ jobs: if [[ "${{ matrix.python-optimize }}" == 'true' ]]; then export PYTHONOPTIMIZE=2 fi - pytest -rfEsXR -n auto \ + pytest -rfEsXR -n auto -sv \ --maxfail=50 --timeout=300 --durations=25 \ --cov-report=xml --cov=lib --log-level=DEBUG --color=yes From a9dc78ff41398a175736fca7c79b870457fda0a3 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 14 Feb 2025 00:50:36 -0500 Subject: [PATCH 5/5] TST: Skip PySide2 when running optimized It doesn't seem to support it, and is not really updated by upstream. --- lib/matplotlib/tests/test_backends_interactive.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/matplotlib/tests/test_backends_interactive.py b/lib/matplotlib/tests/test_backends_interactive.py index a27783fa4be1..4008e0a841e3 100644 --- a/lib/matplotlib/tests/test_backends_interactive.py +++ b/lib/matplotlib/tests/test_backends_interactive.py @@ -460,6 +460,8 @@ def qt5_and_qt6_pairs(): reason="$DISPLAY and $WAYLAND_DISPLAY are unset") @pytest.mark.parametrize('host, mpl', [*qt5_and_qt6_pairs()]) def test_cross_Qt_imports(host, mpl): + if sys.flags.optimize > 0 and 'PySide2' in {host, mpl}: + pytest.xfail('PySide2 does not work optimized') try: proc = _run_helper(_impl_test_cross_Qt_imports, host, mpl, timeout=_test_timeout)