summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2017-10-11 17:56:14 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2017-10-12 13:39:06 -0400
commitc63658973c95996b73251e0953cf4c598cdb262b (patch)
tree1d9aba0b27f2f096369b95cf0a6dbb95f87825ac /test
parent3306d4d34d0f78bdda6f85a0a3be81beb2850676 (diff)
downloadsqlalchemy-c63658973c95996b73251e0953cf4c598cdb262b.tar.gz
Disallow all ambiguous boolean values for Boolean
In release 1.1, the :class:`.Boolean` type was broken in that boolean coercion via ``bool()`` would occur for backends that did not feature "native boolean", but would not occur for native boolean backends, meaning the string ``"0"`` now behaved inconsistently. After a poll, a consensus was reached that non-boolean values should be raising an error, especially in the ambiguous case of string ``"0"``; so the :class:`.Boolean` datatype will now raise ``ValueError`` if an incoming value is not within the range ``None, True, False, 1, 0``. Change-Id: If70c4f79c266f0dd1a0306c0ffe7acb9c66c4cc3 Fixes: #4102
Diffstat (limited to 'test')
-rw-r--r--test/engine/test_processors.py37
-rw-r--r--test/sql/test_types.py172
2 files changed, 167 insertions, 42 deletions
diff --git a/test/engine/test_processors.py b/test/engine/test_processors.py
index 83b5a7948..9f0055e05 100644
--- a/test/engine/test_processors.py
+++ b/test/engine/test_processors.py
@@ -34,43 +34,6 @@ class _BooleanProcessorTest(fixtures.TestBase):
)
-class PyBooleanProcessorTest(_BooleanProcessorTest):
- @classmethod
- def setup_class(cls):
- from sqlalchemy import processors
- cls.module = type(
- "util", (object,),
- dict(
- (k, staticmethod(v))
- for k, v in list(processors.py_fallback().items())
- )
- )
-
- def test_bool_to_int_false(self):
- from sqlalchemy import processors
- eq_(processors.boolean_to_int(False), 0)
-
- def test_bool_to_int_true(self):
- from sqlalchemy import processors
- eq_(processors.boolean_to_int(True), 1)
-
- def test_bool_to_int_positive_int(self):
- from sqlalchemy import processors
- eq_(processors.boolean_to_int(5), 1)
-
- def test_bool_to_int_negative_int(self):
- from sqlalchemy import processors
- eq_(processors.boolean_to_int(-10), 1)
-
- def test_bool_to_int_zero(self):
- from sqlalchemy import processors
- eq_(processors.boolean_to_int(0), 0)
-
- def test_bool_to_int_one(self):
- from sqlalchemy import processors
- eq_(processors.boolean_to_int(1), 1)
-
-
class CBooleanProcessorTest(_BooleanProcessorTest):
__requires__ = ('cextensions',)
diff --git a/test/sql/test_types.py b/test/sql/test_types.py
index f9b5b4945..dd799de1b 100644
--- a/test/sql/test_types.py
+++ b/test/sql/test_types.py
@@ -2621,15 +2621,14 @@ class BooleanTest(
def test_nonnative_processor_coerces_to_onezero(self):
boolean_table = self.tables.boolean_table
with testing.db.connect() as conn:
- conn.execute(
+ assert_raises_message(
+ exc.StatementError,
+ "Value 5 is not None, True, or False",
+ conn.execute,
boolean_table.insert(),
{"id": 1, "unconstrained_value": 5}
)
- eq_(
- conn.scalar("select unconstrained_value from boolean_table"),
- 1
- )
@testing.skip_if(lambda: testing.db.dialect.supports_native_boolean)
def test_nonnative_processor_coerces_integer_to_boolean(self):
@@ -2650,6 +2649,169 @@ class BooleanTest(
True
)
+ def test_bind_processor_coercion_native_true(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=True))
+ is_(proc(True), True)
+
+ def test_bind_processor_coercion_native_false(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=True))
+ is_(proc(False), False)
+
+ def test_bind_processor_coercion_native_none(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=True))
+ is_(proc(None), None)
+
+ def test_bind_processor_coercion_native_0(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=True))
+ is_(proc(0), False)
+
+ def test_bind_processor_coercion_native_1(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=True))
+ is_(proc(1), True)
+
+ def test_bind_processor_coercion_native_str(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=True))
+ assert_raises_message(
+ TypeError,
+ "Not a boolean value: 'foo'",
+ proc, "foo"
+ )
+
+ def test_bind_processor_coercion_native_int_out_of_range(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=True))
+ assert_raises_message(
+ ValueError,
+ "Value 15 is not None, True, or False",
+ proc, 15
+ )
+
+ def test_bind_processor_coercion_nonnative_true(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=False))
+ eq_(proc(True), 1)
+
+ def test_bind_processor_coercion_nonnative_false(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=False))
+ eq_(proc(False), 0)
+
+ def test_bind_processor_coercion_nonnative_none(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=False))
+ is_(proc(None), None)
+
+ def test_bind_processor_coercion_nonnative_0(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=False))
+ eq_(proc(0), 0)
+
+ def test_bind_processor_coercion_nonnative_1(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=False))
+ eq_(proc(1), 1)
+
+ def test_bind_processor_coercion_nonnative_str(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=False))
+ assert_raises_message(
+ TypeError,
+ "Not a boolean value: 'foo'",
+ proc, "foo"
+ )
+
+ def test_bind_processor_coercion_nonnative_int_out_of_range(self):
+ proc = Boolean().bind_processor(
+ mock.Mock(supports_native_boolean=False))
+ assert_raises_message(
+ ValueError,
+ "Value 15 is not None, True, or False",
+ proc, 15
+ )
+
+ def test_literal_processor_coercion_native_true(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=True))
+ eq_(proc(True), "true")
+
+ def test_literal_processor_coercion_native_false(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=True))
+ eq_(proc(False), "false")
+
+ def test_literal_processor_coercion_native_1(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=True))
+ eq_(proc(1), "true")
+
+ def test_literal_processor_coercion_native_0(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=True))
+ eq_(proc(0), "false")
+
+ def test_literal_processor_coercion_native_str(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=True))
+ assert_raises_message(
+ TypeError,
+ "Not a boolean value: 'foo'",
+ proc, "foo"
+ )
+
+ def test_literal_processor_coercion_native_int_out_of_range(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=True))
+ assert_raises_message(
+ ValueError,
+ "Value 15 is not None, True, or False",
+ proc, 15
+ )
+
+ def test_literal_processor_coercion_nonnative_true(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=False))
+ eq_(proc(True), "1")
+
+ def test_literal_processor_coercion_nonnative_false(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=False))
+ eq_(proc(False), "0")
+
+ def test_literal_processor_coercion_nonnative_1(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=False))
+ eq_(proc(1), "1")
+
+ def test_literal_processor_coercion_nonnative_0(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=False))
+ eq_(proc(0), "0")
+
+ def test_literal_processor_coercion_nonnative_str(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=False))
+ assert_raises_message(
+ TypeError,
+ "Not a boolean value: 'foo'",
+ proc, "foo"
+ )
+
+ def test_literal_processor_coercion_native_int_out_of_range(self):
+ proc = Boolean().literal_processor(
+ default.DefaultDialect(supports_native_boolean=True))
+ assert_raises_message(
+ ValueError,
+ "Value 15 is not None, True, or False",
+ proc, 15
+ )
+
+
class PickleTest(fixtures.TestBase):