summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-11-18 10:38:02 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2012-11-18 10:38:02 -0500
commit1e29a74bd62c6c872819388e430901c35f84f07c (patch)
tree98fedf95477a04dd2adf570aba965e248935570d
parent0f56aa56c5de13ab14bd8e8d03b6e785c39a5bf0 (diff)
downloadsqlalchemy-1e29a74bd62c6c872819388e430901c35f84f07c.tar.gz
Fixed a gotcha where inadvertently calling list() on a
:class:`.ColumnElement` would go into an endless loop, if :meth:`.ColumnOperators.__getitem__` were implemented. A new NotImplementedError is emitted via ``__iter__()``.
-rw-r--r--doc/build/changelog/changelog_08.rst12
-rw-r--r--lib/sqlalchemy/sql/operators.py5
-rw-r--r--test/dialect/test_postgresql.py3
-rw-r--r--test/sql/test_operators.py12
4 files changed, 29 insertions, 3 deletions
diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst
index 1fd8719f2..15206134e 100644
--- a/doc/build/changelog/changelog_08.rst
+++ b/doc/build/changelog/changelog_08.rst
@@ -7,13 +7,21 @@
:version: 0.8.0b2
.. change::
- :tags: orm, extensions
+ :tags: sql, bug
+
+ Fixed a gotcha where inadvertently calling list() on a
+ :class:`.ColumnElement` would go into an endless loop, if
+ :meth:`.ColumnOperators.__getitem__` were implemented.
+ A new NotImplementedError is emitted via ``__iter__()``.
+
+ .. change::
+ :tags: orm, extensions, feature
The :mod:`sqlalchemy.ext.mutable` extension now includes the
example :class:`.MutableDict` class as part of the extension.
.. change::
- :tags: postgresql, hstore
+ :tags: postgresql, feature
:tickets: 2606
:class:`.HSTORE` is now available in the Postgresql dialect.
diff --git a/lib/sqlalchemy/sql/operators.py b/lib/sqlalchemy/sql/operators.py
index 88f56e5ec..7513c0b82 100644
--- a/lib/sqlalchemy/sql/operators.py
+++ b/lib/sqlalchemy/sql/operators.py
@@ -310,6 +310,11 @@ class ColumnOperators(Operators):
"""
return self.operate(neg)
+ def __iter__(self):
+ """Block calls to list() from calling __getitem__() endlessly."""
+
+ raise NotImplementedError("Class %s is not iterable" % self.__class__)
+
def __getitem__(self, index):
"""Implement the [] operator.
diff --git a/test/dialect/test_postgresql.py b/test/dialect/test_postgresql.py
index 40d8d0c79..ab3f54a66 100644
--- a/test/dialect/test_postgresql.py
+++ b/test/dialect/test_postgresql.py
@@ -2941,7 +2941,8 @@ class HStoreTest(fixtures.TestBase):
def test_cols_keys(self):
self._test_cols(
- self.hashcol.keys(),
+ # hide from 2to3
+ getattr(self.hashcol, 'keys')(),
"akeys(test_table.hash) AS akeys_1",
True
)
diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py
index eb2885658..9da9d94c3 100644
--- a/test/sql/test_operators.py
+++ b/test/sql/test_operators.py
@@ -325,6 +325,18 @@ class ExtensionOperatorTest(fixtures.TestBase, testing.AssertsCompiledSQL):
"x -> :x_1"
)
+ def test_no_endless_list_call(self):
+ class MyType(UserDefinedType):
+ class comparator_factory(UserDefinedType.Comparator):
+ def __getitem__(self, index):
+ return self.op("->")(index)
+
+ assert_raises_message(
+ NotImplementedError,
+ "Class <class 'sqlalchemy.schema.Column'> is not iterable",
+ list, Column('x', MyType())
+ )
+
def test_lshift(self):
class MyType(UserDefinedType):
class comparator_factory(UserDefinedType.Comparator):