I noticed that the IntFlag enums VerifyFlags and Options from the ssl module are not continuous and contain aliases to (partially) absent members, i.e. "false" aliases.
This gives inconsistencies in flag iteration:
-
overshooting
VerifyFlags
from ssl import VerifyFlags
print(~VerifyFlags(0)) # common for "not no flags", i.e. all flags
# <VerifyFlags.VERIFY_CRL_CHECK_LEAF|VERIFY_X509_STRICT|VERIFY_ALLOW_PROXY_CERTS|VERIFY_X509_TRUSTED_FIRST|VERIFY_X509_PARTIAL_CHAIN|VERIFY_CRL_CHECK_CHAIN|491411: 1048575>
# with added `491411`
Options
from ssl import Options
print(~Options(0)) # common for "not no flags", i.e. all flags
# <Options.OP_LEGACY_SERVER_CONNECT|OP_ENABLE_KTLS|OP_IGNORE_UNEXPECTED_EOF|OP_NO_TICKET|OP_NO_COMPRESSION|OP_ENABLE_MIDDLEBOX_COMPAT|OP_CIPHER_SERVER_PREFERENCE|OP_NO_SSLv3|OP_NO_TLSv1|OP_NO_TLSv1_2|OP_NO_TLSv1_1|OP_NO_TLSv1_3|OP_NO_RENEGOTIATION|OP_ALL|28163875: 4294967295>
# with added `28163875`
-
false aliases
VerifyFlags
from ssl import VerifyFlags
print(list(VerifyFlags.VERIFY_CRL_CHECK_CHAIN)) # with value `12`
# [<VerifyFlags.VERIFY_CRL_CHECK_LEAF: 4>, None]
# member with value `8` is absent from `VerifyFlags`
Options
from ssl import Options
print(list(Options.OP_ALL))
# [None, None, None]
# no foundational members in `Options` at all
-
missing members due to being false aliases
VerifyFlags
from ssl import VerifyFlags
all_members = set(VerifyFlags.__members__.values())
iterated_members = set(VerifyFlags)
print(all_members - iterated_members)
# {<VerifyFlags.VERIFY_DEFAULT: 0>, <VerifyFlags.VERIFY_CRL_CHECK_CHAIN: 12>}
# value `0` is trivial, but `VERIFY_CRL_CHECK_CHAIN` actually needs to be standalone (see previous bullet point)
and consequently
from ssl import VerifyFlags
from functools import reduce
from operator import or_
all = reduce(or_, VerifyFlags) # actually not all flags
print(all)
# <VerifyFlags.VERIFY_CRL_CHECK_LEAF|VERIFY_X509_STRICT|VERIFY_ALLOW_PROXY_CERTS|VERIFY_X509_TRUSTED_FIRST|VERIFY_X509_PARTIAL_CHAIN: 557156>
# missing false alias `VERIFY_CRL_CHECK_CHAIN`
print(sum(set(VerifyFlags.__members__.values())))
# 557168
# missing the `VERIFY_CRL_CHECK_CHAIN` with value `12`
Options
from ssl import Options
all_members = set(Options.__members__.values())
iterated_members = set(Options)
print(all_members - iterated_members)
# {<Options.OP_NO_SSLv2: 0>, <Options.OP_ALL: 2147483728>}
# value `0` is trivial, but `OP_ALL` actually needs to be standalone (see previous bullet point)
and resulting implications analogous to VerifyFlags.
With that, enum.show_flag_values also cannot really be used anymore.
I found these related issues:
The behavior shown above kind of collides with the achievement for simplicity mentioned in #72212 - and also confused me heavily.
@tiran @ethanfurman What do you think?
Reactions are currently unavailable
I noticed that the IntFlag enums VerifyFlags and Options from the ssl module are not continuous and contain aliases to (partially) absent members, i.e. "false" aliases.
This gives inconsistencies in flag iteration:
overshooting
VerifyFlags
Options
false aliases
VerifyFlags
Options
missing members due to being false aliases
VerifyFlags
and consequently
Options
and resulting implications analogous to VerifyFlags.
With that, enum.show_flag_values also cannot really be used anymore.
I found these related issues:
The behavior shown above kind of collides with the achievement for simplicity mentioned in #72212 - and also confused me heavily.
@tiran @ethanfurman What do you think?