utils: add Enum method.

BUG=none
TEST=make test; make lint

Change-Id: I87e7cddf54d8d2b1b27b3dae9404a99a95d66811
diff --git a/graphyte/utils.py b/graphyte/utils.py
index 732a422..f971d3a 100644
--- a/graphyte/utils.py
+++ b/graphyte/utils.py
@@ -6,8 +6,10 @@
 
 """Utils class and functions. """
 
+import collections
 from contextlib import contextmanager
 import inspect
+import itertools
 import math
 import os
 import tempfile
@@ -18,6 +20,22 @@
 from .default_setting import logger
 
 
+def Enum(*args, **kwargs):
+  """Create the immutable enumeration set.
+
+  Usage:
+    1. C-style enum. The value starts from 0 and increase orderly.
+      A = Enum('foo', 'bar')
+      then A.foo == 0, A.bar == 1
+    2. Key-value pair enum.
+      B = Enum(foo='FOO', bar='BAR')
+      then B.foo == 'FOO', B.bar == 'BAR'
+  """
+  fields = dict(zip(args, itertools.count()), **kwargs)
+  enum_type = collections.namedtuple('Enum', fields.keys())
+  return enum_type(**fields)
+
+
 def SearchConfig(filepath, search_dirs=None):
   """Find the config file and return the content.
   The order of searching is:
diff --git a/graphyte/utils_unittest.py b/graphyte/utils_unittest.py
index dd459ab..19b3d77 100755
--- a/graphyte/utils_unittest.py
+++ b/graphyte/utils_unittest.py
@@ -106,3 +106,30 @@
     now = time.time()
     with self.assertRaises(utils.TimeoutError):
       utils.WaitFor(lambda: _ReturnTrueAfter(now + 1), timeout_secs=0.5)
+
+
+class EnumTest(unittest.TestCase):
+  def testArgsEnum(self):
+    ret = utils.Enum('A', 'B', 'C')
+    self.assertEquals(ret.A, 0)
+    self.assertEquals(ret.B, 1)
+    self.assertEquals(ret.C, 2)
+
+  def testKwargsEnum(self):
+    ret = utils.Enum(A='a', B=1, C=False)
+    self.assertEquals(ret.A, 'a')
+    self.assertEquals(ret.B, 1)
+    self.assertEquals(ret.C, False)
+
+  def testArgsAndKwargsEnum(self):
+    ret = utils.Enum('foo', 'bar', A='a', B=1, C=None)
+    self.assertEquals(ret.foo, 0)
+    self.assertEquals(ret.bar, 1)
+    self.assertEquals(ret.A, 'a')
+    self.assertEquals(ret.B, 1)
+    self.assertEquals(ret.C, None)
+
+  def testEnumImmutable(self):
+    ret = utils.Enum('foo')
+    with self.assertRaises(AttributeError):
+      ret.foo = 'NO WAY!!'
OSZAR »