From 2904fc7cb42ab2fab5d9941a9440a5e1c2fdb888 Mon Sep 17 00:00:00 2001 From: Pitchfork-and-Torch <297513015+Pitchfork-and-Torch@users.noreply.github.com> Date: Fri, 18 Sep 2026 04:04:50 +0000 Subject: [PATCH] Reject bool for Schema(int) type checks bool is a subclass of int, so Schema(int) accepted True/False and treated them as 0/1. Reject booleans explicitly so integer fields cannot be satisfied by a bool. Schema(bool) is unchanged. --- voluptuous/schema_builder.py | 4 ++++ voluptuous/tests/tests.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) 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