From 87acbf063156ebb3fec3d35ef139895335061e0b Mon Sep 17 00:00:00 2001 From: Hannes Ljungberg Date: Fri, 19 Feb 2021 12:16:24 +0100 Subject: [PATCH] Fixed #32458 -- Made __repr__() for Index and BaseConstraint subclasses more consistent. --- django/contrib/postgres/constraints.py | 15 ++++----- django/db/models/constraints.py | 12 +++++-- django/db/models/indexes.py | 18 ++++++----- tests/constraints/tests.py | 10 +++--- tests/migrations/test_operations.py | 2 +- tests/migrations/test_state.py | 5 ++- tests/model_indexes/tests.py | 40 +++++++++++++++++++----- tests/postgres_tests/test_constraints.py | 24 ++++++++------ 8 files changed, 84 insertions(+), 42 deletions(-) diff --git a/django/contrib/postgres/constraints.py b/django/contrib/postgres/constraints.py index a844b899b7..32c6bb622e 100644 --- a/django/contrib/postgres/constraints.py +++ b/django/contrib/postgres/constraints.py @@ -155,12 +155,13 @@ class ExclusionConstraint(BaseConstraint): return super().__eq__(other) def __repr__(self): - return '<%s: index_type=%s, expressions=%s%s%s%s%s>' % ( + return '<%s: index_type=%s expressions=%s name=%s%s%s%s%s>' % ( self.__class__.__qualname__, - self.index_type, - self.expressions, - '' if self.condition is None else ', condition=%s' % self.condition, - '' if self.deferrable is None else ', deferrable=%s' % self.deferrable, - '' if not self.include else ', include=%s' % repr(self.include), - '' if not self.opclasses else ', opclasses=%s' % repr(self.opclasses), + repr(self.index_type), + repr(self.expressions), + repr(self.name), + '' if self.condition is None else ' condition=%s' % self.condition, + '' if self.deferrable is None else ' deferrable=%s' % self.deferrable, + '' if not self.include else ' include=%s' % repr(self.include), + '' if not self.opclasses else ' opclasses=%s' % repr(self.opclasses), ) diff --git a/django/db/models/constraints.py b/django/db/models/constraints.py index fd01ec5a11..0b85b46257 100644 --- a/django/db/models/constraints.py +++ b/django/db/models/constraints.py @@ -58,7 +58,11 @@ class CheckConstraint(BaseConstraint): return schema_editor._delete_check_sql(model, self.name) def __repr__(self): - return "<%s: check='%s' name=%r>" % (self.__class__.__name__, self.check, self.name) + return '<%s: check=%s name=%s>' % ( + self.__class__.__qualname__, + self.check, + repr(self.name), + ) def __eq__(self, other): if isinstance(other, CheckConstraint): @@ -161,8 +165,10 @@ class UniqueConstraint(BaseConstraint): ) def __repr__(self): - return '<%s: fields=%r name=%r%s%s%s%s>' % ( - self.__class__.__name__, self.fields, self.name, + return '<%s: fields=%s name=%s%s%s%s%s>' % ( + self.__class__.__qualname__, + repr(self.fields), + repr(self.name), '' if self.condition is None else ' condition=%s' % self.condition, '' if self.deferrable is None else ' deferrable=%s' % self.deferrable, '' if not self.include else ' include=%s' % repr(self.include), diff --git a/django/db/models/indexes.py b/django/db/models/indexes.py index 5530d0b661..cc91c70479 100644 --- a/django/db/models/indexes.py +++ b/django/db/models/indexes.py @@ -169,15 +169,17 @@ class Index: self.name = 'D%s' % self.name[1:] def __repr__(self): - return '<%s:%s%s%s%s%s>' % ( - self.__class__.__name__, - '' if not self.fields else " fields='%s'" % ', '.join(self.fields), - '' if not self.expressions else " expressions='%s'" % ', '.join([ - str(expression) for expression in self.expressions - ]), + return '<%s:%s%s%s%s%s%s%s>' % ( + self.__class__.__qualname__, + '' if not self.fields else ' fields=%s' % repr(self.fields), + '' if not self.expressions else ' expressions=%s' % repr(self.expressions), + '' if not self.name else ' name=%s' % repr(self.name), + '' + if self.db_tablespace is None + else ' db_tablespace=%s' % repr(self.db_tablespace), '' if self.condition is None else ' condition=%s' % self.condition, - '' if not self.include else " include='%s'" % ', '.join(self.include), - '' if not self.opclasses else " opclasses='%s'" % ', '.join(self.opclasses), + '' if not self.include else ' include=%s' % repr(self.include), + '' if not self.opclasses else ' opclasses=%s' % repr(self.opclasses), ) def __eq__(self, other): diff --git a/tests/constraints/tests.py b/tests/constraints/tests.py index 2796a0f30b..cb366d8e45 100644 --- a/tests/constraints/tests.py +++ b/tests/constraints/tests.py @@ -58,12 +58,14 @@ class CheckConstraintTests(TestCase): self.assertNotEqual(models.CheckConstraint(check=check1, name='price'), 1) def test_repr(self): - check = models.Q(price__gt=models.F('discounted_price')) - name = 'price_gt_discounted_price' - constraint = models.CheckConstraint(check=check, name=name) + constraint = models.CheckConstraint( + check=models.Q(price__gt=models.F('discounted_price')), + name='price_gt_discounted_price', + ) self.assertEqual( repr(constraint), - "".format(check, name), + "", ) def test_invalid_check_types(self): diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index 984aefa23d..73a0c63921 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -1840,7 +1840,7 @@ class OperationTests(OperationTestBase): project_state = self.set_up_test_model("test_adin") msg = ( "Indexes passed to AddIndex operations require a name argument. " - " doesn't have one." + " doesn't have one." ) with self.assertRaisesMessage(ValueError, msg): migrations.AddIndex("Pony", models.Index(fields=["pink"])) diff --git a/tests/migrations/test_state.py b/tests/migrations/test_state.py index 5ac9bf858f..4d87a1ebc5 100644 --- a/tests/migrations/test_state.py +++ b/tests/migrations/test_state.py @@ -1046,7 +1046,10 @@ class ModelStateTests(SimpleTestCase): def test_sanity_index_name(self): field = models.IntegerField() options = {'indexes': [models.Index(fields=['field'])]} - msg = "Indexes passed to ModelState require a name attribute. doesn't have one." + msg = ( + "Indexes passed to ModelState require a name attribute. doesn't have one." + ) with self.assertRaisesMessage(ValueError, msg): ModelState('app', 'Model', [('field', field)], options=options) diff --git a/tests/model_indexes/tests.py b/tests/model_indexes/tests.py index ab231edd5e..46f769cddc 100644 --- a/tests/model_indexes/tests.py +++ b/tests/model_indexes/tests.py @@ -16,6 +16,7 @@ class SimpleIndexesTests(SimpleTestCase): def test_repr(self): index = models.Index(fields=['title']) + named_index = models.Index(fields=['title'], name='title_idx') multi_col_index = models.Index(fields=['title', 'author']) partial_index = models.Index(fields=['title'], name='long_books_idx', condition=models.Q(pages__gt=400)) covering_index = models.Index( @@ -28,20 +29,43 @@ class SimpleIndexesTests(SimpleTestCase): name='opclasses_idx', opclasses=['varchar_pattern_ops', 'text_pattern_ops'], ) - func_index = models.Index(Lower('title'), name='book_func_idx') - self.assertEqual(repr(index), "") - self.assertEqual(repr(multi_col_index), "") - self.assertEqual(repr(partial_index), "") + func_index = models.Index(Lower('title'), 'subtitle', name='book_func_idx') + tablespace_index = models.Index( + fields=['title'], + db_tablespace='idx_tbls', + name='book_tablespace_idx', + ) + self.assertEqual(repr(index), "") + self.assertEqual( + repr(named_index), + "", + ) + self.assertEqual(repr(multi_col_index), "") + self.assertEqual( + repr(partial_index), + "", + ) self.assertEqual( repr(covering_index), - "", + "", ) self.assertEqual( repr(opclasses_index), - "", + "", + ) + self.assertEqual( + repr(func_index), + "", + ) + self.assertEqual( + repr(tablespace_index), + "", ) - self.assertEqual(repr(func_index), "") def test_eq(self): index = models.Index(fields=['title']) diff --git a/tests/postgres_tests/test_constraints.py b/tests/postgres_tests/test_constraints.py index 1bf52d0cc0..80c2bb77b6 100644 --- a/tests/postgres_tests/test_constraints.py +++ b/tests/postgres_tests/test_constraints.py @@ -282,8 +282,8 @@ class ExclusionConstraintTests(PostgreSQLTestCase): ) self.assertEqual( repr(constraint), - "", ) constraint = ExclusionConstraint( name='exclude_overlapping', @@ -293,8 +293,9 @@ class ExclusionConstraintTests(PostgreSQLTestCase): ) self.assertEqual( repr(constraint), - "", + "", ) constraint = ExclusionConstraint( name='exclude_overlapping', @@ -303,8 +304,9 @@ class ExclusionConstraintTests(PostgreSQLTestCase): ) self.assertEqual( repr(constraint), - "", + "", ) constraint = ExclusionConstraint( name='exclude_overlapping', @@ -313,8 +315,9 @@ class ExclusionConstraintTests(PostgreSQLTestCase): ) self.assertEqual( repr(constraint), - "", + "", ) constraint = ExclusionConstraint( name='exclude_overlapping', @@ -323,8 +326,9 @@ class ExclusionConstraintTests(PostgreSQLTestCase): ) self.assertEqual( repr(constraint), - "", + "", ) def test_eq(self):