Login

SuperChoices

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

  1. Template tag - list punctuation for a list of items by shapiromatron 3 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 3 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 10 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 10 months, 4 weeks ago
  5. Help text hyperlinks by sa2812 11 months, 3 weeks ago

Comments

Please login first before commenting.