c56bef871b
Sync docs with Docusaurus / sync (push) Waiting to run
Tests / Check if changed (push) Waiting to run
Tests / format (push) Blocked by required conditions
Tests / check-imports (push) Blocked by required conditions
Tests / Unit / macos-latest (push) Blocked by required conditions
Tests / Unit / ubuntu-latest (push) Blocked by required conditions
Tests / Unit / windows-latest (push) Blocked by required conditions
Tests / mypy (push) Blocked by required conditions
Tests / Integration / ubuntu-latest (push) Blocked by required conditions
Tests / Integration / macos-latest (push) Blocked by required conditions
Tests / Integration / windows-latest (push) Blocked by required conditions
Tests / notify-slack-on-failure (push) Blocked by required conditions
Tests / Mark tests as completed (push) Blocked by required conditions
Docker image release / Build base image (push) Waiting to run
CodeQL / Analyze (python) (push) Has been cancelled
Update Platform Components Table / update (push) Has been cancelled
265 lines
8.2 KiB
Python
265 lines
8.2 KiB
Python
# SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
from typing import Any, Optional, Union
|
|
|
|
import pytest
|
|
|
|
from haystack.core.component.types import GreedyVariadic, Variadic
|
|
from haystack.core.super_component.utils import _is_compatible
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"left,right,expected_common",
|
|
[
|
|
(str, str, str),
|
|
(int, int, int),
|
|
(float, float, float),
|
|
(bool, bool, bool),
|
|
(list, list, list),
|
|
(dict, dict, dict),
|
|
(set, set, set),
|
|
(tuple, tuple, tuple),
|
|
],
|
|
)
|
|
def test_basic_types_compatible(left, right, expected_common):
|
|
"""Test compatible basic Python types."""
|
|
is_compat, common = _is_compatible(left, right)
|
|
assert is_compat
|
|
assert common == expected_common
|
|
|
|
|
|
@pytest.mark.parametrize("left,right", [(str, int), (float, int), (bool, str), (list, dict), (set, tuple)])
|
|
def test_basic_types_incompatible(left, right):
|
|
"""Test incompatible basic Python types."""
|
|
is_compat, common = _is_compatible(left, right)
|
|
assert not is_compat
|
|
assert common is None
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"left,right,expected_common",
|
|
[
|
|
(Any, Any, Any),
|
|
# int
|
|
(int, Any, int),
|
|
(Any, int, int),
|
|
# str
|
|
(Any, str, str),
|
|
(str, Any, str),
|
|
# float
|
|
(float, Any, float),
|
|
(Any, float, float),
|
|
# list
|
|
(list, Any, list),
|
|
(Any, list, list),
|
|
# dict
|
|
(dict, Any, dict),
|
|
(Any, dict, dict),
|
|
],
|
|
)
|
|
def test_any_type(left, right, expected_common):
|
|
"""Test Any type compatibility."""
|
|
is_compat, common = _is_compatible(left, right)
|
|
assert is_compat
|
|
assert common == expected_common
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"left,right,expected_common",
|
|
[
|
|
(int, Union[int, str], int),
|
|
(Union[int, str], int, int),
|
|
(Union[int, str], Union[str, int], Union[int, str]),
|
|
(str, Union[int, str], str),
|
|
(str, Union[str, None], str),
|
|
(Union[str, None], str, str),
|
|
(Union[str, None], Optional[str], Optional[str]),
|
|
(Optional[str], Union[str, None], Optional[str]),
|
|
(Union[str, None], Union[str, None], Union[str, None]),
|
|
],
|
|
)
|
|
def test_union_types_compatible(left, right, expected_common):
|
|
"""Test compatible Union types."""
|
|
is_compat, common = _is_compatible(left, right)
|
|
assert is_compat
|
|
assert common == expected_common
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"left,right,expected_common",
|
|
[
|
|
(int, int | str, int),
|
|
(int | str, int, int),
|
|
(int | str, str | int, int | str),
|
|
(str, str | None, str),
|
|
(str | None, str, str),
|
|
(str | None, str | None, str | None),
|
|
# Mixed PEP 604 and typing.Union and Optional
|
|
(int | str, Union[int, str], int | str),
|
|
(Union[int, str], int | str, Union[int, str]),
|
|
(str | None, Optional[str], str | None),
|
|
(Optional[str], str | None, Optional[str]),
|
|
],
|
|
)
|
|
def test_union_types_pep604(left, right, expected_common):
|
|
"""Test PEP 604 union type compatibility."""
|
|
is_compat, common = _is_compatible(left, right)
|
|
assert is_compat
|
|
assert common == expected_common
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"left,right",
|
|
[
|
|
(bool, Union[int, str]),
|
|
(float, Union[int, str]),
|
|
(Union[int, str], Union[float, bool]),
|
|
# Pep 604
|
|
(bool, int | str),
|
|
(float, int | str),
|
|
(int | str, float | bool),
|
|
],
|
|
)
|
|
def test_union_types_incompatible(left, right):
|
|
"""Test incompatible Union types."""
|
|
is_compat, common = _is_compatible(left, right)
|
|
assert not is_compat
|
|
assert common is None
|
|
|
|
|
|
def test_variadic_type_compatibility():
|
|
"""Test compatibility with Variadic and GreedyVariadic types."""
|
|
# Basic type compatibility
|
|
variadic_int = Variadic[int]
|
|
greedy_int = GreedyVariadic[int]
|
|
|
|
is_compat, common = _is_compatible(variadic_int, int)
|
|
assert is_compat and common == int
|
|
|
|
is_compat, common = _is_compatible(int, variadic_int)
|
|
assert is_compat and common == int
|
|
|
|
is_compat, common = _is_compatible(greedy_int, int)
|
|
assert is_compat and common == int
|
|
|
|
is_compat, common = _is_compatible(int, greedy_int)
|
|
assert is_compat and common == int
|
|
|
|
# List type compatibility
|
|
variadic_list = Variadic[list[int]]
|
|
greedy_list = GreedyVariadic[list[int]]
|
|
|
|
is_compat, common = _is_compatible(variadic_list, list[int])
|
|
assert is_compat and common == list[int]
|
|
|
|
is_compat, common = _is_compatible(list[int], variadic_list)
|
|
assert is_compat and common == list[int]
|
|
|
|
is_compat, common = _is_compatible(greedy_list, list[int])
|
|
assert is_compat and common == list[int]
|
|
|
|
is_compat, common = _is_compatible(list[int], greedy_list)
|
|
assert is_compat and common == list[int]
|
|
|
|
# PEP 604 with Variadic
|
|
variadic_union = Variadic[int | str]
|
|
|
|
is_compat, common = _is_compatible(variadic_union, int | str)
|
|
assert is_compat and common == int | str
|
|
|
|
is_compat, common = _is_compatible(int | str, variadic_union)
|
|
assert is_compat and common == int | str
|
|
|
|
# PEP 604 optional with GreedyVariadic
|
|
greedy_opt = GreedyVariadic[int | None]
|
|
|
|
is_compat, common = _is_compatible(greedy_opt, int)
|
|
assert is_compat and common == int
|
|
|
|
is_compat, common = _is_compatible(int, greedy_opt)
|
|
assert is_compat and common == int
|
|
|
|
|
|
def test_nested_type_unwrapping():
|
|
"""Test nested type unwrapping behavior with unwrap_nested parameter."""
|
|
# Test with unwrap_nested=True (default)
|
|
nested_optional = Variadic[list[int | None]]
|
|
|
|
is_compat, common = _is_compatible(nested_optional, list[int])
|
|
assert is_compat and common == list[int]
|
|
|
|
is_compat, common = _is_compatible(list[int], nested_optional)
|
|
assert is_compat and common == list[int]
|
|
|
|
nested_union = Variadic[list[Union[int, None]]]
|
|
|
|
is_compat, common = _is_compatible(nested_union, list[int])
|
|
assert is_compat and common == list[int]
|
|
|
|
is_compat, common = _is_compatible(list[int], nested_union)
|
|
assert is_compat and common == list[int]
|
|
|
|
# PEP 604 (X | Y and X | None syntax)
|
|
nested_pep604_optional = Variadic[list[int | None]]
|
|
|
|
is_compat, common = _is_compatible(nested_pep604_optional, list[int])
|
|
assert is_compat and common == list[int]
|
|
|
|
is_compat, common = _is_compatible(list[int], nested_pep604_optional)
|
|
assert is_compat and common == list[int]
|
|
|
|
nested_pep604_union = Variadic[list[str | int]]
|
|
|
|
is_compat, common = _is_compatible(nested_pep604_union, list[str | int])
|
|
assert is_compat and common == list[str | int]
|
|
|
|
|
|
def test_complex_nested_types():
|
|
"""Test complex nested type scenarios."""
|
|
# Multiple levels of nesting
|
|
complex_type = Variadic[list[list[Variadic[int]]]]
|
|
target_type = list[list[int]]
|
|
|
|
# With unwrap_nested=True
|
|
is_compat, common = _is_compatible(complex_type, target_type)
|
|
assert is_compat and common == list[list[int]]
|
|
|
|
is_compat, common = _is_compatible(target_type, complex_type)
|
|
assert is_compat and common == list[list[int]]
|
|
|
|
# With unwrap_nested=False
|
|
is_compat, common = _is_compatible(complex_type, target_type, unwrap_nested=False)
|
|
assert not is_compat and common is None
|
|
|
|
is_compat, common = _is_compatible(target_type, complex_type, unwrap_nested=False)
|
|
assert not is_compat and common is None
|
|
|
|
|
|
def test_mixed_variadic_types():
|
|
"""Test mixing Variadic and GreedyVariadic with other type constructs."""
|
|
# Variadic with Union
|
|
var_union = Variadic[Union[int, str]]
|
|
|
|
is_compat, common = _is_compatible(var_union, Union[int, str]) # type: ignore[arg-type]
|
|
assert is_compat and common == Union[int, str]
|
|
|
|
is_compat, common = _is_compatible(Union[int, str], var_union) # type: ignore[arg-type]
|
|
assert is_compat and common == Union[int, str]
|
|
|
|
# GreedyVariadic with Optional
|
|
greedy_opt = GreedyVariadic[Optional[int]]
|
|
|
|
is_compat, common = _is_compatible(greedy_opt, int)
|
|
assert is_compat and common == int
|
|
|
|
is_compat, common = _is_compatible(int, greedy_opt)
|
|
assert is_compat and common == int
|
|
|
|
# Nested Variadic and GreedyVariadic
|
|
nested_var = Variadic[list[GreedyVariadic[int]]]
|
|
|
|
is_compat, common = _is_compatible(nested_var, list[int])
|
|
assert is_compat and common == list[int]
|