summaryrefslogtreecommitdiff
path: root/tests/postgres_tests/test_array.py
diff options
context:
space:
mode:
authordjango-bot <ops@djangoproject.com>2022-02-03 20:24:19 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-02-07 20:37:05 +0100
commit9c19aff7c7561e3a82978a272ecdaad40dda5c00 (patch)
treef0506b668a013d0063e5fba3dbf4863b466713ba /tests/postgres_tests/test_array.py
parentf68fa8b45dfac545cfc4111d4e52804c86db68d3 (diff)
Refs #33476 -- Reformatted code with Black.
Diffstat (limited to 'tests/postgres_tests/test_array.py')
-rw-r--r--tests/postgres_tests/test_array.py802
1 files changed, 450 insertions, 352 deletions
diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py
index ba04c15e24..512972b8e6 100644
--- a/tests/postgres_tests/test_array.py
+++ b/tests/postgres_tests/test_array.py
@@ -15,13 +15,18 @@ from django.test import TransactionTestCase, modify_settings, override_settings
from django.test.utils import isolate_apps
from django.utils import timezone
-from . import (
- PostgreSQLSimpleTestCase, PostgreSQLTestCase, PostgreSQLWidgetTestCase,
-)
+from . import PostgreSQLSimpleTestCase, PostgreSQLTestCase, PostgreSQLWidgetTestCase
from .models import (
- ArrayEnumModel, ArrayFieldSubclass, CharArrayModel, DateTimeArrayModel,
- IntegerArrayModel, NestedIntegerArrayModel, NullableIntegerArrayModel,
- OtherTypesArrayModel, PostgreSQLModel, Tag,
+ ArrayEnumModel,
+ ArrayFieldSubclass,
+ CharArrayModel,
+ DateTimeArrayModel,
+ IntegerArrayModel,
+ NestedIntegerArrayModel,
+ NullableIntegerArrayModel,
+ OtherTypesArrayModel,
+ PostgreSQLModel,
+ Tag,
)
try:
@@ -30,33 +35,33 @@ try:
from django.contrib.postgres.aggregates import ArrayAgg
from django.contrib.postgres.expressions import ArraySubquery
from django.contrib.postgres.fields import ArrayField
- from django.contrib.postgres.fields.array import (
- IndexTransform, SliceTransform,
- )
+ from django.contrib.postgres.fields.array import IndexTransform, SliceTransform
from django.contrib.postgres.forms import (
- SimpleArrayField, SplitArrayField, SplitArrayWidget,
+ SimpleArrayField,
+ SplitArrayField,
+ SplitArrayWidget,
)
except ImportError:
pass
-@isolate_apps('postgres_tests')
+@isolate_apps("postgres_tests")
class BasicTests(PostgreSQLSimpleTestCase):
def test_get_field_display(self):
class MyModel(PostgreSQLModel):
field = ArrayField(
models.CharField(max_length=16),
choices=[
- ['Media', [(['vinyl', 'cd'], 'Audio')]],
- (('mp3', 'mp4'), 'Digital'),
+ ["Media", [(["vinyl", "cd"], "Audio")]],
+ (("mp3", "mp4"), "Digital"),
],
)
tests = (
- (['vinyl', 'cd'], 'Audio'),
- (('mp3', 'mp4'), 'Digital'),
- (('a', 'b'), "('a', 'b')"),
- (['c', 'd'], "['c', 'd']"),
+ (["vinyl", "cd"], "Audio"),
+ (("mp3", "mp4"), "Digital"),
+ (("a", "b"), "('a', 'b')"),
+ (["c", "d"], "['c', 'd']"),
)
for value, display in tests:
with self.subTest(value=value, display=display):
@@ -69,17 +74,18 @@ class BasicTests(PostgreSQLSimpleTestCase):
ArrayField(models.CharField(max_length=16)),
choices=[
[
- 'Media',
- [([['vinyl', 'cd'], ('x',)], 'Audio')],
+ "Media",
+ [([["vinyl", "cd"], ("x",)], "Audio")],
],
- ((['mp3'], ('mp4',)), 'Digital'),
+ ((["mp3"], ("mp4",)), "Digital"),
],
)
+
tests = (
- ([['vinyl', 'cd'], ('x',)], 'Audio'),
- ((['mp3'], ('mp4',)), 'Digital'),
- ((('a', 'b'), ('c',)), "(('a', 'b'), ('c',))"),
- ([['a', 'b'], ['c']], "[['a', 'b'], ['c']]"),
+ ([["vinyl", "cd"], ("x",)], "Audio"),
+ ((["mp3"], ("mp4",)), "Digital"),
+ ((("a", "b"), ("c",)), "(('a', 'b'), ('c',))"),
+ ([["a", "b"], ["c"]], "[['a', 'b'], ['c']]"),
)
for value, display in tests:
with self.subTest(value=value, display=display):
@@ -88,7 +94,6 @@ class BasicTests(PostgreSQLSimpleTestCase):
class TestSaveLoad(PostgreSQLTestCase):
-
def test_integer(self):
instance = IntegerArrayModel(field=[1, 2, 3])
instance.save()
@@ -96,7 +101,7 @@ class TestSaveLoad(PostgreSQLTestCase):
self.assertEqual(instance.field, loaded.field)
def test_char(self):
- instance = CharArrayModel(field=['hello', 'goodbye'])
+ instance = CharArrayModel(field=["hello", "goodbye"])
instance.save()
loaded = CharArrayModel.objects.get()
self.assertEqual(instance.field, loaded.field)
@@ -121,7 +126,7 @@ class TestSaveLoad(PostgreSQLTestCase):
def test_integers_passed_as_strings(self):
# This checks that get_prep_value is deferred properly
- instance = IntegerArrayModel(field=['1'])
+ instance = IntegerArrayModel(field=["1"])
instance.save()
loaded = IntegerArrayModel.objects.get()
self.assertEqual(loaded.field, [1])
@@ -151,16 +156,16 @@ class TestSaveLoad(PostgreSQLTestCase):
def test_other_array_types(self):
instance = OtherTypesArrayModel(
- ips=['192.168.0.1', '::1'],
+ ips=["192.168.0.1", "::1"],
uuids=[uuid.uuid4()],
decimals=[decimal.Decimal(1.25), 1.75],
tags=[Tag(1), Tag(2), Tag(3)],
- json=[{'a': 1}, {'b': 2}],
+ json=[{"a": 1}, {"b": 2}],
int_ranges=[NumericRange(10, 20), NumericRange(30, 40)],
bigint_ranges=[
NumericRange(7000000000, 10000000000),
NumericRange(50000000000, 70000000000),
- ]
+ ],
)
instance.save()
loaded = OtherTypesArrayModel.objects.get()
@@ -174,7 +179,7 @@ class TestSaveLoad(PostgreSQLTestCase):
def test_null_from_db_value_handling(self):
instance = OtherTypesArrayModel.objects.create(
- ips=['192.168.0.1', '::1'],
+ ips=["192.168.0.1", "::1"],
uuids=[uuid.uuid4()],
decimals=[decimal.Decimal(1.25), 1.75],
tags=None,
@@ -187,7 +192,7 @@ class TestSaveLoad(PostgreSQLTestCase):
def test_model_set_on_base_field(self):
instance = IntegerArrayModel()
- field = instance._meta.get_field('field')
+ field = instance._meta.get_field("field")
self.assertEqual(field.model, IntegerArrayModel)
self.assertEqual(field.base_field.model, IntegerArrayModel)
@@ -199,29 +204,35 @@ class TestSaveLoad(PostgreSQLTestCase):
class TestQuerying(PostgreSQLTestCase):
-
@classmethod
def setUpTestData(cls):
- cls.objs = NullableIntegerArrayModel.objects.bulk_create([
- NullableIntegerArrayModel(order=1, field=[1]),
- NullableIntegerArrayModel(order=2, field=[2]),
- NullableIntegerArrayModel(order=3, field=[2, 3]),
- NullableIntegerArrayModel(order=4, field=[20, 30, 40]),
- NullableIntegerArrayModel(order=5, field=None),
- ])
+ cls.objs = NullableIntegerArrayModel.objects.bulk_create(
+ [
+ NullableIntegerArrayModel(order=1, field=[1]),
+ NullableIntegerArrayModel(order=2, field=[2]),
+ NullableIntegerArrayModel(order=3, field=[2, 3]),
+ NullableIntegerArrayModel(order=4, field=[20, 30, 40]),
+ NullableIntegerArrayModel(order=5, field=None),
+ ]
+ )
def test_empty_list(self):
NullableIntegerArrayModel.objects.create(field=[])
- obj = NullableIntegerArrayModel.objects.annotate(
- empty_array=models.Value([], output_field=ArrayField(models.IntegerField())),
- ).filter(field=models.F('empty_array')).get()
+ obj = (
+ NullableIntegerArrayModel.objects.annotate(
+ empty_array=models.Value(
+ [], output_field=ArrayField(models.IntegerField())
+ ),
+ )
+ .filter(field=models.F("empty_array"))
+ .get()
+ )
self.assertEqual(obj.field, [])
self.assertEqual(obj.empty_array, [])
def test_exact(self):
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__exact=[1]),
- self.objs[:1]
+ NullableIntegerArrayModel.objects.filter(field__exact=[1]), self.objs[:1]
)
def test_exact_with_expression(self):
@@ -231,50 +242,47 @@ class TestQuerying(PostgreSQLTestCase):
)
def test_exact_charfield(self):
- instance = CharArrayModel.objects.create(field=['text'])
+ instance = CharArrayModel.objects.create(field=["text"])
self.assertSequenceEqual(
- CharArrayModel.objects.filter(field=['text']),
- [instance]
+ CharArrayModel.objects.filter(field=["text"]), [instance]
)
def test_exact_nested(self):
instance = NestedIntegerArrayModel.objects.create(field=[[1, 2], [3, 4]])
self.assertSequenceEqual(
- NestedIntegerArrayModel.objects.filter(field=[[1, 2], [3, 4]]),
- [instance]
+ NestedIntegerArrayModel.objects.filter(field=[[1, 2], [3, 4]]), [instance]
)
def test_isnull(self):
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__isnull=True),
- self.objs[-1:]
+ NullableIntegerArrayModel.objects.filter(field__isnull=True), self.objs[-1:]
)
def test_gt(self):
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__gt=[0]),
- self.objs[:4]
+ NullableIntegerArrayModel.objects.filter(field__gt=[0]), self.objs[:4]
)
def test_lt(self):
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__lt=[2]),
- self.objs[:1]
+ NullableIntegerArrayModel.objects.filter(field__lt=[2]), self.objs[:1]
)
def test_in(self):
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.filter(field__in=[[1], [2]]),
- self.objs[:2]
+ self.objs[:2],
)
def test_in_subquery(self):
IntegerArrayModel.objects.create(field=[2, 3])
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.filter(
- field__in=IntegerArrayModel.objects.all().values_list('field', flat=True)
+ field__in=IntegerArrayModel.objects.all().values_list(
+ "field", flat=True
+ )
),
- self.objs[2:3]
+ self.objs[2:3],
)
@unittest.expectedFailure
@@ -284,42 +292,44 @@ class TestQuerying(PostgreSQLTestCase):
# psycopg2 mogrify method that generates the ARRAY() syntax is
# expecting literals, not column references (#27095).
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__in=[[models.F('id')]]),
- self.objs[:2]
+ NullableIntegerArrayModel.objects.filter(field__in=[[models.F("id")]]),
+ self.objs[:2],
)
def test_in_as_F_object(self):
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__in=[models.F('field')]),
- self.objs[:4]
+ NullableIntegerArrayModel.objects.filter(field__in=[models.F("field")]),
+ self.objs[:4],
)
def test_contained_by(self):
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.filter(field__contained_by=[1, 2]),
- self.objs[:2]
+ self.objs[:2],
)
def test_contained_by_including_F_object(self):
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__contained_by=[models.F('order'), 2]),
+ NullableIntegerArrayModel.objects.filter(
+ field__contained_by=[models.F("order"), 2]
+ ),
self.objs[:3],
)
def test_contains(self):
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.filter(field__contains=[2]),
- self.objs[1:3]
+ self.objs[1:3],
)
def test_contains_subquery(self):
IntegerArrayModel.objects.create(field=[2, 3])
- inner_qs = IntegerArrayModel.objects.values_list('field', flat=True)
+ inner_qs = IntegerArrayModel.objects.values_list("field", flat=True)
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.filter(field__contains=inner_qs[:1]),
self.objs[2:3],
)
- inner_qs = IntegerArrayModel.objects.filter(field__contains=OuterRef('field'))
+ inner_qs = IntegerArrayModel.objects.filter(field__contains=OuterRef("field"))
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.filter(Exists(inner_qs)),
self.objs[1:3],
@@ -335,93 +345,92 @@ class TestQuerying(PostgreSQLTestCase):
def test_icontains(self):
# Using the __icontains lookup with ArrayField is inefficient.
- instance = CharArrayModel.objects.create(field=['FoO'])
+ instance = CharArrayModel.objects.create(field=["FoO"])
self.assertSequenceEqual(
- CharArrayModel.objects.filter(field__icontains='foo'),
- [instance]
+ CharArrayModel.objects.filter(field__icontains="foo"), [instance]
)
def test_contains_charfield(self):
# Regression for #22907
self.assertSequenceEqual(
- CharArrayModel.objects.filter(field__contains=['text']),
- []
+ CharArrayModel.objects.filter(field__contains=["text"]), []
)
def test_contained_by_charfield(self):
self.assertSequenceEqual(
- CharArrayModel.objects.filter(field__contained_by=['text']),
- []
+ CharArrayModel.objects.filter(field__contained_by=["text"]), []
)
def test_overlap_charfield(self):
self.assertSequenceEqual(
- CharArrayModel.objects.filter(field__overlap=['text']),
- []
+ CharArrayModel.objects.filter(field__overlap=["text"]), []
)
def test_overlap_charfield_including_expression(self):
- obj_1 = CharArrayModel.objects.create(field=['TEXT', 'lower text'])
- obj_2 = CharArrayModel.objects.create(field=['lower text', 'TEXT'])
- CharArrayModel.objects.create(field=['lower text', 'text'])
+ obj_1 = CharArrayModel.objects.create(field=["TEXT", "lower text"])
+ obj_2 = CharArrayModel.objects.create(field=["lower text", "TEXT"])
+ CharArrayModel.objects.create(field=["lower text", "text"])
self.assertSequenceEqual(
- CharArrayModel.objects.filter(field__overlap=[
- Upper(Value('text')),
- 'other',
- ]),
+ CharArrayModel.objects.filter(
+ field__overlap=[
+ Upper(Value("text")),
+ "other",
+ ]
+ ),
[obj_1, obj_2],
)
def test_lookups_autofield_array(self):
- qs = NullableIntegerArrayModel.objects.filter(
- field__0__isnull=False,
- ).values('field__0').annotate(
- arrayagg=ArrayAgg('id'),
- ).order_by('field__0')
+ qs = (
+ NullableIntegerArrayModel.objects.filter(
+ field__0__isnull=False,
+ )
+ .values("field__0")
+ .annotate(
+ arrayagg=ArrayAgg("id"),
+ )
+ .order_by("field__0")
+ )
tests = (
- ('contained_by', [self.objs[1].pk, self.objs[2].pk, 0], [2]),
- ('contains', [self.objs[2].pk], [2]),
- ('exact', [self.objs[3].pk], [20]),
- ('overlap', [self.objs[1].pk, self.objs[3].pk], [2, 20]),
+ ("contained_by", [self.objs[1].pk, self.objs[2].pk, 0], [2]),
+ ("contains", [self.objs[2].pk], [2]),
+ ("exact", [self.objs[3].pk], [20]),
+ ("overlap", [self.objs[1].pk, self.objs[3].pk], [2, 20]),
)
for lookup, value, expected in tests:
with self.subTest(lookup=lookup):
self.assertSequenceEqual(
qs.filter(
- **{'arrayagg__' + lookup: value},
- ).values_list('field__0', flat=True),
+ **{"arrayagg__" + lookup: value},
+ ).values_list("field__0", flat=True),
expected,
)
def test_index(self):
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__0=2),
- self.objs[1:3]
+ NullableIntegerArrayModel.objects.filter(field__0=2), self.objs[1:3]
)
def test_index_chained(self):
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__0__lt=3),
- self.objs[0:3]
+ NullableIntegerArrayModel.objects.filter(field__0__lt=3), self.objs[0:3]
)
def test_index_nested(self):
instance = NestedIntegerArrayModel.objects.create(field=[[1, 2], [3, 4]])
self.assertSequenceEqual(
- NestedIntegerArrayModel.objects.filter(field__0__0=1),
- [instance]
+ NestedIntegerArrayModel.objects.filter(field__0__0=1), [instance]
)
@unittest.expectedFailure
def test_index_used_on_nested_data(self):
instance = NestedIntegerArrayModel.objects.create(field=[[1, 2], [3, 4]])
self.assertSequenceEqual(
- NestedIntegerArrayModel.objects.filter(field__0=[1, 2]),
- [instance]
+ NestedIntegerArrayModel.objects.filter(field__0=[1, 2]), [instance]
)
def test_index_transform_expression(self):
- expr = RawSQL("string_to_array(%s, ';')", ['1;2'])
+ expr = RawSQL("string_to_array(%s, ';')", ["1;2"])
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.filter(
field__0=Cast(
@@ -433,40 +442,36 @@ class TestQuerying(PostgreSQLTestCase):
)
def test_index_annotation(self):
- qs = NullableIntegerArrayModel.objects.annotate(second=models.F('field__1'))
+ qs = NullableIntegerArrayModel.objects.annotate(second=models.F("field__1"))
self.assertCountEqual(
- qs.values_list('second', flat=True),
+ qs.values_list("second", flat=True),
[None, None, None, 3, 30],
)
def test_overlap(self):
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.filter(field__overlap=[1, 2]),
- self.objs[0:3]
+ self.objs[0:3],
)
def test_len(self):
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__len__lte=2),
- self.objs[0:3]
+ NullableIntegerArrayModel.objects.filter(field__len__lte=2), self.objs[0:3]
)
def test_len_empty_array(self):
obj = NullableIntegerArrayModel.objects.create(field=[])
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__len=0),
- [obj]
+ NullableIntegerArrayModel.objects.filter(field__len=0), [obj]
)
def test_slice(self):
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__0_1=[2]),
- self.objs[1:3]
+ NullableIntegerArrayModel.objects.filter(field__0_1=[2]), self.objs[1:3]
)
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__0_2=[2, 3]),
- self.objs[2:3]
+ NullableIntegerArrayModel.objects.filter(field__0_2=[2, 3]), self.objs[2:3]
)
def test_order_by_slice(self):
@@ -477,35 +482,42 @@ class TestQuerying(PostgreSQLTestCase):
NullableIntegerArrayModel.objects.create(field=[4, 2]),
)
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.order_by('field__1'),
+ NullableIntegerArrayModel.objects.order_by("field__1"),
[
- more_objs[2], more_objs[1], more_objs[3], self.objs[2],
- self.objs[3], more_objs[0], self.objs[4], self.objs[1],
+ more_objs[2],
+ more_objs[1],
+ more_objs[3],
+ self.objs[2],
+ self.objs[3],
+ more_objs[0],
+ self.objs[4],
+ self.objs[1],
self.objs[0],
- ]
+ ],
)
@unittest.expectedFailure
def test_slice_nested(self):
instance = NestedIntegerArrayModel.objects.create(field=[[1, 2], [3, 4]])
self.assertSequenceEqual(
- NestedIntegerArrayModel.objects.filter(field__0__0_1=[1]),
- [instance]
+ NestedIntegerArrayModel.objects.filter(field__0__0_1=[1]), [instance]
)
def test_slice_transform_expression(self):
- expr = RawSQL("string_to_array(%s, ';')", ['9;2;3'])
+ expr = RawSQL("string_to_array(%s, ';')", ["9;2;3"])
self.assertSequenceEqual(
- NullableIntegerArrayModel.objects.filter(field__0_2=SliceTransform(2, 3, expr)),
+ NullableIntegerArrayModel.objects.filter(
+ field__0_2=SliceTransform(2, 3, expr)
+ ),
self.objs[2:3],
)
def test_slice_annotation(self):
qs = NullableIntegerArrayModel.objects.annotate(
- first_two=models.F('field__0_2'),
+ first_two=models.F("field__0_2"),
)
self.assertCountEqual(
- qs.values_list('first_two', flat=True),
+ qs.values_list("first_two", flat=True),
[None, [1], [2], [2, 3], [20, 30]],
)
@@ -514,17 +526,17 @@ class TestQuerying(PostgreSQLTestCase):
NullableIntegerArrayModel.objects.filter(
id__in=NullableIntegerArrayModel.objects.filter(field__len=3)
),
- [self.objs[3]]
+ [self.objs[3]],
)
def test_enum_lookup(self):
class TestEnum(enum.Enum):
- VALUE_1 = 'value_1'
+ VALUE_1 = "value_1"
instance = ArrayEnumModel.objects.create(array_of_enums=[TestEnum.VALUE_1])
self.assertSequenceEqual(
ArrayEnumModel.objects.filter(array_of_enums__contains=[TestEnum.VALUE_1]),
- [instance]
+ [instance],
)
def test_unsupported_lookup(self):
@@ -541,18 +553,24 @@ class TestQuerying(PostgreSQLTestCase):
self.assertEqual(
NullableIntegerArrayModel.objects.annotate(
array_length=models.Func(
- value, 1, function='ARRAY_LENGTH', output_field=models.IntegerField(),
+ value,
+ 1,
+ function="ARRAY_LENGTH",
+ output_field=models.IntegerField(),
),
- ).values('array_length').annotate(
- count=models.Count('pk'),
- ).get()['array_length'],
+ )
+ .values("array_length")
+ .annotate(
+ count=models.Count("pk"),
+ )
+ .get()["array_length"],
1,
)
def test_filter_by_array_subquery(self):
inner_qs = NullableIntegerArrayModel.objects.filter(
- field__len=models.OuterRef('field__len'),
- ).values('field')
+ field__len=models.OuterRef("field__len"),
+ ).values("field")
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.alias(
same_sized_fields=ArraySubquery(inner_qs),
@@ -562,56 +580,63 @@ class TestQuerying(PostgreSQLTestCase):
def test_annotated_array_subquery(self):
inner_qs = NullableIntegerArrayModel.objects.exclude(
- pk=models.OuterRef('pk')
- ).values('order')
+ pk=models.OuterRef("pk")
+ ).values("order")
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.annotate(
sibling_ids=ArraySubquery(inner_qs),
- ).get(order=1).sibling_ids,
+ )
+ .get(order=1)
+ .sibling_ids,
[2, 3, 4, 5],
)
def test_group_by_with_annotated_array_subquery(self):
inner_qs = NullableIntegerArrayModel.objects.exclude(
- pk=models.OuterRef('pk')
- ).values('order')
+ pk=models.OuterRef("pk")
+ ).values("order")
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.annotate(
sibling_ids=ArraySubquery(inner_qs),
- sibling_count=models.Max('sibling_ids__len'),
- ).values_list('sibling_count', flat=True),
+ sibling_count=models.Max("sibling_ids__len"),
+ ).values_list("sibling_count", flat=True),
[len(self.objs) - 1] * len(self.objs),
)
def test_annotated_ordered_array_subquery(self):
- inner_qs = NullableIntegerArrayModel.objects.order_by('-order').values('order')
+ inner_qs = NullableIntegerArrayModel.objects.order_by("-order").values("order")
self.assertSequenceEqual(
NullableIntegerArrayModel.objects.annotate(
ids=ArraySubquery(inner_qs),
- ).first().ids,
+ )
+ .first()
+ .ids,
[5, 4, 3, 2, 1],
)
def test_annotated_array_subquery_with_json_objects(self):
inner_qs = NullableIntegerArrayModel.objects.exclude(
- pk=models.OuterRef('pk')
- ).values(json=JSONObject(order='order', field='field'))
- siblings_json = NullableIntegerArrayModel.objects.annotate(
- siblings_json=ArraySubquery(inner_qs),
- ).values_list('siblings_json', flat=True).get(order=1)
+ pk=models.OuterRef("pk")
+ ).values(json=JSONObject(order="order", field="field"))
+ siblings_json = (
+ NullableIntegerArrayModel.objects.annotate(
+ siblings_json=ArraySubquery(inner_qs),
+ )
+ .values_list("siblings_json", flat=True)
+ .get(order=1)
+ )
self.assertSequenceEqual(
siblings_json,
[
- {'field': [2], 'order': 2},
- {'field': [2, 3], 'order': 3},
- {'field': [20, 30, 40], 'order': 4},
- {'field': None, 'order': 5},
+ {"field": [2], "order": 2},
+ {"field": [2, 3], "order": 3},
+ {"field": [20, 30, 40], "order": 4},
+ {"field": None, "order": 5},
],
)
class TestDateTimeExactQuerying(PostgreSQLTestCase):
-
@classmethod
def setUpTestData(cls):
now = timezone.now()
@@ -619,33 +644,31 @@ class TestDateTimeExactQuerying(PostgreSQLTestCase):
cls.dates = [now.date()]
cls.times = [now.time()]
cls.objs = [
- DateTimeArrayModel.objects.create(datetimes=cls.datetimes, dates=cls.dates, times=cls.times),
+ DateTimeArrayModel.objects.create(
+ datetimes=cls.datetimes, dates=cls.dates, times=cls.times
+ ),
]
def test_exact_datetimes(self):
self.assertSequenceEqual(
- DateTimeArrayModel.objects.filter(datetimes=self.datetimes),
- self.objs
+ DateTimeArrayModel.objects.filter(datetimes=self.datetimes), self.objs
)
def test_exact_dates(self):
self.assertSequenceEqual(
- DateTimeArrayModel.objects.filter(dates=self.dates),
- self.objs
+ DateTimeArrayModel.objects.filter(dates=self.dates), self.objs
)
def test_exact_times(self):
self.assertSequenceEqual(
- DateTimeArrayModel.objects.filter(times=self.times),
- self.objs
+ DateTimeArrayModel.objects.filter(times=self.times), self.objs
)
class TestOtherTypesExactQuerying(PostgreSQLTestCase):
-
@classmethod
def setUpTestData(cls):
- cls.ips = ['192.168.0.1', '::1']
+ cls.ips = ["192.168.0.1", "::1"]
cls.uuids = [uuid.uuid4()]
cls.decimals = [decimal.Decimal(1.25), 1.75]
cls.tags = [Tag(1), Tag(2), Tag(3)]
@@ -660,32 +683,27 @@ class TestOtherTypesExactQuerying(PostgreSQLTestCase):
def test_exact_ip_addresses(self):
self.assertSequenceEqual(
- OtherTypesArrayModel.objects.filter(ips=self.ips),
- self.objs
+ OtherTypesArrayModel.objects.filter(ips=self.ips), self.objs
)
def test_exact_uuids(self):
self.assertSequenceEqual(
- OtherTypesArrayModel.objects.filter(uuids=self.uuids),
- self.objs
+ OtherTypesArrayModel.objects.filter(uuids=self.uuids), self.objs
)
def test_exact_decimals(self):
self.assertSequenceEqual(
- OtherTypesArrayModel.objects.filter(decimals=self.decimals),
- self.objs
+ OtherTypesArrayModel.objects.filter(decimals=self.decimals), self.objs
)
def test_exact_tags(self):
self.assertSequenceEqual(
- OtherTypesArrayModel.objects.filter(tags=self.tags),
- self.objs
+ OtherTypesArrayModel.objects.filter(tags=self.tags), self.objs
)
-@isolate_apps('postgres_tests')
+@isolate_apps("postgres_tests")
class TestChecks(PostgreSQLSimpleTestCase):
-
def test_field_checks(self):
class MyModel(PostgreSQLModel):
field = ArrayField(models.CharField())
@@ -694,35 +712,40 @@ class TestChecks(PostgreSQLSimpleTestCase):
errors = model.check()
self.assertEqual(len(errors), 1)
# The inner CharField is missing a max_length.
- self.assertEqual(errors[0].id, 'postgres.E001')
- self.assertIn('max_length', errors[0].msg)
+ self.assertEqual(errors[0].id, "postgres.E001")
+ self.assertIn("max_length", errors[0].msg)
def test_invalid_base_fields(self):
class MyModel(PostgreSQLModel):
- field = ArrayField(models.ManyToManyField('postgres_tests.IntegerArrayModel'))
+ field = ArrayField(
+ models.ManyToManyField("postgres_tests.IntegerArrayModel")
+ )
model = MyModel()
errors = model.check()
self.assertEqual(len(errors), 1)
- self.assertEqual(errors[0].id, 'postgres.E002')
+ self.assertEqual(errors[0].id, "postgres.E002")
def test_invalid_default(self):
class MyModel(PostgreSQLModel):
field = ArrayField(models.IntegerField(), default=[])
model = MyModel()
- self.assertEqual(model.check(), [
- checks.Warning(
- msg=(
- "ArrayField default should be a callable instead of an "
- "instance so that it's not shared between all field "
- "instances."
- ),
- hint='Use a callable instead, e.g., use `list` instead of `[]`.',
- obj=MyModel._meta.get_field('field'),
- id='fields.E010',
- )
- ])
+ self.assertEqual(
+ model.check(),
+ [
+ checks.Warning(
+ msg=(
+ "ArrayField default should be a callable instead of an "
+ "instance so that it's not shared between all field "
+ "instances."
+ ),
+ hint="Use a callable instead, e.g., use `list` instead of `[]`.",
+ obj=MyModel._meta.get_field("field"),
+ id="fields.E010",
+ )
+ ],
+ )
def test_valid_default(self):
class MyModel(PostgreSQLModel):
@@ -742,6 +765,7 @@ class TestChecks(PostgreSQLSimpleTestCase):
"""
Nested ArrayFields are permitted.
"""
+
class MyModel(PostgreSQLModel):
field = ArrayField(ArrayField(models.CharField()))
@@ -749,8 +773,8 @@ class TestChecks(PostgreSQLSimpleTestCase):
errors = model.check()
self.assertEqual(len(errors), 1)
# The inner CharField is missing a max_length.
- self.assertEqual(errors[0].id, 'postgres.E001')
- self.assertIn('max_length', errors[0].msg)
+ self.assertEqual(errors[0].id, "postgres.E001")
+ self.assertIn("max_length", errors[0].msg)
def test_choices_tuple_list(self):
class MyModel(PostgreSQLModel):
@@ -758,19 +782,20 @@ class TestChecks(PostgreSQLSimpleTestCase):
models.CharField(max_length=16),
choices=[
[
- 'Media',
- [(['vinyl', 'cd'], 'Audio'), (('vhs', 'dvd'), 'Video')],
+ "Media",
+ [(["vinyl", "cd"], "Audio"), (("vhs", "dvd"), "Video")],
],
- (['mp3', 'mp4'], 'Digital'),
+ (["mp3", "mp4"], "Digital"),
],
)
- self.assertEqual(MyModel._meta.get_field('field').check(), [])
+
+ self.assertEqual(MyModel._meta.get_field("field").check(), [])
-@unittest.skipUnless(connection.vendor == 'postgresql', "PostgreSQL specific tests")
+@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific tests")
class TestMigrations(TransactionTestCase):
- available_apps = ['postgres_tests']
+ available_apps = ["postgres_tests"]
def test_deconstruct(self):
field = ArrayField(models.IntegerField())
@@ -794,84 +819,89 @@ class TestMigrations(TransactionTestCase):
def test_subclass_deconstruct(self):
field = ArrayField(models.IntegerField())
name, path, args, kwargs = field.deconstruct()
- self.assertEqual(path, 'django.contrib.postgres.fields.ArrayField')
+ self.assertEqual(path, "django.contrib.postgres.fields.ArrayField")
field = ArrayFieldSubclass()
name, path, args, kwargs = field.deconstruct()
- self.assertEqual(path, 'postgres_tests.models.ArrayFieldSubclass')
+ self.assertEqual(path, "postgres_tests.models.ArrayFieldSubclass")
- @override_settings(MIGRATION_MODULES={
- "postgres_tests": "postgres_tests.array_default_migrations",
- })
+ @override_settings(
+ MIGRATION_MODULES={
+ "postgres_tests": "postgres_tests.array_default_migrations",
+ }
+ )
def test_adding_field_with_default(self):
# See #22962
- table_name = 'postgres_tests_integerarraydefaultmodel'
+ table_name = "postgres_tests_integerarraydefaultmodel"
with connection.cursor() as cursor:
self.assertNotIn(table_name, connection.introspection.table_names(cursor))
- call_command('migrate', 'postgres_tests', verbosity=0)
+ call_command("migrate", "postgres_tests", verbosity=0)
with connection.cursor() as cursor:
self.assertIn(table_name, connection.introspection.table_names(cursor))
- call_command('migrate', 'postgres_tests', 'zero', verbosity=0)
+ call_command("migrate", "postgres_tests", "zero", verbosity=0)
with connection.cursor() as cursor:
self.assertNotIn(table_name, connection.introspection.table_names(cursor))
- @override_settings(MIGRATION_MODULES={
- "postgres_tests": "postgres_tests.array_index_migrations",
- })
+ @override_settings(
+ MIGRATION_MODULES={
+ "postgres_tests": "postgres_tests.array_index_migrations",
+ }
+ )
def test_adding_arrayfield_with_index(self):
"""
ArrayField shouldn't have varchar_patterns_ops or text_patterns_ops indexes.
"""
- table_name = 'postgres_tests_chartextarrayindexmodel'
- call_command('migrate', 'postgres_tests', verbosity=0)
+ table_name = "postgres_tests_chartextarrayindexmodel"
+ call_command("migrate", "postgres_tests", verbosity=0)
with connection.cursor() as cursor:
like_constraint_columns_list = [
- v['columns']
- for k, v in list(connection.introspection.get_constraints(cursor, table_name).items())
- if k.endswith('_like')
+ v["columns"]
+ for k, v in list(
+ connection.introspection.get_constraints(cursor, table_name).items()
+ )
+ if k.endswith("_like")
]
# Only the CharField should have a LIKE index.
- self.assertEqual(like_constraint_columns_list, [['char2']])
+ self.assertEqual(like_constraint_columns_list, [["char2"]])
# All fields should have regular indexes.
with connection.cursor() as cursor:
indexes = [
- c['columns'][0]
- for c in connection.introspection.get_constraints(cursor, table_name).values()
- if c['index'] and len(c['columns']) == 1
+ c["columns"][0]
+ for c in connection.introspection.get_constraints(
+ cursor, table_name
+ ).values()
+ if c["index"] and len(c["columns"]) == 1
]
- self.assertIn('char', indexes)
- self.assertIn('char2', indexes)
- self.assertIn('text', indexes)
- call_command('migrate', 'postgres_tests', 'zero', verbosity=0)
+ self.assertIn("char", indexes)
+ self.assertIn("char2", indexes)
+ self.assertIn("text", indexes)
+ call_command("migrate", "postgres_tests", "zero", verbosity=0)
with connection.cursor() as cursor:
self.assertNotIn(table_name, connection.introspection.table_names(cursor))
class TestSerialization(PostgreSQLSimpleTestCase):
- test_data = (
- '[{"fields": {"field": "[\\"1\\", \\"2\\", null]"}, "model": "postgres_tests.integerarraymodel", "pk": null}]'
- )
+ test_data = '[{"fields": {"field": "[\\"1\\", \\"2\\", null]"}, "model": "postgres_tests.integerarraymodel", "pk": null}]'
def test_dumping(self):
instance = IntegerArrayModel(field=[1, 2, None])
- data = serializers.serialize('json', [instance])
+ data = serializers.serialize("json", [instance])
self.assertEqual(json.loads(data), json.loads(self.test_data))
def test_loading(self):
- instance = list(serializers.deserialize('json', self.test_data))[0].object
+ instance = list(serializers.deserialize("json", self.test_data))[0].object
self.assertEqual(instance.field, [1, 2, None])
class TestValidation(PostgreSQLSimpleTestCase):
-
def test_unbounded(self):
field = ArrayField(models.IntegerField())
with self.assertRaises(exceptions.ValidationError) as cm:
field.clean([1, None], None)
- self.assertEqual(cm.exception.code, 'item_invalid')
+ self.assertEqual(cm.exception.code, "item_invalid")
self.assertEqual(
cm.exception.message % cm.exception.params,
- 'Item 2 in the array did not validate: This field cannot be null.'
+ "Item 2 in the array did not validate: This field cannot be null.",
)
def test_blank_true(self):
@@ -884,31 +914,41 @@ class TestValidation(PostgreSQLSimpleTestCase):
field.clean([1, 2, 3], None)
with self.assertRaises(exceptions.ValidationError) as cm:
field.clean([1, 2, 3, 4], None)
- self.assertEqual(cm.exception.messages[0], 'List contains 4 items, it should contain no more than 3.')
+ self.assertEqual(
+ cm.exception.messages[0],
+ "List contains 4 items, it should contain no more than 3.",
+ )
def test_nested_array_mismatch(self):
field = ArrayField(ArrayField(models.IntegerField()))
field.clean([[1, 2], [3, 4]], None)
with self.assertRaises(exceptions.ValidationError) as cm:
field.clean([[1, 2], [3, 4, 5]], None)
- self.assertEqual(cm.exception.code, 'nested_array_mismatch')
- self.assertEqual(cm.exception.messages[0], 'Nested arrays must have the same length.')
+ self.assertEqual(cm.exception.code, "nested_array_mismatch")
+ self.assertEqual(
+ cm.exception.messages[0], "Nested arrays must have the same length."
+ )
def test_with_base_field_error_params(self):
field = ArrayField(models.CharField(max_length=2))
with self.assertRaises(exceptions.ValidationError) as cm:
- field.clean(['abc'], None)
+ field.clean(["abc"], None)
self.assertEqual(len(cm.exception.error_list), 1)
exception = cm.exception.error_list[0]
self.assertEqual(
exception.message,
- 'Item 1 in the array did not validate: Ensure this value has at most 2 characters (it has 3).'
+ "Item 1 in the array did not validate: Ensure this value has at most 2 characters (it has 3).",
+ )
+ self.assertEqual(exception.code, "item_invalid")
+ self.assertEqual(
+ exception.params,
+ {"nth": 1, "value": "abc", "limit_value": 2, "show_value": 3},
)
- self.assertEqual(exception.code, 'item_invalid')
- self.assertEqual(exception.params, {'nth': 1, 'value': 'abc', 'limit_value': 2, 'show_value': 3})
def test_with_validators(self):
- field = ArrayField(models.IntegerField(validators=[validators.MinValueValidator(1)]))
+ field = ArrayField(
+ models.IntegerField(validators=[validators.MinValueValidator(1)])
+ )
field.clean([1, 2], None)
with self.assertRaises(exceptions.ValidationError) as cm:
field.clean([0], None)
@@ -916,90 +956,112 @@ class TestValidation(PostgreSQLSimpleTestCase):
exception = cm.exception.error_list[0]
self.assertEqual(
exception.message,
- 'Item 1 in the array did not validate: Ensure this value is greater than or equal to 1.'
+ "Item 1 in the array did not validate: Ensure this value is greater than or equal to 1.",
+ )
+ self.assertEqual(exception.code, "item_invalid")
+ self.assertEqual(
+ exception.params, {"nth": 1, "value": 0, "limit_value": 1, "show_value": 0}
)
- self.assertEqual(exception.code, 'item_invalid')
- self.assertEqual(exception.params, {'nth': 1, 'value': 0, 'limit_value': 1, 'show_value': 0})
class TestSimpleFormField(PostgreSQLSimpleTestCase):
-
def test_valid(self):
field = SimpleArrayField(forms.CharField())
- value = field.clean('a,b,c')
- self.assertEqual(value, ['a', 'b', 'c'])
+ value = field.clean("a,b,c")
+ self.assertEqual(value, ["a", "b", "c"])
def test_to_python_fail(self):
field = SimpleArrayField(forms.IntegerField())
with self.assertRaises(exceptions.ValidationError) as cm:
- field.clean('a,b,9')
- self.assertEqual(cm.exception.messages[0], 'Item 1 in the array did not validate: Enter a whole number.')
+ field.clean("a,b,9")
+ self.assertEqual(
+ cm.exception.messages[0],
+ "Item 1 in the array did not validate: Enter a whole number.",
+ )
def test_validate_fail(self):
field = SimpleArrayField(forms.CharField(required=True))
with self.assertRaises(exceptions.ValidationError) as cm:
- field.clean('a,b,')
- self.assertEqual(cm.exception.messages[0], 'Item 3 in the array did not validate: This field is required.')
+ field.clean("a,b,")
+ self.assertEqual(
+ cm.exception.messages[0],
+ "Item 3 in the array did not validate: This field is required.",
+ )
def test_validate_fail_base_field_error_params(self):
field = SimpleArrayField(forms.CharField(max_length=2))
with self.assertRaises(exceptions.ValidationError) as cm:
- field.clean('abc,c,defg')
+ field.clean("abc,c,defg")
errors = cm.exception.error_list
self.assertEqual(len(errors), 2)
first_error = errors[0]
self.assertEqual(
first_error.message,
- 'Item 1 in the array did not validate: Ensure this value has at most 2 characters (it has 3).'
+ "Item 1 in the array did not validate: Ensure this value has at most 2 characters (it has 3).",
+ )
+ self.assertEqual(first_error.code, "item_invalid")
+ self.assertEqual(
+ first_error.params,
+ {"nth": 1, "value": "abc", "limit_value": 2, "show_value": 3},
)
- self.assertEqual(first_error.code, 'item_invalid')
- self.assertEqual(first_error.params, {'nth': 1, 'value': 'abc', 'limit_value': 2, 'show_value': 3})
second_error = errors[1]
self.assertEqual(
second_error.message,
- 'Item 3 in the array did not validate: Ensure this value has at most 2 characters (it has 4).'
+ "Item 3 in the array did not validate: Ensure this value has at most 2 characters (it has 4).",
+ )
+ self.assertEqual(second_error.code, "item_invalid")
+ self.assertEqual(
+ second_error.params,
+ {"nth": 3, "value": "defg", "limit_value": 2, "show_value": 4},
)
- self.assertEqual(second_error.code, 'item_invalid')
- self.assertEqual(second_error.params, {'nth': 3, 'value': 'defg', 'limit_value': 2, 'show_value': 4})
def test_validators_fail(self):
- field = SimpleArrayField(forms.RegexField('[a-e]{2}'))
+ field = SimpleArrayField(forms.RegexField("[a-e]{2}"))
with self.assertRaises(exceptions.ValidationError) as cm:
- field.clean('a,bc,de')
- self.assertEqual(cm.exception.messages[0], 'Item 1 in the array did not validate: Enter a valid value.')
+ field.clean("a,bc,de")
+ self.assertEqual(
+ cm.exception.messages[0],
+ "Item 1 in the array did not validate: Enter a valid value.",
+ )
def test_delimiter(self):
- field = SimpleArrayField(forms.CharField(), delimiter='|')
- value = field.clean('a|b|c')
- self.assertEqual(value, ['a', 'b', 'c'])
+ field = SimpleArrayField(forms.CharField(), delimiter="|")
+ value = field.clean("a|b|c")
+ self.assertEqual(value, ["a", "b", "c"])
def test_delimiter_with_nesting(self):
- field = SimpleArrayField(SimpleArrayField(forms.CharField()), delimiter='|')
- value = field.clean('a,b|c,d')
- self.assertEqual(value, [['a', 'b'], ['c', 'd']])
+ field = SimpleArrayField(SimpleArrayField(forms.CharField()), delimiter="|")
+ value = field.clean("a,b|c,d")
+ self.assertEqual(value, [["a", "b"], ["c", "d"]])
def test_prepare_value(self):
field = SimpleArrayField(forms.CharField())
- value = field.prepare_value(['a', 'b', 'c'])
- self.assertEqual(value, 'a,b,c')
+ value = field.prepare_value(["a", "b", "c"])
+ self.assertEqual(value, "a,b,c")
def test_max_length(self):
field = SimpleArrayField(forms.CharField(), max_length=2)
with self.assertRaises(exceptions.ValidationError) as cm:
- field.clean('a,b,c')
- self.assertEqual(cm.exception.messages[0], 'List contains 3 items, it should contain no more than 2.')
+ field.clean("a,b,c")
+ self.assertEqual(
+ cm.exception.messages[0],
+ "List contains 3 items, it should contain no more than 2.",
+ )
def test_min_length(self):
field = SimpleArrayField(forms.CharField(), min_length=4)
with self.assertRaises(exceptions.ValidationError) as cm:
- field.clean('a,b,c')
- self.assertEqual(cm.exception.messages[0], 'List contains 3 items, it should contain no fewer than 4.')
+ field.clean("a,b,c")
+ self.assertEqual(
+ cm.exception.messages[0],
+ "List contains 3 items, it should contain no fewer than 4.",
+ )
def test_required(self):
field = SimpleArrayField(forms.CharField(), required=True)
with self.assertRaises(exceptions.ValidationError) as cm:
- field.clean('')
- self.assertEqual(cm.exception.messages[0], 'This field is required.')
+ field.clean("")
+ self.assertEqual(cm.exception.messages[0], "This field is required.")
def test_model_field_formfield(self):
model_field = ArrayField(models.CharField(max_length=27))
@@ -1015,59 +1077,66 @@ class TestSimpleFormField(PostgreSQLSimpleTestCase):
self.assertEqual(form_field.max_length, 4)
def test_model_field_choices(self):
- model_field = ArrayField(models.IntegerField(choices=((1, 'A'), (2, 'B'))))
+ model_field = ArrayField(models.IntegerField(choices=((1, "A"), (2, "B"))))
form_field = model_field.formfield()
- self.assertEqual(form_field.clean('1,2'), [1, 2])
+ self.assertEqual(form_field.clean("1,2"), [1, 2])
def test_already_converted_value(self):
field = SimpleArrayField(forms.CharField())
- vals = ['a', 'b', 'c']
+ vals = ["a", "b", "c"]
self.assertEqual(field.clean(vals), vals)
def test_has_changed(self):
field = SimpleArrayField(forms.IntegerField())
self.assertIs(field.has_changed([1, 2], [1, 2]), False)
- self.assertIs(field.has_changed([1, 2], '1,2'), False)
- self.assertIs(field.has_changed([1, 2], '1,2,3'), True)
- self.assertIs(field.has_changed([1, 2], 'a,b'), True)
+ self.assertIs(field.has_changed([1, 2], "1,2"), False)
+ self.assertIs(field.has_changed([1, 2], "1,2,3"), True)
+ self.assertIs(field.has_changed([1, 2], "a,b"), True)
def test_has_changed_empty(self):
field = SimpleArrayField(forms.CharField())
self.assertIs(field.has_changed(None, None), False)
- self.assertIs(field.has_changed(None, ''), False)
+ self.assertIs(field.has_changed(None, ""), False)
self.assertIs(field.has_changed(None, []), False)
self.assertIs(field.has_changed([], None), False)
- self.assertIs(field.has_changed([], ''), False)
+ self.assertIs(field.has_changed([], ""), False)
class TestSplitFormField(PostgreSQLSimpleTestCase):
-
def test_valid(self):
class SplitForm(forms.Form):
array = SplitArrayField(forms.CharField(), size=3)
- data = {'array_0': 'a', 'array_1': 'b', 'array_2': 'c'}
+ data = {"array_0": "a", "array_1": "b", "array_2": "c"}
form = SplitForm(data)
self.assertTrue(form.is_valid())
- self.assertEqual(form.cleaned_data, {'array': ['a', 'b', 'c']})
+ self.assertEqual(form.cleaned_data, {"array": ["a", "b", "c"]})
def test_required(self):
class SplitForm(forms.Form):
array = SplitArrayField(forms.CharField(), required=True, size=3)
- data = {'array_0': '', 'array_1': '', 'array_2': ''}
+ data = {"array_0": "", "array_1": "", "array_2": ""}
form = SplitForm(data)
self.assertFalse(form.is_valid())
- self.assertEqual(form.errors, {'array': ['This field is required.']})
+ self.assertEqual(form.errors, {"array": ["This field is required."]})
def test_remove_trailing_nulls(self):
class SplitForm(forms.Form):
- array = SplitArrayField(forms.CharField(required=False), size=5, remove_trailing_nulls=True)
+ array = SplitArrayField(
+ forms.CharField(required=False), size=5, remove_trailing_nulls=True
+ )
- data = {'array_0': 'a', 'array_1': '', 'array_2': 'b', 'array_3': '', 'array_4': ''}
+ data = {
+ "array_0": "a",
+ "array_1": "",
+ "array_2": "b",
+ "array_3": "",
+ "array_4": "",
+ }
form = SplitForm(data)
self.assertTrue(form.is_valid(), form.errors)
- self.assertEqual(form.cleaned_data, {'array': ['a', '', 'b']})
+ self.assertEqual(form.cleaned_data, {"array": ["a", "", "b"]})
def test_remove_trailing_nulls_not_required(self):
class SplitForm(forms.Form):
@@ -1078,32 +1147,41 @@ class TestSplitFormField(PostgreSQLSimpleTestCase):
required=False,
)
- data = {'array_0': '', 'array_1': ''}
+ data = {"array_0": "", "array_1": ""}
form = SplitForm(data)
self.assertTrue(form.is_valid())
- self.assertEqual(form.cleaned_data, {'array': []})
+ self.assertEqual(form.cleaned_data, {"array": []})
def test_required_field(self):
class SplitForm(forms.Form):
array = SplitArrayField(forms.CharField(), size=3)
- data = {'array_0': 'a', 'array_1': 'b', 'array_2': ''}
+ data = {"array_0": "a", "array_1": "b", "array_2": ""}
form = SplitForm(data)
self.assertFalse(form.is_valid())
- self.assertEqual(form.errors, {'array': ['Item 3 in the array did not validate: This field is required.']})
+ self.assertEqual(
+ form.errors,
+ {
+ "array": [
+ "Item 3 in the array did not validate: This field is required."
+ ]
+ },
+ )
def test_invalid_integer(self):
- msg = 'Item 2 in the array did not validate: Ensure this value is less than or equal to 100.'
+ msg = "Item 2 in the array did not validate: Ensure this value is less than or equal to 100."
with self.assertRaisesMessage(exceptions.ValidationError, msg):
SplitArrayField(forms.IntegerField(max_value=100), size=2).clean([0, 101])
# To locate the widget's template.
- @modify_settings(INSTALLED_APPS={'append': 'django.contrib.postgres'})
+ @modify_settings(INSTALLED_APPS={"append": "django.contrib.postgres"})
def test_rendering(self):
class SplitForm(forms.Form):
array = SplitArrayField(forms.CharField(), size=3)
- self.assertHTMLEqual(str(SplitForm()), '''
+ self.assertHTMLEqual(
+ str(SplitForm()),
+ """
<tr>
<th><label for="id_array_0">Array:</label></th>
<td>
@@ -1112,16 +1190,20 @@ class TestSplitFormField(PostgreSQLSimpleTestCase):
<input id="id_array_2" name="array_2" type="text" required>
</td>
</tr>
- ''')
+ """,
+ )
def test_invalid_char_length(self):
field = SplitArrayField(forms.CharField(max_length=2), size=3)
with self.assertRaises(exceptions.ValidationError) as cm:
- field.clean(['abc', 'c', 'defg'])
- self.assertEqual(cm.exception.messages, [
- 'Item 1 in the array did not validate: Ensure this value has at most 2 characters (it has 3).',
- 'Item 3 in the array did not validate: Ensure this value has at most 2 characters (it has 4).',
- ])
+ field.clean(["abc", "c", "defg"])
+ self.assertEqual(
+ cm.exception.messages,
+ [
+ "Item 1 in the array did not validate: Ensure this value has at most 2 characters (it has 3).",
+ "Item 3 in the array did not validate: Ensure this value has at most 2 characters (it has 4).",
+ ],
+ )
def test_splitarraywidget_value_omitted_from_data(self):
class Form(forms.ModelForm):
@@ -1129,9 +1211,9 @@ class TestSplitFormField(PostgreSQLSimpleTestCase):
class Meta:
model = IntegerArrayModel
- fields = ('field',)
+ fields = ("field",)
- form = Form({'field_0': '1', 'field_1': '2'})
+ form = Form({"field_0": "1", "field_1": "2"})
self.assertEqual(form.errors, {})
obj = form.save(commit=False)
self.assertEqual(obj.field, [1, 2])
@@ -1142,15 +1224,15 @@ class TestSplitFormField(PostgreSQLSimpleTestCase):
class Meta:
model = IntegerArrayModel
- fields = ('field',)
+ fields = ("field",)
tests = [
- ({}, {'field_0': '', 'field_1': ''}, True),
- ({'field': None}, {'field_0': '', 'field_1': ''}, True),
- ({'field': [1]}, {'field_0': '', 'field_1': ''}, True),
- ({'field': [1]}, {'field_0': '1', 'field_1': '0'}, True),
- ({'field': [1, 2]}, {'field_0': '1', 'field_1': '2'}, False),
- ({'field': [1, 2]}, {'field_0': 'a', 'field_1': 'b'}, True),
+ ({}, {"field_0": "", "field_1": ""}, True),
+ ({"field": None}, {"field_0": "", "field_1": ""}, True),
+ ({"field": [1]}, {"field_0": "", "field_1": ""}, True),
+ ({"field": [1]}, {"field_0": "1", "field_1": "0"}, True),
+ ({"field": [1, 2]}, {"field_0": "1", "field_1": "2"}, False),
+ ({"field": [1, 2]}, {"field_0": "a", "field_1": "b"}, True),
]
for initial, data, expected_result in tests:
with self.subTest(initial=initial, data=data):
@@ -1160,17 +1242,19 @@ class TestSplitFormField(PostgreSQLSimpleTestCase):
def test_splitarrayfield_remove_trailing_nulls_has_changed(self):
class Form(forms.ModelForm):
- field = SplitArrayField(forms.IntegerField(), required=False, size=2, remove_trailing_nulls=True)
+ field = SplitArrayField(
+ forms.IntegerField(), required=False, size=2, remove_trailing_nulls=True
+ )
class Meta:
model = IntegerArrayModel
- fields = ('field',)
+ fields = ("field",)
tests = [
- ({}, {'field_0': '', 'field_1': ''}, False),
- ({'field': None}, {'field_0': '', 'field_1': ''}, False),
- ({'field': []}, {'field_0': '', 'field_1': ''}, False),
- ({'field': [1]}, {'field_0': '1', 'field_1': ''}, False),
+ ({}, {"field_0": "", "field_1": ""}, False),
+ ({"field": None}, {"field_0": "", "field_1": ""}, False),
+ ({"field": []}, {"field_0": "", "field_1": ""}, False),
+ ({"field": [1]}, {"field_0": "1", "field_1": ""}, False),
]
for initial, data, expected_result in tests:
with self.subTest(initial=initial, data=data):
@@ -1180,77 +1264,91 @@ class TestSplitFormField(PostgreSQLSimpleTestCase):
class TestSplitFormWidget(PostgreSQLWidgetTestCase):
-
def test_get_context(self):
self.assertEqual(
- SplitArrayWidget(forms.TextInput(), size=2).get_context('name', ['val1', 'val2']),
+ SplitArrayWidget(forms.TextInput(), size=2).get_context(
+ "name", ["val1", "val2"]
+ ),
{
- 'widget': {
- 'name': 'name',
- 'is_hidden': False,
- 'required': False,
- 'value': "['val1', 'val2']",
- 'attrs': {},
- 'template_name': 'postgres/widgets/split_array.html',
- 'subwidgets': [
+ "widget": {
+ "name": "name",
+ "is_hidden": False,
+ "required": False,
+ "value": "['val1', 'val2']",
+ "attrs": {},
+ "template_name": "postgres/widgets/split_array.html",
+ "subwidgets": [
{
- 'name': 'name_0',
- 'is_hidden': False,
- 'required': False,
- 'value': 'val1',
- 'attrs': {},
- 'template_name': 'django/forms/widgets/text.html',
- 'type': 'text',
+ "name": "name_0",
+ "is_hidden": False,
+ "required": False,
+ "value": "val1",
+ "attrs": {},
+ "template_name": "django/forms/widgets/text.html",
+ "type": "text",
},
{
- 'name': 'name_1',
- 'is_hidden': False,
- 'required': False,
- 'value': 'val2',
- 'attrs': {},
- 'template_name': 'django/forms/widgets/text.html',
- 'type': 'text',
+ "name": "name_1",
+ "is_hidden": False,
+ "required": False,
+ "value": "val2",
+ "attrs": {},
+ "template_name": "django/forms/widgets/text.html",
+ "type": "text",
},
- ]
+ ],
}
- }
+ },
)
def test_checkbox_get_context_attrs(self):
context = SplitArrayWidget(
forms.CheckboxInput(),
size=2,
- ).get_context('name', [True, False])
- self.assertEqual(context['widget']['value'], '[True, False]')
+ ).get_context("name", [True, False])
+ self.assertEqual(context["widget"]["value"], "[True, False]")
self.assertEqual(
- [subwidget['attrs'] for subwidget in context['widget']['subwidgets']],
- [{'checked': True}, {}]
+ [subwidget["attrs"] for subwidget in context["widget"]["subwidgets"]],
+ [{"checked": True}, {}],
)
def test_render(self):
self.check_html(
- SplitArrayWidget(forms.TextInput(), size=2), 'array', None,
+ SplitArrayWidget(forms.TextInput(), size=2),
+ "array",
+ None,
"""
<input name="array_0" type="text">
<input name="array_1" type="text">
- """
+ """,
)
def test_render_attrs(self):
self.check_html(
SplitArrayWidget(forms.TextInput(), size=2),
- 'array', ['val1', 'val2'], attrs={'id': 'foo'},
+ "array",
+ ["val1", "val2"],
+ attrs={"id": "foo"},
html=(
"""
<input id="foo_0" name="array_0" type="text" value="val1">
<input id="foo_1" name="array_1" type="text" value="val2">
"""
- )
+ ),
)
def test_value_omitted_from_data(self):
widget = SplitArrayWidget(forms.TextInput(), size=2)
- self.assertIs(widget.value_omitted_from_data({}, {}, 'field'), True)
- self.assertIs(widget.value_omitted_from_data({'field_0': 'value'}, {}, 'field'), False)
- self.assertIs(widget.value_omitted_from_data({'field_1': 'value'}, {}, 'field'), False)
- self.assertIs(widget.value_omitted_from_data({'field_0': 'value', 'field_1': 'value'}, {}, 'field'), False)
+ self.assertIs(widget.value_omitted_from_data({}, {}, "field"), True)
+ self.assertIs(
+ widget.value_omitted_from_data({"field_0": "value"}, {}, "field"), False
+ )
+ self.assertIs(
+ widget.value_omitted_from_data({"field_1": "value"}, {}, "field"), False
+ )
+ self.assertIs(
+ widget.value_omitted_from_data(
+ {"field_0": "value", "field_1": "value"}, {}, "field"
+ ),
+ False,
+ )