From fecda79f5c384bd8e9dc1a23bf700880cda50138 Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Thu, 15 Apr 2010 22:54:37 -0400 Subject: [PATCH] deprecate ChoiceEnum and document Choices --- README.rst | 38 +++++++++++++++++--------------------- model_utils/__init__.py | 17 +++++++++++++---- model_utils/tests/tests.py | 22 ++++------------------ 3 files changed, 34 insertions(+), 43 deletions(-) diff --git a/README.rst b/README.rst index 9bab051..3645437 100644 --- a/README.rst +++ b/README.rst @@ -7,7 +7,7 @@ Django model mixins and utilities. Installation ============ -Install from PyPI with ``easy_install`` or ``pip``:: +Install from PyPI with ``pip``:: pip install django-model-utils @@ -28,34 +28,30 @@ Dependencies .. _Django: http://www.djangoproject.com/ -ChoiceEnum -========== +Choices +======= -``ChoiceEnum`` makes setting ``choices`` on a Django model field way +``Choices`` makes setting ``choices`` on a Django model field way too easy:: - from model_utils import ChoiceEnum + from model_utils import Choices class Article(models.Model): - STATUS = ChoiceEnum('draft', 'published') + STATUS = Choices('draft', 'published') # ... - status = models.PositiveIntegerField(choices=STATUS, default=STATUS.draft) + status = models.CharField(choices=STATUS, default=STATUS.draft, max_length=20) - def status_desc(self): - return self.STATUS[self.status] +A ``Choices`` object is initialized with any number of choices, which +can either be a string ID or a tuple of (string ID, human-readable +version). If a string ID is given alone, the ID itself is used as the +human-readable version. Accessing the string ID as an attribute on +the ``Choices`` object returns the human-readable version. If iterated +over, a ``ChoiceEnum`` object yields a tuple of two-tuples linking id +to text names, the format expected by the ``choices`` attribute of +Django models. -A ``ChoiceEnum`` object is initialized with any number of choices, -which should be strings. It assigns a sequential id to each -choice. The numerical id for a choice is available through attribute -access (``STATUS.draft``), and the text name for a choice can be -obtained by indexing with the numerical id -(``self.STATUS[self.status]``). If iterated over, a ``ChoiceEnum`` -object yields a tuple of two-tuples linking id to text names, the -format expected by the ``choices`` attribute of Django models. - -Be careful not to add new choices in the middle of the list, as that -will change the numerical ids for all subsequent choices, which could -impact existing data. +.. note:: + Whither ``ChoiceEnum``? It's been deprecated in favor of ``Choices``. fields.SplitField ================= diff --git a/model_utils/__init__.py b/model_utils/__init__.py index 8f45db1..8b67332 100644 --- a/model_utils/__init__.py +++ b/model_utils/__init__.py @@ -1,5 +1,11 @@ class ChoiceEnum(object): """ + DEPRECATED: Use ``Choices`` (below) instead. This class has less + flexibility for human-readable display, and greater potential for + surprising data corruption if new choices are inserted in the + middle of the list. Automatic assignment of numeric IDs is not + such a great idea after all. + A class to encapsulate handy functionality for lists of choices for a Django model field. @@ -22,6 +28,9 @@ class ChoiceEnum(object): """ def __init__(self, *choices): + import warnings + warnings.warn("ChoiceEnum is deprecated, use Choices instead.", + PendingDeprecationWarning) self._choices = tuple(enumerate(choices)) self._choice_dict = dict(self._choices) self._reverse_dict = dict(((i[1], i[0]) for i in self._choices)) @@ -48,10 +57,10 @@ class Choices(object): A class to encapsulate handy functionality for lists of choices for a Django model field. - Accepts as arguments either tuples mapping choice IDs (numeric or - text) to human-readable names, or simply choice IDs (in which case - the ID is also used as the human-readable name). When iterated - over, behaves as the standard Django choices tuple of two-tuples. + Accepts as arguments either tuples mapping choice IDs (strings) to + human-readable names, or simply choice IDs (in which case the ID + is also used as the human-readable name). When iterated over, + behaves as the standard Django choices tuple of two-tuples. Attribute access allows conversion of choice ID to human-readable name. diff --git a/model_utils/tests/tests.py b/model_utils/tests/tests.py index d303254..d556964 100644 --- a/model_utils/tests/tests.py +++ b/model_utils/tests/tests.py @@ -76,20 +76,6 @@ class SplitFieldTests(TestCase): self.assertRaises(AttributeError, _invalid_assignment) -class ChoiceEnumTests(TestCase): - def setUp(self): - self.STATUS = ChoiceEnum('DRAFT', 'PUBLISHED') - - def test_getattr(self): - self.assertEquals(self.STATUS.DRAFT, 0) - - def test_getitem(self): - self.assertEquals(self.STATUS[1], 'PUBLISHED') - - def test_iteration(self): - self.assertEquals(tuple(self.STATUS), ((0, 'DRAFT'), (1, 'PUBLISHED'))) - - class ChoicesTests(TestCase): def setUp(self): self.STATUS = Choices('DRAFT', 'PUBLISHED') @@ -103,15 +89,15 @@ class ChoicesTests(TestCase): class LabelChoicesTests(ChoicesTests): def setUp(self): self.STATUS = Choices( - ('DRAFT', 'draft'), - ('PUBLISHED', 'published'), + ('DRAFT', 'is draft'), + ('PUBLISHED', 'is published'), 'DELETED', ) def test_iteration(self): self.assertEquals(tuple(self.STATUS), ( - ('DRAFT', 'draft'), - ('PUBLISHED', 'published'), + ('DRAFT', 'is draft'), + ('PUBLISHED', 'is published'), ('DELETED', 'DELETED')) )