diff --git a/voluptuous/schema_builder.py b/voluptuous/schema_builder.py index 3673e86..5f28d90 100644 --- a/voluptuous/schema_builder.py +++ b/voluptuous/schema_builder.py @@ -828,6 +828,10 @@ def _compile_scalar(schema): if inspect.isclass(schema): def validate_instance(path, data): + # bool is a subclass of int; reject so True/False are not valid ints + if schema is int and isinstance(data, bool): + msg = 'expected %s' % schema.__name__ + raise er.TypeInvalid(msg, path) if isinstance(data, schema): return data else: diff --git a/voluptuous/tests/tests.py b/voluptuous/tests/tests.py index 0608548..98220c7 100644 --- a/voluptuous/tests/tests.py +++ b/voluptuous/tests/tests.py @@ -2375,3 +2375,20 @@ def test_complex_required_keys_with_specific_value_validation(): error_msg = str(exc_info.value) assert "required" not in error_msg.lower() # No "required field missing" error assert "value must be at most 100" in error_msg # Range validation error + + +def test_boolean_is_not_an_integer(): + """bool is a subclass of int; Schema(int) must still reject True/False.""" + schema = Schema(int) + with pytest.raises(MultipleInvalid): + schema(True) + with pytest.raises(MultipleInvalid): + schema(False) + assert schema(0) == 0 + assert schema(1) == 1 + with pytest.raises(MultipleInvalid): + Schema({'age': int})({'age': True}) + with pytest.raises(MultipleInvalid): + Schema(ExactSequence([int, int]))([True, False]) + assert Schema(bool)(True) is True + assert Schema(bool)(False) is False