From 6e13c086c8893d26954a2337d6ddcecd25e69566 Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Wed, 26 Mar 2025 19:57:10 -0600 Subject: [PATCH 01/19] Backport PR #29810: Declare free-threaded support in MacOS backend extension --- src/_macosx.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/_macosx.m b/src/_macosx.m index c8e2cea43863..1372157bc80d 100755 --- a/src/_macosx.m +++ b/src/_macosx.m @@ -1895,6 +1895,9 @@ - (void)flagsChanged:(NSEvent *)event Py_XDECREF(m); return NULL; } +#ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED); +#endif return m; } From a76759397c40b09d18a13b0ea4d4d993bcbd40ee Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Wed, 22 Oct 2025 22:36:37 +0200 Subject: [PATCH 02/19] Backport PR #30672: Use pathlib.Path instead of matplotlib.path.Path in text.pyi --- lib/matplotlib/text.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/text.pyi b/lib/matplotlib/text.pyi index d65a3dc4c7da..fc1ab1c416cf 100644 --- a/lib/matplotlib/text.pyi +++ b/lib/matplotlib/text.pyi @@ -2,7 +2,7 @@ from .artist import Artist from .backend_bases import RendererBase from .font_manager import FontProperties from .offsetbox import DraggableAnnotation -from .path import Path +from pathlib import Path from .patches import FancyArrowPatch, FancyBboxPatch from .textpath import ( # noqa: F401, reexported API TextPath as TextPath, From b843483d308ce1f8bb94e1449bdb2b77da9a327c Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 21 Oct 2025 03:55:51 -0400 Subject: [PATCH 03/19] Backport PR #30657: Fix `AttributeError: module 'gi' has no attribute 'require_version'` --- lib/matplotlib/backends/backend_gtk3.py | 4 ++-- lib/matplotlib/backends/backend_gtk4.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/backends/backend_gtk3.py b/lib/matplotlib/backends/backend_gtk3.py index 888f5a770f5d..c27b57e36a0a 100644 --- a/lib/matplotlib/backends/backend_gtk3.py +++ b/lib/matplotlib/backends/backend_gtk3.py @@ -10,14 +10,14 @@ CloseEvent, KeyEvent, LocationEvent, MouseEvent, ResizeEvent) try: - import gi + from gi import require_version as gi_require_version except ImportError as err: raise ImportError("The GTK3 backends require PyGObject") from err try: # :raises ValueError: If module/version is already loaded, already # required, or unavailable. - gi.require_version("Gtk", "3.0") + gi_require_version("Gtk", "3.0") except ValueError as e: # in this case we want to re-raise as ImportError so the # auto-backend selection logic correctly skips. diff --git a/lib/matplotlib/backends/backend_gtk4.py b/lib/matplotlib/backends/backend_gtk4.py index cd38968779ed..e3d3548c1cd1 100644 --- a/lib/matplotlib/backends/backend_gtk4.py +++ b/lib/matplotlib/backends/backend_gtk4.py @@ -9,19 +9,20 @@ KeyEvent, LocationEvent, MouseEvent, ResizeEvent, CloseEvent) try: - import gi + from gi import require_version as gi_require_version except ImportError as err: raise ImportError("The GTK4 backends require PyGObject") from err try: # :raises ValueError: If module/version is already loaded, already # required, or unavailable. - gi.require_version("Gtk", "4.0") + gi_require_version("Gtk", "4.0") except ValueError as e: # in this case we want to re-raise as ImportError so the # auto-backend selection logic correctly skips. raise ImportError(e) from e +import gi from gi.repository import Gio, GLib, Gtk, Gdk, GdkPixbuf from . import _backend_gtk from ._backend_gtk import ( # noqa: F401 # pylint: disable=W0611 From c57123f2dc895ee24893d33724d6765769d86b85 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Mon, 27 Oct 2025 17:58:20 +0100 Subject: [PATCH 04/19] Backport PR #30687: DOC: Fix pip link --- doc/install/dependencies.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/dependencies.rst b/doc/install/dependencies.rst index 95d170a06b00..4a2ace7f9883 100644 --- a/doc/install/dependencies.rst +++ b/doc/install/dependencies.rst @@ -220,7 +220,7 @@ Build dependencies Python ------ -``pip`` normally builds packages using :external+pip:doc:`build isolation `, +``pip`` normally builds packages using :external+pip:doc:`build isolation `, which means that ``pip`` installs the dependencies listed here for the duration of the build process. However, build isolation is disabled via the the :external+pip:ref:`--no-build-isolation ` flag From 72a01fe0e3611402dbc73d0e1236ef5397707b11 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Mon, 27 Oct 2025 17:58:20 +0100 Subject: [PATCH 05/19] Backport PR #30687: DOC: Fix pip link --- doc/install/dependencies.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/dependencies.rst b/doc/install/dependencies.rst index 95d170a06b00..4a2ace7f9883 100644 --- a/doc/install/dependencies.rst +++ b/doc/install/dependencies.rst @@ -220,7 +220,7 @@ Build dependencies Python ------ -``pip`` normally builds packages using :external+pip:doc:`build isolation `, +``pip`` normally builds packages using :external+pip:doc:`build isolation `, which means that ``pip`` installs the dependencies listed here for the duration of the build process. However, build isolation is disabled via the the :external+pip:ref:`--no-build-isolation ` flag From c1feb9dbfce97114e7b837145dc44ded2df42393 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Wed, 29 Oct 2025 00:50:48 +0100 Subject: [PATCH 06/19] Backport PR #30698: BLD: update trove metadata to support py3.14 --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 25f4ce8d4948..23c441b52c9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,7 @@ classifiers=[ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Scientific/Engineering :: Visualization", ] From da641b3ed334b087bf6ef226cd89f6d6bf16ac19 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 28 Oct 2025 21:05:25 -0400 Subject: [PATCH 07/19] Backport PR #30624: TST: Increase tolerances for Ghostscript 10.06 --- lib/matplotlib/tests/test_bbox_tight.py | 2 +- lib/matplotlib/tests/test_image.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/tests/test_bbox_tight.py b/lib/matplotlib/tests/test_bbox_tight.py index 7a2809931757..9965c914daa4 100644 --- a/lib/matplotlib/tests/test_bbox_tight.py +++ b/lib/matplotlib/tests/test_bbox_tight.py @@ -108,7 +108,7 @@ def test_bbox_inches_tight_clipping(): plt.gcf().artists.append(patch) -@image_comparison(['bbox_inches_tight_raster'], +@image_comparison(['bbox_inches_tight_raster'], tol=0.15, # For Ghostscript 10.06+. remove_text=True, savefig_kwarg={'bbox_inches': 'tight'}) def test_bbox_inches_tight_raster(): """Test rasterization with tight_layout""" diff --git a/lib/matplotlib/tests/test_image.py b/lib/matplotlib/tests/test_image.py index 5373ed121560..0d1d30291328 100644 --- a/lib/matplotlib/tests/test_image.py +++ b/lib/matplotlib/tests/test_image.py @@ -37,7 +37,7 @@ def test_alpha_interp(): axr.imshow(img, interpolation="bilinear") -@image_comparison(['interp_nearest_vs_none'], +@image_comparison(['interp_nearest_vs_none'], tol=3.7, # For Ghostscript 10.06+. extensions=['pdf', 'svg'], remove_text=True) def test_interp_nearest_vs_none(): """Test the effect of "nearest" and "none" interpolation""" From 5b8e219d70f1daa443330eb6a5a6211506b37362 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sat, 16 Nov 2024 04:22:48 -0500 Subject: [PATCH 08/19] TST: Run macosx backends in a subprocess In the macosx backend, `event_loop_is_running` returns true after `lazy_init` is called, which happens in the `new` constructor for _any_ class. This means it is "running" as soon as a figure is created, and this will block any other backend tests. --- lib/matplotlib/tests/test_backend_macosx.py | 45 +++++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/lib/matplotlib/tests/test_backend_macosx.py b/lib/matplotlib/tests/test_backend_macosx.py index 8e50ddf84024..fe4c9a6fba3c 100644 --- a/lib/matplotlib/tests/test_backend_macosx.py +++ b/lib/matplotlib/tests/test_backend_macosx.py @@ -1,18 +1,18 @@ import os +from pathlib import Path import pytest from unittest import mock import matplotlib as mpl import matplotlib.pyplot as plt -try: - from matplotlib.backends import _macosx -except ImportError: - pytest.skip("These are mac only tests", allow_module_level=True) +from matplotlib.testing import subprocess_run_helper -@pytest.mark.backend('macosx') -def test_cached_renderer(): +_test_timeout = 60 + + +def _test_cached_renderer(): # Make sure that figures have an associated renderer after # a fig.canvas.draw() call fig = plt.figure(1) @@ -24,8 +24,14 @@ def test_cached_renderer(): assert fig.canvas.get_renderer()._renderer is not None -@pytest.mark.backend('macosx') -def test_savefig_rcparam(monkeypatch, tmp_path): +@pytest.mark.backend('macosx', skip_on_importerror=True) +def test_cached_renderer(): + subprocess_run_helper(_test_cached_renderer, timeout=_test_timeout, + extra_env={"MPLBACKEND": "macosx"}) + + +def _test_savefig_rcparam(): + tmp_path = Path(os.environ["TEST_SAVEFIG_PATH"]) def new_choose_save_file(title, directory, filename): # Replacement function instead of opening a GUI window @@ -34,9 +40,10 @@ def new_choose_save_file(title, directory, filename): os.makedirs(f"{directory}/test") return f"{directory}/test/{filename}" - monkeypatch.setattr(_macosx, "choose_save_file", new_choose_save_file) fig = plt.figure() - with mpl.rc_context({"savefig.directory": tmp_path}): + with (mock.patch("matplotlib.backends._macosx.choose_save_file", + new_choose_save_file), + mpl.rc_context({"savefig.directory": tmp_path})): fig.canvas.toolbar.save_figure() # Check the saved location got created save_file = f"{tmp_path}/test/{fig.canvas.get_default_filename()}" @@ -47,14 +54,20 @@ def new_choose_save_file(title, directory, filename): assert mpl.rcParams["savefig.directory"] == f"{tmp_path}/test" -@pytest.mark.backend('macosx') +@pytest.mark.backend('macosx', skip_on_importerror=True) +def test_savefig_rcparam(tmp_path): + subprocess_run_helper( + _test_savefig_rcparam, timeout=_test_timeout, + extra_env={"MPLBACKEND": "macosx", "TEST_SAVEFIG_PATH": tmp_path}) + + +@pytest.mark.backend('macosx', skip_on_importerror=True) def test_ipython(): from matplotlib.testing import ipython_in_subprocess ipython_in_subprocess("osx", {(8, 24): "macosx", (7, 0): "MacOSX"}) -@pytest.mark.backend('macosx') -def test_save_figure_return(): +def _test_save_figure_return(): fig, ax = plt.subplots() ax.imshow([[1]]) prop = "matplotlib.backends._macosx.choose_save_file" @@ -65,3 +78,9 @@ def test_save_figure_return(): with mock.patch(prop, return_value=None): fname = fig.canvas.manager.toolbar.save_figure() assert fname is None + + +@pytest.mark.backend('macosx', skip_on_importerror=True) +def test_save_figure_return(): + subprocess_run_helper(_test_save_figure_return, timeout=_test_timeout, + extra_env={"MPLBACKEND": "macosx"}) From 134000ba19a4354da2ad1084627039e05c936754 Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Fri, 31 Oct 2025 06:09:02 -0600 Subject: [PATCH 09/19] Merge pull request #30697 from ngoldbaum/fix-plotting-on-worker-threads BUG: raise when creating a MacOS FigureManager outside the main thread (cherry picked from commit 94def4ee50ce92ce96461f269e0c79c188588610) --- lib/matplotlib/tests/test_backend_macosx.py | 23 +++++++++++++++++++++ src/_macosx.m | 10 +++++++++ 2 files changed, 33 insertions(+) diff --git a/lib/matplotlib/tests/test_backend_macosx.py b/lib/matplotlib/tests/test_backend_macosx.py index fe4c9a6fba3c..0648e43cde94 100644 --- a/lib/matplotlib/tests/test_backend_macosx.py +++ b/lib/matplotlib/tests/test_backend_macosx.py @@ -1,4 +1,5 @@ import os +import threading from pathlib import Path import pytest @@ -84,3 +85,25 @@ def _test_save_figure_return(): def test_save_figure_return(): subprocess_run_helper(_test_save_figure_return, timeout=_test_timeout, extra_env={"MPLBACKEND": "macosx"}) + + +def _test_create_figure_on_worker_thread_fails(): + def create_figure(): + warn_msg = "Matplotlib GUI outside of the main thread will likely fail." + err_msg = "Cannot create a GUI FigureManager outside the main thread" + with pytest.warns(UserWarning, match=warn_msg): + with pytest.raises(RuntimeError, match=err_msg): + plt.gcf() + + worker = threading.Thread(target=create_figure) + worker.start() + worker.join() + + +@pytest.mark.backend('macosx', skip_on_importerror=True) +def test_create_figure_on_worker_thread_fails(): + subprocess_run_helper( + _test_create_figure_on_worker_thread_fails, + timeout=_test_timeout, + extra_env={"MPLBACKEND": "macosx"} + ) diff --git a/src/_macosx.m b/src/_macosx.m index 1372157bc80d..fcc221cf6fd5 100755 --- a/src/_macosx.m +++ b/src/_macosx.m @@ -580,6 +580,16 @@ bool mpl_check_modifier(bool present, PyObject* list, char const* name) static PyObject* FigureManager_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { + if (![NSThread isMainThread]) { + PyErr_SetString( + PyExc_RuntimeError, + "Cannot create a GUI FigureManager outside the main thread " + "using the MacOS backend. Use a non-interactive " + "backend like 'agg' to make plots on worker threads." + ); + return NULL; + } + lazy_init(); Window* window = [Window alloc]; if (!window) { return NULL; } From d300769285e2c920804134e40ec83837eabe16d8 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 2 Nov 2025 15:49:16 +0100 Subject: [PATCH 10/19] Backport PR #30714: FIX: Gracefully handle numpy arrays as input to check_in_list() --- lib/matplotlib/_api/__init__.py | 16 +++++++++++++++- lib/matplotlib/tests/test_api.py | 5 +++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/_api/__init__.py b/lib/matplotlib/_api/__init__.py index 22b58b62ff8e..1fc1aeb49e8f 100644 --- a/lib/matplotlib/_api/__init__.py +++ b/lib/matplotlib/_api/__init__.py @@ -106,6 +106,9 @@ def check_in_list(values, /, *, _print_supported_values=True, **kwargs): ---------- values : iterable Sequence of values to check on. + + Note: All values must support == comparisons. + This means in particular the entries must not be numpy arrays. _print_supported_values : bool, default: True Whether to print *values* when raising ValueError. **kwargs : dict @@ -123,7 +126,18 @@ def check_in_list(values, /, *, _print_supported_values=True, **kwargs): if not kwargs: raise TypeError("No argument to check!") for key, val in kwargs.items(): - if val not in values: + try: + exists = val in values + except ValueError: + # `in` internally uses `val == values[i]`. There are some objects + # that do not support == to arbitrary other objects, in particular + # numpy arrays. + # Since such objects are not allowed in values, we can gracefully + # handle the case that val (typically provided by users) is of such + # type and directly state it's not in the list instead of letting + # the individual `val == values[i]` ValueError surface. + exists = False + if not exists: msg = f"{val!r} is not a valid value for {key}" if _print_supported_values: msg += f"; supported values are {', '.join(map(repr, values))}" diff --git a/lib/matplotlib/tests/test_api.py b/lib/matplotlib/tests/test_api.py index f04604c14cce..81b7f9cdc96c 100644 --- a/lib/matplotlib/tests/test_api.py +++ b/lib/matplotlib/tests/test_api.py @@ -150,3 +150,8 @@ def f() -> None: def test_empty_check_in_list() -> None: with pytest.raises(TypeError, match="No argument to check!"): _api.check_in_list(["a"]) + + +def test_check_in_list_numpy() -> None: + with pytest.raises(ValueError, match=r"array\(5\) is not a valid value"): + _api.check_in_list(['a', 'b'], value=np.array(5)) From 86b38d3f29aa2af2ddcbd1895433117caa0fba47 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Wed, 12 Nov 2025 19:45:06 -0600 Subject: [PATCH 11/19] Github stats v3.10.8 --- doc/users/github_stats.rst | 55 +++++++------- .../prev_whats_new/github_stats_3.10.7.rst | 74 +++++++++++++++++++ 2 files changed, 103 insertions(+), 26 deletions(-) create mode 100644 doc/users/prev_whats_new/github_stats_3.10.7.rst diff --git a/doc/users/github_stats.rst b/doc/users/github_stats.rst index c40bedb4cb5b..8d93759ac756 100644 --- a/doc/users/github_stats.rst +++ b/doc/users/github_stats.rst @@ -1,19 +1,18 @@ .. _github-stats: -GitHub statistics for 3.10.7 (Oct 08, 2025) +GitHub statistics for 3.10.8 (Nov 12, 2025) =========================================== -GitHub statistics for 2024/12/14 (tag: v3.10.0) - 2025/10/08 +GitHub statistics for 2024/12/14 (tag: v3.10.0) - 2025/11/12 These lists are automatically generated, and may be incomplete or contain duplicates. We closed 4 issues and merged 16 pull requests. -The full list can be seen `on GitHub `__ +The full list can be seen `on GitHub `__ -The following 32 authors contributed 422 commits. +The following 35 authors contributed 445 commits. * Aasma Gupta -* AASMA GUPTA * Antony Lee * Christine P. Chai * David Stansby @@ -22,6 +21,7 @@ The following 32 authors contributed 422 commits. * G.D. McBain * Greg Lucas * hannah +* heinrich5991 * hu-xiaonan * Ian Thomas * Inês Cachola @@ -29,19 +29,22 @@ The following 32 authors contributed 422 commits. * Jouni K. Seppänen * Khushi_29 * Kyle Sunden +* Lucas Gruwez * Lumberbot (aka Jack) * N R Navaneet * Nathan G. Wiseman +* Nathan Goldbaum +* Nick Coish * Oscar Gustafsson * Praful Gulani * Qian Zhang +* Rafael Katri * Raphael Erik Hviding * Roman * Ruth Comer * saikarna913 * Scott Shambaugh * Thomas A Caswell -* Tim Heap * Tim Hoffmann * Trygve Magnus Ræder @@ -49,29 +52,29 @@ GitHub issues and pull requests: Pull Requests (16): -* :ghpull:`30628`: Backport PR #30626 on branch v3.10.x (MNT: Fix new F401 unused imports warnings) -* :ghpull:`30626`: MNT: Fix new F401 unused imports warnings -* :ghpull:`30589`: Backport PR #29745: Use PEP8 style method and function names from -* :ghpull:`30614`: Backport PR #30612 on branch v3.10.x (MNT: update black pin) -* :ghpull:`30612`: MNT: update black pin -* :ghpull:`30572`: Backport PR #30571 on branch v3.10.x (CI: remove macos13) -* :ghpull:`30571`: CI: remove macos13 -* :ghpull:`30570`: Backport PR #30558 on branch v3.10.x (Fix stubtest with mypy 18) -* :ghpull:`30558`: Fix stubtest with mypy 18 -* :ghpull:`30540`: Backport PR #30539 on branch v3.10.x (Fix scale_unit/scale_units typo in quiver docs) -* :ghpull:`30539`: Fix scale_unit/scale_units typo in quiver docs -* :ghpull:`30518`: Backport PR #30497 on branch v3.10.x (TST: Use a temporary directory for test_save_figure_return) -* :ghpull:`30497`: TST: Use a temporary directory for test_save_figure_return -* :ghpull:`30506`: Backport PR #30490 on branch v3.10.x (Fix SVG rendering error in def update_background) -* :ghpull:`30490`: Fix SVG rendering error in def update_background -* :ghpull:`30494`: Backport PR #30492 on branch v3.10.x (DOC: pytz link should be from PyPI) +* :ghpull:`30717`: Backport PR #30714 on branch v3.10.x (FIX: Gracefully handle numpy arrays as input to check_in_list()) +* :ghpull:`30714`: FIX: Gracefully handle numpy arrays as input to check_in_list() +* :ghpull:`30560`: Consistent zoom boxes +* :ghpull:`30711`: Backport PR #30697 on branch v3.10.x (BUG: raise when creating a MacOS FigureManager outside the main thread) +* :ghpull:`30697`: BUG: raise when creating a MacOS FigureManager outside the main thread +* :ghpull:`30656`: Backport PR #29810 on branch v3.10.x (Declare free-threaded support in MacOS backend extension) +* :ghpull:`30702`: Backport PR #30624 on branch v3.10.x (TST: Increase tolerances for Ghostscript 10.06) +* :ghpull:`30700`: Backport PR #30698 on branch v3.10.x (BLD: update trove metadata to support py3.14) +* :ghpull:`30624`: TST: Increase tolerances for Ghostscript 10.06 +* :ghpull:`30698`: BLD: update trove metadata to support py3.14 +* :ghpull:`30688`: Backport PR #30687 on branch v3.10.x (DOC: Fix pip link) +* :ghpull:`30675`: Backport PR #30657 on branch v3.10.x (Fix AttributeError: module 'gi' has no attribute 'require_version') +* :ghpull:`30674`: Backport PR #30672 on branch v3.10.x (Use pathlib.Path instead of matplotlib.path.Path in text.pyi) +* :ghpull:`30672`: Use pathlib.Path instead of matplotlib.path.Path in text.pyi +* :ghpull:`30657`: Fix ``AttributeError: module 'gi' has no attribute 'require_version'`` +* :ghpull:`29810`: Declare free-threaded support in MacOS backend extension Issues (4): -* :ghissue:`30611`: [MNT]: black version -* :ghissue:`30551`: [Bug]: Mypy stubtest failure on disjoint_base -* :ghissue:`30493`: [Bug]: test_save_figure_return seems flaky -* :ghissue:`30485`: [Bug]: figures with SpanSelector(..., useblit=True) can't be saved to SVG or PDF +* :ghissue:`30706`: [Bug]: Axes.grouped_bar() with non-string orientation (e.g., NumPy array) raises ambiguous truth-value error instead of clean ValueError +* :ghissue:`30666`: [Bug]: calling pyplot.gca() outside the main thread crashes the interpreter with the MacOS backend +* :ghissue:`30669`: [Bug]: Type hint for fontproperties keyword in text.pyi is wrong +* :ghissue:`30654`: [Bug]: error plotting: AttributeError: module 'gi' has no attribute 'require_version' Previous GitHub statistics diff --git a/doc/users/prev_whats_new/github_stats_3.10.7.rst b/doc/users/prev_whats_new/github_stats_3.10.7.rst new file mode 100644 index 000000000000..8c12e4050219 --- /dev/null +++ b/doc/users/prev_whats_new/github_stats_3.10.7.rst @@ -0,0 +1,74 @@ +.. _github-stats_3-10-7: + +GitHub statistics for 3.10.7 (Oct 08, 2025) +=========================================== + +GitHub statistics for 2024/12/14 (tag: v3.10.0) - 2025/10/08 + +These lists are automatically generated, and may be incomplete or contain duplicates. + +We closed 4 issues and merged 16 pull requests. +The full list can be seen `on GitHub `__ + +The following 32 authors contributed 422 commits. + +* Aasma Gupta +* AASMA GUPTA +* Antony Lee +* Christine P. Chai +* David Stansby +* dependabot[bot] +* Elliott Sales de Andrade +* G.D. McBain +* Greg Lucas +* hannah +* hu-xiaonan +* Ian Thomas +* Inês Cachola +* Jody Klymak +* Jouni K. Seppänen +* Khushi_29 +* Kyle Sunden +* Lumberbot (aka Jack) +* N R Navaneet +* Nathan G. Wiseman +* Oscar Gustafsson +* Praful Gulani +* Qian Zhang +* Raphael Erik Hviding +* Roman +* Ruth Comer +* saikarna913 +* Scott Shambaugh +* Thomas A Caswell +* Tim Heap +* Tim Hoffmann +* Trygve Magnus Ræder + +GitHub issues and pull requests: + +Pull Requests (16): + +* :ghpull:`30628`: Backport PR #30626 on branch v3.10.x (MNT: Fix new F401 unused imports warnings) +* :ghpull:`30626`: MNT: Fix new F401 unused imports warnings +* :ghpull:`30589`: Backport PR #29745: Use PEP8 style method and function names from +* :ghpull:`30614`: Backport PR #30612 on branch v3.10.x (MNT: update black pin) +* :ghpull:`30612`: MNT: update black pin +* :ghpull:`30572`: Backport PR #30571 on branch v3.10.x (CI: remove macos13) +* :ghpull:`30571`: CI: remove macos13 +* :ghpull:`30570`: Backport PR #30558 on branch v3.10.x (Fix stubtest with mypy 18) +* :ghpull:`30558`: Fix stubtest with mypy 18 +* :ghpull:`30540`: Backport PR #30539 on branch v3.10.x (Fix scale_unit/scale_units typo in quiver docs) +* :ghpull:`30539`: Fix scale_unit/scale_units typo in quiver docs +* :ghpull:`30518`: Backport PR #30497 on branch v3.10.x (TST: Use a temporary directory for test_save_figure_return) +* :ghpull:`30497`: TST: Use a temporary directory for test_save_figure_return +* :ghpull:`30506`: Backport PR #30490 on branch v3.10.x (Fix SVG rendering error in def update_background) +* :ghpull:`30490`: Fix SVG rendering error in def update_background +* :ghpull:`30494`: Backport PR #30492 on branch v3.10.x (DOC: pytz link should be from PyPI) + +Issues (4): + +* :ghissue:`30611`: [MNT]: black version +* :ghissue:`30551`: [Bug]: Mypy stubtest failure on disjoint_base +* :ghissue:`30493`: [Bug]: test_save_figure_return seems flaky +* :ghissue:`30485`: [Bug]: figures with SpanSelector(..., useblit=True) can't be saved to SVG or PDF From 0b9ebb35f8310f22eb7f932b2ae14befb1f40b6f Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Wed, 12 Nov 2025 19:49:57 -0600 Subject: [PATCH 12/19] Doc release prep v3.10.8 --- doc/_static/switcher.json | 2 +- doc/users/release_notes.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/_static/switcher.json b/doc/_static/switcher.json index 3912afd8a17d..36e743db21b8 100644 --- a/doc/_static/switcher.json +++ b/doc/_static/switcher.json @@ -1,7 +1,7 @@ [ { "name": "3.10 (stable)", - "version": "3.10.7", + "version": "3.10.8", "url": "https://matplotlib.org/stable/", "preferred": true }, diff --git a/doc/users/release_notes.rst b/doc/users/release_notes.rst index ea0541d5f04b..dbdcd61437ac 100644 --- a/doc/users/release_notes.rst +++ b/doc/users/release_notes.rst @@ -22,6 +22,7 @@ Version 3.10 ../api/prev_api_changes/api_changes_3.10.1.rst ../api/prev_api_changes/api_changes_3.10.0.rst github_stats.rst + prev_whats_new/github_stats_3.10.7.rst prev_whats_new/github_stats_3.10.6.rst prev_whats_new/github_stats_3.10.5.rst prev_whats_new/github_stats_3.10.3.rst From 1392cbe3c79cdb93f9282747841d648770f60249 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Wed, 12 Nov 2025 20:07:31 -0600 Subject: [PATCH 13/19] REL: v3.10.8 This is a bugfix release in the 3.10.x series. The primary highlights of this release are: - Properly allow freethreaded mode in the MacOS backend - Better error handling for MacOS backend From e4b804a11af4c65faeb0618f53672ecde06f4e09 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Wed, 12 Nov 2025 20:10:50 -0600 Subject: [PATCH 14/19] REL: Bump from v3.10.8 tag From 3f937281e87b68f3a42ca178db67d9a677a0a332 Mon Sep 17 00:00:00 2001 From: "Lumberbot (aka Jack)" <39504233+meeseeksmachine@users.noreply.github.com> Date: Tue, 25 Nov 2025 17:30:44 +0100 Subject: [PATCH 15/19] Backport PR #30788: Fix typo in key-mapping for "f11" (#30791) Co-authored-by: Ruth Comer <10599679+rcomer@users.noreply.github.com> --- lib/matplotlib/backends/backend_qt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/backends/backend_qt.py b/lib/matplotlib/backends/backend_qt.py index d0aded5fff63..dd642ba838af 100644 --- a/lib/matplotlib/backends/backend_qt.py +++ b/lib/matplotlib/backends/backend_qt.py @@ -55,7 +55,7 @@ ("Key_F8", "f8"), ("Key_F9", "f9"), ("Key_F10", "f10"), - ("Key_F10", "f11"), + ("Key_F11", "f11"), ("Key_F12", "f12"), ("Key_Super_L", "super"), ("Key_Super_R", "super"), From 6a38e4e0725f5ca0310c098d674edce3f5947d5f Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Sat, 29 Nov 2025 21:19:05 +0000 Subject: [PATCH 16/19] Backport PR #30763: DOC: Add example how to align tick labels --- galleries/examples/ticks/align_ticklabels.py | 32 ++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 galleries/examples/ticks/align_ticklabels.py diff --git a/galleries/examples/ticks/align_ticklabels.py b/galleries/examples/ticks/align_ticklabels.py new file mode 100644 index 000000000000..ec36e0db4d07 --- /dev/null +++ b/galleries/examples/ticks/align_ticklabels.py @@ -0,0 +1,32 @@ +""" +================= +Align tick labels +================= + +By default, tick labels are aligned towards the axis. This means the set of +*y* tick labels appear right-aligned. Because the alignment reference point +is on the axis, left-aligned tick labels would overlap the plotting area. +To achieve a good-looking left-alignment, you have to additionally increase +the padding. +""" +import matplotlib.pyplot as plt + +population = { + "Sydney": 5.2, + "Mexico City": 8.8, + "São Paulo": 12.2, + "Istanbul": 15.9, + "Lagos": 15.9, + "Shanghai": 21.9, +} + +fig, ax = plt.subplots(layout="constrained") +ax.barh(population.keys(), population.values()) +ax.set_xlabel('Population (in millions)') + +# left-align all ticklabels +for ticklabel in ax.get_yticklabels(): + ticklabel.set_horizontalalignment("left") + +# increase padding +ax.tick_params("y", pad=70) From ce645296e2ce963e85d254e869238c200635d7be Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sun, 7 Dec 2025 15:30:40 +0100 Subject: [PATCH 17/19] Backport PR #30817: Update sphinx-gallery header patch --- doc/conf.py | 2 +- lib/matplotlib/tests/test_doc.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 96738492b68b..03df9340e66c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -364,7 +364,7 @@ def gallery_image_warning_filter(record): :class: sphx-glr-download-link-note :ref:`Go to the end ` - to download the full example code.{2} + to download the full example code{2} .. rst-class:: sphx-glr-example-title diff --git a/lib/matplotlib/tests/test_doc.py b/lib/matplotlib/tests/test_doc.py index 3e28fd1b8eb7..6e8ce9fd630c 100644 --- a/lib/matplotlib/tests/test_doc.py +++ b/lib/matplotlib/tests/test_doc.py @@ -9,7 +9,7 @@ def test_sphinx_gallery_example_header(): EXAMPLE_HEADER, this test will start to fail. In that case, please update the monkey-patching of EXAMPLE_HEADER in conf.py. """ - pytest.importorskip('sphinx_gallery', minversion='0.16.0') + pytest.importorskip('sphinx_gallery', minversion='0.20.0') from sphinx_gallery import gen_rst EXAMPLE_HEADER = """ @@ -25,7 +25,7 @@ def test_sphinx_gallery_example_header(): :class: sphx-glr-download-link-note :ref:`Go to the end ` - to download the full example code.{2} + to download the full example code{2} .. rst-class:: sphx-glr-example-title From 1957ba391889a4d6b9048b77080f62b1a1dbcad0 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Fri, 12 Dec 2025 12:24:39 -0600 Subject: [PATCH 18/19] Zenodo v3.10.8 --- doc/_static/zenodo_cache/17595503.svg | 35 +++++++++++++++++++++++++++ doc/project/citing.rst | 3 +++ tools/cache_zenodo_svg.py | 1 + 3 files changed, 39 insertions(+) create mode 100644 doc/_static/zenodo_cache/17595503.svg diff --git a/doc/_static/zenodo_cache/17595503.svg b/doc/_static/zenodo_cache/17595503.svg new file mode 100644 index 000000000000..891bd118d125 --- /dev/null +++ b/doc/_static/zenodo_cache/17595503.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + DOI + + + DOI + + + 10.5281/zenodo.17595503 + + + 10.5281/zenodo.17595503 + + + \ No newline at end of file diff --git a/doc/project/citing.rst b/doc/project/citing.rst index c5e56e6f12d4..1f8c6509e9e6 100644 --- a/doc/project/citing.rst +++ b/doc/project/citing.rst @@ -32,6 +32,9 @@ By version .. START OF AUTOGENERATED +v3.10.8 + .. image:: ../_static/zenodo_cache/17595503.svg + :target: https://doi.org/10.5281/zenodo.17595503 v3.10.7 .. image:: ../_static/zenodo_cache/17298696.svg :target: https://doi.org/10.5281/zenodo.17298696 diff --git a/tools/cache_zenodo_svg.py b/tools/cache_zenodo_svg.py index 07b67a3e04ee..2ee72c6a89fa 100644 --- a/tools/cache_zenodo_svg.py +++ b/tools/cache_zenodo_svg.py @@ -63,6 +63,7 @@ def _get_xdg_cache_dir(): if __name__ == "__main__": data = { + "v3.10.8": "17595503", "v3.10.7": "17298696", "v3.10.6": "16999430", "v3.10.5": "16644850", From 9d0781d25f363466c71898dabb1e1abffe14c504 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 15 Dec 2025 09:41:14 -0500 Subject: [PATCH 19/19] Backport PR #30858: DOC: reinstate "codex" search term --- doc/conf.py | 29 +---------------------------- doc/sphinxext/util.py | 32 ++++++++++++++++++++++++++++++++ lib/matplotlib/tests/test_doc.py | 2 +- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 03df9340e66c..292aff3e1983 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -200,8 +200,6 @@ def _check_dependencies(): else: sg_matplotlib_animations = True -# The following import is only necessary to monkey patch the signature later on -from sphinx_gallery import gen_rst # Prevent plt.show() from emitting a non-GUI backend warning. warnings.filterwarnings('ignore', category=UserWarning, @@ -299,7 +297,7 @@ def autodoc_process_bases(app, name, obj, options, bases): 'reference_url': {'matplotlib': None, 'mpl_toolkits': None}, 'prefer_full_module': {r'mpl_toolkits\.'}, 'remove_config_comments': True, - 'reset_modules': ('matplotlib', clear_basic_units), + 'reset_modules': ('matplotlib', clear_basic_units, 'sphinxext.util.patch_header'), 'subsection_order': gallery_order_sectionorder, 'thumbnail_size': (320, 224), 'within_subsection_order': gallery_order_subsectionorder, @@ -347,31 +345,6 @@ def gallery_image_warning_filter(record): mathmpl_fontsize = 11.0 mathmpl_srcset = ['2x'] -# Monkey-patching gallery header to include search keywords -gen_rst.EXAMPLE_HEADER = """ -.. DO NOT EDIT. -.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. -.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: -.. "{0}" -.. LINE NUMBERS ARE GIVEN BELOW. - -.. only:: html - - .. meta:: - :keywords: codex - - .. note:: - :class: sphx-glr-download-link-note - - :ref:`Go to the end ` - to download the full example code{2} - -.. rst-class:: sphx-glr-example-title - -.. _sphx_glr_{1}: - -""" - # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/doc/sphinxext/util.py b/doc/sphinxext/util.py index 14097ba9396a..c0f336eaea18 100644 --- a/doc/sphinxext/util.py +++ b/doc/sphinxext/util.py @@ -1,5 +1,7 @@ import sys +from sphinx_gallery import gen_rst + def matplotlib_reduced_latex_scraper(block, block_vars, gallery_conf, **kwargs): @@ -19,3 +21,33 @@ def matplotlib_reduced_latex_scraper(block, block_vars, gallery_conf, # Clear basic_units module to re-register with unit registry on import. def clear_basic_units(gallery_conf, fname): return sys.modules.pop('basic_units', None) + + +# Monkey-patching gallery header to include search keywords +EXAMPLE_HEADER = """ +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "{0}" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. meta:: + :keywords: codex + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code{2} + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_{1}: + +""" + + +def patch_header(gallery_conf, fname): + gen_rst.EXAMPLE_HEADER = EXAMPLE_HEADER diff --git a/lib/matplotlib/tests/test_doc.py b/lib/matplotlib/tests/test_doc.py index 6e8ce9fd630c..f3d6d6e3fd5d 100644 --- a/lib/matplotlib/tests/test_doc.py +++ b/lib/matplotlib/tests/test_doc.py @@ -7,7 +7,7 @@ def test_sphinx_gallery_example_header(): This test monitors that the version we have copied is still the same as the EXAMPLE_HEADER in sphinx-gallery. If sphinx-gallery changes its EXAMPLE_HEADER, this test will start to fail. In that case, please update - the monkey-patching of EXAMPLE_HEADER in conf.py. + the monkey-patching of EXAMPLE_HEADER in sphinxext/util.py. """ pytest.importorskip('sphinx_gallery', minversion='0.20.0') from sphinx_gallery import gen_rst