From 925664b01f5037ca11c06bf0b416b807e9b4034d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Ram=C3=ADrez=20Mondrag=C3=B3n?= <16805946+edgarrmondragon@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:02:53 -0600 Subject: [PATCH] fix: JSON schema union types are no longer conformed into boolean values (#2723) * fix: JSON schema union types are no longer conformed into boolean values * Do conform the most obvious cases * Make sure it is tested * Test one more case --- singer_sdk/helpers/_typing.py | 13 ++++++++++++- tests/core/test_typing.py | 9 +++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/singer_sdk/helpers/_typing.py b/singer_sdk/helpers/_typing.py index 1e7370fd9..b02ecb512 100644 --- a/singer_sdk/helpers/_typing.py +++ b/singer_sdk/helpers/_typing.py @@ -279,6 +279,17 @@ def is_boolean_type(property_schema: dict) -> bool | None: return False +def _is_exclusive_boolean_type(property_schema: dict) -> bool: + if "type" not in property_schema: + return False + + return ( + property_schema["type"] == "boolean" + or property_schema["type"] == ["boolean"] + or set(property_schema["type"]) == {"boolean", "null"} + ) + + def is_integer_type(property_schema: dict) -> bool | None: """Return true if the JSON Schema type is an integer or None if detection fails.""" if "anyOf" not in property_schema and "type" not in property_schema: @@ -523,6 +534,6 @@ def _conform_primitive_property( # noqa: PLR0911 if isinstance(elem, bytes): # for BIT value, treat 0 as False and anything else as True return elem != b"\x00" if is_boolean_type(property_schema) else elem.hex() - if is_boolean_type(property_schema): + if _is_exclusive_boolean_type(property_schema): return None if elem is None else elem != 0 return elem diff --git a/tests/core/test_typing.py b/tests/core/test_typing.py index 5043c75e1..25d9c68df 100644 --- a/tests/core/test_typing.py +++ b/tests/core/test_typing.py @@ -313,7 +313,16 @@ def test_conform_primitives(): assert _conform_primitive_property(None, {"type": "boolean"}) is None assert _conform_primitive_property(0, {"type": "boolean"}) is False + assert ( + _conform_primitive_property( + 0, {"anyOf": [{"type": "boolean"}, {"type": "integer"}]} + ) + == 0 + ) + assert _conform_primitive_property(0, {"type": ["boolean", "integer"]}) == 0 assert _conform_primitive_property(1, {"type": "boolean"}) is True + assert _conform_primitive_property(1, {"type": ["boolean", "null"]}) is True + assert _conform_primitive_property(1, {"type": ["boolean"]}) is True @pytest.mark.parametrize(