From df63aa87480e7ca37a7087efa27a774f4624641d Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 9 Oct 2014 17:20:30 -0400 Subject: [PATCH] - Fixed bug where a fair number of SQL elements within the sql package would fail to ``__repr__()`` successfully, due to a missing ``description`` attribute that would then invoke a recursion overflow when an internal AttributeError would then re-invoke ``__repr__()``. fixes #3195 --- doc/build/changelog/changelog_09.rst | 11 +++++++++++ lib/sqlalchemy/sql/elements.py | 3 ++- test/sql/test_selectable.py | 24 ++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst index 692c6e3925..e2b893d07f 100644 --- a/doc/build/changelog/changelog_09.rst +++ b/doc/build/changelog/changelog_09.rst @@ -13,6 +13,17 @@ .. changelog:: :version: 0.9.8 + .. change:: + :tags: bug, sql + :versions: 1.0.0 + :tickets: 3195 + + Fixed bug where a fair number of SQL elements within + the sql package would fail to ``__repr__()`` successfully, + due to a missing ``description`` attribute that would then invoke + a recursion overflow when an internal AttributeError would then + re-invoke ``__repr__()``. + .. change:: :tags: bug, declarative, orm :versions: 1.0.0 diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 8cae831694..6623db2c8a 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -227,6 +227,7 @@ class ClauseElement(Visitable): is_selectable = False is_clause_element = True + description = None _order_by_label_element = None _is_from_container = False @@ -539,7 +540,7 @@ class ClauseElement(Visitable): __nonzero__ = __bool__ def __repr__(self): - friendly = getattr(self, 'description', None) + friendly = self.description if friendly is None: return object.__repr__(self) else: diff --git a/test/sql/test_selectable.py b/test/sql/test_selectable.py index c5736b26f4..45f9fa2481 100644 --- a/test/sql/test_selectable.py +++ b/test/sql/test_selectable.py @@ -5,6 +5,7 @@ from sqlalchemy.testing import eq_, assert_raises, \ from sqlalchemy import * from sqlalchemy.testing import fixtures, AssertsCompiledSQL, \ AssertsExecutionResults +from sqlalchemy.sql import elements from sqlalchemy import testing from sqlalchemy.sql import util as sql_util, visitors, expression from sqlalchemy import exc @@ -1927,6 +1928,29 @@ class AnnotationsTest(fixtures.TestBase): assert (c2 == 5).left._annotations == {"foo": "bar", "bat": "hoho"} +class ReprTest(fixtures.TestBase): + def test_ensure_repr_elements(self): + for obj in [ + elements.Cast(1, 2), + elements.TypeClause(String()), + elements.ColumnClause('x'), + elements.BindParameter('q'), + elements.Null(), + elements.True_(), + elements.False_(), + elements.ClauseList(), + elements.BooleanClauseList.and_(), + elements.Tuple(), + elements.Case([]), + elements.Extract('foo', column('x')), + elements.UnaryExpression(column('x')), + elements.Grouping(column('x')), + elements.Over(func.foo()), + elements.Label('q', column('x')), + ]: + repr(obj) + + class WithLabelsTest(fixtures.TestBase): def _assert_labels_warning(self, s): -- 2.47.3