diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml
index e88d83cccd53..cd9ad2161595 100644
--- a/.github/workflows/cibuildwheel.yml
+++ b/.github/workflows/cibuildwheel.yml
@@ -148,8 +148,6 @@ jobs:
package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }}
env:
CIBW_BUILD: "cp313-* cp313t-*"
- # No free-threading wheels for NumPy; musllinux skipped for main builds also.
- CIBW_SKIP: "cp313t-win_amd64 *-musllinux_aarch64"
CIBW_BUILD_FRONTEND:
"pip; args: --pre --extra-index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple"
CIBW_FREE_THREADED_SUPPORT: true
diff --git a/doc/users/next_whats_new/freethreading.rst b/doc/users/next_whats_new/freethreading.rst
new file mode 100644
index 000000000000..6ed7a0d636b6
--- /dev/null
+++ b/doc/users/next_whats_new/freethreading.rst
@@ -0,0 +1,22 @@
+Preliminary support for free-threaded CPython 3.13
+--------------------------------------------------
+
+Matplotlib 3.10 has preliminary support for the free-threaded build of CPython 3.13. See
+https://py-free-threading.github.io, `PEP 703 `_ and
+the `CPython 3.13 release notes
+`_ for more detail
+about free-threaded Python.
+
+Support for free-threaded Python does not mean that Matplotlib is wholly thread safe. We
+expect that use of a Figure within a single thread will work, and though input data is
+usually copied, modification of data objects used for a plot from another thread may
+cause inconsistencies in cases where it is not. Use of any global state (such as the
+``pyplot`` module) is highly discouraged and unlikely to work consistently. Also note
+that most GUI toolkits expect to run on the main thread, so interactive usage may be
+limited or unsupported from other threads.
+
+If you are interested in free-threaded Python, for example because you have a
+multiprocessing-based workflow that you are interested in running with Python threads, we
+encourage testing and experimentation. If you run into problems that you suspect are
+because of Matplotlib, please open an issue, checking first if the bug also occurs in the
+“regular” non-free-threaded CPython 3.13 build.
diff --git a/src/_backend_agg_wrapper.cpp b/src/_backend_agg_wrapper.cpp
index bfc8584d688d..233c2289972f 100644
--- a/src/_backend_agg_wrapper.cpp
+++ b/src/_backend_agg_wrapper.cpp
@@ -185,7 +185,7 @@ PyRendererAgg_draw_gouraud_triangles(RendererAgg *self,
self->draw_gouraud_triangles(gc, points, colors, trans);
}
-PYBIND11_MODULE(_backend_agg, m)
+PYBIND11_MODULE(_backend_agg, m, py::mod_gil_not_used())
{
py::class_(m, "RendererAgg", py::buffer_protocol())
.def(py::init(),
diff --git a/src/_c_internal_utils.cpp b/src/_c_internal_utils.cpp
index 561cb303639c..db6191849bbe 100644
--- a/src/_c_internal_utils.cpp
+++ b/src/_c_internal_utils.cpp
@@ -196,7 +196,7 @@ mpl_SetProcessDpiAwareness_max(void)
#endif
}
-PYBIND11_MODULE(_c_internal_utils, m)
+PYBIND11_MODULE(_c_internal_utils, m, py::mod_gil_not_used())
{
m.def(
"display_is_valid", &mpl_display_is_valid,
diff --git a/src/_image_wrapper.cpp b/src/_image_wrapper.cpp
index 0095f52e5997..0f7b0da88de8 100644
--- a/src/_image_wrapper.cpp
+++ b/src/_image_wrapper.cpp
@@ -200,7 +200,8 @@ image_resample(py::array input_array,
}
-PYBIND11_MODULE(_image, m) {
+PYBIND11_MODULE(_image, m, py::mod_gil_not_used())
+{
py::enum_(m, "_InterpolationType")
.value("NEAREST", NEAREST)
.value("BILINEAR", BILINEAR)
diff --git a/src/_path_wrapper.cpp b/src/_path_wrapper.cpp
index 7a7cb343b8e7..e8322cb51b7b 100644
--- a/src/_path_wrapper.cpp
+++ b/src/_path_wrapper.cpp
@@ -368,7 +368,7 @@ Py_is_sorted_and_has_non_nan(py::object obj)
return result;
}
-PYBIND11_MODULE(_path, m)
+PYBIND11_MODULE(_path, m, py::mod_gil_not_used())
{
m.def("point_in_path", &Py_point_in_path,
"x"_a, "y"_a, "radius"_a, "path"_a, "trans"_a);
diff --git a/src/_qhull_wrapper.cpp b/src/_qhull_wrapper.cpp
index 9784a1698ba1..da623a8d1b71 100644
--- a/src/_qhull_wrapper.cpp
+++ b/src/_qhull_wrapper.cpp
@@ -276,7 +276,8 @@ delaunay(const CoordArray& x, const CoordArray& y, int verbose)
return delaunay_impl(npoints, x.data(), y.data(), verbose == 0);
}
-PYBIND11_MODULE(_qhull, m) {
+PYBIND11_MODULE(_qhull, m, py::mod_gil_not_used())
+{
m.doc() = "Computing Delaunay triangulations.\n";
m.def("delaunay", &delaunay, "x"_a, "y"_a, "verbose"_a,
diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp
index bfc2253188fd..04ca3d4d1b84 100644
--- a/src/_tkagg.cpp
+++ b/src/_tkagg.cpp
@@ -333,7 +333,7 @@ load_tkinter_funcs()
}
#endif // end not Windows
-PYBIND11_MODULE(_tkagg, m)
+PYBIND11_MODULE(_tkagg, m, py::mod_gil_not_used())
{
try {
load_tkinter_funcs();
diff --git a/src/ft2font_wrapper.cpp b/src/ft2font_wrapper.cpp
index 4358646beede..8d332d2af4d4 100644
--- a/src/ft2font_wrapper.cpp
+++ b/src/ft2font_wrapper.cpp
@@ -952,7 +952,7 @@ PyFT2Font_fname(PyFT2Font *self)
}
}
-PYBIND11_MODULE(ft2font, m)
+PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used())
{
if (FT_Init_FreeType(&_ft2Library)) { // initialize library
throw std::runtime_error("Could not initialize the freetype2 library");
diff --git a/src/tri/_tri_wrapper.cpp b/src/tri/_tri_wrapper.cpp
index 54d1c32e9c57..732e1af5f310 100644
--- a/src/tri/_tri_wrapper.cpp
+++ b/src/tri/_tri_wrapper.cpp
@@ -2,7 +2,8 @@
using namespace pybind11::literals;
-PYBIND11_MODULE(_tri, m) {
+PYBIND11_MODULE(_tri, m, py::mod_gil_not_used())
+{
py::class_(m, "Triangulation", py::is_final())
.def(py::initpFad - Phonifier reborn
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.