docs: def repeat_masker_alignment_iterator(fn, index_friendly=True, verbose=False):
    """
    Iterator for repeat masker alignment files; yields multiple alignment objects.
  
    Iterate over a file/stream of full repeat alignments in the repeatmasker
    format. Briefly, this format is as follows: each record (alignment) begins
    with a header line (see _rm_parse_header_line documentation for details of
    header format), followed by the alignment itself (example below) and finally
    a set of key-value meta-data pairs.
  
    The actual alignment looks like this::
  
      chr1               11 CCCTGGAGATTCTTATT--AGTGATTTGGGCT 41
                               ii        v   -- v  i i    v
      C MER5B#DNA/hAT    10 CCCCAGAGATTCTGATTTAATTGGTCTGGGGT 42
  
      chr1               42 GACTG 47
                             v
      C MER5B#DNA/hAT    43 CACTG 48
  
    The 'C' indicates that its the reverse complement of the consensus. The
    central string gives information about matches; "-" indicates an
    insertion/deletion, "i" a transition (G<->A, C<->T) and "v" a transversion
    (all other substitutions).
  
    :param fh:             filename or stream-like object to read from.
    :param index_friendly: if True, we will ensure the file/stream
                           position is before the start of the record when we
                           yield it; this requires the ability to seek within
                           the stream though, so if iterating over a
                           stream wtihout that ability, you'll have to set this
                           to false. Further, this will disable buffering for
                           the file, to ensure file.tell() behaves correctly,
                           so a performance hit will be incurred.
    :param verbose:        if true, output progress messages to stderr.
    """
    # step 1 -- build our iterator for the stream..
    try:
      fh = open(fn)
    except (TypeError):
      fh = fn
    iterable = fh
    if index_friendly:
      iterable = iter(fh.readline, '')
  
    # build progress indicator, if we want one and we're able to
    if verbose:
      try:
        m_fn = ": " + fh.name
      except TypeError:
        m_fn = ""
      try:
        current = fh.tell()
        fh.seek(0, 2)
        total_progress = fh.tell()
        fh.seek(current)
        pind = ProgressIndicator(totalToDo=total_progress,
                                 messagePrefix="completed",
                                 messageSuffix="of processing repeat-masker "
                                               "alignment file" + m_fn)
      except IOError:
        pind = None
  
    old_fh_pos = None
    new_fh_pos = fh.tell()
  
    s1 = None
    s2 = None
    s1_name = None
    s2_name = None
    s1_start = None
    s1_end = None
    s2_start = None
    s2_end = None
    meta_data = None
    alignment_line_counter = 0
    alig_l_space = 0
    prev_seq_len = 0
    rev_comp_match = None
    remaining_repeat = None
    remaining_genomic = None
  
    for line in iterable:
      if verbose and pind is not None:
        pind.done = fh.tell()
        pind.showProgress()
  
      if index_friendly:
        old_fh_pos = new_fh_pos
        new_fh_pos = fh.tell()
      line = line.rstrip()
      if line.lstrip() == "" and alignment_line_counter % 3 != 1:
        continue
  
      s_pres_split = re.split(r'(\s+)', line)
      parts = [x for x in s_pres_split if not (x.isspace() or x == "")]
  
      n = len(parts)
      for i in REPEATMASKER_FIELDS_TO_TRIM:
        if n >= i + 1:
          parts[i] = parts[i].strip()
  
      # decide what to do with this line -- is it a header line, part of the
      # alignment or a meta-data key-value line
      if alignment_line_counter % 3 == 1:
        if (REPEATMASKER_VALIDATE_MUTATIONS and
           not _rm_is_valid_annotation_line(line)):
          raise IOError("invalid mutation line: " + line)
        l_space = _rm_compute_leading_space(s_pres_split) - alig_l_space
        pad_right = prev_seq_len - (l_space + len(line.strip()))
        meta_data[ANNOTATION_KEY] += ((' ' * l_space) + line.strip() +
                                      (' ' * pad_right))
        alignment_line_counter += 1
      elif _rm_is_header_line(parts, n):
        if not (s1 is None and s2 is None and meta_data is None):
          if ANNOTATION_KEY in meta_data:
            meta_data[ANNOTATION_KEY] = meta_data[ANNOTATION_KEY].rstrip()
          if index_friendly:
            fh.seek(old_fh_pos)
          ss1 = Sequence(s1_name, s1, s1_start, s1_end, "+", remaining_genomic)
          s2s = "-" if rev_comp_match else "+"
          ss2 = Sequence(s2_name, s2, s2_start, s2_end, s2s, remaining_repeat)
          yield PairwiseAlignment(ss1, ss2, meta_data)
          if index_friendly:
            fh.seek(new_fh_pos)
        meta_data = {}
        s1 = ""
        s2 = ""
        s1_name, s2_name = _rm_get_names_from_header(parts)
        s1_start, s1_end = _rm_get_reference_coords_from_header(parts)
        s2_start, s2_end = _rm_get_repeat_coords_from_header(parts)
        rev_comp_match = _rm_is_reverse_comp_match(parts)
        remaining_repeat = _rm_get_remaining_repeat_from_header(parts)
        remaining_genomic = _rm_get_remaining_genomic_from_header(parts)
  
        _rm_parse_header_line(parts, meta_data)
        alignment_line_counter = 0
      elif _rm_is_alignment_line(parts, s1_name, s2_name):
        alignment_line_counter += 1
        name, seq = _rm_extract_sequence_and_name(parts, s1_name, s2_name)
        if name == s1_name:
          s1 += seq
        elif name == s2_name:
          s2 += seq
        alig_l_space = _rm_compute_leading_space_alig(s_pres_split, seq)
        prev_seq_len = len(seq)
      else:
        k, v = _rm_parse_meta_line(parts)
        meta_data[k] = v
    if index_friendly:
      fh.seek(old_fh_pos)
    ss1 = Sequence(s1_name, s1, s1_start, s1_end, "+", remaining_genomic)
    s2s = "-" if rev_comp_match else "+"
    ss2 = Sequence(s2_name, s2, s2_start, s2_end, s2s, remaining_repeat)
    yield PairwiseAlignment(ss1, ss2, meta_data)
    if index_friendly:
      fh.seek(new_fh_pos)