mirror of
https://github.com/python/cpython.git
synced 2025-08-23 18:24:46 +00:00
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.
This commit is contained in:
parent
16931c3559
commit
6f20bd6063
3 changed files with 49 additions and 2 deletions
10
Lib/enum.py
10
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()
|
||||
if filter(name)}
|
||||
# We use an OrderedDict of sorted source keys so that the
|
||||
# _value2member_map is populated in the same order every time
|
||||
# for a consistent reverse mapping of number to name when there
|
||||
# are multiple names for the same number rather than varying
|
||||
# between runs due to hash randomization of the module dictionary.
|
||||
members = OrderedDict((name, source[name])
|
||||
for name in sorted(source.keys())
|
||||
if filter(name))
|
||||
cls = cls(name, members, module=module)
|
||||
cls.__reduce_ex__ = _reduce_ex_by_name
|
||||
module_globals.update(cls.__members__)
|
||||
|
|
|
@ -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(
|
||||
'UnittestConvert', 'test.test_enum',
|
||||
filter=lambda x: x.startswith('CONVERT_TEST_'))
|
||||
# We don't want the reverse lookup value to vary when there are
|
||||
# multiple possible names for a given value. It should always
|
||||
# report the first lexigraphical name in that case.
|
||||
self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
|
||||
|
||||
def test_convert(self):
|
||||
test_type = enum.IntEnum._convert(
|
||||
'UnittestConvert', 'test.test_enum',
|
||||
filter=lambda x: x.startswith('CONVERT_TEST_'))
|
||||
# Ensure that test_type has all of the desired names and values.
|
||||
self.assertEqual(test_type.CONVERT_TEST_NAME_F,
|
||||
test_type.CONVERT_TEST_NAME_A)
|
||||
self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
|
||||
self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
|
||||
self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
|
||||
self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
|
||||
# Ensure that test_type only picked up names matching the filter.
|
||||
self.assertEqual([name for name in dir(test_type)
|
||||
if name[0:2] not in ('CO', '__')],
|
||||
[], msg='Names other than CONVERT_TEST_* found.')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -27,6 +27,11 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- 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.
|
||||
|
||||
- Issue #27167: Clarify the subprocess.CalledProcessError error message text
|
||||
when the child process died due to a signal.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue