After all the defenses I still don't like Tim's proposed syntax. Color me Barry.
On Tue, Feb 12, 2013 at 11:54 AM, Tim Delaney tim.delaney@aptare.com wrote:
On 13 February 2013 06:13, Guido van Rossum guido@python.org wrote:
So with Tim's implementation, what happens here:
class Color(Enum): RED, GREEN, BLUE if sys.platform == 'win32': MAGENTA
and you happen to have no "import sys" in your module? The sys lookup will succeed, create a new enum, and then you will get an error something like this:
AttributeError: 'Enum' object has no attribute 'platform'
Well, that particular case would work (you'd get a NameError: sys) due to having done an attribute lookup on sys, but the following:
class Color(Enum): RED, GREEN, BLUE if platfor == 'win32': MAGENTA
would create an enum value 'platfor'.
Personally, I don't think it's possible to have an enum with a simple interface and powerful semantics with just python code without it being fragile. I think I've got it fairly close, but there is horrible magic in there (multiple kinds) and there are definitely still edge cases. Any complete enum implementation is going to need some special handling by the parser I think.
I'm actually thinking that to simplify things, I need a sentinel object to mark the end of the enum list (which allows other names after it). But that still wouldn't handle the case above (the if statement).
BTW, for anyone who hasn't seen the magic code (largely uncommented, no explanations yet of how it's doing it - I probably won't get to that until the weekend) it's here: https://bitbucket.org/magao/enum
Tim Delaney
-- --Guido van Rossum (python.org/~guido)
On Tue, Feb 12, 2013 at 11:59 AM, Guido van Rossum guido@python.org wrote:
After all the defenses I still don't like Tim's proposed syntax. Color me Barry.
In this case, I see no reason not to use Barry's flufl.enum - it's pretty good and has been around for a while. The main advantage of Tim's implementation syntax (wasn't it Michael Foord who originally proposed it?) is that it lets us do less typing which is great. IOW, sure with flufl.enum I can do this and be reasonably happy:
class Color(Enum): RED = 1 BLUE = 2 GREEN = 3
But in 99% of the cases in Python code I absolutely don't care about the values of these enumerations (*), so I'd much, *much* rather write:
class Color(Enum): RED, BLUE, GREEN
Yes, the implementation is messy, but it can be documented and tested well, and it's fairly small and confined. But this is a matter of preference, and I can see your point (Guido) about preferring the more explicit syntax in order to avoid too much magic.
Eli
(*) And where I do care, I'd still enjoy them being generated automatically.
On Tue, 12 Feb 2013 12:58:44 -0800 Eli Bendersky eliben@gmail.com wrote:
On Tue, Feb 12, 2013 at 11:59 AM, Guido van Rossum guido@python.org wrote:
After all the defenses I still don't like Tim's proposed syntax. Color me Barry.
In this case, I see no reason not to use Barry's flufl.enum - it's pretty good and has been around for a while. The main advantage of Tim's implementation syntax (wasn't it Michael Foord who originally proposed it?) is that it lets us do less typing which is great. IOW, sure with flufl.enum I can do this and be reasonably happy:
class Color(Enum): RED = 1 BLUE = 2 GREEN = 3
I still hope enum values are strings by default - or, if not, that they get nice reprs. Integer enums are only useful for interoperability with stubborn low-level libraries :-)
Regards
Antoine.
Definitely they need nice reprs.
On Tue, Feb 12, 2013 at 1:04 PM, Antoine Pitrou solipsis@pitrou.net wrote:
On Tue, 12 Feb 2013 12:58:44 -0800 Eli Bendersky eliben@gmail.com wrote:
On Tue, Feb 12, 2013 at 11:59 AM, Guido van Rossum guido@python.org wrote:
After all the defenses I still don't like Tim's proposed syntax. Color me Barry.
In this case, I see no reason not to use Barry's flufl.enum - it's pretty good and has been around for a while. The main advantage of Tim's implementation syntax (wasn't it Michael Foord who originally proposed it?) is that it lets us do less typing which is great. IOW, sure with flufl.enum I can do this and be reasonably happy:
class Color(Enum): RED = 1 BLUE = 2 GREEN = 3
I still hope enum values are strings by default - or, if not, that they get nice reprs. Integer enums are only useful for interoperability with stubborn low-level libraries :-)
Regards
Antoine.
Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- --Guido van Rossum (python.org/~guido)
On Tue, Feb 12, 2013 at 1:04 PM, Antoine Pitrou solipsis@pitrou.net wrote:
On Tue, 12 Feb 2013 12:58:44 -0800 Eli Bendersky eliben@gmail.com wrote:
On Tue, Feb 12, 2013 at 11:59 AM, Guido van Rossum guido@python.org
wrote:
After all the defenses I still don't like Tim's proposed syntax. Color
me
Barry.
In this case, I see no reason not to use Barry's flufl.enum - it's pretty good and has been around for a while. The main advantage of Tim's implementation syntax (wasn't it Michael Foord who originally proposed
it?)
is that it lets us do less typing which is great. IOW, sure with
flufl.enum
I can do this and be reasonably happy:
class Color(Enum): RED = 1 BLUE = 2 GREEN = 3
I still hope enum values are strings by default - or, if not, that they get nice reprs. Integer enums are only useful for interoperability with stubborn low-level libraries :-)
I agree, and Tim's implementation provides a very nice string representation, no matter what the value underneath is. I don't really care what the value underneath is, actually.
Eli
On Feb 12, 2013, at 02:13 PM, Eli Bendersky wrote:
I agree, and Tim's implementation provides a very nice string representation, no matter what the value underneath is. I don't really care what the value underneath is, actually.
Except that sometimes you do, which is why flufl.enum has a nice concise str and a more detailed repr. The former doesn't include the underlying value while the latter does. Edible cake.
-Barry
On 14 February 2013 05:14, Barry Warsaw barry@python.org wrote:
On Feb 12, 2013, at 02:13 PM, Eli Bendersky wrote:
I agree, and Tim's implementation provides a very nice string representation, no matter what the value underneath is. I don't really
care
what the value underneath is, actually.
Except that sometimes you do, which is why flufl.enum has a nice concise str and a more detailed repr. The former doesn't include the underlying value while the latter does. Edible cake.
Yes - my enum's exactly the same - simple, concise str (for both the enum and values) and detailed repr. The actual repr is a little different to flufl.enum repr (I think the str is the same) but conveys the same information.
Color.RED <EnumValue 'Color.RED': 0>
{RED:0, GREEN:1, BLUE:2, CYAN:10, MAGENTA:11, YELLOW:12, BLACK:127} <enum __main__.Color {<EnumValue 'RED': 0>, <EnumValue 'GREEN': 1>, <EnumValue 'BLUE': 2>, <EnumValue 'CYAN': 10>, <EnumValue 'MAGENTA': 11>, <EnumValue 'YELLOW': 12>, <EnumValue 'BLACK': 127>}>
Tim Delaney
On Feb 14, 2013, at 06:22 AM, Tim Delaney wrote:
Yes - my enum's exactly the same - simple, concise str (for both the enum and values) and detailed repr. The actual repr is a little different to flufl.enum repr (I think the str is the same) but conveys the same information.
I like that you came to the same conclusion, namely that the str should be simple and the repr more detailed. The exactly color of that detail can be bikeshedded to death now. :)
-Barry
On 13/02/13 08:04, Antoine Pitrou wrote:
I still hope enum values are strings by default - or, if not, that they get nice reprs.
99.9% of the time I don't care what value enums have, in fact it is an advantage if I don't know. Pascal, as I remember it, doesn't give you any way to find out. But I consider enums displaying as their name to be essential to an enum.
Steven D'Aprano wrote:
99.9% of the time I don't care what value enums have, in fact it is an advantage if I don't know. Pascal, as I remember it, doesn't give you any way to find out.
Yes, it does: the ord() function.
But I consider enums displaying as their name to be essential to an enum.
That's one thing that, frustratingly, standard Pascal *doesn't* give you (although many dialects have extensions that do).
On Feb 12, 2013, at 10:04 PM, Antoine Pitrou wrote:
I still hope enum values are strings by default - or, if not, that they get nice reprs. Integer enums are only useful for interoperability with stubborn low-level libraries :-)
>>> from flufl.enum import make >>> Colors = make('Colors', 'RED GREEN BLUE'.split()) >>> print(Colors.RED) Colors.RED >>> Colors.RED <EnumValue: Colors.RED [int=1]>
Having the enum name in the str and (admittedly uglier but more informational) repr is very important to me, because I typically use enums like so:
from mailman.interfaces.members import DeliveryMode ... def send_plaintext(member): ... if member.delivery_mode is DeliveryMode.regular: ... elif member.delivery_mode is DeliveryMode.mime_digests: ...
Now, if something goes wrong, I can set a breakpoint or debug-print right before the conditional and get the value of `member.delivery_mode`. The fact that it will print `DeliveryMode.regular` makes debugging the problem a *much* better experience.
Cheers, -Barry
On 13 February 2013 07:58, Eli Bendersky eliben@gmail.com wrote:
On Tue, Feb 12, 2013 at 11:59 AM, Guido van Rossum guido@python.orgwrote:
After all the defenses I still don't like Tim's proposed syntax. Color me Barry.
The main advantage of Tim's implementation syntax (wasn't it Michael Foord who originally proposed it?)
Indeed it was and I don't want to take any of the "credit" away from Michael. I simply took his original inspired idea and added several extra layers of magic on top ;) I've updated my README to make that clear.
Tim Delaney
On 13 February 2013 07:58, Eli Bendersky eliben@gmail.com wrote:
But in 99% of the cases in Python code I absolutely don't care about the values of these enumerations (*), so I'd much, *much* rather write:
class Color(Enum): RED, BLUE, GREEN
Yes, the implementation is messy, but it can be documented and tested well, and it's fairly small and confined. But this is a matter of preference, and I can see your point (Guido) about preferring the more explicit syntax in order to avoid too much magic.
Eli
(*) And where I do care, I'd still enjoy them being generated automatically.
I'm of the opinion that the most fundamental property of an enum is that it can generate its values automatically. Everything else is a nice-to-have, but without that property it's not much use as an enum.
Tim Delaney
And I'm of the opinion that the most fundamental property of an enum is that it doesn't print as an int.
On Tue, Feb 12, 2013 at 1:19 PM, Tim Delaney timothy.c.delaney@gmail.com wrote:
On 13 February 2013 07:58, Eli Bendersky eliben@gmail.com wrote:
But in 99% of the cases in Python code I absolutely don't care about the values of these enumerations (*), so I'd much, *much* rather write:
class Color(Enum): RED, BLUE, GREEN
Yes, the implementation is messy, but it can be documented and tested well, and it's fairly small and confined. But this is a matter of preference, and I can see your point (Guido) about preferring the more explicit syntax in order to avoid too much magic.
Eli
(*) And where I do care, I'd still enjoy them being generated automatically.
I'm of the opinion that the most fundamental property of an enum is that it can generate its values automatically. Everything else is a nice-to-have, but without that property it's not much use as an enum.
Tim Delaney
-- --Guido van Rossum (python.org/~guido)
On 13 February 2013 08:59, Guido van Rossum guido@python.org wrote:
And I'm of the opinion that the most fundamental property of an enum is that it doesn't print as an int.
That part is easy.
Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information.
from enum import Enum class Color(Enum):
... RED ...
str(Color.RED)
'Color.RED'
repr(Color.RED)
"<EnumValue 'Color.RED': 0>"
str(Color)
'{RED:0}'
repr(Color)
"<enum __main__.Color {<EnumValue 'RED': 0>}>"
Making an appropriate str/repr just requires deciding what it should be. I chose to make the reprs give more information, but there's no reason they couldn't be simplified.
I'll see if I can come up with a syntax for declaration that we're both happy with, but I doubt I'll be as happy with it as what I've currently got (despite its edge cases).
Tim Delaney
On Feb 13, 2013, at 08:19 AM, Tim Delaney wrote:
I'm of the opinion that the most fundamental property of an enum is that it can generate its values automatically. Everything else is a nice-to-have, but without that property it's not much use as an enum.
See, I don't care about that much because I define an enum once, but I *use* it hundreds of times. Thus a little more verbosity/explicitness at definition time is a one-time cost, and a very low one at that. It might not seems that way when you're writing them in so many mailing list replies though ;).
In real code, having a really good str and repr, along with good semantics makes them much more useful for debugging, and very pleasant to use.
Cheers, -Barry
On 14 February 2013 05:19, Barry Warsaw barry@python.org wrote:
On Feb 13, 2013, at 08:19 AM, Tim Delaney wrote:
I'm of the opinion that the most fundamental property of an enum is that
it
can generate its values automatically. Everything else is a nice-to-have, but without that property it's not much use as an enum.
See, I don't care about that much because I define an enum once, but I *use* it hundreds of times. Thus a little more verbosity/explicitness at definition time is a one-time cost, and a very low one at that. It might not seems that way when you're writing them in so many mailing list replies though ;).
My main concern regarding this is ensuring that:
1. Values don't get repeated.
2. Values don't get skipped (unless explicitly skipped);
#1 obviously is the most important property, but in practice I find #2 to be very important as well. Whilst it's more verbose, the ... syntax isn't bad, and I've added support to it to my enum to play with. Currently my enum implementation includes the kitchen sink, but I'm looking to do some renovations soon.
In real code, having a really good str and repr, along with good semantics makes them much more useful for debugging, and very pleasant to use.
Absolutely. But it's not just that either. If you can convert from the string name to the enum, it makes the enum suitable as a transport mechanism. Each end can have different values for the enum in practice so long as the names don't change - it can make things much more robust across versions.
Tim Delaney
On Feb 14, 2013, at 06:28 AM, Tim Delaney wrote:
- Values don't get repeated.
This is easy, and flufl.enum guarantees this, even for subclasses:
>>> class Colors(Enum): ... red = 1 ... blue = 1 ... Traceback (most recent call last): ... TypeError: Multiple enum values: 1 >>> class Colors(Enum): ... red = 1 ... blue = 2 ... >>> class MoreColors(Colors): ... green = 2 ... Traceback (most recent call last): ... TypeError: Multiple enum values: 2
- Values don't get skipped (unless explicitly skipped);
Is #2 is the reason why you have different subclasses for flag enums, since the definition of "skipped" is different?
Many folks have said they don't care about the actual enum values, so for them, skips don't matter. Setting aside explicit skips, you can add such verification with a class decorator, e.g.:
-----snip snip----- from flufl.enum import Enum
def noskips(cls): for i, intval in enumerate(cls, start=1): if i != int(intval): raise TypeError('Skipped value: {}'.format(i)) return cls
@noskips class GoodColors(Enum): green = 3 blue = 1 red = 2
@noskips class BadColors(Enum): green = 4 blue = 1 red = 2
$ python3 noskips.py Traceback (most recent call last): ... TypeError: Skipped value: 3 -----snip snip-----
If you can convert from the string name to the enum, it makes the enum suitable as a transport mechanism.
>>> from flufl.enum import make >>> Colors = make('Colors', 'red green blue'.split()) >>> Colors['red'] <EnumValue: Colors.red [int=1]> >>> Colors[2] <EnumValue: Colors.green [int=2]> >>> Colors[Colors.green.name] <EnumValue: Colors.green [int=2]>
Cheers, -Barry
On Wed, 13 Feb 2013 13:19:14 -0500 Barry Warsaw barry@python.org wrote:
On Feb 13, 2013, at 08:19 AM, Tim Delaney wrote:
I'm of the opinion that the most fundamental property of an enum is that it can generate its values automatically. Everything else is a nice-to-have, but without that property it's not much use as an enum.
See, I don't care about that much because I define an enum once, but I *use* it hundreds of times. Thus a little more verbosity/explicitness at definition time is a one-time cost, and a very low one at that.
The cost is not low when you have many values. Also, with many values and one value per line, it can make your declaration very long vertically.
And it's not always true that you use an enum much more often than you define it. For example, you may define many error codes (e.g. errnos) for compatibility with another system, but only check a few of them explicitly in your application code.
Regards
Antoine.
On Feb 13, 2013, at 08:30 PM, Antoine Pitrou wrote:
The cost is not low when you have many values. Also, with many values and one value per line, it can make your declaration very long vertically.
And it's not always true that you use an enum much more often than you define it. For example, you may define many error codes (e.g. errnos) for compatibility with another system, but only check a few of them explicitly in your application code.
Huge enums haven't been common in my experience, but in that case I'd probably just use the make() helper.
-Barry
Le Wed, 13 Feb 2013 17:28:09 -0500, Barry Warsaw barry@python.org a écrit :
On Feb 13, 2013, at 08:30 PM, Antoine Pitrou wrote:
The cost is not low when you have many values. Also, with many values and one value per line, it can make your declaration very long vertically.
And it's not always true that you use an enum much more often than you define it. For example, you may define many error codes (e.g. errnos) for compatibility with another system, but only check a few of them explicitly in your application code.
Huge enums haven't been common in my experience, but in that case I'd probably just use the make() helper.
One of my common use cases for wanting an enum has always been to map a third-party protocol or library's error codes.
Really, the one screaming use case in the stdlib is in the errno module :-) For that you have to be able to define an enum that subclasses int, though.
Regards
Antoine.
Please. Anything *except*
class Color(Enum): RED, BLUE, GREEN
And not this eiter:
class Color(Enum): RED BLUE GREEN
On Tue, Feb 12, 2013 at 12:58 PM, Eli Bendersky eliben@gmail.com wrote:
On Tue, Feb 12, 2013 at 11:59 AM, Guido van Rossum guido@python.org wrote:
After all the defenses I still don't like Tim's proposed syntax. Color me Barry.
In this case, I see no reason not to use Barry's flufl.enum - it's pretty good and has been around for a while. The main advantage of Tim's implementation syntax (wasn't it Michael Foord who originally proposed it?) is that it lets us do less typing which is great. IOW, sure with flufl.enum I can do this and be reasonably happy:
class Color(Enum): RED = 1 BLUE = 2 GREEN = 3
But in 99% of the cases in Python code I absolutely don't care about the values of these enumerations (*), so I'd much, *much* rather write:
class Color(Enum): RED, BLUE, GREEN
Yes, the implementation is messy, but it can be documented and tested well, and it's fairly small and confined. But this is a matter of preference, and I can see your point (Guido) about preferring the more explicit syntax in order to avoid too much magic.
Eli
(*) And where I do care, I'd still enjoy them being generated automatically.
-- --Guido van Rossum (python.org/~guido)
Guido van Rossum guido@python.org wrote:
Please. Anything *except*
class Color(Enum): RED, BLUE, GREEN
And not this eiter:
class Color(Enum): RED BLUE GREEN
Is a new enum keyword still a possibility? To me that seems to be the cleanest way.
Stefan Krah
Forgive me, a lurker, but I wonder: how does an enum differ in usage from something like a Symbol from ruby, other than that an enum is required to be declared beforehand?
I'm definitely a python guy, but the idea of identifiers that are their own value interests me, and seems like it could have some overlap with the concept and usage of enums.
If there's not much difference in usage between enums and symbols apart from declaration, perhaps we could make the declaration optional and combine the concepts? This would certainly require parser changes.
Ryan
I don't know Ruby symbols, but if they are anything like Lisp symbols, they are completely different. Lisp symbols are interned strings -- Python just uses strings (and if they happen to be interned you get a modest speedup). This is for things like:
if hasattr(x, 'foo'): x.foo()
On Tue, Feb 12, 2013 at 1:55 PM, ryan@ryanhiebert.com wrote:
Forgive me, a lurker, but I wonder: how does an enum differ in usage from something like a Symbol from ruby, other than that an enum is required to be declared beforehand?
I'm definitely a python guy, but the idea of identifiers that are their own value interests me, and seems like it could have some overlap with the concept and usage of enums.
If there's not much difference in usage between enums and symbols apart from declaration, perhaps we could make the declaration optional and combine the concepts? This would certainly require parser changes.
Ryan
Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- --Guido van Rossum (python.org/~guido)
Thanks for that. I think that when I consider the cases that I don't like the idea of using strings, using a proper enum makes better sense anyway.
On Feb 12, 2013, at 1:58 PM, Guido van Rossum guido@python.org wrote:
I don't know Ruby symbols, but if they are anything like Lisp symbols, they are completely different. Lisp symbols are interned strings -- Python just uses strings (and if they happen to be interned you get a modest speedup). This is for things like:
if hasattr(x, 'foo'): x.foo()
On Tue, Feb 12, 2013 at 1:55 PM, ryan@ryanhiebert.com wrote:
Forgive me, a lurker, but I wonder: how does an enum differ in usage from something like a Symbol from ruby, other than that an enum is required to be declared beforehand?
I'm definitely a python guy, but the idea of identifiers that are their own value interests me, and seems like it could have some overlap with the concept and usage of enums.
If there's not much difference in usage between enums and symbols apart from declaration, perhaps we could make the declaration optional and combine the concepts? This would certainly require parser changes.
Ryan
Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- --Guido van Rossum (python.org/~guido)
2013/2/12 Stefan Krah stefan@bytereef.org
Guido van Rossum guido@python.org wrote:
Please. Anything *except*
class Color(Enum): RED, BLUE, GREEN
And not this eiter:
class Color(Enum): RED BLUE GREEN
Is a new enum keyword still a possibility? To me that seems to be the cleanest way.
I was just thinking the same. We don't like to have more syntax than necessary, but we should also not introduce too much magic...
On 13 February 2013 09:29, Jonathan Slenders jonathan@slenders.be wrote:
Is a new enum keyword still a possibility? To me that seems to be the
cleanest way.
I was just thinking the same. We don't like to have more syntax than necessary, but we should also not introduce too much magic...
That's my conclusion as well. To get a nice* enum with guaranteed semantics and no edge cases, I think it needs parser support.
* for my definition of "nice".
Tim Delaney
Just quickly thinking a little out of the box.
Suppose, that we added grammar for scheme-like symbols. (You know, these atomic identifiers, prefixed with a quote. I don't know much about scheme, but as I understand, they are just constants.)
In Python, the syntax could be similar, we could simply do in a global module scope:
sym symbol
which would translate to:
locals()['symbol'] = Symbol('symbol')
Where Symbol is a built-in that cannot change, which doesn't have a content, except for its name, and never equals anything but itself. From then on, we can access it through the name-binding 'symbol'
Then we could probably create enums, using the classes as we have:
class Colors: sym red sym green sym blue
There are probably some gaps here in my reasoning, but this could also work.
Cheers, Jonathan
2013/2/12 Tim Delaney timothy.c.delaney@gmail.com
On 13 February 2013 09:29, Jonathan Slenders jonathan@slenders.be wrote:
Is a new enum keyword still a possibility? To me that seems to be the
cleanest way.
I was just thinking the same. We don't like to have more syntax than necessary, but we should also not introduce too much magic...
That's my conclusion as well. To get a nice* enum with guaranteed semantics and no edge cases, I think it needs parser support.
- for my definition of "nice".
Tim Delaney
Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
Stefan Krah writes:
Guido van Rossum guido@python.org wrote:
Please. Anything *except*
class Color(Enum): RED, BLUE, GREEN
I'll take you at your word. But maybe you should stop reading now.<wink/>
Is a new enum keyword still a possibility? To me that seems to be the cleanest way.
If parser support were on the table, couldn't we avoid a new keyword by aping the Pascal syntax with
class Color(Enum) = [RED, GREEN, BLUE]
or something like that? I realize this is horrible because of the missing colon, and because availability of the syntax depends on the base class. Maybe it will suggest something to somebody, though. The base class seems to be needed to support variants like OrderedEnum and FlagEnum, as the implicit Enum
class Color = [RED, GREEN, BLUE]
can't disambiguate common use cases (ordered enums, or-able flags). Another possibility would be to allow the list of identifiers as the base class:
class Color([RED, GREEN, BLUE]): pass
I suppose this is better than the version using "=", which doesn't seem to allow explicit initialization of the enumerated ids, or operations on them, in the class body. Perhaps the Enum base class should be explicit:
class Color(Enum, [RED, GREEN, BLUE]): pass
In all cases the point of using lists instead of (implicit) tuples is to clearly guarantee order of evaluation to support OrderedEnum. Sets are out because FlagEnum doesn't need such support.
On 12 February 2013 19:29, Guido van Rossum guido@python.org wrote:
Please. Anything *except*
class Color(Enum): RED, BLUE, GREEN
And not this eiter:
class Color(Enum): RED BLUE GREEN
Just throwing in another syntax that is valid, requires no quotes and no magic - in case someone is interested in developing on it:
Colors = make(RED=..., GREEN=..., BLUE=...)