From 280135670aa86e6d064b5fa24049e53e2171094f Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Thu, 27 Feb 2025 12:59:49 -0600 Subject: [PATCH 01/16] Zenodo v3.10.1 --- doc/_static/zenodo_cache/14940554.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/14940554.svg diff --git a/doc/_static/zenodo_cache/14940554.svg b/doc/_static/zenodo_cache/14940554.svg new file mode 100644 index 000000000000..6e7d5c37bf7b --- /dev/null +++ b/doc/_static/zenodo_cache/14940554.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + DOI + + + DOI + + + 10.5281/zenodo.14940554 + + + 10.5281/zenodo.14940554 + + + \ No newline at end of file diff --git a/doc/project/citing.rst b/doc/project/citing.rst index 2cd317906bb5..d04ebec0d3c9 100644 --- a/doc/project/citing.rst +++ b/doc/project/citing.rst @@ -32,6 +32,9 @@ By version .. START OF AUTOGENERATED +v3.10.1 + .. image:: ../_static/zenodo_cache/14940554.svg + :target: https://doi.org/10.5281/zenodo.14940554 v3.10.0 .. image:: ../_static/zenodo_cache/14464227.svg :target: https://doi.org/10.5281/zenodo.14464227 diff --git a/tools/cache_zenodo_svg.py b/tools/cache_zenodo_svg.py index 3be7d6ca21e4..9e5c4076bd1d 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.1": "14940554", "v3.10.0": "14464227", "v3.9.4": "14436121", "v3.9.3": "14249941", From 80583533bb14b9243fa4389ddc5d097d19fc33d0 Mon Sep 17 00:00:00 2001 From: hannah Date: Mon, 10 Mar 2025 14:39:24 -0400 Subject: [PATCH 02/16] Backport PR #29726: Add reference tag to Hatch style reference --- .../examples/shapes_and_collections/hatch_style_reference.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/galleries/examples/shapes_and_collections/hatch_style_reference.py b/galleries/examples/shapes_and_collections/hatch_style_reference.py index 724abde051b4..e0409d989e6b 100644 --- a/galleries/examples/shapes_and_collections/hatch_style_reference.py +++ b/galleries/examples/shapes_and_collections/hatch_style_reference.py @@ -62,3 +62,7 @@ def hatches_plot(ax, h): # - `matplotlib.patches.Rectangle` # - `matplotlib.axes.Axes.add_patch` # - `matplotlib.axes.Axes.text` +# +# .. tags:: +# +# purpose: reference From e5b4d9b5d2a2a3df8781da4174c2c4cbe8685644 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Wed, 12 Mar 2025 13:01:26 +0100 Subject: [PATCH 03/16] Backport PR #29734: ci: MacOS 14: temporarily upper-bound the 'PyGObject' Python package version --- .github/workflows/tests.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d42ac6ea00a2..e856eef76c6e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -103,10 +103,14 @@ jobs: pyside6-ver: '!=6.5.1' - os: macos-14 # This runner is on M1 (arm64) chips. python-version: '3.12' + # https://github.com/matplotlib/matplotlib/issues/29732 + pygobject-ver: '<3.52.0' # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346 pyside6-ver: '!=6.5.1' - os: macos-14 # This runner is on M1 (arm64) chips. python-version: '3.13' + # https://github.com/matplotlib/matplotlib/issues/29732 + pygobject-ver: '<3.52.0' # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346 pyside6-ver: '!=6.5.1' @@ -270,7 +274,7 @@ jobs: # (sometimes, the install appears to be successful but shared # libraries cannot be loaded at runtime, so an actual import is a # better check). - python -m pip install --upgrade pycairo 'cairocffi>=0.8' PyGObject && + python -m pip install --upgrade pycairo 'cairocffi>=0.8' PyGObject${{ matrix.pygobject-ver }} && ( python -c 'import gi; gi.require_version("Gtk", "4.0"); from gi.repository import Gtk' && echo 'PyGObject 4 is available' || echo 'PyGObject 4 is not available' From 45e703faa84f318b76deee57f89e18f4a8b6747a Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 13 Mar 2025 15:14:15 -0400 Subject: [PATCH 04/16] Backport PR #29748: Fix PyGObject version pinning in macOS tests --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e856eef76c6e..376aaa3e293d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -274,7 +274,7 @@ jobs: # (sometimes, the install appears to be successful but shared # libraries cannot be loaded at runtime, so an actual import is a # better check). - python -m pip install --upgrade pycairo 'cairocffi>=0.8' PyGObject${{ matrix.pygobject-ver }} && + python -m pip install --upgrade pycairo 'cairocffi>=0.8' 'PyGObject${{ matrix.pygobject-ver }}' && ( python -c 'import gi; gi.require_version("Gtk", "4.0"); from gi.repository import Gtk' && echo 'PyGObject 4 is available' || echo 'PyGObject 4 is not available' From 3913318e10ac1abb60892a2e2a84151e048625a8 Mon Sep 17 00:00:00 2001 From: Qian Zhang <88585542+QianZhang19@users.noreply.github.com> Date: Tue, 18 Mar 2025 14:11:23 +0000 Subject: [PATCH 05/16] Backport PR #29767: Add description to logit_demo.py script --- galleries/examples/scales/logit_demo.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/galleries/examples/scales/logit_demo.py b/galleries/examples/scales/logit_demo.py index 22a56433ccd7..e8d42fc35711 100644 --- a/galleries/examples/scales/logit_demo.py +++ b/galleries/examples/scales/logit_demo.py @@ -4,6 +4,20 @@ =========== Examples of plots with logit axes. + +This example visualises how ``set_yscale("logit")`` works on probability plots +by generating three distributions: normal, laplacian, and cauchy in one plot. + +The advantage of logit scale is that it effectively spreads out values close to 0 and 1. + +In a linear scale plot, probability values near 0 and 1 appear compressed, +making it difficult to see differences in those regions. + +In a logit scale plot, the transformation expands these regions, +making the graph cleaner and easier to compare across different probability values. + +This makes the logit scale especially useful when visalising probabilities in logistic +regression, classification models, and cumulative distribution functions. """ import math From b0577b65fc9e939505a3abbf2d04ba7703a4016d Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Tue, 18 Mar 2025 22:34:47 +0100 Subject: [PATCH 06/16] Backport PR #29752: DOC: Add install instructions for pixi and uv --- doc/index.rst | 28 ++++++++++++++++++++++++++++ doc/install/index.rst | 3 ++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index dedd614985df..74a183d6cd7b 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -29,6 +29,34 @@ Install conda install -c conda-forge matplotlib + .. tab-item:: pixi + + .. code-block:: bash + + pixi add matplotlib + + .. tab-item:: uv + + .. code-block:: bash + + uv add matplotlib + + .. warning:: + + If you install Python with ``uv`` then the ``tkagg`` backend + will not be available because python-build-standalone (used by uv + to distribute Python) does not contain tk bindings that are usable by + Matplotlib (see `this issue`_ for details). If you want Matplotlib + to be able to display plots in a window, you should install one of + the other :ref:`supported GUI frameworks `, + e.g. + + .. code-block:: bash + + uv add matplotlib pyside6 + + .. _this issue: https://github.com/astral-sh/uv/issues/6893#issuecomment-2565965851 + .. tab-item:: other .. rst-class:: section-toc diff --git a/doc/install/index.rst b/doc/install/index.rst index 99ccc163a82e..2d9e724e6a73 100644 --- a/doc/install/index.rst +++ b/doc/install/index.rst @@ -28,7 +28,8 @@ precompiled wheel for your OS and Python. The following backends work out of the box: Agg, ps, pdf, svg Python is typically shipped with tk bindings which are used by - TkAgg. + TkAgg. Notably, python-build-standalone – used by ``uv`` – does + not include tk bindings that are usable by Matplotlib. For support of other GUI frameworks, LaTeX rendering, saving animations and a larger selection of file formats, you can From 77c8cf3bc0940949eace94f20850bd4b3fa94295 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Fri, 21 Mar 2025 08:24:14 +0100 Subject: [PATCH 07/16] Backport PR #29755: DOC: Simplify annotation arrow style reference --- .../fancyarrow_demo.py | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/galleries/examples/text_labels_and_annotations/fancyarrow_demo.py b/galleries/examples/text_labels_and_annotations/fancyarrow_demo.py index 8d0027831e4a..4f45a9a72a47 100644 --- a/galleries/examples/text_labels_and_annotations/fancyarrow_demo.py +++ b/galleries/examples/text_labels_and_annotations/fancyarrow_demo.py @@ -19,35 +19,31 @@ nrow = (len(styles) + 1) // ncol axs = (plt.figure(figsize=(4 * ncol, 1 + nrow)) .add_gridspec(1 + nrow, ncol, - wspace=.7, left=.1, right=.9, bottom=0, top=1).subplots()) + wspace=0, hspace=0, left=0, right=1, bottom=0, top=1).subplots()) for ax in axs.flat: + ax.set_xlim(-0.5, 4) ax.set_axis_off() for ax in axs[0, :]: - ax.text(0, .5, "arrowstyle", - transform=ax.transAxes, size="large", color="tab:blue", - horizontalalignment="center", verticalalignment="center") - ax.text(.35, .5, "default parameters", - transform=ax.transAxes, - horizontalalignment="left", verticalalignment="center") + ax.text(-0.25, 0.5, "arrowstyle", size="large", color="tab:blue") + ax.text(1.25, .5, "default parameters", size="large") for ax, (stylename, stylecls) in zip(axs[1:, :].T.flat, styles.items()): - l, = ax.plot(.25, .5, "ok", transform=ax.transAxes) - ax.annotate(stylename, (.25, .5), (-0.1, .5), - xycoords="axes fraction", textcoords="axes fraction", - size="large", color="tab:blue", - horizontalalignment="center", verticalalignment="center", + # draw dot and annotation with arrowstyle + l, = ax.plot(1, 0, "o", color="grey") + ax.annotate(stylename, (1, 0), (0, 0), + size="large", color="tab:blue", ha="center", va="center", arrowprops=dict( arrowstyle=stylename, connectionstyle="arc3,rad=-0.05", color="k", shrinkA=5, shrinkB=5, patchB=l, ), - bbox=dict(boxstyle="square", fc="w")) + bbox=dict(boxstyle="square", fc="w", ec="grey")) + # draw default parameters # wrap at every nth comma (n = 1 or 2, depending on text length) s = str(inspect.signature(stylecls))[1:-1] n = 2 if s.count(',') > 3 else 1 - ax.text(.35, .5, + ax.text(1.25, 0, re.sub(', ', lambda m, c=itertools.count(1): m.group() if next(c) % n else '\n', s), - transform=ax.transAxes, - horizontalalignment="left", verticalalignment="center") + verticalalignment="center") plt.show() From ba036e6bd549c6b0ea8154c612e26f52bbd1d8de Mon Sep 17 00:00:00 2001 From: David Stansby Date: Fri, 21 Mar 2025 19:58:34 +0000 Subject: [PATCH 08/16] Backport PR #29770: MNT: Move test for old ipython behavior to minver tests --- .github/workflows/tests.yml | 7 +------ requirements/testing/minver.txt | 8 ++++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 376aaa3e293d..91fe6d982455 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -59,12 +59,7 @@ jobs: pyside6-ver: '==6.2.0' - os: ubuntu-20.04 python-version: '3.10' - # One CI run tests ipython/matplotlib-inline before backend mapping moved to mpl - extra-requirements: - -r requirements/testing/extra.txt - "ipython==7.29.0" - "ipykernel==5.5.6" - "matplotlib-inline<0.1.7" + extra-requirements: '-r requirements/testing/extra.txt' CFLAGS: "-fno-lto" # Ensure that disabling LTO works. # https://github.com/matplotlib/matplotlib/pull/26052#issuecomment-1574595954 # https://www.riverbankcomputing.com/pipermail/pyqt/2023-November/045606.html diff --git a/requirements/testing/minver.txt b/requirements/testing/minver.txt index 3932e68eb015..d30ebf08f04b 100644 --- a/requirements/testing/minver.txt +++ b/requirements/testing/minver.txt @@ -13,3 +13,11 @@ pillow==8.3.2 pyparsing==2.3.1 pytest==7.0.0 python-dateutil==2.7 + +# Test ipython/matplotlib-inline before backend mapping moved to mpl. +# This should be tested for a reasonably long transition period, +# but we will eventually remove the test when we no longer support +# ipython/matplotlib-inline versions from before the transition. +ipython==7.29.0 +ipykernel==5.5.6 +matplotlib-inline<0.1.7 From 588365a35203859d4cd1b0a93cc4990e25f3d839 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Fri, 28 Mar 2025 00:14:24 +0100 Subject: [PATCH 09/16] Backport PR #29801: DOC: Slightly further improve arrowstyle demo --- .../fancyarrow_demo.py | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/galleries/examples/text_labels_and_annotations/fancyarrow_demo.py b/galleries/examples/text_labels_and_annotations/fancyarrow_demo.py index 4f45a9a72a47..6a2700d20515 100644 --- a/galleries/examples/text_labels_and_annotations/fancyarrow_demo.py +++ b/galleries/examples/text_labels_and_annotations/fancyarrow_demo.py @@ -3,7 +3,11 @@ Annotation arrow style reference ================================ -Overview of the arrow styles available in `~.Axes.annotate`. +Overview of the available `.ArrowStyle` settings. These are used for the *arrowstyle* +parameter of `~.Axes.annotate` and `.FancyArrowPatch`. + +Each style can be configured with a set of parameters, which are stated along with +their default values. """ import inspect @@ -12,38 +16,38 @@ import matplotlib.pyplot as plt -import matplotlib.patches as mpatches +from matplotlib.patches import ArrowStyle -styles = mpatches.ArrowStyle.get_styles() +styles = ArrowStyle.get_styles() ncol = 2 nrow = (len(styles) + 1) // ncol -axs = (plt.figure(figsize=(4 * ncol, 1 + nrow)) - .add_gridspec(1 + nrow, ncol, - wspace=0, hspace=0, left=0, right=1, bottom=0, top=1).subplots()) +gridspec_kw = dict(wspace=0, hspace=0.05, left=0, right=1, bottom=0, top=1) +fig, axs = plt.subplots(1 + nrow, ncol, + figsize=(4 * ncol, 1 + nrow), gridspec_kw=gridspec_kw) for ax in axs.flat: - ax.set_xlim(-0.5, 4) + ax.set_xlim(-0.1, 4) ax.set_axis_off() for ax in axs[0, :]: - ax.text(-0.25, 0.5, "arrowstyle", size="large", color="tab:blue") - ax.text(1.25, .5, "default parameters", size="large") + ax.text(0, 0.5, "arrowstyle", size="large", color="tab:blue") + ax.text(1.4, .5, "default parameters", size="large") for ax, (stylename, stylecls) in zip(axs[1:, :].T.flat, styles.items()): # draw dot and annotation with arrowstyle - l, = ax.plot(1, 0, "o", color="grey") - ax.annotate(stylename, (1, 0), (0, 0), - size="large", color="tab:blue", ha="center", va="center", + l, = ax.plot(1.25, 0, "o", color="darkgrey") + ax.annotate(stylename, (1.25, 0), (0, 0), + size="large", color="tab:blue", va="center", family="monospace", arrowprops=dict( - arrowstyle=stylename, connectionstyle="arc3,rad=-0.05", - color="k", shrinkA=5, shrinkB=5, patchB=l, + arrowstyle=stylename, connectionstyle="arc3,rad=0", + color="black", shrinkA=5, shrinkB=5, patchB=l, ), - bbox=dict(boxstyle="square", fc="w", ec="grey")) + bbox=dict(boxstyle="square", fc="w", ec="darkgrey")) # draw default parameters # wrap at every nth comma (n = 1 or 2, depending on text length) s = str(inspect.signature(stylecls))[1:-1] n = 2 if s.count(',') > 3 else 1 - ax.text(1.25, 0, + ax.text(1.4, 0, re.sub(', ', lambda m, c=itertools.count(1): m.group() if next(c) % n else '\n', s), - verticalalignment="center") + verticalalignment="center", color="0.3") plt.show() From dd57eb44f85339569dadbbd814d228584f6486ac Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 3 Apr 2025 13:38:47 +0200 Subject: [PATCH 10/16] Backport PR #29773: DOC: Improve interactive figures guide / Blocking input --- .../figure/interactive_guide.rst | 78 ++++++++++--------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/galleries/users_explain/figure/interactive_guide.rst b/galleries/users_explain/figure/interactive_guide.rst index 5cc55edc0955..6cbdca4ab3f9 100644 --- a/galleries/users_explain/figure/interactive_guide.rst +++ b/galleries/users_explain/figure/interactive_guide.rst @@ -11,7 +11,7 @@ Interactive figures and asynchronous programming Matplotlib supports rich interactive figures by embedding figures into a GUI window. The basic interactions of panning and zooming in an -Axes to inspect your data is "baked in" to Matplotlib. This is +Axes to inspect your data is available out-of-the-box. This is supported by a full mouse and keyboard event handling system that you can use to build sophisticated interactive graphs. @@ -23,6 +23,21 @@ handling system `, `Interactive Tutorial `Interactive Applications using Matplotlib `__. + +GUI events +========== + +All GUI frameworks (Qt, Wx, Gtk, Tk, macOS, or web) have some method of +capturing user interactions and passing them back to the application, but +the exact details depend on the toolkit (for example callbacks in Tk or +the ``Signal`` / ``Slot`` framework in Qt). The Matplotlib :ref:`backends +` encapsulate the details of the GUI frameworks and +provide a framework-independent interface to GUI events through Matplotlib's +:ref:`event handling system `. By connecting functions +to the event handling system (see `.FigureCanvasBase.mpl_connect`), you can +interactively respond to user actions in a GUI toolkit agnostic way. + + Event loops =========== @@ -58,19 +73,6 @@ depending on the library, by methods with names like ``exec``, ``run``, or ``start``. -All GUI frameworks (Qt, Wx, Gtk, tk, macOS, or web) have some method of -capturing user interactions and passing them back to the application -(for example ``Signal`` / ``Slot`` framework in Qt) but the exact -details depend on the toolkit. Matplotlib has a :ref:`backend -` for each GUI toolkit we support which uses the -toolkit API to bridge the toolkit UI events into Matplotlib's :ref:`event -handling system `. You can then use -`.FigureCanvasBase.mpl_connect` to connect your function to -Matplotlib's event handling system. This allows you to directly -interact with your data and write GUI toolkit agnostic user -interfaces. - - .. _cp_integration: Command prompt integration @@ -81,16 +83,16 @@ lets us interactively send code to the interpreter and get results back. We also have the GUI toolkit that runs an event loop waiting for user input and lets us register functions to be run when that happens. However, if we want to do both we have a problem: the prompt -and the GUI event loop are both infinite loops that each think *they* -are in charge! In order for both the prompt and the GUI windows to be +and the GUI event loop are both infinite loops and cannot run in +parallel. In order for both the prompt and the GUI windows to be responsive we need a method to allow the loops to "timeshare" : -1. let the GUI main loop block the python process when you want - interactive windows -2. let the CLI main loop block the python process and intermittently - run the GUI loop -3. fully embed python in the GUI (but this is basically writing a full - application) +1. **Blocking the prompt**: let the GUI main loop block the python + process when you want interactive windows +2. **Input hook integration**: let the CLI main loop block the python + process and intermittently run the GUI loop +3. **Full embedding**: fully embed python in the GUI + (but this is basically writing a full application) .. _cp_block_the_prompt: @@ -108,24 +110,26 @@ Blocking the prompt backend_bases.FigureCanvasBase.stop_event_loop -The simplest "integration" is to start the GUI event loop in -"blocking" mode and take over the CLI. While the GUI event loop is -running you cannot enter new commands into the prompt (your terminal -may echo the characters typed into the terminal, but they will not be -sent to the Python interpreter because it is busy running the GUI -event loop), but the figure windows will be responsive. Once the -event loop is stopped (leaving any still open figure windows -non-responsive) you will be able to use the prompt again. Re-starting -the event loop will make any open figure responsive again (and will -process any queued up user interaction). +The simplest solution is to start the GUI event loop and let it run +exclusively, which results in responsive figure windows. However, the +CLI event loop will not run, so that you cannot enter new commands. +We call this "blocking" mode. (Your terminal may echo the typed characters, +but they will not yet be processed by the CLI event loop because the Python +interpreter is busy running the GUI event loop). + +It is possible to stop the GUI event loop and return control to the CLI +event loop. You can then use the prompt again, but any still open figure +windows are non-responsive. Re-starting the GUI event loop will make these +figure responsive again (and will process any queued up user interaction). + -To start the event loop until all open figures are closed, use -`.pyplot.show` as :: +The typical command to show all figures and run the GUI event loop +exclusively until all figures are closed is :: - pyplot.show(block=True) + plt.show() -To start the event loop for a fixed amount of time (in seconds) use -`.pyplot.pause`. +Alternatively, you can start the GUI event loop for a fixed amount of time +using `.pyplot.pause`. If you are not using `.pyplot` you can start and stop the event loops via `.FigureCanvasBase.start_event_loop` and From f66a9cb4963ba13a83c252923b7c5bf80d33eaf4 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Sun, 30 Mar 2025 03:53:32 -0700 Subject: [PATCH 11/16] Backport PR #29834: TST: pin flake8 --- environment.yml | 2 +- requirements/testing/flake8.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/environment.yml b/environment.yml index 8c4221d0a0fa..d95cab0509ff 100644 --- a/environment.yml +++ b/environment.yml @@ -53,7 +53,7 @@ dependencies: # testing - black<24 - coverage - - flake8>=3.8 + - flake8>=3.8,<7.2 - flake8-docstrings>=1.4.0 - gtk4 - ipykernel diff --git a/requirements/testing/flake8.txt b/requirements/testing/flake8.txt index a4d006b8551e..cb34fee3f385 100644 --- a/requirements/testing/flake8.txt +++ b/requirements/testing/flake8.txt @@ -1,6 +1,6 @@ # Extra pip requirements for the GitHub Actions flake8 build -flake8>=3.8 +flake8>=3.8,<7.2 # versions less than 5.1.0 raise on some interp'd docstrings pydocstyle>=5.1.0 # 1.4.0 adds docstring-convention=all From 36a5aa0796e69b0bbe389d0730c4b37f545a2ac8 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 8 Apr 2025 20:08:27 -0400 Subject: [PATCH 12/16] Backport PR #29803: DOC: Improve FancyArrowPatch docstring --- lib/matplotlib/patches.py | 87 ++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index f47c8abee32d..736b1e77e1ac 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -2335,7 +2335,7 @@ def get_styles(cls): @classmethod def pprint_styles(cls): """Return the available styles as pretty-printed string.""" - table = [('Class', 'Name', 'Attrs'), + table = [('Class', 'Name', 'Parameters'), *[(cls.__name__, # Add backquotes, as - and | have special meaning in reST. f'``{name}``', @@ -4159,49 +4159,90 @@ def __init__(self, posA=None, posB=None, *, patchA=None, patchB=None, shrinkA=2, shrinkB=2, mutation_scale=1, mutation_aspect=1, **kwargs): """ - There are two ways for defining an arrow: + **Defining the arrow position and path** - - If *posA* and *posB* are given, a path connecting two points is - created according to *connectionstyle*. The path will be - clipped with *patchA* and *patchB* and further shrunken by - *shrinkA* and *shrinkB*. An arrow is drawn along this - resulting path using the *arrowstyle* parameter. + There are two ways to define the arrow position and path: - - Alternatively if *path* is provided, an arrow is drawn along this - path and *patchA*, *patchB*, *shrinkA*, and *shrinkB* are ignored. + - **Start, end and connection**: + The typical approach is to define the start and end points of the + arrow using *posA* and *posB*. The curve between these two can + further be configured using *connectionstyle*. + + If given, the arrow curve is clipped by *patchA* and *patchB*, + allowing it to start/end at the border of these patches. + Additionally, the arrow curve can be shortened by *shrinkA* and *shrinkB* + to create a margin between start/end (after possible clipping) and the + drawn arrow. + + - **path**: Alternatively if *path* is provided, an arrow is drawn along + this Path. In this case, *connectionstyle*, *patchA*, *patchB*, + *shrinkA*, and *shrinkB* are ignored. + + **Styling** + + The *arrowstyle* defines the styling of the arrow head, tail and shaft. + The resulting arrows can be styled further by setting the `.Patch` + properties such as *linewidth*, *color*, *facecolor*, *edgecolor* + etc. via keyword arguments. Parameters ---------- - posA, posB : (float, float), default: None - (x, y) coordinates of arrow tail and arrow head respectively. + posA, posB : (float, float), optional + (x, y) coordinates of start and end point of the arrow. + The actually drawn start and end positions may be modified + through *patchA*, *patchB*, *shrinkA*, and *shrinkB*. - path : `~matplotlib.path.Path`, default: None + *posA*, *posB* are exclusive of *path*. + + path : `~matplotlib.path.Path`, optional If provided, an arrow is drawn along this path and *patchA*, *patchB*, *shrinkA*, and *shrinkB* are ignored. + *path* is exclusive of *posA*, *posB*. + arrowstyle : str or `.ArrowStyle`, default: 'simple' - The `.ArrowStyle` with which the fancy arrow is drawn. If a - string, it should be one of the available arrowstyle names, with - optional comma-separated attributes. The optional attributes are - meant to be scaled with the *mutation_scale*. The following arrow - styles are available: + The styling of arrow head, tail and shaft. This can be + + - `.ArrowStyle` or one of its subclasses + - The shorthand string name (e.g. "->") as given in the table below, + optionally containing a comma-separated list of style parameters, + e.g. "->, head_length=10, head_width=5". + + The style parameters are scaled by *mutation_scale*. + + The following arrow styles are available. See also + :doc:`/gallery/text_labels_and_annotations/fancyarrow_demo`. %(ArrowStyle:table)s + Only the styles ``<|-``, ``-|>``, ``<|-|>`` ``simple``, ``fancy`` + and ``wedge`` contain closed paths and can be filled. + connectionstyle : str or `.ConnectionStyle` or None, optional, \ default: 'arc3' - The `.ConnectionStyle` with which *posA* and *posB* are connected. - If a string, it should be one of the available connectionstyle - names, with optional comma-separated attributes. The following - connection styles are available: + `.ConnectionStyle` with which *posA* and *posB* are connected. + This can be + + - `.ConnectionStyle` or one of its subclasses + - The shorthand string name as given in the table below, e.g. "arc3". %(ConnectionStyle:table)s + Ignored if *path* is provided. + patchA, patchB : `~matplotlib.patches.Patch`, default: None - Head and tail patches, respectively. + Optional Patches at *posA* and *posB*, respectively. If given, + the arrow path is clipped by these patches such that head and tail + are at the border of the patches. + + Ignored if *path* is provided. shrinkA, shrinkB : float, default: 2 - Shrink amount, in points, of the tail and head of the arrow respectively. + Shorten the arrow path at *posA* and *posB* by this amount in points. + This allows to add a margin between the intended start/end points and + the arrow. + + Ignored if *path* is provided. mutation_scale : float, default: 1 Value with which attributes of *arrowstyle* (e.g., *head_length*) From 64c3ccee0298730733179e4c100fa5535f542937 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 10 Apr 2025 23:23:16 +0200 Subject: [PATCH 13/16] Backport PR #29899: [doc] minimally document what basic units is doing --- galleries/examples/units/basic_units.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/galleries/examples/units/basic_units.py b/galleries/examples/units/basic_units.py index 486918a8eafc..f7bdcc18b0dc 100644 --- a/galleries/examples/units/basic_units.py +++ b/galleries/examples/units/basic_units.py @@ -5,6 +5,14 @@ Basic units =========== + +This file implements a units library that supports registering arbitrary units, +conversions between units, and math with unitized data. This library also implements a +Matplotlib unit converter and registers its units with Matplotlib. This library is used +in the examples to demonstrate Matplotlib's unit support. It is only maintained for the +purposes of building documentation and should never be used outside of the Matplotlib +documentation. + """ import itertools From 59b63dd3d911c2c12708397386d02c32247c9430 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 18 Apr 2025 09:38:14 -0400 Subject: [PATCH 14/16] Fix doc build on 3.10.1-doc (cherry picked from commit 09bea955b84937ae177ded93d6384b233de6c707) --- galleries/users_explain/figure/interactive_guide.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/galleries/users_explain/figure/interactive_guide.rst b/galleries/users_explain/figure/interactive_guide.rst index 6cbdca4ab3f9..21658bb5849b 100644 --- a/galleries/users_explain/figure/interactive_guide.rst +++ b/galleries/users_explain/figure/interactive_guide.rst @@ -324,7 +324,7 @@ with what is displayed on the screen. This is intended to be used to determine if ``draw_idle`` should be called to schedule a re-rendering of the figure. -Each artist has a `.Artist.stale_callback` attribute which holds a callback +Each artist has a `!Artist.stale_callback` attribute which holds a callback with the signature :: def callback(self: Artist, val: bool) -> None: @@ -343,7 +343,7 @@ default callback is `None`. If you call `.pyplot.ion` and are not in `~.backend_bases.FigureCanvasBase.draw_idle` on any stale figures after having executed the user's input, but before returning the prompt to the user. If you are not using `.pyplot` you can use the callback -`Figure.stale_callback` attribute to be notified when a figure has +`!Figure.stale_callback` attribute to be notified when a figure has become stale. @@ -424,7 +424,7 @@ IPython / prompt_toolkit With IPython >= 5.0 IPython has changed from using CPython's readline based prompt to a ``prompt_toolkit`` based prompt. ``prompt_toolkit`` has the same conceptual input hook, which is fed into ``prompt_toolkit`` via the -:meth:`IPython.terminal.interactiveshell.TerminalInteractiveShell.inputhook` +:meth:`!IPython.terminal.interactiveshell.TerminalInteractiveShell.inputhook` method. The source for the ``prompt_toolkit`` input hooks lives at ``IPython.terminal.pt_inputhooks``. From 97737f57bef2d36eeb0700e6b1e1e5eac17cc50c Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Tue, 1 Apr 2025 02:47:40 +0200 Subject: [PATCH 15/16] Backport PR #29796: ci: rotate soon-to-be-unsupported GitHub Actions ubuntu-20.04 runner out of roster (cherry picked from commit 0d11978c9f933a9fc7a585891b350c09958e034b) --- .github/workflows/tests.yml | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 91fe6d982455..282b015fcbf1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -48,7 +48,7 @@ jobs: matrix: include: - name-suffix: "(Minimum Versions)" - os: ubuntu-20.04 + os: ubuntu-22.04 python-version: '3.10' extra-requirements: '-c requirements/testing/minver.txt' delete-font-cache: true @@ -57,17 +57,9 @@ jobs: pyqt6-ver: '==6.2.0 PyQt6-Qt6==6.2.0' pyside2-ver: '==5.15.2.1' pyside6-ver: '==6.2.0' - - os: ubuntu-20.04 - python-version: '3.10' - extra-requirements: '-r requirements/testing/extra.txt' - CFLAGS: "-fno-lto" # Ensure that disabling LTO works. - # https://github.com/matplotlib/matplotlib/pull/26052#issuecomment-1574595954 - # https://www.riverbankcomputing.com/pipermail/pyqt/2023-November/045606.html - pyqt6-ver: '!=6.5.1,!=6.6.0,!=6.7.1' - # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346 - pyside6-ver: '!=6.5.1' - os: ubuntu-22.04 python-version: '3.11' + CFLAGS: "-fno-lto" # Ensure that disabling LTO works. # https://www.riverbankcomputing.com/pipermail/pyqt/2023-November/045606.html pyqt6-ver: '!=6.6.0' # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346 @@ -175,11 +167,7 @@ jobs: texlive-luatex \ texlive-pictures \ texlive-xetex - if [[ "${{ matrix.os }}" = ubuntu-20.04 ]]; then - sudo apt-get install -yy --no-install-recommends libopengl0 - else # ubuntu-22.04 - sudo apt-get install -yy --no-install-recommends gir1.2-gtk-4.0 - fi + sudo apt-get install -yy --no-install-recommends gir1.2-gtk-4.0 ;; macOS) brew update From c4c74fd945a9477593bd356afa35accca182854a Mon Sep 17 00:00:00 2001 From: David Stansby Date: Wed, 30 Apr 2025 10:36:32 +0100 Subject: [PATCH 16/16] Backport PR #29789: Improve layout of cheatsheets in sidebar --- doc/_static/mpl.css | 12 ++++++++++++ doc/_templates/cheatsheet_sidebar.html | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/_static/mpl.css b/doc/_static/mpl.css index 9049ddbd8334..022c9c9d63e5 100644 --- a/doc/_static/mpl.css +++ b/doc/_static/mpl.css @@ -207,3 +207,15 @@ div.wide-table table th.stub { .section-toc.toctree-wrapper li>ul{ padding-inline-start:0; } + +.sidebar-cheatsheets { + margin-bottom: 3em; +} + +.sidebar-cheatsheets > h3 { + margin-top: 0; +} + +.sidebar-cheatsheets > img { + width: 100%; +} diff --git a/doc/_templates/cheatsheet_sidebar.html b/doc/_templates/cheatsheet_sidebar.html index 3f2b7c4f4db1..2ca6548ddd4d 100644 --- a/doc/_templates/cheatsheet_sidebar.html +++ b/doc/_templates/cheatsheet_sidebar.html @@ -1,6 +1,6 @@