diff options
| author | django-bot <ops@djangoproject.com> | 2022-02-03 20:24:19 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-02-07 20:37:05 +0100 |
| commit | 9c19aff7c7561e3a82978a272ecdaad40dda5c00 (patch) | |
| tree | f0506b668a013d0063e5fba3dbf4863b466713ba /tests/postgres_tests/test_array.py | |
| parent | f68fa8b45dfac545cfc4111d4e52804c86db68d3 (diff) | |
Refs #33476 -- Reformatted code with Black.
Diffstat (limited to 'tests/postgres_tests/test_array.py')
| -rw-r--r-- | tests/postgres_tests/test_array.py | 802 |
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, + ) |
