Fixed #32458 -- Made __repr__() for Index and BaseConstraint subclasses more consistent.
This commit is contained in:
parent
7c18b22e2f
commit
87acbf0631
|
@ -155,12 +155,13 @@ class ExclusionConstraint(BaseConstraint):
|
||||||
return super().__eq__(other)
|
return super().__eq__(other)
|
||||||
|
|
||||||
def __repr__(self):
|
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.__class__.__qualname__,
|
||||||
self.index_type,
|
repr(self.index_type),
|
||||||
self.expressions,
|
repr(self.expressions),
|
||||||
'' if self.condition is None else ', condition=%s' % self.condition,
|
repr(self.name),
|
||||||
'' if self.deferrable is None else ', deferrable=%s' % self.deferrable,
|
'' if self.condition is None else ' condition=%s' % self.condition,
|
||||||
'' if not self.include else ', include=%s' % repr(self.include),
|
'' if self.deferrable is None else ' deferrable=%s' % self.deferrable,
|
||||||
'' if not self.opclasses else ', opclasses=%s' % repr(self.opclasses),
|
'' if not self.include else ' include=%s' % repr(self.include),
|
||||||
|
'' if not self.opclasses else ' opclasses=%s' % repr(self.opclasses),
|
||||||
)
|
)
|
||||||
|
|
|
@ -58,7 +58,11 @@ class CheckConstraint(BaseConstraint):
|
||||||
return schema_editor._delete_check_sql(model, self.name)
|
return schema_editor._delete_check_sql(model, self.name)
|
||||||
|
|
||||||
def __repr__(self):
|
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):
|
def __eq__(self, other):
|
||||||
if isinstance(other, CheckConstraint):
|
if isinstance(other, CheckConstraint):
|
||||||
|
@ -161,8 +165,10 @@ class UniqueConstraint(BaseConstraint):
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: fields=%r name=%r%s%s%s%s>' % (
|
return '<%s: fields=%s name=%s%s%s%s%s>' % (
|
||||||
self.__class__.__name__, self.fields, self.name,
|
self.__class__.__qualname__,
|
||||||
|
repr(self.fields),
|
||||||
|
repr(self.name),
|
||||||
'' if self.condition is None else ' condition=%s' % self.condition,
|
'' if self.condition is None else ' condition=%s' % self.condition,
|
||||||
'' if self.deferrable is None else ' deferrable=%s' % self.deferrable,
|
'' if self.deferrable is None else ' deferrable=%s' % self.deferrable,
|
||||||
'' if not self.include else ' include=%s' % repr(self.include),
|
'' if not self.include else ' include=%s' % repr(self.include),
|
||||||
|
|
|
@ -169,15 +169,17 @@ class Index:
|
||||||
self.name = 'D%s' % self.name[1:]
|
self.name = 'D%s' % self.name[1:]
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s:%s%s%s%s%s>' % (
|
return '<%s:%s%s%s%s%s%s%s>' % (
|
||||||
self.__class__.__name__,
|
self.__class__.__qualname__,
|
||||||
'' if not self.fields else " fields='%s'" % ', '.join(self.fields),
|
'' if not self.fields else ' fields=%s' % repr(self.fields),
|
||||||
'' if not self.expressions else " expressions='%s'" % ', '.join([
|
'' if not self.expressions else ' expressions=%s' % repr(self.expressions),
|
||||||
str(expression) for expression in 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 self.condition is None else ' condition=%s' % self.condition,
|
||||||
'' if not self.include else " include='%s'" % ', '.join(self.include),
|
'' if not self.include else ' include=%s' % repr(self.include),
|
||||||
'' if not self.opclasses else " opclasses='%s'" % ', '.join(self.opclasses),
|
'' if not self.opclasses else ' opclasses=%s' % repr(self.opclasses),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
|
|
|
@ -58,12 +58,14 @@ class CheckConstraintTests(TestCase):
|
||||||
self.assertNotEqual(models.CheckConstraint(check=check1, name='price'), 1)
|
self.assertNotEqual(models.CheckConstraint(check=check1, name='price'), 1)
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
check = models.Q(price__gt=models.F('discounted_price'))
|
constraint = models.CheckConstraint(
|
||||||
name = 'price_gt_discounted_price'
|
check=models.Q(price__gt=models.F('discounted_price')),
|
||||||
constraint = models.CheckConstraint(check=check, name=name)
|
name='price_gt_discounted_price',
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
repr(constraint),
|
repr(constraint),
|
||||||
"<CheckConstraint: check='{}' name='{}'>".format(check, name),
|
"<CheckConstraint: check=(AND: ('price__gt', F(discounted_price))) "
|
||||||
|
"name='price_gt_discounted_price'>",
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_invalid_check_types(self):
|
def test_invalid_check_types(self):
|
||||||
|
|
|
@ -1840,7 +1840,7 @@ class OperationTests(OperationTestBase):
|
||||||
project_state = self.set_up_test_model("test_adin")
|
project_state = self.set_up_test_model("test_adin")
|
||||||
msg = (
|
msg = (
|
||||||
"Indexes passed to AddIndex operations require a name argument. "
|
"Indexes passed to AddIndex operations require a name argument. "
|
||||||
"<Index: fields='pink'> doesn't have one."
|
"<Index: fields=['pink']> doesn't have one."
|
||||||
)
|
)
|
||||||
with self.assertRaisesMessage(ValueError, msg):
|
with self.assertRaisesMessage(ValueError, msg):
|
||||||
migrations.AddIndex("Pony", models.Index(fields=["pink"]))
|
migrations.AddIndex("Pony", models.Index(fields=["pink"]))
|
||||||
|
|
|
@ -1046,7 +1046,10 @@ class ModelStateTests(SimpleTestCase):
|
||||||
def test_sanity_index_name(self):
|
def test_sanity_index_name(self):
|
||||||
field = models.IntegerField()
|
field = models.IntegerField()
|
||||||
options = {'indexes': [models.Index(fields=['field'])]}
|
options = {'indexes': [models.Index(fields=['field'])]}
|
||||||
msg = "Indexes passed to ModelState require a name attribute. <Index: fields='field'> doesn't have one."
|
msg = (
|
||||||
|
"Indexes passed to ModelState require a name attribute. <Index: "
|
||||||
|
"fields=['field']> doesn't have one."
|
||||||
|
)
|
||||||
with self.assertRaisesMessage(ValueError, msg):
|
with self.assertRaisesMessage(ValueError, msg):
|
||||||
ModelState('app', 'Model', [('field', field)], options=options)
|
ModelState('app', 'Model', [('field', field)], options=options)
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ class SimpleIndexesTests(SimpleTestCase):
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
index = models.Index(fields=['title'])
|
index = models.Index(fields=['title'])
|
||||||
|
named_index = models.Index(fields=['title'], name='title_idx')
|
||||||
multi_col_index = models.Index(fields=['title', 'author'])
|
multi_col_index = models.Index(fields=['title', 'author'])
|
||||||
partial_index = models.Index(fields=['title'], name='long_books_idx', condition=models.Q(pages__gt=400))
|
partial_index = models.Index(fields=['title'], name='long_books_idx', condition=models.Q(pages__gt=400))
|
||||||
covering_index = models.Index(
|
covering_index = models.Index(
|
||||||
|
@ -28,20 +29,43 @@ class SimpleIndexesTests(SimpleTestCase):
|
||||||
name='opclasses_idx',
|
name='opclasses_idx',
|
||||||
opclasses=['varchar_pattern_ops', 'text_pattern_ops'],
|
opclasses=['varchar_pattern_ops', 'text_pattern_ops'],
|
||||||
)
|
)
|
||||||
func_index = models.Index(Lower('title'), name='book_func_idx')
|
func_index = models.Index(Lower('title'), 'subtitle', name='book_func_idx')
|
||||||
self.assertEqual(repr(index), "<Index: fields='title'>")
|
tablespace_index = models.Index(
|
||||||
self.assertEqual(repr(multi_col_index), "<Index: fields='title, author'>")
|
fields=['title'],
|
||||||
self.assertEqual(repr(partial_index), "<Index: fields='title' condition=(AND: ('pages__gt', 400))>")
|
db_tablespace='idx_tbls',
|
||||||
|
name='book_tablespace_idx',
|
||||||
|
)
|
||||||
|
self.assertEqual(repr(index), "<Index: fields=['title']>")
|
||||||
|
self.assertEqual(
|
||||||
|
repr(named_index),
|
||||||
|
"<Index: fields=['title'] name='title_idx'>",
|
||||||
|
)
|
||||||
|
self.assertEqual(repr(multi_col_index), "<Index: fields=['title', 'author']>")
|
||||||
|
self.assertEqual(
|
||||||
|
repr(partial_index),
|
||||||
|
"<Index: fields=['title'] name='long_books_idx' "
|
||||||
|
"condition=(AND: ('pages__gt', 400))>",
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
repr(covering_index),
|
repr(covering_index),
|
||||||
"<Index: fields='title' include='author, pages'>",
|
"<Index: fields=['title'] name='include_idx' "
|
||||||
|
"include=('author', 'pages')>",
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
repr(opclasses_index),
|
repr(opclasses_index),
|
||||||
"<Index: fields='headline, body' "
|
"<Index: fields=['headline', 'body'] name='opclasses_idx' "
|
||||||
"opclasses='varchar_pattern_ops, text_pattern_ops'>",
|
"opclasses=['varchar_pattern_ops', 'text_pattern_ops']>",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
repr(func_index),
|
||||||
|
"<Index: expressions=(Lower(F(title)), F(subtitle)) "
|
||||||
|
"name='book_func_idx'>",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
repr(tablespace_index),
|
||||||
|
"<Index: fields=['title'] name='book_tablespace_idx' "
|
||||||
|
"db_tablespace='idx_tbls'>",
|
||||||
)
|
)
|
||||||
self.assertEqual(repr(func_index), "<Index: expressions='Lower(F(title))'>")
|
|
||||||
|
|
||||||
def test_eq(self):
|
def test_eq(self):
|
||||||
index = models.Index(fields=['title'])
|
index = models.Index(fields=['title'])
|
||||||
|
|
|
@ -282,8 +282,8 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
repr(constraint),
|
repr(constraint),
|
||||||
"<ExclusionConstraint: index_type=GIST, expressions=["
|
"<ExclusionConstraint: index_type='GIST' expressions=["
|
||||||
"(F(datespan), '&&'), (F(room), '=')]>",
|
"(F(datespan), '&&'), (F(room), '=')] name='exclude_overlapping'>",
|
||||||
)
|
)
|
||||||
constraint = ExclusionConstraint(
|
constraint = ExclusionConstraint(
|
||||||
name='exclude_overlapping',
|
name='exclude_overlapping',
|
||||||
|
@ -293,8 +293,9 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
repr(constraint),
|
repr(constraint),
|
||||||
"<ExclusionConstraint: index_type=SPGiST, expressions=["
|
"<ExclusionConstraint: index_type='SPGiST' expressions=["
|
||||||
"(F(datespan), '-|-')], condition=(AND: ('cancelled', False))>",
|
"(F(datespan), '-|-')] name='exclude_overlapping' "
|
||||||
|
"condition=(AND: ('cancelled', False))>",
|
||||||
)
|
)
|
||||||
constraint = ExclusionConstraint(
|
constraint = ExclusionConstraint(
|
||||||
name='exclude_overlapping',
|
name='exclude_overlapping',
|
||||||
|
@ -303,8 +304,9 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
repr(constraint),
|
repr(constraint),
|
||||||
"<ExclusionConstraint: index_type=GIST, expressions=["
|
"<ExclusionConstraint: index_type='GIST' expressions=["
|
||||||
"(F(datespan), '-|-')], deferrable=Deferrable.IMMEDIATE>",
|
"(F(datespan), '-|-')] name='exclude_overlapping' "
|
||||||
|
"deferrable=Deferrable.IMMEDIATE>",
|
||||||
)
|
)
|
||||||
constraint = ExclusionConstraint(
|
constraint = ExclusionConstraint(
|
||||||
name='exclude_overlapping',
|
name='exclude_overlapping',
|
||||||
|
@ -313,8 +315,9 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
repr(constraint),
|
repr(constraint),
|
||||||
"<ExclusionConstraint: index_type=GIST, expressions=["
|
"<ExclusionConstraint: index_type='GIST' expressions=["
|
||||||
"(F(datespan), '-|-')], include=('cancelled', 'room')>",
|
"(F(datespan), '-|-')] name='exclude_overlapping' "
|
||||||
|
"include=('cancelled', 'room')>",
|
||||||
)
|
)
|
||||||
constraint = ExclusionConstraint(
|
constraint = ExclusionConstraint(
|
||||||
name='exclude_overlapping',
|
name='exclude_overlapping',
|
||||||
|
@ -323,8 +326,9 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
repr(constraint),
|
repr(constraint),
|
||||||
"<ExclusionConstraint: index_type=GIST, expressions=["
|
"<ExclusionConstraint: index_type='GIST' expressions=["
|
||||||
"(F(datespan), '-|-')], opclasses=['range_ops']>",
|
"(F(datespan), '-|-')] name='exclude_overlapping' "
|
||||||
|
"opclasses=['range_ops']>",
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_eq(self):
|
def test_eq(self):
|
||||||
|
|
Loading…
Reference in New Issue