cpython: 365b5e6163a6 (original) (raw)
Mercurial > cpython
changeset 101662:365b5e6163a6
signal, socket, and ssl module IntEnum constant name lookups now return a consistent name for values having multiple names. Ex: signal.Signals(6) now refers to itself as signal.SIGALRM rather than flipping between that and signal.SIGIOT based on the interpreter's hash randomization seed. This helps finish issue27167. [#27167]
Gregory P. Smith greg@krypto.org [Google Inc.] | |
---|---|
date | Fri, 03 Jun 2016 19:14:52 +0000 |
parents | 050e5f803999 |
children | 8b6b6add8e47 |
files | Lib/enum.py Lib/test/test_enum.py Misc/NEWS |
diffstat | 3 files changed, 49 insertions(+), 2 deletions(-)[+] [-] Lib/enum.py 10 Lib/test/test_enum.py 36 Misc/NEWS 5 |
line wrap: on
line diff
--- a/Lib/enum.py +++ b/Lib/enum.py @@ -550,8 +550,14 @@ class Enum(metaclass=EnumMeta): source = vars(source) else: source = module_globals
members = {name: value for name, value in source.items()[](#l1.7)
if filter(name)}[](#l1.8)
# We use an OrderedDict of sorted source keys so that the[](#l1.9)
# _value2member_map is populated in the same order every time[](#l1.10)
# for a consistent reverse mapping of number to name when there[](#l1.11)
# are multiple names for the same number rather than varying[](#l1.12)
# between runs due to hash randomization of the module dictionary.[](#l1.13)
members = OrderedDict((name, source[name])[](#l1.14)
for name in sorted(source.keys())[](#l1.15)
if filter(name))[](#l1.16) cls = cls(name, members, module=module)[](#l1.17) cls.__reduce_ex__ = _reduce_ex_by_name[](#l1.18) module_globals.update(cls.__members__)[](#l1.19)
--- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -1768,5 +1768,41 @@ class MiscTestCase(unittest.TestCase): support.check__all__(self, enum) +# These are unordered here on purpose to ensure that declaration order +# makes no difference. +CONVERT_TEST_NAME_D = 5 +CONVERT_TEST_NAME_C = 5 +CONVERT_TEST_NAME_B = 5 +CONVERT_TEST_NAME_A = 5 # This one should sort first. +CONVERT_TEST_NAME_E = 5 +CONVERT_TEST_NAME_F = 5 + +class TestIntEnumConvert(unittest.TestCase):
- def test_convert_value_lookup_priority(self):
test_type = enum.IntEnum._convert([](#l2.18)
'UnittestConvert', 'test.test_enum',[](#l2.19)
filter=lambda x: x.startswith('CONVERT_TEST_'))[](#l2.20)
# We don't want the reverse lookup value to vary when there are[](#l2.21)
# multiple possible names for a given value. It should always[](#l2.22)
# report the first lexigraphical name in that case.[](#l2.23)
self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')[](#l2.24)
- def test_convert(self):
test_type = enum.IntEnum._convert([](#l2.27)
'UnittestConvert', 'test.test_enum',[](#l2.28)
filter=lambda x: x.startswith('CONVERT_TEST_'))[](#l2.29)
# Ensure that test_type has all of the desired names and values.[](#l2.30)
self.assertEqual(test_type.CONVERT_TEST_NAME_F,[](#l2.31)
test_type.CONVERT_TEST_NAME_A)[](#l2.32)
self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)[](#l2.33)
self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)[](#l2.34)
self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)[](#l2.35)
self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)[](#l2.36)
# Ensure that test_type only picked up names matching the filter.[](#l2.37)
self.assertEqual([name for name in dir(test_type)[](#l2.38)
if name[0:2] not in ('CO', '__')],[](#l2.39)
[], msg='Names other than CONVERT_TEST_* found.')[](#l2.40)
+ + if name == 'main': unittest.main()
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,11 @@ Core and Builtins Library ------- +- signal, socket, and ssl module IntEnum constant name lookups now return a