You were indeed very lucky if all projects you've worked on had decent test coverage.
In order to ease porting, I've created a modified Python 3.6 interpreter that generates warnings in a lot of the cases that real Python 3 would generate an exception. See https://github.com/nascheme/ppython .
The goal is to have a 2to3 script that generates something that will run, with warnings, under me modified Python. Once you fix all the warnings, your code should run correctly in Python 3.
Surely that's a bug in the system that you've just uncovered and fixed? Py2 used to use the memory address of the object when comparing by default, which is just... crazy, especially for a language with so few WTFs:
>>> object() > object()
True
>>> object() > object()
False
>>> object() > object()
True
>>> object() > object()
False
> In order to ease porting, I've created a modified Python 3.6 interpreterThat looks amazing! We're going to end up porting a fairly large + critical Django app to py3 and I definitely think this could ease some of the pain. I'm going to give it a go when I get the chance.
Its true that that's crazy, but, OTOH, everything-can-be-sorted is a useful feature (which Erlang has, for instance). Py3 could conceptually have retained it with a different implementation (this would probably still have been a breaking change from Py2, but not a feature loss.)
Out of interest whats the biggest time sink while doing this? I've had a lot of luck using 2to3 and with decent test coverage and a UAT environment that people can access, its not exactly months and months of work changing "xrange" to "range", and "print" to "print()"