Issue24840
Created on 2015-08-11 00:09 by novas0x2a, last changed 2022-04-11 14:58 by admin. This issue is now closed.
| Files | ||||
|---|---|---|---|---|
| File name | Uploaded | Description | Edit | |
| issue24840.master.patch | novas0x2a, 2015-08-11 00:18 | Patch for master/3.6 that also applies cleanly to 3.5 and 3.4 | review | |
| Messages (16) | |||
|---|---|---|---|
| msg248378 - (view) | Author: Mike Lundy (novas0x2a) * | Date: 2015-08-11 00:09 | |
There's a slightly odd edge case which can be summarized as follows:
====================
from enum import Enum
class Bool(Enum):
Yep = True
Nope = False
for value in Bool:
print('%18r is %r' % (value, bool(value)))
====================
output:
====================
<Bool.Yep: True> is True
<Bool.Nope: False> is True
====================
This isn't really a big deal, but can be made better with the attached patch. I can't think of any odd consequences this might cause, but others may know better.
|
|||
| msg248379 - (view) | Author: R. David Murray (r.david.murray) * ![]() |
Date: 2015-08-11 00:13 | |
No patch is attached. |
|||
| msg248380 - (view) | Author: Mike Lundy (novas0x2a) * | Date: 2015-08-11 00:18 | |
@r.david.murray man you're fast :) Sorry, realized I forgot to actually run the tests for 3.5 and 3.4, I'd only run them for master (I've now run them for 3.5 and 3.4 now, too). |
|||
| msg248381 - (view) | Author: Mike Lundy (novas0x2a) * | Date: 2015-08-11 00:20 | |
(I should note that I just recently signed the contributor agreement, not that this a particularly complex fix, but it hasn't propagated to my profile yet). |
|||
| msg248391 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * ![]() |
Date: 2015-08-11 05:41 | |
This looks to me as very special case. Enum doesn't delegates the __bool__ method as well as it doesn't delegates __float__, __lt__, __len__, etc. It is left to user to add these methods if needed. It is easy to add the __bool__ method to user enum. In your case you also can inherit from IntEnum. >>> class Bool(IntEnum): ... Yep = True ... Nope = False ... >>> bool(Bool.Yep) True >>> bool(Bool.Nope) False |
|||
| msg248394 - (view) | Author: Mike Lundy (novas0x2a) * | Date: 2015-08-11 06:15 | |
@serhiy.storchaka: It's somewhat of a special case, to be sure. However, I do think it's justified to put it into the base (rather than a user type) for three reasons:
1) It makes IntEnum and Enum consistent. IntEnum actually already handles this case just fine, because it's an int and therefore already supports __bool__ correctly. It feels odd that changing the storage format from an IntEnum to a Enum should break the logic- correctly used, the actual enum values should never matter. This small change just brings them into line.
2) It is less surprising than the current case; I discovered this when I did something like the Enum.Nope case here, and I naively used the enum in an if statement, assuming that the value would control the __bool__ value. (This was caught by my tests, of course, but the point remains that I wrote the code). Normally in python, you'd expect the default bool conversion to be unconditionally True, but enums aren't really normal objects; for any use case for which there is a default noop value, you'd generally put that value _into_ the enum:
class FilterType(Enum):
NONE = None
SUB = 'Sub'
UP = 'Up'
...
3) It's not logically inconsistent with the idea of Enums. The other dunder methods you mention aren't consistent with the concept: __float__ (enum values aren't generally numbers except as an implementation detail), __lt__ (enums aren't generally ordered), __len__ (enums aren't generally containers). The one thing an enum does have is a value, and it feels consistent to me to check the truthiness of an enum without having to reach into the .value to do so.
Anyway, that's my case for inclusion!
|
|||
| msg248408 - (view) | Author: R. David Murray (r.david.murray) * ![]() |
Date: 2015-08-11 14:59 | |
I agree that it seems odd that testing a 'value' that is false for its truth value would return True. It is surprising, even if it is an edge case. |
|||
| msg248442 - (view) | Author: Ethan Furman (ethan.furman) * ![]() |
Date: 2015-08-12 01:51 | |
Thanks for finding that, Mike. I'll review and merge in the next few days. |
|||
| msg250932 - (view) | Author: Roundup Robot (python-dev) ![]() |
Date: 2015-09-18 04:49 | |
New changeset 87a9dff5106c by Ethan Furman in branch 'default': Close issue24840: Enum._value_ is queried for bool(); original patch by Mike Lundy https://hg.python.org/cpython/rev/87a9dff5106c |
|||
| msg256869 - (view) | Author: Gregory P. Smith (gregory.p.smith) * ![]() |
Date: 2015-12-22 21:23 | |
This change breaks existing code that is relying on the behavior of the enum API as shipped in 3.4 and 3.5. Please do NOT do this. Worse, you've landed this change in a "stable" release of the enum34 "backport" module (1.1.1) despite it never having been released as a stable Python API. Please do not let *the backport* get ahead of the latest stable released Python API. https://bitbucket.org/stoneleaf/enum34/issues/10/versions-of-enum34-111-break-support-for |
|||
| msg256872 - (view) | Author: Ethan Furman (ethan.furman) * ![]() |
Date: 2015-12-22 22:11 | |
The enum34 backport has been fixed to not have 3.6 only features (assuming the __bool__ change was the only one). Was that your only objection, or do you not want this change in 3.6 either? |
|||
| msg256875 - (view) | Author: Gregory P. Smith (gregory.p.smith) * ![]() |
Date: 2015-12-22 22:22 | |
lets collect some examples of where it causes problems (someone ran into the problem at work which is why i hunted down this bugs.python.org issue) before deciding. If it stays in, it needs a mention in both Misc/NEWS and What's New as it will require some people to test and update their code for 3.6. Examples will let us decide which way to go. |
|||
| msg258328 - (view) | Author: Ethan Furman (ethan.furman) * ![]() |
Date: 2016-01-15 21:17 | |
Mike, my apologies. In the future I'll make sure and read the docs before I go through with changes. In the docs (https://www.python.org/dev/peps/pep-0435/#id35): The reason for defaulting to 1 as the starting number and not 0 is that 0 is False in a boolean sense, but enum members all evaluate to True. From a newer discussion on Python Ideas and Python Dev: Barry Warsaw: I think in general enums are primarily a symbolic value and don't have truthiness. It's also so easy to override when you define the enum that it's not worth changing the current behavior. Guido van Rossum: Honestly I think it's too late to change. The proposal to change plain Enums to False when their value is zero (or falsey) would be a huge backward incompatibility. I don't think there's a reasonable path forward, and also don't think there's a big reason to regret the current semantics. Thank you, Gregory, for catching that. |
|||
| msg258339 - (view) | Author: Ethan Furman (ethan.furman) * ![]() |
Date: 2016-01-15 23:05 | |
New changeset: 52dc28ee3c88 |
|||
| msg258340 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * ![]() |
Date: 2016-01-15 23:18 | |
I think it is better to use "value" instead of "_value_" in the documentation. |
|||
| msg258407 - (view) | Author: Ethan Furman (ethan.furman) * ![]() |
Date: 2016-01-16 20:42 | |
New changeset e4c22eadc25c: use public 'value' |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022-04-11 14:58:19 | admin | set | github: 69028 |
| 2016-01-16 20:42:03 | ethan.furman | set | messages: + msg258407 |
| 2016-01-15 23:18:00 | serhiy.storchaka | set | messages: + msg258340 |
| 2016-01-15 23:05:47 | ethan.furman | set | status: open -> closed resolution: rejected messages: + msg258339 |
| 2016-01-15 21:17:27 | ethan.furman | set | messages: + msg258328 |
| 2015-12-22 22:22:11 | gregory.p.smith | set | messages: + msg256875 |
| 2015-12-22 22:11:48 | ethan.furman | set | messages: + msg256872 |
| 2015-12-22 21:23:58 | gregory.p.smith | set | status: closed -> open versions: + Python 3.6 nosy: + gregory.p.smith messages: + msg256869 resolution: fixed -> (no value) |
| 2015-09-18 04:49:36 | python-dev | set | status: open -> closed nosy:
+ python-dev resolution: fixed |
| 2015-08-12 01:51:32 | ethan.furman | set | assignee: ethan.furman messages: + msg248442 stage: patch review |
| 2015-08-11 14:59:13 | r.david.murray | set | messages: + msg248408 |
| 2015-08-11 06:15:25 | novas0x2a | set | messages: + msg248394 |
| 2015-08-11 05:41:14 | serhiy.storchaka | set | nosy:
+ serhiy.storchaka messages: + msg248391 |
| 2015-08-11 00:20:36 | novas0x2a | set | messages: + msg248381 |
| 2015-08-11 00:18:49 | novas0x2a | set | files:
+ issue24840.master.patch keywords: + patch messages: + msg248380 |
| 2015-08-11 00:16:59 | yselivanov | set | nosy:
+ ethan.furman |
| 2015-08-11 00:13:49 | r.david.murray | set | nosy:
+ r.david.murray messages: + msg248379 |
| 2015-08-11 00:09:32 | novas0x2a | create | |

