Issue 26266: add classattribute to enum to handle non-Enum attributes (original) (raw)

The rules for what objects in an Enum become members and which do not are fairly straight-forward:

double_underscore do not (but is reserved for Python) single_underscore do not (but is reserved for Enum itself) any descriptored object (such as functions) do not

Which means the proper way to add constants/attributes to an Enum is to write a descriptor, but most folks don't think about that when the Enum is not working properly they (okay, and me :/ ) just add the double-underscore.

This question has already come up a couple times on StackOverflow:

While this doesn't come up very often, that just means it is even more likely to have the attribute be double_underscored instead of descriptored.

The solution is have a descriptor in the Enum module for this case. While it would be possible to have several (constant-unless-mutable, constant-even-if-mutable, not-constant, possibly others) I think the not-constant would be sufficient (aka a writable property), although I am not opposed to a constant-unless mutable version as well.

The not-constant version would look like this (I'll attach patch later):

class classattribute: def init(self, value): self.value = value def get(self, *args): return self.value def set(self, value): self.value = value def repr(self): return '%s(%r)' % (self.class.name, self.value)

One possible downside to the classattribute route is that we have a descriptor whose only purpose is to shield the item from becoming a member; the up-side is that it's simple to implement.

Another possibility is skip:

class skip: """ Protects item from becaming an Enum member during class creation. """ def init(self, value): self.value = value

def __get__(self, instance, ownerclass=None):
    return self.value

The advantage is that it is replaced by the metaclass with the stored value, so we have no extraneous descriptor after the Enum is created; the downside is that it requires change in the metaclass to do the right thing.

Thoughts?