Skip to content

Add parallel test target, using pytest-xdist #8972

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

wiredfool
Copy link
Member

@wiredfool wiredfool commented May 23, 2025

Changes proposed in this pull request:

  • Added parallel test target in the make file.

This seems to be running 4 runners on an 8 core machine, for about a 2.5x speedup. Note that this is on the standard with GIL python, but I'm seeing 1.5x the user time. -n 8 on this machine doesn't speed up the wall clock time much (2-4%, but does significantly add to user time.

(note, these numbers are a 8 core intel server in the cloud, probably 5 years old at this point)

$ time make test
....
real	2m8.944s
user	2m1.800s
sys	0m8.598s

$ time make test-p
...
real	0m47.244s
user	3m3.306s
sys	0m10.233s

On an M4 Air

$ time make test 
...
real    0m38.527s
user    0m32.428s
sys     0m5.074s

$ time make test-p
real    0m12.731s
user    0m59.613s
sys     0m8.361s

@hugovk
Copy link
Member

hugovk commented May 23, 2025

That's a huge improvement!

Shall we just make it the default? Then it'll be used through make, tox, and direct pytest.

--- a/pyproject.toml
+++ b/pyproject.toml
 [tool.pytest.ini_options]
-addopts = "-ra --color=yes"
+addopts = "-ra --color=yes --numprocesses=auto"

Although it does change the (pytest and tox) output from:

Tests/oss-fuzz/test_fuzzers.py ................................................................... [  1%]
.................................................................................................. [  3%]
.................................................................................................. [  5%]
.................................................................................................. [  7%]
.................................................................................................. [  9%]
.................................................................................................. [ 11%]
.................................................................................................. [ 13%]
.................................................................................................. [ 15%]
.................................................................................................. [ 16%]
.................................................................................................. [ 18%]
.................................................................................................. [ 20%]
.................................................................................................. [ 22%]
...............                                                                                    [ 23%]
Tests/test_000_sanity.py .                                                                         [ 23%]
Tests/test_arrow.py ......................                                                         [ 23%]
Tests/test_binary.py ...                                                                           [ 23%]
Tests/test_bmp_reference.py ...                                                                    [ 23%]
Tests/test_box_blur.py ................                                                            [ 24%]
Tests/test_color_lut.py .......................ss.............                                     [ 24%]
Tests/test_core_resources.py ................                                                      [ 25%]
Tests/test_decompression_bomb.py ...........                                                       [ 25%]
Tests/test_deprecate.py ..........                                                                 [ 25%]
Tests/test_features.py ......s................                                                     [ 25%]
Tests/test_file_apng.py ............................................                               [ 26%]
Tests/test_file_avif.py ..................................................................s....... [ 28%]
s...s....s......s...........                                                                       [ 28%]
Tests/test_file_blp.py .............                                                               [ 29%]
Tests/test_file_bmp.py .............................                                               [ 29%]
Tests/test_file_bufrstub.py .....                                                                  [ 29%]
Tests/test_file_container.py ........................                                              [ 30%]
Tests/test_file_cur.py ..                                                                          [ 30%]
Tests/test_file_dcx.py .........                                                                   [ 30%]
Tests/test_file_dds.py ................................................                            [ 31%]
Tests/test_file_eps.py ..........................................................                  [ 32%]
Tests/test_file_fits.py ......                                                                     [ 32%]
Tests/test_file_fli.py .................                                                           [ 33%]
Tests/test_file_fpx.py ....                                                                        [ 33%]
Tests/test_file_ftex.py ....                                                                       [ 33%]
Tests/test_file_gbr.py ....                                                                        [ 33%]
Tests/test_file_gd.py ...                                                                          [ 33%]
Tests/test_file_gif.py ........................................................................... [ 34%]
...............................                                                                    [ 35%]
Tests/test_file_gimpgradient.py ..........                                                         [ 35%]
Tests/test_file_gimppalette.py ....                                                                [ 35%]
Tests/test_file_gribstub.py .....                                                                  [ 35%]
Tests/test_file_hdf5stub.py .....                                                                  [ 35%]
Tests/test_file_icns.py ...........                                                                [ 36%]
Tests/test_file_ico.py ......................                                                      [ 36%]
Tests/test_file_im.py ...............                                                              [ 36%]
Tests/test_file_imt.py ....                                                                        [ 37%]
Tests/test_file_iptc.py ..........                                                                 [ 37%]
Tests/test_file_jpeg.py .......................................................................... [ 38%]
.............................s                                                                     [ 39%]
Tests/test_file_jpeg2k.py .....................s................ss..........sssss........          [ 40%]
Tests/test_file_libtiff.py ...........................................................s........... [ 41%]
............................                                                                       [ 42%]
Tests/test_file_libtiff_small.py ...                                                               [ 42%]
Tests/test_file_mcidas.py ..                                                                       [ 42%]
Tests/test_file_mic.py .......                                                                     [ 42%]
Tests/test_file_mpeg.py ...                                                                        [ 42%]
Tests/test_file_mpo.py ................................                                            [ 43%]
Tests/test_file_msp.py .......                                                                     [ 43%]
Tests/test_file_palm.py ....                                                                       [ 43%]
Tests/test_file_pcd.py .                                                                           [ 43%]
Tests/test_file_pcx.py ..................                                                          [ 44%]
Tests/test_file_pdf.py .....................                                                       [ 44%]
Tests/test_file_pixar.py ..                                                                        [ 44%]
Tests/test_file_png.py .............................................................               [ 45%]
Tests/test_file_ppm.py ..............................................                              [ 46%]
Tests/test_file_psd.py ....................                                                        [ 47%]
Tests/test_file_qoi.py ..                                                                          [ 47%]
Tests/test_file_sgi.py .............                                                               [ 47%]
Tests/test_file_spider.py ................                                                         [ 47%]
Tests/test_file_sun.py ........                                                                    [ 47%]
Tests/test_file_tar.py .......                                                                     [ 47%]
Tests/test_file_tga.py ........................................                                    [ 48%]
Tests/test_file_tiff.py .......................................................................... [ 50%]
...........s                                                                                       [ 50%]
Tests/test_file_tiff_metadata.py ............................                                      [ 51%]
Tests/test_file_wal.py ..                                                                          [ 51%]
Tests/test_file_webp.py .......................                                                    [ 51%]
Tests/test_file_webp_alpha.py ......                                                               [ 51%]
Tests/test_file_webp_animated.py ........                                                          [ 51%]
Tests/test_file_webp_lossless.py .                                                                 [ 51%]
Tests/test_file_webp_metadata.py ........                                                          [ 52%]
Tests/test_file_wmf.py .........                                                                   [ 52%]
Tests/test_file_xbm.py ......                                                                      [ 52%]
Tests/test_file_xpm.py ...                                                                         [ 52%]
Tests/test_file_xvthumb.py ...                                                                     [ 52%]
Tests/test_font_bdf.py ...                                                                         [ 52%]
Tests/test_font_crash.py .                                                                         [ 52%]
Tests/test_font_leaks.py ..                                                                        [ 52%]
Tests/test_font_pcf.py ......                                                                      [ 52%]
Tests/test_font_pcf_charsets.py .........                                                          [ 52%]
Tests/test_fontfile.py ..                                                                          [ 52%]
Tests/test_format_hsv.py ....                                                                      [ 52%]
Tests/test_format_lab.py ...                                                                       [ 53%]
Tests/test_image.py .............................................................................. [ 54%]
.................................................................................................. [ 56%]
..................                                                                                 [ 56%]
Tests/test_image_access.py ..s......................................................s              [ 58%]
Tests/test_image_convert.py ...........................                                            [ 58%]
Tests/test_image_copy.py ........                                                                  [ 58%]
Tests/test_image_crop.py .............                                                             [ 59%]
Tests/test_image_draft.py ...                                                                      [ 59%]
Tests/test_image_entropy.py .                                                                      [ 59%]
Tests/test_image_filter.py ....................................................................... [ 60%]
.................................................................................................. [ 62%]
...............................................................                                    [ 63%]
Tests/test_image_frombytes.py ..                                                                   [ 63%]
Tests/test_image_fromqimage.py sssss                                                               [ 63%]
Tests/test_image_getbands.py .                                                                     [ 63%]
Tests/test_image_getbbox.py .......                                                                [ 64%]
Tests/test_image_getcolors.py ..                                                                   [ 64%]
Tests/test_image_getdata.py ..                                                                     [ 64%]
Tests/test_image_getextrema.py ..                                                                  [ 64%]
Tests/test_image_getim.py .                                                                        [ 64%]
Tests/test_image_getpalette.py ..                                                                  [ 64%]
Tests/test_image_getprojection.py .                                                                [ 64%]
Tests/test_image_histogram.py .                                                                    [ 64%]
Tests/test_image_load.py .....                                                                     [ 64%]
Tests/test_image_mode.py ...........                                                               [ 64%]
Tests/test_image_paste.py ...................................                                      [ 65%]
Tests/test_image_point.py ....                                                                     [ 65%]
Tests/test_image_putalpha.py ...                                                                   [ 65%]
Tests/test_image_putdata.py ...............                                                        [ 65%]
Tests/test_image_putpalette.py ........                                                            [ 65%]
Tests/test_image_quantize.py .s...............                                                     [ 66%]
Tests/test_image_reduce.py ....................................................................... [ 67%]
.................................................................................................. [ 69%]
........................................                                                           [ 70%]
Tests/test_image_resample.py ...............................................xx.................... [ 71%]
...............                                                                                    [ 72%]
Tests/test_image_resize.py ....................................................................... [ 73%]
.......                                                                                            [ 73%]
Tests/test_image_rotate.py ..........................                                              [ 74%]
Tests/test_image_split.py ...........                                                              [ 74%]
Tests/test_image_thumbnail.py ..........                                                           [ 74%]
Tests/test_image_tobitmap.py .                                                                     [ 74%]
Tests/test_image_tobytes.py .                                                                      [ 74%]
Tests/test_image_transform.py .................................................................... [ 75%]
.......                                                                                            [ 76%]
Tests/test_image_transpose.py ........................................                             [ 76%]
Tests/test_imagechops.py ..............................                                            [ 77%]
Tests/test_imagecms.py ......................................                                      [ 78%]
Tests/test_imagecolor.py ......                                                                    [ 78%]
Tests/test_imagedraw.py .......................................................................... [ 79%]
.................................................................................................. [ 81%]
.........................................................x........................................ [ 83%]
...                                                                                                [ 83%]
Tests/test_imagedraw2.py ................................................                          [ 84%]
Tests/test_imageenhance.py ......                                                                  [ 84%]
Tests/test_imagefile.py ...........................                                                [ 85%]
Tests/test_imagefont.py .......................................................................... [ 86%]
...................s.............................................................................. [ 88%]
..................s..................                                                              [ 89%]
Tests/test_imagefontctl.py ......................................ss............................... [ 90%]
.........                                                                                          [ 91%]
Tests/test_imagefontpil.py ......                                                                  [ 91%]
Tests/test_imagegrab.py .ss.s.sssssss                                                              [ 91%]
Tests/test_imagemath_lambda_eval.py .......................                                        [ 92%]
Tests/test_imagemath_unsafe_eval.py .............................                                  [ 92%]
Tests/test_imagemorph.py .......................                                                   [ 93%]
Tests/test_imageops.py ...................................                                         [ 93%]
Tests/test_imageops_usm.py .....                                                                   [ 93%]
Tests/test_imagepalette.py ...............                                                         [ 94%]
Tests/test_imagepath.py ............................                                               [ 94%]
Tests/test_imageqt.py ssssssss                                                                     [ 94%]
Tests/test_imagesequence.py ........                                                               [ 95%]
Tests/test_imageshow.py ....sssss..............                                                    [ 95%]
Tests/test_imagestat.py ...                                                                        [ 95%]
Tests/test_imagetk.py .............                                                                [ 95%]
Tests/test_imagewin.py ...ssssss                                                                   [ 95%]
Tests/test_lib_image.py .                                                                          [ 95%]
Tests/test_lib_pack.py ......................................                                      [ 96%]
Tests/test_locale.py s                                                                             [ 96%]
Tests/test_main.py ...                                                                             [ 96%]
Tests/test_map.py ..s                                                                              [ 96%]
Tests/test_mode_i16.py .......                                                                     [ 97%]
Tests/test_pdfparser.py .....                                                                      [ 97%]
Tests/test_pickle.py ............................................................................. [ 98%]
.................                                                                                  [ 99%]
Tests/test_psdraw.py ..                                                                            [ 99%]
Tests/test_pyroma.py .                                                                             [ 99%]
Tests/test_qt_image_qapplication.py s                                                              [ 99%]
Tests/test_qt_image_toqimage.py sssss                                                              [ 99%]
Tests/test_sgi_crash.py ...........                                                                [ 99%]
Tests/test_shell_injection.py ....                                                                 [ 99%]
Tests/test_tiff_crashes.py ...............                                                         [ 99%]
Tests/test_tiff_ifdrational.py .....                                                               [ 99%]
Tests/test_util.py .....                                                                           [ 99%]
Tests/test_webp_leaks.py .                                                                         [100%]

To:

.................................................................................................. [  1%]
.................................................................................................. [  3%]
.................................................................................................. [  5%]
.................................................................................................. [  7%]
...........................................................................ss..................... [  9%]
.................................................................................................. [ 11%]
.................................................................................................. [ 13%]
.........................................................................s........................ [ 15%]
.................................................................................................. [ 17%]
.................................................................................................. [ 19%]
.................................................................................................. [ 21%]
.................................................................................................. [ 23%]
...........................s...................................................................... [ 25%]
.................................................................................................. [ 27%]
...................s.............................................................................. [ 29%]
.................................................................................................. [ 31%]
...................................................s.................................ss........s.. [ 33%]
.s.................s....sssss..................................................................... [ 35%]
.................................................................................................. [ 37%]
...............................................s.................................................. [ 39%]
.................................................................................................. [ 41%]
.............................................................s.................................... [ 42%]
..............................................................s................................... [ 44%]
.................................................................................................. [ 46%]
.................................................................................................. [ 48%]
.................................................................................................. [ 50%]
..........sssss...............s................................................................... [ 52%]
.................................................................................................. [ 54%]
.................................................................................................. [ 56%]
.............................s.................................................................... [ 58%]
.............................................................x..........x......................... [ 60%]
.................................................................................................. [ 62%]
.................................................................................................. [ 64%]
.................................................................................................. [ 66%]
.................................................................................................. [ 68%]
.................................................................................................. [ 70%]
.................................................................................................. [ 72%]
.................................................................................................. [ 74%]
.................................................................................................. [ 76%]
...............................................................................x.................. [ 78%]
.................................................................................................. [ 80%]
...........................s....s...............................s.....s........................... [ 82%]
.......................................ss......................................................... [ 84%]
.................................................................................................. [ 85%]
........s........sssssss.....sssss................................................................ [ 87%]
...................sssss............................................s..................ss......... [ 89%]
..................................................s............................................... [ 91%]
....................................................s..ss.ss...................................... [ 93%]
..................................ss.s...s...................s..s.sss............................. [ 95%]
.................................................................................................. [ 97%]
.................................................................................................. [ 99%]
................                                                                                   [100%]

One option is to add pytest-sugar to optional-dependencies.tests (see https://blog.trailofbits.com/2025/05/01/making-pypis-test-suite-81-faster/ for sample video):

 Tests/oss-fuzz/test_fuzzers.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓  1% ▎
                                ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓  3% ▍
                                ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓  4% ▌
 Tests/test_000_sanity.py ✓                                                                           3% ▍
 Tests/test_arrow.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                           5% ▌
 Tests/oss-fuzz/test_fuzzers.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓  6% ▋
 Tests/test_binary.py ✓✓✓                                                                             5% ▌
 Tests/test_bmp_reference.py ✓✓✓                                                                      7% ▋
 Tests/oss-fuzz/test_fuzzers.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓  8% ▊
 Tests/test_box_blur.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                              7% ▊
 Tests/test_color_lut.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                       9% ▉
 Tests/oss-fuzz/test_fuzzers.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 10% █
 Tests/test_core_resources.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                       10% ▉
 Tests/test_decompression_bomb.py ✓✓✓✓✓✓✓✓✓✓✓                                                        14% █▌
 Tests/test_file_avif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                          35% ███▌
 Tests/oss-fuzz/test_fuzzers.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 12% █▎
 Tests/test_file_avif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                         36% ███▋
                                ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 15% █▌
 Tests/test_deprecate.py ✓✓✓✓✓✓✓✓✓✓                                                                  15% █▌
 Tests/test_file_avif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                       36% ███▋
 Tests/test_features.py ✓✓✓✓✓✓s✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                      15% █▌
 Tests/test_file_avif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                      37% ███▋
 Tests/test_file_avif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s                  38% ███▉
                                ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 18% █▉
 Tests/test_file_avif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓                39% ███▉
 Tests/test_file_avif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓✓s✓✓✓s✓✓✓✓s 40% ████
 Tests/test_file_dds.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                             38% ███▊
 Tests/oss-fuzz/test_fuzzers.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 23% ██▍
 Tests/test_file_apng.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                 42% ████▎
 Tests/test_file_apng.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                42% ████▎
 Tests/oss-fuzz/test_fuzzers.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 28% ██▉
 Tests/test_file_eps.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                             43% ████▍
 Tests/test_file_libtiff.py ✓✓✓✓✓✓✓✓✓✓✓✓✓                                                            26% ██▋
 Tests/test_file_fits.py ✓✓✓✓✓✓                                                                      29% ██▉
 Tests/test_file_jpeg.py ✓✓✓✓✓✓✓✓✓✓✓✓✓s                                                              35% ███▌
 Tests/test_file_tar.py ✓✓✓                                                                          28% ██▊
 Tests/test_file_tga.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                     32% ███▎
 Tests/oss-fuzz/test_fuzzers.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 45% ████▌
 Tests/test_file_fli.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                            30% ██▉
 Tests/test_file_fpx.py ✓✓✓✓                                                                         30% ███
 Tests/test_file_ftex.py ✓✓✓✓                                                                        30% ███
 Tests/test_file_eps.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                            49% ████▉
 Tests/test_file_pcd.py ✓                                                                            30% ███
 Tests/test_file_gbr.py ✓✓✓✓                                                                         30% ███
 Tests/test_file_pcx.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                           32% ███▎
 Tests/test_file_gd.py ✓✓✓                                                                           30% ███
 Tests/test_file_gif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                    36% ███▋
 Tests/test_file_pdf.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                        46% ████▋
 Tests/test_file_eps.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                           50% █████
 Tests/test_file_bmp.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                35% ███▌
 Tests/test_file_jpeg2k.py ✓✓✓✓✓✓✓✓✓✓✓✓                                                              50% █████
 Tests/test_file_bufrstub.py ✓✓✓✓✓                                                                   36% ███▋
 Tests/test_file_tiff_metadata.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                       38% ███▉
 Tests/test_file_container.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                               36% ███▋
 Tests/test_file_tiff.py ✓✓✓✓✓✓✓✓✓✓s                                                                 37% ███▊
 Tests/test_file_cur.py ✓✓                                                                           37% ███▋
 Tests/test_file_dcx.py ✓✓✓✓✓✓✓✓✓                                                                    37% ███▊
 Tests/test_image.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 39% ███▉
 Tests/test_file_wal.py ✓✓                                                                           38% ███▉
 Tests/test_file_jpeg2k.py ✓✓✓✓✓✓✓✓✓✓✓✓✓                                                             51% █████▏
 Tests/test_image.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                          41% ████▏
 Tests/test_file_avif.py ✓✓✓✓✓✓✓✓✓✓✓✓                                                                43% ████▍
 Tests/test_image_access.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓               44% ████▌
 Tests/test_image_array.py ✓✓✓✓                                                                      41% ████▎
 Tests/test_file_jpeg2k.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                           52% █████▎
 Tests/test_image_copy.py ✓✓✓✓✓✓✓✓                                                                   44% ████▍
 Tests/test_file_hdf5stub.py ✓✓✓✓✓                                                                   44% ████▍
 Tests/test_image_crop.py ✓✓✓✓✓✓✓✓✓✓✓✓✓                                                              45% ████▌
 Tests/test_image_filter.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 46% ████▋
 Tests/test_file_avif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                              55% █████▌
 Tests/test_file_jpeg2k.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓                                                56% █████▋
 Tests/test_image_entropy.py ✓                                                                       46% ████▋
 Tests/test_file_gif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓  58% █████▉
 Tests/test_file_gif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 58% █████▉
 Tests/test_file_jpeg2k.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓✓✓                                            60% ██████
 Tests/test_file_jpeg2k.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓✓✓✓                                           60% ██████
 Tests/oss-fuzz/test_fuzzers.py ✓✓✓✓                                                                 57% █████▋
 Tests/test_file_jpeg2k.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓✓✓✓✓                                          61% ██████▏
 Tests/test_file_webp_metadata.py ✓✓✓✓✓✓✓✓                                                           50% █████
 Tests/test_image_frombytes.py ✓✓                                                                    50% █████
 Tests/test_image_fromqimage.py sssss                                                                51% █████▎
 Tests/test_file_eps.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                 63% ██████▍
 Tests/test_image_getbbox.py ✓✓✓✓✓✓✓                                                                 50% █████
 Tests/test_file_wmf.py ✓✓✓✓✓✓✓✓✓                                                                    50% █████▏
 Tests/test_image_getcolors.py ✓✓                                                                    51% █████▏
 Tests/test_file_xbm.py ✓✓✓✓✓✓                                                                       51% █████▏
 Tests/test_file_avif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓                                                      64% ██████▌
 Tests/test_file_eps.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                65% ██████▌
 Tests/test_file_icns.py ✓✓✓✓✓✓                                                                      65% ██████▌
 Tests/test_image_getpalette.py ✓✓                                                                   51% █████▏
 Tests/test_file_xpm.py ✓✓✓                                                                          51% █████▏
 Tests/test_file_avif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓✓✓                                                    68% ██████▊
 Tests/test_file_jpeg2k.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ss✓✓✓✓✓✓✓✓✓✓sssss✓✓✓✓✓✓             70% ██████▉
 Tests/test_file_libtiff.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                          71% ███████▎
 Tests/test_file_xvthumb.py ✓✓✓                                                                      51% █████▏
 Tests/test_font_bdf.py ✓✓✓                                                                          51% █████▏
 Tests/test_file_icns.py ✓✓✓✓✓✓✓✓✓✓✓                                                                 72% ███████▎
 Tests/test_file_libtiff.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                        73% ███████▍
 Tests/test_file_libtiff.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                      73% ███████▍
 Tests/test_file_eps.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                               74% ███████▌
 Tests/test_image_putalpha.py ✓✓✓                                                                    52% █████▎
 Tests/test_image_putdata.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                         53% █████▍
 Tests/test_image_putpalette.py ✓✓✓✓✓✓✓✓                                                             53% █████▍
 Tests/test_file_jpeg.py ✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                               78% ███████▊
 Tests/test_file_eps.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                             79% ███████▉
                            ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 56% █████▋
                            ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                    59% █████▉
 Tests/test_image_resample.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 59% █████▉
 Tests/test_image_resize.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 63% ██████▍
 Tests/test_file_gif.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                               63% ██████▍
 Tests/test_image_rotate.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                               63% ██████▍
 Tests/test_image_resample.py xx✓✓✓✓✓✓✓✓✓✓✓✓                                                         62% ██████▎
 Tests/test_image_split.py ✓✓✓✓✓✓✓✓✓✓✓                                                               61% ██████▏
 Tests/test_image_thumbnail.py ✓✓✓✓✓✓✓✓✓✓                                                            61% ██████▏
 Tests/test_file_eps.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                    83% ████████▍
 Tests/test_image_tobytes.py ✓                                                                       61% ██████▎
 Tests/test_image_transform.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 65% ██████▌
 Tests/test_file_gimpgradient.py ✓✓✓✓✓✓✓✓✓✓                                                          63% ██████▍
 Tests/test_file_eps.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                   85% ████████▌
 Tests/test_file_libtiff.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                    85% ████████▌
 Tests/test_file_gribstub.py ✓✓✓✓✓                                                                   64% ██████▍
 Tests/test_file_libtiff.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                           86% ████████▋
 Tests/test_imagechops.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                             67% ██████▋
 Tests/test_file_libtiff.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                    86% ████████▋
                            ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                86% ████████▋
                            ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                               86% ████████▋
 Tests/test_imagedraw.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 68% ██████▉
                            ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                      87% ████████▊
                            ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓         88% ████████▊
                            ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓        88% ████████▊
 Tests/test_imagedraw.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓x✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                            74% ███████▌
 Tests/test_imagedraw2.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                           75% ███████▌
 Tests/test_file_ico.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                       75% ███████▋
 Tests/test_imageenhance.py ✓✓✓✓✓✓                                                                   74% ███████▍
 Tests/test_file_libtiff.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 90% █████████
 Tests/test_file_im.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                               76% ███████▋
 Tests/test_file_imt.py ✓✓✓✓                                                                         76% ███████▋
 Tests/test_file_iptc.py ✓✓✓✓✓✓✓✓✓✓                                                                  77% ███████▋
 Tests/test_imagefont.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 78% ███████▉
                         ✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                            80% ████████
 Tests/test_imagefontctl.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓s✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 81% ████████▎
 Tests/test_font_pcf.py ✓✓✓✓✓✓                                                                       81% ████████▏
 Tests/test_imagemath_lambda_eval.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                         82% ████████▎
 Tests/test_font_pcf_charsets.py ✓✓✓✓✓✓✓✓✓                                                           85% ████████▋
 Tests/test_imagefontctl.py ✓✓✓✓✓✓✓✓                                                                 82% ████████▎
                         ✓✓✓✓✓✓✓✓✓✓✓s✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                 94% █████████▍
 Tests/test_imagefontpil.py ✓✓✓✓✓✓                                                                   85% ████████▌
 Tests/test_imagemath_unsafe_eval.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                   82% ████████▎
 Tests/test_file_webp.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                     94% █████████▌
 Tests/test_imageops.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                          84% ████████▌
 Tests/test_file_png.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                              95% █████████▌
 Tests/test_image.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓      96% █████████▋
 Tests/test_image.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 96% █████████▋
 Tests/test_imageqt.py ssssssss                                                                      85% ████████▌
 Tests/test_imagesequence.py ✓✓✓✓✓✓✓✓                                                                86% ████████▋
 Tests/test_imageshow.py ssss✓✓✓✓✓✓✓s✓✓✓✓✓✓✓✓✓s                                                      86% ████████▋
 Tests/test_imagestat.py ✓✓✓                                                                         85% ████████▌
 Tests/test_file_png.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                98% █████████▊
 Tests/test_format_hsv.py ✓✓✓✓                                                                       86% ████████▋
 Tests/test_file_palm.py ✓✓✓✓                                                                        99% █████████▉
 Tests/test_imagewin.py ssss✓✓✓ss                                                                    90% █████████
 Tests/test_lib_image.py ✓                                                                           86% ████████▋
 Tests/test_lib_pack.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                       87% ████████▊
 Tests/test_locale.py s                                                                              87% ████████▊
 Tests/test_file_tar.py ✓✓✓✓✓✓✓                                                                     100% ██████████
 Tests/test_mode_i16.py ✓✓✓✓✓✓✓                                                                      91% █████████▏
 Tests/test_numpy.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                           89% ████████▉
 Tests/test_imagetk.py ✓✓✓✓✓✓✓✓✓✓✓✓✓                                                                 90% █████████
 Tests/test_pdfparser.py ✓✓✓✓✓                                                                       89% ████████▉
 Tests/test_pickle.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓ 92% █████████▎
 Tests/test_file_libtiff.py s✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                              96% █████████▋
 Tests/test_map.py ✓✓✓                                                                               91% █████████▏
 Tests/test_pickle.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                               92% █████████▎
 Tests/test_psdraw.py ✓✓                                                                             92% █████████▎
 Tests/test_qt_image_toqimage.py sssss                                                               92% █████████▎
 Tests/test_sgi_crash.py ✓✓✓✓✓✓✓✓✓✓✓                                                                 92% █████████▎
 Tests/test_shell_injection.py ✓✓✓✓                                                                  94% █████████▌
 Tests/test_tiff_crashes.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                          94% █████████▌
 Tests/test_imagefile.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                 94% █████████▍
 Tests/test_tiff_ifdrational.py ✓✓✓✓✓                                                                93% █████████▍
 Tests/test_util.py ✓✓✓✓✓                                                                            94% █████████▍
 Tests/test_webp_leaks.py ✓                                                                          94% █████████▍
 Tests/test_pyroma.py ✓                                                                              94% █████████▍
 Tests/test_qt_image_qapplication.py s                                                               94% █████████▍
 Tests/test_file_webp_alpha.py ✓✓✓✓✓✓                                                                94% █████████▌
 Tests/test_file_webp_animated.py ✓✓✓✓✓✓✓✓                                                           95% █████████▌
 Tests/test_file_webp_lossless.py ✓                                                                  95% █████████▌
 Tests/test_file_libtiff_small.py ✓✓✓                                                                96% █████████▋
 Tests/test_file_mcidas.py ✓✓                                                                        96% █████████▋
 Tests/test_image.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                            97% █████████▊
 Tests/test_file_mic.py ✓✓✓✓✓✓✓                                                                      97% █████████▋
 Tests/test_file_mpeg.py ✓✓✓                                                                         97% █████████▋
 Tests/test_file_mpo.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                             98% █████████▊
 Tests/test_file_ppm.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                               99% █████████▉
 Tests/test_file_msp.py ✓✓✓✓✓✓✓                                                                      98% █████████▉
 Tests/test_file_psd.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                         99% █████████▉
 Tests/test_file_qoi.py ✓✓                                                                           99% █████████▉
 Tests/test_file_sgi.py ✓✓✓✓✓✓✓✓✓✓✓✓✓                                                                99% █████████▉
 Tests/test_file_spider.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                                          99% ██████████
 Tests/test_file_sun.py ✓✓✓✓✓✓✓✓                                                                     99% ██████████

@wiredfool
Copy link
Member Author

wiredfool commented May 23, 2025

I think the format change is the -qq in the make test that isn't the same as the standard tests we're running in CI. The output is (mostly, barring some threading issues) the same between make test and make test-p.

One interesting thing -- if we do this, we're going to be running parallel tests on freethread python, which would definitely be a good thing.

Edit -- looks like #8492 is actually referring to pytest-run-parallel, which is threads.

@wiredfool
Copy link
Member Author

wiredfool commented May 23, 2025

The only thing that we'd have to be careful of is the valgrind tests can only run in one process thread. Something is off between pytest-valgrind and pytest-xdist that doesn't play nicely with the multiple runners, even when valgrind is tracing subprocesses.

@hugovk
Copy link
Member

hugovk commented May 23, 2025

The formatting change also happens when running plain pytest, so it's not only -qq in the Makefile.

@wiredfool
Copy link
Member Author

I don't care that much about what the format is, other than I want fast tests when I'm iterating. Shorter CI logs aren't a bad thing, but there's a lot less context when you're tailing them.

@@ -95,7 +95,13 @@ sdist:
.PHONY: test
test:
python3 -c "import pytest" > /dev/null 2>&1 || python3 -m pip install pytest
python3 -m pytest -qq
python3 -m pytest -qq Tests/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

@@ -70,6 +70,7 @@ optional-dependencies.tests = [
"pytest",
"pytest-cov",
"pytest-timeout",
"pytest-xdist",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the Makefile is going to install pytest-xdist by itself, and we're not using it anywhere else, I don't think this needs to be in pyproject.toml?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants