Merge branch 'feature/designer' into feature/store-i18n

This commit is contained in:
kevinveenbirkenbach committed 2026-10-16 13:19:15 +02:00
commit 338a2ffa7f
34 files changed
+597 -186

No files matched your search

@@ -56,6 +56,48 @@ class TestApplicationsCarrierActionPlugin(unittest.TestCase):
self.assertEqual(variables, {"applications": {}})
self.assertTrue(kwargs["carrier"])
def test_revalidates_the_tokens_file_before_rendering(self):
order = []
lookup = _FakeLookup({"key": ["roles", []], "applications": {}})
lookup.run = lambda *args, **kwargs: order.append("render") or [{}]
action = _make_action(_FakeTask())
with (
patch(
"plugins.action.applications_carrier.ActionBase.run",
autospec=True,
return_value={},
),
patch(
"plugins.action.applications_carrier.lookup_loader.get",
return_value=lookup,
),
patch(
"plugins.action.applications_carrier.revalidate_tokens_file",
side_effect=lambda variables: order.append(("revalidate", variables)),
),
):
action.run(task_vars={"FILE_TOKENS": "/x/tokens.yml"})
self.assertEqual(
order, [("revalidate", {"FILE_TOKENS": "/x/tokens.yml"}), "render"]
)
def test_clear_does_not_revalidate(self):
action = _make_action(_FakeTask(args={"clear": True}))
with (
patch(
"plugins.action.applications_carrier.ActionBase.run",
autospec=True,
return_value={},
),
patch(
"plugins.action.applications_carrier.revalidate_tokens_file"
) as revalidate,
):
action.run(task_vars={})
revalidate.assert_not_called()
def test_rejects_arguments(self):
action = _make_action(_FakeTask(args={"foo": 1}))
with (
@@ -74,6 +74,7 @@ def render(
remote_models=REMOTE_MODELS,
router_alias="",
measured_speed=None,
logo_url="",
):
"""The rendered config as a parsed mapping.
@@ -86,6 +87,7 @@ def render(
is what every case that predates the router expects.
measured_speed: alias -> tokens per second from the last deploy's
measurement; empty means nothing has been measured yet.
logo_url: LITELLM_UI_LOGO_URL; empty while the admin UI shows no corporate logo.
"""
env = Environment(
undefined=StrictUndefined,
@@ -108,6 +110,7 @@ def render(
+ [MOCK["provider"]],
LITELLM_ROUTER_ALIAS=router_alias,
LITELLM_MEASURED_SPEED=measured_speed or {},
LITELLM_UI_LOGO_URL=logo_url,
)
return yaml.safe_load(
rendered
@@ -183,6 +186,17 @@ class TestBothBackends(unittest.TestCase):
)
class TestUiTheme(unittest.TestCase):
def test_a_logo_url_reaches_the_ui_theme_config(self) -> None:
url = "https://cdn.example/roles/web-app-litellm/latest/img/design/logo.svg"
settings = render(logo_url=url)["litellm_settings"]
self.assertEqual(settings["ui_theme_config"], {"logo_url": url})
self.assertTrue(settings["drop_params"])
def test_without_a_logo_url_the_ui_theme_config_is_absent(self) -> None:
self.assertNotIn("ui_theme_config", render()["litellm_settings"])
class TestNoBackend(unittest.TestCase):
def test_the_model_list_is_empty(self) -> None:
self.assertEqual(render()["model_list"], [])
+39 -4
View File
@@ -10,9 +10,11 @@ files; this file pins the contract of base itself.
from __future__ import annotations
import os
import tempfile
import textwrap
import unittest
import unittest.mock as mock
from pathlib import Path
from utils.cache import _reset_cache_for_tests, base
@@ -153,11 +155,13 @@ class TestStableVariablesSignature(unittest.TestCase):
class TestTokensFileSignature(unittest.TestCase):
def test_missing_file_returns_zeroed_signature(self):
def setUp(self):
base._reset()
def test_missing_file_returns_an_empty_digest(self):
with tempfile.TemporaryDirectory() as tmp:
sig = base._tokens_file_signature(Path(tmp) / "absent.yml")
self.assertEqual(sig[1], 0)
self.assertEqual(sig[2], 0)
path = Path(tmp) / "absent.yml"
self.assertEqual(base._tokens_file_signature(path), (str(path), ""))
def test_signature_changes_when_file_changes(self):
with tempfile.TemporaryDirectory() as tmp:
@@ -168,6 +172,37 @@ class TestTokensFileSignature(unittest.TestCase):
sig_after = base._tokens_file_signature(path)
self.assertNotEqual(sig_before, sig_after)
def test_a_touch_keeps_the_signature(self):
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "tokens.yml"
path.write_text("a: 1\n", encoding="utf-8")
sig_before = base._tokens_file_signature(path)
later = path.stat().st_mtime_ns + 5_000_000_000
os.utime(path, ns=(later, later))
self.assertEqual(base._tokens_file_signature(path), sig_before)
def test_an_unchanged_stat_serves_the_digest_without_reading(self):
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "tokens.yml"
path.write_text("a: 1\n", encoding="utf-8")
sig_before = base._tokens_file_signature(path)
with mock.patch.object(Path, "open", side_effect=AssertionError):
self.assertEqual(base._tokens_file_signature(path), sig_before)
class TestRevalidateTokensFile(unittest.TestCase):
def test_opens_the_file(self):
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "tokens.yml"
path.write_text("a: 1\n", encoding="utf-8")
with mock.patch.object(Path, "open", wraps=path.open) as opened:
base._revalidate_tokens_file(path)
opened.assert_called_once_with("rb")
def test_a_missing_file_is_ignored(self):
with tempfile.TemporaryDirectory() as tmp:
base._revalidate_tokens_file(Path(tmp) / "absent.yml")
class TestRenderWithTemplar(unittest.TestCase):
"""`_render_with_templar` is the single ansible-coupled symbol in