Close issue21706: add 'start' parameter to functional API
This commit is contained in:
parent
52351c7037
commit
d9925a18ec
|
@ -400,7 +400,8 @@ The second argument is the *source* of enumeration member names. It can be a
|
|||
whitespace-separated string of names, a sequence of names, a sequence of
|
||||
2-tuples with key/value pairs, or a mapping (e.g. dictionary) of names to
|
||||
values. The last two options enable assigning arbitrary values to
|
||||
enumerations; the others auto-assign increasing integers starting with 1. A
|
||||
enumerations; the others auto-assign increasing integers starting with 1 (use
|
||||
the `start` parameter to specify a different starting value). A
|
||||
new class derived from :class:`Enum` is returned. In other words, the above
|
||||
assignment to :class:`Animal` is equivalent to::
|
||||
|
||||
|
@ -438,12 +439,12 @@ SomeData in the global scope::
|
|||
|
||||
The complete signature is::
|
||||
|
||||
Enum(value='NewEnumName', names=<...>, *, module='...', qualname='...', type=<mixed-in class>)
|
||||
Enum(value='NewEnumName', names=<...>, *, module='...', qualname='...', type=<mixed-in class>, start=1)
|
||||
|
||||
:value: What the new Enum class will record as its name.
|
||||
|
||||
:names: The Enum members. This can be a whitespace or comma separated string
|
||||
(values will start at 1)::
|
||||
(values will start at 1 unless otherwise specified)::
|
||||
|
||||
'red green blue' | 'red,green,blue' | 'red, green, blue'
|
||||
|
||||
|
@ -461,6 +462,8 @@ The complete signature is::
|
|||
|
||||
:type: type to mix in to new Enum class.
|
||||
|
||||
:start: number to start counting at if only names are passed in
|
||||
|
||||
|
||||
Derived Enumerations
|
||||
--------------------
|
||||
|
|
16
Lib/enum.py
16
Lib/enum.py
|
@ -193,7 +193,7 @@ class EnumMeta(type):
|
|||
enum_class.__new__ = Enum.__new__
|
||||
return enum_class
|
||||
|
||||
def __call__(cls, value, names=None, *, module=None, qualname=None, type=None):
|
||||
def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):
|
||||
"""Either returns an existing member, or creates a new enum class.
|
||||
|
||||
This method is used both when an enum class is given a value to match
|
||||
|
@ -205,7 +205,7 @@ class EnumMeta(type):
|
|||
`value` will be the name of the new class.
|
||||
|
||||
`names` should be either a string of white-space/comma delimited names
|
||||
(values will start at 1), or an iterator/mapping of name, value pairs.
|
||||
(values will start at `start`), or an iterator/mapping of name, value pairs.
|
||||
|
||||
`module` should be set to the module this class is being created in;
|
||||
if it is not set, an attempt to find that module will be made, but if
|
||||
|
@ -221,7 +221,7 @@ class EnumMeta(type):
|
|||
if names is None: # simple value lookup
|
||||
return cls.__new__(cls, value)
|
||||
# otherwise, functional API: we're creating a new Enum type
|
||||
return cls._create_(value, names, module=module, qualname=qualname, type=type)
|
||||
return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)
|
||||
|
||||
def __contains__(cls, member):
|
||||
return isinstance(member, cls) and member._name_ in cls._member_map_
|
||||
|
@ -292,16 +292,16 @@ class EnumMeta(type):
|
|||
raise AttributeError('Cannot reassign members.')
|
||||
super().__setattr__(name, value)
|
||||
|
||||
def _create_(cls, class_name, names=None, *, module=None, qualname=None, type=None):
|
||||
def _create_(cls, class_name, names=None, *, module=None, qualname=None, type=None, start=1):
|
||||
"""Convenience method to create a new Enum class.
|
||||
|
||||
`names` can be:
|
||||
|
||||
* A string containing member names, separated either with spaces or
|
||||
commas. Values are auto-numbered from 1.
|
||||
* An iterable of member names. Values are auto-numbered from 1.
|
||||
commas. Values are incremented by 1 from `start`.
|
||||
* An iterable of member names. Values are incremented by 1 from `start`.
|
||||
* An iterable of (member name, value) pairs.
|
||||
* A mapping of member name -> value.
|
||||
* A mapping of member name -> value pairs.
|
||||
|
||||
"""
|
||||
metacls = cls.__class__
|
||||
|
@ -312,7 +312,7 @@ class EnumMeta(type):
|
|||
if isinstance(names, str):
|
||||
names = names.replace(',', ' ').split()
|
||||
if isinstance(names, (tuple, list)) and isinstance(names[0], str):
|
||||
names = [(e, i) for (i, e) in enumerate(names, 1)]
|
||||
names = [(e, i) for (i, e) in enumerate(names, start)]
|
||||
|
||||
# Here, names is either an iterable of (name, value) or a mapping.
|
||||
for item in names:
|
||||
|
|
|
@ -634,6 +634,23 @@ class TestEnum(unittest.TestCase):
|
|||
self.assertIn(e, SummerMonth)
|
||||
self.assertIs(type(e), SummerMonth)
|
||||
|
||||
def test_programatic_function_string_with_start(self):
|
||||
SummerMonth = Enum('SummerMonth', 'june july august', start=10)
|
||||
lst = list(SummerMonth)
|
||||
self.assertEqual(len(lst), len(SummerMonth))
|
||||
self.assertEqual(len(SummerMonth), 3, SummerMonth)
|
||||
self.assertEqual(
|
||||
[SummerMonth.june, SummerMonth.july, SummerMonth.august],
|
||||
lst,
|
||||
)
|
||||
for i, month in enumerate('june july august'.split(), 10):
|
||||
e = SummerMonth(i)
|
||||
self.assertEqual(int(e.value), i)
|
||||
self.assertNotEqual(e, i)
|
||||
self.assertEqual(e.name, month)
|
||||
self.assertIn(e, SummerMonth)
|
||||
self.assertIs(type(e), SummerMonth)
|
||||
|
||||
def test_programatic_function_string_list(self):
|
||||
SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
|
||||
lst = list(SummerMonth)
|
||||
|
@ -651,6 +668,23 @@ class TestEnum(unittest.TestCase):
|
|||
self.assertIn(e, SummerMonth)
|
||||
self.assertIs(type(e), SummerMonth)
|
||||
|
||||
def test_programatic_function_string_list_with_start(self):
|
||||
SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20)
|
||||
lst = list(SummerMonth)
|
||||
self.assertEqual(len(lst), len(SummerMonth))
|
||||
self.assertEqual(len(SummerMonth), 3, SummerMonth)
|
||||
self.assertEqual(
|
||||
[SummerMonth.june, SummerMonth.july, SummerMonth.august],
|
||||
lst,
|
||||
)
|
||||
for i, month in enumerate('june july august'.split(), 20):
|
||||
e = SummerMonth(i)
|
||||
self.assertEqual(int(e.value), i)
|
||||
self.assertNotEqual(e, i)
|
||||
self.assertEqual(e.name, month)
|
||||
self.assertIn(e, SummerMonth)
|
||||
self.assertIs(type(e), SummerMonth)
|
||||
|
||||
def test_programatic_function_iterable(self):
|
||||
SummerMonth = Enum(
|
||||
'SummerMonth',
|
||||
|
@ -707,6 +741,22 @@ class TestEnum(unittest.TestCase):
|
|||
self.assertIn(e, SummerMonth)
|
||||
self.assertIs(type(e), SummerMonth)
|
||||
|
||||
def test_programatic_function_type_with_start(self):
|
||||
SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30)
|
||||
lst = list(SummerMonth)
|
||||
self.assertEqual(len(lst), len(SummerMonth))
|
||||
self.assertEqual(len(SummerMonth), 3, SummerMonth)
|
||||
self.assertEqual(
|
||||
[SummerMonth.june, SummerMonth.july, SummerMonth.august],
|
||||
lst,
|
||||
)
|
||||
for i, month in enumerate('june july august'.split(), 30):
|
||||
e = SummerMonth(i)
|
||||
self.assertEqual(e, i)
|
||||
self.assertEqual(e.name, month)
|
||||
self.assertIn(e, SummerMonth)
|
||||
self.assertIs(type(e), SummerMonth)
|
||||
|
||||
def test_programatic_function_type_from_subclass(self):
|
||||
SummerMonth = IntEnum('SummerMonth', 'june july august')
|
||||
lst = list(SummerMonth)
|
||||
|
@ -723,6 +773,22 @@ class TestEnum(unittest.TestCase):
|
|||
self.assertIn(e, SummerMonth)
|
||||
self.assertIs(type(e), SummerMonth)
|
||||
|
||||
def test_programatic_function_type_from_subclass_with_start(self):
|
||||
SummerMonth = IntEnum('SummerMonth', 'june july august', start=40)
|
||||
lst = list(SummerMonth)
|
||||
self.assertEqual(len(lst), len(SummerMonth))
|
||||
self.assertEqual(len(SummerMonth), 3, SummerMonth)
|
||||
self.assertEqual(
|
||||
[SummerMonth.june, SummerMonth.july, SummerMonth.august],
|
||||
lst,
|
||||
)
|
||||
for i, month in enumerate('june july august'.split(), 40):
|
||||
e = SummerMonth(i)
|
||||
self.assertEqual(e, i)
|
||||
self.assertEqual(e.name, month)
|
||||
self.assertIn(e, SummerMonth)
|
||||
self.assertIs(type(e), SummerMonth)
|
||||
|
||||
def test_subclassing(self):
|
||||
if isinstance(Name, Exception):
|
||||
raise Name
|
||||
|
|
Loading…
Reference in New Issue