Refactor and port to Python 3