diff --git a/.appveyor.yml b/.appveyor.yml
index da2aec993979..c3fcb0ea9591 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -17,7 +17,7 @@ skip_commits:
clone_depth: 50
-image: Visual Studio 2019
+image: Visual Studio 2022
environment:
@@ -45,9 +45,8 @@ cache:
init:
- ps:
- # Pinned due to https://github.com/mamba-org/mamba/issues/3467
Invoke-Webrequest
- -URI https://github.com/mamba-org/micromamba-releases/releases/download/1.5.10-0/micromamba-win-64.tar.bz2
+ -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\
@@ -55,6 +54,7 @@ init:
- micromamba shell init --shell cmd.exe
- micromamba config set always_yes true
- micromamba config prepend channels conda-forge
+ - micromamba info
install:
- micromamba env create -f environment.yml python=%PYTHON_VERSION% pywin32
@@ -63,7 +63,7 @@ install:
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'
@@ -91,7 +91,7 @@ artifacts:
on_finish:
- micromamba install codecov
- - codecov -e PYTHON_VERSION PLATFORM -n "$PYTHON_VERSION Windows"
+ - 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 e7348b868d4b..40ba933cf0d9 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -98,7 +98,7 @@ commands:
parameters:
numpy_version:
type: string
- default: "~=2.0.0"
+ default: ""
steps:
- run:
name: Install Python dependencies
diff --git a/.flake8 b/.flake8
deleted file mode 100644
index 7297d72b5841..000000000000
--- a/.flake8
+++ /dev/null
@@ -1,91 +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
- lib/matplotlib/_mathtext_data.py: E203
- 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
- lib/matplotlib/tri/_triinterpolate.py: E201, E221
- lib/mpl_toolkits/axes_grid1/axes_size.py: E272
- lib/mpl_toolkits/axisartist/angle_helper.py: E221
- lib/mpl_toolkits/mplot3d/proj3d.py: E201
-
- 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/.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/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index e857416b13d8..bf483dbdd4f4 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -13,6 +13,11 @@ out the development guide https://matplotlib.org/devdocs/devel/index.html
Additionally, please summarize the changes in the title, for example "Raise ValueError on
non-numeric input to set_xlim" and avoid non-descriptive titles such as "Addresses
issue #8576".
+
+If possible, please provide a minimum self-contained example. If you have used
+generative AI as an aid in preparing this PR, see
+
+https://matplotlib.org/devdocs/devel/contribute.html#restrictions-on-generative-ai-usage
-->
diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml
index cd9ad2161595..a870ce76c2d7 100644
--- a/.github/workflows/cibuildwheel.yml
+++ b/.github/workflows/cibuildwheel.yml
@@ -24,29 +24,32 @@ permissions:
jobs:
build_sdist:
if: >-
- github.event_name == 'push' ||
- github.event_name == 'pull_request' && (
- (
- github.event.action == 'labeled' &&
- github.event.label.name == 'CI: Run cibuildwheel'
- ) ||
- contains(github.event.pull_request.labels.*.name,
- 'CI: Run cibuildwheel')
+ github.repository == 'matplotlib/matplotlib' && (
+ github.event_name == 'push' ||
+ github.event_name == 'pull_request' && (
+ (
+ github.event.action == 'labeled' &&
+ github.event.label.name == 'CI: Run cibuildwheel'
+ ) ||
+ contains(github.event.pull_request.labels.*.name,
+ '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.10'
+ 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 +72,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
@@ -77,14 +80,16 @@ jobs:
build_wheels:
if: >-
- github.event_name == 'push' ||
- github.event_name == 'pull_request' && (
- (
- github.event.action == 'labeled' &&
- github.event.label.name == 'CI: Run cibuildwheel'
- ) ||
- contains(github.event.pull_request.labels.*.name,
- 'CI: Run cibuildwheel')
+ github.repository == 'matplotlib/matplotlib' && (
+ github.event_name == 'push' ||
+ github.event_name == 'pull_request' && (
+ (
+ github.event.action == 'labeled' &&
+ github.event.label.name == 'CI: Run cibuildwheel'
+ ) ||
+ contains(github.event.pull_request.labels.*.name,
+ 'CI: Run cibuildwheel')
+ )
)
needs: build_sdist
name: Build wheels on ${{ matrix.os }} for ${{ matrix.cibw_archs }}
@@ -114,54 +119,54 @@ 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"
+ cibw_archs: "AMD64"
+ - os: windows-11-arm
+ cibw_archs: "ARM64"
- os: macos-13
cibw_archs: "x86_64"
- os: macos-14
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.14
+ uses: pypa/cibuildwheel@95d2f3a92fbf80abe066b09418bbf128a8923df2 # v3.0.1
+ with:
+ package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }}
+ env:
+ CIBW_BUILD: "cp314-* cp314t-*"
+ CIBW_ENABLE: "cpython-freethreading cpython-prerelease"
+ CIBW_ARCHS: ${{ matrix.cibw_archs }}
+ CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
+ CIBW_BEFORE_TEST: >-
+ python -m pip install
+ --index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
+ --upgrade --pre --only-binary=:all: contourpy numpy pillow
+
- name: Build wheels for CPython 3.13
- uses: pypa/cibuildwheel@7940a4c0e76eb2030e473a5f864f291f63ee879b # v2.21.3
+ uses: pypa/cibuildwheel@95d2f3a92fbf80abe066b09418bbf128a8923df2 # v3.0.1
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
- # 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_ENABLE: cpython-freethreading
CIBW_ARCHS: ${{ matrix.cibw_archs }}
- name: Build wheels for CPython 3.12
- uses: pypa/cibuildwheel@7940a4c0e76eb2030e473a5f864f291f63ee879b # v2.21.3
+ uses: pypa/cibuildwheel@95d2f3a92fbf80abe066b09418bbf128a8923df2 # v3.0.1
with:
package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }}
env:
@@ -169,46 +174,31 @@ jobs:
CIBW_ARCHS: ${{ matrix.cibw_archs }}
- name: Build wheels for CPython 3.11
- uses: pypa/cibuildwheel@7940a4c0e76eb2030e473a5f864f291f63ee879b # v2.21.3
+ uses: pypa/cibuildwheel@95d2f3a92fbf80abe066b09418bbf128a8923df2 # v3.0.1
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 PyPy
- uses: pypa/cibuildwheel@7940a4c0e76eb2030e473a5f864f291f63ee879b # v2.21.3
+ uses: pypa/cibuildwheel@95d2f3a92fbf80abe066b09418bbf128a8923df2 # v3.0.1
with:
package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }}
env:
- CIBW_BUILD: "pp310-*"
+ CIBW_BUILD: "pp311-*"
CIBW_ARCHS: ${{ matrix.cibw_archs }}
- # Work around for https://github.com/pypa/setuptools/issues/4571
- # This can be removed once kiwisolver has wheels for PyPy 3.10
- # https://github.com/nucleic/kiwi/pull/182
- CIBW_BEFORE_TEST: >-
- export PIP_CONSTRAINT=pypy-constraint.txt &&
- echo "setuptools!=72.2.0" > $PIP_CONSTRAINT &&
- pip install kiwisolver &&
- unset PIP_CONSTRAINT
- if: matrix.cibw_archs != 'aarch64' && matrix.os != 'windows-latest'
+ CIBW_ENABLE: pypy
+ if: matrix.cibw_archs != 'aarch64' && matrix.os != 'windows-latest' && matrix.os != 'windows-11-arm'
- - 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
if-no-files-found: error
publish:
- if: github.event_name == 'push' && github.ref_type == 'tag'
+ if: github.repository == 'matplotlib/matplotlib' && github.event_name == 'push' && github.ref_type == 'tag'
name: Upload release to PyPI
needs: [build_sdist, build_wheels]
runs-on: ubuntu-latest
@@ -219,7 +209,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 +219,9 @@ jobs:
run: ls dist
- name: Generate artifact attestation for sdist and wheel
- uses: actions/attest-build-provenance@1c608d11d69870c2092266b3f9a6f3abbf17002c # v1.4.3
+ uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0
with:
subject-path: dist/matplotlib-*
- name: Publish package distributions to PyPI
- uses: pypa/gh-action-pypi-publish@f7600683efdcb7656dec5b29656edb7bc586e597 # v1.10.3
+ uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
diff --git a/.github/workflows/circleci.yml b/.github/workflows/circleci.yml
index a64b312e8246..d61db3f14345 100644
--- a/.github/workflows/circleci.yml
+++ b/.github/workflows/circleci.yml
@@ -11,7 +11,7 @@ jobs:
steps:
- name: GitHub Action step
uses:
- scientific-python/circleci-artifacts-redirector-action@4e13a10d89177f4bfc8007a7064bdbeda848d8d1 # v1.0.0
+ scientific-python/circleci-artifacts-redirector-action@7eafdb60666f57706a5525a2f5eb76224dc8779b # v1.1.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
api-token: ${{ secrets.CIRCLECI_TOKEN }}
@@ -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..7e9f37f38b20 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -12,6 +12,7 @@ on:
jobs:
analyze:
+ if: github.repository == 'matplotlib/matplotlib'
name: Analyze
runs-on: ubuntu-latest
permissions:
@@ -26,10 +27,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@d6bbdef45e766d081b84a2def353b0055f728d3e # v3.29.3
with:
languages: ${{ matrix.language }}
@@ -40,4 +43,4 @@ jobs:
pip install --user -v .
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v3
+ uses: github/codeql-action/analyze@d6bbdef45e766d081b84a2def353b0055f728d3e # v3.29.3
diff --git a/.github/workflows/conflictcheck.yml b/.github/workflows/conflictcheck.yml
index 3110839e5150..f4a687cd28d7 100644
--- a/.github/workflows/conflictcheck.yml
+++ b/.github/workflows/conflictcheck.yml
@@ -9,15 +9,15 @@ on:
pull_request_target:
types: [synchronize]
-permissions:
- pull-requests: write
-
jobs:
main:
+ if: github.repository == 'matplotlib/matplotlib'
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 5dee68597d5c..a52343c5d22c 100644
--- a/.github/workflows/cygwin.yml
+++ b/.github/workflows/cygwin.yml
@@ -79,11 +79,12 @@ jobs:
- 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@f2009323764960f80959895c7bc3bb30210afe4d # v6
with:
packages: >-
ccache gcc-g++ gdb git graphviz libcairo-devel libffi-devel
@@ -139,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/linting.yml b/.github/workflows/linting.yml
new file mode 100644
index 000000000000..86f934270812
--- /dev/null
+++ b/.github/workflows/linting.yml
@@ -0,0 +1,100 @@
+---
+name: Linting
+on: [pull_request]
+
+permissions:
+ contents: read
+
+jobs:
+ pre-commit:
+ name: precommit
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ fetch-depth: 0
+ persist-credentials: false
+ - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.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@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+ with:
+ python-version: '3.11'
+
+ - name: Install ruff
+ run: pip3 install ruff
+
+ - name: Set up reviewdog
+ uses: reviewdog/action-setup@e04ffabe3898a0af8d0fb1af00c188831c4b5893 # v1.3.9
+
+ - name: Run ruff
+ env:
+ REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ set -o pipefail
+ 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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
+
+ - name: Set up Python 3
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+ with:
+ 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@e04ffabe3898a0af8d0fb1af00c188831c4b5893 # v1.3.9
+
+ - name: Run mypy
+ env:
+ REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ set -o pipefail
+ mypy --config pyproject.toml | \
+ reviewdog -f=mypy -name=mypy \
+ -tee -reporter=github-check -filter-mode nofilter
+
+
+ eslint:
+ name: eslint
+ runs-on: ubuntu-latest
+ permissions:
+ checks: write
+ steps:
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
+
+ - name: eslint
+ uses: reviewdog/action-eslint@2fee6dd72a5419ff4113f694e2068d2a03bb35dd # v1.33.2
+ with:
+ filter_mode: nofilter
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ reporter: github-check
+ workdir: 'lib/matplotlib/backends/web_backend/'
diff --git a/.github/workflows/mypy-stubtest.yml b/.github/workflows/mypy-stubtest.yml
index 5b29a93b7533..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.10'
+ 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.10/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 25e2bb344eda..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@82396a2ed4269ba06c6b2988bb4fd568ef3c3d6b # 0.6.1
+ 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..7271e19ff4c1 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@2d4393e6bc0e2efb2e48fba7e06819c3bf61ffc9 # v2.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
pr-message: >+
diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml
deleted file mode 100644
index 12b59d866e42..000000000000
--- a/.github/workflows/reviewdog.yml
+++ /dev/null
@@ -1,75 +0,0 @@
----
-name: Linting
-on: [pull_request]
-
-permissions:
- contents: read
- checks: write
- pull-requests: write
-
-jobs:
- flake8:
- name: flake8
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set up Python 3
- uses: actions/setup-python@v5
- with:
- python-version: '3.10'
-
- - name: Install flake8
- run: pip3 install -r requirements/testing/flake8.txt
-
- - name: Set up reviewdog
- uses: reviewdog/action-setup@v1
-
- - name: Run flake8
- env:
- REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- set -o pipefail
- flake8 --docstring-convention=all | \
- reviewdog -f=pep8 -name=flake8 \
- -tee -reporter=github-check -filter-mode nofilter
- mypy:
- name: mypy
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set up Python 3
- uses: actions/setup-python@v5
- with:
- python-version: '3.10'
-
- - 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
-
- - name: Run mypy
- env:
- REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- set -o pipefail
- mypy --config pyproject.toml | \
- reviewdog -f=mypy -name=mypy \
- -tee -reporter=github-check -filter-mode nofilter
-
-
- eslint:
- name: eslint
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: eslint
- uses: reviewdog/action-eslint@v1
- with:
- filter_mode: nofilter
- github_token: ${{ secrets.GITHUB_TOKEN }}
- reporter: github-check
- workdir: 'lib/matplotlib/backends/web_backend/'
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 f73fde457be3..852a01c270c0 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -48,87 +48,59 @@ jobs:
matrix:
include:
- name-suffix: "(Minimum Versions)"
- os: ubuntu-20.04
- python-version: '3.10'
+ os: ubuntu-22.04
+ python-version: '3.11'
extra-requirements: '-c requirements/testing/minver.txt'
delete-font-cache: true
- # Oldest versions with Py3.10 wheels.
- pyqt5-ver: '==5.15.5 sip==6.3.0'
- 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'
- # 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"
- 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'
+ # 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'
- - os: ubuntu-22.04
+ # https://github.com/matplotlib/matplotlib/issues/29844
+ pygobject-ver: '<3.52.0'
+ - name-suffix: "(Extra TeX packages)"
+ 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'
+ extra-packages: 'texlive-fonts-extra texlive-lang-cyrillic'
+ # 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.10'
- # 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'
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- - name: Set up Python ${{ matrix.python-version }}
- uses: deadsnakes/action@e640ac8743173a67cca4d7d77cd837e514bf98e8 # v3.2.0
- if: matrix.python-version == '3.13t'
- with:
- python-version: '3.13'
- nogil: true
-
- name: Install OS dependencies
run: |
case "${{ runner.os }}" in
@@ -139,7 +111,6 @@ jobs:
ccache \
cm-super \
dvipng \
- ffmpeg \
fonts-freefont-otf \
fonts-noto-cjk \
fonts-wqy-zenhei \
@@ -153,7 +124,7 @@ jobs:
libcairo2-dev \
libffi-dev \
libgeos-dev \
- libgirepository1.0-dev \
+ libnotify4 \
libsdl2-2.0-0 \
libxkbcommon-x11-0 \
libxcb-cursor0 \
@@ -173,17 +144,18 @@ jobs:
texlive-latex-recommended \
texlive-luatex \
texlive-pictures \
- texlive-xetex
- if [[ "${{ matrix.python-version }}" = '3.13t' ]]; then
- # TODO: Remove this once setup-python supports nogil distributions.
- sudo apt-get install -yy --no-install-recommends \
- python3.13-tk-nogil
+ texlive-xetex \
+ ${{ matrix.extra-packages }}
+ if [[ "${{ matrix.name-suffix }}" != '(Minimum Versions)' ]]; then
+ sudo apt-get install -yy --no-install-recommends ffmpeg poppler-utils
fi
- if [[ "${{ matrix.os }}" = ubuntu-20.04 ]]; then
- sudo apt-get install -yy --no-install-recommends libopengl0
- else # ubuntu-22.04
+ 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 libnotify4
+ gir1.2-gtk-4.0 \
+ libgirepository1.0-dev
+ else # ubuntu-24.04
+ sudo apt-get install -yy --no-install-recommends \
+ libgirepository-2.0-dev
fi
;;
macOS)
@@ -199,13 +171,15 @@ jobs:
brew unlink ${python_package}
brew link --overwrite ${python_package}
done
- brew install ccache ghostscript gobject-introspection gtk4 ninja
- brew install --cask font-noto-sans-cjk inkscape
+ # Workaround for https://github.com/actions/runner-images/issues/10984
+ brew uninstall --ignore-dependencies --force pkg-config@0.29.2
+ 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 +187,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 +195,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,25 +203,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-
-
- - name: Install the nightly dependencies
- if: matrix.python-version == '3.13t'
- run: |
- python -m pip install pytz tzdata python-dateutil # Must be installed for Pandas.
- python -m pip install \
- --pre \
- --index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple \
- --upgrade --only-binary=:all: numpy pandas pillow contourpy
+ 6-${{ matrix.os }}-py${{ matrix.python-version }}-mpl-${{ github.ref }}-
+ 6-${{ matrix.os }}-py${{ matrix.python-version }}-mpl-
- name: Install Python dependencies
run: |
@@ -281,7 +246,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'
@@ -290,30 +255,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' &&
@@ -329,7 +297,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: |
@@ -370,32 +344,29 @@ jobs:
- 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
+ find ./result_images -name "*-expected*.png" | while read file; do
+ if [[ $file == *-expected_???.png ]]; then
+ extension=${file: -7:3}
+ base=${file%*-expected_$extension.png}_$extension
+ else
+ extension="png"
+ base=${file%-expected.png}
+ fi
+ if [[ ! -e ${base}-failed-diff.png ]]; then
+ indent=""
+ list=($file $base.png)
+ if [[ $extension != "png" ]]; then
+ list+=(${base%_$extension}-expected.$extension ${base%_$extension}.$extension)
+ fi
+ for to_remove in "${list[@]}"; do
+ if [[ -e $to_remove ]]; then
+ rm $to_remove
+ echo "${indent}Removed $to_remove"
+ fi
+ indent+=" "
done
- }
-
- remove_files "png"; remove_files "svg"; remove_files "pdf"; remove_files "eps";
+ fi
+ done
if [ "$(find ./result_images -mindepth 1 -type d)" ]; then
find ./result_images/* -type d -empty -delete
@@ -405,11 +376,17 @@ jobs:
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 \
@@ -419,12 +396,12 @@ jobs:
fi
- name: Upload code coverage
if: ${{ !cancelled() && github.event_name != 'schedule' }}
- uses: codecov/codecov-action@v4
+ uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
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"
@@ -441,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..9389a1612b14 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,7 @@ pip-wheel-metadata/*
.tox
# build subproject files
subprojects/*/
+subprojects/.*
!subprojects/packagefiles/
# OS generated files #
@@ -103,6 +104,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 6068b8b0df83..86a9a0f45440 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -10,7 +10,7 @@ exclude: |
doc/devel/gitwash|
doc/users/prev|
doc/api/prev|
- lib/matplotlib/tests/tinypages
+ lib/matplotlib/tests/data/tinypages
)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
@@ -28,7 +28,7 @@ repos:
- id: trailing-whitespace
exclude_types: [svg]
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v1.11.2
+ 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.1.1
+
+ - 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.3.0
+ rev: v2.4.1
hooks:
- id: codespell
files: ^.*\.(py|c|cpp|h|m|md|rst|yml)$
@@ -61,7 +60,7 @@ 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)
@@ -74,12 +73,12 @@ repos:
- 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.29.3
+ 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 4bccb5da8ed2..d68a9d36f0d3 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -49,24 +49,15 @@ stages:
- job: Pytest
strategy:
matrix:
- Linux_py310:
- vmImage: 'ubuntu-20.04' # keep one job pinned to the oldest image
- python.version: '3.10'
- Linux_py311:
- vmImage: 'ubuntu-latest'
- python.version: '3.11'
- macOS_py310:
- vmImage: 'macOS-latest'
- python.version: '3.10'
- macOS_py311:
- vmImage: 'macOS-latest'
- python.version: '3.11'
- Windows_py310:
- vmImage: 'windows-2019' # keep one job pinned to the oldest image
- python.version: '3.10'
Windows_py311:
- vmImage: 'windows-latest'
+ vmImage: 'windows-2022' # Keep one job pinned to the oldest image
python.version: '3.11'
+ Windows_py312:
+ vmImage: 'windows-latest'
+ python.version: '3.12'
+ Windows_py313:
+ vmImage: 'windows-latest'
+ python.version: '3.13'
maxParallel: 4
pool:
vmImage: '$(vmImage)'
@@ -78,61 +69,7 @@ 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
- 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: |
@@ -142,23 +79,9 @@ stages:
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 \
@@ -173,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
-
{node["caption"]}
\n' - html_block += 'Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: