4343
4444import pytest
4545
46- from .kernels import (DEFAULT_HAMMING_TOLERANCE , DEFAULT_HASH_SIZE ,
47- DEFAULT_HIGH_FREQUENCY_FACTOR , KERNEL_SHA256 , kernel_factory )
46+ from .kernels import KERNEL_SHA256 , kernel_factory
4847from .summary .html import generate_summary_basic_html , generate_summary_html
4948
5049#: The default matplotlib backend.
6564#: The default matplotlib plot style.
6665DEFAULT_STYLE = "classic"
6766
68- #: Metadata entry in the JSON hash library defining the source kernel of the hashes.
69- META_HASH_LIBRARY_KERNEL = 'pytest-mpl-kernel'
67+ #: JSON metadata entry defining the source kernel of the hashes.
68+ META_HASH_KERNEL = 'pytest-mpl-kernel'
7069
7170#: Valid formats for generate summary.
7271SUPPORTED_FORMATS = {'html' , 'json' , 'basic-html' }
@@ -326,20 +325,18 @@ def __init__(self,
326325
327326 # Configure hashing kernel options.
328327 option = 'mpl-hash-size'
329- hash_size = int (config .getoption (f'--{ option } ' ) or
330- config .getini (option ) or DEFAULT_HASH_SIZE )
328+ hash_size = (config .getoption (f'--{ option } ' ) or
329+ config .getini (option ) or None )
331330 self .hash_size = hash_size
332331
333332 option = 'mpl-hamming-tolerance'
334- hamming_tolerance = int (config .getoption (f'--{ option } ' ) or
335- config .getini (option ) or
336- DEFAULT_HAMMING_TOLERANCE )
333+ hamming_tolerance = (config .getoption (f'--{ option } ' ) or
334+ config .getini (option ) or None )
337335 self .hamming_tolerance = hamming_tolerance
338336
339337 option = 'mpl-high-freq-factor'
340- high_freq_factor = int (config .getoption (f'--{ option } ' ) or
341- config .getini (option ) or
342- DEFAULT_HIGH_FREQUENCY_FACTOR )
338+ high_freq_factor = (config .getoption (f'--{ option } ' ) or
339+ config .getini (option ) or None )
343340 self .high_freq_factor = high_freq_factor
344341
345342 # Configure the hashing kernel - must be done *after* kernel options.
@@ -351,12 +348,8 @@ def __init__(self,
351348 emsg = f'Unrecognised hashing kernel { kernel !r} not supported.'
352349 raise ValueError (emsg )
353350 kernel = requested
354- # Flag that the kernel has been user configured.
355- self .kernel_default = False
356351 else :
357352 kernel = DEFAULT_KERNEL
358- # Flag that the kernel has been configured by default.
359- self .kernel_default = True
360353 # Create the kernel.
361354 self .kernel = kernel_factory [kernel ](self )
362355
@@ -600,9 +593,63 @@ def compare_image_to_baseline(self, item, fig, result_dir, summary=None):
600593 summary ['status_msg' ] = error_message
601594 return error_message
602595
603- def load_hash_library (self , library_path ):
604- with open (str (library_path )) as fp :
605- return json .load (fp )
596+ def load_hash_library (self , fname ):
597+ with open (str (fname )) as fi :
598+ hash_library = json .load (fi )
599+ kernel_metadata = hash_library .get (META_HASH_KERNEL )
600+ if kernel_metadata is None :
601+ msg = (f'Hash library { str (fname )!r} missing a '
602+ f'{ META_HASH_KERNEL !r} entry. Assuming that a '
603+ f'{ self .kernel .name !r} kernel generated the library.' )
604+ self .logger .info (msg )
605+ else :
606+ if "name" not in kernel_metadata :
607+ emsg = (f"Missing kernel 'name' in the { META_HASH_KERNEL !r} entry, "
608+ f'for the hash library { str (fname )!r} .' )
609+ pytest .fail (emsg )
610+ kernel_name = kernel_metadata ["name" ]
611+ if kernel_name not in kernel_factory :
612+ emsg = (f'Unrecognised hashing kernel { kernel_name !r} specified '
613+ f'in the hash library { str (fname )!r} .' )
614+ pytest .fail (emsg )
615+ if kernel_name != self .kernel .name :
616+ option = 'mpl-kernel'
617+ if (self .config .getoption (f'--{ option } ' ) is None and
618+ len (self .config .getini (option )) == 0 ):
619+ # Override the default kernel with the kernel configured
620+ # within the hash library.
621+ self .kernel = kernel_factory [kernel_name ](self )
622+ else :
623+ emsg = (f'Hash library { str (fname )!r} kernel '
624+ f'{ kernel_name !r} does not match configured runtime '
625+ f'kernel { self .kernel .name !r} .' )
626+ pytest .fail (emsg )
627+
628+ def check_metadata (key ):
629+ if key not in kernel_metadata :
630+ emsg = (f'Missing kernel { key !r} in the '
631+ f'{ META_HASH_KERNEL !r} entry, for the hash '
632+ f'library { str (fname )!r} .' )
633+ pytest .fail (emsg )
634+ value = kernel_metadata [key ]
635+ if value != getattr (self .kernel , key ):
636+ option = f'mpl-{ key .replace ("_" , "-" )} '
637+ if (self .config .getoption (f'--{ option } ' ) is None and
638+ len (self .config .getini (option )) == 0 ):
639+ # Override the default kernel value with the
640+ # configured value within the hash library.
641+ setattr (self .kernel , key , value )
642+ else :
643+ emsg = (f"Hash library { str (fname )!r} '{ key } ={ value } ' "
644+ 'does not match configured runtime kernel '
645+ f"'{ key } ={ getattr (self .kernel , key )} '." )
646+ pytest .fail (emsg )
647+
648+ for key in self .kernel .metadata :
649+ if key != "name" :
650+ check_metadata (key )
651+
652+ return hash_library
606653
607654 def compare_image_to_hash_library (self , item , fig , result_dir , summary = None ):
608655 hash_comparison_pass = False
@@ -623,27 +670,6 @@ def compare_image_to_hash_library(self, item, fig, result_dir, summary=None):
623670 pytest .fail (f"Can't find hash library at path { str (hash_library_filename )!r} ." )
624671
625672 hash_library = self .load_hash_library (hash_library_filename )
626- kernel_name = hash_library .get (META_HASH_LIBRARY_KERNEL )
627- if kernel_name is None :
628- msg = (f'Hash library { str (hash_library_filename )!r} missing a '
629- f'{ META_HASH_LIBRARY_KERNEL !r} entry. Assuming that a '
630- f'{ self .kernel .name !r} kernel generated the library.' )
631- self .logger .info (msg )
632- else :
633- if kernel_name not in kernel_factory :
634- emsg = (f'Unrecognised hashing kernel { kernel_name !r} specified '
635- f'in the hash library { str (hash_library_filename )!r} .' )
636- pytest .fail (emsg )
637- if kernel_name != self .kernel .name :
638- if self .kernel_default :
639- # Override the default kernel with the kernel configured
640- # within the hash library.
641- self .kernel = kernel_factory [kernel_name ](self )
642- else :
643- emsg = (f'Hash library { str (hash_library_filename )!r} kernel '
644- f'{ kernel_name !r} does not match configured runtime '
645- f'kernel { self .kernel .name !r} .' )
646- pytest .fail (emsg )
647673
648674 hash_name = self .generate_test_name (item )
649675 baseline_hash = hash_library .get (hash_name , None )
@@ -838,7 +864,7 @@ def pytest_unconfigure(self, config):
838864 # It's safe to inject this metadata, as the key is an invalid Python
839865 # class/function/method name, therefore there's no possible
840866 # namespace conflict with user py.test marker decorated tokens.
841- self ._generated_hash_library [META_HASH_LIBRARY_KERNEL ] = self .kernel .name
867+ self ._generated_hash_library [META_HASH_KERNEL ] = self .kernel .metadata
842868 with open (hash_library_path , "w" ) as fp :
843869 json .dump (self ._generated_hash_library , fp , indent = 2 )
844870 if self .results_always : # Make accessible in results directory
@@ -849,7 +875,7 @@ def pytest_unconfigure(self, config):
849875 result_hashes = {k : v ['result_hash' ] for k , v in self ._test_results .items ()
850876 if v ['result_hash' ]}
851877 if len (result_hashes ) > 0 : # At least one hash comparison test
852- result_hashes [META_HASH_LIBRARY_KERNEL ] = self .kernel .name
878+ result_hashes [META_HASH_KERNEL ] = self .kernel .metadata
853879 with open (result_hash_library , "w" ) as fp :
854880 json .dump (result_hashes , fp , indent = 2 )
855881
0 commit comments