summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorEthan Furman <ethan@stoneleaf.us>2021-03-31 04:17:26 (GMT)
committerGitHub <noreply@github.com>2021-03-31 04:17:26 (GMT)
commitb775106d940e3d77c8af7967545bb9a5b7b162df (patch)
treea5146740d7fab61a70bf410e4f348a9525cb1fd4 /Lib
parent51a85ddce8b336addcb61b96f04c9c5edef07296 (diff)
downloadcpython-b775106d940e3d77c8af7967545bb9a5b7b162df.zip
cpython-b775106d940e3d77c8af7967545bb9a5b7b162df.tar.gz
cpython-b775106d940e3d77c8af7967545bb9a5b7b162df.tar.bz2
bpo-40066: Enum: modify `repr()` and `str()` (GH-22392)
* Enum: streamline repr() and str(); improve docs - repr() is now ``enum_class.member_name`` - stdlib global enums are ``module_name.member_name`` - str() is now ``member_name`` - add HOW-TO section for ``Enum`` - change main documentation to be an API reference
Diffstat (limited to 'Lib')
-rw-r--r--Lib/enum.py86
-rw-r--r--Lib/inspect.py3
-rw-r--r--Lib/plistlib.py3
-rw-r--r--Lib/re.py17
-rw-r--r--Lib/test/test_enum.py267
-rw-r--r--Lib/test/test_pydoc.py2
-rw-r--r--Lib/test/test_signal.py2
-rwxr-xr-xLib/test/test_socket.py8
-rw-r--r--Lib/test/test_ssl.py2
-rw-r--r--Lib/test/test_unicode.py8
10 files changed, 228 insertions, 170 deletions
diff --git a/Lib/enum.py b/Lib/enum.py
index 84c7b0d..f31779b 100644
--- a/Lib/enum.py
+++ b/Lib/enum.py
@@ -4,17 +4,18 @@ from builtins import property as _bltin_property, bin as _bltin_bin
__all__ = [
- 'EnumMeta',
+ 'EnumType', 'EnumMeta',
'Enum', 'IntEnum', 'StrEnum', 'Flag', 'IntFlag',
'auto', 'unique',
'property',
'FlagBoundary', 'STRICT', 'CONFORM', 'EJECT', 'KEEP',
+ 'global_flag_repr', 'global_enum_repr', 'global_enum',
]
# Dummy value for Enum and Flag as there are explicit checks for them
# before they have been created.
-# This is also why there are checks in EnumMeta like `if Enum is not None`
+# This is also why there are checks in EnumType like `if Enum is not None`
Enum = Flag = EJECT = None
def _is_descriptor(obj):
@@ -285,7 +286,7 @@ class _EnumDict(dict):
"""
Track enum member order and ensure member names are not reused.
- EnumMeta will use the names found in self._member_names as the
+ EnumType will use the names found in self._member_names as the
enumeration member names.
"""
def __init__(self):
@@ -321,7 +322,8 @@ class _EnumDict(dict):
# check if members already defined as auto()
if self._auto_called:
raise TypeError("_generate_next_value_ must be defined before members")
- setattr(self, '_generate_next_value', value)
+ _gnv = value.__func__ if isinstance(value, staticmethod) else value
+ setattr(self, '_generate_next_value', _gnv)
elif key == '_ignore_':
if isinstance(value, str):
value = value.replace(',',' ').split()
@@ -368,7 +370,7 @@ class _EnumDict(dict):
self[name] = value
-class EnumMeta(type):
+class EnumType(type):
"""
Metaclass for Enum
"""
@@ -756,9 +758,9 @@ class EnumMeta(type):
# module;
# also, replace the __reduce_ex__ method so unpickling works in
# previous Python versions
- module_globals = vars(sys.modules[module])
+ module_globals = sys.modules[module].__dict__
if source:
- source = vars(source)
+ source = source.__dict__
else:
source = module_globals
# _value2member_map_ is populated in the same order every time
@@ -776,7 +778,7 @@ class EnumMeta(type):
members.sort(key=lambda t: t[0])
cls = cls(name, members, module=module, boundary=boundary or KEEP)
cls.__reduce_ex__ = _reduce_ex_by_name
- module_globals.update(cls.__members__)
+ global_enum(cls)
module_globals[name] = cls
return cls
@@ -881,9 +883,10 @@ class EnumMeta(type):
else:
use_args = True
return __new__, save_new, use_args
+EnumMeta = EnumType
-class Enum(metaclass=EnumMeta):
+class Enum(metaclass=EnumType):
"""
Generic enumeration.
@@ -958,11 +961,10 @@ class Enum(metaclass=EnumMeta):
return None
def __repr__(self):
- return "<%s.%s: %r>" % (
- self.__class__.__name__, self._name_, self._value_)
+ return "%s.%s" % ( self.__class__.__name__, self._name_)
def __str__(self):
- return "%s.%s" % (self.__class__.__name__, self._name_)
+ return "%s" % (self._name_, )
def __dir__(self):
"""
@@ -1220,19 +1222,28 @@ class Flag(Enum, boundary=STRICT):
return self._value_.bit_count()
def __repr__(self):
- cls = self.__class__
- if self._name_ is not None:
- return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_)
+ cls_name = self.__class__.__name__
+ if self._name_ is None:
+ return "0x%x" % (self._value_, )
+ if _is_single_bit(self._value_):
+ return '%s.%s' % (cls_name, self._name_)
+ if self._boundary_ is not FlagBoundary.KEEP:
+ return '%s.' % cls_name + ('|%s.' % cls_name).join(self.name.split('|'))
else:
- # only zero is unnamed by default
- return '<%s: %r>' % (cls.__name__, self._value_)
+ name = []
+ for n in self._name_.split('|'):
+ if n.startswith('0'):
+ name.append(n)
+ else:
+ name.append('%s.%s' % (cls_name, n))
+ return '|'.join(name)
def __str__(self):
cls = self.__class__
- if self._name_ is not None:
- return '%s.%s' % (cls.__name__, self._name_)
+ if self._name_ is None:
+ return '%s(%x)' % (cls.__name__, self._value_)
else:
- return '%s(%s)' % (cls.__name__, self._value_)
+ return self._name_
def __bool__(self):
return bool(self._value_)
@@ -1329,3 +1340,38 @@ def _power_of_two(value):
if value < 1:
return False
return value == 2 ** _high_bit(value)
+
+def global_enum_repr(self):
+ return '%s.%s' % (self.__class__.__module__, self._name_)
+
+def global_flag_repr(self):
+ module = self.__class__.__module__
+ cls_name = self.__class__.__name__
+ if self._name_ is None:
+ return "%x" % (module, cls_name, self._value_)
+ if _is_single_bit(self):
+ return '%s.%s' % (module, self._name_)
+ if self._boundary_ is not FlagBoundary.KEEP:
+ return module + module.join(self.name.split('|'))
+ else:
+ name = []
+ for n in self._name_.split('|'):
+ if n.startswith('0'):
+ name.append(n)
+ else:
+ name.append('%s.%s' % (module, n))
+ return '|'.join(name)
+
+
+def global_enum(cls):
+ """
+ decorator that makes the repr() of an enum member reference its module
+ instead of its class; also exports all members to the enum's module's
+ global namespace
+ """
+ if issubclass(cls, Flag):
+ cls.__repr__ = global_flag_repr
+ else:
+ cls.__repr__ = global_enum_repr
+ sys.modules[cls.__module__].__dict__.update(cls.__members__)
+ return cls
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 1f2cdeb..d6d2ce6 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -2455,9 +2455,6 @@ class _ParameterKind(enum.IntEnum):
KEYWORD_ONLY = 3
VAR_KEYWORD = 4
- def __str__(self):
- return self._name_
-
@property
def description(self):
return _PARAM_NAME_MAPPING[self]
diff --git a/Lib/plistlib.py b/Lib/plistlib.py
index 2eeebe4..5772efd 100644
--- a/Lib/plistlib.py
+++ b/Lib/plistlib.py
@@ -61,8 +61,7 @@ import struct
from xml.parsers.expat import ParserCreate
-PlistFormat = enum.Enum('PlistFormat', 'FMT_XML FMT_BINARY', module=__name__)
-globals().update(PlistFormat.__members__)
+PlistFormat = enum.global_enum(enum.Enum('PlistFormat', 'FMT_XML FMT_BINARY', module=__name__))
class UID:
diff --git a/Lib/re.py b/Lib/re.py
index a39ff04..5e40c7b 100644
--- a/Lib/re.py
+++ b/Lib/re.py
@@ -142,6 +142,7 @@ __all__ = [
__version__ = "2.2.1"
+@enum.global_enum
class RegexFlag(enum.IntFlag, boundary=enum.KEEP):
ASCII = A = sre_compile.SRE_FLAG_ASCII # assume ascii "locale"
IGNORECASE = I = sre_compile.SRE_FLAG_IGNORECASE # ignore case
@@ -154,22 +155,6 @@ class RegexFlag(enum.IntFlag, boundary=enum.KEEP):
TEMPLATE = T = sre_compile.SRE_FLAG_TEMPLATE # disable backtracking
DEBUG = sre_compile.SRE_FLAG_DEBUG # dump pattern after compilation
- def __repr__(self):
- res = ''
- if self._name_:
- member_names = self._name_.split('|')
- constant = None
- if member_names[-1].startswith('0x'):
- constant = member_names.pop()
- res = 're.' + '|re.'.join(member_names)
- if constant:
- res += '|%s' % constant
- return res
-
- __str__ = object.__str__
-
-globals().update(RegexFlag.__members__)
-
# sre exception
error = sre_compile.error
diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py
index 69392e0..6002cd8 100644
--- a/Lib/test/test_enum.py
+++ b/Lib/test/test_enum.py
@@ -7,7 +7,7 @@ import sys
import unittest
import threading
from collections import OrderedDict
-from enum import Enum, IntEnum, StrEnum, EnumMeta, Flag, IntFlag, unique, auto
+from enum import Enum, IntEnum, StrEnum, EnumType, Flag, IntFlag, unique, auto
from enum import STRICT, CONFORM, EJECT, KEEP
from io import StringIO
from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
@@ -262,11 +262,8 @@ class TestEnum(unittest.TestCase):
self.assertIn(e, Season)
self.assertIs(type(e), Season)
self.assertIsInstance(e, Season)
- self.assertEqual(str(e), 'Season.' + season)
- self.assertEqual(
- repr(e),
- '<Season.{0}: {1}>'.format(season, i),
- )
+ self.assertEqual(str(e), season)
+ self.assertEqual(repr(e), 'Season.{0}'.format(season))
def test_value_name(self):
Season = self.Season
@@ -440,7 +437,7 @@ class TestEnum(unittest.TestCase):
def test_reserved__sunder_(self):
with self.assertRaisesRegex(
ValueError,
- "_sunder_ names, such as '_bad_', are reserved",
+ '_sunder_ names, such as ._bad_., are reserved',
):
class Bad(Enum):
_bad_ = 1
@@ -488,7 +485,7 @@ class TestEnum(unittest.TestCase):
two = 2.0
def __format__(self, spec):
return 'Format!!'
- self.assertEqual(str(EnumWithFormatOverride.one), 'EnumWithFormatOverride.one')
+ self.assertEqual(str(EnumWithFormatOverride.one), 'one')
self.assertEqual('{}'.format(EnumWithFormatOverride.one), 'Format!!')
def test_str_and_format_override_enum(self):
@@ -528,7 +525,7 @@ class TestEnum(unittest.TestCase):
two = 2.0
def __format__(self, spec):
return 'TestFloat success!'
- self.assertEqual(str(TestFloat.one), 'TestFloat.one')
+ self.assertEqual(str(TestFloat.one), 'one')
self.assertEqual('{}'.format(TestFloat.one), 'TestFloat success!')
def assertFormatIsValue(self, spec, member):
@@ -614,6 +611,8 @@ class TestEnum(unittest.TestCase):
A = 1
B = 2
C = 3
+ def __repr__(self):
+ return '<%s.%s: %r>' % (self.__class__.__name__, self._name_, self._value_)
self.assertEqual(repr(MyEnum.A), '<MyEnum.A: 0x1>')
def test_too_many_data_types(self):
@@ -1959,7 +1958,7 @@ class TestEnum(unittest.TestCase):
self.assertEqual(Color.GREEN.value, 2)
self.assertEqual(Color.BLUE.value, 3)
self.assertEqual(Color.MAX, 3)
- self.assertEqual(str(Color.BLUE), 'Color.BLUE')
+ self.assertEqual(str(Color.BLUE), 'BLUE')
class Color(MaxMixin, StrMixin, Enum):
RED = auto()
GREEN = auto()
@@ -2330,64 +2329,62 @@ class TestFlag(unittest.TestCase):
def test_str(self):
Perm = self.Perm
- self.assertEqual(str(Perm.R), 'Perm.R')
- self.assertEqual(str(Perm.W), 'Perm.W')
- self.assertEqual(str(Perm.X), 'Perm.X')
- self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
- self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
+ self.assertEqual(str(Perm.R), 'R')
+ self.assertEqual(str(Perm.W), 'W')
+ self.assertEqual(str(Perm.X), 'X')
+ self.assertEqual(str(Perm.R | Perm.W), 'R|W')
+ self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'R|W|X')
self.assertEqual(str(Perm(0)), 'Perm(0)')
- self.assertEqual(str(~Perm.R), 'Perm.W|X')
- self.assertEqual(str(~Perm.W), 'Perm.R|X')
- self.assertEqual(str(~Perm.X), 'Perm.R|W')
- self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
+ self.assertEqual(str(~Perm.R), 'W|X')
+ self.assertEqual(str(~Perm.W), 'R|X')
+ self.assertEqual(str(~Perm.X), 'R|W')
+ self.assertEqual(str(~(Perm.R | Perm.W)), 'X')
self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm(0)')
- self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
+ self.assertEqual(str(Perm(~0)), 'R|W|X')
Open = self.Open
- self.assertEqual(str(Open.RO), 'Open.RO')
- self.assertEqual(str(Open.WO), 'Open.WO')
- self.assertEqual(str(Open.AC), 'Open.AC')
- self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
- self.assertEqual(str(Open.WO | Open.CE), 'Open.WO|CE')
- self.assertEqual(str(~Open.RO), 'Open.WO|RW|CE')
- self.assertEqual(str(~Open.WO), 'Open.RW|CE')
- self.assertEqual(str(~Open.AC), 'Open.CE')
- self.assertEqual(str(~Open.CE), 'Open.AC')
- self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
- self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
+ self.assertEqual(str(Open.RO), 'RO')
+ self.assertEqual(str(Open.WO), 'WO')
+ self.assertEqual(str(Open.AC), 'AC')
+ self.assertEqual(str(Open.RO | Open.CE), 'CE')
+ self.assertEqual(str(Open.WO | Open.CE), 'WO|CE')
+ self.assertEqual(str(~Open.RO), 'WO|RW|CE')
+ self.assertEqual(str(~Open.WO), 'RW|CE')
+ self.assertEqual(str(~Open.AC), 'CE')
+ self.assertEqual(str(~(Open.RO | Open.CE)), 'AC')
+ self.assertEqual(str(~(Open.WO | Open.CE)), 'RW')
def test_repr(self):
Perm = self.Perm
- self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
- self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
- self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
- self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
- self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
- self.assertEqual(repr(Perm(0)), '<Perm: 0>')
- self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
- self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
- self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
- self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
- self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm: 0>')
- self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
+ self.assertEqual(repr(Perm.R), 'Perm.R')
+ self.assertEqual(repr(Perm.W), 'Perm.W')
+ self.assertEqual(repr(Perm.X), 'Perm.X')
+ self.assertEqual(repr(Perm.R | Perm.W), 'Perm.R|Perm.W')
+ self.assertEqual(repr(Perm.R | Perm.W | Perm.X), 'Perm.R|Perm.W|Perm.X')
+ self.assertEqual(repr(Perm(0)), '0x0')
+ self.assertEqual(repr(~Perm.R), 'Perm.W|Perm.X')
+ self.assertEqual(repr(~Perm.W), 'Perm.R|Perm.X')
+ self.assertEqual(repr(~Perm.X), 'Perm.R|Perm.W')
+ self.assertEqual(repr(~(Perm.R | Perm.W)), 'Perm.X')
+ self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '0x0')
+ self.assertEqual(repr(Perm(~0)), 'Perm.R|Perm.W|Perm.X')
Open = self.Open
- self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
- self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
- self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
- self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
- self.assertEqual(repr(Open.WO | Open.CE), '<Open.WO|CE: 524289>')
- self.assertEqual(repr(~Open.RO), '<Open.WO|RW|CE: 524291>')
- self.assertEqual(repr(~Open.WO), '<Open.RW|CE: 524290>')
- self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
- self.assertEqual(repr(~Open.CE), '<Open.AC: 3>')
- self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
- self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
+ self.assertEqual(repr(Open.RO), 'Open.RO')
+ self.assertEqual(repr(Open.WO), 'Open.WO')
+ self.assertEqual(repr(Open.AC), 'Open.AC')
+ self.assertEqual(repr(Open.RO | Open.CE), 'Open.CE')
+ self.assertEqual(repr(Open.WO | Open.CE), 'Open.WO|Open.CE')
+ self.assertEqual(repr(~Open.RO), 'Open.WO|Open.RW|Open.CE')
+ self.assertEqual(repr(~Open.WO), 'Open.RW|Open.CE')
+ self.assertEqual(repr(~Open.AC), 'Open.CE')
+ self.assertEqual(repr(~(Open.RO | Open.CE)), 'Open.AC')
+ self.assertEqual(repr(~(Open.WO | Open.CE)), 'Open.RW')
def test_format(self):
Perm = self.Perm
- self.assertEqual(format(Perm.R, ''), 'Perm.R')
- self.assertEqual(format(Perm.R | Perm.X, ''), 'Perm.R|X')
+ self.assertEqual(format(Perm.R, ''), 'R')
+ self.assertEqual(format(Perm.R | Perm.X, ''), 'R|X')
def test_or(self):
Perm = self.Perm
@@ -2707,7 +2704,7 @@ class TestFlag(unittest.TestCase):
self.assertEqual(Color.GREEN.value, 2)
self.assertEqual(Color.BLUE.value, 4)
self.assertEqual(Color.ALL.value, 7)
- self.assertEqual(str(Color.BLUE), 'Color.BLUE')
+ self.assertEqual(str(Color.BLUE), 'BLUE')
class Color(AllMixin, StrMixin, Flag):
RED = auto()
GREEN = auto()
@@ -2850,77 +2847,70 @@ class TestIntFlag(unittest.TestCase):
def test_str(self):
Perm = self.Perm
- self.assertEqual(str(Perm.R), 'Perm.R')
- self.assertEqual(str(Perm.W), 'Perm.W')
- self.assertEqual(str(Perm.X), 'Perm.X')
- self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
- self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
+ self.assertEqual(str(Perm.R), 'R')
+ self.assertEqual(str(Perm.W), 'W')
+ self.assertEqual(str(Perm.X), 'X')
+ self.assertEqual(str(Perm.R | Perm.W), 'R|W')
+ self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'R|W|X')
self.assertEqual(str(Perm.R | 8), '12')
self.assertEqual(str(Perm(0)), 'Perm(0)')
self.assertEqual(str(Perm(8)), '8')
- self.assertEqual(str(~Perm.R), 'Perm.W|X')
- self.assertEqual(str(~Perm.W), 'Perm.R|X')
- self.assertEqual(str(~Perm.X), 'Perm.R|W')
- self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
+ self.assertEqual(str(~Perm.R), 'W|X')
+ self.assertEqual(str(~Perm.W), 'R|X')
+ self.assertEqual(str(~Perm.X), 'R|W')
+ self.assertEqual(str(~(Perm.R | Perm.W)), 'X')
self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm(0)')
self.assertEqual(str(~(Perm.R | 8)), '-13')
- self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
+ self.assertEqual(str(Perm(~0)), 'R|W|X')
self.assertEqual(str(Perm(~8)), '-9')
Open = self.Open
- self.assertEqual(str(Open.RO), 'Open.RO')
- self.assertEqual(str(Open.WO), 'Open.WO')
- self.assertEqual(str(Open.AC), 'Open.AC')
- self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
- self.assertEqual(str(Open.WO | Open.CE), 'Open.WO|CE')
+ self.assertEqual(str(Open.RO), 'RO')
+ self.assertEqual(str(Open.WO), 'WO')
+ self.assertEqual(str(Open.AC), 'AC')
+ self.assertEqual(str(Open.RO | Open.CE), 'CE')
+ self.assertEqual(str(Open.WO | Open.CE), 'WO|CE')
self.assertEqual(str(Open(4)), '4')
- self.assertEqual(str(~Open.RO), 'Open.WO|RW|CE')
- self.assertEqual(str(~Open.WO), 'Open.RW|CE')
- self.assertEqual(str(~Open.AC), 'Open.CE')
- self.assertEqual(str(~Open.CE), 'Open.AC')
- self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
- self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
+ self.assertEqual(str(~Open.RO), 'WO|RW|CE')
+ self.assertEqual(str(~Open.WO), 'RW|CE')
+ self.assertEqual(str(~Open.AC), 'CE')
+ self.assertEqual(str(~(Open.RO | Open.CE)), 'AC')
+ self.assertEqual(str(~(Open.WO | Open.CE)), 'RW')
self.assertEqual(str(Open(~4)), '-5')
- Skip = self.Skip
- self.assertEqual(str(Skip(~4)), 'Skip.FIRST|SECOND|EIGHTH')
-
def test_repr(self):
Perm = self.Perm
- self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
- self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
- self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
- self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
- self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
+ self.assertEqual(repr(Perm.R), 'Perm.R')
+ self.assertEqual(repr(Perm.W), 'Perm.W')
+ self.assertEqual(repr(Perm.X), 'Perm.X')
+ self.assertEqual(repr(Perm.R | Perm.W), 'Perm.R|Perm.W')
+ self.assertEqual(repr(Perm.R | Perm.W | Perm.X), 'Perm.R|Perm.W|Perm.X')
self.assertEqual(repr(Perm.R | 8), '12')
- self.assertEqual(repr(Perm(0)), '<Perm: 0>')
+ self.assertEqual(repr(Perm(0)), '0x0')
self.assertEqual(repr(Perm(8)), '8')
- self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
- self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
- self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
- self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
- self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm: 0>')
+ self.assertEqual(repr(~Perm.R), 'Perm.W|Perm.X')
+ self.assertEqual(repr(~Perm.W), 'Perm.R|Perm.X')
+ self.assertEqual(repr(~Perm.X), 'Perm.R|Perm.W')
+ self.assertEqual(repr(~(Perm.R | Perm.W)), 'Perm.X')
+ self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '0x0')
self.assertEqual(repr(~(Perm.R | 8)), '-13')
- self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
+ self.assertEqual(repr(Perm(~0)), 'Perm.R|Perm.W|Perm.X')
self.assertEqual(repr(Perm(~8)), '-9')
Open = self.Open
- self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
- self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
- self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
- self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
- self.assertEqual(repr(Open.WO | Open.CE), '<Open.WO|CE: 524289>')
+ self.assertEqual(repr(Open.RO), 'Open.RO')
+ self.assertEqual(repr(Open.WO), 'Open.WO')
+ self.assertEqual(repr(Open.AC), 'Open.AC')
+ self.assertEqual(repr(Open.RO | Open.CE), 'Open.CE')
+ self.assertEqual(repr(Open.WO | Open.CE), 'Open.WO|Open.CE')
self.assertEqual(repr(Open(4)), '4')
- self.assertEqual(repr(~Open.RO), '<Open.WO|RW|CE: 524291>')
- self.assertEqual(repr(~Open.WO), '<Open.RW|CE: 524290>')
- self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
- self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
- self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
+ self.assertEqual(repr(~Open.RO), 'Open.WO|Open.RW|Open.CE')
+ self.assertEqual(repr(~Open.WO), 'Open.RW|Open.CE')
+ self.assertEqual(repr(~Open.AC), 'Open.CE')
+ self.assertEqual(repr(~(Open.RO | Open.CE)), 'Open.AC')
+ self.assertEqual(repr(~(Open.WO | Open.CE)), 'Open.RW')
self.assertEqual(repr(Open(~4)), '-5')
- Skip = self.Skip
- self.assertEqual(repr(Skip(~4)), '<Skip.FIRST|SECOND|EIGHTH: 11>')
-
def test_format(self):
Perm = self.Perm
self.assertEqual(format(Perm.R, ''), '4')
@@ -3252,7 +3242,7 @@ class TestIntFlag(unittest.TestCase):
self.assertEqual(Color.GREEN.value, 2)
self.assertEqual(Color.BLUE.value, 4)
self.assertEqual(Color.ALL.value, 7)
- self.assertEqual(str(Color.BLUE), 'Color.BLUE')
+ self.assertEqual(str(Color.BLUE), 'BLUE')
class Color(AllMixin, StrMixin, IntFlag):
RED = auto()
GREEN = auto()
@@ -3374,6 +3364,8 @@ class TestUnique(unittest.TestCase):
value = 4
+class TestEnumTypeSubclassing(unittest.TestCase):
+ pass
expected_help_output_with_docs = """\
Help on class Color in module %s:
@@ -3390,11 +3382,11 @@ class Color(enum.Enum)
|\x20\x20
| Data and other attributes defined here:
|\x20\x20
- | blue = <Color.blue: 3>
+ | blue = Color.blue
|\x20\x20
- | green = <Color.green: 2>
+ | green = Color.green
|\x20\x20
- | red = <Color.red: 1>
+ | red = Color.red
|\x20\x20
| ----------------------------------------------------------------------
| Data descriptors inherited from enum.Enum:
@@ -3406,7 +3398,7 @@ class Color(enum.Enum)
| The value of the Enum member.
|\x20\x20
| ----------------------------------------------------------------------
- | Readonly properties inherited from enum.EnumMeta:
+ | Readonly properties inherited from enum.EnumType:
|\x20\x20
| __members__
| Returns a mapping of member name->value.
@@ -3427,11 +3419,11 @@ class Color(enum.Enum)
|\x20\x20
| Data and other attributes defined here:
|\x20\x20
- | blue = <Color.blue: 3>
+ | blue = Color.blue
|\x20\x20
- | green = <Color.green: 2>
+ | green = Color.green
|\x20\x20
- | red = <Color.red: 1>
+ | red = Color.red
|\x20\x20
| ----------------------------------------------------------------------
| Data descriptors inherited from enum.Enum:
@@ -3441,7 +3433,7 @@ class Color(enum.Enum)
| value
|\x20\x20
| ----------------------------------------------------------------------
- | Data descriptors inherited from enum.EnumMeta:
+ | Data descriptors inherited from enum.EnumType:
|\x20\x20
| __members__"""
@@ -3468,7 +3460,7 @@ class TestStdLib(unittest.TestCase):
def test_inspect_getmembers(self):
values = dict((
- ('__class__', EnumMeta),
+ ('__class__', EnumType),
('__doc__', 'An enumeration.'),
('__members__', self.Color.__members__),
('__module__', __name__),
@@ -3495,11 +3487,11 @@ class TestStdLib(unittest.TestCase):
from inspect import Attribute
values = [
Attribute(name='__class__', kind='data',
- defining_class=object, object=EnumMeta),
+ defining_class=object, object=EnumType),
Attribute(name='__doc__', kind='data',
defining_class=self.Color, object='An enumeration.'),
Attribute(name='__members__', kind='property',
- defining_class=EnumMeta, object=EnumMeta.__members__),
+ defining_class=EnumType, object=EnumType.__members__),
Attribute(name='__module__', kind='data',
defining_class=self.Color, object=__name__),
Attribute(name='blue', kind='data',
@@ -3589,6 +3581,45 @@ class TestIntEnumConvert(unittest.TestCase):
('test.test_enum', '__main__')[__name__=='__main__'],
filter=lambda x: x.startswith('CONVERT_TEST_'))
+ def test_convert_repr_and_str(self):
+ module = ('test.test_enum', '__main__')[__name__=='__main__']
+ test_type = enum.IntEnum._convert_(
+ 'UnittestConvert',
+ module,
+ filter=lambda x: x.startswith('CONVERT_TEST_'))
+ self.assertEqual(repr(test_type.CONVERT_TEST_NAME_A), '%s.CONVERT_TEST_NAME_A' % module)
+ self.assertEqual(str(test_type.CONVERT_TEST_NAME_A), 'CONVERT_TEST_NAME_A')
+ self.assertEqual(format(test_type.CONVERT_TEST_NAME_A), '5')
+
+# global names for StrEnum._convert_ test
+CONVERT_STR_TEST_2 = 'goodbye'
+CONVERT_STR_TEST_1 = 'hello'
+
+class TestStrEnumConvert(unittest.TestCase):
+
+ def test_convert(self):
+ test_type = enum.StrEnum._convert_(
+ 'UnittestConvert',
+ ('test.test_enum', '__main__')[__name__=='__main__'],
+ filter=lambda x: x.startswith('CONVERT_STR_'))
+ # Ensure that test_type has all of the desired names and values.
+ self.assertEqual(test_type.CONVERT_STR_TEST_1, 'hello')
+ self.assertEqual(test_type.CONVERT_STR_TEST_2, 'goodbye')
+ # 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_STR_* found.')
+
+ def test_convert_repr_and_str(self):
+ module = ('test.test_enum', '__main__')[__name__=='__main__']
+ test_type = enum.StrEnum._convert_(
+ 'UnittestConvert',
+ module,
+ filter=lambda x: x.startswith('CONVERT_STR_'))
+ self.assertEqual(repr(test_type.CONVERT_STR_TEST_1), '%s.CONVERT_STR_TEST_1' % module)
+ self.assertEqual(str(test_type.CONVERT_STR_TEST_2), 'goodbye')
+ self.assertEqual(format(test_type.CONVERT_STR_TEST_1), 'hello')
+
if __name__ == '__main__':
unittest.main()
diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py
index 3bc0e9e..61575b5 100644
--- a/Lib/test/test_pydoc.py
+++ b/Lib/test/test_pydoc.py
@@ -453,7 +453,7 @@ class PydocDocTest(unittest.TestCase):
zero = 0
one = 1
doc = pydoc.render_doc(BinaryInteger)
- self.assertIn('<BinaryInteger.zero: 0>', doc)
+ self.assertIn('BinaryInteger.zero', doc)
def test_mixed_case_module_names_are_lower_cased(self):
# issue16484
diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py
index f973d4f..8f943be 100644
--- a/Lib/test/test_signal.py
+++ b/Lib/test/test_signal.py
@@ -872,7 +872,7 @@ class PendingSignalsTests(unittest.TestCase):
%s
- blocked = %s
+ blocked = %r
signum = signal.SIGALRM
# child: block and wait the signal
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index bc28030..f91e000 100755
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -1518,9 +1518,9 @@ class GeneralModuleTests(unittest.TestCase):
infos = socket.getaddrinfo(HOST, 80, socket.AF_INET, socket.SOCK_STREAM)
for family, type, _, _, _ in infos:
self.assertEqual(family, socket.AF_INET)
- self.assertEqual(str(family), 'AddressFamily.AF_INET')
+ self.assertEqual(str(family), 'AF_INET')
self.assertEqual(type, socket.SOCK_STREAM)
- self.assertEqual(str(type), 'SocketKind.SOCK_STREAM')
+ self.assertEqual(str(type), 'SOCK_STREAM')
infos = socket.getaddrinfo(HOST, None, 0, socket.SOCK_STREAM)
for _, socktype, _, _, _ in infos:
self.assertEqual(socktype, socket.SOCK_STREAM)
@@ -1793,8 +1793,8 @@ class GeneralModuleTests(unittest.TestCase):
# Make sure that the AF_* and SOCK_* constants have enum-like string
# reprs.
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
- self.assertEqual(str(s.family), 'AddressFamily.AF_INET')
- self.assertEqual(str(s.type), 'SocketKind.SOCK_STREAM')
+ self.assertEqual(str(s.family), 'AF_INET')
+ self.assertEqual(str(s.type), 'SOCK_STREAM')
def test_socket_consistent_sock_type(self):
SOCK_NONBLOCK = getattr(socket, 'SOCK_NONBLOCK', 0)
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index fa77406..4ef1fb8 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -381,7 +381,7 @@ class BasicSocketTests(unittest.TestCase):
# Make sure that the PROTOCOL_* constants have enum-like string
# reprs.
proto = ssl.PROTOCOL_TLS
- self.assertEqual(str(proto), '_SSLMethod.PROTOCOL_TLS')
+ self.assertEqual(str(proto), 'PROTOCOL_TLS')
ctx = ssl.SSLContext(proto)
self.assertIs(ctx.protocol, proto)
diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py
index 42c77f0..d47cf28 100644
--- a/Lib/test/test_unicode.py
+++ b/Lib/test/test_unicode.py
@@ -1467,18 +1467,18 @@ class UnicodeTest(string_tests.CommonTest,
ABC = 'abc'
# Testing Unicode formatting strings...
self.assertEqual("%s, %s" % (Str.ABC, Str.ABC),
- 'Str.ABC, Str.ABC')
+ 'ABC, ABC')
self.assertEqual("%s, %s, %d, %i, %u, %f, %5.2f" %
(Str.ABC, Str.ABC,
Int.IDES, Int.IDES, Int.IDES,
Float.PI, Float.PI),
- 'Str.ABC, Str.ABC, 15, 15, 15, 3.141593, 3.14')
+ 'ABC, ABC, 15, 15, 15, 3.141593, 3.14')
# formatting jobs delegated from the string implementation:
self.assertEqual('...%(foo)s...' % {'foo':Str.ABC},
- '...Str.ABC...')
+ '...ABC...')
self.assertEqual('...%(foo)s...' % {'foo':Int.IDES},
- '...Int.IDES...')
+ '...IDES...')
self.assertEqual('...%(foo)i...' % {'foo':Int.IDES},
'...15...')
self.assertEqual('...%(foo)d...' % {'foo':Int.IDES},