Browse Source

Renamed ChoicesMeta to ChoicesType.

This also uses enum.EnumType for Python 3.11+ as Python 3.11 renamed
EnumMeta to EnumType. While the former is still available as an alias
of the latter for now, let's prefer the canonical name for this.

Check out https://docs.python.org/3/library/enum.html#enum.EnumType
Nick Pope 1 year ago
parent
commit
e15174983a

+ 21 - 3
django/db/models/enums.py

@@ -1,13 +1,20 @@
 import enum
+import warnings
 from types import DynamicClassAttribute
 
+from django.utils.deprecation import RemovedInDjango60Warning
 from django.utils.functional import Promise
-from django.utils.version import PY312
+from django.utils.version import PY311, PY312
+
+if PY311:
+    from enum import EnumType
+else:
+    from enum import EnumMeta as EnumType
 
 __all__ = ["Choices", "IntegerChoices", "TextChoices"]
 
 
-class ChoicesMeta(enum.EnumMeta):
+class ChoicesType(EnumType):
     """A metaclass for creating a enum choices."""
 
     def __new__(metacls, classname, bases, classdict, **kwds):
@@ -59,7 +66,7 @@ class ChoicesMeta(enum.EnumMeta):
         return [value for value, _ in cls.choices]
 
 
-class Choices(enum.Enum, metaclass=ChoicesMeta):
+class Choices(enum.Enum, metaclass=ChoicesType):
     """Class for creating enumerated choices."""
 
     @DynamicClassAttribute
@@ -93,3 +100,14 @@ class TextChoices(str, Choices):
 
     def _generate_next_value_(name, start, count, last_values):
         return name
+
+
+def __getattr__(name):
+    if name == "ChoicesMeta":
+        warnings.warn(
+            "ChoicesMeta is deprecated in favor of ChoicesType.",
+            RemovedInDjango60Warning,
+            stacklevel=2,
+        )
+        return ChoicesType
+    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

+ 2 - 2
django/utils/choices.py

@@ -20,7 +20,7 @@ class CallableChoiceIterator(BaseChoiceIterator):
 def normalize_choices(value, *, depth=0):
     """Normalize choices values consistently for fields and widgets."""
     # Avoid circular import when importing django.forms.
-    from django.db.models.enums import ChoicesMeta
+    from django.db.models.enums import ChoicesType
 
     match value:
         case BaseChoiceIterator() | Promise() | bytes() | str():
@@ -28,7 +28,7 @@ def normalize_choices(value, *, depth=0):
             # Because string-like types are iterable, return early to avoid
             # iterating over them in the guard for the Iterable case below.
             return value
-        case ChoicesMeta():
+        case ChoicesType():
             # Choices enumeration helpers already output in canonical form.
             return value.choices
         case Mapping() if depth < 2:

+ 3 - 0
docs/internals/deprecation.txt

@@ -42,6 +42,9 @@ details on these changes.
 
 * ``BaseDatabaseOperations.field_cast_sql()`` will be removed.
 
+* The ``ChoicesMeta`` alias to ``django.db.models.enums.ChoicesType`` will be
+  removed.
+
 .. _deprecation-removed-in-5.1:
 
 5.1

+ 3 - 0
docs/releases/5.0.txt

@@ -685,6 +685,9 @@ Miscellaneous
   ``BuiltinLookup.process_lhs()`` will no longer call ``field_cast_sql()``.
   Third-party database backends should implement ``lookup_cast()`` instead.
 
+* The ``django.db.models.enums.ChoicesMeta`` metaclass is renamed to
+  ``ChoicesType``.
+
 .. _`oracledb`: https://oracle.github.io/python-oracledb/
 
 Features removed in 5.0

+ 10 - 0
tests/model_enums/tests.py

@@ -6,6 +6,7 @@ import uuid
 from django.db import models
 from django.template import Context, Template
 from django.test import SimpleTestCase
+from django.utils.deprecation import RemovedInDjango60Warning
 from django.utils.functional import Promise
 from django.utils.translation import gettext_lazy as _
 
@@ -315,3 +316,12 @@ class CustomChoicesTests(SimpleTestCase):
 
             class Identifier(uuid.UUID, models.Choices):
                 A = "972ce4eb-a95f-4a56-9339-68c208a76f18"
+
+
+class ChoicesMetaDeprecationTests(SimpleTestCase):
+    def test_deprecation_warning(self):
+        from django.db.models import enums
+
+        msg = "ChoicesMeta is deprecated in favor of ChoicesType."
+        with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
+            enums.ChoicesMeta