Since Python 2 is still in heavy use, at least in the deployment of the DMOJ judge, compatibility with it must be maintained. This necessitated writing code in such a fashion as to be compatible with both Python 2 and Python 3. The
six library has proved tremendously helpful in abstracting away the differences, some of which highly non-trivial.
six.with_metaclass hides away the difference in metaclass use. In Python 2, the
__metaclass__ class member defines the metaclass used for the class, while in Python 3, one would specify it as
class Class(metaclass=MetaClass). The latter would be a syntax error in Python 2, and the former has no effect in Python 3.
six provides a solution that is highly non-obvious and yet works perfectly.
The most frustrating part is unicode-handling. The DMOJ judge was written somewhat sloppily in regards to unicode handling, dealing mostly with bytestrings and raw bytes. With the separation of
str in Python 3, strings in the judge must be turned into either
str on a case-by-case basis. It is decided that source code and program output will be treated as raw bytes, and textual data that are derived from these will be handled as UTF-8.