From 764b7ea78d506cf06828e4034946d86afa67770a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Araujo?= Date: Sat, 8 Dec 2018 00:47:54 -0500 Subject: [PATCH] Add support for reverse iteration of Choices (#314) --- CHANGES.rst | 1 + model_utils/choices.py | 3 +++ tests/test_choices.py | 28 ++++++++++++++++++++++++---- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 7d71665..4eff3da 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,6 +6,7 @@ master (unreleased) - Fix handling of deferred attributes on Django 1.10+, fixes GH-278 - Fix `FieldTracker.has_changed()` and `FieldTracker.previous()` to return correct responses for deferred fields. +- Support `reversed` for all kinds of `Choices` objects, fixes GH-309 - Fix Model instance non picklable GH-330 3.1.2 (2018.05.09) diff --git a/model_utils/choices.py b/model_utils/choices.py index 681e44b..6339503 100644 --- a/model_utils/choices.py +++ b/model_utils/choices.py @@ -102,6 +102,9 @@ class Choices(object): def __iter__(self): return iter(self._doubles) + def __reversed__(self): + return reversed(self._doubles) + def __getattr__(self, attname): try: return self._identifier_map[attname] diff --git a/tests/test_choices.py b/tests/test_choices.py index 29dbb36..986670c 100644 --- a/tests/test_choices.py +++ b/tests/test_choices.py @@ -16,7 +16,12 @@ class ChoicesTests(TestCase): self.assertEqual(self.STATUS['PUBLISHED'], 'PUBLISHED') def test_iteration(self): - self.assertEqual(tuple(self.STATUS), (('DRAFT', 'DRAFT'), ('PUBLISHED', 'PUBLISHED'))) + self.assertEqual(tuple(self.STATUS), + (('DRAFT', 'DRAFT'), ('PUBLISHED', 'PUBLISHED'))) + + def test_reversed(self): + self.assertEqual(tuple(reversed(self.STATUS)), + (('PUBLISHED', 'PUBLISHED'), ('DRAFT', 'DRAFT'))) def test_len(self): self.assertEqual(len(self.STATUS), 2) @@ -78,8 +83,15 @@ class LabelChoicesTests(ChoicesTests): self.assertEqual(tuple(self.STATUS), ( ('DRAFT', 'is draft'), ('PUBLISHED', 'is published'), - ('DELETED', 'DELETED')) - ) + ('DELETED', 'DELETED'), + )) + + def test_reversed(self): + self.assertEqual(tuple(reversed(self.STATUS)), ( + ('DELETED', 'DELETED'), + ('PUBLISHED', 'is published'), + ('DRAFT', 'is draft'), + )) def test_indexing(self): self.assertEqual(self.STATUS['PUBLISHED'], 'is published') @@ -169,7 +181,15 @@ class IdentifierChoicesTests(ChoicesTests): self.assertEqual(tuple(self.STATUS), ( (0, 'is draft'), (1, 'is published'), - (2, 'is deleted'))) + (2, 'is deleted'), + )) + + def test_reversed(self): + self.assertEqual(tuple(reversed(self.STATUS)), ( + (2, 'is deleted'), + (1, 'is published'), + (0, 'is draft'), + )) def test_indexing(self): self.assertEqual(self.STATUS[1], 'is published')