Skip to content

Instantly share code, notes, and snippets.

@gsakkis
Created September 28, 2010 21:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gsakkis/601855 to your computer and use it in GitHub Desktop.
Save gsakkis/601855 to your computer and use it in GitHub Desktop.
from collections import Mapping, namedtuple
def choices(fields):
'''Create a tuple-like instance appropriate for Django's ``Field.choices``.
Additionally the returned instance also supports attribute access by field name.
Example usage::
>>> t = choices(enumerate(['abc', 'pqr', 'xyz']))
>>> list(t)
[(0, 'abc'), (1, 'pqr'), (2, 'xyz')]
>>> (t.abc, t.pqr, t.xyz)
(0, 1, 2)
>>> list(choices({0:'abc', 1:'pqr', 2:'xyz'}))
[(0, 'abc'), (1, 'pqr'), (2, 'xyz')]
>>> list(choices(['abc', 'pqr', 'xyz']))
[('abc', 'abc'), ('pqr', 'pqr'), ('xyz', 'xyz')]
>>> list(choices('abc pqr xyz'))
[('abc', 'abc'), ('pqr', 'pqr'), ('xyz', 'xyz')]
:param fields: It can be:
1. An iterable of ``(value, name)`` tuples.
2. A ``{value: name}`` mapping.
3. An iterable of names. Equivalent to an iterable of ``(name, name)``
tuples, i.e. the names are used as values too.
4. A space and/or comma separated string. Equivalent to (3) after
splitting it.
'''
clsname = 'Choices_%d' % id(fields)
if isinstance(fields, basestring):
cls = namedtuple(clsname, fields)
values = cls._fields
elif isinstance(fields, Mapping):
cls = namedtuple(clsname, fields.itervalues())
values = fields.keys()
else:
values, names = [], []
for field in fields:
if isinstance(field, basestring):
value = name = field
else:
value, name = field
names.append(name)
values.append(value)
cls = namedtuple(clsname, names)
if len(values) != len(set(values)):
raise ValueError('Field values must be unique')
items = zip(values, cls._fields)
cls.__iter__ = lambda self: iter(items)
return cls(*values)
if __name__ == '__main__':
import doctest; doctest.testmod()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment