6565#: The default matplotlib plot style.
6666DEFAULT_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.
6972SUPPORTED_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