From 65da4e99547042f9eed63578b9a804d9503c1854 Mon Sep 17 00:00:00 2001 From: Kyle Spengler Date: Mon, 18 Aug 2025 17:33:22 +0000 Subject: [PATCH] utils: add maybe_single + unit tests --- src/supabase/src/supabase/_utils.py | 18 ++++++++++++++++++ src/supabase/tests/test_utils_maybe_single.py | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/supabase/src/supabase/_utils.py create mode 100644 src/supabase/tests/test_utils_maybe_single.py diff --git a/src/supabase/src/supabase/_utils.py b/src/supabase/src/supabase/_utils.py new file mode 100644 index 00000000..f6e574cf --- /dev/null +++ b/src/supabase/src/supabase/_utils.py @@ -0,0 +1,18 @@ +from __future__ import annotations +from typing import Iterable, TypeVar, Union + +T = TypeVar("T") + +def maybe_single(value: Union[T, Iterable[T], None]) -> Union[T, list[T], None]: + """ + If value is a 1-length list/tuple, unwrap to the single item. + If it's a longer tuple, return a list. If it's None or a scalar, return as-is. + """ + if value is None: + return None + if isinstance(value, (list, tuple)): + if len(value) == 1: + return value[0] + # normalize tuples to list for consistency + return list(value) if isinstance(value, tuple) else value + return value diff --git a/src/supabase/tests/test_utils_maybe_single.py b/src/supabase/tests/test_utils_maybe_single.py new file mode 100644 index 00000000..70b02b32 --- /dev/null +++ b/src/supabase/tests/test_utils_maybe_single.py @@ -0,0 +1,18 @@ +from supabase._utils import maybe_single + +def test_none_passthrough(): + assert maybe_single(None) is None + +def test_scalar_passthrough(): + assert maybe_single(5) == 5 + assert maybe_single("x") == "x" + +def test_singleton_list_unwraps(): + assert maybe_single([42]) == 42 + +def test_multi_item_list_stays_list(): + assert maybe_single([1, 2]) == [1, 2] + +def test_tuple_behaviour(): + assert maybe_single((7,)) == 7 + assert maybe_single((7, 8)) == [7, 8]