diff --git a/.appveyor.yml b/.appveyor.yml
index 87f6cbde6384..a637fe545466 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -1,7 +1,6 @@
# With infos from
# http://tjelvarolsson.com/blog/how-to-continuously-test-your-python-code-on-windows-using-appveyor/
# https://packaging.python.org/en/latest/appveyor/
-# https://github.com/rmcgibbo/python-appveyor-conda-example
---
# Backslashes in quotes need to be escaped: \ -> "\\"
@@ -18,7 +17,7 @@ skip_commits:
clone_depth: 50
-image: Visual Studio 2017
+image: Visual Studio 2019
environment:
@@ -30,7 +29,6 @@ environment:
matrix:
- PYTHON_VERSION: "3.11"
- CONDA_INSTALL_LOCN: "C:\\Miniconda3-x64"
TEST_ALL: "yes"
# We always use a 64-bit machine, but can build x86 distributions
@@ -46,35 +44,32 @@ cache:
- '%USERPROFILE%\.cache\matplotlib'
init:
- - echo %PYTHON_VERSION% %CONDA_INSTALL_LOCN%
+ - ps:
+ Invoke-Webrequest
+ -URI https://micro.mamba.pm/api/micromamba/win-64/latest
+ -OutFile C:\projects\micromamba.tar.bz2
+ - ps: C:\PROGRA~1\7-Zip\7z.exe x C:\projects\micromamba.tar.bz2 -aoa -oC:\projects\
+ - ps: C:\PROGRA~1\7-Zip\7z.exe x C:\projects\micromamba.tar -ttar -aoa -oC:\projects\
+ - 'set PATH=C:\projects\Library\bin;%PATH%'
+ - micromamba shell init --shell cmd.exe
+ - micromamba config set always_yes true
+ - micromamba config prepend channels conda-forge
+ - micromamba info
install:
- - set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH%;
- - conda config --set always_yes true
- - conda config --set show_channel_urls yes
- - conda config --prepend channels conda-forge
-
- # For building, use a new environment
- # Add python version to environment
- # `^ ` escapes spaces for indentation
- - echo ^ ^ - python=%PYTHON_VERSION% >> environment.yml
- - conda env create -f environment.yml
- - activate mpl-dev
- - conda install -c conda-forge pywin32
- - echo %PYTHON_VERSION% %TARGET_ARCH%
- # Show the installed packages + versions
- - conda list
+ - micromamba env create -f environment.yml python=%PYTHON_VERSION% pywin32
+ - micromamba activate mpl-dev
test_script:
# Now build the thing..
- set LINK=/LIBPATH:%cd%\lib
- - pip install -v --no-build-isolation --config-settings=setup-args="--vsenv" --editable .[dev]
+ - pip install -v --no-build-isolation --editable .[dev]
# this should show no freetype dll...
- set "DUMPBIN=%VS140COMNTOOLS%\..\..\VC\bin\dumpbin.exe"
- '"%DUMPBIN%" /DEPENDENTS lib\matplotlib\ft2font*.pyd | findstr freetype.*.dll && exit /b 1 || exit /b 0'
# this are optional dependencies so that we don't skip so many tests...
- - if x%TEST_ALL% == xyes conda install -q ffmpeg inkscape
+ - if x%TEST_ALL% == xyes micromamba install -q ffmpeg inkscape
# miktex is available on conda, but seems to fail with permission errors.
# missing packages on conda-forge for imagemagick
# This install sometimes failed randomly :-(
@@ -95,8 +90,8 @@ artifacts:
type: Zip
on_finish:
- - conda install codecov
- - codecov -e PYTHON_VERSION PLATFORM -n "$PYTHON_VERSION Windows"
+ - micromamba install codecov
+ - codecov -e PYTHON_VERSION PLATFORM -n "%PYTHON_VERSION% Windows"
on_failure:
# Generate a html for visual tests
diff --git a/.circleci/config.yml b/.circleci/config.yml
index eef9ca87f30d..40ba933cf0d9 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -103,10 +103,12 @@ commands:
- run:
name: Install Python dependencies
command: |
- python -m pip install --user meson-python numpy pybind11 setuptools-scm
+ python -m pip install --user -r requirements/dev/build-requirements.txt
python -m pip install --user \
numpy<< parameters.numpy_version >> \
-r requirements/doc/doc-requirements.txt
+ python -m pip install --no-deps --user \
+ git+https://github.com/matplotlib/mpl-sphinx-theme.git
mpl-install:
steps:
@@ -145,7 +147,7 @@ commands:
export RELEASE_TAG='-t release'
fi
mkdir -p logs
- make html O="-T $RELEASE_TAG -j1 -w /tmp/sphinxerrorswarnings.log"
+ make html O="-T $RELEASE_TAG -j4 -w /tmp/sphinxerrorswarnings.log"
rm -r build/html/_sources
working_directory: doc
- save_cache:
@@ -214,9 +216,9 @@ commands:
#
jobs:
- docs-python39:
+ docs-python3:
docker:
- - image: cimg/python:3.9
+ - image: cimg/python:3.12
resource_class: large
steps:
- checkout
@@ -257,4 +259,4 @@ workflows:
jobs:
# NOTE: If you rename this job, then you must update the `if` condition
# and `circleci-jobs` option in `.github/workflows/circleci.yml`.
- - docs-python39
+ - docs-python3
diff --git a/.flake8 b/.flake8
deleted file mode 100644
index 36e8bcf5476f..000000000000
--- a/.flake8
+++ /dev/null
@@ -1,90 +0,0 @@
-[flake8]
-max-line-length = 88
-select =
- # flake8 default
- D, E, F, W,
-ignore =
- # flake8 default
- E121,E123,E126,E226,E24,E704,W503,W504,
- # Additional ignores:
- E127, E131,
- E266,
- E305, E306,
- E741,
- F841,
- # pydocstyle
- D100, D101, D102, D103, D104, D105, D106,
- D200, D202, D204, D205,
- D301,
- D400, D401, D403, D404
- # ignored by pydocstyle numpy docstring convention
- D107, D203, D212, D402, D413, D415, D416, D417,
- # while D213 is ignored by the numpy docstring convention, it's left out above,
- # because we want to enforce it.
-
-exclude =
- .git
- build
- doc/gallery
- doc/tutorials
- # External files.
- tools/gh_api.py
- .tox
- .eggs
-
-per-file-ignores =
- lib/matplotlib/_cm.py: E202, E203, E302
- lib/matplotlib/_mathtext.py: E221, E251
- lib/matplotlib/_mathtext_data.py: E203, E261
- lib/matplotlib/backends/backend_template.py: F401
- lib/matplotlib/mathtext.py: E221
- lib/matplotlib/pylab.py: F401, F403
- lib/matplotlib/pyplot.py: F811
- lib/matplotlib/tests/test_mathtext.py: E501
- lib/matplotlib/transforms.py: E201, E202, E203
- lib/matplotlib/tri/_triinterpolate.py: E201, E221
- lib/mpl_toolkits/axes_grid1/axes_size.py: E272
- lib/mpl_toolkits/axisartist/angle_helper.py: E221
-
- doc/conf.py: E402
- galleries/users_explain/quick_start.py: E402
- galleries/users_explain/artists/paths.py: E402
- galleries/users_explain/artists/patheffects_guide.py: E402
- galleries/users_explain/artists/transforms_tutorial.py: E402, E501
- galleries/users_explain/colors/colormaps.py: E501
- galleries/users_explain/colors/colors.py: E402
- galleries/tutorials/artists.py: E402
- galleries/users_explain/axes/constrainedlayout_guide.py: E402
- galleries/users_explain/axes/legend_guide.py: E402
- galleries/users_explain/axes/tight_layout_guide.py: E402
- galleries/users_explain/animations/animations.py: E501
- galleries/tutorials/images.py: E501
- galleries/tutorials/pyplot.py: E402, E501
- galleries/users_explain/text/annotations.py: E402, E501
- galleries/users_explain/text/mathtext.py: E501
- galleries/users_explain/text/text_intro.py: E402
- galleries/users_explain/text/text_props.py: E501
-
- galleries/examples/animation/frame_grabbing_sgskip.py: E402
- galleries/examples/images_contours_and_fields/tricontour_demo.py: E201
- galleries/examples/images_contours_and_fields/tripcolor_demo.py: E201
- galleries/examples/images_contours_and_fields/triplot_demo.py: E201
- galleries/examples/lines_bars_and_markers/marker_reference.py: E402
- galleries/examples/misc/print_stdout_sgskip.py: E402
- galleries/examples/misc/table_demo.py: E201
- galleries/examples/style_sheets/bmh.py: E501
- galleries/examples/subplots_axes_and_figures/demo_constrained_layout.py: E402
- galleries/examples/text_labels_and_annotations/custom_legends.py: E402
- galleries/examples/ticks/date_concise_formatter.py: E402
- galleries/examples/ticks/date_formatters_locators.py: F401
- galleries/examples/user_interfaces/embedding_in_gtk3_panzoom_sgskip.py: E402
- galleries/examples/user_interfaces/embedding_in_gtk3_sgskip.py: E402
- galleries/examples/user_interfaces/embedding_in_gtk4_panzoom_sgskip.py: E402
- galleries/examples/user_interfaces/embedding_in_gtk4_sgskip.py: E402
- galleries/examples/user_interfaces/gtk3_spreadsheet_sgskip.py: E402
- galleries/examples/user_interfaces/gtk4_spreadsheet_sgskip.py: E402
- galleries/examples/user_interfaces/mpl_with_glade3_sgskip.py: E402
- galleries/examples/user_interfaces/pylab_with_gtk3_sgskip.py: E402
- galleries/examples/user_interfaces/pylab_with_gtk4_sgskip.py: E402
- galleries/examples/userdemo/pgf_preamble_sgskip.py: E402
-force-check = True
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 613852425632..611431e707ab 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -12,3 +12,6 @@ c1a33a481b9c2df605bcb9bef9c19fe65c3dac21
# chore: pyupgrade --py39-plus
4d306402bb66d6d4c694d8e3e14b91054417070e
+
+# style: docstring parameter indentation
+68daa962de5634753205cba27f21d6edff7be7a2
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 045386dc7402..a19b6d2346e3 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -15,7 +15,9 @@ body:
attributes:
label: Code for reproduction
description: >-
- If possible, please provide a minimum self-contained example.
+ If possible, please provide a minimum self-contained example. If you
+ have used generative AI as an aid see
+ https://matplotlib.org/devdocs/devel/contribute.html#restrictions-on-generative-ai-usage
placeholder: Paste your code here. This field is automatically formatted as Python code.
render: Python
validations:
diff --git a/.github/ISSUE_TEMPLATE/tag_proposal.yml b/.github/ISSUE_TEMPLATE/tag_proposal.yml
index aa3345336089..2bb856d26be6 100644
--- a/.github/ISSUE_TEMPLATE/tag_proposal.yml
+++ b/.github/ISSUE_TEMPLATE/tag_proposal.yml
@@ -2,7 +2,7 @@
name: Tag Proposal
description: Suggest a new tag or subcategory for the gallery of examples
title: "[Tag]: "
-labels: [Tag proposal]
+labels: ["Documentation: tags"]
body:
- type: markdown
attributes:
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 7f17a80dc4b6..bf483dbdd4f4 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -4,13 +4,20 @@ out the development guide https://matplotlib.org/devdocs/devel/index.html
-->
## PR summary
-
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 43a1246ba68a..75adfed57f43 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -89,6 +89,7 @@
- 'doc/conf.py'
- 'doc/Makefile'
- 'doc/make.bat'
+ - 'doc/sphinxext/**'
"Documentation: devdocs":
- changed-files:
- any-glob-to-any-file:
diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml
index aa0366ad16ff..9ced8e2f5060 100644
--- a/.github/workflows/cibuildwheel.yml
+++ b/.github/workflows/cibuildwheel.yml
@@ -34,19 +34,20 @@ jobs:
'CI: Run cibuildwheel')
)
name: Build sdist
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-latest
outputs:
SDIST_NAME: ${{ steps.sdist.outputs.SDIST_NAME }}
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
+ persist-credentials: false
- - uses: actions/setup-python@v5
+ - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
name: Install Python
with:
- python-version: 3.9
+ python-version: '3.11'
# Something changed somewhere that prevents the downloaded-at-build-time
# licenses from being included in built wheels, so pre-download them so
@@ -69,7 +70,7 @@ jobs:
run: twine check dist/*
- name: Upload sdist result
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: cibw-sdist
path: dist/*.tar.gz
@@ -114,13 +115,12 @@ jobs:
CIBW_TEST_COMMAND: >-
python {package}/ci/check_version_number.py
MACOSX_DEPLOYMENT_TARGET: "10.12"
- MPL_DISABLE_FH4: "yes"
strategy:
matrix:
include:
- - os: ubuntu-20.04
+ - os: ubuntu-latest
cibw_archs: "x86_64"
- - os: ubuntu-20.04
+ - os: ubuntu-24.04-arm
cibw_archs: "aarch64"
- os: windows-latest
cibw_archs: "auto64"
@@ -130,38 +130,25 @@ jobs:
cibw_archs: "arm64"
steps:
- - name: Set up QEMU
- if: matrix.cibw_archs == 'aarch64'
- uses: docker/setup-qemu-action@v3
- with:
- platforms: arm64
-
- name: Download sdist
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: cibw-sdist
path: dist/
- name: Build wheels for CPython 3.13
- uses: pypa/cibuildwheel@7940a4c0e76eb2030e473a5f864f291f63ee879b # v2.21.3
+ uses: pypa/cibuildwheel@faf86a6ed7efa889faf6996aa23820831055001a # v2.23.3
with:
package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }}
env:
CIBW_BUILD: "cp313-* cp313t-*"
- CIBW_BUILD_FRONTEND:
- "pip; args: --pre --extra-index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple"
- CIBW_FREE_THREADED_SUPPORT: true
+ CIBW_ENABLE: cpython-freethreading
# No free-threading wheels available for aarch64 on Pillow.
CIBW_TEST_SKIP: "cp313t-manylinux_aarch64"
- # We need pre-releases to get the nightly wheels.
- CIBW_BEFORE_TEST: >-
- pip install --pre
- --extra-index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
- contourpy numpy pillow
CIBW_ARCHS: ${{ matrix.cibw_archs }}
- name: Build wheels for CPython 3.12
- uses: pypa/cibuildwheel@7940a4c0e76eb2030e473a5f864f291f63ee879b # v2.21.3
+ uses: pypa/cibuildwheel@faf86a6ed7efa889faf6996aa23820831055001a # v2.23.3
with:
package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }}
env:
@@ -169,39 +156,27 @@ jobs:
CIBW_ARCHS: ${{ matrix.cibw_archs }}
- name: Build wheels for CPython 3.11
- uses: pypa/cibuildwheel@7940a4c0e76eb2030e473a5f864f291f63ee879b # v2.21.3
+ uses: pypa/cibuildwheel@faf86a6ed7efa889faf6996aa23820831055001a # v2.23.3
with:
package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }}
env:
CIBW_BUILD: "cp311-*"
CIBW_ARCHS: ${{ matrix.cibw_archs }}
- - name: Build wheels for CPython 3.10
- uses: pypa/cibuildwheel@7940a4c0e76eb2030e473a5f864f291f63ee879b # v2.21.3
- with:
- package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }}
- env:
- CIBW_BUILD: "cp310-*"
- CIBW_ARCHS: ${{ matrix.cibw_archs }}
-
- - name: Build wheels for CPython 3.9
- uses: pypa/cibuildwheel@7940a4c0e76eb2030e473a5f864f291f63ee879b # v2.21.3
- with:
- package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }}
- env:
- CIBW_BUILD: "cp39-*"
- CIBW_ARCHS: ${{ matrix.cibw_archs }}
- name: Build wheels for PyPy
- uses: pypa/cibuildwheel@7940a4c0e76eb2030e473a5f864f291f63ee879b # v2.21.3
+ uses: pypa/cibuildwheel@faf86a6ed7efa889faf6996aa23820831055001a # v2.23.3
with:
package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }}
env:
- CIBW_BUILD: "pp39-*"
+ CIBW_BUILD: "pp311-*"
CIBW_ARCHS: ${{ matrix.cibw_archs }}
- if: matrix.cibw_archs != 'aarch64'
+ CIBW_ENABLE: pypy
+ # No wheels available for Pillow with pp311 yet.
+ CIBW_TEST_SKIP: "pp311*"
+ if: matrix.cibw_archs != 'aarch64' && matrix.os != 'windows-latest'
- - uses: actions/upload-artifact@v4
+ - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: cibw-wheels-${{ runner.os }}-${{ matrix.cibw_archs }}
path: ./wheelhouse/*.whl
@@ -219,7 +194,7 @@ jobs:
contents: read
steps:
- name: Download packages
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
pattern: cibw-*
path: dist
@@ -229,9 +204,9 @@ jobs:
run: ls dist
- name: Generate artifact attestation for sdist and wheel
- uses: actions/attest-build-provenance@ef244123eb79f2f7a7e75d99086184180e6d0018 # v1.4.4
+ uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0
with:
subject-path: dist/matplotlib-*
- name: Publish package distributions to PyPI
- uses: pypa/gh-action-pypi-publish@15c56dba361d8335944d31a2ecd17d700fc7bcbc # v1.12.2
+ uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
diff --git a/.github/workflows/circleci.yml b/.github/workflows/circleci.yml
index 3aead720cf20..f0ae304882e7 100644
--- a/.github/workflows/circleci.yml
+++ b/.github/workflows/circleci.yml
@@ -3,7 +3,7 @@ name: "CircleCI artifact handling"
on: [status]
jobs:
circleci_artifacts_redirector_job:
- if: "${{ github.event.context == 'ci/circleci: docs-python39' }}"
+ if: "${{ github.event.context == 'ci/circleci: docs-python3' }}"
permissions:
statuses: write
runs-on: ubuntu-latest
@@ -16,11 +16,11 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
api-token: ${{ secrets.CIRCLECI_TOKEN }}
artifact-path: 0/doc/build/html/index.html
- circleci-jobs: docs-python39
+ circleci-jobs: docs-python3
job-title: View the built docs
post_warnings_as_review:
- if: "${{ github.event.context == 'ci/circleci: docs-python39' }}"
+ if: "${{ github.event.context == 'ci/circleci: docs-python3' }}"
permissions:
contents: read
checks: write
@@ -28,16 +28,20 @@ jobs:
runs-on: ubuntu-latest
name: Post warnings/errors as review
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
- name: Fetch result artifacts
id: fetch-artifacts
+ env:
+ target_url: "${{ github.event.target_url }}"
run: |
- python .circleci/fetch_doc_logs.py "${{ github.event.target_url }}"
+ python .circleci/fetch_doc_logs.py "${target_url}"
- name: Set up reviewdog
if: "${{ steps.fetch-artifacts.outputs.count != 0 }}"
- uses: reviewdog/action-setup@v1
+ uses: reviewdog/action-setup@e04ffabe3898a0af8d0fb1af00c188831c4b5893 # v1.3.2
with:
reviewdog_version: latest
diff --git a/.github/workflows/clean_pr.yml b/.github/workflows/clean_pr.yml
index 77e49f7c1d9e..fc9021c920c0 100644
--- a/.github/workflows/clean_pr.yml
+++ b/.github/workflows/clean_pr.yml
@@ -10,9 +10,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: '0'
+ persist-credentials: false
- name: Check for added-and-deleted files
run: |
git fetch --quiet origin "$GITHUB_BASE_REF"
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 203b0eee9ca4..774de9b116d8 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -26,10 +26,12 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
- name: Initialize CodeQL
- uses: github/codeql-action/init@v3
+ uses: github/codeql-action/init@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
with:
languages: ${{ matrix.language }}
@@ -40,4 +42,4 @@ jobs:
pip install --user -v .
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v3
+ uses: github/codeql-action/analyze@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
diff --git a/.github/workflows/conflictcheck.yml b/.github/workflows/conflictcheck.yml
index 3110839e5150..c426c4d6c399 100644
--- a/.github/workflows/conflictcheck.yml
+++ b/.github/workflows/conflictcheck.yml
@@ -9,15 +9,14 @@ on:
pull_request_target:
types: [synchronize]
-permissions:
- pull-requests: write
-
jobs:
main:
runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
steps:
- name: Check if PRs have merge conflicts
- uses: eps1lon/actions-label-merge-conflict@1b1b1fcde06a9b3d089f3464c96417961dde1168 # v3.0.2
+ uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3
with:
dirtyLabel: "status: needs rebase"
repoToken: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml
index a3f93ba195a8..4a5b79c0538e 100644
--- a/.github/workflows/cygwin.yml
+++ b/.github/workflows/cygwin.yml
@@ -48,10 +48,12 @@ jobs:
test-cygwin:
runs-on: windows-latest
name: Python 3.${{ matrix.python-minor-version }} on Cygwin
+ # Enable these when Cygwin has Python 3.12.
if: >-
github.event_name == 'workflow_dispatch' ||
- github.event_name == 'schedule' ||
+ (false && github.event_name == 'schedule') ||
(
+ false &&
github.repository == 'matplotlib/matplotlib' &&
!contains(github.event.head_commit.message, '[ci skip]') &&
!contains(github.event.head_commit.message, '[skip ci]') &&
@@ -71,17 +73,18 @@ jobs:
)
strategy:
matrix:
- python-minor-version: [9]
+ python-minor-version: [12]
steps:
- name: Fix line endings
run: git config --global core.autocrlf input
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
+ persist-credentials: false
- - uses: cygwin/cygwin-install-action@v4
+ - uses: cygwin/cygwin-install-action@f61179d72284ceddc397ed07ddb444d82bf9e559 # v5
with:
packages: >-
ccache gcc-g++ gdb git graphviz libcairo-devel libffi-devel
@@ -137,21 +140,21 @@ jobs:
# FreeType build fails with bash, succeeds with dash
- name: Cache pip
- uses: actions/cache@v4
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: C:\cygwin\home\runneradmin\.cache\pip
key: Cygwin-py3.${{ matrix.python-minor-version }}-pip-${{ hashFiles('requirements/*/*.txt') }}
restore-keys: ${{ matrix.os }}-py3.${{ matrix.python-minor-version }}-pip-
- name: Cache ccache
- uses: actions/cache@v4
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: C:\cygwin\home\runneradmin\.ccache
key: Cygwin-py3.${{ matrix.python-minor-version }}-ccache-${{ hashFiles('src/*') }}
restore-keys: Cygwin-py3.${{ matrix.python-minor-version }}-ccache-
- name: Cache Matplotlib
- uses: actions/cache@v4
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
C:\cygwin\home\runneradmin\.cache\matplotlib
diff --git a/.github/workflows/do_not_merge.yml b/.github/workflows/do_not_merge.yml
index dde5bfb5ec81..d8664df9ba9a 100644
--- a/.github/workflows/do_not_merge.yml
+++ b/.github/workflows/do_not_merge.yml
@@ -23,7 +23,6 @@ jobs:
echo "This PR cannot be merged because it has one of the following labels: "
echo "* status: needs comment/discussion"
echo "* status: waiting for other PR"
- echo "${{env.has_tag}}"
exit 1
- name: Allow merging
if: ${{'false' == env.has_tag}}
diff --git a/.github/workflows/good-first-issue.yml b/.github/workflows/good-first-issue.yml
index 8905511fc01d..cc15717e3351 100644
--- a/.github/workflows/good-first-issue.yml
+++ b/.github/workflows/good-first-issue.yml
@@ -12,7 +12,7 @@ jobs:
issues: write
steps:
- name: Add comment
- uses: peter-evans/create-or-update-comment@v4
+ uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
with:
issue-number: ${{ github.event.issue.number }}
body: |
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
index dc7a0716bfe8..8e2002353164 100644
--- a/.github/workflows/labeler.yml
+++ b/.github/workflows/labeler.yml
@@ -10,6 +10,6 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- - uses: actions/labeler@v5
+ - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0
with:
sync-labels: true
diff --git a/.github/workflows/mypy-stubtest.yml b/.github/workflows/mypy-stubtest.yml
index 969aacccad74..92a67236fb9d 100644
--- a/.github/workflows/mypy-stubtest.yml
+++ b/.github/workflows/mypy-stubtest.yml
@@ -4,22 +4,25 @@ on: [pull_request]
permissions:
contents: read
- checks: write
jobs:
mypy-stubtest:
name: mypy-stubtest
runs-on: ubuntu-latest
+ permissions:
+ checks: write
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
- name: Set up Python 3
- uses: actions/setup-python@v5
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
- python-version: 3.9
+ python-version: '3.11'
- name: Set up reviewdog
- uses: reviewdog/action-setup@v1
+ uses: reviewdog/action-setup@e04ffabe3898a0af8d0fb1af00c188831c4b5893 # v1.3.9
- name: Install tox
run: python -m pip install tox
@@ -30,7 +33,7 @@ jobs:
run: |
set -o pipefail
tox -e stubtest | \
- sed -e "s!.tox/stubtest/lib/python3.9/site-packages!lib!g" | \
+ sed -e "s!.tox/stubtest/lib/python3.11/site-packages!lib!g" | \
reviewdog \
-efm '%Eerror: %m' \
-efm '%CStub: in file %f:%l' \
diff --git a/.github/workflows/nightlies.yml b/.github/workflows/nightlies.yml
index 54e81f06b166..393ce2e73472 100644
--- a/.github/workflows/nightlies.yml
+++ b/.github/workflows/nightlies.yml
@@ -59,7 +59,7 @@ jobs:
ls -l dist/
- name: Upload wheels to Anaconda Cloud as nightlies
- uses: scientific-python/upload-nightly-action@b67d7fcc0396e1128a474d1ab2b48aa94680f9fc # 0.5.0
+ uses: scientific-python/upload-nightly-action@b36e8c0c10dbcfd2e05bf95f17ef8c14fd708dbf # 0.6.2
with:
artifacts_path: dist
anaconda_nightly_upload_token: ${{ secrets.ANACONDA_ORG_UPLOAD_TOKEN }}
diff --git a/.github/workflows/pr_welcome.yml b/.github/workflows/pr_welcome.yml
index 533f676a0fab..3bb172ca70e7 100644
--- a/.github/workflows/pr_welcome.yml
+++ b/.github/workflows/pr_welcome.yml
@@ -3,15 +3,13 @@ name: PR Greetings
on: [pull_request_target]
-permissions:
- pull-requests: write
-
jobs:
greeting:
runs-on: ubuntu-latest
-
+ permissions:
+ pull-requests: write
steps:
- - uses: actions/first-interaction@v1
+ - uses: actions/first-interaction@34f15e814fe48ac9312ccf29db4e74fa767cbab7 # v1.3.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
pr-message: >+
diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml
index fbd724571d80..09b7886e9c99 100644
--- a/.github/workflows/reviewdog.yml
+++ b/.github/workflows/reviewdog.yml
@@ -4,51 +4,71 @@ on: [pull_request]
permissions:
contents: read
- checks: write
- pull-requests: write
jobs:
- flake8:
- name: flake8
+ pre-commit:
+ name: precommit
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ fetch-depth: 0
+ - uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
+ with:
+ python-version: "3.x"
+ - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
+ with:
+ extra_args: --hook-stage manual --all-files
+
+ ruff:
+ name: ruff
+ runs-on: ubuntu-latest
+ permissions:
+ checks: write
+ steps:
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
- name: Set up Python 3
- uses: actions/setup-python@v5
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
- python-version: 3.9
+ python-version: '3.11'
- - name: Install flake8
- run: pip3 install -r requirements/testing/flake8.txt
+ - name: Install ruff
+ run: pip3 install ruff
- name: Set up reviewdog
- uses: reviewdog/action-setup@v1
+ uses: reviewdog/action-setup@e04ffabe3898a0af8d0fb1af00c188831c4b5893 # v1.3.9
- - name: Run flake8
+ - name: Run ruff
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -o pipefail
- flake8 --docstring-convention=all | \
- reviewdog -f=pep8 -name=flake8 \
+ ruff check --output-format rdjson | \
+ reviewdog -f=rdjson \
-tee -reporter=github-check -filter-mode nofilter
mypy:
name: mypy
runs-on: ubuntu-latest
+ permissions:
+ checks: write
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
- name: Set up Python 3
- uses: actions/setup-python@v5
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
- python-version: 3.9
+ python-version: '3.11'
- name: Install mypy
run: pip3 install -r requirements/testing/mypy.txt -r requirements/testing/all.txt
- name: Set up reviewdog
- uses: reviewdog/action-setup@v1
+ uses: reviewdog/action-setup@e04ffabe3898a0af8d0fb1af00c188831c4b5893 # v1.3.9
- name: Run mypy
env:
@@ -63,11 +83,15 @@ jobs:
eslint:
name: eslint
runs-on: ubuntu-latest
+ permissions:
+ checks: write
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
- name: eslint
- uses: reviewdog/action-eslint@v1
+ uses: reviewdog/action-eslint@2fee6dd72a5419ff4113f694e2068d2a03bb35dd # v1.33.2
with:
filter_mode: nofilter
github_token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/stale-tidy.yml b/.github/workflows/stale-tidy.yml
index 92a81ee856e4..bc50dc892155 100644
--- a/.github/workflows/stale-tidy.yml
+++ b/.github/workflows/stale-tidy.yml
@@ -9,7 +9,7 @@ jobs:
if: github.repository == 'matplotlib/matplotlib'
runs-on: ubuntu-latest
steps:
- - uses: actions/stale@v9
+ - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
operations-per-run: 300
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index c606d4288bd2..b65b44a59e88 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -9,7 +9,7 @@ jobs:
if: github.repository == 'matplotlib/matplotlib'
runs-on: ubuntu-latest
steps:
- - uses: actions/stale@v9
+ - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
operations-per-run: 20
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index dc216c6959f0..46bc4fb918b0 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -48,86 +48,53 @@ jobs:
matrix:
include:
- name-suffix: "(Minimum Versions)"
- os: ubuntu-20.04
- python-version: 3.9
+ os: ubuntu-22.04
+ python-version: '3.11'
extra-requirements: '-c requirements/testing/minver.txt'
- pyqt5-ver: '==5.12.2 sip==5.0.0' # oldest versions with a Py3.9 wheel.
- pyqt6-ver: '==6.1.0 PyQt6-Qt6==6.1.0'
- pyside2-ver: '==5.15.1' # oldest version with working Py3.9 wheel.
- pyside6-ver: '==6.0.0'
delete-font-cache: true
- - os: ubuntu-20.04
- python-version: 3.9
- # One CI run tests ipython/matplotlib-inline before backend mapping moved to mpl
- extra-requirements: '-r requirements/testing/extra.txt "ipython==7.19" "matplotlib-inline<0.1.7"'
- 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-20.04
- python-version: '3.10'
- extra-requirements: '-r requirements/testing/extra.txt'
- # 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'
+ # https://github.com/matplotlib/matplotlib/issues/29844
+ pygobject-ver: '<3.52.0'
- os: ubuntu-22.04
python-version: '3.11'
- # https://www.riverbankcomputing.com/pipermail/pyqt/2023-November/045606.html
- pyqt6-ver: '!=6.6.0'
- # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346
- pyside6-ver: '!=6.5.1'
+ CFLAGS: "-fno-lto" # Ensure that disabling LTO works.
extra-requirements: '-r requirements/testing/extra.txt'
- - os: ubuntu-22.04
+ # https://github.com/matplotlib/matplotlib/issues/29844
+ pygobject-ver: '<3.52.0'
+ - os: ubuntu-22.04-arm
python-version: '3.12'
- # https://www.riverbankcomputing.com/pipermail/pyqt/2023-November/045606.html
- pyqt6-ver: '!=6.6.0'
- # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346
- pyside6-ver: '!=6.5.1'
+ # https://github.com/matplotlib/matplotlib/issues/29844
+ pygobject-ver: '<3.52.0'
- os: ubuntu-22.04
python-version: '3.13'
- # https://www.riverbankcomputing.com/pipermail/pyqt/2023-November/045606.html
- pyqt6-ver: '!=6.6.0'
- # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346
- pyside6-ver: '!=6.5.1'
+ # https://github.com/matplotlib/matplotlib/issues/29844
+ pygobject-ver: '<3.52.0'
- name-suffix: "Free-threaded"
os: ubuntu-22.04
python-version: '3.13t'
- # https://www.riverbankcomputing.com/pipermail/pyqt/2023-November/045606.html
- pyqt6-ver: '!=6.6.0'
- # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346
- pyside6-ver: '!=6.5.1'
+ # https://github.com/matplotlib/matplotlib/issues/29844
+ pygobject-ver: '<3.52.0'
+ - os: ubuntu-24.04
+ python-version: '3.12'
- os: macos-13 # This runner is on Intel chips.
- python-version: '3.9'
- # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346
- pyside6-ver: '!=6.5.1'
+ # merge numpy and pandas install in nighties test when this runner is dropped
+ python-version: '3.11'
- os: macos-14 # This runner is on M1 (arm64) chips.
python-version: '3.12'
- # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346
- pyside6-ver: '!=6.5.1'
+ # https://github.com/matplotlib/matplotlib/issues/29732
+ pygobject-ver: '<3.52.0'
- os: macos-14 # This runner is on M1 (arm64) chips.
python-version: '3.13'
- # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346
- pyside6-ver: '!=6.5.1'
+ # https://github.com/matplotlib/matplotlib/issues/29732
+ pygobject-ver: '<3.52.0'
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
+ persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v5
- if: matrix.python-version != '3.13t'
- with:
- python-version: ${{ matrix.python-version }}
- allow-prereleases: true
-
- - name: Set up Python ${{ matrix.python-version }}
- uses: Quansight-Labs/setup-python@b9ab292c751a42bcd2bb465b7fa202ea2c3f5796 # v5.3.1
- if: matrix.python-version == '3.13t'
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
@@ -142,7 +109,6 @@ jobs:
ccache \
cm-super \
dvipng \
- ffmpeg \
fonts-freefont-otf \
fonts-noto-cjk \
fonts-wqy-zenhei \
@@ -156,7 +122,7 @@ jobs:
libcairo2-dev \
libffi-dev \
libgeos-dev \
- libgirepository1.0-dev \
+ libnotify4 \
libsdl2-2.0-0 \
libxkbcommon-x11-0 \
libxcb-cursor0 \
@@ -177,11 +143,16 @@ 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
+ if [[ "${{ matrix.name-suffix }}" != '(Minimum Versions)' ]]; then
+ sudo apt-get install -yy --no-install-recommends ffmpeg poppler-utils
+ fi
+ if [[ "${{ matrix.os }}" = ubuntu-22.04 || "${{ matrix.os }}" = ubuntu-22.04-arm ]]; then
+ sudo apt-get install -yy --no-install-recommends \
+ gir1.2-gtk-4.0 \
+ libgirepository1.0-dev
+ else # ubuntu-24.04
sudo apt-get install -yy --no-install-recommends \
- gir1.2-gtk-4.0 libnotify4
+ libgirepository-2.0-dev
fi
;;
macOS)
@@ -199,13 +170,13 @@ jobs:
done
# Workaround for https://github.com/actions/runner-images/issues/10984
brew uninstall --ignore-dependencies --force pkg-config@0.29.2
- brew install ccache ghostscript gobject-introspection gtk4 ninja
- brew install --cask font-noto-sans-cjk inkscape
+ brew install ccache ffmpeg ghostscript gobject-introspection gtk4 imagemagick ninja
+ brew install --cask font-noto-sans-cjk font-noto-sans-cjk-sc inkscape
;;
esac
- name: Cache pip
- uses: actions/cache@v4
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
if: startsWith(runner.os, 'Linux')
with:
path: ~/.cache/pip
@@ -213,7 +184,7 @@ jobs:
restore-keys: |
${{ matrix.os }}-py${{ matrix.python-version }}-pip-
- name: Cache pip
- uses: actions/cache@v4
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
if: startsWith(runner.os, 'macOS')
with:
path: ~/Library/Caches/pip
@@ -221,7 +192,7 @@ jobs:
restore-keys: |
${{ matrix.os }}-py${{ matrix.python-version }}-pip-
- name: Cache ccache
- uses: actions/cache@v4
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
~/.ccache
@@ -229,16 +200,16 @@ jobs:
restore-keys: |
${{ matrix.os }}-py${{ matrix.python-version }}-ccache-
- name: Cache Matplotlib
- uses: actions/cache@v4
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
~/.cache/matplotlib
!~/.cache/matplotlib/tex.cache
!~/.cache/matplotlib/test_cache
- key: 4-${{ runner.os }}-py${{ matrix.python-version }}-mpl-${{ github.ref }}-${{ github.sha }}
+ key: 6-${{ matrix.os }}-py${{ matrix.python-version }}-mpl-${{ github.ref }}-${{ github.sha }}
restore-keys: |
- 4-${{ runner.os }}-py${{ matrix.python-version }}-mpl-${{ github.ref }}-
- 4-${{ runner.os }}-py${{ matrix.python-version }}-mpl-
+ 6-${{ matrix.os }}-py${{ matrix.python-version }}-mpl-${{ github.ref }}-
+ 6-${{ matrix.os }}-py${{ matrix.python-version }}-mpl-
- name: Install Python dependencies
run: |
@@ -256,8 +227,8 @@ 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 \
- numpy packaging pillow 'pyparsing!=3.1.0' python-dateutil setuptools-scm \
- 'meson-python>=0.13.1' 'pybind11>=2.6' \
+ packaging pillow 'pyparsing!=3.1.0' python-dateutil setuptools-scm \
+ 'meson-python>=0.13.1' 'pybind11>=2.13.2' \
-r requirements/testing/all.txt \
${{ matrix.extra-requirements }}
@@ -272,7 +243,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'
@@ -281,30 +252,33 @@ jobs:
echo 'PyGObject 3 is available' || echo 'PyGObject 3 is not available'
)
- python -mpip install --upgrade pyqt5${{ matrix.pyqt5-ver }} &&
- python -c 'import PyQt5.QtCore' &&
- echo 'PyQt5 is available' ||
- echo 'PyQt5 is not available'
+ # PyQt5 does not have any wheels for ARM on Linux.
+ if [[ "${{ matrix.os }}" != 'ubuntu-22.04-arm' ]]; then
+ python -mpip install --upgrade --only-binary :all: pyqt5 &&
+ python -c 'import PyQt5.QtCore' &&
+ echo 'PyQt5 is available' ||
+ echo 'PyQt5 is not available'
+ fi
# Even though PySide2 wheels can be installed on Python 3.12+, they are broken and since PySide2 is
# deprecated, they are unlikely to be fixed. For the same deprecation reason, there are no wheels
# on M1 macOS, so don't bother there either.
if [[ "${{ matrix.os }}" != 'macos-14'
&& "${{ matrix.python-version }}" != '3.12' && "${{ matrix.python-version }}" != '3.13' ]]; then
- python -mpip install --upgrade pyside2${{ matrix.pyside2-ver }} &&
+ python -mpip install --upgrade pyside2 &&
python -c 'import PySide2.QtCore' &&
echo 'PySide2 is available' ||
echo 'PySide2 is not available'
fi
- python -mpip install --upgrade pyqt6${{ matrix.pyqt6-ver }} &&
+ python -mpip install --upgrade --only-binary :all: pyqt6 &&
python -c 'import PyQt6.QtCore' &&
echo 'PyQt6 is available' ||
echo 'PyQt6 is not available'
- python -mpip install --upgrade pyside6${{ matrix.pyside6-ver }} &&
+ python -mpip install --upgrade --only-binary :all: pyside6 &&
python -c 'import PySide6.QtCore' &&
echo 'PySide6 is available' ||
echo 'PySide6 is not available'
- python -mpip install --upgrade \
+ python -mpip install --upgrade --only-binary :all: \
-f "https://extras.wxpython.org/wxPython4/extras/linux/gtk3/${{ matrix.os }}" \
wxPython &&
python -c 'import wx' &&
@@ -320,7 +294,13 @@ jobs:
python -m pip install pytz tzdata # Must be installed for Pandas.
python -m pip install \
--index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple \
- --upgrade --only-binary=:all: numpy pandas
+ --upgrade --only-binary=:all: numpy
+ # wheels for intel osx is not always available on nightly wheels index, merge this back into
+ # the above install command when the OSX-13 (intel) runners are dropped.
+ python -m pip install \
+ --index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple \
+ --upgrade --only-binary=:all: pandas || true
+
- name: Install Matplotlib
run: |
@@ -358,15 +338,55 @@ jobs:
--maxfail=50 --timeout=300 --durations=25 \
--cov-report=xml --cov=lib --log-level=DEBUG --color=yes
+ - name: Cleanup non-failed image files
+ if: failure()
+ run: |
+ function remove_files() {
+ local extension=$1
+ find ./result_images -type f -name "*-expected*.$extension" | while read file; do
+ if [[ $file == *"-expected_pdf"* ]]; then
+ base=${file%-expected_pdf.$extension}_pdf
+ elif [[ $file == *"-expected_eps"* ]]; then
+ base=${file%-expected_eps.$extension}_eps
+ elif [[ $file == *"-expected_svg"* ]]; then
+ base=${file%-expected_svg.$extension}_svg
+ else
+ base=${file%-expected.$extension}
+ fi
+ if [[ ! -e "${base}-failed-diff.$extension" ]]; then
+ if [[ -e "$file" ]]; then
+ rm "$file"
+ echo "Removed $file"
+ fi
+ if [[ -e "${base}.$extension" ]]; then
+ rm "${base}.$extension"
+ echo " Removed ${base}.$extension"
+ fi
+ fi
+ done
+ }
+
+ remove_files "png"; remove_files "svg"; remove_files "pdf"; remove_files "eps";
+
+ if [ "$(find ./result_images -mindepth 1 -type d)" ]; then
+ find ./result_images/* -type d -empty -delete
+ fi
+
- name: Filter C coverage
if: ${{ !cancelled() && github.event_name != 'schedule' }}
run: |
if [[ "${{ runner.os }}" != 'macOS' ]]; then
- lcov --rc lcov_branch_coverage=1 --capture --directory . \
- --output-file coverage.info
- lcov --rc lcov_branch_coverage=1 --output-file coverage.info \
- --extract coverage.info $PWD/src/'*' $PWD/lib/'*'
- lcov --rc lcov_branch_coverage=1 --list coverage.info
+ LCOV_IGNORE_ERRORS=',' # do not ignore any lcov errors by default
+ if [[ "${{ matrix.os }}" = ubuntu-24.04 ]]; then
+ # filter mismatch and unused-entity errors detected by lcov 2.x
+ LCOV_IGNORE_ERRORS='mismatch,unused'
+ fi
+ lcov --rc lcov_branch_coverage=1 --ignore-errors $LCOV_IGNORE_ERRORS \
+ --capture --directory . --output-file coverage.info
+ lcov --rc lcov_branch_coverage=1 --ignore-errors $LCOV_IGNORE_ERRORS \
+ --output-file coverage.info --extract coverage.info $PWD/src/'*' $PWD/lib/'*'
+ lcov --rc lcov_branch_coverage=1 --ignore-errors $LCOV_IGNORE_ERRORS \
+ --list coverage.info
find . -name '*.gc*' -delete
else
xcrun llvm-profdata merge -sparse default.*.profraw \
@@ -376,12 +396,12 @@ jobs:
fi
- name: Upload code coverage
if: ${{ !cancelled() && github.event_name != 'schedule' }}
- uses: codecov/codecov-action@v5
+ uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d # v5.4.2
with:
name: "${{ matrix.python-version }} ${{ matrix.os }} ${{ matrix.name-suffix }}"
token: ${{ secrets.CODECOV_TOKEN }}
- - uses: actions/upload-artifact@v4
+ - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: failure()
with:
name: "${{ matrix.python-version }} ${{ matrix.os }} ${{ matrix.name-suffix }} result images"
@@ -398,7 +418,7 @@ jobs:
steps:
- name: Create issue on failure
- uses: imjohnbo/issue-bot@v3
+ uses: imjohnbo/issue-bot@572eed14422c4d6ca37e870f97e7da209422f5bd # v3.4.4
with:
title: "[TST] Upcoming dependency test failures"
body: |
diff --git a/.gitignore b/.gitignore
index b6f9e1ee74f4..1d30ba69aeaa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -103,6 +103,16 @@ __conda_version__.txt
lib/png.lib
lib/z.lib
+# Environments #
+################
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
# Jupyter files #
#################
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 14817e95929f..afcdc44c1b4a 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -14,7 +14,7 @@ exclude: |
)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.5.0
+ rev: v5.0.0
hooks:
- id: check-added-large-files
- id: check-docstring-first
@@ -28,7 +28,7 @@ repos:
- id: trailing-whitespace
exclude_types: [svg]
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v1.9.0
+ rev: v1.15.0
hooks:
- id: mypy
additional_dependencies:
@@ -41,17 +41,16 @@ repos:
args: ["--config-file=pyproject.toml", "lib/matplotlib"]
files: lib/matplotlib # Only run when files in lib/matplotlib are changed.
pass_filenames: false
- - repo: https://github.com/pycqa/flake8
- rev: 7.0.0
+
+ - repo: https://github.com/astral-sh/ruff-pre-commit
+ # Ruff version.
+ rev: v0.11.5
hooks:
- - id: flake8
- additional_dependencies:
- - pydocstyle>5.1.0
- - flake8-docstrings>1.4.0
- - flake8-force
- args: ["--docstring-convention=all"]
+ # Run the linter.
+ - id: ruff
+ args: [--fix, --show-fixes]
- repo: https://github.com/codespell-project/codespell
- rev: v2.2.6
+ rev: v2.4.1
hooks:
- id: codespell
files: ^.*\.(py|c|cpp|h|m|md|rst|yml)$
@@ -61,25 +60,25 @@ repos:
- "--skip"
- "doc/project/credits.rst"
- repo: https://github.com/pycqa/isort
- rev: 5.13.2
+ rev: 6.0.1
hooks:
- id: isort
name: isort (python)
files: ^galleries/tutorials/|^galleries/examples/|^galleries/plot_types/
- repo: https://github.com/rstcheck/rstcheck
- rev: v6.2.0
+ rev: v6.2.4
hooks:
- id: rstcheck
additional_dependencies:
- sphinx>=1.8.1
- tomli
- repo: https://github.com/adrienverge/yamllint
- rev: v1.35.1
+ rev: v1.37.0
hooks:
- id: yamllint
args: ["--strict", "--config-file=.yamllint.yml"]
- repo: https://github.com/python-jsonschema/check-jsonschema
- rev: 0.28.4
+ rev: 0.33.0
hooks:
# TODO: Re-enable this when https://github.com/microsoft/azure-pipelines-vscode/issues/567 is fixed.
# - id: check-azure-pipelines
diff --git a/LICENSE/LICENSE_LAST_RESORT_FONT b/LICENSE/LICENSE_LAST_RESORT_FONT
new file mode 100644
index 000000000000..5fe3297bc1e1
--- /dev/null
+++ b/LICENSE/LICENSE_LAST_RESORT_FONT
@@ -0,0 +1,97 @@
+Last Resort High-Efficiency Font License
+========================================
+
+This Font Software is licensed under the SIL Open Font License,
+Version 1.1.
+
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font
+creation efforts of academic and linguistic communities, and to
+provide a free and open framework in which fonts may be shared and
+improved in partnership with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply to
+any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software
+components as distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to,
+deleting, or substituting -- in part or in whole -- any of the
+components of the Original Version, by changing formats or by porting
+the Font Software to a new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed,
+modify, redistribute, and sell modified and unmodified copies of the
+Font Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components, in
+Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the
+corresponding Copyright Holder. This restriction only applies to the
+primary font name as presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created using
+the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
+
+SPDX-License-Identifier: OFL-1.1
diff --git a/SECURITY.md b/SECURITY.md
index ce022ca60a0f..4400a4501b51 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -8,14 +8,13 @@ versions.
| Version | Supported |
| ------- | ------------------ |
+| 3.10.x | :white_check_mark: |
| 3.9.x | :white_check_mark: |
-| 3.8.x | :white_check_mark: |
+| 3.8.x | :x: |
| 3.7.x | :x: |
| 3.6.x | :x: |
| 3.5.x | :x: |
-| 3.4.x | :x: |
-| 3.3.x | :x: |
-| < 3.3 | :x: |
+| < 3.5 | :x: |
## Reporting a Vulnerability
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 00edc8e9a412..d68a9d36f0d3 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -49,33 +49,15 @@ stages:
- job: Pytest
strategy:
matrix:
- Linux_py39:
- vmImage: 'ubuntu-20.04' # keep one job pinned to the oldest image
- python.version: '3.9'
- Linux_py310:
- vmImage: 'ubuntu-latest'
- python.version: '3.10'
- Linux_py311:
- vmImage: 'ubuntu-latest'
- python.version: '3.11'
- macOS_py39:
- vmImage: 'macOS-latest'
- python.version: '3.9'
- macOS_py310:
- vmImage: 'macOS-latest'
- python.version: '3.10'
- macOS_py311:
- vmImage: 'macOS-latest'
+ Windows_py311:
+ vmImage: 'windows-2022' # Keep one job pinned to the oldest image
python.version: '3.11'
- Windows_py39:
- vmImage: 'windows-2019' # keep one job pinned to the oldest image
- python.version: '3.9'
- Windows_py310:
+ Windows_py312:
vmImage: 'windows-latest'
- python.version: '3.10'
- Windows_py311:
+ python.version: '3.12'
+ Windows_py313:
vmImage: 'windows-latest'
- python.version: '3.11'
+ python.version: '3.13'
maxParallel: 4
pool:
vmImage: '$(vmImage)'
@@ -87,89 +69,19 @@ stages:
displayName: 'Use Python $(python.version)'
- bash: |
- set -e
- case "$AGENT_OS" in
- Linux)
- echo 'Acquire::Retries "3";' | sudo tee /etc/apt/apt.conf.d/80-retries
- sudo apt update
- sudo apt install --no-install-recommends \
- cm-super \
- dvipng \
- ffmpeg \
- fonts-freefont-otf \
- fonts-noto-cjk \
- fonts-wqy-zenhei \
- gdb \
- gir1.2-gtk-3.0 \
- graphviz \
- inkscape \
- language-pack-de \
- lcov \
- libcairo2 \
- libgirepository-1.0-1 \
- lmodern \
- ninja-build \
- poppler-utils \
- texlive-fonts-recommended \
- texlive-latex-base \
- texlive-latex-extra \
- texlive-latex-recommended \
- texlive-luatex \
- texlive-pictures \
- texlive-xetex
- ;;
- Darwin)
- brew update
- # Periodically, Homebrew updates Python and fails to overwrite the
- # existing not-managed-by-Homebrew copy without explicitly being told
- # to do so. GitHub/Azure continues to avoid fixing their runner images:
- # https://github.com/actions/runner-images/issues/9966
- # so force an overwrite even if there are no Python updates.
- # We don't even care about Homebrew's Python because we use the one
- # from UsePythonVersion.
- for python_package in $(brew list | grep python@); do
- brew unlink ${python_package}
- brew link --overwrite ${python_package}
- done
- # Workaround for https://github.com/actions/runner-images/issues/10984
- brew uninstall --ignore-dependencies --force pkg-config@0.29.2
- brew install --cask xquartz
- brew install ccache ffmpeg imagemagick mplayer ninja pkg-config
- brew install --cask font-noto-sans-cjk-sc
- ;;
- Windows_NT)
- choco install ninja
- ;;
- *)
- exit 1
- ;;
- esac
+ choco install ninja
displayName: 'Install dependencies'
- bash: |
python -m pip install --upgrade pip
- python -m pip install --upgrade meson-python numpy pybind11 setuptools-scm
+ python -m pip install --upgrade -r requirements/dev/build-requirements.txt
python -m pip install -r requirements/testing/all.txt -r requirements/testing/extra.txt
displayName: 'Install dependencies with pip'
- bash: |
- case "$AGENT_OS" in
- Linux)
- export CPPFLAGS='--coverage -fprofile-abs-path'
- ;;
- Darwin)
- export CPPFLAGS='-fprofile-instr-generate=default.%m.profraw'
- export CPPFLAGS="$CPPFLAGS -fcoverage-mapping"
- ;;
- Windows_NT)
- CONFIG='--config-settings=setup-args=--vsenv'
- CONFIG="$CONFIG --config-settings=setup-args=-Dcpp_link_args=-PROFILE"
- CONFIG="$CONFIG --config-settings=setup-args=-Dbuildtype=debug"
- ;;
- *)
- exit 1
- ;;
- esac
+ CONFIG='--config-settings=setup-args=--vsenv'
+ CONFIG="$CONFIG --config-settings=setup-args=-Dcpp_link_args=-PROFILE"
+ CONFIG="$CONFIG --config-settings=setup-args=-Dbuildtype=debug"
python -m pip install \
--no-build-isolation $CONFIG \
@@ -184,102 +96,52 @@ stages:
- bash: |
set -e
- if [[ "$AGENT_OS" == 'Windows_NT' ]]; then
- SESSION_ID=$(python -c "import uuid; print(uuid.uuid4(), end='')")
- echo "Coverage session ID: ${SESSION_ID}"
- VS=$(ls -d /c/Program\ Files*/Microsoft\ Visual\ Studio/*/Enterprise)
- echo "Visual Studio: ${VS}"
- DIR="$VS/Common7/IDE/Extensions/Microsoft/CodeCoverage.Console"
- if [[ -d $DIR ]]; then
- # This is for MSVC 2022 (on windows-latest).
- TOOL="$DIR/Microsoft.CodeCoverage.Console.exe"
- for f in build/cp*/src/*.pyd; do
- echo $f
- echo "=============================="
- "$TOOL" instrument $f --session-id $SESSION_ID \
- --log-level Verbose --log-file instrument.log
- cat instrument.log
- rm instrument.log
- done
- echo "Starting $TOOL in server mode"
- "$TOOL" collect \
- --session-id $SESSION_ID --server-mode \
- --output-format cobertura --output extensions.xml \
- --log-level Verbose --log-file extensions.log &
- VS_VER=2022
- else
- DIR="$VS"/Team\ Tools/Dynamic\ Code\ Coverage\ Tools/amd64
- if [[ -d $DIR ]]; then
- # This is for MSVC 2019 (on windows-2019).
- VSINSTR="$VS"/Team\ Tools/Performance\ Tools/vsinstr.exe
- for f in build/cp*/src/*.pyd; do
- "$VSINSTR" $f -Verbose -Coverage
- done
- TOOL="$DIR/CodeCoverage.exe"
- cat > extensions.config << EOF
-