code: def cdna_codon_sequence_after_deletion_or_substitution_frameshift(
          sequence_from_start_codon,
          cds_offset,
          trimmed_cdna_ref,
          trimmed_cdna_alt):
      
      mutated_codon_index = cds_offset // 3
      # get the sequence starting from the first modified codon until the end
      # of the transcript.
      sequence_after_mutated_codon = \
          sequence_from_start_codon[mutated_codon_index * 3:]
  
      # the variant's ref nucleotides should start either 0, 1, or 2 nucleotides
      # into `sequence_after_mutated_codon`
      offset_into_mutated_codon = cds_offset % 3
  
      sequence_from_mutated_codon = substitute(
          sequence=sequence_after_mutated_codon,
          offset=offset_into_mutated_codon,
          ref=trimmed_cdna_ref,
          alt=trimmed_cdna_alt)
      return mutated_codon_index, sequence_from_mutated_codon
docs: Logic for any frameshift which isn't an insertion.
  
      We have insertions as a special case since our base-inclusive
      indexing means something different for insertions:
         cds_offset = base before insertion
      Whereas in this case:
        cds_offset = first reference base affected by a variant
  
      Returns index of first modified codon and sequence from that codon
      onward.