def compute_edits(old, new):
    """Compute the in-place edits needed to convert from old to new

    Returns a list ``[(index_1,change_1), (index_2,change_2)...]``
    where ``index_i`` is an offset into old, and ``change_1`` is the
    new bytes to replace.

    For example, calling ``compute_edits("abcdef", "qbcdzw")`` will return
    ``[(0, "q"), (4, "zw")]``.

    That is, the update should be preformed as (abusing notation):

    ``new[index:index+len(change)] = change``

    :param str old: The old data
    :param str new: The new data

    :returns: A list of tuples (index_i, change_i)
    """
    deltas = []
    delta = None
    for index, (n, o) in enumerate(zip(new, old)):
        if n == o:
            if delta is not None:
                deltas.append(delta)
                delta = None
        else:
            if delta is None:
                delta = (index, [])
            delta[1].append(n)

    if delta is not None:
        deltas.append(delta)

    return [(i, "".join(x)) for i, x in deltas]