bpo-38250: [Enum] single-bit flags are canonical by ethanfurman · Pull Request #24215 · python/cpython

Conversation

ethanfurman

Flag members are now divided by one-bit verses multi-bit, with multi-bit
being treated as aliases.  Iterating over a flag only returns the
contained single-bit flags.

repr() and str() now only show the Flags, not extra integer values; any
extra integer values are either discarded (CONFORM), turned into
``int``s (EJECT) or treated as errors (STRICT).  Flag classes can
specify which of those three behaviors is desired:

    >>> class Test(Flag, boundary=CONFORM):
    ...     ONE = 1
    ...     TWO = 2
    ...
    >>> Test(5)
    <Test.ONE: 1>
some flag sets, such as ``ssl.Options`` are incomplete/inconsistent;
using KEEP allows those flags to exist, and have useful repr()s, etc.

also, add ``_inverted_`` attribute to Flag members to significantly
speed up that operation.
repr() has been modified to support as closely as possible its previous
output; the big difference is that inverted flags cannot be output as
before because the inversion operation now always returns the comparable
positive result; i.e.

   re.A|re.I|re.M|re.S is ~(re.L|re.U|re.S|re.T|re.DEBUG)

in both of the above terms, the ``value`` is 282.

re's tests have been updated to reflect the modifications to repr().

belm0

belm0

hongweipeng

Iteration is now in member definition order.  If member definition order
matches increasing value order, then a more efficient method of flag
decomposition is used; otherwise, sort() is called on the results of
that method to get definition order.

belm0

new composite members aren't always added to _value2member_map_ -- this
ensures the operation succeeds

belm0

auto() for flags returns the first power of two not used

_order_ has any names that are aliases removed before checking against
_member_names_

adorilson pushed a commit to adorilson/cpython that referenced this pull request

Mar 13, 2021
Flag members are now divided by one-bit verses multi-bit, with multi-bit being treated as aliases. Iterating over a flag only returns the contained single-bit flags.

Iterating, repr(), and str() show members in definition order.

When constructing combined-member flags, any extra integer values are either discarded (CONFORM), turned into ints (EJECT) or treated as errors (STRICT). Flag classes can specify which of those three behaviors is desired:

>>> class Test(Flag, boundary=CONFORM):
...     ONE = 1
...     TWO = 2
...
>>> Test(5)
<Test.ONE: 1>

Besides the three above behaviors, there is also KEEP, which should not be used unless necessary -- for example, _convert_ specifies KEEP as there are flag sets in the stdlib that are incomplete and/or inconsistent (e.g. ssl.Options). KEEP will, as the name suggests, keep all bits; however, iterating over a flag with extra bits will only return the canonical flags contained, not the extra bits.

Iteration is now in member definition order.  If member definition order
matches increasing value order, then a more efficient method of flag
decomposition is used; otherwise, sort() is called on the results of
that method to get definition order.


``re`` module:

repr() has been modified to support as closely as possible its previous
output; the big difference is that inverted flags cannot be output as
before because the inversion operation now always returns the comparable
positive result; i.e.

   re.A|re.I|re.M|re.S is ~(re.L|re.U|re.S|re.T|re.DEBUG)

in both of the above terms, the ``value`` is 282.

re's tests have been updated to reflect the modifications to repr().

tacaswell added a commit to tacaswell/ophyd that referenced this pull request

May 4, 2021
Python 3.10 makes a number of changes to Enum and its sub-classes.  Under
the new default behavior of IntFlag the fact that we have `0b1b1` as a
flag, but not `0b100` is considered a class definition time error (preventing
import of ophyd).

This opts back into allowing our (unorthodox) definition to import again and
hides the new features behind a version gate.

python/cpython#24215

tacaswell added a commit to tacaswell/ophyd that referenced this pull request

Apr 5, 2022
Python 3.10 makes a number of changes to Enum and its sub-classes.  Under
the new default behavior of IntFlag the fact that we have `0b1b1` as a
flag, but not `0b100` is considered a class definition time error (preventing
import of ophyd).

This opts back into allowing our (unorthodox) definition to import again and
hides the new features behind a version gate.

python/cpython#24215