forked from matplotlib/matplotlib
-
Notifications
You must be signed in to change notification settings - Fork 1
458 lines (425 loc) · 18.5 KB
/
tests.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
---
name: Tests
concurrency:
group: ${{ github.workflow }}-${{ github.event.number }}-${{ github.event.ref }}
cancel-in-progress: true
on:
push:
branches-ignore:
- auto-backport-of-pr-[0-9]+
- v[0-9]+.[0-9]+.[0-9x]+-doc
- dependabot/**
pull_request:
branches-ignore:
- v[0-9]+.[0-9]+.[0-9x]+-doc
paths-ignore:
# Skip running tests if changes are only in documentation directories
- 'doc/**'
- 'galleries/**'
schedule:
# 5:47 UTC on Saturdays
- cron: "47 5 * * 6"
workflow_dispatch:
env:
NO_AT_BRIDGE: 1 # Necessary for GTK3 interactive test.
OPENBLAS_NUM_THREADS: 1
PYTHONFAULTHANDLER: 1
jobs:
test:
if: >-
github.event_name == 'workflow_dispatch' ||
(
github.repository == 'matplotlib/matplotlib' &&
!contains(github.event.head_commit.message, '[ci skip]') &&
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip github]') &&
!contains(github.event.head_commit.message, '[ci doc]')
)
permissions:
contents: read
name: "Python ${{ matrix.python-version }} on ${{ matrix.os }} ${{ matrix.name-suffix }}"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- name-suffix: "(Minimum Versions)"
os: ubuntu-20.04
python-version: '3.10'
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'
- 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'
extra-requirements: '-r requirements/testing/extra.txt'
- os: ubuntu-22.04
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: 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'
- 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'
- 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'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- 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: 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
Linux)
echo 'Acquire::Retries "3";' | sudo tee /etc/apt/apt.conf.d/80-retries
sudo apt-get update -yy
sudo apt-get install -yy --no-install-recommends \
ccache \
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 \
libcairo2-dev \
libffi-dev \
libgeos-dev \
libgirepository1.0-dev \
libsdl2-2.0-0 \
libxkbcommon-x11-0 \
libxcb-cursor0 \
libxcb-icccm4 \
libxcb-image0 \
libxcb-keysyms1 \
libxcb-randr0 \
libxcb-render-util0 \
libxcb-xinerama0 \
lmodern \
ninja-build \
pkg-config \
qtbase5-dev \
texlive-fonts-recommended \
texlive-latex-base \
texlive-latex-extra \
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
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 libnotify4
fi
;;
macOS)
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 actions/setup-python.
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 [email protected]
brew install ccache ghostscript gobject-introspection gtk4 ninja
brew install --cask font-noto-sans-cjk inkscape
;;
esac
- name: Cache pip
uses: actions/cache@v4
if: startsWith(runner.os, 'Linux')
with:
path: ~/.cache/pip
key: ${{ matrix.os }}-py${{ matrix.python-version }}-pip-${{ hashFiles('requirements/*/*.txt') }}
restore-keys: |
${{ matrix.os }}-py${{ matrix.python-version }}-pip-
- name: Cache pip
uses: actions/cache@v4
if: startsWith(runner.os, 'macOS')
with:
path: ~/Library/Caches/pip
key: ${{ matrix.os }}-py${{ matrix.python-version }}-pip-${{ hashFiles('requirements/*/*.txt') }}
restore-keys: |
${{ matrix.os }}-py${{ matrix.python-version }}-pip-
- name: Cache ccache
uses: actions/cache@v4
with:
path: |
~/.ccache
key: ${{ matrix.os }}-py${{ matrix.python-version }}-ccache-${{ hashFiles('src/*') }}
restore-keys: |
${{ matrix.os }}-py${{ matrix.python-version }}-ccache-
- name: Cache Matplotlib
uses: actions/cache@v4
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 }}
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
- name: Install Python dependencies
run: |
# Upgrade pip and setuptools and wheel to get as clean an install as
# possible.
python -m pip install --upgrade pip setuptools wheel
# Install pre-release versions during our weekly upcoming dependency tests.
if [[ "${{ github.event_name }}" == 'schedule'
&& "${{ matrix.name-suffix }}" != '(Minimum Versions)' ]]; then
PRE="--pre"
fi
# Install dependencies from PyPI.
# Preinstall build requirements to enable no-build-isolation builds.
python -m pip install --upgrade $PRE \
'contourpy>=1.0.1' cycler fonttools kiwisolver importlib_resources \
packaging pillow 'pyparsing!=3.1.0' python-dateutil setuptools-scm \
'meson-python>=0.13.1' 'pybind11>=2.13.2' \
-r requirements/testing/all.txt \
${{ matrix.extra-requirements }}
# Install optional dependencies from PyPI.
# Sphinx is needed to run sphinxext tests
python -m pip install --upgrade sphinx!=6.1.2
if [[ "${{ matrix.python-version }}" != '3.13t' ]]; then
# GUI toolkits are pip-installable only for some versions of Python
# so don't fail if we can't install them. Make it easier to check
# whether the install was successful by trying to import the toolkit
# (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 -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'
) && (
python -c 'import gi; gi.require_version("Gtk", "3.0"); from gi.repository import Gtk' &&
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'
# 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 -c 'import PySide2.QtCore' &&
echo 'PySide2 is available' ||
echo 'PySide2 is not available'
fi
python -mpip install --upgrade pyqt6${{ matrix.pyqt6-ver }} &&
python -c 'import PyQt6.QtCore' &&
echo 'PyQt6 is available' ||
echo 'PyQt6 is not available'
python -mpip install --upgrade pyside6${{ matrix.pyside6-ver }} &&
python -c 'import PySide6.QtCore' &&
echo 'PySide6 is available' ||
echo 'PySide6 is not available'
python -mpip install --upgrade \
-f "https://extras.wxpython.org/wxPython4/extras/linux/gtk3/${{ matrix.os }}" \
wxPython &&
python -c 'import wx' &&
echo 'wxPython is available' ||
echo 'wxPython is not available'
fi # Skip backends on Python 3.13t.
- name: Install the nightly dependencies
# Only install the nightly dependencies during the scheduled event
if: github.event_name == 'schedule' && matrix.name-suffix != '(Minimum Versions)'
run: |
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
- name: Install Matplotlib
run: |
ccache -s
git describe
# Set flag in a delayed manner to avoid issues with installing other
# packages
if [[ "${{ runner.os }}" == 'macOS' ]]; then
export CPPFLAGS='-fprofile-instr-generate=default.%m.profraw'
export CPPFLAGS="$CPPFLAGS -fcoverage-mapping"
else
export CPPFLAGS='--coverage -fprofile-abs-path'
fi
python -m pip install --no-deps --no-build-isolation --verbose \
--config-settings=setup-args="-DrcParams-backend=Agg" \
--editable .[dev]
if [[ "${{ runner.os }}" != 'macOS' ]]; then
unset CPPFLAGS
fi
- name: Clear font cache
run: |
rm -rf ~/.cache/matplotlib
if: matrix.delete-font-cache
- name: Run pytest
run: |
if [[ "${{ matrix.python-version }}" == '3.13t' ]]; then
export PYTHON_GIL=0
fi
pytest -rfEsXR -n auto \
--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
find . -name '*.gc*' -delete
else
xcrun llvm-profdata merge -sparse default.*.profraw \
-o default.profdata
xcrun llvm-cov export -format="lcov" build/*/src/*.so \
-instr-profile default.profdata > info.lcov
fi
- name: Upload code coverage
if: ${{ !cancelled() && github.event_name != 'schedule' }}
uses: codecov/codecov-action@v4
with:
name: "${{ matrix.python-version }} ${{ matrix.os }} ${{ matrix.name-suffix }}"
token: ${{ secrets.CODECOV_TOKEN }}
- uses: actions/upload-artifact@v4
if: failure()
with:
name: "${{ matrix.python-version }} ${{ matrix.os }} ${{ matrix.name-suffix }} result images"
path: ./result_images
# Separate dependent job to only upload one issue from the matrix of jobs
create-issue:
if: ${{ failure() && github.event_name == 'schedule' }}
needs: [test]
permissions:
issues: write
runs-on: ubuntu-latest
name: "Create issue on failure"
steps:
- name: Create issue on failure
uses: imjohnbo/issue-bot@v3
with:
title: "[TST] Upcoming dependency test failures"
body: |
The weekly build with nightly wheels from numpy and pandas
has failed. Check the logs for any updates that need to be
made in matplotlib.
https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
pinned: false
close-previous: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}