From: Mike Bayer Date: Sat, 22 Aug 2015 20:01:23 +0000 (-0400) Subject: - repair the inspection hook in sqltypes to not be fooled X-Git-Tag: rel_1_1_0b1~84^2~70^2~132 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=03e47a8255476d9ed50c5aec73e6c272761d67eb;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - repair the inspection hook in sqltypes to not be fooled by mock and other __getattr__ impostors --- diff --git a/lib/sqlalchemy/orm/state.py b/lib/sqlalchemy/orm/state.py index 3cbeed0b4e..6c9f07bffa 100644 --- a/lib/sqlalchemy/orm/state.py +++ b/lib/sqlalchemy/orm/state.py @@ -14,6 +14,7 @@ defines a large part of the ORM's interactivity. import weakref from .. import util +from .. import inspection from . import exc as orm_exc, interfaces from .path_registry import PathRegistry from .base import PASSIVE_NO_RESULT, SQL_OK, NEVER_SET, ATTR_WAS_SET, \ @@ -21,6 +22,7 @@ from .base import PASSIVE_NO_RESULT, SQL_OK, NEVER_SET, ATTR_WAS_SET, \ from . import base +@inspection._self_inspects class InstanceState(interfaces.InspectionAttr): """tracks state information at the instance level. diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index b5c575143b..92a0628da0 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -1745,7 +1745,12 @@ def _resolve_value_to_type(value): # use inspect() to detect SQLAlchemy built-in # objects. insp = inspection.inspect(value, False) - if insp is not None: + if ( + insp is not None and + # foil mock.Mock() and other impostors by ensuring + # the inspection target itself self-inspects + insp.__class__ in inspection._registrars + ): raise exc.ArgumentError( "Object %r is not legal as a SQL literal value" % value) return NULLTYPE diff --git a/test/sql/test_types.py b/test/sql/test_types.py index 90fac97c21..d562c83ce6 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -26,7 +26,7 @@ from sqlalchemy.testing import AssertsCompiledSQL, AssertsExecutionResults, \ from sqlalchemy.testing.util import picklers from sqlalchemy.testing.util import round_decimal from sqlalchemy.testing import fixtures - +from sqlalchemy.testing import mock class AdaptTest(fixtures.TestBase): @@ -1668,6 +1668,14 @@ class ExpressionTest( types.NULLTYPE ) + def test_detect_coercion_not_fooled_by_mock(self): + m1 = mock.Mock() + is_( + bindparam('x', m1).type, + types.NULLTYPE + ) + + class CompileTest(fixtures.TestBase, AssertsCompiledSQL): __dialect__ = 'default'