@@ -874,7 +874,7 @@ def from_image(klass, img):
874874 extra = img .extra .copy ())
875875
876876 @classmethod
877- def _sniff_meta_for (klass , filename , sniff_nbytes ):
877+ def _sniff_meta_for (klass , filename , sniff_nbytes , sniff = None ):
878878 """ Sniff metadata for image represented by `filename`
879879
880880 Parameters
@@ -886,28 +886,39 @@ def _sniff_meta_for(klass, filename, sniff_nbytes):
886886 and read from that instead of `filename`.
887887 sniff_nbytes : int
888888 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.
889893
890894 Returns
891895 -------
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] `
894898 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.
896901 """
897902 froot , ext , trailing = splitext_addext (filename ,
898903 klass ._compressed_suffixes )
899- # Determine the metadata location, then sniff it
904+ # Determine the metadata location
900905 t_fnames = types_filenames (
901906 filename ,
902907 klass .files_types ,
903908 trailing_suffixes = klass ._compressed_suffixes )
904909 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
905916 try :
906917 with ImageOpener (meta_fname , 'rb' ) as fobj :
907- sniff = fobj .read (sniff_nbytes )
918+ binaryblock = fobj .read (sniff_nbytes )
908919 except IOError :
909920 return None
910- return sniff
921+ return ( binaryblock , meta_fname )
911922
912923 @classmethod
913924 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):
920931 If `filename` points to an image data file, and the image type has
921932 a separate "header" file, we work out the name of the header file,
922933 and read from that instead of `filename`.
923- sniff : None or bytes, optional
934+ sniff : None or ( bytes, filename) , optional
924935 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
928941 method to read the metadata.
929942 sniff_max : int, optional
930943 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):
938951 -------
939952 maybe_image : bool
940953 True if `filename` may be valid for an image of this class.
941- sniff : None or bytes
954+ sniff : None or ( bytes, filename)
942955 Read bytes content from found metadata. May be None if the file
943956 does not appear to have useful metadata.
944957 """
@@ -948,14 +961,16 @@ def path_maybe_image(klass, filename, sniff=None, sniff_max=1024):
948961 return False , sniff
949962 if not hasattr (klass .header_class , 'may_contain_header' ):
950963 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 :
957972 return False , sniff
958- return klass .header_class .may_contain_header (sniff ), sniff
973+ return klass .header_class .may_contain_header (sniff [ 0 ] ), sniff
959974
960975 def __getitem__ (self ):
961976 ''' No slicing or dictionary interface for images
0 commit comments