django-enum 2.2.2__tar.gz → 2.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. {django_enum-2.2.2 → django_enum-2.2.3}/.github/workflows/debug.yml +2 -2
  2. {django_enum-2.2.2 → django_enum-2.2.3}/.github/workflows/lint.yml +2 -2
  3. {django_enum-2.2.2 → django_enum-2.2.3}/.github/workflows/release.yml +1 -1
  4. {django_enum-2.2.2 → django_enum-2.2.3}/.github/workflows/test.yml +15 -15
  5. {django_enum-2.2.2 → django_enum-2.2.3}/PKG-INFO +1 -1
  6. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/changelog.rst +5 -0
  7. django_enum-2.2.3/doc/source/howto/admin.rst +13 -0
  8. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/howto/external.rst +31 -0
  9. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/howto/index.rst +1 -0
  10. {django_enum-2.2.2 → django_enum-2.2.3}/pyproject.toml +1 -1
  11. {django_enum-2.2.2 → django_enum-2.2.3}/src/django_enum/__init__.py +1 -1
  12. {django_enum-2.2.2 → django_enum-2.2.3}/tests/djenum/admin.py +8 -1
  13. {django_enum-2.2.2 → django_enum-2.2.3}/tests/djenum/enums.py +58 -0
  14. {django_enum-2.2.2 → django_enum-2.2.3}/tests/djenum/models.py +9 -0
  15. django_enum-2.2.3/tests/examples/hash_equivalency_howto.py +37 -0
  16. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/__init__.py +2 -0
  17. django_enum-2.2.3/tests/examples/models/hash_equivalency.py +55 -0
  18. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_examples.py +3 -0
  19. {django_enum-2.2.2 → django_enum-2.2.3}/uv.lock +1 -1
  20. {django_enum-2.2.2 → django_enum-2.2.3}/.codecov.yml +0 -0
  21. {django_enum-2.2.2 → django_enum-2.2.3}/.gitattributes +0 -0
  22. {django_enum-2.2.2 → django_enum-2.2.3}/.github/dependabot.yml +0 -0
  23. {django_enum-2.2.2 → django_enum-2.2.3}/.github/workflows/scorecard.yml +0 -0
  24. {django_enum-2.2.2 → django_enum-2.2.3}/.github/workflows/zizmor.yml +0 -0
  25. {django_enum-2.2.2 → django_enum-2.2.3}/.gitignore +0 -0
  26. {django_enum-2.2.2 → django_enum-2.2.3}/.pre-commit-config.yaml +0 -0
  27. {django_enum-2.2.2 → django_enum-2.2.3}/CODE_OF_CONDUCT.md +0 -0
  28. {django_enum-2.2.2 → django_enum-2.2.3}/CONTRIBUTING.md +0 -0
  29. {django_enum-2.2.2 → django_enum-2.2.3}/LICENSE +0 -0
  30. {django_enum-2.2.2 → django_enum-2.2.3}/README.md +0 -0
  31. {django_enum-2.2.2 → django_enum-2.2.3}/SECURITY.md +0 -0
  32. {django_enum-2.2.2 → django_enum-2.2.3}/doc/.readthedocs.yaml +0 -0
  33. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/conf.py +0 -0
  34. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/eccentric.rst +0 -0
  35. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/howto/flags.rst +0 -0
  36. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/howto/forms.rst +0 -0
  37. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/howto/integrations.rst +0 -0
  38. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/howto/migrations.rst +0 -0
  39. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/howto/options.rst +0 -0
  40. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/howto/urls.rst +0 -0
  41. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/index.rst +0 -0
  42. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/performance.rst +0 -0
  43. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/plots/FlagSizeBenchmark.png +0 -0
  44. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/plots/IndexedExactQueryPerformance_postgres.png +0 -0
  45. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/plots/NoIndexQueryPerformance_postgres.png +0 -0
  46. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/plots/QueryPerformance_postgresql.png +0 -0
  47. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/reference/DRF.rst +0 -0
  48. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/reference/choices.rst +0 -0
  49. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/reference/fields.rst +0 -0
  50. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/reference/filters.rst +0 -0
  51. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/reference/forms.rst +0 -0
  52. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/reference/index.rst +0 -0
  53. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/reference/query.rst +0 -0
  54. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/reference/urls.rst +0 -0
  55. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/reference/utils.rst +0 -0
  56. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/reference/widgets.rst +0 -0
  57. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/refs.rst +0 -0
  58. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/tutorials/flags.rst +0 -0
  59. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/tutorials/index.rst +0 -0
  60. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/tutorials/properties.rst +0 -0
  61. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/widgets/FlagCheckbox.png +0 -0
  62. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/widgets/FlagCheckbox_nulls.png +0 -0
  63. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/widgets/FlagSelectMultiple.png +0 -0
  64. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/widgets/NonStrictFlagCheckbox.png +0 -0
  65. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/widgets/NonStrictFlagSelectMultiple.png +0 -0
  66. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/widgets/NonStrictRadioSelect.png +0 -0
  67. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/widgets/NonStrictSelect.png +0 -0
  68. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/widgets/RadioSelect.png +0 -0
  69. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/widgets/RadioSelect_nulls.png +0 -0
  70. {django_enum-2.2.2 → django_enum-2.2.3}/doc/source/widgets/Select.png +0 -0
  71. {django_enum-2.2.2 → django_enum-2.2.3}/justfile +0 -0
  72. {django_enum-2.2.2 → django_enum-2.2.3}/src/django_enum/choices.py +0 -0
  73. {django_enum-2.2.2 → django_enum-2.2.3}/src/django_enum/drf.py +0 -0
  74. {django_enum-2.2.2 → django_enum-2.2.3}/src/django_enum/fields.py +0 -0
  75. {django_enum-2.2.2 → django_enum-2.2.3}/src/django_enum/filters.py +0 -0
  76. {django_enum-2.2.2 → django_enum-2.2.3}/src/django_enum/forms.py +0 -0
  77. {django_enum-2.2.2 → django_enum-2.2.3}/src/django_enum/py.typed +0 -0
  78. {django_enum-2.2.2 → django_enum-2.2.3}/src/django_enum/query.py +0 -0
  79. {django_enum-2.2.2 → django_enum-2.2.3}/src/django_enum/urls.py +0 -0
  80. {django_enum-2.2.2 → django_enum-2.2.3}/src/django_enum/utils.py +0 -0
  81. {django_enum-2.2.2 → django_enum-2.2.3}/tests/__init__.py +0 -0
  82. {django_enum-2.2.2 → django_enum-2.2.3}/tests/benchmark/__init__.py +0 -0
  83. {django_enum-2.2.2 → django_enum-2.2.3}/tests/benchmark/apps.py +0 -0
  84. {django_enum-2.2.2 → django_enum-2.2.3}/tests/benchmark/enums.py +0 -0
  85. {django_enum-2.2.2 → django_enum-2.2.3}/tests/benchmark/models.py +0 -0
  86. {django_enum-2.2.2 → django_enum-2.2.3}/tests/benchmarks.py +0 -0
  87. {django_enum-2.2.2 → django_enum-2.2.3}/tests/constraints/__init__.py +0 -0
  88. {django_enum-2.2.2 → django_enum-2.2.3}/tests/constraints/apps.py +0 -0
  89. {django_enum-2.2.2 → django_enum-2.2.3}/tests/constraints/enums.py +0 -0
  90. {django_enum-2.2.2 → django_enum-2.2.3}/tests/constraints/models.py +0 -0
  91. {django_enum-2.2.2 → django_enum-2.2.3}/tests/converters/__init__.py +0 -0
  92. {django_enum-2.2.2 → django_enum-2.2.3}/tests/converters/apps.py +0 -0
  93. {django_enum-2.2.2 → django_enum-2.2.3}/tests/converters/urls.py +0 -0
  94. {django_enum-2.2.2 → django_enum-2.2.3}/tests/db_default/__init__.py +0 -0
  95. {django_enum-2.2.2 → django_enum-2.2.3}/tests/db_default/apps.py +0 -0
  96. {django_enum-2.2.2 → django_enum-2.2.3}/tests/db_default/models.py +0 -0
  97. {django_enum-2.2.2 → django_enum-2.2.3}/tests/djenum/__init__.py +0 -0
  98. {django_enum-2.2.2 → django_enum-2.2.3}/tests/djenum/apps.py +0 -0
  99. {django_enum-2.2.2 → django_enum-2.2.3}/tests/djenum/forms.py +0 -0
  100. {django_enum-2.2.2 → django_enum-2.2.3}/tests/djenum/urls.py +0 -0
  101. {django_enum-2.2.2 → django_enum-2.2.3}/tests/djenum/views.py +0 -0
  102. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/__init__.py +0 -0
  103. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/apps.py +0 -0
  104. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/edits/_1.py +0 -0
  105. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/edits/_10.py +0 -0
  106. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/edits/_2.py +0 -0
  107. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/edits/_3.py +0 -0
  108. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/edits/_4.py +0 -0
  109. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/edits/_5.py +0 -0
  110. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/edits/_6.py +0 -0
  111. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/edits/_7.py +0 -0
  112. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/edits/_8.py +0 -0
  113. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/edits/_9.py +0 -0
  114. {django_enum-2.2.2 → django_enum-2.2.3}/tests/edit_tests/models.py +0 -0
  115. {django_enum-2.2.2 → django_enum-2.2.3}/tests/enum_prop/__init__.py +0 -0
  116. {django_enum-2.2.2 → django_enum-2.2.3}/tests/enum_prop/admin.py +0 -0
  117. {django_enum-2.2.2 → django_enum-2.2.3}/tests/enum_prop/apps.py +0 -0
  118. {django_enum-2.2.2 → django_enum-2.2.3}/tests/enum_prop/enums.py +0 -0
  119. {django_enum-2.2.2 → django_enum-2.2.3}/tests/enum_prop/forms.py +0 -0
  120. {django_enum-2.2.2 → django_enum-2.2.3}/tests/enum_prop/models.py +0 -0
  121. {django_enum-2.2.2 → django_enum-2.2.3}/tests/enum_prop/urls.py +0 -0
  122. {django_enum-2.2.2 → django_enum-2.2.3}/tests/enum_prop/views.py +0 -0
  123. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/__init__.py +0 -0
  124. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/admin.py +0 -0
  125. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/apps.py +0 -0
  126. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/basic_example.py +0 -0
  127. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/checkboxes_form_howto.py +0 -0
  128. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/choice_form_howto.py +0 -0
  129. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/custom_value_example.py +0 -0
  130. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/drf_modelserializer_howto.py +0 -0
  131. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/drf_serializer_howto.py +0 -0
  132. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/enums/__init__.py +0 -0
  133. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/enums/color.py +0 -0
  134. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/enums/permissions.py +0 -0
  135. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/equivalency_howto.py +0 -0
  136. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/extern_howto.py +0 -0
  137. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/filterfield_howto.py +0 -0
  138. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/filterset_howto.py +0 -0
  139. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/flag_example.py +0 -0
  140. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/flag_form_howto.py +0 -0
  141. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/flag_howto.py +0 -0
  142. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/flagfilterfield_howto.py +0 -0
  143. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/gnss_tutorial.py +0 -0
  144. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/gnss_vanilla_tutorial.py +0 -0
  145. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/mapbox_tutorial.py +0 -0
  146. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/mixed_value_example.py +0 -0
  147. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/basic.py +0 -0
  148. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/custom_value.py +0 -0
  149. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/equivalency.py +0 -0
  150. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/extern.py +0 -0
  151. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/flag.py +0 -0
  152. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/flag_howto.py +0 -0
  153. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/gnss.py +0 -0
  154. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/gnss_vanilla.py +0 -0
  155. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/mapbox.py +0 -0
  156. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/mixed_value.py +0 -0
  157. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/no_coerce.py +0 -0
  158. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/path_value.py +0 -0
  159. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/properties.py +0 -0
  160. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/properties_choices.py +0 -0
  161. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/strict.py +0 -0
  162. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/text_choices.py +0 -0
  163. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/models/widgets.py +0 -0
  164. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/no_coerce_howto.py +0 -0
  165. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/path_value_example.py +0 -0
  166. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/properties_example.py +0 -0
  167. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/radio_form_howto.py +0 -0
  168. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/strict_howto.py +0 -0
  169. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/templates/tests_examples/choice_form_howto.html +0 -0
  170. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/templates/tests_examples/flag_form_howto.html +0 -0
  171. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/templates/tests_examples/textchoicesexample_filter.html +0 -0
  172. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/text_choices_howto.py +0 -0
  173. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/url_converter_howto.py +0 -0
  174. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/urls.py +0 -0
  175. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/urls_forms.py +0 -0
  176. {django_enum-2.2.2 → django_enum-2.2.3}/tests/examples/urls_howto.py +0 -0
  177. {django_enum-2.2.2 → django_enum-2.2.3}/tests/flag_constraints/__init__.py +0 -0
  178. {django_enum-2.2.2 → django_enum-2.2.3}/tests/flag_constraints/apps.py +0 -0
  179. {django_enum-2.2.2 → django_enum-2.2.3}/tests/flag_constraints/enums.py +0 -0
  180. {django_enum-2.2.2 → django_enum-2.2.3}/tests/flag_constraints/models.py +0 -0
  181. {django_enum-2.2.2 → django_enum-2.2.3}/tests/oracle_patch.py +0 -0
  182. {django_enum-2.2.2 → django_enum-2.2.3}/tests/settings.py +0 -0
  183. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_admin.py +0 -0
  184. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_admin_ep.py +0 -0
  185. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_bulk.py +0 -0
  186. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_bulk_ep.py +0 -0
  187. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_choices.py +0 -0
  188. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_choices_ep.py +0 -0
  189. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_constraints.py +0 -0
  190. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_converter.py +0 -0
  191. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_db_defaults.py +0 -0
  192. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_eccentric.py +0 -0
  193. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_enum_props.py +0 -0
  194. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_errors.py +0 -0
  195. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_external.py +0 -0
  196. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_field_types.py +0 -0
  197. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_field_types_ep.py +0 -0
  198. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_flags.py +0 -0
  199. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_flags_ep.py +0 -0
  200. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_forms.py +0 -0
  201. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_forms_ep.py +0 -0
  202. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_migrations.py +0 -0
  203. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_name_override.py +0 -0
  204. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_queries.py +0 -0
  205. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_queries_ep.py +0 -0
  206. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_requests.py +0 -0
  207. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_requests_ep.py +0 -0
  208. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_requests_flags.py +0 -0
  209. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_requests_flags_ep.py +0 -0
  210. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_utils.py +0 -0
  211. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_validation.py +0 -0
  212. {django_enum-2.2.2 → django_enum-2.2.3}/tests/test_verify_environment.py +0 -0
  213. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/__init__.py +0 -0
  214. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/apps.py +0 -0
  215. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/templates/base.html +0 -0
  216. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/templates/enumtester_confirm_delete.html +0 -0
  217. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/templates/enumtester_detail.html +0 -0
  218. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/templates/enumtester_form.html +0 -0
  219. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/templates/enumtester_list.html +0 -0
  220. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/templates/flagtester_confirm_delete.html +0 -0
  221. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/templates/flagtester_detail.html +0 -0
  222. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/templates/flagtester_form.html +0 -0
  223. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/templates/flagtester_list.html +0 -0
  224. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/templatetags/__init__.py +0 -0
  225. {django_enum-2.2.2 → django_enum-2.2.3}/tests/tmpls/templatetags/test_tags.py +0 -0
  226. {django_enum-2.2.2 → django_enum-2.2.3}/tests/urls.py +0 -0
  227. {django_enum-2.2.2 → django_enum-2.2.3}/tests/utils.py +0 -0
@@ -35,7 +35,7 @@ jobs:
35
35
  with:
36
36
  python-version: ${{ github.event.inputs.python-version }}
37
37
  - name: Install uv
38
- uses: astral-sh/setup-uv@v5
38
+ uses: astral-sh/setup-uv@v6
39
39
  with:
40
40
  enable-cache: true
41
41
  - name: Install Just
@@ -47,7 +47,7 @@ jobs:
47
47
  run: |
48
48
  sudo apt install emacs
49
49
  - name: Setup tmate session
50
- uses: mxschmitt/action-tmate@v3.19
50
+ uses: mxschmitt/action-tmate@v3.21
51
51
  with:
52
52
  detached: true
53
53
  timeout-minutes: 60
@@ -54,7 +54,7 @@ jobs:
54
54
  with:
55
55
  python-version: ${{ matrix.python-version }}
56
56
  - name: Install uv
57
- uses: astral-sh/setup-uv@v5
57
+ uses: astral-sh/setup-uv@v6
58
58
  with:
59
59
  enable-cache: true
60
60
  - name: Install Just
@@ -70,7 +70,7 @@ jobs:
70
70
  sudo apt install emacs
71
71
  - name: Setup tmate session
72
72
  if: ${{ github.event.inputs.debug == 'true' }}
73
- uses: mxschmitt/action-tmate@v3.19
73
+ uses: mxschmitt/action-tmate@v3.21
74
74
  with:
75
75
  detached: true
76
76
  timeout-minutes: 60
@@ -46,7 +46,7 @@ jobs:
46
46
  with:
47
47
  python-version: "3.12" # for tomlib
48
48
  - name: Install uv
49
- uses: astral-sh/setup-uv@v5
49
+ uses: astral-sh/setup-uv@v6
50
50
  with:
51
51
  enable-cache: true
52
52
  - name: Setup Just
@@ -118,7 +118,7 @@ jobs:
118
118
  with:
119
119
  python-version: ${{ matrix.python-version }}
120
120
  - name: Install uv
121
- uses: astral-sh/setup-uv@v5
121
+ uses: astral-sh/setup-uv@v6
122
122
  with:
123
123
  enable-cache: true
124
124
  - name: Setup Just
@@ -133,7 +133,7 @@ jobs:
133
133
  sudo apt install emacs
134
134
  - name: Setup tmate session
135
135
  if: ${{ github.event.inputs.debug == 'true' }}
136
- uses: mxschmitt/action-tmate@v3.19
136
+ uses: mxschmitt/action-tmate@v3.21
137
137
  with:
138
138
  detached: true
139
139
  timeout-minutes: 60
@@ -180,7 +180,7 @@ jobs:
180
180
  with:
181
181
  python-version: ${{ matrix.python-version }}
182
182
  - name: Install uv
183
- uses: astral-sh/setup-uv@v5
183
+ uses: astral-sh/setup-uv@v6
184
184
  with:
185
185
  enable-cache: true
186
186
  - name: Setup Just
@@ -196,7 +196,7 @@ jobs:
196
196
  sudo apt install emacs
197
197
  - name: Setup tmate session
198
198
  if: ${{ github.event.inputs.debug == 'true' }}
199
- uses: mxschmitt/action-tmate@v3.19
199
+ uses: mxschmitt/action-tmate@v3.21
200
200
  with:
201
201
  detached: true
202
202
  timeout-minutes: 60
@@ -284,12 +284,12 @@ jobs:
284
284
  sudo apt install emacs
285
285
  - name: Setup tmate session
286
286
  if: ${{ github.event.inputs.debug == 'true' }}
287
- uses: mxschmitt/action-tmate@v3.19
287
+ uses: mxschmitt/action-tmate@v3.21
288
288
  with:
289
289
  detached: true
290
290
  timeout-minutes: 60
291
291
  - name: Install uv
292
- uses: astral-sh/setup-uv@v5
292
+ uses: astral-sh/setup-uv@v6
293
293
  with:
294
294
  enable-cache: true
295
295
  - name: Setup Just
@@ -389,12 +389,12 @@ jobs:
389
389
  sudo apt install emacs
390
390
  - name: Setup tmate session
391
391
  if: ${{ github.event.inputs.debug == 'true' }}
392
- uses: mxschmitt/action-tmate@v3.19
392
+ uses: mxschmitt/action-tmate@v3.21
393
393
  with:
394
394
  detached: true
395
395
  timeout-minutes: 60
396
396
  - name: Install uv
397
- uses: astral-sh/setup-uv@v5
397
+ uses: astral-sh/setup-uv@v6
398
398
  with:
399
399
  enable-cache: true
400
400
  - name: Setup Just
@@ -490,12 +490,12 @@ jobs:
490
490
  sudo apt install emacs
491
491
  - name: Setup tmate session
492
492
  if: ${{ github.event.inputs.debug == 'true' }}
493
- uses: mxschmitt/action-tmate@v3.19
493
+ uses: mxschmitt/action-tmate@v3.21
494
494
  with:
495
495
  detached: true
496
496
  timeout-minutes: 60
497
497
  - name: Install uv
498
- uses: astral-sh/setup-uv@v5
498
+ uses: astral-sh/setup-uv@v6
499
499
  with:
500
500
  enable-cache: true
501
501
  - name: Setup Just
@@ -556,7 +556,7 @@ jobs:
556
556
  with:
557
557
  python-version: ${{ matrix.python-version }}
558
558
  - name: Install uv
559
- uses: astral-sh/setup-uv@v5
559
+ uses: astral-sh/setup-uv@v6
560
560
  with:
561
561
  enable-cache: true
562
562
  - name: Setup Just
@@ -571,7 +571,7 @@ jobs:
571
571
  uses: rhysd/action-setup-vim@v1
572
572
  - name: Setup tmate session
573
573
  if: ${{ github.event.inputs.debug == 'true' }}
574
- uses: mxschmitt/action-tmate@v3.19
574
+ uses: mxschmitt/action-tmate@v3.21
575
575
  with:
576
576
  detached: true
577
577
  timeout-minutes: 60
@@ -617,7 +617,7 @@ jobs:
617
617
  with:
618
618
  python-version: ${{ matrix.python-version }}
619
619
  - name: Install uv
620
- uses: astral-sh/setup-uv@v5
620
+ uses: astral-sh/setup-uv@v6
621
621
  with:
622
622
  enable-cache: true
623
623
  - name: Setup Just
@@ -633,7 +633,7 @@ jobs:
633
633
  brew install emacs
634
634
  - name: Setup tmate session
635
635
  if: ${{ github.event.inputs.debug == 'true' }}
636
- uses: mxschmitt/action-tmate@v3.19
636
+ uses: mxschmitt/action-tmate@v3.21
637
637
  with:
638
638
  detached: true
639
639
  timeout-minutes: 60
@@ -659,7 +659,7 @@ jobs:
659
659
  with:
660
660
  python-version: '3.12'
661
661
  - name: Install uv
662
- uses: astral-sh/setup-uv@v5
662
+ uses: astral-sh/setup-uv@v6
663
663
  with:
664
664
  enable-cache: true
665
665
  - name: Setup Just
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-enum
3
- Version: 2.2.2
3
+ Version: 2.2.3
4
4
  Summary: Full and natural support for enumerations as Django model fields.
5
5
  Project-URL: Homepage, https://django-enum.readthedocs.io
6
6
  Project-URL: Documentation, https://django-enum.readthedocs.io
@@ -4,6 +4,11 @@
4
4
  Change Log
5
5
  ==========
6
6
 
7
+ v2.2.3 (2025-04-28)
8
+ ===================
9
+
10
+ * Add docs on hash equivalency, fixing `Enum value doesn't show in Django Admin's list_display <https://github.com/django-commons/django-enum/issues/123>`_
11
+
7
12
  v2.2.2 (2025-04-18)
8
13
  ===================
9
14
 
@@ -0,0 +1,13 @@
1
+ .. include:: ../refs.rst
2
+
3
+ .. _admin:
4
+
5
+ ================
6
+ Use Django Admin
7
+ ================
8
+
9
+ :class:`~django_enum.fields.EnumField` will mostly just work in the Django
10
+ :mod:`~django.contrib.admin`. There is
11
+ `one issue <https://github.com/django-commons/django-enum/issues/123>`_ where :ref:`enums that are
12
+ not hash equivalent <hash_equivalency>` will not render value labels correctly in the
13
+ :class:`~django.contrib.admin.ModelAdmin` :attr:`~django.contrib.admin.ModelAdmin.list_display`.
@@ -29,3 +29,34 @@ The list of choice tuples for each field are:
29
29
  values assigned depend on the order of declaration. This means that if the order changes
30
30
  existing database values will no longer align with the enumeration values. When control over the
31
31
  values is not certain it is a good idea to add integration tests that look for value changes.
32
+
33
+ .. _hash_equivalency:
34
+
35
+ Hash Equivalency
36
+ ----------------
37
+
38
+ .. tip::
39
+
40
+ It is a good idea to make sure your enumeration instances are hash equivalent to their
41
+ primitive values. You can do this simply by inheriting from their primitive value
42
+ (e.g. ``class MyEnum(str, Enum):``) or by using :class:`~enum.StrEnum` and
43
+ :class:`~enum.IntEnum` types. Any enumeration defined using :doc:`enum-properties:index`
44
+ will be hash equivalent to its values by default.
45
+
46
+ :class:`~django_enum.fields.EnumField` automatically sets the choices tuple on the field. Django_
47
+ has logic in a number of places that handles fields with choices in a special way
48
+ (e.g. :ref:`in the admin <admin>`). For example, the choices may be converted to a dictionary
49
+ mapping values to labels. The values will be the primitive values of the enumeration not
50
+ enumeration instances and the current value of the field which may be an enumeration instance will
51
+ be searched for in the dictionary. This will fail if the enumeration instance is not hash
52
+ equivalent to its value.
53
+
54
+ To control the hashing behavior of an object, you must override its :meth:`~object.__hash__` and
55
+ :meth:`~object.__eq__` methods.
56
+
57
+ For example:
58
+
59
+ .. literalinclude:: ../../../tests/examples/models/hash_equivalency.py
60
+
61
+ .. literalinclude:: ../../../tests/examples/hash_equivalency_howto.py
62
+ :lines: 3-
@@ -45,3 +45,4 @@ are possible with :class:`~django_enum.fields.EnumField`. See :ref:`enum_props`.
45
45
  integrations
46
46
  migrations
47
47
  urls
48
+ admin
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "django-enum"
3
- version = "2.2.2"
3
+ version = "2.2.3"
4
4
  description = "Full and natural support for enumerations as Django model fields."
5
5
  requires-python = ">=3.9,<4.0"
6
6
  authors = [
@@ -16,7 +16,7 @@ from django_enum.fields import EnumField
16
16
 
17
17
  __all__ = ["EnumField"]
18
18
 
19
- VERSION = (2, 2, 2)
19
+ VERSION = (2, 2, 3)
20
20
 
21
21
  __title__ = "Django Enum"
22
22
  __version__ = ".".join(str(i) for i in VERSION)
@@ -27,7 +27,14 @@ admin.site.register(NullableStrFormTester)
27
27
 
28
28
 
29
29
  class AdminDisplayBug35Admin(admin.ModelAdmin):
30
- list_display = ("text_enum", "int_enum")
30
+ list_display = (
31
+ "text_enum",
32
+ "int_enum",
33
+ "status_basic",
34
+ "status_basic_int",
35
+ "status_str",
36
+ "status_int",
37
+ )
31
38
  readonly_fields = ("text_enum", "int_enum", "blank_int", "blank_txt")
32
39
 
33
40
 
@@ -398,3 +398,61 @@ class GNSSConstellation(IntFlag):
398
398
  GALILEO = 1 << 2
399
399
  BEIDOU = 1 << 3
400
400
  QZSS = 1 << 4
401
+
402
+
403
+ class NestStatusBasic(Enum):
404
+ INIT = "INIT"
405
+ LOADED = "LOADED"
406
+ ACTIVE = "ACTIVE"
407
+ DONE = "DONE"
408
+ REJECTED = "REJECTED"
409
+ CANCELLED = "CANCELLED"
410
+
411
+ def __hash__(self):
412
+ return hash(self.value)
413
+
414
+ def __eq__(self, value) -> bool:
415
+ if isinstance(value, self.__class__):
416
+ return self.value == value.value
417
+ try:
418
+ return self.value == self.__class__(value).value
419
+ except (ValueError, TypeError):
420
+ return False
421
+
422
+
423
+ class NestStatusStr(str, Enum):
424
+ INIT = "INIT"
425
+ LOADED = "LOADED"
426
+ ACTIVE = "ACTIVE"
427
+ DONE = "DONE"
428
+ REJECTED = "REJECTED"
429
+ CANCELLED = "CANCELLED"
430
+
431
+
432
+ class NestStatusBasicInt(Enum):
433
+ INIT = 0
434
+ LOADED = 1
435
+ ACTIVE = 2
436
+ DONE = 3
437
+ REJECTED = 4
438
+ CANCELLED = 5
439
+
440
+ def __hash__(self):
441
+ return hash(self.value)
442
+
443
+ def __eq__(self, value) -> bool:
444
+ if isinstance(value, self.__class__):
445
+ return self.value == value.value
446
+ try:
447
+ return self.value == self.__class__(value).value
448
+ except (ValueError, TypeError):
449
+ return False
450
+
451
+
452
+ class NestStatusInt(int, Enum):
453
+ INIT = 0
454
+ LOADED = 1
455
+ ACTIVE = 2
456
+ DONE = 3
457
+ REJECTED = 4
458
+ CANCELLED = 5
@@ -41,6 +41,10 @@ from tests.djenum.enums import (
41
41
  TimeEnum,
42
42
  NullableConstants,
43
43
  GNSSConstellation,
44
+ NestStatusBasic,
45
+ NestStatusInt,
46
+ NestStatusBasicInt,
47
+ NestStatusStr,
44
48
  )
45
49
 
46
50
 
@@ -159,6 +163,11 @@ class AdminDisplayBug35(models.Model):
159
163
 
160
164
  blank_txt = EnumField(TextEnum, null=True, default=None)
161
165
 
166
+ status_basic = EnumField(NestStatusBasic, null=True, default=None)
167
+ status_basic_int = EnumField(NestStatusBasicInt, null=True, default=None)
168
+ status_int = EnumField(NestStatusInt, null=True, default=None)
169
+ status_str = EnumField(NestStatusStr, null=True, default=None)
170
+
162
171
 
163
172
  class EmptyEnumValueTester(models.Model):
164
173
  class BlankTextEnum(TextChoices):
@@ -0,0 +1,37 @@
1
+ from .models.hash_equivalency import HashEquivalencyExample
2
+
3
+
4
+ obj = HashEquivalencyExample.objects.create(
5
+ not_hash_eq=HashEquivalencyExample.NotHashEq.VALUE1,
6
+ hash_eq=HashEquivalencyExample.HashEq.VALUE1,
7
+ hash_eq_str=HashEquivalencyExample.HashEqStr.VALUE1
8
+ )
9
+
10
+ # direct comparisons to values do not work
11
+ assert obj.not_hash_eq != "V1"
12
+
13
+ # unless you have provided __eq__ or inherited from the primitive
14
+ assert obj.hash_eq == obj.hash_eq_str == "V1"
15
+
16
+ # here is the problem that can break some Django internals in rare instances:
17
+ assert dict(HashEquivalencyExample._meta.get_field("not_hash_eq").flatchoices) == {
18
+ "V1": "VALUE1",
19
+ "V2": "VALUE2",
20
+ "V3": "VALUE3"
21
+ }
22
+
23
+ try:
24
+ dict(HashEquivalencyExample._meta.get_field("not_hash_eq").flatchoices)[
25
+ HashEquivalencyExample.NotHashEq.VALUE1
26
+ ]
27
+ assert False
28
+ except KeyError:
29
+ assert True
30
+
31
+ # if we've made our enum hash equivalent though, this works:
32
+ assert dict(HashEquivalencyExample._meta.get_field("hash_eq").flatchoices)[
33
+ HashEquivalencyExample.HashEq.VALUE1
34
+ ] == "VALUE1"
35
+ assert dict(HashEquivalencyExample._meta.get_field("hash_eq_str").flatchoices)[
36
+ HashEquivalencyExample.HashEqStr.VALUE1
37
+ ] == "VALUE1"
@@ -11,6 +11,7 @@ from .custom_value import CustomValueExample
11
11
  from .gnss import GNSSReceiver, Constellation
12
12
  from .gnss_vanilla import GNSSReceiverBasic
13
13
  from .equivalency import EquivalencyExample
14
+ from .hash_equivalency import HashEquivalencyExample
14
15
  from .extern import ExternalChoices
15
16
  from .flag_howto import Group
16
17
  from .text_choices import TextChoicesExample
@@ -37,6 +38,7 @@ __all__ = [
37
38
  "Constellation",
38
39
  "GNSSReceiverBasic",
39
40
  "EquivalencyExample",
41
+ "HashEquivalencyExample",
40
42
  "ExternalChoices",
41
43
  "Group",
42
44
  "TextChoicesExample",
@@ -0,0 +1,55 @@
1
+ from enum import Enum
2
+ from django.db.models import Model
3
+ from django_enum import EnumField
4
+
5
+
6
+ class HashEquivalencyExample(Model):
7
+ """
8
+ This example model defines three enum fields. The first uses an enum that
9
+ is not hash equivalent to its values. The second two are.
10
+ """
11
+
12
+ class NotHashEq(Enum):
13
+ """
14
+ Enums that inherit only from :class:`~enum.Enum` are not hash equivalent
15
+ to their values by default.
16
+ """
17
+
18
+ VALUE1 = "V1"
19
+ VALUE2 = "V2"
20
+ VALUE3 = "V3"
21
+
22
+ class HashEq(Enum):
23
+ """
24
+ We can force our Enum to be hash equivalent by overriding the necessary
25
+ dunder methods..
26
+ """
27
+
28
+ VALUE1 = "V1"
29
+ VALUE2 = "V2"
30
+ VALUE3 = "V3"
31
+
32
+ def __hash__(self):
33
+ return hash(self.value)
34
+
35
+ def __eq__(self, value) -> bool:
36
+ if isinstance(value, self.__class__):
37
+ return self.value == value.value
38
+ try:
39
+ return self.value == self.__class__(value).value
40
+ except (ValueError, TypeError):
41
+ return False
42
+
43
+ class HashEqStr(str, Enum): # or StrEnum on py 3.11+
44
+ """
45
+ Or we can inherit from the primitive value type.
46
+ """
47
+
48
+ VALUE1 = "V1"
49
+ VALUE2 = "V2"
50
+ VALUE3 = "V3"
51
+
52
+
53
+ not_hash_eq = EnumField(NotHashEq)
54
+ hash_eq = EnumField(HashEq)
55
+ hash_eq_str = EnumField(HashEqStr)
@@ -304,6 +304,9 @@ class ExampleTests(TestCase): # pragma: no cover - why is this necessary?
304
304
  def test_equivalency_howto(self):
305
305
  from tests.examples import equivalency_howto
306
306
 
307
+ def test_hash_equivalency_howto(self):
308
+ from tests.examples import hash_equivalency_howto
309
+
307
310
  def test_extern_howto(self):
308
311
  from tests.examples import extern_howto
309
312
 
@@ -548,7 +548,7 @@ wheels = [
548
548
 
549
549
  [[package]]
550
550
  name = "django-enum"
551
- version = "2.2.2"
551
+ version = "2.2.3"
552
552
  source = { editable = "." }
553
553
  dependencies = [
554
554
  { name = "django" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes