cpython: 058cb219b3b5 (original) (raw)
--- a/Doc/library/enum.rst
+++ b/Doc/library/enum.rst
@@ -463,6 +463,12 @@ 2. While :class:Enum
can have members
3. When another data type is mixed in, the :attr:value
attribute is not the
same as the enum member itself, although it is equivalant and will compare
equal.
+4. %-style formatting: %s
and %r
call :class:Enum
's :meth:__str__
and
- :meth:
__repr__
respectively; other codes (such as%i
or%h
for - IntEnum) treat the enum member as its mixed-in type.
+5. :class:
str
.:meth:__format__
(or :func:format
) will use the mixed-in - type's :meth:
__format__
. If the :class:Enum
's :func:str
or - :func:
repr
is desired use the!s
or!r
:class:str
format codes.
--- a/Lib/enum.py +++ b/Lib/enum.py @@ -50,7 +50,6 @@ def _make_class_unpicklable(cls): cls.reduce = _break_on_call_reduce cls.module = '' - class _EnumDict(dict): """Keeps track of definition order of the enum items. @@ -182,7 +181,7 @@ class EnumMeta(type): # double check that repr and friends are not the mixin's or various # things break (such as pickle)
for name in ('__repr__', '__str__', '__getnewargs__'):[](#l2.15)
for name in ('__repr__', '__str__', '__format__', '__getnewargs__'):[](#l2.16) class_method = getattr(enum_class, name)[](#l2.17) obj_method = getattr(member_type, name, None)[](#l2.18) enum_method = getattr(first_enum, name, None)[](#l2.19)
@@ -441,6 +440,21 @@ class Enum(metaclass=EnumMeta): return self is other return NotImplemented
- def format(self, format_spec):
# mixed-in Enums should use the mixed-in type's __format__, otherwise[](#l2.25)
# we can get strange results with the Enum name showing up instead of[](#l2.26)
# the value[](#l2.27)
# pure Enum branch[](#l2.29)
if self._member_type_ is object:[](#l2.30)
cls = str[](#l2.31)
val = str(self)[](#l2.32)
# mix-in branch[](#l2.33)
else:[](#l2.34)
cls = self._member_type_[](#l2.35)
val = self.value[](#l2.36)
return cls.__format__(val, format_spec)[](#l2.37)
+ def getnewargs(self): return (self.value, )
--- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -67,6 +67,33 @@ class TestEnum(unittest.TestCase): WINTER = 4 self.Season = Season
class Konstants(float, Enum):[](#l3.7)
E = 2.7182818[](#l3.8)
PI = 3.1415926[](#l3.9)
TAU = 2 * PI[](#l3.10)
self.Konstants = Konstants[](#l3.11)
class Grades(IntEnum):[](#l3.13)
A = 5[](#l3.14)
B = 4[](#l3.15)
C = 3[](#l3.16)
D = 2[](#l3.17)
F = 0[](#l3.18)
self.Grades = Grades[](#l3.19)
class Directional(str, Enum):[](#l3.21)
EAST = 'east'[](#l3.22)
WEST = 'west'[](#l3.23)
NORTH = 'north'[](#l3.24)
SOUTH = 'south'[](#l3.25)
self.Directional = Directional[](#l3.26)
from datetime import date[](#l3.28)
class Holiday(date, Enum):[](#l3.29)
NEW_YEAR = 2013, 1, 1[](#l3.30)
IDES_OF_MARCH = 2013, 3, 15[](#l3.31)
self.Holiday = Holiday[](#l3.32)
+ def test_dir_on_class(self): Season = self.Season self.assertEqual( @@ -207,6 +234,77 @@ class TestEnum(unittest.TestCase): self.assertIs(type(Huh.name), Huh) self.assertEqual(Huh.name.name, 'name') self.assertEqual(Huh.name.value, 1) +
- def test_format_enum(self):
Season = self.Season[](#l3.43)
self.assertEqual('{}'.format(Season.SPRING),[](#l3.44)
'{}'.format(str(Season.SPRING)))[](#l3.45)
self.assertEqual( '{:}'.format(Season.SPRING),[](#l3.46)
'{:}'.format(str(Season.SPRING)))[](#l3.47)
self.assertEqual('{:20}'.format(Season.SPRING),[](#l3.48)
'{:20}'.format(str(Season.SPRING)))[](#l3.49)
self.assertEqual('{:^20}'.format(Season.SPRING),[](#l3.50)
'{:^20}'.format(str(Season.SPRING)))[](#l3.51)
self.assertEqual('{:>20}'.format(Season.SPRING),[](#l3.52)
'{:>20}'.format(str(Season.SPRING)))[](#l3.53)
self.assertEqual('{:<20}'.format(Season.SPRING),[](#l3.54)
'{:<20}'.format(str(Season.SPRING)))[](#l3.55)
- def test_format_enum_custom(self):
class TestFloat(float, Enum):[](#l3.58)
one = 1.0[](#l3.59)
two = 2.0[](#l3.60)
def __format__(self, spec):[](#l3.61)
return 'TestFloat success!'[](#l3.62)
self.assertEqual('{}'.format(TestFloat.one), 'TestFloat success!')[](#l3.63)
- def assertFormatIsValue(self, spec, member):
self.assertEqual(spec.format(member), spec.format(member.value))[](#l3.66)
- def test_format_enum_date(self):
Holiday = self.Holiday[](#l3.69)
self.assertFormatIsValue('{}', Holiday.IDES_OF_MARCH)[](#l3.70)
self.assertFormatIsValue('{:}', Holiday.IDES_OF_MARCH)[](#l3.71)
self.assertFormatIsValue('{:20}', Holiday.IDES_OF_MARCH)[](#l3.72)
self.assertFormatIsValue('{:^20}', Holiday.IDES_OF_MARCH)[](#l3.73)
self.assertFormatIsValue('{:>20}', Holiday.IDES_OF_MARCH)[](#l3.74)
self.assertFormatIsValue('{:<20}', Holiday.IDES_OF_MARCH)[](#l3.75)
self.assertFormatIsValue('{:%Y %m}', Holiday.IDES_OF_MARCH)[](#l3.76)
self.assertFormatIsValue('{:%Y %m %M:00}', Holiday.IDES_OF_MARCH)[](#l3.77)
- def test_format_enum_float(self):
Konstants = self.Konstants[](#l3.80)
self.assertFormatIsValue('{}', Konstants.TAU)[](#l3.81)
self.assertFormatIsValue('{:}', Konstants.TAU)[](#l3.82)
self.assertFormatIsValue('{:20}', Konstants.TAU)[](#l3.83)
self.assertFormatIsValue('{:^20}', Konstants.TAU)[](#l3.84)
self.assertFormatIsValue('{:>20}', Konstants.TAU)[](#l3.85)
self.assertFormatIsValue('{:<20}', Konstants.TAU)[](#l3.86)
self.assertFormatIsValue('{:n}', Konstants.TAU)[](#l3.87)
self.assertFormatIsValue('{:5.2}', Konstants.TAU)[](#l3.88)
self.assertFormatIsValue('{:f}', Konstants.TAU)[](#l3.89)
- def test_format_enum_int(self):
Grades = self.Grades[](#l3.92)
self.assertFormatIsValue('{}', Grades.C)[](#l3.93)
self.assertFormatIsValue('{:}', Grades.C)[](#l3.94)
self.assertFormatIsValue('{:20}', Grades.C)[](#l3.95)
self.assertFormatIsValue('{:^20}', Grades.C)[](#l3.96)
self.assertFormatIsValue('{:>20}', Grades.C)[](#l3.97)
self.assertFormatIsValue('{:<20}', Grades.C)[](#l3.98)
self.assertFormatIsValue('{:+}', Grades.C)[](#l3.99)
self.assertFormatIsValue('{:08X}', Grades.C)[](#l3.100)
self.assertFormatIsValue('{:b}', Grades.C)[](#l3.101)
- def test_format_enum_str(self):
Directional = self.Directional[](#l3.104)
self.assertFormatIsValue('{}', Directional.WEST)[](#l3.105)
self.assertFormatIsValue('{:}', Directional.WEST)[](#l3.106)
self.assertFormatIsValue('{:20}', Directional.WEST)[](#l3.107)
self.assertFormatIsValue('{:^20}', Directional.WEST)[](#l3.108)
self.assertFormatIsValue('{:>20}', Directional.WEST)[](#l3.109)
self.assertFormatIsValue('{:<20}', Directional.WEST)[](#l3.110)
+ def test_hash(self): Season = self.Season dates = {} @@ -232,7 +330,7 @@ class TestEnum(unittest.TestCase): def test_floatenum_from_scratch(self): class phy(float, Enum):
pi = 3.141596[](#l3.119)
pi = 3.1415926[](#l3.120) tau = 2 * pi[](#l3.121) self.assertTrue(phy.pi < phy.tau)[](#l3.122)
@@ -240,7 +338,7 @@ class TestEnum(unittest.TestCase): class FloatEnum(float, Enum): pass class phy(FloatEnum):
pi = 3.141596[](#l3.128)
pi = 3.1415926[](#l3.129) tau = 2 * pi[](#l3.130) self.assertTrue(phy.pi < phy.tau)[](#l3.131)