From 0b41a922f95f62b620d5a197b9f2ed8e4bb70730 Mon Sep 17 00:00:00 2001 From: HongWeipeng <961365124@qq.com> Date: Wed, 27 Nov 2019 06:36:02 +0800 Subject: 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 --- Lib/enum.py | 33 +++++++--------------- .../2019-09-30-12-09-41.bpo-38045.VDRtd3.rst | 1 + 2 files changed, 11 insertions(+), 23 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-09-30-12-09-41.bpo-38045.VDRtd3.rst diff --git a/Lib/enum.py b/Lib/enum.py index 06f42a9..0be1b60 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -861,28 +861,20 @@ def _decompose(flag, value): # _decompose is only called if the value is not named not_covered = value 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 = [] - 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: members.append(member) 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_: members.append(flag._value2member_map_[value]) 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 members.pop(0) return members, not_covered - -def _power_of_two(value): - if value < 1: - return False - return value == 2 ** _high_bit(value) diff --git a/Misc/NEWS.d/next/Library/2019-09-30-12-09-41.bpo-38045.VDRtd3.rst b/Misc/NEWS.d/next/Library/2019-09-30-12-09-41.bpo-38045.VDRtd3.rst new file mode 100644 index 0000000..e7e515f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-09-30-12-09-41.bpo-38045.VDRtd3.rst @@ -0,0 +1 @@ +Improve the performance of :func:`enum._decompose` in :mod:`enum`. Patch by hongweipeng. -- cgit v0.12