diff --git a/doc/_static/switcher.json b/doc/_static/switcher.json
index 2d02ec01ae56..36e743db21b8 100644
--- a/doc/_static/switcher.json
+++ b/doc/_static/switcher.json
@@ -1,7 +1,7 @@
[
{
"name": "3.10 (stable)",
- "version": "3.10.6",
+ "version": "3.10.8",
"url": "https://matplotlib.org/stable/",
"preferred": true
},
@@ -12,8 +12,8 @@
},
{
"name": "3.9",
- "version": "3.9.4",
- "url": "https://matplotlib.org/3.9.4/"
+ "version": "3.9.3",
+ "url": "https://matplotlib.org/3.9.3/"
},
{
"name": "3.8",
diff --git a/doc/_static/zenodo_cache/17298696.svg b/doc/_static/zenodo_cache/17298696.svg
new file mode 100644
index 000000000000..9aa8d7c94349
--- /dev/null
+++ b/doc/_static/zenodo_cache/17298696.svg
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/doc/api/next_api_changes/development/29745-DS.rst b/doc/api/prev_api_changes/api_changes_3.10.7.rst
similarity index 67%
rename from doc/api/next_api_changes/development/29745-DS.rst
rename to doc/api/prev_api_changes/api_changes_3.10.7.rst
index 7d9b1c2b143b..a60061e86277 100644
--- a/doc/api/next_api_changes/development/29745-DS.rst
+++ b/doc/api/prev_api_changes/api_changes_3.10.7.rst
@@ -1,3 +1,9 @@
+API Changes for 3.10.7
+======================
+
+Development
+-----------
+
New minimum version of pyparsing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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
diff --git a/doc/project/citing.rst b/doc/project/citing.rst
index ae2061e7349c..c5e56e6f12d4 100644
--- a/doc/project/citing.rst
+++ b/doc/project/citing.rst
@@ -32,6 +32,9 @@ By version
.. START OF AUTOGENERATED
+v3.10.7
+ .. image:: ../_static/zenodo_cache/17298696.svg
+ :target: https://doi.org/10.5281/zenodo.17298696
v3.10.6
.. image:: ../_static/zenodo_cache/16999430.svg
:target: https://doi.org/10.5281/zenodo.16999430
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
diff --git a/doc/users/release_notes.rst b/doc/users/release_notes.rst
index 1ca483ab15a2..dbdcd61437ac 100644
--- a/doc/users/release_notes.rst
+++ b/doc/users/release_notes.rst
@@ -18,9 +18,12 @@ Version 3.10
:maxdepth: 1
prev_whats_new/whats_new_3.10.0.rst
+ ../api/prev_api_changes/api_changes_3.10.7.rst
../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
prev_whats_new/github_stats_3.10.1.rst
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/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
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))
diff --git a/lib/matplotlib/tests/test_backend_macosx.py b/lib/matplotlib/tests/test_backend_macosx.py
index 8e50ddf84024..0648e43cde94 100644
--- a/lib/matplotlib/tests/test_backend_macosx.py
+++ b/lib/matplotlib/tests/test_backend_macosx.py
@@ -1,18 +1,19 @@
import os
+import threading
+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 +25,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 +41,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 +55,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 +79,31 @@ 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"})
+
+
+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/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"""
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,
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",
]
diff --git a/src/_macosx.m b/src/_macosx.m
index c8e2cea43863..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; }
@@ -1895,6 +1905,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;
}
diff --git a/tools/cache_zenodo_svg.py b/tools/cache_zenodo_svg.py
index c6783dd9f19d..07b67a3e04ee 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.7": "17298696",
"v3.10.6": "16999430",
"v3.10.5": "16644850",
"v3.10.3": "15375714",