In the summer of 2022, my partner was taking her machine learning course as part of UBC's Key Capabilities in Data Science certificate. I was Andrea's on-call tutor for any Python questions, so while Andrea was listening to lectures I decided to do a small project that I thought I could complete during the course.
At the time, the Python steering council had received a couple of asks on backwards-compatibility related to the
enum module. I had also been told anecdotally that the
enum module didn't perform fast enough for some to want to use it (typically around import costs). I had a look at the source code and noticed it was over 2000 lines long and used
sys._getframe(). Obviously the
enum module has multiple classes and such with a lot of subtle details to it, so it isn't necessarily a small API, but the use of
sys._getframe() made me want to see if I could replicate API for
enum.Enum in less code.
In the end, I got most of the API implemented in less than 200 lines via
.compat.Enum. I couldn't get
type(enum.variant) and restricted subclassing to work, but I managed to get everything else working (that I can think of; as I said, the API is surprisingly subtle). And according to benchmarking, creation – and thus importing – is way faster, while enum variant access and comparison – i.e. attribute access and equality – are the same.
The really tricky bit with this whole endeavour, though, is typing. Enums are special-cased by type checkers. And while
@typing.dataclass_transform() exists to help make dataclass-like packages be treated like
dataclass itself, no such decorator exists for enums. As such, you effectively have to lie to the type checkers that
basicenum.compat.Enum is equivalent to
enum.Enum during type checking:
As long as you don't rely on
type(enum.variant) to be the same as how
enum.Enum works, this trick should work (once again, assuming I didn't miss anything).
I honestly don't have any further plans for this package. While I namespaced things such that if I decided to create an enum type that wasn't compatible with
enum.Enum to see how simple and/or fast I could make it I could without people getting confused as to what enum type is which, I have no plans to pursue that idea. But it was at least a fun challenge to see if I could at least pull off my goal of re-implementing most of