Skip to content

Commit 95d4b9d

Browse files
committed
Started implementing support for determinstic figure output
1 parent df3a8fe commit 95d4b9d

File tree

2 files changed

+39
-29
lines changed

2 files changed

+39
-29
lines changed

Diff for: pytest_mpl/plugin.py

+37-11
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import contextlib
4040
from pathlib import Path
4141
from urllib.request import urlopen
42+
from contextlib import nullcontext
4243

4344
import pytest
4445

@@ -432,15 +433,13 @@ def generate_baseline_image(self, item, fig):
432433
Generate reference figures.
433434
"""
434435
compare = get_compare(item)
435-
savefig_kwargs = compare.kwargs.get('savefig_kwargs', {})
436436

437437
if not os.path.exists(self.generate_dir):
438438
os.makedirs(self.generate_dir)
439439

440440
baseline_filename = self.generate_filename(item)
441441
baseline_path = (self.generate_dir / baseline_filename).absolute()
442-
fig.savefig(str(baseline_path), **savefig_kwargs)
443-
442+
self.save_figure(item, fig, baseline_path)
444443
close_mpl_figure(fig)
445444

446445
return baseline_path
@@ -450,13 +449,9 @@ def generate_image_hash(self, item, fig):
450449
For a `matplotlib.figure.Figure`, returns the SHA256 hash as a hexadecimal
451450
string.
452451
"""
453-
compare = get_compare(item)
454-
savefig_kwargs = compare.kwargs.get('savefig_kwargs', {})
455-
456-
ext = self._file_extension(item)
457452

458453
imgdata = io.BytesIO()
459-
fig.savefig(imgdata, **savefig_kwargs)
454+
self.save_figure(item, fig, imgdata)
460455
out = _hash_file(imgdata)
461456
imgdata.close()
462457

@@ -476,13 +471,14 @@ def compare_image_to_baseline(self, item, fig, result_dir, summary=None):
476471
compare = get_compare(item)
477472
tolerance = compare.kwargs.get('tolerance', 2)
478473
savefig_kwargs = compare.kwargs.get('savefig_kwargs', {})
474+
deterministic = compare.kwargs.get('deterministic', False)
479475

480476
ext = self._file_extension(item)
481477

482478
baseline_image_ref = self.obtain_baseline_image(item, result_dir)
483479

484480
test_image = (result_dir / f"result.{ext}").absolute()
485-
fig.savefig(str(test_image), **savefig_kwargs)
481+
self.save_figure(item, fig, test_image)
486482

487483
if ext in ['png', 'svg']: # Use original file
488484
summary['result_image'] = test_image.relative_to(self.results_dir).as_posix()
@@ -554,13 +550,43 @@ def load_hash_library(self, library_path):
554550
with open(str(library_path)) as fp:
555551
return json.load(fp)
556552

553+
def save_figure(self, item, fig, filename):
554+
if isinstance(filename, Path):
555+
filename = str(filename)
556+
compare = get_compare(item)
557+
savefig_kwargs = compare.kwargs.get('savefig_kwargs', {})
558+
deterministic = compare.kwargs.get('deterministic', False)
559+
560+
if deterministic:
561+
562+
# Make sure we don't modify the original dictionary in case is a common
563+
# object used by different tests
564+
savefig_kwargs = savefig_kwargs.copy()
565+
566+
if 'metadata' not in savefig_kwargs:
567+
savefig_kwargs['metadata'] = {}
568+
569+
ext = self._file_extension(item)
570+
571+
if ext == 'png':
572+
extra_metadata = {"Software": None}
573+
elif ext == 'pdf':
574+
extra_metadata = {"Creator": None, "Producer": None, "CreationDate": None}
575+
elif ext == 'eps':
576+
extra_metadata = {"Creator": "test"}
577+
elif ext == 'svg':
578+
extra_metadata = {"Date": None}
579+
580+
savefig_kwargs['metadata'].update(extra_metadata)
581+
582+
fig.savefig(filename, **savefig_kwargs)
583+
557584
def compare_image_to_hash_library(self, item, fig, result_dir, summary=None):
558585
hash_comparison_pass = False
559586
if summary is None:
560587
summary = {}
561588

562589
compare = get_compare(item)
563-
savefig_kwargs = compare.kwargs.get('savefig_kwargs', {})
564590

565591
ext = self._file_extension(item)
566592

@@ -601,7 +627,7 @@ def compare_image_to_hash_library(self, item, fig, result_dir, summary=None):
601627

602628
# Save the figure for later summary (will be removed later if not needed)
603629
test_image = (result_dir / f"result.{ext}").absolute()
604-
fig.savefig(str(test_image), **savefig_kwargs)
630+
self.save_figure(item, fig, test_image)
605631
summary['result_image'] = test_image.relative_to(self.results_dir).as_posix()
606632

607633
# Hybrid mode (hash and image comparison)

Diff for: tests/test_pytest_mpl.py

+2-18
Original file line numberDiff line numberDiff line change
@@ -704,15 +704,6 @@ def test_formats(pytester, use_hash_library, passes, file_format):
704704
else:
705705
pytest.skip('Comparing EPS and PDF files requires ghostscript to be installed')
706706

707-
if file_format == 'png':
708-
metadata = '{"Software": None}'
709-
elif file_format == 'pdf':
710-
metadata = '{"Creator": None, "Producer": None, "CreationDate": None}'
711-
elif file_format == 'eps':
712-
metadata = '{"Creator": "test"}'
713-
elif file_format == 'svg':
714-
metadata = '{"Date": None}'
715-
716707
pytester.makepyfile(
717708
f"""
718709
import os
@@ -721,16 +712,9 @@ def test_formats(pytester, use_hash_library, passes, file_format):
721712
@pytest.mark.mpl_image_compare(baseline_dir=r"{baseline_dir_abs}",
722713
{f'hash_library=r"{hash_library}",' if use_hash_library else ''}
723714
tolerance={DEFAULT_TOLERANCE},
724-
savefig_kwargs={{'format': '{file_format}',
725-
'metadata': {metadata}}})
715+
deterministic=True,
716+
savefig_kwargs={{'format': '{file_format}'}})
726717
def test_format_{file_format}():
727-
728-
# For reproducible EPS output
729-
os.environ['SOURCE_DATE_EPOCH'] = '1680254601'
730-
731-
# For reproducible SVG output
732-
plt.rcParams['svg.hashsalt'] = 'test'
733-
734718
fig = plt.figure()
735719
ax = fig.add_subplot(1, 1, 1)
736720
ax.plot([{1 if passes else 3}, 2, 3])

0 commit comments

Comments
 (0)