bpo-38045: Improve the performance of _decompose() in enum.py (GH-16483)

* Improve the performance of _decompose() in enum.py

Co-Authored-By: Brandt Bucher <brandtbucher@gmail.com>
This commit is contained in:
HongWeipeng 2019-11-27 06:36:02 +08:00 committed by Ethan Furman
parent e563a155be
commit 0b41a922f9
2 changed files with 11 additions and 23 deletions

View File

@ -861,28 +861,20 @@ def _decompose(flag, value):
# _decompose is only called if the value is not named # _decompose is only called if the value is not named
not_covered = value not_covered = value
negative = value < 0 negative = value < 0
# issue29167: wrap accesses to _value2member_map_ in a list to avoid race
# conditions between iterating over it and having more pseudo-
# members added to it
if negative:
# only check for named flags
flags_to_check = [
(m, v)
for v, m in list(flag._value2member_map_.items())
if m.name is not None
]
else:
# check for named flags and powers-of-two flags
flags_to_check = [
(m, v)
for v, m in list(flag._value2member_map_.items())
if m.name is not None or _power_of_two(v)
]
members = [] members = []
for member, member_value in flags_to_check: for member in flag:
member_value = member.value
if member_value and member_value & value == member_value: if member_value and member_value & value == member_value:
members.append(member) members.append(member)
not_covered &= ~member_value not_covered &= ~member_value
if not negative:
tmp = not_covered
while tmp:
flag_value = 2 ** _high_bit(tmp)
if flag_value in flag._value2member_map_:
members.append(flag._value2member_map_[flag_value])
not_covered &= ~flag_value
tmp &= ~flag_value
if not members and value in flag._value2member_map_: if not members and value in flag._value2member_map_:
members.append(flag._value2member_map_[value]) members.append(flag._value2member_map_[value])
members.sort(key=lambda m: m._value_, reverse=True) members.sort(key=lambda m: m._value_, reverse=True)
@ -890,8 +882,3 @@ def _decompose(flag, value):
# we have the breakdown, don't need the value member itself # we have the breakdown, don't need the value member itself
members.pop(0) members.pop(0)
return members, not_covered return members, not_covered
def _power_of_two(value):
if value < 1:
return False
return value == 2 ** _high_bit(value)

View File

@ -0,0 +1 @@
Improve the performance of :func:`enum._decompose` in :mod:`enum`. Patch by hongweipeng.