43
43
44
44
import pytest
45
45
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
48
47
from .summary .html import generate_summary_basic_html , generate_summary_html
49
48
50
49
#: The default matplotlib backend.
65
64
#: The default matplotlib plot style.
66
65
DEFAULT_STYLE = "classic"
67
66
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'
70
69
71
70
#: Valid formats for generate summary.
72
71
SUPPORTED_FORMATS = {'html' , 'json' , 'basic-html' }
@@ -326,20 +325,18 @@ def __init__(self,
326
325
327
326
# Configure hashing kernel options.
328
327
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 )
331
330
self .hash_size = hash_size
332
331
333
332
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 )
337
335
self .hamming_tolerance = hamming_tolerance
338
336
339
337
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 )
343
340
self .high_freq_factor = high_freq_factor
344
341
345
342
# Configure the hashing kernel - must be done *after* kernel options.
@@ -351,12 +348,8 @@ def __init__(self,
351
348
emsg = f'Unrecognised hashing kernel { kernel !r} not supported.'
352
349
raise ValueError (emsg )
353
350
kernel = requested
354
- # Flag that the kernel has been user configured.
355
- self .kernel_default = False
356
351
else :
357
352
kernel = DEFAULT_KERNEL
358
- # Flag that the kernel has been configured by default.
359
- self .kernel_default = True
360
353
# Create the kernel.
361
354
self .kernel = kernel_factory [kernel ](self )
362
355
@@ -600,9 +593,63 @@ def compare_image_to_baseline(self, item, fig, result_dir, summary=None):
600
593
summary ['status_msg' ] = error_message
601
594
return error_message
602
595
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
606
653
607
654
def compare_image_to_hash_library (self , item , fig , result_dir , summary = None ):
608
655
hash_comparison_pass = False
@@ -623,27 +670,6 @@ def compare_image_to_hash_library(self, item, fig, result_dir, summary=None):
623
670
pytest .fail (f"Can't find hash library at path { str (hash_library_filename )!r} ." )
624
671
625
672
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 )
647
673
648
674
hash_name = self .generate_test_name (item )
649
675
baseline_hash = hash_library .get (hash_name , None )
@@ -838,7 +864,7 @@ def pytest_unconfigure(self, config):
838
864
# It's safe to inject this metadata, as the key is an invalid Python
839
865
# class/function/method name, therefore there's no possible
840
866
# 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
842
868
with open (hash_library_path , "w" ) as fp :
843
869
json .dump (self ._generated_hash_library , fp , indent = 2 )
844
870
if self .results_always : # Make accessible in results directory
@@ -849,7 +875,7 @@ def pytest_unconfigure(self, config):
849
875
result_hashes = {k : v ['result_hash' ] for k , v in self ._test_results .items ()
850
876
if v ['result_hash' ]}
851
877
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
853
879
with open (result_hash_library , "w" ) as fp :
854
880
json .dump (result_hashes , fp , indent = 2 )
855
881
0 commit comments