From 2f8b805ca3e1aa3f63aa0bda709c749b444a2fd8 Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Sun, 14 Jun 2026 13:57:38 +0100 Subject: [PATCH 01/21] Backport PR #31885: Skip hidden y-axis offset text when positioning titles (fix #31881) --- lib/matplotlib/axes/_base.py | 7 ++++++- lib/matplotlib/tests/test_axes.py | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 0ddf18b12ec2..31da7cdd414d 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -3256,7 +3256,12 @@ def _update_title_position(self, renderer): if title.get_text(): for ax in axs: ax.yaxis.get_tightbbox(renderer) # update offsetText - if ax.yaxis.offsetText.get_text(): + # A hidden offset text (e.g. on the shared y axis of an + # inner subplot) is not drawn, so it must not move the + # title: its tight bbox is non-finite and would otherwise + # push the title to infinity. + if (ax.yaxis.offsetText.get_visible() + and ax.yaxis.offsetText.get_text()): bb = ax.yaxis.offsetText.get_tightbbox(renderer) if bb.intersection(title.get_tightbbox(renderer), bb): top = bb.ymax diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index b3797171cfae..911d2a63f4ed 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -7965,6 +7965,22 @@ def test_title_above_offset(left, center): assert ycenter == yleft +def test_title_above_hidden_offset(): + # On an inner subplot with a shared y axis the offset text is hidden, but + # it still carries text. It must not be considered when positioning the + # title: its tight bbox is non-finite and used to push the title (and the + # subplot position computed by tight_layout) to NaN/inf. See #31881. + mpl.rcParams['axes.titley'] = None + fig, axs = plt.subplots(1, 2, sharey=True, tight_layout=True) + for i, ax in enumerate(axs): + ax.set_title(f'Subplot {i}') + ax.plot(range(10), [1e53] * 10) + fig.draw_without_rendering() # used to raise ValueError (NaN -> int) + for ax in axs: + assert np.isfinite(ax.title.get_window_extent().ymin) + assert np.all(np.isfinite(ax.get_position().bounds)) + + def test_title_no_move_off_page(): # If an Axes is off the figure (ie. if it is cropped during a save) # make sure that the automatic title repositioning does not get done. From e31a4291323bac3cb6bf37a7d2177e12e4fad324 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Mon, 15 Jun 2026 06:29:24 +0200 Subject: [PATCH 02/21] Backport PR #31896: TST: temporarily pin pytest --- environment.yml | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/environment.yml b/environment.yml index ed9cc7009541..0266ac2b52e2 100644 --- a/environment.yml +++ b/environment.yml @@ -63,7 +63,7 @@ dependencies: - psutil - prek - pydocstyle>=5.1.0 - - pytest!=4.6.0,!=5.4.0,!=8.1.0 + - pytest!=4.6.0,!=5.4.0,!=8.1.0,<9.1.0 - pytest-cov - pytest-rerunfailures - pytest-timeout diff --git a/pyproject.toml b/pyproject.toml index 02e2cf3b6734..49457323cbec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -130,7 +130,7 @@ test = [ "certifi", "coverage!=6.3", "psutil; sys_platform != 'cygwin'", - "pytest!=4.6.0,!=5.4.0,!=8.1.0", + "pytest!=4.6.0,!=5.4.0,!=8.1.0,<9.1.0", "pytest-cov", "pytest-rerunfailures!=16.0", "pytest-timeout", From 8ddcf7238354c7c9c81563d63ccb547b9738a95d Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 16 May 2026 07:16:23 +0200 Subject: [PATCH 03/21] Backport PR #31678: Bump the actions group with 2 updates (cherry picked from commit b5a5ff806e36c2357303bd319781fd4ee9354da9) --- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/linting.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 71425e9cc3e9..04609e6a868f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -34,7 +34,7 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 + uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 with: languages: ${{ matrix.language }} @@ -45,4 +45,4 @@ jobs: pip install --user -v . - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 + uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 7d3784e07e91..5a9f8ff34aa8 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.x" - - uses: j178/prek-action@6ad80277337ad479fe43bd70701c3f7f8aa74db3 # v2.0.3 + - uses: j178/prek-action@bdca6f102f98e2b4c7029491a53dfd366469e33d # v2.0.4 with: extra-args: --hook-stage manual --all-files From f08223337708d566a2a21cb6eabebdb7adf4fb28 Mon Sep 17 00:00:00 2001 From: Scott Shambaugh <14363975+scottshambaugh@users.noreply.github.com> Date: Wed, 3 Jun 2026 13:20:57 -0600 Subject: [PATCH 04/21] Backport PR #31782: Bump the actions group across 1 directory with 4 updates (cherry picked from commit 99ae86bc6d52ac429fc1eba40978261a2465905f) --- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/conflictcheck.yml | 2 +- .github/workflows/stale-tidy.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/tests.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 04609e6a868f..3dc935180f6e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -34,7 +34,7 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 + uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: languages: ${{ matrix.language }} @@ -45,4 +45,4 @@ jobs: pip install --user -v . - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 + uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 diff --git a/.github/workflows/conflictcheck.yml b/.github/workflows/conflictcheck.yml index 2058da8ca9fb..e353e47bfb79 100644 --- a/.github/workflows/conflictcheck.yml +++ b/.github/workflows/conflictcheck.yml @@ -19,7 +19,7 @@ jobs: pull-requests: write steps: - name: Check if PRs have merge conflicts - uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3 + uses: eps1lon/actions-label-merge-conflict@0273be72a0bbd58fcd71d0d6c02c209b50d1e5e1 # v3.1.0 with: dirtyLabel: "status: needs rebase" repoToken: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/stale-tidy.yml b/.github/workflows/stale-tidy.yml index feb1fe701d70..e7d8272bdf24 100644 --- a/.github/workflows/stale-tidy.yml +++ b/.github/workflows/stale-tidy.yml @@ -13,7 +13,7 @@ jobs: permissions: issues: write steps: - - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 + - uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} operations-per-run: 300 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 63f1a1ce3b05..4ebcdcee1f31 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -14,7 +14,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 + - uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} operations-per-run: 20 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a3a9def4bd40..9214e80ea8e7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -396,7 +396,7 @@ jobs: fi - name: Upload code coverage if: ${{ !cancelled() && github.event_name != 'schedule' }} - uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 + uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 with: name: "${{ matrix.python-version }} ${{ matrix.os }} ${{ matrix.name-suffix }}" token: ${{ secrets.CODECOV_TOKEN }} From cb4b0b0b5b0582591a05805736efe9fd57f0ae0d Mon Sep 17 00:00:00 2001 From: "Lumberbot (aka Jack)" <39504233+meeseeksmachine@users.noreply.github.com> Date: Tue, 16 Jun 2026 21:01:01 +0200 Subject: [PATCH 05/21] Backport PR #31904: DOC: clarify valid inputs and return type of `same_color` (#31911) Co-authored-by: Ruth Comer <10599679+rcomer@users.noreply.github.com> --- lib/matplotlib/colors.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 53471e0f0a17..333b06464478 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -288,7 +288,15 @@ def same_color(c1, c2): """ Return whether the colors *c1* and *c2* are the same. - *c1*, *c2* can be single colors or lists/arrays of colors. + Parameters + ---------- + c1, c2 : :mpltype:`color` or list of :mpltype:`color` or RGB(A) array + If passing multiple colors, *c1* and *c2* must be of the same length. RGB(A) + arrays must be of shape (ncolors, 3) or (ncolors, 4). + + Returns + ------- + bool """ c1 = to_rgba_array(c1) c2 = to_rgba_array(c2) From c24d2211e05d811ab99e13e5f4450864adb87686 Mon Sep 17 00:00:00 2001 From: Rayan Salhab Date: Thu, 18 Jun 2026 04:55:30 +0300 Subject: [PATCH 06/21] Backport PR #31898: fix: allow array-like fill_between where masks --- lib/matplotlib/axes/_axes.pyi | 4 ++-- lib/matplotlib/pyplot.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/axes/_axes.pyi b/lib/matplotlib/axes/_axes.pyi index b43ad157f6b5..1ec52655676f 100644 --- a/lib/matplotlib/axes/_axes.pyi +++ b/lib/matplotlib/axes/_axes.pyi @@ -479,7 +479,7 @@ class Axes(_AxesBase): x: ArrayLike, y1: ArrayLike | float, y2: ArrayLike | float = ..., - where: Sequence[bool] | None = ..., + where: ArrayLike | None = ..., interpolate: bool = ..., step: Literal["pre", "post", "mid"] | None = ..., *, @@ -491,7 +491,7 @@ class Axes(_AxesBase): y: ArrayLike, x1: ArrayLike | float, x2: ArrayLike | float = ..., - where: Sequence[bool] | None = ..., + where: ArrayLike | None = ..., step: Literal["pre", "post", "mid"] | None = ..., interpolate: bool = ..., *, diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 732ec874bf38..97fd1bc6209e 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -3497,7 +3497,7 @@ def fill_between( x: ArrayLike, y1: ArrayLike | float, y2: ArrayLike | float = 0, - where: Sequence[bool] | None = None, + where: ArrayLike | None = None, interpolate: bool = False, step: Literal["pre", "post", "mid"] | None = None, *, @@ -3522,7 +3522,7 @@ def fill_betweenx( y: ArrayLike, x1: ArrayLike | float, x2: ArrayLike | float = 0, - where: Sequence[bool] | None = None, + where: ArrayLike | None = None, step: Literal["pre", "post", "mid"] | None = None, interpolate: bool = False, *, From cf5cebedbbef083289a2153b3c713a627f8acb30 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 18 Jun 2026 17:31:03 +0200 Subject: [PATCH 07/21] Backport PR #31906: TST: unpin pytest --- environment.yml | 2 +- lib/matplotlib/tests/test_animation.py | 4 ++-- lib/matplotlib/tests/test_mathtext.py | 8 ++++---- lib/matplotlib/tests/test_mlab.py | 8 ++------ lib/matplotlib/tests/test_path.py | 2 +- lib/matplotlib/tests/test_rcparams.py | 4 ++-- lib/matplotlib/tests/test_ticker.py | 4 ++-- pyproject.toml | 2 +- 8 files changed, 15 insertions(+), 19 deletions(-) diff --git a/environment.yml b/environment.yml index 0266ac2b52e2..ed9cc7009541 100644 --- a/environment.yml +++ b/environment.yml @@ -63,7 +63,7 @@ dependencies: - psutil - prek - pydocstyle>=5.1.0 - - pytest!=4.6.0,!=5.4.0,!=8.1.0,<9.1.0 + - pytest!=4.6.0,!=5.4.0,!=8.1.0 - pytest-cov - pytest-rerunfailures - pytest-timeout diff --git a/lib/matplotlib/tests/test_animation.py b/lib/matplotlib/tests/test_animation.py index a00adcdf95f0..bfddddf6d665 100644 --- a/lib/matplotlib/tests/test_animation.py +++ b/lib/matplotlib/tests/test_animation.py @@ -181,7 +181,7 @@ def gen_writers(): # Smoke test for saving animations. In the future, we should probably # design more sophisticated tests which compare resulting frames a-la # matplotlib.testing.image_comparison -@pytest.mark.parametrize('writer, frame_format, output', gen_writers()) +@pytest.mark.parametrize('writer, frame_format, output', list(gen_writers())) @pytest.mark.parametrize('anim', [dict(klass=dict)], indirect=['anim']) def test_save_animation_smoketest(tmp_path, writer, frame_format, output, anim): if frame_format is not None: @@ -201,7 +201,7 @@ def test_save_animation_smoketest(tmp_path, writer, frame_format, output, anim): del anim -@pytest.mark.parametrize('writer, frame_format, output', gen_writers()) +@pytest.mark.parametrize('writer, frame_format, output', list(gen_writers())) def test_grabframe(tmp_path, writer, frame_format, output): WriterClass = animation.writers[writer] diff --git a/lib/matplotlib/tests/test_mathtext.py b/lib/matplotlib/tests/test_mathtext.py index a8f9236b5208..b200c3a9e048 100644 --- a/lib/matplotlib/tests/test_mathtext.py +++ b/lib/matplotlib/tests/test_mathtext.py @@ -221,7 +221,7 @@ def baseline_images(request, fontset, index, text): @pytest.mark.parametrize( - 'index, text', enumerate(math_tests), ids=range(len(math_tests))) + 'index, text', list(enumerate(math_tests)), ids=range(len(math_tests))) @pytest.mark.parametrize( 'fontset', ['cm', 'stix', 'stixsans', 'dejavusans', 'dejavuserif']) @pytest.mark.parametrize('baseline_images', ['mathtext'], indirect=True) @@ -237,7 +237,7 @@ def test_mathtext_rendering(baseline_images, fontset, index, text): horizontalalignment='center', verticalalignment='center') -@pytest.mark.parametrize('index, text', enumerate(svgastext_math_tests), +@pytest.mark.parametrize('index, text', list(enumerate(svgastext_math_tests)), ids=range(len(svgastext_math_tests))) @pytest.mark.parametrize('fontset', ['cm', 'dejavusans']) @pytest.mark.parametrize('baseline_images', ['mathtext0'], indirect=True) @@ -254,7 +254,7 @@ def test_mathtext_rendering_svgastext(baseline_images, fontset, index, text): horizontalalignment='center', verticalalignment='center') -@pytest.mark.parametrize('index, text', enumerate(lightweight_math_tests), +@pytest.mark.parametrize('index, text', list(enumerate(lightweight_math_tests)), ids=range(len(lightweight_math_tests))) @pytest.mark.parametrize('fontset', ['dejavusans']) @pytest.mark.parametrize('baseline_images', ['mathtext1'], indirect=True) @@ -266,7 +266,7 @@ def test_mathtext_rendering_lightweight(baseline_images, fontset, index, text): @pytest.mark.parametrize( - 'index, text', enumerate(font_tests), ids=range(len(font_tests))) + 'index, text', list(enumerate(font_tests)), ids=range(len(font_tests))) @pytest.mark.parametrize( 'fontset', ['cm', 'stix', 'stixsans', 'dejavusans', 'dejavuserif']) @pytest.mark.parametrize('baseline_images', ['mathfont'], indirect=True) diff --git a/lib/matplotlib/tests/test_mlab.py b/lib/matplotlib/tests/test_mlab.py index 82f877b4cc01..4f2ae49f4772 100644 --- a/lib/matplotlib/tests/test_mlab.py +++ b/lib/matplotlib/tests/test_mlab.py @@ -207,7 +207,8 @@ def test_detrend_linear_2d(self): scope='class') class TestSpectral: @pytest.fixture(scope='class', autouse=True) - def stim(self, request, fstims, iscomplex, sides, len_x, NFFT_density, + @classmethod + def stim(cls, request, fstims, iscomplex, sides, len_x, NFFT_density, nover_density, pad_to_density, pad_to_spectrum): Fs = 100. @@ -323,11 +324,6 @@ def stim(self, request, fstims, iscomplex, sides, len_x, NFFT_density, if iscomplex: y = y.astype('complex') - # Interestingly, the instance on which this fixture is called is not - # the same as the one on which a test is run. So we need to modify the - # class itself when using a class-scoped fixture. - cls = request.cls - cls.Fs = Fs cls.sides = sides cls.fstims = fstims diff --git a/lib/matplotlib/tests/test_path.py b/lib/matplotlib/tests/test_path.py index 3c7ad5e2f99b..c31f33647879 100644 --- a/lib/matplotlib/tests/test_path.py +++ b/lib/matplotlib/tests/test_path.py @@ -105,7 +105,7 @@ def test_contains_points_negative_radius(): (1., 2., 1., 2.)] -@pytest.mark.parametrize('path, extents', zip(_test_paths, _test_path_extents)) +@pytest.mark.parametrize('path, extents', list(zip(_test_paths, _test_path_extents))) def test_exact_extents(path, extents): # notice that if we just looked at the control points to get the bounding # box of each curve, we would get the wrong answers. For example, for diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py index dc36392ab676..e740d2454125 100644 --- a/lib/matplotlib/tests/test_rcparams.py +++ b/lib/matplotlib/tests/test_rcparams.py @@ -444,7 +444,7 @@ def generate_validator_testcases(valid): @pytest.mark.parametrize('validator, arg, target', - generate_validator_testcases(True)) + list(generate_validator_testcases(True))) def test_validator_valid(validator, arg, target): res = validator(arg) if isinstance(target, np.ndarray): @@ -457,7 +457,7 @@ def test_validator_valid(validator, arg, target): @pytest.mark.parametrize('validator, arg, exception_type', - generate_validator_testcases(False)) + list(generate_validator_testcases(False))) def test_validator_invalid(validator, arg, exception_type): with pytest.raises(exception_type): validator(arg) diff --git a/lib/matplotlib/tests/test_ticker.py b/lib/matplotlib/tests/test_ticker.py index 0d01677acc8c..7930a05ff497 100644 --- a/lib/matplotlib/tests/test_ticker.py +++ b/lib/matplotlib/tests/test_ticker.py @@ -461,7 +461,7 @@ class TestLogitLocator: @pytest.mark.parametrize( "lims, expected_low_ticks", - zip(ref_basic_limits, ref_basic_major_ticks), + list(zip(ref_basic_limits, ref_basic_major_ticks)), ) def test_basic_major(self, lims, expected_low_ticks): """ @@ -506,7 +506,7 @@ def test_nbins_major(self, lims): @pytest.mark.parametrize( "lims, expected_low_ticks", - zip(ref_basic_limits, ref_basic_major_ticks), + list(zip(ref_basic_limits, ref_basic_major_ticks)), ) def test_minor(self, lims, expected_low_ticks): """ diff --git a/pyproject.toml b/pyproject.toml index 49457323cbec..02e2cf3b6734 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -130,7 +130,7 @@ test = [ "certifi", "coverage!=6.3", "psutil; sys_platform != 'cygwin'", - "pytest!=4.6.0,!=5.4.0,!=8.1.0,<9.1.0", + "pytest!=4.6.0,!=5.4.0,!=8.1.0", "pytest-cov", "pytest-rerunfailures!=16.0", "pytest-timeout", From 0ebdea5432f859fddbec6bb95c2486f9c9c5440a Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Wed, 24 Jun 2026 07:01:50 -0700 Subject: [PATCH 08/21] Backport PR #31943: FIX: allow non-strict monotonicity in LinearSegmented.from_list values --- lib/matplotlib/colors.py | 2 +- lib/matplotlib/tests/test_colors.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 333b06464478..010f73131fbc 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -1233,7 +1233,7 @@ def from_list(name, colors, N=256, gamma=1.0, *, bad=None, under=None, over=None except Exception as e2: raise e2 from e vals = np.asarray(_vals) - if np.min(vals) < 0 or np.max(vals) > 1 or np.any(np.diff(vals) <= 0): + if np.min(vals) < 0 or np.max(vals) > 1 or np.any(np.diff(vals) < 0): raise ValueError( "the values passed in the (value, color) pairs " "must increase monotonically from 0 to 1." diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 5bc1f8aea973..2ef9b7c5d091 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -1828,6 +1828,13 @@ def test_LinearSegmentedColormap_from_list_value_color_tuple(): ) +def test_LinearSegmentedColormap_from_list_repeat_values(): + # Smoke test that we can pass repeated values to make a solid band of color + # followed by a linear ramp. + value_color_tuples = [(0, "red"), (0.6, "red"), (0.6, "blue"), (1, "green")] + mcolors.LinearSegmentedColormap.from_list("lsc", value_color_tuples, N=11) + + @image_comparison(['test_norm_abc.png'], remove_text=True, style='_classic_test', tol=0 if platform.machine() == 'x86_64' else 0.05) def test_norm_abc(): From f4461ce6fd89e5740b53d52a65e925cfe42c144a Mon Sep 17 00:00:00 2001 From: "Lumberbot (aka Jack)" <39504233+meeseeksmachine@users.noreply.github.com> Date: Wed, 24 Jun 2026 16:16:05 +0200 Subject: [PATCH 09/21] Backport PR #31931: TST: address pikepdf deprecation (#31941) Co-authored-by: Elliott Sales de Andrade --- lib/matplotlib/tests/test_backend_pdf.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_backend_pdf.py b/lib/matplotlib/tests/test_backend_pdf.py index 2088ce764b5c..90db19110814 100644 --- a/lib/matplotlib/tests/test_backend_pdf.py +++ b/lib/matplotlib/tests/test_backend_pdf.py @@ -5,6 +5,7 @@ import string import numpy as np +from packaging.version import parse as parse_version import pytest import matplotlib as mpl @@ -112,7 +113,10 @@ def test_indexed_image(): with pikepdf.Pdf.open(buf) as pdf: page, = pdf.pages - image, = page.images.values() + if parse_version(pikepdf.__version__) < parse_version('10.9.0'): + image, = page.images.values() + else: + image, = page.get_images().values() pdf_image = pikepdf.PdfImage(image) assert pdf_image.indexed pil_image = pdf_image.as_pil_image() From 9c4c9a9ddd78d11f74ab55601d2f845619edb78d Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Wed, 24 Jun 2026 18:50:07 +0200 Subject: [PATCH 10/21] Backport PR #31920: Fix various small type hint issues --- ci/mypy-stubtest-allowlist.txt | 1 - lib/matplotlib/artist.pyi | 4 ++-- lib/matplotlib/axes/_base.pyi | 2 +- lib/matplotlib/backends/registry.pyi | 2 +- lib/matplotlib/colorbar.pyi | 7 +++--- lib/matplotlib/font_manager.pyi | 2 +- lib/matplotlib/image.pyi | 2 +- lib/matplotlib/rcsetup.pyi | 8 ++++++- lib/matplotlib/testing/compare.pyi | 5 +++-- lib/matplotlib/transforms.py | 2 +- lib/matplotlib/transforms.pyi | 30 +++++++++++++++++++++++--- lib/matplotlib/typing.py | 32 ++++++++++++++++------------ 12 files changed, 66 insertions(+), 31 deletions(-) diff --git a/ci/mypy-stubtest-allowlist.txt b/ci/mypy-stubtest-allowlist.txt index 0e199889cb07..5bb4f0d36c5e 100644 --- a/ci/mypy-stubtest-allowlist.txt +++ b/ci/mypy-stubtest-allowlist.txt @@ -3,7 +3,6 @@ matplotlib\.backends\..* matplotlib\.tests(\..*)? matplotlib\.pylab(\..*)? matplotlib\._.* -matplotlib\.rcsetup\._listify_validator matplotlib\.rcsetup\._validate_linestyle matplotlib\.ft2font\.Glyph matplotlib\.ft2font\.LayoutItem diff --git a/lib/matplotlib/artist.pyi b/lib/matplotlib/artist.pyi index 7b8b0c36be69..c70a9ac750fc 100644 --- a/lib/matplotlib/artist.pyi +++ b/lib/matplotlib/artist.pyi @@ -23,8 +23,8 @@ _T_Artist = TypeVar("_T_Artist", bound=Artist) def allow_rasterization(draw): ... class _XYPair(NamedTuple): - x: ArrayLike - y: ArrayLike + x: list[float] + y: list[float] class Artist: zorder: float diff --git a/lib/matplotlib/axes/_base.pyi b/lib/matplotlib/axes/_base.pyi index 4a70405346a5..f90ddc45f347 100644 --- a/lib/matplotlib/axes/_base.pyi +++ b/lib/matplotlib/axes/_base.pyi @@ -67,7 +67,7 @@ class _AxesBase(martist.Artist): def __init__( self, - fig: Figure, + fig: Figure | SubFigure, *args: tuple[float, float, float, float] | Bbox | int, facecolor: ColorType | None = ..., frameon: bool = ..., diff --git a/lib/matplotlib/backends/registry.pyi b/lib/matplotlib/backends/registry.pyi index 565f044bf212..d1ba09cb523b 100644 --- a/lib/matplotlib/backends/registry.pyi +++ b/lib/matplotlib/backends/registry.pyi @@ -25,7 +25,7 @@ class BackendRegistry: def backend_for_gui_framework(self, framework: str) -> str | None: ... def is_valid_backend(self, backend: str) -> bool: ... def list_all(self) -> list[str]: ... - def list_builtin(self, filter_: BackendFilter | None) -> list[str]: ... + def list_builtin(self, filter_: BackendFilter | None = ...) -> list[str]: ... def list_gui_frameworks(self) -> list[str]: ... def load_backend_module(self, backend: str) -> ModuleType: ... def resolve_backend(self, backend: str | None) -> tuple[str, str | None]: ... diff --git a/lib/matplotlib/colorbar.pyi b/lib/matplotlib/colorbar.pyi index 07467ca74f3d..33a63ddd5335 100644 --- a/lib/matplotlib/colorbar.pyi +++ b/lib/matplotlib/colorbar.pyi @@ -13,11 +13,12 @@ from collections.abc import Sequence from typing import Any, Literal, overload from .typing import ColorType -class _ColorbarSpine(mspines.Spines): + +class _ColorbarSpine(mspines.Spine): def __init__(self, axes: Axes): ... - def get_window_extent(self, renderer: RendererBase | None = ...) -> Bbox:... + def get_window_extent(self, renderer: RendererBase | None = ...) -> Bbox: ... def set_xy(self, xy: ArrayLike) -> None: ... - def draw(self, renderer: RendererBase | None) -> None:... + def draw(self, renderer: RendererBase | None) -> None: ... class Colorbar: diff --git a/lib/matplotlib/font_manager.pyi b/lib/matplotlib/font_manager.pyi index 4bb1a8bae2a9..45cafeb23e3f 100644 --- a/lib/matplotlib/font_manager.pyi +++ b/lib/matplotlib/font_manager.pyi @@ -147,7 +147,7 @@ class FontManager: rebuild_if_missing: bool = ..., ) -> list[FontPath]: ... -def is_opentype_cff_font(filename: str) -> bool: ... +def is_opentype_cff_font(filename: str | os.PathLike) -> bool: ... def get_font( font_filepaths: Iterable[str | bytes | os.PathLike | FontPath] | str | bytes | os.PathLike | FontPath, ) -> ft2font.FT2Font: ... diff --git a/lib/matplotlib/image.pyi b/lib/matplotlib/image.pyi index 1fcc1a710bfd..4c2a8fbdb0e6 100644 --- a/lib/matplotlib/image.pyi +++ b/lib/matplotlib/image.pyi @@ -84,7 +84,7 @@ class _ImageBase(colorizer.ColorizingArtist): self, renderer: RendererBase, magnification: float = ..., unsampled: bool = ... ) -> tuple[np.ndarray, float, float, Affine2D]: ... def draw(self, renderer: RendererBase) -> None: ... - def write_png(self, fname: str | pathlib.Path | BinaryIO) -> None: ... + def write_png(self, fname: str | os.PathLike | BinaryIO) -> None: ... def set_data(self, A: ArrayLike | None) -> None: ... def set_array(self, A: ArrayLike | None) -> None: ... def get_shape(self) -> tuple[int, int, int]: ... diff --git a/lib/matplotlib/rcsetup.pyi b/lib/matplotlib/rcsetup.pyi index 120c0c93bec9..79f96430107a 100644 --- a/lib/matplotlib/rcsetup.pyi +++ b/lib/matplotlib/rcsetup.pyi @@ -7,7 +7,13 @@ from matplotlib.typing import ColorType, LineStyleType, MarkEveryType _T = TypeVar("_T") -def _listify_validator(s: Callable[[Any], _T]) -> Callable[[Any], list[_T]]: ... +def _listify_validator( + scalar_validator: Callable[[Any], _T], + allow_stringlist: bool = ..., + *, + n: int | None = ..., + doc: str | None = ..., +) -> Callable[[Any], list[_T]]: ... class ValidateInStrings: key: str diff --git a/lib/matplotlib/testing/compare.pyi b/lib/matplotlib/testing/compare.pyi index 8f11b3bebc1a..c673bdad6231 100644 --- a/lib/matplotlib/testing/compare.pyi +++ b/lib/matplotlib/testing/compare.pyi @@ -1,18 +1,19 @@ from collections.abc import Callable +from os import PathLike from typing import Literal, overload from numpy.typing import NDArray __all__ = ["calculate_rms", "comparable_formats", "compare_images"] -def make_test_filename(fname: str, purpose: str) -> str: ... +def make_test_filename(fname: str | PathLike, purpose: str) -> str: ... def get_cache_dir() -> str: ... def get_file_hash(path: str, block_size: int = ...) -> str: ... converter: dict[str, Callable[[str, str], None]] = {} def comparable_formats() -> list[str]: ... -def convert(filename: str, cache: bool) -> str: ... +def convert(filename: str | PathLike, cache: bool) -> str: ... def crop_to_same( actual_path: str, actual_image: NDArray, expected_path: str, expected_image: NDArray ) -> tuple[NDArray, NDArray]: ... diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index a279de0dfd8b..2b46deae43dd 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -156,7 +156,7 @@ def invalidate(self): Invalidate this `TransformNode` and triggers an invalidation of its ancestors. Should be called any time the transform changes. """ - return self._invalidate_internal( + self._invalidate_internal( level=self._INVALID_AFFINE_ONLY if self.is_affine else self._INVALID_FULL, invalidating_node=self) diff --git a/lib/matplotlib/transforms.pyi b/lib/matplotlib/transforms.pyi index ebee3954a3a7..d3cd5f4ab692 100644 --- a/lib/matplotlib/transforms.pyi +++ b/lib/matplotlib/transforms.pyi @@ -9,9 +9,6 @@ from typing import Literal DEBUG: bool class TransformNode: - INVALID_NON_AFFINE: int - INVALID_AFFINE: int - INVALID: int # Implemented as a standard attr in base class, but functionally readonly and some subclasses implement as such @property def is_affine(self) -> bool: ... @@ -130,12 +127,39 @@ class Bbox(BboxBase): updatex: bool = ..., updatey: bool = ..., ) -> None: ... + # Access to the parent class property is broken in mypy right now, so ignore that + # check for the following read/write properties. + # https://github.com/python/mypy/issues/5936 + @BboxBase.x0.setter # type: ignore[attr-defined,misc] + def x0(self, val: float) -> None: ... + @BboxBase.y0.setter # type: ignore[attr-defined,misc] + def y0(self, val: float) -> None: ... + @BboxBase.x1.setter # type: ignore[attr-defined,misc] + def x1(self, val: float) -> None: ... + @BboxBase.y1.setter # type: ignore[attr-defined,misc] + def y1(self, val: float) -> None: ... + @BboxBase.p0.setter # type: ignore[attr-defined,misc] + def p0(self, val: tuple[float, float]) -> None: ... + @BboxBase.p1.setter # type: ignore[attr-defined,misc] + def p1(self, val: tuple[float, float]) -> None: ... + @BboxBase.intervalx.setter # type: ignore[attr-defined,misc] + def intervalx(self, interval: tuple[float, float]) -> None: ... + @BboxBase.intervaly.setter # type: ignore[attr-defined,misc] + def intervaly(self, interval: tuple[float, float]) -> None: ... + @BboxBase.bounds.setter # type: ignore[attr-defined,misc] + def bounds(self, bounds: tuple[float, float, float, float]) -> None: ... @property def minpos(self) -> float: ... + @minpos.setter + def minpos(self, val: float) -> None: ... @property def minposx(self) -> float: ... + @minposx.setter + def minposx(self, val: float) -> None: ... @property def minposy(self) -> float: ... + @minposy.setter + def minposy(self, val: float) -> None: ... def get_points(self) -> np.ndarray: ... def set_points(self, points: ArrayLike) -> None: ... def set(self, other: Bbox) -> None: ... diff --git a/lib/matplotlib/typing.py b/lib/matplotlib/typing.py index 76b5f2b642f3..68325fe284e2 100644 --- a/lib/matplotlib/typing.py +++ b/lib/matplotlib/typing.py @@ -12,7 +12,7 @@ """ from collections.abc import Hashable, Sequence import pathlib -from typing import Any, Literal, TypeAlias, TypeVar, Union +from typing import Any, Literal, TypeAlias, TypeVar from collections.abc import Callable, Mapping from . import path @@ -99,19 +99,14 @@ LogLevel: TypeAlias = Literal["NOTSET", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] """Literal type for valid logging levels accepted by `matplotlib.set_loglevel()`.""" -CoordsBaseType = Union[ - str, - Artist, - Transform, - Callable[ - [RendererBase], - Union[Bbox, Transform] - ] -] -CoordsType = Union[ - CoordsBaseType, - tuple[CoordsBaseType, CoordsBaseType] -] +CoordsBaseType: TypeAlias = ( + str | + Artist | + Transform | + Callable[[RendererBase], Bbox | Transform] +) +CoordsType: TypeAlias = CoordsBaseType | tuple[CoordsBaseType, CoordsBaseType] +"""Annotation coordinate systems. See :doc:`/users/explain/text/annotations`.""" RcStyleType: TypeAlias = ( str | @@ -138,16 +133,22 @@ "axes_enter_event", "axes_leave_event", ] +"""Literal type for valid `.MouseEvent` names.""" KeyEventType: TypeAlias = Literal[ "key_press_event", "key_release_event" ] +"""Literal type for valid `.KeyEvent` names.""" DrawEventType: TypeAlias = Literal["draw_event"] +"""Literal type for valid `.DrawEvent` names.""" PickEventType: TypeAlias = Literal["pick_event"] +"""Literal type for valid `.PickEvent` names.""" ResizeEventType: TypeAlias = Literal["resize_event"] +"""Literal type for valid `.ResizeEvent` names.""" CloseEventType: TypeAlias = Literal["close_event"] +"""Literal type for valid `.CloseEvent` names.""" EventType: TypeAlias = Literal[ MouseEventType, @@ -157,6 +158,7 @@ ResizeEventType, CloseEventType, ] +"""Literal type for all valid events.""" LegendLocType: TypeAlias = ( Literal[ @@ -524,6 +526,7 @@ "ytick.minor.width", "ytick.right", ] +"""Valid specifiers for keys in `matplotlib.rcParams` and `matplotlib.rc_context`.""" RcGroupKeyType: TypeAlias = Literal[ "agg", @@ -590,3 +593,4 @@ "ytick.major", "ytick.minor", ] +"""Literal type for valid groups accepted by `matplotlib.rc`.""" From d1902a52db017dca5fe9c9eb68ff7457e559e6fd Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Fri, 26 Jun 2026 18:29:43 +0200 Subject: [PATCH 11/21] Backport PR #31946: TST: Increase some tolerances for non-x86_64 architectures --- lib/matplotlib/tests/test_axes.py | 10 +++++----- lib/matplotlib/tests/test_figure.py | 2 +- lib/matplotlib/tests/test_legend.py | 5 ++--- lib/matplotlib/tests/test_patheffects.py | 6 +++--- lib/matplotlib/tests/test_polar.py | 6 +++--- lib/mpl_toolkits/mplot3d/tests/test_axes3d.py | 2 +- lib/mpl_toolkits/mplot3d/tests/test_legend3d.py | 4 ++-- 7 files changed, 17 insertions(+), 18 deletions(-) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 911d2a63f4ed..a1dce857b4ef 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -240,7 +240,7 @@ def test_matshow(fig_test, fig_ref): @image_comparison([f'formatter_ticker_{i:03d}.png' for i in range(1, 6)], style='mpl20', - tol=0.03 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.03) def test_formatter_ticker(): import matplotlib.testing.jpl_units as units units.register() @@ -5611,7 +5611,7 @@ def test_marker_styles(): @image_comparison(['rc_markerfill.png'], style='mpl20', - tol=0.033 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.033) def test_markers_fillstyle_rcparams(): fig, ax = plt.subplots() x = np.arange(7) @@ -5634,7 +5634,7 @@ def test_vertex_markers(): @image_comparison(['vline_hline_zorder.png', 'errorbar_zorder.png'], style='mpl20', - tol=0.02 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.02) def test_eb_line_zorder(): x = list(range(10)) @@ -6666,7 +6666,7 @@ def test_pie_linewidth_0(): @image_comparison(['pie_center_radius.png'], style='mpl20', - tol=0.01 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.01) def test_pie_center_radius(): # The slices will be ordered and plotted counter-clockwise. labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' @@ -9857,7 +9857,7 @@ def test_zorder_and_explicit_rasterization(): @image_comparison(["preset_clip_paths.png"], remove_text=True, style="mpl20", - tol=0.01 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.01) def test_preset_clip_paths(): fig, ax = plt.subplots() diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index fbfb2515f42e..8391bda62e3c 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -1397,7 +1397,7 @@ def test_subfigure_dpi(): @image_comparison(['test_subfigure_ss.png'], style='mpl20', savefig_kwarg={'facecolor': 'teal'}, - tol=0.022 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.022) def test_subfigure_ss(): # test assigning the subfigure via subplotspec np.random.seed(19680801) diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index 67b433fe7447..84d3b7c4f09d 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -2,7 +2,6 @@ import io import itertools import platform -import sys import time from unittest import mock import warnings @@ -203,7 +202,7 @@ def test_alpha_rcparam(): @image_comparison(['fancy.png'], remove_text=True, style='mpl20', - tol=0.01 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.01) def test_fancy(): # using subplot triggers some offsetbox functionality untested elsewhere plt.subplot(121) @@ -665,7 +664,7 @@ def test_empty_bar_chart_with_legend(): @image_comparison(['shadow_argument_types.png'], remove_text=True, style='mpl20', - tol=0.028 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.028) def test_shadow_argument_types(): # Test that different arguments for shadow work as expected fig, ax = plt.subplots() diff --git a/lib/matplotlib/tests/test_patheffects.py b/lib/matplotlib/tests/test_patheffects.py index 7095f6b3855b..d8dfee3c1b94 100644 --- a/lib/matplotlib/tests/test_patheffects.py +++ b/lib/matplotlib/tests/test_patheffects.py @@ -1,4 +1,4 @@ -import sys +import platform import numpy as np @@ -30,7 +30,7 @@ def test_patheffect1(): @image_comparison(['patheffect2'], remove_text=True, style='mpl20', - tol=0.051 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.051) def test_patheffect2(): ax2 = plt.subplot() @@ -46,7 +46,7 @@ def test_patheffect2(): @image_comparison(['patheffect3'], style='mpl20', - tol=0.02 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.02) def test_patheffect3(): plt.figure(figsize=(8, 6)) p1, = plt.plot([1, 3, 5, 4, 3], 'o-b', lw=4) diff --git a/lib/matplotlib/tests/test_polar.py b/lib/matplotlib/tests/test_polar.py index 168047d0c07e..b7c55335aaa7 100644 --- a/lib/matplotlib/tests/test_polar.py +++ b/lib/matplotlib/tests/test_polar.py @@ -1,4 +1,4 @@ -import sys +import platform import numpy as np from numpy.testing import assert_allclose @@ -12,7 +12,7 @@ @image_comparison(['polar_axes.png'], style='default', - tol=0.009 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.009) def test_polar_annotations(): # You can specify the xypoint and the xytext in different positions and # coordinate systems, and optionally turn on a connecting line and mark the @@ -47,7 +47,7 @@ def test_polar_annotations(): @image_comparison(['polar_coords.png'], style='default', remove_text=True, - tol=0.013 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.013) def test_polar_coord_annotations(): # You can also use polar notation on a cartesian axes. Here the native # coordinate system ('data') is cartesian, so you need to specify the diff --git a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py index 14bb1bbd9ba5..9d6b094ce005 100644 --- a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py +++ b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py @@ -1724,7 +1724,7 @@ def test_errorbar3d_errorevery(): @mpl3d_image_comparison(['errorbar3d.png'], style='mpl20', - tol=0.015 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.015) def test_errorbar3d(): """Tests limits, color styling, and legend for 3D errorbars.""" fig = plt.figure() diff --git a/lib/mpl_toolkits/mplot3d/tests/test_legend3d.py b/lib/mpl_toolkits/mplot3d/tests/test_legend3d.py index a46c958222d8..86e0017699fb 100644 --- a/lib/mpl_toolkits/mplot3d/tests/test_legend3d.py +++ b/lib/mpl_toolkits/mplot3d/tests/test_legend3d.py @@ -1,4 +1,4 @@ -import sys +import platform import numpy as np @@ -28,7 +28,7 @@ def test_legend_bar(): @image_comparison(['fancy.png'], remove_text=True, style='mpl20', - tol=0.01 if sys.platform == 'darwin' else 0) + tol=0 if platform.machine() == 'x86_64' else 0.01) def test_fancy(): fig, ax = plt.subplots(subplot_kw=dict(projection='3d')) ax.plot(np.arange(10), np.full(10, 5), np.full(10, 5), 'o--', label='line') From 70e08de954049392c5460daca80187a2405a8156 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 26 Jun 2026 14:24:56 -0400 Subject: [PATCH 12/21] Backport PR #31857: bound ft2font stream read to the requested count --- lib/matplotlib/tests/test_ft2font.py | 25 +++++++++++++++++++++++++ src/ft2font_wrapper.cpp | 9 +++++++++ 2 files changed, 34 insertions(+) diff --git a/lib/matplotlib/tests/test_ft2font.py b/lib/matplotlib/tests/test_ft2font.py index ee7c7cea3aac..105feb37fa2f 100644 --- a/lib/matplotlib/tests/test_ft2font.py +++ b/lib/matplotlib/tests/test_ft2font.py @@ -203,6 +203,31 @@ def test_ft2font_invalid_args(tmp_path): ft2font.FT2Font(file, _kerning_factor=123) +def test_ft2font_oversized_read(): + # A file object whose read() returns *more* bytes than requested is + # misbehaving: FreeType only sizes its buffer for the requested count, so + # an over-long read must be rejected rather than overflow the buffer or be + # silently truncated. Verify that such an object causes construction to + # fail loudly instead. + data = Path(fm.findfont('DejaVu Sans')).read_bytes() + + class OversizedReader: + def __init__(self, data): + self._data = data + + def seek(self, offset): + pass + + def read(self, size): + # Ignore the requested size and hand back the whole file, which is + # far more than FreeType ever asks for. The initial read(0) probe + # in the constructor still gets an empty bytes object. + return self._data if size else b'' + + with pytest.raises(RuntimeError): + ft2font.FT2Font(OversizedReader(data)) + + @pytest.mark.parametrize('name, size, skippable', [('DejaVu Sans', 1, False), ('WenQuanYi Zen Hei', 3, True)]) def test_ft2font_face_index(name, size, skippable): diff --git a/src/ft2font_wrapper.cpp b/src/ft2font_wrapper.cpp index 771f1db5a191..a8654ba1d8a3 100644 --- a/src/ft2font_wrapper.cpp +++ b/src/ft2font_wrapper.cpp @@ -453,6 +453,15 @@ read_from_file_callback(FT_Stream stream, unsigned long offset, unsigned char *b if (PyBytes_AsStringAndSize(read_result.ptr(), &tmpbuf, &n_read) == -1) { throw py::error_already_set(); } + if ((unsigned long)n_read > count) { + // A well-behaved read() never returns more than the requested + // number of bytes. FreeType only ever sized `buffer` for `count` + // bytes, so honoring an over-long read would overflow it. Rather + // than silently truncate (which would feed FreeType corrupt data), + // signal a failed read so that FT_Open_Face -- and in turn the + // FT2Font constructor -- raises. + n_read = 0; + } memcpy(buffer, tmpbuf, n_read); } catch (py::error_already_set &eas) { eas.discard_as_unraisable(__func__); From 30fb47df5011f0f973fe2a5390a19d698acd51ad Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Fri, 26 Jun 2026 13:27:42 -0500 Subject: [PATCH 13/21] Backport PR #30252: Move cibuildwheel configuration to pyproject.toml --- .github/labeler.yml | 1 + .github/workflows/cibuildwheel.yml | 30 +---------------------- pyproject.toml | 38 ++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 77b79146b47f..ee49868c8d7f 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -4,6 +4,7 @@ - any-glob-to-any-file: - '.github/workflows/cibuildwheel.yml' - '.github/workflows/wasm.yml' + - 'pyproject.toml' "CI: Run cygwin": - changed-files: - any-glob-to-any-file: ['.github/workflows/cygwin.yml'] diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml index 2bb7f9544902..8ef0add983e3 100644 --- a/.github/workflows/cibuildwheel.yml +++ b/.github/workflows/cibuildwheel.yml @@ -97,31 +97,6 @@ jobs: permissions: contents: read runs-on: ${{ matrix.os }} - env: - CIBW_BEFORE_BUILD: >- - rm -rf {package}/build - CIBW_BEFORE_BUILD_WINDOWS: >- - pip install delvewheel && - rm -rf {package}/build - CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: >- - delvewheel repair -w {dest_dir} {wheel} - CIBW_AFTER_BUILD: >- - twine check {wheel} && - python {package}/ci/check_wheel_licenses.py {wheel} - # On Windows, we explicitly request MSVC compilers (as GitHub Action runners have - # MinGW on PATH that would be picked otherwise), switch to a static build for - # runtimes, but use dynamic linking for `VCRUNTIME140.dll`, `VCRUNTIME140_1.dll`, - # and the UCRT. This avoids requiring specific versions of `MSVCP140.dll`, while - # keeping shared state with the rest of the Python process/extensions. - CIBW_CONFIG_SETTINGS_WINDOWS: >- - setup-args="--vsenv" - setup-args="-Db_vscrt=mt" - setup-args="-Dcpp_link_args=['ucrt.lib','vcruntime.lib','/nodefaultlib:libucrt.lib','/nodefaultlib:libvcruntime.lib']" - CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014 - CIBW_SKIP: "*-musllinux_aarch64" - CIBW_TEST_COMMAND: >- - python {package}/ci/check_version_number.py - MACOSX_DEPLOYMENT_TARGET: "10.12" strategy: matrix: include: @@ -155,17 +130,14 @@ jobs: package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }} env: CIBW_BUILD: "cp314-* cp314t-*" - CIBW_ENABLE: "cpython-freethreading cpython-prerelease" CIBW_ARCHS: ${{ matrix.cibw_archs }} - CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28 - name: Build wheels for CPython 3.13 uses: pypa/cibuildwheel@8d2b08b68458a16aeb24b64e68a09ab1c8e82084 # v3.4.1 with: package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }} env: - CIBW_BUILD: "cp313-* cp313t-*" - CIBW_ENABLE: cpython-freethreading + CIBW_BUILD: "cp313-*" CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.12 diff --git a/pyproject.toml b/pyproject.toml index 02e2cf3b6734..20fff2d6deb6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -401,6 +401,21 @@ addopts = [ "--import-mode=importlib", ] +[tool.cibuildwheel] +enable = ["cpython-freethreading"] +skip = "*-musllinux_aarch64" +manylinux-x86_64-image = "manylinux2014" + +before-build = "rm -rf {package}/build" +test-command = [ + # "python {package}/ci/check_wheel_licenses.py {wheel}", + "python {package}/ci/check_version_number.py", +] +test-environment = "PIP_PREFER_BINARY=true" + +[tool.cibuildwheel.macos.environment] +MACOSX_DEPLOYMENT_TARGET = "10.12" + [tool.cibuildwheel.pyodide] test-requires = "pytest" test-command = [ @@ -423,3 +438,26 @@ test-command = [ CFLAGS = "-fexceptions" CXXFLAGS = "-fexceptions" LDFLAGS = "-fexceptions" + +[tool.cibuildwheel.windows] +before-build = [ + "pip install delvewheel", + "rm -rf {package}/build", +] +repair-wheel-command = "delvewheel repair -w {dest_dir} {wheel}" + +[tool.cibuildwheel.windows.config-settings] +# On Windows, we explicitly request MSVC compilers (as GitHub Action runners have +# MinGW on PATH that would be picked otherwise), switch to a static build for +# runtimes, but use dynamic linking for `VCRUNTIME140.dll`, `VCRUNTIME140_1.dll`, +# and the UCRT. This avoids requiring specific versions of `MSVCP140.dll`, while +# keeping shared state with the rest of the Python process/extensions. +setup-args = [ + "--vsenv", + "-Db_vscrt=mt", + "-Dcpp_link_args=['ucrt.lib','vcruntime.lib','/nodefaultlib:libucrt.lib','/nodefaultlib:libvcruntime.lib']", +] + +[[tool.cibuildwheel.overrides]] +select = "cp314*" +manylinux-x86_64-image = "manylinux_2_28" From 18fdd78b40dbdbee5ebc48fb66689e8c5898669b Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Fri, 26 Jun 2026 13:28:06 -0500 Subject: [PATCH 14/21] Backport PR #31928: Fix notdef handling when subsetting Type 1 fonts --- lib/matplotlib/_type1font.py | 8 ++++---- .../test_usetex/test_usetex.pdf | Bin 39233 -> 47064 bytes .../test_usetex/test_usetex.png | Bin 13253 -> 13453 bytes lib/matplotlib/tests/test_usetex.py | 7 ++++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/matplotlib/_type1font.py b/lib/matplotlib/_type1font.py index b4ee5edb233c..c7b73f9c0c7e 100644 --- a/lib/matplotlib/_type1font.py +++ b/lib/matplotlib/_type1font.py @@ -866,17 +866,16 @@ def subset(self, characters, name_prefix): encoding = {code: glyph for code, glyph in self.prop['Encoding'].items() if code in characters} - encoding[0] = '.notdef' # todo and done include strings (glyph names) - todo = set(encoding.values()) + todo = {'.notdef', *encoding.values()} done = set() seen_subrs = {0, 1, 2, 3} while todo: glyph = todo.pop() called_glyphs, called_subrs = _CharstringSimulator(self).run(glyph) + done.add(glyph) todo.update(called_glyphs - done) seen_subrs.update(called_subrs) - done.add(glyph) charstrings = self._subset_charstrings(done) subrs = self._subset_subrs(seen_subrs) @@ -949,7 +948,8 @@ def _charstring_tokens(data): def _postscript_encoding(self, encoding): """Return a PostScript encoding array for the encoding.""" return '\n'.join([ - '/Encoding 256 array\n0 1 255 { 1 index exch /.notdef put} for', + '/Encoding 256 array', + '0 1 255 { 1 index exch /.notdef put} for', *( f'dup {i} /{glyph} put' for i, glyph in sorted(encoding.items()) diff --git a/lib/matplotlib/tests/baseline_images/test_usetex/test_usetex.pdf b/lib/matplotlib/tests/baseline_images/test_usetex/test_usetex.pdf index f2ebbeb528cc52fc9958a37ed484af06e9e05ff6..bce9d583d4d4b6e5dbd679b0da85c3bb2dcc7439 100644 GIT binary patch delta 42699 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 delta 35084 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 diff --git a/lib/matplotlib/tests/test_usetex.py b/lib/matplotlib/tests/test_usetex.py index 87277f152789..6d7506055ce5 100644 --- a/lib/matplotlib/tests/test_usetex.py +++ b/lib/matplotlib/tests/test_usetex.py @@ -26,10 +26,11 @@ def test_usetex(): kwargs = {"verticalalignment": "baseline", "size": 24, "bbox": dict(pad=0, edgecolor="k", facecolor="none")} ax.text(0.2, 0.7, - # the \LaTeX macro exercises character sizing and placement, + # The \LaTeX macro exercises character sizing and placement, # \left[ ... \right\} draw some variable-height characters, - # \sqrt and \frac draw horizontal rules, \mathrm changes the font - r'\LaTeX\ $\left[\int\limits_e^{2e}' + # \sqrt and \frac draw horizontal rules, \mathrm changes the font, + # the minus sign hits character code 0 in the Type 1 font that LaTeX uses. + r'\LaTeX\ $\left[\int\limits_e^{-2e}' r'\sqrt\frac{\log^3 x}{x}\,\mathrm{d}x \right\}$', **kwargs) ax.text(0.2, 0.3, "lg", **kwargs) From 95f0ddd723cb8cb76b1bf011e16dcfb656119d77 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 26 Jun 2026 23:27:18 -0400 Subject: [PATCH 15/21] Backport PR #31940: Add loongarch64 image comparison tolerances --- lib/matplotlib/tests/test_inset.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/tests/test_inset.py b/lib/matplotlib/tests/test_inset.py index 81528580c723..bbf481c23253 100644 --- a/lib/matplotlib/tests/test_inset.py +++ b/lib/matplotlib/tests/test_inset.py @@ -93,8 +93,10 @@ def test_inset_indicator_zorder(): assert inset.get_zorder() == 42 -@image_comparison(['zoom_inset_connector_styles.png'], remove_text=True, style='mpl20', - tol=0.024 if platform.machine() in ['aarch64', 'arm64'] else 0) +@image_comparison(['zoom_inset_connector_styles.png'], + remove_text=True, style='mpl20', + tol=(0.024 if platform.machine() in ['aarch64', 'arm64', + 'loongarch64'] else 0)) def test_zoom_inset_connector_styles(): fig, axs = plt.subplots(2) for ax in axs: From 3ec62ff6a8d7297852481e460f8880004257c0dd Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 27 Jun 2026 07:20:58 +0200 Subject: [PATCH 16/21] Backport PR #31910: FIX: Add mtext into RendererBase._draw_as_path() arguments --- lib/matplotlib/backend_bases.py | 2 +- lib/matplotlib/tests/test_usetex.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 27c3752858a7..633ce987269d 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -506,7 +506,7 @@ def draw_tex(self, gc, x, y, s, prop, angle, *, mtext=None): mtext : `~matplotlib.text.Text` The original text object to be rendered. """ - self._draw_text_as_path(gc, x, y, s, prop, angle, ismath="TeX") + self._draw_text_as_path(gc, x, y, s, prop, angle, ismath="TeX", mtext=mtext) def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): """ diff --git a/lib/matplotlib/tests/test_usetex.py b/lib/matplotlib/tests/test_usetex.py index 87277f152789..7aa43a05d45b 100644 --- a/lib/matplotlib/tests/test_usetex.py +++ b/lib/matplotlib/tests/test_usetex.py @@ -43,6 +43,18 @@ def test_usetex(): ax.set_axis_off() +def test_usetex_fallback(monkeypatch): + # Smoke test that the base draw_tex implementation works. + from matplotlib.backend_bases import RendererBase + from matplotlib.backends.backend_agg import RendererAgg + monkeypatch.setattr(RendererAgg, 'draw_tex', RendererBase.draw_tex) + + plt.rcParams["text.usetex"] = True + fig, ax = plt.subplots() + ax.text(0, 0, "foo_bar") + fig.canvas.draw() + + @check_figures_equal(extensions=['png', 'pdf', 'svg']) def test_empty(fig_test, fig_ref): mpl.rcParams['text.usetex'] = True From 6091e12f54d6abd424f7fcfd0bfa8ba1491d0335 Mon Sep 17 00:00:00 2001 From: "Albert Y. Shih" Date: Mon, 29 Jun 2026 15:01:37 -0400 Subject: [PATCH 17/21] Backport PR #31969: Stop passing symlinks to ImageMagick --- lib/matplotlib/testing/compare.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/matplotlib/testing/compare.py b/lib/matplotlib/testing/compare.py index 2b94847a72b6..92547c3585f6 100644 --- a/lib/matplotlib/testing/compare.py +++ b/lib/matplotlib/testing/compare.py @@ -100,6 +100,9 @@ def _read_until(self, terminator): class _MagickConverter: def __call__(self, orig, dest): try: + # ImageMagick may not be permitted to follow a symlink, so resolve it + if orig.is_symlink(): + orig = orig.resolve() subprocess.run( [mpl._get_executable_info("magick").executable, orig, dest], check=True) From 578ebdf028cf805e2b4156cdd812f3238c730943 Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Tue, 30 Jun 2026 15:58:39 +0100 Subject: [PATCH 18/21] Backport PR #31932: FIX: include axis labels in get_tightbbox when not for_layout_only --- lib/matplotlib/axes/_base.py | 5 ++++- lib/matplotlib/tests/test_axes.py | 15 +++++++++++++ lib/mpl_toolkits/mplot3d/axes3d.py | 6 ++++-- lib/mpl_toolkits/mplot3d/tests/test_axes3d.py | 21 +++++++++++++++++++ 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 31da7cdd414d..edd93f9f3d52 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -4742,7 +4742,10 @@ def get_tightbbox(self, renderer=None, *, call_axes_locator=True, for axis in self._axis_map.values(): if self.axison and axis.get_visible(): - ba = martist._get_tightbbox_for_layout_only(axis, renderer) + if for_layout_only: + ba = martist._get_tightbbox_for_layout_only(axis, renderer) + else: + ba = axis.get_tightbbox(renderer) if ba: bb.append(ba) self._update_title_position(renderer) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index a1dce857b4ef..9e27e9ab0a16 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -8330,6 +8330,21 @@ def test_tick_padding_tightbbox(): assert bb.y0 < bb2.y0 +def test_tightbbox_includes_long_label(): + fig, ax = plt.subplots() + + renderer = fig._get_renderer() + bbox_no_xlabel = ax.get_tightbbox(renderer, for_layout_only=False) + + ax.set_xlabel( + 'loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong') + bbox_long_xlabel = ax.get_tightbbox(renderer, for_layout_only=False) + + # When for_layout_only is False, the axes tightbbox should encompass its labels even + # if they are long enough to extent beyond its limits. + assert bbox_long_xlabel.width > bbox_no_xlabel.width + + def test_inset(): """ Ensure that inset_ax argument is indeed optional diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index 2ce76acf49d3..d2c3e66bfe37 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -4167,8 +4167,10 @@ def get_tightbbox(self, renderer=None, *, call_axes_locator=True, if self._axis3don: for axis in self._axis_map.values(): if axis.get_visible(): - axis_bb = martist._get_tightbbox_for_layout_only( - axis, renderer) + if for_layout_only: + axis_bb = martist._get_tightbbox_for_layout_only(axis, renderer) + else: + axis_bb = axis.get_tightbbox(renderer=renderer) if axis_bb: batch.append(axis_bb) return mtransforms.Bbox.union(batch) diff --git a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py index 9d6b094ce005..e724f04c7875 100644 --- a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py +++ b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py @@ -3204,3 +3204,24 @@ def test_plot_surface_log_scale_invalid_values(): zmin, zmax = ax.get_zlim() assert 1e-3 < zmin < zmax < 1e3, f"zlim corrupted: {(zmin, zmax)}" + + +def test_axes3d_tightbbox_includes_axis_labels(): + fig = plt.figure() + ax = fig.add_subplot(projection='3d') + ax.scatter([1], [1], [1]) + + fig.draw_without_rendering() + renderer = fig._get_renderer() + bb_no_labels = ax.get_tightbbox(renderer) + + ax.set_xlabel('X label') + ax.set_ylabel('Y label') + ax.set_zlabel('Z label') + + fig.draw_without_rendering() + bb_full = ax.get_tightbbox(renderer) + + # The full bbox must be strictly larger in at least one dimension than the + # bbox not including labels. + assert bb_full.width > bb_no_labels.width or bb_full.height > bb_no_labels.height From ddf019d5bec0cdfc25c9bb5cd301fdbabdda8546 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 2 Jul 2026 13:38:48 -0400 Subject: [PATCH 19/21] Backport PR #31985: DOC: Fix broken configobj link in 0.99.x API changes --- doc/api/prev_api_changes/api_changes_0.99.x.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/prev_api_changes/api_changes_0.99.x.rst b/doc/api/prev_api_changes/api_changes_0.99.x.rst index 4736d066d43e..012e64550da7 100644 --- a/doc/api/prev_api_changes/api_changes_0.99.x.rst +++ b/doc/api/prev_api_changes/api_changes_0.99.x.rst @@ -67,7 +67,7 @@ Changes beyond 0.99.x required by the experimental traited config and are somewhat out of date. If needed, install them independently. -.. _configobj: http://www.voidspace.org.uk/python/configobj.html +.. _configobj: https://configobj.readthedocs.io/en/latest/ .. _`enthought.traits`: http://code.enthought.com/pages/traits.html * The new rc parameter ``savefig.extension`` sets the filename extension From 1a58546b77b746924e2a987cd2f0518e125eb010 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Tue, 7 Jul 2026 11:01:45 +0200 Subject: [PATCH 20/21] Backport PR #31994: Bump the actions group across 1 directory with 9 updates --- .github/workflows/autoclose_schedule.yml | 4 ++-- .github/workflows/cibuildwheel.yml | 10 +++++----- .github/workflows/circleci.yml | 2 +- .github/workflows/clean_pr.yml | 2 +- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/cygwin.yml | 10 +++++----- .github/workflows/linting.yml | 18 +++++++++--------- .github/workflows/mypy-stubtest.yml | 4 ++-- .github/workflows/tests.yml | 14 +++++++------- .github/workflows/wasm.yml | 6 +++--- .github/workflows/zizmor.yml | 4 ++-- 11 files changed, 40 insertions(+), 40 deletions(-) diff --git a/.github/workflows/autoclose_schedule.yml b/.github/workflows/autoclose_schedule.yml index a4eba770699c..006cb3dda986 100644 --- a/.github/workflows/autoclose_schedule.yml +++ b/.github/workflows/autoclose_schedule.yml @@ -22,10 +22,10 @@ jobs: name: autoclose labeled PRs runs-on: ubuntu-latest steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: '3.13' - name: Install PyGithub diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml index 8ef0add983e3..5618d0eb8764 100644 --- a/.github/workflows/cibuildwheel.yml +++ b/.github/workflows/cibuildwheel.yml @@ -42,12 +42,12 @@ jobs: SDIST_NAME: ${{ steps.sdist.outputs.SDIST_NAME }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: false - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 name: Install Python with: python-version: '3.11' @@ -125,7 +125,7 @@ jobs: run: Remove-Item -Recurse C:\Strawberry - name: Build wheels for CPython 3.14 - uses: pypa/cibuildwheel@8d2b08b68458a16aeb24b64e68a09ab1c8e82084 # v3.4.1 + uses: pypa/cibuildwheel@294735312765b09d24a2fbec22660ce817587d55 # v4.1.0 with: package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }} env: @@ -133,7 +133,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.13 - uses: pypa/cibuildwheel@8d2b08b68458a16aeb24b64e68a09ab1c8e82084 # v3.4.1 + uses: pypa/cibuildwheel@294735312765b09d24a2fbec22660ce817587d55 # v4.1.0 with: package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }} env: @@ -141,7 +141,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.12 - uses: pypa/cibuildwheel@8d2b08b68458a16aeb24b64e68a09ab1c8e82084 # v3.4.1 + uses: pypa/cibuildwheel@294735312765b09d24a2fbec22660ce817587d55 # v4.1.0 with: package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }} env: diff --git a/.github/workflows/circleci.yml b/.github/workflows/circleci.yml index 49dc4ea3b3ec..017bba79148d 100644 --- a/.github/workflows/circleci.yml +++ b/.github/workflows/circleci.yml @@ -31,7 +31,7 @@ jobs: runs-on: ubuntu-latest name: Post warnings/errors as review steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false diff --git a/.github/workflows/clean_pr.yml b/.github/workflows/clean_pr.yml index 75f6a451c7ee..acc1994e7a9c 100644 --- a/.github/workflows/clean_pr.yml +++ b/.github/workflows/clean_pr.yml @@ -11,7 +11,7 @@ jobs: contents: read steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: '0' persist-credentials: false diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3dc935180f6e..d312d60100ad 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: languages: ${{ matrix.language }} @@ -45,4 +45,4 @@ jobs: pip install --user -v . - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml index 4b790ea52a7d..02636954b8cf 100644 --- a/.github/workflows/cygwin.yml +++ b/.github/workflows/cygwin.yml @@ -80,12 +80,12 @@ jobs: - name: Fix line endings run: git config --global core.autocrlf input - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: false - - uses: cygwin/cygwin-install-action@711d29f3da23c9f4a1798e369a6f01198c13b11a # v6 + - uses: cygwin/cygwin-install-action@3f0a3f9f988f7e96b8c18098ae05eaec175f5b52 # v6 with: packages: >- ccache gcc-g++ gdb git graphviz libcairo-devel libffi-devel @@ -141,21 +141,21 @@ jobs: # FreeType build fails with bash, succeeds with dash - name: Cache pip - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: C:\cygwin\home\runneradmin\.cache\pip key: Cygwin-py3.${{ matrix.python-minor-version }}-pip-${{ hashFiles('pyproject.toml') }} restore-keys: ${{ matrix.os }}-py3.${{ matrix.python-minor-version }}-pip- - name: Cache ccache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: C:\cygwin\home\runneradmin\.ccache key: Cygwin-py3.${{ matrix.python-minor-version }}-ccache-${{ hashFiles('src/*') }} restore-keys: Cygwin-py3.${{ matrix.python-minor-version }}-ccache- - name: Cache Matplotlib - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: | C:\cygwin\home\runneradmin\.cache\matplotlib diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 5a9f8ff34aa8..1f68ff3a9e86 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -11,11 +11,11 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: false - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.x" - uses: j178/prek-action@bdca6f102f98e2b4c7029491a53dfd366469e33d # v2.0.4 @@ -29,12 +29,12 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python 3 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: '3.11' @@ -59,12 +59,12 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python 3 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: '3.11' @@ -90,12 +90,12 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python 3 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: '3.14' @@ -122,7 +122,7 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false diff --git a/.github/workflows/mypy-stubtest.yml b/.github/workflows/mypy-stubtest.yml index 81fcd48462e8..2c78aaf08bc4 100644 --- a/.github/workflows/mypy-stubtest.yml +++ b/.github/workflows/mypy-stubtest.yml @@ -12,12 +12,12 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python 3 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: '3.11' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9214e80ea8e7..34861a727a75 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -97,13 +97,13 @@ jobs: pygobject-ver: '<3.52.0' steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: false - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.python-version }} allow-prereleases: true @@ -186,7 +186,7 @@ jobs: esac - name: Cache pip - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 if: startsWith(runner.os, 'Linux') with: path: ~/.cache/pip @@ -196,7 +196,7 @@ jobs: restore-keys: | ${{ matrix.os }}-py${{ matrix.python-version }}-pip- - name: Cache pip - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 if: startsWith(runner.os, 'macOS') with: path: ~/Library/Caches/pip @@ -204,7 +204,7 @@ jobs: restore-keys: | ${{ matrix.os }}-py${{ matrix.python-version }}-pip- - name: Cache ccache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: | ~/.ccache @@ -212,7 +212,7 @@ jobs: restore-keys: | ${{ matrix.os }}-py${{ matrix.python-version }}-ccache- - name: Cache Matplotlib - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: | ~/.cache/matplotlib @@ -396,7 +396,7 @@ jobs: fi - name: Upload code coverage if: ${{ !cancelled() && github.event_name != 'schedule' }} - uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: name: "${{ matrix.python-version }} ${{ matrix.os }} ${{ matrix.name-suffix }}" token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index e1668d99af60..af6cfa5ee3a1 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -39,18 +39,18 @@ jobs: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: false - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 name: Install Python with: python-version: '3.13' - name: Build wheels for wasm - uses: pypa/cibuildwheel@8d2b08b68458a16aeb24b64e68a09ab1c8e82084 # v3.4.1 + uses: pypa/cibuildwheel@294735312765b09d24a2fbec22660ce817587d55 # v4.1.0 env: CIBW_BUILD: "cp312-*" CIBW_PLATFORM: "pyodide" diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index f6e77b3d6000..c276e7a42548 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -22,9 +22,9 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Run zizmor - uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 + uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7 From 10f9bd80e493c16aec99e964d3aa7a28e3072e68 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Tue, 7 Jul 2026 07:38:03 -0700 Subject: [PATCH 21/21] Backport PR #32009: DOC: Fix outdated text in image_resampling example --- .../images_contours_and_fields/image_antialiasing.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/galleries/examples/images_contours_and_fields/image_antialiasing.py b/galleries/examples/images_contours_and_fields/image_antialiasing.py index 10f563875767..5d3c2f81b843 100644 --- a/galleries/examples/images_contours_and_fields/image_antialiasing.py +++ b/galleries/examples/images_contours_and_fields/image_antialiasing.py @@ -63,7 +63,7 @@ # # ``interpolation_stage='data'``: Data -> Interpolate/Resample -> Normalize -> RGBA # -# For both keyword arguments, Matplotlib has a default "antialiased", that is +# For both keyword arguments, Matplotlib has a default "auto", that is # recommended for most situations, and is described below. Note that this # default behaves differently if the image is being down- or up-sampled, as # described below. @@ -166,12 +166,12 @@ # %% # A final example shows the desirability of performing the anti-aliasing at the # RGBA stage when using non-trivial interpolation kernels. In the following, -# the data in the upper 100 rows is exactly 0.0, and data in the inner circle +# the data in the outer circle is exactly 0.0, and data in the inner circle # is exactly 2.0. If we perform the *interpolation_stage* in 'data' space and # use an anti-aliasing filter (first panel), then floating point imprecision # makes some of the data values just a bit less than zero or a bit more than # 2.0, and they get assigned the under- or over- colors. This can be avoided if -# you do not use an anti-aliasing filter (*interpolation* set set to +# you do not use an anti-aliasing filter (*interpolation* set to # 'nearest'), however, that makes the part of the data susceptible to Moiré # patterns much worse (second panel). Therefore, we recommend the default # *interpolation* of 'hanning'/'auto', and *interpolation_stage* of