I have a Python project with 28KLOC of Python, 22KLOC for a Python/C extension, and 26KLOC for the tests, so about 4x larger.
It took me about 6-8 weeks to port.
Part of it was because I had to change the API. I had an API with a method like "X.to_string(fmt)" where the format specifier could be something like 'csv' for text and 'csv.gz' for gzip-compressed text.
I had to split that out into a "X.to_string()" and "X.to_bytes()" variants.
I also deal with formats which almost always only use ASCII but where people end up putting in Latin-1 or UTF-8. The API was something like "X.get_field(name)", where name was a byte string, and it returned a byte string.
(GIGO and it's your responsibility to deal with your byte strings.)
In Python 3, X had to acquire an "encoding" and "errors" parameter, so it could know the expected encoding for the entire record. But to make it work, in practice each field could have a different encoding, so I ended up also adding a "X.get_field_as_bytes(name)". The 'name' can be a Unicode or byte string.
These changes to return a Unicode string from a byte string ended up adding a lot of code of the form:
try:
field = field_bytes.decode(self.encoding, self.encoding_errors)
except UnicodeDecodeError as error:
die("Cannot decode field %r (%r): %s" %
(field_name, field_bytes, error)
All of these new branches then meant adding unit tests to ensure coverage.
Parts of the code supported passing in a byte string, Unicode string containing only ASCII characters, or buffer object. There's no easy way to handle that in the API, so I eventually dug into Python's own source code to copy how Modules/binascii.c supports it.
I also had to switch all my code to use the new buffer API. Only to find I missed a PyBuffer_Release(), which caused a slow memory leak.
Then the performance in Python 3 was slower than Python 2, so I pushed more of the Python-level code into a C extension.
I'm not convinced the new API is all that much better. It's certainly harder to implement and therefore maintain, and I don't have all that many users.
But I can say that "you can convert that in 2 days" feels like an optimistic statement. The test suite contains over 2000 byte string constants, and even at 5 changes per minute that one change alone would take 6 hours.
Admittedly, part of the reason it took 6-8 weeks was because the result works under both Python 2.7 and Python 3.5+. It is not so easy to make compatible Python/C extensions. But as literally all of my users were using Python 2.x, I wasn't going to drop support for at least Python 2.7.
(I learned a few months ago that one potential customer was still using Python 2.6 on their compute cluster. They have since upgraded to Python 2.7. I warned them about 2020.)