PageRenderTime 62ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 0ms

/scrumdo-web/apps/activities/scrumdo_model_utils/__init__.py

https://github.com/abstract-open-solutions/ScrumDo
Python | 126 lines | 107 code | 0 blank | 19 comment | 1 complexity | 02b2629111b8edbe7c1c73bd5c3a119e MD5 | raw file
  1. class ChoiceEnum(object):
  2. """
  3. DEPRECATED: Use ``Choices`` (below) instead. This class has less
  4. flexibility for human-readable display, and greater potential for
  5. surprising data corruption if new choices are inserted in the
  6. middle of the list. Automatic assignment of numeric IDs is not
  7. such a great idea after all.
  8. A class to encapsulate handy functionality for lists of choices
  9. for a Django model field.
  10. Accepts verbose choice names as arguments, and automatically
  11. assigns numeric keys to them. When iterated over, behaves as the
  12. standard Django choices list of two-tuples.
  13. Attribute access allows conversion of verbose choice name to
  14. choice key, dictionary access the reverse.
  15. Example:
  16. >>> STATUS = ChoiceEnum('DRAFT', 'PUBLISHED')
  17. >>> STATUS.DRAFT
  18. 0
  19. >>> STATUS[1]
  20. 'PUBLISHED'
  21. >>> tuple(STATUS)
  22. ((0, 'DRAFT'), (1, 'PUBLISHED'))
  23. """
  24. def __init__(self, *choices):
  25. import warnings
  26. warnings.warn("ChoiceEnum is deprecated, use Choices instead.",
  27. PendingDeprecationWarning)
  28. self._choices = tuple(enumerate(choices))
  29. self._choice_dict = dict(self._choices)
  30. self._reverse_dict = dict(((i[1], i[0]) for i in self._choices))
  31. def __iter__(self):
  32. return iter(self._choices)
  33. def __getattr__(self, attname):
  34. try:
  35. return self._reverse_dict[attname]
  36. except KeyError:
  37. raise AttributeError(attname)
  38. def __getitem__(self, key):
  39. return self._choice_dict[key]
  40. def __repr__(self):
  41. return '%s(%s)' % (self.__class__.__name__,
  42. ', '.join(("'%s'" % i[1] for i in self._choices)))
  43. class Choices(object):
  44. """
  45. A class to encapsulate handy functionality for lists of choices
  46. for a Django model field.
  47. Each argument to ``Choices`` is a choice, represented as either a
  48. string, a two-tuple, or a three-tuple.
  49. If a single string is provided, that string is used as the
  50. database representation of the choice as well as the
  51. human-readable presentation.
  52. If a two-tuple is provided, the first item is used as the database
  53. representation and the second the human-readable presentation.
  54. If a triple is provided, the first item is the database
  55. representation, the second a valid Python identifier that can be
  56. used as a readable label in code, and the third the human-readable
  57. presentation. This is most useful when the database representation
  58. must sacrifice readability for some reason: to achieve a specific
  59. ordering, to use an integer rather than a character field, etc.
  60. Regardless of what representation of each choice is originally
  61. given, when iterated over or indexed into, a ``Choices`` object
  62. behaves as the standard Django choices list of two-tuples.
  63. If the triple form is used, the Python identifier names can be
  64. accessed as attributes on the ``Choices`` object, returning the
  65. database representation. (If the single or two-tuple forms are
  66. used and the database representation happens to be a valid Python
  67. identifier, the database representation itself is available as an
  68. attribute on the ``Choices`` object, returning itself.)
  69. """
  70. def __init__(self, *choices):
  71. self._full = []
  72. self._choices = []
  73. self._choice_dict = {}
  74. for choice in self.equalize(choices):
  75. self._full.append(choice)
  76. self._choices.append((choice[0], choice[2]))
  77. self._choice_dict[choice[1]] = choice[0]
  78. def equalize(self, choices):
  79. for choice in choices:
  80. if isinstance(choice, (list, tuple)):
  81. if len(choice) == 3:
  82. yield choice
  83. elif len(choice) == 2:
  84. yield (choice[0], choice[0], choice[1])
  85. else:
  86. raise ValueError("Choices can't handle a list/tuple of length %s, only 2 or 3"
  87. % len(choice))
  88. else:
  89. yield (choice, choice, choice)
  90. def __iter__(self):
  91. return iter(self._choices)
  92. def __getattr__(self, attname):
  93. try:
  94. return self._choice_dict[attname]
  95. except KeyError:
  96. raise AttributeError(attname)
  97. def __getitem__(self, index):
  98. return self._choices[index]
  99. def __repr__(self):
  100. return '%s(%s)' % (self.__class__.__name__,
  101. ', '.join(("%s" % str(i) for i in self._full)))