Skip to content

Commit

Permalink
Started implementing support for determinstic figure output
Browse files Browse the repository at this point in the history
  • Loading branch information
astrofrog committed Apr 1, 2023
1 parent df3a8fe commit 95d4b9d
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 29 deletions.
48 changes: 37 additions & 11 deletions pytest_mpl/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import contextlib
from pathlib import Path
from urllib.request import urlopen
from contextlib import nullcontext

import pytest

Expand Down Expand Up @@ -432,15 +433,13 @@ def generate_baseline_image(self, item, fig):
Generate reference figures.
"""
compare = get_compare(item)
savefig_kwargs = compare.kwargs.get('savefig_kwargs', {})

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

baseline_filename = self.generate_filename(item)
baseline_path = (self.generate_dir / baseline_filename).absolute()
fig.savefig(str(baseline_path), **savefig_kwargs)

self.save_figure(item, fig, baseline_path)
close_mpl_figure(fig)

return baseline_path
Expand All @@ -450,13 +449,9 @@ def generate_image_hash(self, item, fig):
For a `matplotlib.figure.Figure`, returns the SHA256 hash as a hexadecimal
string.
"""
compare = get_compare(item)
savefig_kwargs = compare.kwargs.get('savefig_kwargs', {})

ext = self._file_extension(item)

imgdata = io.BytesIO()
fig.savefig(imgdata, **savefig_kwargs)
self.save_figure(item, fig, imgdata)
out = _hash_file(imgdata)
imgdata.close()

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

ext = self._file_extension(item)

baseline_image_ref = self.obtain_baseline_image(item, result_dir)

test_image = (result_dir / f"result.{ext}").absolute()
fig.savefig(str(test_image), **savefig_kwargs)
self.save_figure(item, fig, test_image)

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

def save_figure(self, item, fig, filename):
if isinstance(filename, Path):
filename = str(filename)
compare = get_compare(item)
savefig_kwargs = compare.kwargs.get('savefig_kwargs', {})
deterministic = compare.kwargs.get('deterministic', False)

if deterministic:

# Make sure we don't modify the original dictionary in case is a common
# object used by different tests
savefig_kwargs = savefig_kwargs.copy()

if 'metadata' not in savefig_kwargs:
savefig_kwargs['metadata'] = {}

ext = self._file_extension(item)

if ext == 'png':
extra_metadata = {"Software": None}
elif ext == 'pdf':
extra_metadata = {"Creator": None, "Producer": None, "CreationDate": None}
elif ext == 'eps':
extra_metadata = {"Creator": "test"}
elif ext == 'svg':
extra_metadata = {"Date": None}

savefig_kwargs['metadata'].update(extra_metadata)

fig.savefig(filename, **savefig_kwargs)

def compare_image_to_hash_library(self, item, fig, result_dir, summary=None):
hash_comparison_pass = False
if summary is None:
summary = {}

compare = get_compare(item)
savefig_kwargs = compare.kwargs.get('savefig_kwargs', {})

ext = self._file_extension(item)

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

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

# Hybrid mode (hash and image comparison)
Expand Down
20 changes: 2 additions & 18 deletions tests/test_pytest_mpl.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,15 +704,6 @@ def test_formats(pytester, use_hash_library, passes, file_format):
else:
pytest.skip('Comparing EPS and PDF files requires ghostscript to be installed')

if file_format == 'png':
metadata = '{"Software": None}'
elif file_format == 'pdf':
metadata = '{"Creator": None, "Producer": None, "CreationDate": None}'
elif file_format == 'eps':
metadata = '{"Creator": "test"}'
elif file_format == 'svg':
metadata = '{"Date": None}'

pytester.makepyfile(
f"""
import os
Expand All @@ -721,16 +712,9 @@ def test_formats(pytester, use_hash_library, passes, file_format):
@pytest.mark.mpl_image_compare(baseline_dir=r"{baseline_dir_abs}",
{f'hash_library=r"{hash_library}",' if use_hash_library else ''}
tolerance={DEFAULT_TOLERANCE},
savefig_kwargs={{'format': '{file_format}',
'metadata': {metadata}}})
deterministic=True,
savefig_kwargs={{'format': '{file_format}'}})
def test_format_{file_format}():
# For reproducible EPS output
os.environ['SOURCE_DATE_EPOCH'] = '1680254601'
# For reproducible SVG output
plt.rcParams['svg.hashsalt'] = 'test'
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot([{1 if passes else 3}, 2, 3])
Expand Down

0 comments on commit 95d4b9d

Please sign in to comment.