From c8d3298e1bb6a9245449dac1c8727ce3d932cd1d Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Mon, 10 Aug 2026 18:28:58 +0200 Subject: feat: dialog for per-model context size, vision and prices Field conversion is separated from the widget so the part with the edge cases is testable without a running Qt application. Vision is tri-state through a binary checkbox: an unchecked box with an unknown prefill stays unknown rather than writing False, which would shadow a provider-level vision=True through models.resolve's pick(). Co-Authored-By: Claude Opus 5 --- test_llamachat.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'test_llamachat.py') diff --git a/test_llamachat.py b/test_llamachat.py index 1217176..b561b66 100755 --- a/test_llamachat.py +++ b/test_llamachat.py @@ -1972,6 +1972,59 @@ def test_multi_client(): print("ok multi-provider client") +def test_model_dialog_values(): + """The dialog's field text converts to ModelInfo, blanks meaning unknown.""" + from llamachat import models, modeldialog + + # Everything filled in. + info = modeldialog.to_info( + ctx_text="32768", vision=True, in_text="1.2", out_text="0.9" + ) + assert info.ctx_size == 32768 + assert info.vision is True + assert info.price_in == 1.2 + assert info.price_out == 0.9 + + # Blank prices are legal and mean unpriced, not free. + blank = modeldialog.to_info( + ctx_text="8192", vision=False, in_text="", out_text=" " + ) + assert blank.ctx_size == 8192 + assert blank.price_in is None + assert blank.price_out is None + + # Garbage reads as unknown rather than crashing the dialog. + junk = modeldialog.to_info( + ctx_text="not a number", vision=False, in_text="free", out_text="" + ) + assert junk.ctx_size is None + assert junk.price_in is None + + # Vision is tri-state through a binary checkbox: an unchecked box with an + # unknown prefill stays unknown, instead of writing False, which would + # shadow a provider-level vision=True through models.resolve's pick(). A + # known prefill (True or False) left unchecked is a real "no". + assert modeldialog.to_info( + ctx_text="", vision=True, in_text="", out_text="" + ).vision is True + assert modeldialog.to_info( + ctx_text="", vision=False, in_text="", out_text="" + ).vision is None + assert modeldialog.to_info( + ctx_text="", vision=False, in_text="", out_text="", vision_prefill=True + ).vision is False + assert modeldialog.to_info( + ctx_text="", vision=False, in_text="", out_text="", vision_prefill=False + ).vision is False + + # Prefill is the inverse: unknown becomes an empty field. + assert modeldialog.to_fields(models.ModelInfo()) == ("", False, "", "") + assert modeldialog.to_fields( + models.ModelInfo(ctx_size=4096, vision=True, price_in=0.5) + ) == ("4096", True, "0.5", "") + print("ok model dialog value conversion") + + class _FakeResponse: """Enough of an http.client response for urlopen's context manager.""" @@ -2734,6 +2787,7 @@ if __name__ == "__main__": test_token_column_migration() test_client_auth_header() test_multi_client() + test_model_dialog_values() test_search_tool_schema() test_search_results_sanitising() test_tool_call_accumulation() -- cgit v1.2.3