- Author:
- willhardy
- Posted:
- November 11, 2008
- Language:
- Python
- Version:
- 1.0
- Score:
- 1 (after 1 ratings)
Seeing snippet 1178 reminded me that I also had a go at writing a Choices class at some point. I'm content with the result, but I doubt xgettext will discover your translation strings, which will no doubt be inconvenient.
Here it is anyway, in all its overly-complicated glory :-) The following demo was pulled from the function's docstring tests.
>>> simple = Choices("one", "two", "three")
>>> simple
Choices(one=0, two=1, three=2)
>>> tuple(simple)
((0, u'ein'), (1, u'zwei'), (2, u'drei'))
>>> (0, _('one')) in simple
True
>>> simple.ONE
0
>>> hasattr(simple, 'FOUR')
False
Ordering just follows the order that positional arguments were given. Keyword arguments are ordered by their value at appear after positional arguments.
>>> [ key for key, val in simple ]
[0, 1, 2]
>>> Choices(one=1, two=2, three=3)
Choices(one=1, two=2, three=3)
A Mix of keyword and non-keyword arguments
>>> Choices("one", two=2, three=3)
Choices(one=0, two=2, three=3)
Automatically generated values (for "one" below) should not clash.
>>> Choices("one", none=0, three=1, four=2)
Choices(one=3, none=0, three=1, four=2)
Here is an example of combined usage, using different object types.
>>> combined = Choices(one=1, two="two", three=None, four=False)
>>> len(combined)
4
>>> (1, _('one')) in combined
True
>>> ('two', _('two')) in combined
True
>>> (None, _('three')) in combined
True
>>> (False, _('four')) in combined
True
And here is an empty choices set. Not sure why you would want this....
>>> empty = Choices()
>>> empty
Choices()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
Title: Choices
Author: Will Hardy (http://willhardy.com.au/)
Date: November 2007
Description: A convenient but complicated Choices tool.
Problems: xgettext probably wont find your strings to be translated.
This is an uncomfortable problem.
"""
from django.utils.translation import ugettext as _
class Choices(tuple):
""" A more readable, convenient way of declaring translatable choices.
"""
def __new__(cls, *args, **kwargs):
# Create a normalised dictionary of items
items = {}
order_list = []
# Add the keyword arguments as is
items.update(kwargs)
# Add the non-keyword arguments, enumerating them automatically
for value, name in enumerate(args):
# Avoid clashes in the automatically generated values
# Explicit values (in the keyword arguments) are allowed to clash
while value in items.values():
value += 1
items[name] = value
order_list.append(name)
# keyword arguments come last
sorted_keywords = [ (value, key) for key, value in kwargs.items() ]
order_list.extend([ key for value, key in sorted(sorted_keywords) ])
# Create the actual choices list
choices = []
for name in order_list:
choices.append((items[name], _(name)))
# Save the choices list as a tuple
self = super(Choices, cls).__new__(cls, choices)
# Add our stored value to the object for reference
for name in order_list:
# Remove all non-alphanumeric characters, replace with non-repeating underscore
key = "_".join("".join([ a.isalnum() and a or " " for a in name]).split()).upper()
setattr(self, key, items[name])
# Add our dictionary of items for reference
self._items = items
self._order_list = order_list
return self
def __repr__(self):
""" Displays a way of re-creating this object. """
return "Choices(%s)" % ", ".join([ "%s=%s" % (name, self._items[name]) for name in self._order_list ] )
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Please login first before commenting.