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/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml index 44043679bc34..9ced8e2f5060 100644 --- a/.github/workflows/cibuildwheel.yml +++ b/.github/workflows/cibuildwheel.yml @@ -44,10 +44,10 @@ jobs: fetch-depth: 0 persist-credentials: false - - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 + - 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 @@ -70,7 +70,7 @@ jobs: run: twine check dist/* - name: Upload sdist result - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: cibw-sdist path: dist/*.tar.gz @@ -131,13 +131,13 @@ jobs: steps: - name: Download sdist - uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: cibw-sdist path: dist/ - name: Build wheels for CPython 3.13 - uses: pypa/cibuildwheel@42728e866bbc80d544a70825bd9990b9a26f1a50 # v2.23.1 + uses: pypa/cibuildwheel@faf86a6ed7efa889faf6996aa23820831055001a # v2.23.3 with: package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }} env: @@ -148,7 +148,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.12 - uses: pypa/cibuildwheel@42728e866bbc80d544a70825bd9990b9a26f1a50 # v2.23.1 + uses: pypa/cibuildwheel@faf86a6ed7efa889faf6996aa23820831055001a # v2.23.3 with: package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }} env: @@ -156,32 +156,27 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_archs }} - name: Build wheels for CPython 3.11 - uses: pypa/cibuildwheel@42728e866bbc80d544a70825bd9990b9a26f1a50 # v2.23.1 + 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@42728e866bbc80d544a70825bd9990b9a26f1a50 # v2.23.1 - 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@42728e866bbc80d544a70825bd9990b9a26f1a50 # v2.23.1 + uses: pypa/cibuildwheel@faf86a6ed7efa889faf6996aa23820831055001a # v2.23.3 with: package-dir: dist/${{ needs.build_sdist.outputs.SDIST_NAME }} env: - CIBW_BUILD: "pp310-*" + CIBW_BUILD: "pp311-*" CIBW_ARCHS: ${{ matrix.cibw_archs }} 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@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: cibw-wheels-${{ runner.os }}-${{ matrix.cibw_archs }} path: ./wheelhouse/*.whl @@ -199,7 +194,7 @@ jobs: contents: read steps: - name: Download packages - uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: pattern: cibw-* path: dist @@ -209,7 +204,7 @@ jobs: run: ls dist - name: Generate artifact attestation for sdist and wheel - uses: actions/attest-build-provenance@c074443f1aee8d4aeeae555aebba3282517141b2 # v2.2.3 + uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0 with: subject-path: dist/matplotlib-* diff --git a/.github/workflows/circleci.yml b/.github/workflows/circleci.yml index e0ed6adf4e65..f0ae304882e7 100644 --- a/.github/workflows/circleci.yml +++ b/.github/workflows/circleci.yml @@ -41,7 +41,7 @@ jobs: - name: Set up reviewdog if: "${{ steps.fetch-artifacts.outputs.count != 0 }}" - uses: reviewdog/action-setup@3f401fe1d58fe77e10d665ab713057375e39b887 # v1.3.0 + uses: reviewdog/action-setup@e04ffabe3898a0af8d0fb1af00c188831c4b5893 # v1.3.2 with: reviewdog_version: latest diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c9d7019f2e8d..774de9b116d8 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -31,7 +31,7 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/init@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17 with: languages: ${{ matrix.language }} @@ -42,4 +42,4 @@ jobs: pip install --user -v . - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/analyze@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17 diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml index f4941513d86e..4a5b79c0538e 100644 --- a/.github/workflows/cygwin.yml +++ b/.github/workflows/cygwin.yml @@ -140,21 +140,21 @@ jobs: # FreeType build fails with bash, succeeds with dash - name: Cache pip - uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 + 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@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 + 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@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: path: | C:\cygwin\home\runneradmin\.cache\matplotlib diff --git a/.github/workflows/mypy-stubtest.yml b/.github/workflows/mypy-stubtest.yml index ddd9a9d0e80b..92a67236fb9d 100644 --- a/.github/workflows/mypy-stubtest.yml +++ b/.github/workflows/mypy-stubtest.yml @@ -17,12 +17,12 @@ jobs: persist-credentials: false - name: Set up Python 3 - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 + 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@3f401fe1d58fe77e10d665ab713057375e39b887 # v1.3.9 + uses: reviewdog/action-setup@e04ffabe3898a0af8d0fb1af00c188831c4b5893 # v1.3.9 - name: Install tox run: python -m pip install tox @@ -33,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/reviewdog.yml b/.github/workflows/reviewdog.yml index c53c70d7a948..c803fcc6ba38 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -6,8 +6,8 @@ permissions: contents: read jobs: - flake8: - name: flake8 + ruff: + name: ruff runs-on: ubuntu-latest permissions: checks: write @@ -17,23 +17,23 @@ jobs: persist-credentials: false - name: Set up Python 3 - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: - python-version: '3.10' + 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@3f401fe1d58fe77e10d665ab713057375e39b887 # v1.3.9 + 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 @@ -46,15 +46,15 @@ jobs: persist-credentials: false - name: Set up Python 3 - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: - python-version: '3.10' + 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@3f401fe1d58fe77e10d665ab713057375e39b887 # v1.3.9 + uses: reviewdog/action-setup@e04ffabe3898a0af8d0fb1af00c188831c4b5893 # v1.3.9 - name: Run mypy env: @@ -77,7 +77,7 @@ jobs: persist-credentials: false - name: eslint - uses: reviewdog/action-eslint@9b5b0150e399e1f007ee3c27bc156549810a64e3 # v1.33.0 + uses: reviewdog/action-eslint@2fee6dd72a5419ff4113f694e2068d2a03bb35dd # v1.33.2 with: filter_mode: nofilter github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8960e61e8f2c..911fa69ec38b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -48,67 +48,34 @@ 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' - extra-requirements: '-r requirements/testing/extra.txt' - CFLAGS: "-fno-lto" # Ensure that disabling LTO works. - # https://github.com/matplotlib/matplotlib/pull/26052#issuecomment-1574595954 - # https://www.riverbankcomputing.com/pipermail/pyqt/2023-November/045606.html - pyqt6-ver: '!=6.5.1,!=6.6.0,!=6.7.1' - # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346 - pyside6-ver: '!=6.5.1' - os: ubuntu-22.04 python-version: '3.11' - # 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-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 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' - 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' + - os: ubuntu-24.04 + python-version: '3.12' - os: macos-13 # This runner is on Intel chips. # merge numpy and pandas install in nighties test when this runner is dropped - python-version: '3.10' - # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346 - pyside6-ver: '!=6.5.1' + python-version: '3.11' - os: macos-14 # This runner is on M1 (arm64) chips. python-version: '3.12' # https://github.com/matplotlib/matplotlib/issues/29732 pygobject-ver: '<3.52.0' - # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346 - pyside6-ver: '!=6.5.1' - os: macos-14 # This runner is on M1 (arm64) chips. python-version: '3.13' # https://github.com/matplotlib/matplotlib/issues/29732 pygobject-ver: '<3.52.0' - # https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-2346 - pyside6-ver: '!=6.5.1' steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -117,15 +84,7 @@ jobs: persist-credentials: false - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 - 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@869aeafb7eeb9dc48ba68acc0479e6fc3fd7ce5e # v5.4.0 - if: matrix.python-version == '3.13t' + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ matrix.python-version }} allow-prereleases: true @@ -153,7 +112,6 @@ jobs: libcairo2-dev \ libffi-dev \ libgeos-dev \ - libgirepository1.0-dev \ libnotify4 \ libsdl2-2.0-0 \ libxkbcommon-x11-0 \ @@ -178,10 +136,13 @@ jobs: 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 - sudo apt-get install -yy --no-install-recommends gir1.2-gtk-4.0 + 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 \ + libgirepository-2.0-dev fi ;; macOS) @@ -205,7 +166,7 @@ jobs: esac - name: Cache pip - uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 if: startsWith(runner.os, 'Linux') with: path: ~/.cache/pip @@ -213,7 +174,7 @@ jobs: restore-keys: | ${{ matrix.os }}-py${{ matrix.python-version }}-pip- - name: Cache pip - uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 if: startsWith(runner.os, 'macOS') with: path: ~/Library/Caches/pip @@ -221,7 +182,7 @@ jobs: restore-keys: | ${{ matrix.os }}-py${{ matrix.python-version }}-pip- - name: Cache ccache - uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: path: | ~/.ccache @@ -229,16 +190,16 @@ jobs: restore-keys: | ${{ matrix.os }}-py${{ matrix.python-version }}-ccache- - name: Cache Matplotlib - uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: path: | ~/.cache/matplotlib !~/.cache/matplotlib/tex.cache !~/.cache/matplotlib/test_cache - key: 5-${{ matrix.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: | - 5-${{ matrix.os }}-py${{ matrix.python-version }}-mpl-${{ github.ref }}- - 5-${{ matrix.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: | @@ -283,7 +244,7 @@ jobs: # 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${{ matrix.pyqt5-ver }} && + python -mpip install --upgrade --only-binary :all: pyqt5 && python -c 'import PyQt5.QtCore' && echo 'PyQt5 is available' || echo 'PyQt5 is not available' @@ -293,16 +254,16 @@ jobs: # 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 --only-binary :all: 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 --only-binary :all: 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' @@ -405,11 +366,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 +386,12 @@ jobs: fi - name: Upload code coverage if: ${{ !cancelled() && github.event_name != 'schedule' }} - uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0 + 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@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: failure() with: name: "${{ matrix.python-version }} ${{ matrix.os }} ${{ matrix.name-suffix }} result images" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0dc717a56e9e..afcdc44c1b4a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,7 +28,7 @@ repos: - id: trailing-whitespace exclude_types: [svg] - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.14.1 + 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.30.0 + 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/azure-pipelines.yml b/azure-pipelines.yml index fff14a1819d6..d68a9d36f0d3 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -49,11 +49,8 @@ stages: - job: Pytest strategy: matrix: - 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' @@ -104,50 +101,23 @@ stages: 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 - - true - - - .*\\.*\.pyd - - - - EOF - echo "Starting $TOOL in server mode" - "$TOOL" collect \ - -config:extensions.config -session:$SESSION_ID \ - -output:extensions.coverage -verbose & - echo "Started $TOOL" - VS_VER=2019 - fi - fi + # 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 + echo "##vso[task.setvariable variable=VS_COVERAGE_TOOL]$TOOL" PYTHONFAULTHANDLER=1 pytest -rfEsXR -n 2 \ diff --git a/ci/codespell-ignore-words.txt b/ci/codespell-ignore-words.txt index e28e7ef99fd7..0ebc5211b80c 100644 --- a/ci/codespell-ignore-words.txt +++ b/ci/codespell-ignore-words.txt @@ -1,4 +1,5 @@ aas +ABD axises coo curvelinear diff --git a/doc/_embedded_plots/figure_subplots_adjust.py b/doc/_embedded_plots/figure_subplots_adjust.py index b4b8d7d32a3d..6f99a3febcdc 100644 --- a/doc/_embedded_plots/figure_subplots_adjust.py +++ b/doc/_embedded_plots/figure_subplots_adjust.py @@ -1,28 +1,34 @@ import matplotlib.pyplot as plt -def arrow(p1, p2, **props): - axs[0, 0].annotate( - "", p1, p2, xycoords='figure fraction', - arrowprops=dict(arrowstyle="<->", shrinkA=0, shrinkB=0, **props)) - - fig, axs = plt.subplots(2, 2, figsize=(6.5, 4)) fig.set_facecolor('lightblue') fig.subplots_adjust(0.1, 0.1, 0.9, 0.9, 0.4, 0.4) + +overlay = fig.add_axes([0, 0, 1, 1], zorder=100) +overlay.axis("off") +xycoords='figure fraction' +arrowprops=dict(arrowstyle="<->", shrinkA=0, shrinkB=0) + for ax in axs.flat: ax.set(xticks=[], yticks=[]) -arrow((0, 0.75), (0.1, 0.75)) # left -arrow((0.435, 0.75), (0.565, 0.75)) # wspace -arrow((0.9, 0.75), (1, 0.75)) # right +overlay.annotate("", (0, 0.75), (0.1, 0.75), + xycoords=xycoords, arrowprops=arrowprops) # left +overlay.annotate("", (0.435, 0.25), (0.565, 0.25), + xycoords=xycoords, arrowprops=arrowprops) # wspace +overlay.annotate("", (0, 0.8), (0.9, 0.8), + xycoords=xycoords, arrowprops=arrowprops) # right fig.text(0.05, 0.7, "left", ha="center") -fig.text(0.5, 0.7, "wspace", ha="center") -fig.text(0.95, 0.7, "right", ha="center") +fig.text(0.5, 0.3, "wspace", ha="center") +fig.text(0.05, 0.83, "right", ha="center") -arrow((0.25, 0), (0.25, 0.1)) # bottom -arrow((0.25, 0.435), (0.25, 0.565)) # hspace -arrow((0.25, 0.9), (0.25, 1)) # top -fig.text(0.28, 0.05, "bottom", va="center") +overlay.annotate("", (0.75, 0), (0.75, 0.1), + xycoords=xycoords, arrowprops=arrowprops) # bottom +overlay.annotate("", (0.25, 0.435), (0.25, 0.565), + xycoords=xycoords, arrowprops=arrowprops) # hspace +overlay.annotate("", (0.8, 0), (0.8, 0.9), + xycoords=xycoords, arrowprops=arrowprops) # top +fig.text(0.65, 0.05, "bottom", va="center") fig.text(0.28, 0.5, "hspace", va="center") -fig.text(0.28, 0.95, "top", va="center") +fig.text(0.82, 0.05, "top", va="center") diff --git a/doc/_static/mpl.css b/doc/_static/mpl.css index 204739b1741b..25bad17c3938 100644 --- a/doc/_static/mpl.css +++ b/doc/_static/mpl.css @@ -208,3 +208,15 @@ div.wide-table table th.stub { .section-toc.toctree-wrapper .toctree-l1>ul{ padding-left: 0; } + +.sidebar-cheatsheets { + margin-bottom: 3em; +} + +.sidebar-cheatsheets > h3 { + margin-top: 0; +} + +.sidebar-cheatsheets > img { + width: 100%; +} diff --git a/doc/_templates/cheatsheet_sidebar.html b/doc/_templates/cheatsheet_sidebar.html index 3f2b7c4f4db1..2ca6548ddd4d 100644 --- a/doc/_templates/cheatsheet_sidebar.html +++ b/doc/_templates/cheatsheet_sidebar.html @@ -1,6 +1,6 @@