Skip to content

Commit 526500d

Browse files
committed
more test updates - upgrade dependency on enum-properties
1 parent 8ac4e79 commit 526500d

File tree

13 files changed

+680
-148
lines changed

13 files changed

+680
-148
lines changed

CONTRIBUTING.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ installed:
3131

3232
.. code-block::
3333
34-
poetry install
34+
poetry install -E all
3535
3636
Documentation
3737
-------------

django_enum/fields.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def __init__(self, *args, enum=None, strict=strict, **kwargs):
4545
super().__init__(*args, **kwargs)
4646

4747
def _try_coerce(self, value):
48-
if self.enum is not None:
48+
if self.enum is not None and not isinstance(value, self.enum):
4949
try:
5050
value = self.enum(value)
5151
except (TypeError, ValueError):

django_enum/forms.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,25 @@ def __init__(self, enum, *, empty_value='', choices=(), **kwargs):
1818
**kwargs
1919
)
2020

21+
def _coerce_to_value_type(self, value):
22+
"""Coerce the value to the enumerations value type"""
23+
return type(self.enum.values[0])(value)
24+
2125
def _coerce(self, value):
22-
"""
23-
Validate that the value is coercible to the enumeration type.
24-
"""
2526
if value == self.empty_value or value in self.empty_values:
2627
return self.empty_value
27-
try:
28-
value = self.enum(value).value
29-
except (ValueError, TypeError, ValidationError) as err:
30-
raise ValidationError(
31-
f'{value} is not a valid {self.enum}.',
32-
code='invalid_choice',
33-
params={'value': value},
34-
) from err
28+
if self.enum is not None and not isinstance(value, self.enum):
29+
try:
30+
value = self.enum(value)
31+
except (TypeError, ValueError):
32+
try:
33+
value = self.enum(self._coerce_to_value_type(value))
34+
except (TypeError, ValueError) as err:
35+
raise ValidationError(
36+
f'{value} is not a valid {self.enum}.',
37+
code='invalid_choice',
38+
params={'value': value},
39+
) from err
3540
return value
3641

3742
def clean(self, value):

django_enum/tests/app1/forms.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from django.forms import ModelForm
2+
from django_enum import EnumChoiceField
3+
from django_enum.tests.app1.enums import (
4+
SmallPosIntEnum,
5+
SmallIntEnum,
6+
PosIntEnum,
7+
IntEnum,
8+
BigIntEnum,
9+
BigPosIntEnum,
10+
Constants,
11+
TextEnum,
12+
DJIntEnum,
13+
DJTextEnum
14+
)
15+
from django_enum.tests.app1.models import EnumTester
16+
17+
18+
class EnumTesterForm(ModelForm):
19+
small_pos_int = EnumChoiceField(SmallPosIntEnum)
20+
small_int = EnumChoiceField(SmallIntEnum)
21+
pos_int = EnumChoiceField(PosIntEnum)
22+
int = EnumChoiceField(IntEnum)
23+
big_pos_int = EnumChoiceField(BigPosIntEnum)
24+
big_int = EnumChoiceField(BigIntEnum)
25+
constant = EnumChoiceField(Constants)
26+
text = EnumChoiceField(TextEnum)
27+
dj_int_enum = EnumChoiceField(DJIntEnum)
28+
dj_text_enum = EnumChoiceField(DJTextEnum)
29+
non_strict_int = EnumChoiceField(SmallPosIntEnum)
30+
31+
class Meta:
32+
model = EnumTester
33+
fields = '__all__'

django_enum/tests/app1/migrations/0001_initial.py

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# Generated by Django 3.2.14 on 2022-07-22 14:29
1+
# Generated by Django 3.2.14 on 2022-07-23 12:19
22

3-
import django_enum.fields
43
from django.db import migrations, models
4+
import django_enum.fields
55

66

77
class Migration(migrations.Migration):
@@ -31,6 +31,7 @@ class Migration(migrations.Migration):
3131
('char_field', models.CharField(blank=True, default='A', max_length=1)),
3232
('dj_int_enum', django_enum.fields.EnumPositiveSmallIntegerField(choices=[(1, 'One'), (2, 'Two'), (3, 'Three')], default=1)),
3333
('dj_text_enum', django_enum.fields.EnumCharField(choices=[('A', 'Label A'), ('B', 'Label B'), ('C', 'Label C')], default='A', max_length=1)),
34+
('non_strict_int', django_enum.fields.EnumPositiveSmallIntegerField(blank=True, choices=[(0, 'Value 1'), (2, 'Value 2'), (32767, 'Value 32767')], default=None, null=True)),
3435
],
3536
options={
3637
'ordering': ('id',),
@@ -45,4 +46,43 @@ class Migration(migrations.Migration):
4546
('color', django_enum.fields.EnumCharField(choices=[('R', 'Red'), ('G', 'Green'), ('B', 'Blue')], max_length=1)),
4647
],
4748
),
49+
migrations.CreateModel(
50+
name='PerfCompare',
51+
fields=[
52+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
53+
('small_pos_int', models.PositiveSmallIntegerField(blank=True, choices=[(0, 'Value 1'), (2, 'Value 2'), (32767, 'Value 32767')], db_index=True, default=None, null=True)),
54+
('small_int', models.SmallIntegerField(blank=True, choices=[(-32768, 'Value -32768'), (0, 'Value 0'), (1, 'Value 1'), (2, 'Value 2'), (32767, 'Value 32767')], db_index=True, default=32767)),
55+
('pos_int', models.PositiveIntegerField(blank=True, choices=[(0, 'Value 0'), (1, 'Value 1'), (2, 'Value 2'), (2147483647, 'Value 2147483647')], db_index=True, default=2147483647)),
56+
('int', models.IntegerField(blank=True, choices=[(-2147483648, 'Value -2147483648'), (0, 'Value 0'), (1, 'Value 1'), (2, 'Value 2'), (2147483647, 'Value 2147483647')], db_index=True, null=True)),
57+
('big_pos_int', models.PositiveBigIntegerField(blank=True, choices=[(0, 'Value 0'), (1, 'Value 1'), (2, 'Value 2'), (2147483648, 'Value 2147483647')], db_index=True, default=None, null=True)),
58+
('big_int', models.BigIntegerField(blank=True, choices=[(-2147483649, 'Value -2147483649'), (1, 'Value 1'), (2, 'Value 2'), (2147483648, 'Value 2147483647')], db_index=True, default=-2147483649)),
59+
('constant', models.FloatField(blank=True, choices=[(3.141592653589793, 'Pi'), (2.71828, "Euler's Number"), (1.618033988749895, 'Golden Ratio')], db_index=True, default=None, null=True)),
60+
('text', models.CharField(blank=True, choices=[('V1', 'Value1'), ('V22', 'Value2'), ('V333', 'Value3'), ('D', 'Default')], db_index=True, default=None, max_length=4, null=True)),
61+
('int_choice', models.IntegerField(blank=True, choices=[(1, 'One'), (2, 'Two'), (3, 'Three')], default=1)),
62+
('char_choice', models.CharField(blank=True, choices=[('A', 'First'), ('B', 'Second'), ('C', 'Third')], default='A', max_length=1)),
63+
('int_field', models.IntegerField(blank=True, default=1)),
64+
('float_field', models.FloatField(blank=True, default=1.5)),
65+
('char_field', models.CharField(blank=True, default='A', max_length=1)),
66+
('dj_int_enum', models.PositiveSmallIntegerField(choices=[(1, 'One'), (2, 'Two'), (3, 'Three')], default=1)),
67+
('dj_text_enum', models.CharField(choices=[('A', 'Label A'), ('B', 'Label B'), ('C', 'Label C')], default='A', max_length=1)),
68+
('non_strict_int', models.PositiveSmallIntegerField(blank=True, choices=[(0, 'Value 1'), (2, 'Value 2'), (32767, 'Value 32767')], default=None, null=True)),
69+
],
70+
options={
71+
'ordering': ('id',),
72+
},
73+
),
74+
migrations.CreateModel(
75+
name='SingleEnumPerf',
76+
fields=[
77+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
78+
('small_pos_int', django_enum.fields.EnumPositiveSmallIntegerField(blank=True, choices=[(0, 'Value 1'), (2, 'Value 2'), (32767, 'Value 32767')], db_index=True, default=None, null=True)),
79+
],
80+
),
81+
migrations.CreateModel(
82+
name='SingleFieldPerf',
83+
fields=[
84+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
85+
('small_pos_int', models.PositiveSmallIntegerField(blank=True, choices=[(0, 'Value 1'), (2, 'Value 2'), (32767, 'Value 32767')], db_index=True, default=None, null=True)),
86+
],
87+
),
4888
]

django_enum/tests/app1/models.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ class EnumTester(models.Model):
7272
dj_int_enum = EnumField(DJIntEnum, default=DJIntEnum.ONE.value)
7373
dj_text_enum = EnumField(DJTextEnum, default=DJTextEnum.A.value)
7474

75+
# Non-strict
76+
non_strict_int = EnumField(
77+
SmallPosIntEnum,
78+
strict=False,
79+
null=True,
80+
default=None,
81+
blank=True
82+
)
83+
7584
def get_absolute_url(self):
7685
return reverse('django_enum_tests_app1:enum-detail', kwargs={'pk': self.pk})
7786

@@ -103,3 +112,73 @@ class Color(TextChoices, s('rgb'), s('hex', case_fold=True)):
103112
int_enum = EnumField(IntEnum)
104113
color = EnumField(Color)
105114

115+
116+
class PerfCompare(models.Model):
117+
118+
small_pos_int = models.PositiveSmallIntegerField(choices=SmallPosIntEnum.choices, null=True, default=None, db_index=True, blank=True)
119+
small_int = models.SmallIntegerField(choices=SmallIntEnum.choices, null=False, default=SmallIntEnum.VAL3, db_index=True, blank=True)
120+
121+
pos_int = models.PositiveIntegerField(choices=PosIntEnum.choices, default=PosIntEnum.VAL3, db_index=True, blank=True)
122+
int = models.IntegerField(choices=IntEnum.choices, null=True, db_index=True, blank=True)
123+
124+
big_pos_int = models.PositiveBigIntegerField(choices=BigPosIntEnum.choices, null=True, default=None, db_index=True, blank=True)
125+
big_int = models.BigIntegerField(choices=BigIntEnum.choices, default=BigIntEnum.VAL0, db_index=True, blank=True)
126+
127+
constant = models.FloatField(choices=Constants.choices, null=True, default=None, db_index=True, blank=True)
128+
129+
text = models.CharField(choices=TextEnum.choices, max_length=4, null=True, default=None, db_index=True, blank=True)
130+
131+
# basic choice fields - used to compare behavior
132+
int_choice = models.IntegerField(
133+
default=1,
134+
null=False,
135+
blank=True,
136+
choices=((1, 'One'), (2, 'Two'), (3, 'Three'))
137+
)
138+
139+
char_choice = models.CharField(
140+
max_length=1,
141+
default='A',
142+
null=False,
143+
blank=True,
144+
choices=(('A', 'First'), ('B', 'Second'), ('C', 'Third'))
145+
)
146+
147+
int_field = models.IntegerField(
148+
default=1,
149+
null=False,
150+
blank=True
151+
)
152+
153+
float_field = models.FloatField(
154+
default=1.5,
155+
null=False,
156+
blank=True
157+
)
158+
159+
char_field = models.CharField(
160+
max_length=1,
161+
default='A',
162+
null=False,
163+
blank=True
164+
)
165+
################################################
166+
167+
dj_int_enum = models.PositiveSmallIntegerField(choices=DJIntEnum.choices, default=DJIntEnum.ONE.value)
168+
dj_text_enum = models.CharField(choices=DJTextEnum.choices, default=DJTextEnum.A.value, max_length=1)
169+
170+
# Non-strict
171+
non_strict_int = models.PositiveSmallIntegerField(choices=SmallPosIntEnum.choices, null=True, default=None, blank=True)
172+
173+
class Meta:
174+
ordering = ('id',)
175+
176+
177+
class SingleEnumPerf(models.Model):
178+
179+
small_pos_int = EnumField(enum=SmallPosIntEnum, null=True, default=None, db_index=True, blank=True)
180+
181+
182+
class SingleFieldPerf(models.Model):
183+
184+
small_pos_int = models.PositiveSmallIntegerField(choices=SmallPosIntEnum.choices, null=True, default=None, db_index=True, blank=True)

django_enum/tests/app1/templates/django_enum_tests_app1/enumtester_detail.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ <h1>{{ object.pk }}</h1>
1313
<p class="text">text: <b><span class="value">{{ object.text.value }}</span></b> <b><span class="label">{{ object.text.label }}</span></b></p>
1414
<p class="dj_int_enum">dj_int_enum: <b><span class="value">{{ object.dj_int_enum.value }}</span></b> <b><span class="label">{{ object.dj_int_enum.label }}</span></b></p>
1515
<p class="dj_text_enum">dj_text_enum: <b><span class="value">{{ object.dj_text_enum.value }}</span></b> <b><span class="label">{{ object.dj_text_enum.label }}</span></b></p>
16+
<p class="non_strict_int">non_strict_int: <b><span class="value">{{ object.non_strict_int.value}}</span></b> <b><span class="label">{{ object.non_strict_int.label }}</span></b></p>
1617

1718
<p>
1819
<a href="{% url 'django_enum_tests_app1:enum-update' pk=object.pk %}">Edit</a>

django_enum/tests/app1/templates/django_enum_tests_app1/enumtester_list.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ <h2>{{ object.pk }}</h2>
1515
<p class="text">text: <b><span class="value">{{ object.text.value }}</span></b> <b><span class="label">{{ object.text.label }}</span></b></p>
1616
<p class="dj_int_enum">dj_int_enum: <b><span class="value">{{ object.dj_int_enum.value }}</span></b> <b><span class="label">{{ object.dj_int_enum.label }}</span></b></p>
1717
<p class="dj_text_enum">dj_text_enum: <b><span class="value">{{ object.dj_text_enum.value }}</span></b> <b><span class="label">{{ object.dj_text_enum.label }}</span></b></p>
18+
<p class="non_strict_int">non_strict_int: <b><span class="value">{{ object.non_strict_int.value}}</span></b> <b><span class="label">{{ object.non_strict_int.label }}</span></b></p>
1819

1920
<p>
2021
<a href="{% url 'django_enum_tests_app1:enum-update' pk=object.pk %}">Edit</a>

django_enum/tests/app1/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
EnumTesterFormView,
99
EnumTesterListView,
1010
EnumTesterUpdateView,
11+
EnumTesterFormCreateView
1112
)
1213
from django_filters.views import FilterView
1314

@@ -31,6 +32,7 @@
3132
name='enum-filter_explicit'
3233
),
3334
path('enum/add/', EnumTesterCreateView.as_view(), name='enum-add'),
35+
path('enum/form/add/', EnumTesterFormCreateView.as_view(), name='enum-form-add'),
3436
path('enum/<int:pk>/', EnumTesterUpdateView.as_view(), name='enum-update'),
3537
path('enum/form/<int:pk>/', EnumTesterFormView.as_view(), name='enum-form-update'),
3638
path('enum/<int:pk>/delete/', EnumTesterDeleteView.as_view(), name='enum-delete'),

django_enum/tests/app1/views.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
SmallPosIntEnum,
1717
TextEnum,
1818
)
19+
from django_enum.tests.app1.forms import EnumTesterForm
1920
from django_enum.tests.app1.models import EnumTester
2021
from django_filters.views import FilterView
2122

@@ -40,21 +41,11 @@ class EnumTesterUpdateView(UpdateView):
4041

4142
class EnumTesterFormView(UpdateView):
4243

43-
class EnumTesterForm(ModelForm):
44-
small_pos_int = EnumChoiceField(SmallPosIntEnum)
45-
small_int = EnumChoiceField(SmallIntEnum)
46-
pos_int = EnumChoiceField(PosIntEnum)
47-
int = EnumChoiceField(IntEnum)
48-
big_pos_int = EnumChoiceField(BigPosIntEnum)
49-
big_int = EnumChoiceField(BigIntEnum)
50-
constant = EnumChoiceField(Constants)
51-
text = EnumChoiceField(TextEnum)
52-
dj_int_enum = EnumChoiceField(DJIntEnum)
53-
dj_text_enum = EnumChoiceField(DJTextEnum)
44+
form_class = EnumTesterForm
45+
model = EnumTester
5446

55-
class Meta:
56-
model = EnumTester
57-
fields = '__all__'
47+
48+
class EnumTesterFormCreateView(CreateView):
5849

5950
form_class = EnumTesterForm
6051
model = EnumTester

0 commit comments

Comments
 (0)