Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a59d1d2
Backport PR #30960: SVG backend - handle font weight as integer
steveberardi Jan 14, 2026
58d5aea
Merge pull request #30964 from meeseeksmachine/auto-backport-of-pr-30…
timhoffm Jan 14, 2026
bc44318
Backport PR #30952: DOC: Tutorial on API shortcuts
timhoffm Jan 15, 2026
521df0b
Merge pull request #30965 from meeseeksmachine/auto-backport-of-pr-30…
timhoffm Jan 15, 2026
8c7d40f
Backport PR #30969: DOC: Simplify barh() example
rcomer Jan 15, 2026
df313af
Merge pull request #30971 from meeseeksmachine/auto-backport-of-pr-30…
rcomer Jan 15, 2026
89a35d8
Backport PR #30985: MNT: do not assign a numpy array shape
scottshambaugh Jan 17, 2026
50d13e4
Merge pull request #30986 from meeseeksmachine/auto-backport-of-pr-30…
timhoffm Jan 17, 2026
2deb54c
Backport PR #31035: DOCS: Fix typo in time array step size comment
rcomer Jan 26, 2026
8db8148
Merge pull request #31036 from meeseeksmachine/auto-backport-of-pr-31…
rcomer Jan 26, 2026
313a44d
Backport PR #31075: Fix remove method for figure title and xy-labels
QuLogic Feb 4, 2026
b9d7e7f
Backport PR #31153: TST: Use correct method of clearing mock objects
ksunden Feb 13, 2026
cc7fe5a
Merge pull request #31154 from meeseeksmachine/auto-backport-of-pr-31…
timhoffm Feb 13, 2026
ef19bdc
Backport PR #31278: Fix `clabel` manual argument not accepting unit-t…
aman-coder03 Mar 11, 2026
f32af1d
Backport PR #31323: FIX: Prevent crash when removing a subfigure cont…
Vikash-Kumar-23 Mar 27, 2026
6aac3da
Backport PR #31401: BLD: Temporarily pin setuptools-scm<10
QuLogic Mar 27, 2026
9220b77
Merge pull request #31418 from rcomer/pin-setuptools-scm-backport
timhoffm Mar 29, 2026
3c91aec
Backport PR #31420: Fix outdated Savannah URL for freetype download
timhoffm Mar 29, 2026
b9163f8
Merge pull request #31421 from meeseeksmachine/auto-backport-of-pr-31…
rcomer Mar 29, 2026
51c85f7
Merge pull request #31411 from meeseeksmachine/auto-backport-of-pr-31…
rcomer Mar 29, 2026
69e6954
Backport PR #31437: mathtext: Fix type inconsistency with fontmaps
tacaswell Apr 2, 2026
cada119
Bump mimimum Ubuntu Version on Azure because 20.04 is EOL
ksunden Apr 3, 2026
45ac295
Merge pull request #31445 from ksunden/auto-backport-of-pr-31437-on-v…
QuLogic Apr 7, 2026
614abdd
Backport PR #31504: Re-order variants to prioritize narrower types
QuLogic Apr 16, 2026
6e203dc
Merge pull request #31511 from meeseeksmachine/auto-backport-of-pr-31…
ksunden Apr 17, 2026
2da812c
Backport PR #31020: DOC: Fix doc builds with Sphinx 9
timhoffm Jan 24, 2026
52059e4
Merge pull request #31520 from meeseeksmachine/auto-backport-of-pr-31…
ksunden Apr 21, 2026
851f769
Merge pull request #31280 from meeseeksmachine/auto-backport-of-pr-31…
ksunden Apr 21, 2026
e3fb541
Merge pull request #31078 from meeseeksmachine/auto-backport-of-pr-31…
ksunden Apr 21, 2026
b2ed196
Backport PR #31248: SEC: Remove eval() from validate_cycler
scottshambaugh Mar 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/cygwin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ jobs:
export PATH="/usr/local/bin:$PATH"
python -m pip install --no-build-isolation 'contourpy>=1.0.1'
python -m pip install --upgrade cycler fonttools \
packaging pyparsing python-dateutil setuptools-scm \
packaging pyparsing python-dateutil 'setuptools-scm<10' \
-r requirements_test.txt sphinx ipython
python -m pip install --upgrade pycairo 'cairocffi>=0.8' PyGObject &&
python -c 'import gi; gi.require_version("Gtk", "3.0"); from gi.repository import Gtk' &&
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ jobs:
# Preinstall build requirements to enable no-build-isolation builds.
python -m pip install --upgrade $PRE \
'contourpy>=1.0.1' cycler fonttools kiwisolver importlib_resources \
packaging pillow 'pyparsing!=3.1.0' python-dateutil setuptools-scm \
packaging pillow 'pyparsing!=3.1.0' python-dateutil 'setuptools-scm<10' \
'meson-python>=0.13.1' 'pybind11>=2.13.2' \
-r requirements/testing/all.txt \
${{ matrix.extra-requirements }}
Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ stages:
strategy:
matrix:
Linux_py310:
vmImage: 'ubuntu-20.04' # keep one job pinned to the oldest image
vmImage: 'ubuntu-22.04' # keep one job pinned to the oldest image
python.version: '3.10'
Linux_py311:
vmImage: 'ubuntu-latest'
Expand Down
1 change: 0 additions & 1 deletion ci/mypy-stubtest-allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ matplotlib\.ticker\.LogitLocator\.nonsingular

# Stdlib/Enum considered inconsistent (no fault of ours, I don't think)
matplotlib\.backend_bases\._Mode\.__new__
matplotlib\.units\.Number\.__hash__

# 3.6 Pending deprecations
matplotlib\.figure\.Figure\.set_constrained_layout
Expand Down
9 changes: 9 additions & 0 deletions doc/api/next_api_changes/deprecations/31248-SS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Arbitrary code in ``axes.prop_cycle`` rcParam strings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``axes.prop_cycle`` rcParam accepts Python expressions that are evaluated
in a limited context. The evaluation context has been further limited and some
expressions that previously worked (list comprehensions, for example) no longer
will. This change is made without a deprecation period to improve security.
The previously documented cycler operations at
https://matplotlib.org/cycler/ are still supported.
1 change: 1 addition & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -891,3 +891,4 @@ def setup(app):
if sphinx.version_info[:2] < (7, 1):
app.connect('html-page-context', add_html_cache_busting, priority=1000)
generate_ScalarMappable_docs()
app.config.autodoc_use_legacy_class_based = True
14 changes: 14 additions & 0 deletions doc/users/next_whats_new/cycler_rcparam_security.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
``axes.prop_cycle`` rcParam security improvements
-------------------------------------------------

The ``axes.prop_cycle`` rcParam is now parsed in a safer and more restricted
manner. Only literals, ``cycler()`` and ``concat()`` calls, the operators
``+`` and ``*``, and slicing are allowed. All previously valid cycler strings
documented at https://matplotlib.org/cycler/ are still supported, for example:

.. code-block:: none

axes.prop_cycle : cycler('color', ['r', 'g', 'b']) + cycler('linewidth', [1, 2, 3])
axes.prop_cycle : 2 * cycler('color', 'rgb')
axes.prop_cycle : concat(cycler('color', 'rgb'), cycler('color', 'cmk'))
axes.prop_cycle : cycler('color', 'rgbcmk')[:3]
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies:
- pyqt
- python>=3.10
- python-dateutil>=2.1
- setuptools_scm
- setuptools_scm<10
- wxpython
# building documentation
- colorspacious
Expand Down
2 changes: 1 addition & 1 deletion galleries/examples/animation/double_pendulum.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def derivs(t, state):

return dydx

# create a time array from 0..t_stop sampled at 0.02 second steps
# create a time array from 0..t_stop sampled at 0.01 second steps
dt = 0.01
t = np.arange(0, t_stop, dt)

Expand Down
4 changes: 1 addition & 3 deletions galleries/examples/lines_bars_and_markers/barh.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@

# Example data
people = ('Tom', 'Dick', 'Harry', 'Slim', 'Jim')
y_pos = np.arange(len(people))
performance = 3 + 10 * np.random.rand(len(people))
error = np.random.rand(len(people))

ax.barh(y_pos, performance, xerr=error, align='center')
ax.set_yticks(y_pos, labels=people)
ax.barh(people, performance, xerr=error, align='center')
ax.invert_yaxis() # labels read top-to-bottom
ax.set_xlabel('Performance')
ax.set_title('How fast do you want to go today?')
Expand Down
172 changes: 172 additions & 0 deletions galleries/tutorials/coding_shortcuts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
"""
================
Coding shortcuts
================

Matplotlib's primary and universal API is the :ref:`Axes interface <api_interfaces>`.
While it is clearly structured and powerful, it can sometimes feel overly verbose and
thus cumbersome to write. This page collects patterns for condensing the code
of the Axes-based API and achieving the same results with less typing for many simpler
plots.

.. note::

The :ref:`pyplot interface <pyplot_interface>` is an alternative more compact
interface, and was historically modeled to be similar to MATLAB. It remains a
valid approach for those who want to use it. However, it has the disadvantage that
it achieves its brevity through implicit assumptions that you have to understand.

Since it follows a different paradigm, switching between the Axes interface and
the pyplot interface requires a shift of the mental model, and some code rewrite,
if the code develops to a point at which pyplot no longer provides enough
flexibility.

This tutorial goes the other way round, starting from the standard verbose Axes
interface and using its capabilities for shortcuts when you don't need all the
generality.

Let's assume we want to make a plot of the number of daylight hours per day over the
year in London.

The standard approach with the Axes interface looks like this.
"""

import matplotlib.pyplot as plt
import numpy as np

day = np.arange(365)
hours = 4.276 * np.sin(2 * np.pi * (day - 80)/365) + 12.203

fig, ax = plt.subplots()
ax.plot(day, hours, color="orange")
ax.set_xlabel("day")
ax.set_ylabel("daylight hours")
ax.set_title("London")
plt.show()

# %%
# Note that we've included ``plt.show()`` here. This is needed to show the plot window
# when running from a command line or in a Python script. If you run a Jupyter notebook,
# this command is automatically executed at the end of each cell.
#
# For the rest of the tutorial, we'll assume that we are in a notebook and leave this
# out for brevity. Depending on your context you may still need it.
#
# If you instead want to save to a file, use ``fig.savefig("daylight.png")``.
#
#
# Collect Axes properties into a single ``set()`` call
# ====================================================
#
# The properties of Matplotlib Artists can be modified through their respective
# ``set_*()`` methods. Artists additionally have a generic ``set()`` method, that takes
# keyword arguments and is equivalent to calling all the respective ``set_*()`` methods.
# ::
#
# ax.set_xlabel("day")
# ax.set_ylabel("daylight hours")
#
# can also be written as ::
#
# ax.set(xlabel="day", ylabel="daylight hours")
#
# This is the most simple and effective reduction you can do. With that we can shorten
# the above plot to

fig, ax = plt.subplots()
ax.plot(day, hours, color="orange")
ax.set(xlabel="day", ylabel="daylight hours", title="London")

# %%
#
# This works as long as you only need to pass one parameter to the ``set_*()`` function.
# The individual functions are still necessary if you want more control, e.g.
# ``set_title("London", fontsize=16)``.
#
#
# Not storing a reference to the figure
# =====================================
# Another nuisance of ``fig, ax = plt.subplots()`` is that you always create a ``fig``
# variable, even if you don't use it. A slightly shorter version would be using the
# standard variable for unused value in Python (``_``): ``_, ax = plt.subplots()``.
# However, that's only marginally better.
#
# You can work around this by separating figure and Axes creation and chaining them ::
#
# ax = plt.figure().add_subplot()
#
# This is a bit cleaner logically and has the slight advantage that you could set
# figure properties inline as well; e.g. ``plt.figure(facecolor="lightgoldenrod")``.
# But it has the disadvantage that it's longer than ``fig, ax = plt.subplots()``.
#
# You can still obtain the figure from the Axes if needed, e.g. ::
#
# ax.figure.savefig("daylight_hours.png")
#
# The example code now looks like this:

ax = plt.figure().add_subplot()
ax.plot(day, hours, color="orange")
ax.set(xlabel="day", ylabel="daylight hours", title="London")

# %%
# Define Axes properties during axes creation
# ===========================================
# The ``set_*`` methods as well as ``set`` modify existing objects. You can
# alternatively define them right at creation. Since you typically don't instantiate
# classes yourself in Matplotlib, but rather call some factory function that creates
# the object and wires it up correctly with the plot, this may seem less obvious. But
# in fact you just pass the desired properties to the factory functions. You are likely
# doing this already in some places without realizing. Consider the function to create
# a line ::
#
# ax.plot(x, y, color="orange")
#
# This is equivalent to ::
#
# line, = ax.plot(x, y)
# line.set_color("orange")
#
# The same can be done with functions that create Axes.

ax = plt.figure().add_subplot(xlabel="day", ylabel="daylight hours", title="London")
ax.plot(day, hours, color="orange")

# %%
# .. important::
# The Axes properties are only accepted as keyword arguments by
# `.Figure.add_subplot`, which creates a single Axes.
#
# For `.Figure.subplots` and `.pyplot.subplots`, you'd have to pass the properties
# as a dict via the keyword argument ``subplot_kw``. The limitation here is that
# such parameters are given to all Axes. For example, if you need two subplots
# (``fig, (ax1, ax2) = plt.subplots(1, 2)``) with different labels, you have to
# set them individually.
#
# Defining Axes properties during creation is best used for single subplots or when
# all subplots share the same properties.
#
#
# Using implicit figure creation
# ==============================
# You can go even further by tapping into the pyplot logic and use `.pyplot.axes` to
# create the axes:

ax = plt.axes(xlabel="day", ylabel="daylight hours", title="London")
ax.plot(day, hours, color="orange")

# %%
# .. warning::
# When using this, you have to be aware of the implicit figure semantics of pyplot.
# ``plt.axes()`` will only create a new figure if no figure exists. Otherwise, it
# will add the Axes to the current existing figure, which is likely not what you
# want.
#
# Not storing a reference to the Axes
# ===================================
# If you only need to visualize one dataset, you can append the plot command
# directly to the Axes creation. This may be useful e.g. in notebooks,
# where you want to create a plot with some configuration, but as little distracting
# code as possible:

plt.axes(xlabel="day", ylabel="daylight hours").plot(day, hours, color="orange")
18 changes: 18 additions & 0 deletions galleries/tutorials/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@ a :ref:`FAQ <howto-faq>` in our :ref:`user guide <users-guide-index>`.
</div>


.. raw:: html

<div class="sphx-glr-thumbcontainer" tooltip="Coding shortcuts">

.. only:: html

.. image:: /tutorials/images/thumb/sphx_glr_coding_shortcuts_thumb.png
:alt: Coding shortcuts

:ref:`sphx_glr_tutorials_coding_shortcuts.py`

.. raw:: html

<div class="sphx-glr-thumbnail-title">Coding shortcuts</div>
</div>


.. raw:: html

<div class="sphx-glr-thumbcontainer" tooltip="A short tutorial on plotting images with Matplotlib.">
Expand Down Expand Up @@ -92,6 +109,7 @@ a :ref:`FAQ <howto-faq>` in our :ref:`user guide <users-guide-index>`.
:hidden:

/tutorials/pyplot
/tutorials/coding_shortcuts
/tutorials/images
/tutorials/lifecycle
/tutorials/artists
Expand Down
Loading
Loading