Skip to content

Commit

Permalink
Add the OrderedChoices subclass
Browse files Browse the repository at this point in the history
It uses OrderedDict for dict_class by default
  • Loading branch information
twidi committed Nov 3, 2016
1 parent 4359387 commit 53f088b
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 8 deletions.
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ If you want these dicts to be ordered, you can pass the dict class to use to the
dict_class = OrderedDict
)
Since version ``1.1``, the new ``OrderedChoices`` class is provided, that is exactly that:
a ``Choices`` using ``OrderedDict`` by default for ``dict_class``.

You can check if a constant, value, or display name exists:

.. code-block:: python
Expand Down
52 changes: 45 additions & 7 deletions extended_choices/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,14 @@ def __unicode__(self):

from __future__ import unicode_literals

import sys
from past.builtins import basestring

if sys.version_info >= (2, 7):
from collections import OrderedDict
else:
from django.utils.datastructures import SortedDict as OrderedDict

from .helpers import ChoiceEntry

__all__ = ['Choices']
Expand Down Expand Up @@ -90,19 +96,14 @@ class Choices(list):
construct your ``Choices`` instance with many calls to ``add_choices``.
dict_class : type, optional
``dict`` by default, it's the dict class to use to create dictionaries (``constants``,
``values`` and ``displays``. Could be set for example to ``OrderedSet``.
``values`` and ``displays``. Could be set for example to ``OrderedDict`` (you can use
``OrderedChoices`` that is a simple subclass using ``OrderedDict``.
Example
-------
Start by declaring your ``Choices``:
>>> import sys
>>> if sys.version_info >= (2, 7):
... from collections import OrderedDict
... else:
... from django.utils.datastructures import SortedDict as OrderedDict
>>> ALIGNMENTS = Choices(
... ('BAD', 10, 'bad'),
... ('NEUTRAL', 20, 'neutral'),
Expand Down Expand Up @@ -827,6 +828,43 @@ def __reduce__(self):
)


class OrderedChoices(Choices):
"""Simple subclass of ``Choices`` using ``OrderedDict`` as ``dict_class``
Example
-------
Start by declaring your ``Choices``:
>>> ALIGNMENTS = OrderedChoices(
... ('BAD', 10, 'bad'),
... ('NEUTRAL', 20, 'neutral'),
... ('CHAOTIC_GOOD', 30, 'chaotic good'),
... ('GOOD', 40, 'good'),
... )
>>> ALIGNMENTS.dict_class
<class 'collections.OrderedDict'>
>>> ALIGNMENTS.constants
OrderedDict([('BAD', ('BAD', 10, 'bad')), ('NEUTRAL', ('NEUTRAL', 20, 'neutral')), ('CHAOTIC_GOOD', ('CHAOTIC_GOOD', 30, 'chaotic good')), ('GOOD', ('GOOD', 40, 'good'))])
>>> ALIGNMENTS.values
OrderedDict([(10, ('BAD', 10, 'bad')), (20, ('NEUTRAL', 20, 'neutral')), (30, ('CHAOTIC_GOOD', 30, 'chaotic good')), (40, ('GOOD', 40, 'good'))])
>>> ALIGNMENTS.displays
OrderedDict([('bad', ('BAD', 10, 'bad')), ('neutral', ('NEUTRAL', 20, 'neutral')), ('chaotic good', ('CHAOTIC_GOOD', 30, 'chaotic good')), ('good', ('GOOD', 40, 'good'))])
"""

def __init__(self, *choices, **kwargs):

# Class to use for dicts
if 'dict_class' not in kwargs:
kwargs['dict_class'] = OrderedDict

super(OrderedChoices, self).__init__(*choices, **kwargs)



def create_choice(klass, choices, subsets, kwargs):
"""Create an instance of a ``Choices`` object.
Expand Down
36 changes: 35 additions & 1 deletion extended_choices/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
from django.utils.functional import Promise
from django.utils.translation import ugettext_lazy

from .choices import Choices
from .choices import Choices, OrderedChoices
from .fields import NamedExtendedChoiceFormField
from .helpers import ChoiceAttributeMixin, ChoiceEntry

Expand Down Expand Up @@ -683,6 +683,40 @@ def test_bool(self):
self.assertTrue(second.value)
self.assertTrue(second.display)

def test_dict_class(self):
"""Test that the dict_class argument is taken into account"""

dict_choices = Choices(
('FOO', 1, 'foo'),
('BAR', 2, 'bar')
)

self.assertIs(dict_choices.dict_class, dict)
self.assertIsInstance(dict_choices.constants, dict)
self.assertIsInstance(dict_choices.values, dict)
self.assertIsInstance(dict_choices.displays, dict)

ordered_dict_choices = Choices(
('FOO', 1, 'foo'),
('BAR', 2, 'bar'),
dict_class=OrderedDict
)

self.assertIs(ordered_dict_choices.dict_class, OrderedDict)
self.assertIsInstance(ordered_dict_choices.constants, OrderedDict)
self.assertIsInstance(ordered_dict_choices.values, OrderedDict)
self.assertIsInstance(ordered_dict_choices.displays, OrderedDict)

ordered_choices = OrderedChoices(
('FOO', 1, 'foo'),
('BAR', 2, 'bar'),
)

self.assertIs(ordered_choices.dict_class, OrderedDict)
self.assertIsInstance(ordered_choices.constants, OrderedDict)
self.assertIsInstance(ordered_choices.values, OrderedDict)
self.assertIsInstance(ordered_choices.displays, OrderedDict)


class ChoiceAttributeMixinTestCase(BaseTestCase):
"""Test the ``ChoiceAttributeMixin`` class."""
Expand Down

0 comments on commit 53f088b

Please sign in to comment.