]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- repair the inspection hook in sqltypes to not be fooled
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 22 Aug 2015 20:01:23 +0000 (16:01 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 22 Aug 2015 20:01:23 +0000 (16:01 -0400)
by mock and other __getattr__ impostors

lib/sqlalchemy/orm/state.py
lib/sqlalchemy/sql/sqltypes.py
test/sql/test_types.py

index 3cbeed0b4eb9714bf288183b6ad80042a6e2e409..6c9f07bffa283c559b6772e66e0a45f813687b93 100644 (file)
@@ -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.
 
index b5c575143bff8ae70a3fa05d04fd595b01e8cc52..92a0628da0ecf727cf4eea33d442c103170781f9 100644 (file)
@@ -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
index 90fac97c21b449a23ba7e4c814dd4c3c61eed323..d562c83ce6f7c9123f7510a7056a4a0e2a8e9616 100644 (file)
@@ -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'