The migration succeeded but the original plan didn't. People were supposed to write Python 2 and generate Python 3.[1] What worked was making it possible to have a single code base.
Agreed, all successful migrations I've seen started early and consistently used `from __future__` and python-future to write compatible code over a few years. This incremental approach almost made it trivial.