class_docstr: OLE container object
  
  This class encapsulates the interface to an OLE 2 structured
  storage file.  Use the listdir and openstream methods to
  access the contents of this file.
  
  Object names are given as a list of strings, one for each subentry
  level.  The root entry should be omitted.  For example, the following
  code extracts all image streams from a Microsoft Image Composer file::
  
      ole = OleFileIO("fan.mic")
  
      for entry in ole.listdir():
          if entry[1:2] == "Image":
              fin = ole.openstream(entry)
              fout = open(entry[0:1], "wb")
              while True:
                  s = fin.read(8192)
                  if not s:
                      break
                  fout.write(s)
  
  You can use the viewer application provided with the Python Imaging
  Library to view the resulting files (which happens to be standard
  TIFF files).
class_docstr_tok: ["OLE","container","object","This","class","encapsulates","the","interface","to","an","OLE","2","structured","storage","file",".","Use","the","listdir","and","openstream","methods","to","access","the","contents","of","this","file",".","Object","names","are","given","as","a","list","of","strings",",","one","for","each","subentry","level",".","The","root","entry","should","be","omitted",".","For","example",",","the","following","code","extracts","all","image","streams","from","a","Microsoft","Image","Composer","file",":",":","ole","=","OleFileIO","(","``","fan.mic","''",")","for","entry","in","ole.listdir","(",")",":","if","entry","[","1:2","]","==","``","Image","''",":","fin","=","ole.openstream","(","entry",")","fout","=","open","(","entry","[","0:1","]",",","``","wb","''",")","while","True",":","s","=","fin.read","(","8192",")","if","not","s",":","break","fout.write","(","s",")","You","can","use","the","viewer","application","provided","with","the","Python","Imaging","Library","to","view","the","resulting","files","(","which","happens","to","be","standard","TIFF","files",")","."]
docstr: Write a stream to disk. For now, it is only possible to replace an
  existing stream by data of the same size.
  
  :param stream_name: path of stream in storage tree (except root entry), either:
  
      - a string using Unix path syntax, for example:
        'storage_1/storage_1.2/stream'
      - or a list of storage filenames, path to the desired stream/storage.
        Example: ['storage_1', 'storage_1.2', 'stream']
  
  :param data: bytes, data to be written, must be the same size as the original
      stream.
docstr_tok: ["Write","a","stream","to","disk",".","For","now",",","it","is","only","possible","to","replace","an","existing","stream","by","data","of","the","same","size",".",":","param","stream_name",":","path","of","stream","in","storage","tree","(","except","root","entry",")",",","either",":","-","a","string","using","Unix","path","syntax",",","for","example",":","'storage_1\/storage_1.2\/stream'","-","or","a","list","of","storage","filenames",",","path","to","the","desired","stream\/storage",".","Example",":","[","'storage_1","'",",","'storage_1.2","'",",","'stream","'","]",":","param","data",":","bytes",",","data","to","be","written",",","must","be","the","same","size","as","the","original","stream","."]
code: def write_stream(self, stream_name, data):
      """
      Write a stream to disk. For now, it is only possible to replace an
      existing stream by data of the same size.
  
      :param stream_name: path of stream in storage tree (except root entry), either:
  
          - a string using Unix path syntax, for example:
            'storage_1/storage_1.2/stream'
          - or a list of storage filenames, path to the desired stream/storage.
            Example: ['storage_1', 'storage_1.2', 'stream']
  
      :param data: bytes, data to be written, must be the same size as the original
          stream.
      """
      if not isinstance(data, bytes):
          raise TypeError("write_stream: data must be a bytes string")
      sid = self._find(stream_name)
      entry = self.direntries[sid]
      if entry.entry_type != STGTY_STREAM:
          raise IOError("this is not a stream")
      size = entry.size
      if size != len(data):
          raise ValueError(
              "write_stream: data must be the same size as the existing stream"
          )
      if (
          size < self.minisectorcutoff
          and entry.entry_type != STGTY_ROOT
      ):
          return self._write_mini_stream(
              entry=entry, data_to_write=data
          )
  
      sect = entry.isectStart
      # number of sectors to write
      nb_sectors = (size + (self.sectorsize - 1)) // self.sectorsize
      log.debug("nb_sectors = %d" % nb_sectors)
      for i in range(nb_sectors):
          ##            try:
          ##                self.fp.seek(offset + self.sectorsize * sect)
          ##            except:
          ##                log.debug('sect=%d, seek=%d' %
          ##                    (sect, offset+self.sectorsize*sect))
          ##                raise IOError('OLE sector index out of range')
          # extract one sector from data, the last one being smaller:
          if i < (nb_sectors - 1):
              data_sector = data[
                  i * self.sectorsize : (i + 1) * self.sectorsize
              ]
              # TODO: comment this if it works
              assert len(data_sector) == self.sectorsize
          else:
              data_sector = data[i * self.sectorsize :]
              # TODO: comment this if it works
              log.debug(
                  "write_stream: size=%d sectorsize=%d data_sector=%Xh size%%sectorsize=%d"
                  % (
                      size,
                      self.sectorsize,
                      len(data_sector),
                      size % self.sectorsize,
                  )
              )
              assert (
                  len(data_sector) % self.sectorsize
                  == size % self.sectorsize
              )
          self.write_sect(sect, data_sector)
          ##            self.fp.write(data_sector)
          # jump to next sector in the FAT:
          try:
              sect = self.fat[sect]
          except IndexError:
              # [PL] if pointer is out of the FAT an exception is raised
              raise IOError(
                  "incorrect OLE FAT, sector index out of range"
              )
      # [PL] Last sector should be a "end of chain" marker:
      if sect != ENDOFCHAIN:
          raise IOError("incorrect last sector index in OLE stream")
  
imports: from __future__ import print_function
  import io
  import sys
  import struct, array, os.path, datetime, logging
label_desc: Use image node_id 27 for calling the OleFileIO obj's underlying member method code with example usage: obj.write_stream(stream_name, data) and returns: self