v2.7.6 (#600)
Co-authored-by: Clément Sirieix <clement.sirieix@mistral.ai> Co-authored-by: Kim-Adeline Miguel <51720070+kimadeline@users.noreply.github.com> Co-authored-by: Mathias Gesbert <mathias.gesbert@mistral.ai> Co-authored-by: Maxime Dolores <maxime.dolores@ext.mistral.ai> Co-authored-by: Michel Thomazo <51709227+michelTho@users.noreply.github.com> Co-authored-by: Paul Cacheux <paul.cacheux@mistral.ai> Co-authored-by: Quentin <quentin.torroba@mistral.ai> Co-authored-by: Simon <80467011+sorgfresser@users.noreply.github.com> Co-authored-by: angelapopopo <angele.lenglemetz@mistral.ai> Co-authored-by: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
parent
e1a25caa52
commit
95336528f6
59 changed files with 3992 additions and 403 deletions
163
tests/core/test_merge.py
Normal file
163
tests/core/test_merge.py
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from vibe.core.utils.merge import MergeConflictError, MergeStrategy
|
||||
|
||||
|
||||
class TestMergeStrategyEnum:
|
||||
def test_values_are_lowercase_strings(self) -> None:
|
||||
assert MergeStrategy.REPLACE == "replace"
|
||||
assert MergeStrategy.CONCAT == "concat"
|
||||
assert MergeStrategy.UNION == "union"
|
||||
assert MergeStrategy.MERGE == "merge"
|
||||
assert MergeStrategy.CONFLICT == "conflict"
|
||||
|
||||
def test_all_strategies_exist(self) -> None:
|
||||
assert len(MergeStrategy) == 5
|
||||
|
||||
def test_unknown_strategy_raises_not_implemented(self) -> None:
|
||||
fake = MagicMock(spec=MergeStrategy)
|
||||
with pytest.raises(NotImplementedError, match="not implemented"):
|
||||
MergeStrategy.apply(fake, "a", "b")
|
||||
|
||||
|
||||
class TestReplace:
|
||||
def test_override_wins(self) -> None:
|
||||
assert MergeStrategy.REPLACE.apply(1, 2) == 2
|
||||
|
||||
def test_base_returned_when_override_none(self) -> None:
|
||||
assert MergeStrategy.REPLACE.apply(1, None) == 1
|
||||
|
||||
def test_both_none_returns_none(self) -> None:
|
||||
assert MergeStrategy.REPLACE.apply(None, None) is None
|
||||
|
||||
def test_override_none_preserves_base_type(self) -> None:
|
||||
assert MergeStrategy.REPLACE.apply([1, 2], None) == [1, 2]
|
||||
assert MergeStrategy.REPLACE.apply({"a": 1}, None) == {"a": 1}
|
||||
|
||||
def test_override_can_be_falsy(self) -> None:
|
||||
assert MergeStrategy.REPLACE.apply(1, 0) == 0
|
||||
assert MergeStrategy.REPLACE.apply(1, "") == ""
|
||||
assert MergeStrategy.REPLACE.apply(1, False) is False
|
||||
|
||||
|
||||
class TestConcat:
|
||||
def test_lists_concatenated(self) -> None:
|
||||
assert MergeStrategy.CONCAT.apply([1, 2], [3, 4]) == [1, 2, 3, 4]
|
||||
|
||||
def test_base_none_returns_override(self) -> None:
|
||||
assert MergeStrategy.CONCAT.apply(None, [1]) == [1]
|
||||
|
||||
def test_override_none_returns_base(self) -> None:
|
||||
assert MergeStrategy.CONCAT.apply([1], None) == [1]
|
||||
|
||||
def test_both_none_returns_none(self) -> None:
|
||||
assert MergeStrategy.CONCAT.apply(None, None) is None
|
||||
|
||||
def test_empty_lists(self) -> None:
|
||||
assert MergeStrategy.CONCAT.apply([], []) == []
|
||||
|
||||
def test_raises_type_error_for_non_list(self) -> None:
|
||||
with pytest.raises(TypeError, match="CONCAT requires list operands"):
|
||||
MergeStrategy.CONCAT.apply("a", [1])
|
||||
with pytest.raises(TypeError, match="CONCAT requires list operands"):
|
||||
MergeStrategy.CONCAT.apply([1], "b")
|
||||
|
||||
|
||||
class TestUnion:
|
||||
def test_merge_by_key_override_wins(self) -> None:
|
||||
base = [{"name": "a", "v": 1}, {"name": "b", "v": 2}]
|
||||
override = [{"name": "b", "v": 99}]
|
||||
result = MergeStrategy.UNION.apply(base, override, key_fn=lambda x: x["name"])
|
||||
assert result == [{"name": "a", "v": 1}, {"name": "b", "v": 99}]
|
||||
|
||||
def test_preserves_order_base_first(self) -> None:
|
||||
base = [{"name": "a"}, {"name": "b"}]
|
||||
override = [{"name": "c"}]
|
||||
result = MergeStrategy.UNION.apply(base, override, key_fn=lambda x: x["name"])
|
||||
assert [x["name"] for x in result] == ["a", "b", "c"]
|
||||
|
||||
def test_new_keys_from_override_appended(self) -> None:
|
||||
base = [{"name": "a"}]
|
||||
override = [{"name": "b"}, {"name": "c"}]
|
||||
result = MergeStrategy.UNION.apply(base, override, key_fn=lambda x: x["name"])
|
||||
assert len(result) == 3
|
||||
|
||||
def test_base_none_returns_override(self) -> None:
|
||||
assert MergeStrategy.UNION.apply(None, [1], key_fn=str) == [1]
|
||||
|
||||
def test_override_none_returns_base(self) -> None:
|
||||
assert MergeStrategy.UNION.apply([1], None, key_fn=str) == [1]
|
||||
|
||||
def test_both_none_returns_none(self) -> None:
|
||||
assert MergeStrategy.UNION.apply(None, None) is None
|
||||
|
||||
def test_raises_without_key_fn(self) -> None:
|
||||
with pytest.raises(ValueError, match="UNION strategy requires key_fn"):
|
||||
MergeStrategy.UNION.apply([1], [2])
|
||||
|
||||
def test_raises_type_error_for_non_list(self) -> None:
|
||||
with pytest.raises(TypeError, match="UNION requires list operands"):
|
||||
MergeStrategy.UNION.apply("a", [1], key_fn=str)
|
||||
|
||||
|
||||
class TestMerge:
|
||||
def test_dicts_merged_one_level(self) -> None:
|
||||
result = MergeStrategy.MERGE.apply({"a": 1, "b": 2}, {"b": 3, "c": 4})
|
||||
assert result == {"a": 1, "b": 3, "c": 4}
|
||||
|
||||
def test_nested_dicts_not_recursed(self) -> None:
|
||||
base = {"a": {"x": 1, "y": 2}}
|
||||
override = {"a": {"y": 3, "z": 4}}
|
||||
result = MergeStrategy.MERGE.apply(base, override)
|
||||
assert result == {"a": {"y": 3, "z": 4}}
|
||||
|
||||
def test_base_none_returns_override(self) -> None:
|
||||
assert MergeStrategy.MERGE.apply(None, {"a": 1}) == {"a": 1}
|
||||
|
||||
def test_override_none_returns_base(self) -> None:
|
||||
assert MergeStrategy.MERGE.apply({"a": 1}, None) == {"a": 1}
|
||||
|
||||
def test_both_none_returns_none(self) -> None:
|
||||
assert MergeStrategy.MERGE.apply(None, None) is None
|
||||
|
||||
def test_raises_type_error_for_non_dict(self) -> None:
|
||||
with pytest.raises(TypeError, match="MERGE requires dict operands"):
|
||||
MergeStrategy.MERGE.apply([1], {"a": 1})
|
||||
|
||||
def test_does_not_mutate_inputs(self) -> None:
|
||||
base = {"a": 1}
|
||||
override = {"b": 2}
|
||||
MergeStrategy.MERGE.apply(base, override)
|
||||
assert base == {"a": 1}
|
||||
assert override == {"b": 2}
|
||||
|
||||
|
||||
class TestConflict:
|
||||
def test_raises_when_both_provided(self) -> None:
|
||||
with pytest.raises(MergeConflictError):
|
||||
MergeStrategy.CONFLICT.apply(1, 2)
|
||||
|
||||
def test_base_only_returns_base(self) -> None:
|
||||
assert MergeStrategy.CONFLICT.apply(1, None) == 1
|
||||
|
||||
def test_override_only_returns_override(self) -> None:
|
||||
assert MergeStrategy.CONFLICT.apply(None, 2) == 2
|
||||
|
||||
def test_both_none_returns_none(self) -> None:
|
||||
assert MergeStrategy.CONFLICT.apply(None, None) is None
|
||||
|
||||
|
||||
class TestMergeConflictError:
|
||||
def test_default_message(self) -> None:
|
||||
err = MergeConflictError()
|
||||
assert str(err) == "Merge conflict"
|
||||
assert err.field_name == ""
|
||||
|
||||
def test_message_with_field_name(self) -> None:
|
||||
err = MergeConflictError("active_model")
|
||||
assert str(err) == "Merge conflict on field 'active_model'"
|
||||
assert err.field_name == "active_model"
|
||||
|
|
@ -489,7 +489,7 @@ class TestTelemetryClient:
|
|||
|
||||
assert (
|
||||
client._get_telemetry_url("not-a-valid-url")
|
||||
== "https://codestral.mistral.ai/v1/datalake/events"
|
||||
== "https://api.mistral.ai/v1/datalake/events"
|
||||
)
|
||||
|
||||
def test_is_active_false_when_mistral_provider_exists_but_no_api_key(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue