"No offense intended, but I think that using `2to3` at release time is exactly the wrong way around."
It's not a method I'd recommend, but I was just pointing out that some people had such success with 2to3 that it's reliable enough for them to provide releases based on it. I would guess that this isn't their eternal 3.x support plan, but may give some confidence in projects that 3.x is only a 2to3 run away.
As the name implies, 2to3 gets you from 2 to 3, but it leaves 2 behind entirely which isn't something most people are ready to do (myself included). I'm a fan of trying to run a single codebase that supports 2 and 3, so the method I like is to run 2to3 up front but don't immediately apply the patch it generates. Use that patch as a guide for the area that needs attention, then manually apply changes where the patch points you to and ensure they will work for both versions.
For example, 2to3 changes "print 'hello'" to "print('hello')", but if you need to support 2.4-3.2, you'll need something like "sys.stdout.write('hello')". Even supporting 2.7-3.2, 2to3 will make the same suggestion, but I would add "from future import print_function" at the top in order to function across both versions.
The same goes for imports. "import ConfigParser" will be changed to "import configparser", but what in my case I want...
try:
import configparser
except ImportError:
import ConfigParser as configparser
I've never had much difficulty in porting using this method. It's more work than creating a 3.x branch for your product and just letting 2to3 apply its changes there, but then you have the ongoing maintenance of two separate branches.
It's not a method I'd recommend, but I was just pointing out that some people had such success with 2to3 that it's reliable enough for them to provide releases based on it. I would guess that this isn't their eternal 3.x support plan, but may give some confidence in projects that 3.x is only a 2to3 run away.