Skip to content

Commit c2186d6

Browse files
committed
inject source kernel to hash lib + checks
1 parent 35789fd commit c2186d6

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

pytest_mpl/kernels.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ def update_summary(self, summary):
193193

194194
class KernelSHA256(Kernel):
195195
"""
196-
A simple kernel that calculates a 256-bit SHA hash of an image.
196+
A simple kernel that calculates a 256-bit cryptographic SHA hash
197+
of an image.
197198
198199
"""
199200

pytest_mpl/plugin.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@
6565
#: The default matplotlib plot style.
6666
DEFAULT_STYLE = "classic"
6767

68+
#: Metadata entry in the JSON hash library defining the source kernel of the hashes.
69+
META_HASH_LIBRARY_KERNEL = 'pytest-mpl-kernel'
70+
6871
#: Valid formats for generate summary.
6972
SUPPORTED_FORMATS = {'html', 'json', 'basic-html'}
7073

@@ -615,9 +618,28 @@ def compare_image_to_hash_library(self, item, fig, result_dir, summary=None):
615618
hash_library_filename = (Path(item.fspath).parent / hash_library_filename).absolute()
616619

617620
if not Path(hash_library_filename).exists():
618-
pytest.fail(f"Can't find hash library at path {hash_library_filename}")
621+
pytest.fail(f"Can't find hash library at path {str(hash_library_filename)!r}.")
619622

620623
hash_library = self.load_hash_library(hash_library_filename)
624+
kernel_name = hash_library.get(META_HASH_LIBRARY_KERNEL)
625+
if kernel_name is None:
626+
msg = (f'Hash library {str(hash_library_filename)!r} missing a '
627+
f'{META_HASH_LIBRARY_KERNEL!r} entry. Assuming that a '
628+
f'{self.kernel.name!r} kernel generated the library.')
629+
self.logger.info(msg)
630+
else:
631+
if kernel_name not in kernel_factory:
632+
emsg = (f'Unrecognised hashing kernel {kernel_name!r} specified '
633+
f'in the hash library {str(hash_library_filename)!r}.')
634+
pytest.fail(emsg)
635+
if kernel_name != self.kernel.name:
636+
# TODO: we could be lenient here by raising a warning and hot-swap to
637+
# use the hash library kernel, instead of forcing a test failure?
638+
emsg = (f'Hash library {str(hash_library_filename)!r} kernel '
639+
f'{kernel_name!r} does not match configured runtime '
640+
f'kernel {self.kernel.name!r}.')
641+
pytest.fail(emsg)
642+
621643
hash_name = self.generate_test_name(item)
622644
baseline_hash = hash_library.get(hash_name, None)
623645
summary['baseline_hash'] = baseline_hash
@@ -630,7 +652,7 @@ def compare_image_to_hash_library(self, item, fig, result_dir, summary=None):
630652
summary['status'] = 'failed'
631653
summary['hash_status'] = 'missing'
632654
msg = (f'Hash for test {hash_name!r} not found in '
633-
f'{hash_library_filename!r}. Generated hash is '
655+
f'{str(hash_library_filename)!r}. Generated hash is '
634656
f'{result_hash!r}.')
635657
summary['status_msg'] = msg
636658
elif self.kernel.equivalent_hash(result_hash, baseline_hash): # hash-match
@@ -759,6 +781,7 @@ def item_function_wrapper(*args, **kwargs):
759781
image_hash = self.generate_image_hash(item, fig)
760782
self._generated_hash_library[test_name] = image_hash
761783
summary['baseline_hash'] = image_hash
784+
summary['kernel'] = self.kernel.name
762785

763786
# Only test figures if not generating images
764787
if self.generate_dir is None:
@@ -807,6 +830,10 @@ def pytest_unconfigure(self, config):
807830
if self.generate_hash_library is not None:
808831
hash_library_path = Path(config.rootdir) / self.generate_hash_library
809832
hash_library_path.parent.mkdir(parents=True, exist_ok=True)
833+
# It's safe to inject this metadata, as the key is an invalid Python
834+
# class/function/method name, therefore there's no possible
835+
# namespace conflict with user py.test marker decorated tokens.
836+
self._generated_hash_library[META_HASH_LIBRARY_KERNEL] = self.kernel.name
810837
with open(hash_library_path, "w") as fp:
811838
json.dump(self._generated_hash_library, fp, indent=2)
812839
if self.results_always: # Make accessible in results directory
@@ -817,6 +844,7 @@ def pytest_unconfigure(self, config):
817844
result_hashes = {k: v['result_hash'] for k, v in self._test_results.items()
818845
if v['result_hash']}
819846
if len(result_hashes) > 0: # At least one hash comparison test
847+
result_hashes[META_HASH_LIBRARY_KERNEL] = self.kernel.name
820848
with open(result_hash_library, "w") as fp:
821849
json.dump(result_hashes, fp, indent=2)
822850

0 commit comments

Comments
 (0)