ported to python 3 with backward compatibility