1e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh"""\
2e8819cdf80ca0e0602d22551a50f970aa68e108dmblighGeneric enumeration support.
3e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh"""
4e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
5e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh__author__ = 'showard@google.com (Steve Howard)'
6e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
7e8819cdf80ca0e0602d22551a50f970aa68e108dmblighclass Enum(object):
80afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    """\
90afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    Utility class to implement Enum-like functionality.
10e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
110afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    >>> e = Enum('String one', 'String two')
120afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    >>> e.STRING_ONE
130afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    0
140afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    >>> e.STRING_TWO
150afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    1
160afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    >>> e.choices()
170afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    [(0, 'String one'), (1, 'String two')]
180afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    >>> e.get_value('String one')
190afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    0
200afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    >>> e.get_string(0)
210afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    'String one'
22e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
230afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    >>> e = Enum('Hello', 'Goodbye', string_values=True)
240afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    >>> e.HELLO, e.GOODBYE
250afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    ('Hello', 'Goodbye')
26e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
270afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    >>> e = Enum('One', 'Two', start_value=1)
280afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    >>> e.ONE
290afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    1
300afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    >>> e.TWO
310afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    2
320afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    """
330afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def __init__(self, *names, **kwargs):
340afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        self.string_values = kwargs.get('string_values')
350afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        start_value = kwargs.get('start_value', 0)
36ef446dd987a5bfe501dc0ae872f87648e83eade1Alex Miller        step = kwargs.get('step', 1)
370afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        self.names = names
380afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        self.values = []
390afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        for i, name in enumerate(names):
400afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            if self.string_values:
410afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                value = name
420afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            else:
43ef446dd987a5bfe501dc0ae872f87648e83eade1Alex Miller                value = i * step + start_value
440afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            self.values.append(value)
450afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            setattr(self, self.get_attr_name(name), value)
46e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
47e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
480afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    @staticmethod
490afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def get_attr_name(string):
500afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        return string.upper().replace(' ', '_')
51e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
52e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
530afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def choices(self):
540afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        'Return choice list suitable for Django model choices.'
550afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        return zip(self.values, self.names)
56e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
57e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
580afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def get_value(self, name):
590afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        """\
600afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        Convert a string name to it's corresponding value.  If a value
610afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        is passed in, it is returned.
620afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        """
637c72f9c6cd22c252a4fbd20c079a471ab3ba9f7eAviv Keshet        if isinstance(name, (int, long)) and not self.string_values:
640afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            # name is already a value
650afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            return name
660afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        return getattr(self, self.get_attr_name(name))
67e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
68e8819cdf80ca0e0602d22551a50f970aa68e108dmbligh
690afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def get_string(self, value):
700afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        ' Given a value, get the string name for it.'
710afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        if value not in self.values:
720afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            raise ValueError('Value %s not in this enum' % value)
730afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        index = self.values.index(value)
740afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        return self.names[index]
75