[Python-checkins] cpython: Close issue21706: add 'start' parameter to functional API

ethan.furman python-checkins at python.org
Wed Sep 17 05:36:21 CEST 2014


http://hg.python.org/cpython/rev/ec016ba862ba
changeset:   92448:ec016ba862ba
user:        Ethan Furman <ethan at stoneleaf.us>
date:        Tue Sep 16 20:35:55 2014 -0700
summary:
  Close issue21706: add 'start' parameter to functional API

files:
  Doc/library/enum.rst  |   9 ++-
  Lib/enum.py           |  16 +++---
  Lib/test/test_enum.py |  66 +++++++++++++++++++++++++++++++
  3 files changed, 80 insertions(+), 11 deletions(-)


diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst
--- a/Doc/library/enum.rst
+++ b/Doc/library/enum.rst
@@ -400,7 +400,8 @@
 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 @@
 
 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 @@
 
 :type: type to mix in to new Enum class.
 
+:start: number to start counting at if only names are passed in
+
 
 Derived Enumerations
 --------------------
diff --git a/Lib/enum.py b/Lib/enum.py
--- a/Lib/enum.py
+++ b/Lib/enum.py
@@ -193,7 +193,7 @@
             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 @@
         `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 @@
         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 @@
             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 @@
         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:
diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py
--- a/Lib/test/test_enum.py
+++ b/Lib/test/test_enum.py
@@ -634,6 +634,23 @@
             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 @@
             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 @@
             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 @@
             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

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list