Repository navigation
Inverted enum.Flag #107538
Description
Activity
Cannot reproduce on current main. Seems that this case fixed by #105542
It's not failing, and the first three work correctly, but Y.d should be an alias for Y.b, not -2.
@ethanfurman may be you are right but I find following quite confusing:
~a changed while a remaining the same
class X(enum.Flag):
a = enum.auto()
b = enum.auto()
c = enum.auto()>>> list(X)
[<X.a: 1>, <X.b: 2>, <X.c: 4>]
>>> ~X.a
<X.b|c: 6>
>>> list(~X.a)
[<X.b: 2>, <X.c: 4>]class Y(enum.Flag):
a = enum.auto()
b = enum.auto()
c = enum.auto()
d = ~a>>> list(Y)
[<Y.a: 1>, <Y.b: 2>, <Y.c: 4>]
>>> ~Y.a
<Y.d: -2>
>>> list(~Y.a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/enum.py", line 1482, in __iter__
yield from self._iter_member_(self._value_)
File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/enum.py", line 1359, in _iter_member_by_value_
for val in _iter_bits_lsb(value & cls._flag_mask_):
File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/enum.py", line 122, in _iter_bits_lsb
raise ValueError('%r is not a positive integer' % original)
ValueError: -2 is not a positive integer@GrafLearnt, in your latest example, d should be 6 (i.e. b|c). Thanks for the reminder, this will be a more involved fix than I was originally thinking.
@ethanfurman d = b | c will work perfectly fine until someone add new member without adding it to d
Well, presumably, if they write d = b|c that's what they want; while d = ~a means every member that's not a.
@ethanfurman
I love it:
class X(enum.Flag):
a = enum.auto()
b = enum.auto()
c = enum.auto()>>> ~X.a
<X.b|c: 6>But this doesn't look correct to me:
class Y(enum.Flag):
a = enum.auto()
b = enum.auto()
c = enum.auto()
d = ~a>>> ~Y.a
<Y.d: -2>Kindly ask to clarify if I am allowed to define inverted.
It brakes iteration of ~Y.a
Also I get following:
>>> ~Y.b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/enum.py", line 1542, in __invert__
self._inverted_ = self.__class__(self._flag_mask_ ^ self._value_)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/enum.py", line 711, in __call__
return cls.__new__(cls, value)
^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/enum.py", line 1136, in __new__
raise exc
File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/enum.py", line 1113, in __new__
result = cls._missing_(value)
^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/enum.py", line 1399, in _missing_
raise ValueError(
ValueError: <flag 'Y'> invalid value -3
given 0b1 01
allowed 0b1 11Defining ~a as a member is what is not working correctly.
I believe that last error is fixed in 3.11.5.
@ethanfurman is defining inverted restricted or will be fixed?
Works fine in Python 3.10.12:
>>> ~Y.b
<Y.c|a: 5>Will be fixed.
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Bug report
Checklist
A clear and concise description of the bug
Adding inverted option to enum.Flag brakes logic of enum.
I assume it caused by ambiguous implementation of
bitwise NOTin Flag which processes ~value option different inside class scope and outside class scope unlikebitwise ORTraceback:
Your environment
Linked PRs