Skip to content

Instantly share code, notes, and snippets.

@gjbagrowski
Created June 17, 2014 10:49
Show Gist options
  • Save gjbagrowski/91add6f9ddf84fccd830 to your computer and use it in GitHub Desktop.
Save gjbagrowski/91add6f9ddf84fccd830 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals
from six import string_types, integer_types
from itertools import chain
class EnumMetaclass(type):
"""Metaclass for enumerations.
You must define the values using UPPERCASE names and having value in one of
allowed_types.
Generates:
cls.names - reverse dictionary mapping value to name
cls.pairs - sorted list of (id, name) pairs suitable for model choices
cls.values - list of values defined by the enumeration
cls.trans_name - reverse dictionary mapping value to string ready for
translation
cls.display_names - reverse dictionary mapping value to string ready to
display as a human-readable text
cls.display_pairs - sorted list of (id, display_name) pairs suitable for
model choices
Example:
class X(object):
__metaclass__ = EnumMetaclass
A = 1
B = 2
CCC = 3
>>> X.names
{1: 'A', 2: 'B', 3: 'CCC'}
>>> X.values
[1, 2, 3]
>>> X.pairs
[(1, 'A'), (2, 'B'), (3, 'CCC')]
>>> X.trans_names
{1: 'X.A', 2: 'X.B', 3: 'X.CCC'}
>>> X.display_names
[(1, 'A'), (2, 'B'), (3, 'Ccc')]
>>> X.display_pairs
[(1, 'A'), (2, 'B'), (3, 'Ccc')]
"""
allowed_types = tuple(chain(string_types, integer_types, [float]))
def __new__(cls, name, bases, attrs):
def make_display_name(name):
return name.replace('_', ' ').capitalize()
def make_trans_name(attrname):
return "{}.{}".format(name, attrname)
def is_enum_val(item):
key, val = item
return (
key.isupper() and
not key.startswith('__') and
isinstance(val, cls.allowed_types)
)
def map_name(fun, items):
return dict([(item[0], fun(item[1])) for item in items.items()])
attrs['names'] = names = dict([
i[::-1] for i in filter(is_enum_val, attrs.items())
])
attrs['values'] = sorted(names.keys())
attrs['trans_names'] = map_name(make_trans_name, names)
attrs['display_names'] = map_name(make_display_name, names)
attrs['pairs'] = sorted(names.items())
attrs['display_pairs'] = sorted(attrs['display_names'].items())
return type.__new__(cls, name, bases, attrs)
class Enum(object):
__metaclass = EnumMetaclass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment