@@ -874,7 +874,7 @@ def from_image(klass, img):
874
874
extra = img .extra .copy ())
875
875
876
876
@classmethod
877
- def _sniff_meta_for (klass , filename , sniff_nbytes ):
877
+ def _sniff_meta_for (klass , filename , sniff_nbytes , sniff = None ):
878
878
""" Sniff metadata for image represented by `filename`
879
879
880
880
Parameters
@@ -886,28 +886,39 @@ def _sniff_meta_for(klass, filename, sniff_nbytes):
886
886
and read from that instead of `filename`.
887
887
sniff_nbytes : int
888
888
Number of bytes to read from the image or metadata file
889
+ sniff : (bytes, fname), optional
890
+ The result of a previous call to `_sniff_meta_for`. If fname
891
+ matches the computed header file name, `sniff` is returned without
892
+ rereading the file.
889
893
890
894
Returns
891
895
-------
892
- meta_bytes : None or bytes
893
- None if we could not read the image or metadata file. `meta_bytes `
896
+ sniff : None or ( bytes, fname)
897
+ None if we could not read the image or metadata file. `sniff[0] `
894
898
is either length `sniff_nbytes` or the length of the image /
895
- metadata file, whichever is the shorter.
899
+ metadata file, whichever is the shorter. `fname` is the name of
900
+ the sniffed file.
896
901
"""
897
902
froot , ext , trailing = splitext_addext (filename ,
898
903
klass ._compressed_suffixes )
899
- # Determine the metadata location, then sniff it
904
+ # Determine the metadata location
900
905
t_fnames = types_filenames (
901
906
filename ,
902
907
klass .files_types ,
903
908
trailing_suffixes = klass ._compressed_suffixes )
904
909
meta_fname = t_fnames .get ('header' , filename )
910
+
911
+ # Do not re-sniff if it would be from the same file
912
+ if sniff is not None and sniff [1 ] == meta_fname :
913
+ return sniff
914
+
915
+ # Attempt to sniff from metadata location
905
916
try :
906
917
with ImageOpener (meta_fname , 'rb' ) as fobj :
907
- sniff = fobj .read (sniff_nbytes )
918
+ binaryblock = fobj .read (sniff_nbytes )
908
919
except IOError :
909
920
return None
910
- return sniff
921
+ return ( binaryblock , meta_fname )
911
922
912
923
@classmethod
913
924
def path_maybe_image (klass , filename , sniff = None , sniff_max = 1024 ):
@@ -920,11 +931,13 @@ def path_maybe_image(klass, filename, sniff=None, sniff_max=1024):
920
931
If `filename` points to an image data file, and the image type has
921
932
a separate "header" file, we work out the name of the header file,
922
933
and read from that instead of `filename`.
923
- sniff : None or bytes, optional
934
+ sniff : None or ( bytes, filename) , optional
924
935
Bytes content read from a previous call to this method, on another
925
- class. This allows us to read metadata bytes once from the image /
926
- or header, and pass this read set of bytes to other image classes,
927
- therefore saving a repeat read of the metadata. None forces this
936
+ class, with metadata filename. This allows us to read metadata
937
+ bytes once from the image or header, and pass this read set of
938
+ bytes to other image classes, therefore saving a repeat read of the
939
+ metadata. `filename` is used to validate that metadata would be
940
+ read from the same file, re-reading if not. None forces this
928
941
method to read the metadata.
929
942
sniff_max : int, optional
930
943
The maximum number of bytes to read from the metadata. If the
@@ -938,7 +951,7 @@ def path_maybe_image(klass, filename, sniff=None, sniff_max=1024):
938
951
-------
939
952
maybe_image : bool
940
953
True if `filename` may be valid for an image of this class.
941
- sniff : None or bytes
954
+ sniff : None or ( bytes, filename)
942
955
Read bytes content from found metadata. May be None if the file
943
956
does not appear to have useful metadata.
944
957
"""
@@ -948,14 +961,16 @@ def path_maybe_image(klass, filename, sniff=None, sniff_max=1024):
948
961
return False , sniff
949
962
if not hasattr (klass .header_class , 'may_contain_header' ):
950
963
return True , sniff
951
- if sniff is None or len (sniff ) < klass ._meta_sniff_len :
952
- sniff_nbytes = max (klass ._meta_sniff_len , sniff_max )
953
- sniff = klass ._sniff_meta_for (filename , sniff_nbytes )
954
- if sniff is None : # Can't sniff, won't sniff
955
- return False , None
956
- if len (sniff ) < klass ._meta_sniff_len :
964
+
965
+ # Force re-sniff on too-short sniff
966
+ if sniff is not None and len (sniff [0 ]) < klass ._meta_sniff_len :
967
+ sniff = None
968
+ sniff = klass ._sniff_meta_for (filename ,
969
+ max (klass ._meta_sniff_len , sniff_max ),
970
+ sniff )
971
+ if sniff is None or len (sniff [0 ]) < klass ._meta_sniff_len :
957
972
return False , sniff
958
- return klass .header_class .may_contain_header (sniff ), sniff
973
+ return klass .header_class .may_contain_header (sniff [ 0 ] ), sniff
959
974
960
975
def __getitem__ (self ):
961
976
''' No slicing or dictionary interface for images
0 commit comments