Skip to content

Commit 7fc8829

Browse files
authored
Merge pull request #8695 from chrisburr/fix/python-3.14-test-compat
[9.1] test: Python 3.14 and matplotlib 3.11 compatibility in test suite
2 parents f22c4cb + 8541fdb commit 7fc8829

9 files changed

Lines changed: 47 additions & 11 deletions

File tree

src/DIRAC/tests/Utilities/plots.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# pylint: disable=protected-access
2+
import glob
23
import math
34
import operator
5+
import os
46
from functools import reduce
57

68
from PIL import Image
@@ -24,3 +26,37 @@ def compare(file1Path, file2Path):
2426
h2 = image2.histogram()
2527
rms = math.sqrt(reduce(operator.add, map(lambda a, b: (a - b) ** 2, h1, h2)) / len(h1))
2628
return rms
29+
30+
31+
def referenceImages(directory, stem):
32+
"""Return every reference image available for a given plot.
33+
34+
The primary reference is ``<stem>.png``. Additional references may be added
35+
as ``<stem>.<tag>.png`` (for example ``histogram1.mpl-3.10.png``) when a new
36+
matplotlib version renders a plot slightly differently. Keeping several
37+
references side by side means a plot is accepted against any supported
38+
plotting-stack version, so an upgrade only needs an extra reference image
39+
rather than replacing the existing one (which would break older versions).
40+
41+
:param str directory: Directory holding the reference images.
42+
:param str stem: Base name of the plot, without extension.
43+
:return: Sorted list of reference image paths.
44+
"""
45+
paths = glob.glob(os.path.join(directory, f"{stem}.png"))
46+
paths += glob.glob(os.path.join(directory, f"{stem}.*.png"))
47+
return sorted(paths)
48+
49+
50+
def compareToReferences(generatedPath, referencePaths):
51+
"""Compare a generated plot against several candidate reference images.
52+
53+
:param str generatedPath: Path to the freshly generated plot.
54+
:param referencePaths: Iterable of reference image paths to compare against.
55+
56+
:return: The smallest RMS obtained against any of the references, so a plot
57+
is accepted as soon as it is identical (rms == 0.0) to one of them.
58+
"""
59+
referencePaths = list(referencePaths)
60+
if not referencePaths:
61+
raise ValueError(f"No reference images provided for {generatedPath}")
62+
return min(compare(generatedPath, reference) for reference in referencePaths)

tests/Integration/AccountingSystem/Test_Plots.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
generateNoDataPlot,
1212
generatePiePlot,
1313
)
14-
from DIRAC.tests.Utilities.plots import compare
14+
from DIRAC.tests.Utilities.plots import compareToReferences, referenceImages
1515

1616
plots_directory = os.path.join(os.path.dirname(__file__), "plots")
1717
filename = "plot.png"
@@ -25,21 +25,21 @@ def test_histogram():
2525
res = generateHistogram(filename, [2, 2, 3, 4, 5, 5], {})
2626
assert res["OK"] is True
2727

28-
res = compare(filename, os.path.join(plots_directory, "histogram1.png"))
28+
res = compareToReferences(filename, referenceImages(plots_directory, "histogram1"))
2929
assert res == 0.0
3030

3131
res = generateHistogram(
3232
filename, [{"a": [1, 2, 3, 1, 2, 2, 4, 2]}, {"b": [2, 2, 2, 4, 4, 1, 1]}], {"plot_grid": "2:1"}
3333
)
3434
assert res["OK"] is True
3535

36-
res = compare(filename, os.path.join(plots_directory, "histogram2.png"))
36+
res = compareToReferences(filename, referenceImages(plots_directory, "histogram2"))
3737
assert res == 0.0
3838

3939
res = generateHistogram(filename, [{"a": [1]}, {"b": [2, 3, 3, 5, 5]}], {})
4040
assert res["OK"] is True
4141

42-
res = compare(filename, os.path.join(plots_directory, "histogram3.png"))
42+
res = compareToReferences(filename, referenceImages(plots_directory, "histogram3"))
4343
assert res == 0.0
4444

4545

@@ -50,7 +50,7 @@ def test_piechartplot():
5050
res = generatePiePlot(filename, {"a": 16.0, "b": 56.0, "c": 15, "d": 20}, {})
5151
assert res["OK"] is True
5252

53-
res = compare(filename, os.path.join(plots_directory, "piechart.png"))
53+
res = compareToReferences(filename, referenceImages(plots_directory, "piechart"))
5454
assert res == 0.0
5555

5656

@@ -61,7 +61,7 @@ def test_nodataplot():
6161

6262
res = generateNoDataPlot(filename, {}, {"title": "Test plot"})
6363
assert res["OK"] is True
64-
res = compare(filename, os.path.join(plots_directory, "nodata.png"))
64+
res = compareToReferences(filename, referenceImages(plots_directory, "nodata"))
6565
assert res == 0.0
6666

6767

@@ -74,5 +74,5 @@ def test_error():
7474
with open(filename, "wb") as out:
7575
out.write(res)
7676

77-
res = compare(filename, os.path.join(plots_directory, "error.png"))
77+
res = compareToReferences(filename, referenceImages(plots_directory, "error"))
7878
assert res == 0.0
4.76 KB
Loading
24.9 KB
Loading
31.9 KB
Loading
25.7 KB
Loading
5.24 KB
Loading
38 KB
Loading

tests/Integration/DataManagementSystem/Test_UserMetadata.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ def test_metaIndex(self):
110110
# meta show
111111
result = self.fc.getMetadataFields()
112112
self.assertTrue(result["OK"])
113-
self.assertDictContainsSubset({"MetaInt6": "INT"}, result["Value"]["FileMetaFields"])
114-
self.assertDictContainsSubset({"TestDirectory6": "INT"}, result["Value"]["DirectoryMetaFields"])
113+
self.assertLessEqual({"MetaInt6": "INT"}.items(), result["Value"]["FileMetaFields"].items())
114+
self.assertLessEqual({"TestDirectory6": "INT"}.items(), result["Value"]["DirectoryMetaFields"].items())
115115

116116
# meta set
117117
metaDict6 = {"MetaInt6": 13}
@@ -135,15 +135,15 @@ def test_metaIndex(self):
135135
# API call only
136136
result = self.fc.getFileUserMetadata(self.lfn5)
137137
self.assertTrue(result["OK"])
138-
self.assertDictContainsSubset({"MetaInt6": 13}, result["Value"])
138+
self.assertLessEqual({"MetaInt6": 13}.items(), result["Value"].items())
139139
# file: expect a failure
140140
result = self.fc.getDirectoryUserMetadata(self.lfn5)
141141
self.assertFalse(result["OK"])
142142

143143
# directory
144144
result = self.fc.getDirectoryUserMetadata(self.dir5)
145145
self.assertTrue(result["OK"])
146-
self.assertDictContainsSubset({"TestDirectory6": 126}, result["Value"])
146+
self.assertLessEqual({"TestDirectory6": 126}.items(), result["Value"].items())
147147

148148
# finally remove
149149
# meta remove lfn5 MetaInt6

0 commit comments

Comments
 (0)