class_docstr: Backend storage for our "array of bits" using a python array of integers up
  to some maximum number of bytes, then spilling over to a file.
  This is -not- a cache; we instead save the leftmost bits in RAM, and the
  rightmost bits (if necessary) in a file.  On open, we read from the file to
  RAM.  On close, we write from RAM to the file.
class_docstr_tok: ["Backend","storage","for","our","``","array","of","bits","''","using","a","python","array","of","integers","up","to","some","maximum","number","of","bytes",",","then","spilling","over","to","a","file",".","This","is","-not-","a","cache",";","we","instead","save","the","leftmost","bits","in","RAM",",","and","the","rightmost","bits","(","if","necessary",")","in","a","file",".","On","open",",","we","read","from","the","file","to","RAM",".","On","close",",","we","write","from","RAM","to","the","file","."]
code: def __init__(self, num_bits, filename, max_bytes_in_memory):
      self.num_bits = num_bits
      num_chars = (self.num_bits + 7) // 8
      self.filename = filename
      self.max_bytes_in_memory = max_bytes_in_memory
      self.bits_in_memory = min(num_bits, self.max_bytes_in_memory * 8)
      self.bits_in_file = max(self.num_bits - self.bits_in_memory, 0)
      self.bytes_in_memory = (self.bits_in_memory + 7) // 8
      self.bytes_in_file = (self.bits_in_file + 7) // 8
  
      self.array_ = array.array("B", [0]) * self.bytes_in_memory
      flags = os.O_RDWR | os.O_CREAT
      if hasattr(os, "O_BINARY"):
          flags |= getattr(os, "O_BINARY")
      self.file_ = os.open(filename, flags)
      os.lseek(self.file_, num_chars + 1, os.SEEK_SET)
      os.write(self.file_, b"\x00")
  
      os.lseek(self.file_, 0, os.SEEK_SET)
      offset = 0
      intended_block_len = 2**17
      while True:
          if offset + intended_block_len < self.bytes_in_memory:
              block = os.read(self.file_, intended_block_len)
          elif offset < self.bytes_in_memory:
              block = os.read(self.file_, self.bytes_in_memory - offset)
          else:
              break
          for index_in_block, byte in enumerate(block):
              self.array_[offset + index_in_block] = byte
          offset += intended_block_len
  
imports: import array
  import math
  import os
  import random
label_desc: Use image node_id 1 to create a new Array_then_file_seek_backend object from inherited base classes: object with example: obj = Array_then_file_seek_backend(num_bits, filename, max_bytes_in_memory)