Skip to content

Commit da12416

Browse files
committed
adjust tests, add hashing test
1 parent b855066 commit da12416

File tree

7 files changed

+51
-64
lines changed

7 files changed

+51
-64
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ Many packages aim to ease usage of Python enumerations as model fields. Most wer
9191

9292
class Permissions(IntFlag):
9393

94-
READ = 0**2
95-
WRITE = 1**2
96-
EXECUTE = 2**3
94+
READ = 1**2
95+
WRITE = 2**2
96+
EXECUTE = 3**2
9797

9898

9999
class FlagExample(models.Model):

django_enum/choices.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@
1111
from django.db.models import IntegerChoices as DjangoIntegerChoices
1212
from django.db.models import TextChoices as DjangoTextChoices
1313
from django.db.models import enums as model_enums
14+
from enum_properties import DecomposeMixin, EnumPropertiesMeta, SymmetricMixin
1415

1516
from django_enum.utils import choices, names
1617

17-
from enum_properties import DecomposeMixin, EnumPropertiesMeta, SymmetricMixin
18-
1918
ChoicesType = (
2019
model_enums.ChoicesType
2120
if django_version[0:2] >= (5, 0)
@@ -49,6 +48,7 @@ def choices(self):
4948
"""
5049
return super().choices or choices(self, override=True)
5150

51+
5252
class DjangoSymmetricMixin(SymmetricMixin):
5353
"""
5454
An enumeration mixin that makes Django's Choices type label field
@@ -57,6 +57,7 @@ class DjangoSymmetricMixin(SymmetricMixin):
5757

5858
_symmetric_builtins_ = ["name", "label"]
5959

60+
6061
class TextChoices(
6162
DjangoSymmetricMixin, DjangoTextChoices, metaclass=DjangoEnumPropertiesMeta
6263
):
@@ -70,6 +71,7 @@ def __hash__(self):
7071

7172
label: str
7273

74+
7375
class IntegerChoices(
7476
DjangoSymmetricMixin, DjangoIntegerChoices, metaclass=DjangoEnumPropertiesMeta
7577
):
@@ -83,6 +85,7 @@ def __hash__(self):
8385

8486
label: str
8587

88+
8689
class FloatChoices(
8790
DjangoSymmetricMixin, float, Choices, metaclass=DjangoEnumPropertiesMeta
8891
):
@@ -99,6 +102,7 @@ def __str__(self):
99102

100103
label: str
101104

105+
102106
# mult inheritance type hint bug
103107
class FlagChoices( # type: ignore
104108
DecomposeMixin,

django_enum/drf.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
with_typehint,
3232
)
3333

34+
3435
class ClassLookupDict:
3536
"""
3637
A dict-like object that looks up values using the MRO of a class or
@@ -65,6 +66,7 @@ def __getitem__(self, key: Any) -> Optional[Any]:
6566
return self.mapping.get(cls, None)
6667
return None
6768

69+
6870
class EnumField(ChoiceField):
6971
"""
7072
A djangorestframework serializer field for Enumeration types. If
@@ -165,6 +167,7 @@ def to_representation(self, value: Any) -> Any:
165167
"""
166168
return getattr(value, "value", value)
167169

170+
168171
class EnumFieldMixin(with_typehint(ModelSerializer)): # type: ignore
169172
"""
170173
A mixin for ModelSerializers that adds auto-magic support for

django_enum/filters.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
from typing import Tuple, Type
44

55
from django.db.models import Field as ModelField
6+
from django_filters import Filter, TypedChoiceFilter, filterset
67

78
from django_enum.forms import EnumChoiceField
89
from django_enum.utils import choices
910

10-
from django_filters import Filter, TypedChoiceFilter, filterset
11-
1211

1312
class EnumFilter(TypedChoiceFilter):
1413
"""

tests/examples/models.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ class IntEnum(models.IntegerChoices):
111111

112112
class Permissions(IntFlag):
113113

114-
READ = 0**2
115-
WRITE = 1**2
116-
EXECUTE = 2**3
114+
READ = 1**2
115+
WRITE = 2**2
116+
EXECUTE = 3**2
117117

118118
# this is equivalent to:
119119
# CharField(max_length=2, choices=TextEnum.choices, null=True, blank=True)

tests/test_choices.py

Lines changed: 14 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import pytest
2+
from importlib.util import find_spec
23
from tests.utils import EnumTypeMixin, IGNORE_ORA_01843
34
from django.test import TestCase
45
from django.db import connection
@@ -726,67 +727,26 @@ def test_clean(self):
726727
self.assertTrue("text" in ve.message_dict)
727728
self.assertTrue("extern" in ve.message_dict)
728729

729-
def do_rest_framework_missing(self):
730+
@pytest.mark.skipif(
731+
find_spec("rest_framework") is not None, reason="rest_framework is installed"
732+
)
733+
def test_rest_framework_missing(self):
730734
with self.assertRaises(ImportError):
731735
from django_enum.drf import EnumField
732736

733-
def test_rest_framework_missing(self):
734-
import sys
735-
from importlib import reload
736-
from unittest.mock import patch
737-
738-
if "rest_framework.fields" in sys.modules:
739-
with patch.dict(sys.modules, {"rest_framework.fields": None}):
740-
reload(sys.modules["django_enum.drf"])
741-
self.do_rest_framework_missing()
742-
reload(sys.modules["django_enum.drf"])
743-
else:
744-
self.do_rest_framework_missing() # pragma: no cover
745-
746-
def do_django_filters_missing(self):
747-
737+
@pytest.mark.skipif(
738+
find_spec("django_filters") is not None, reason="django-filter is installed"
739+
)
740+
def test_django_filters_missing(self):
748741
with self.assertRaises(ImportError):
749742
from django_enum.filters import EnumFilter
750743

751-
752-
def test_django_filters_missing(self):
753-
import sys
754-
from importlib import reload
755-
from unittest.mock import patch
756-
757-
if "django_filters" in sys.modules:
758-
with patch.dict(sys.modules, {"django_filters": None}):
759-
reload(sys.modules["django_enum.filters"])
760-
self.do_django_filters_missing()
761-
reload(sys.modules["django_enum.filters"])
762-
else:
763-
self.do_django_filters_missing() # pragma: no cover
764-
765-
def do_enum_properties_missing(self):
766-
744+
@pytest.mark.skipif(
745+
find_spec("enum_properties") is not None, reason="enum-properties is installed"
746+
)
747+
def test_enum_properties_missing(self):
767748
with self.assertRaises(ImportError):
768-
from django_enum.choices import (
769-
DjangoEnumPropertiesMeta,
770-
DjangoSymmetricMixin,
771-
FloatChoices,
772-
IntegerChoices,
773-
TextChoices,
774-
)
749+
from django_enum.choices import TextChoices
775750

776751
self.do_test_integer_choices()
777752
self.do_test_text_choices()
778-
779-
def test_enum_properties_missing(self):
780-
import sys
781-
from importlib import reload
782-
from unittest.mock import patch
783-
784-
if "enum_properties" in sys.modules:
785-
with patch.dict(sys.modules, {"enum_properties": None}):
786-
from django_enum import choices
787-
788-
reload(sys.modules["django_enum.choices"])
789-
self.do_enum_properties_missing()
790-
reload(sys.modules["django_enum.choices"])
791-
else:
792-
self.do_enum_properties_missing() # pragma: no cover

tests/test_choices_ep.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
pytest.importorskip("enum_properties")
44

55
from tests.test_choices import TestChoices as BaseTestChoices
6+
from django_enum.choices import FlagChoices
67
from tests.enum_prop.models import EnumTester
78
from datetime import date, datetime, time, timedelta
89
from decimal import Decimal
@@ -129,6 +130,26 @@ def test_coerce_to_primitive_error(self):
129130
tester.refresh_from_db()
130131
self.assertEqual(tester.no_coerce, 32767)
131132

133+
def test_flag_choice_hashable(self):
134+
class HashableFlagChoice(FlagChoices):
135+
READ = 1**2
136+
WRITE = 2**2
137+
EXECUTE = 3**2
138+
139+
self.assertEqual(hash(HashableFlagChoice.READ), hash(1**2))
140+
self.assertEqual(hash(HashableFlagChoice.WRITE), hash(2**2))
141+
self.assertEqual(hash(HashableFlagChoice.EXECUTE), hash(3**2))
142+
143+
test_dict = {
144+
HashableFlagChoice.READ: "read",
145+
HashableFlagChoice.WRITE: "write",
146+
HashableFlagChoice.EXECUTE: "execute",
147+
}
148+
149+
self.assertEqual(test_dict[HashableFlagChoice.READ], "read")
150+
self.assertEqual(test_dict[HashableFlagChoice.WRITE], "write")
151+
self.assertEqual(test_dict[HashableFlagChoice.EXECUTE], "execute")
152+
132153

133154
# we do this to avoid the base class tests from being collected and re-run in this module
134155
BaseTestChoices = None

0 commit comments

Comments
 (0)