docs: def read(path='', mode='r', record_size=None, record_seperator=None, offset=0, autostrip=False):
      ''' instead of writing open('file').read(), this is much more efficient and has some extra goodies '''
      assert isinstance(path, str), 'path needs to be a string, not: {}'.format(repr(path))
      assert isinstance(mode, str), 'mode needs to be a string, not: {}'.format(repr(mode))
      assert ((record_size is None)+(record_seperator is None))>0 , 'generators.read does not support both record_seperator and record_size options being used at the same time: {} {}'.format(record_size, record_seperator)
      assert record_size is None or type(record_size) is int, 'record_size can only be defined as an int, not: {}'.format(repr(record_size))
      assert record_seperator is None or isinstance(record_seperator, str) and len(record_seperator), 'record_seperator can only be defined as a non-empty string, not: {}'.format(repr(record_seperator))
      assert type(offset) == int and offset>=0, 'offset needs to be a positive int, not: {}'.format(repr(offset))
      assert type(autostrip) == bool, 'autostrip needs to be a boolean, not: {}'.format(repr(autostrip))
  
      stop_value = b'' if mode == 'rb' else ''
      if autostrip:
          autostrip = lambda i:i.strip()
      else:
          autostrip = lambda i:i
  
      if path=='': # if path is empty, use stdin
          if record_seperator is None:
              for line in stdin:
                  yield autostrip(line)
          else:
              for entry in read_with_seperator(stdin, record_seperator, stop_value):
                  yield autostrip(entry)
      else: # otherwise, open path
          with open(path, mode) as f:
              if record_size is None and record_seperator is None:  # no record_size or record_seperator? iterate over lines
                  for line in f:
                      if offset > 0: # offset in line reading mode offsets per each line
                          offset -= 1
                      else:
                          yield autostrip(line)
              elif record_seperator is not None:
                  f.seek(offset)
                  for record in read_with_seperator(f, record_seperator, stop_value):
                      yield autostrip(record)
              else:  # if record_size is specified, iterate over records at that size
                  f.seek(offset)
                  for record in iter(partial(f.read, record_size), stop_value):
                      yield autostrip(record)