diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-07-19 10:00:13 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-07-19 10:00:13 -0400 |
commit | 41aead96cdfd581c053a395992e1a3cf0b6a5572 (patch) | |
tree | fceafc25ac4ae48d181f5d34a45d5b49149e381e | |
parent | 18a078654da286c0adf51a20a21398e357ed12ed (diff) | |
download | sqlalchemy-41aead96cdfd581c053a395992e1a3cf0b6a5572.tar.gz |
- Fixed potential issue where a custom subclass
of :class:`.FunctionElement` or other column element that incorrectly
states 'None' or any other invalid object as the ``.type``
attribute will report this exception instead of recursion overflow.
fixes #3485
-rw-r--r-- | doc/build/changelog/changelog_10.rst | 9 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/elements.py | 9 | ||||
-rw-r--r-- | test/sql/test_functions.py | 16 |
3 files changed, 31 insertions, 3 deletions
diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst index 48626a525..c4d9ab448 100644 --- a/doc/build/changelog/changelog_10.rst +++ b/doc/build/changelog/changelog_10.rst @@ -20,6 +20,15 @@ .. change:: :tags: bug, sql + :tickets: 3485 + + Fixed potential issue where a custom subclass + of :class:`.FunctionElement` or other column element that incorrectly + states 'None' or any other invalid object as the ``.type`` + attribute will report this exception instead of recursion overflow. + + .. change:: + :tags: bug, sql :pullreq: github:188 Fixed bug where the modulus SQL operator wouldn't work in reverse diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 27ecce2b0..41dfcf147 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -715,7 +715,14 @@ class ColumnElement(operators.ColumnOperators, ClauseElement): @util.memoized_property def comparator(self): - return self.type.comparator_factory(self) + try: + comparator_factory = self.type.comparator_factory + except AttributeError: + raise TypeError( + "Object %r associated with '.type' attribute " + "is not a TypeEngine class or object" % self.type) + else: + return comparator_factory(self) def __getattr__(self, key): try: diff --git a/test/sql/test_functions.py b/test/sql/test_functions.py index ec8d9b5c0..ccc9b2dcd 100644 --- a/test/sql/test_functions.py +++ b/test/sql/test_functions.py @@ -9,12 +9,12 @@ from sqlalchemy.sql.compiler import BIND_TEMPLATES from sqlalchemy.testing.engines import all_dialects from sqlalchemy import types as sqltypes from sqlalchemy.sql import functions -from sqlalchemy.sql.functions import GenericFunction +from sqlalchemy.sql.functions import GenericFunction, FunctionElement import decimal from sqlalchemy import testing from sqlalchemy.testing import fixtures, AssertsCompiledSQL, engines from sqlalchemy.dialects import sqlite, postgresql, mysql, oracle - +from sqlalchemy.testing import assert_raises_message table1 = table('mytable', column('myid', Integer), @@ -477,6 +477,18 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): "AS anon_1 FROM mytable" ) + def test_incorrect_none_type(self): + class MissingType(FunctionElement): + name = 'mt' + type = None + + assert_raises_message( + TypeError, + "Object None associated with '.type' attribute is " + "not a TypeEngine class or object", + MissingType().compile + ) + class ExecuteTest(fixtures.TestBase): |