summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHongWeipeng <961365124@qq.com>2019-11-26 22:36:02 (GMT)
committerEthan Furman <ethan@stoneleaf.us>2019-11-26 22:36:02 (GMT)
commit0b41a922f95f62b620d5a197b9f2ed8e4bb70730 (patch)
treed9db36ebe3acbb32ae944e5cffd291232a1e0687
parente563a155be60fc0757914f87c8138f10de00bb16 (diff)
downloadcpython-0b41a922f95f62b620d5a197b9f2ed8e4bb70730.zip
cpython-0b41a922f95f62b620d5a197b9f2ed8e4bb70730.tar.gz
cpython-0b41a922f95f62b620d5a197b9f2ed8e4bb70730.tar.bz2
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>
-rw-r--r--Lib/enum.py33
-rw-r--r--Misc/NEWS.d/next/Library/2019-09-30-12-09-41.bpo-38045.VDRtd3.rst1
2 files changed, 11 insertions, 23 deletions
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.