Files

1 line
28 KiB
JSON

{"repo": "69gg/undefined", "files": {"tests/test_webui_render_toml.py": {"5a8d3ae7f13db16beb5fb8d5642119189a266c62": {"t": 1785747498.4251673, "n": 5849, "h": "4517ab419a6abe03", "c": "\"\"\"render_toml array-of-tables 单元测试\"\"\"\n\nimport tomllib\n\nfrom Undefined.webui.utils import parse_comment_map_text, render_toml\n\n\ndef _roundtrip(toml_str: str) -> dict: # type: ignore[type-arg]\n data = tomllib.loads(toml_str)\n rendered = render_toml(data)\n return tomllib.loads(rendered)\n\n\nclass TestRenderTomlArrayOfTables:\n def test_pool_models_roundtrip(self) -> None:\n \"\"\"[[models.chat.pool.models]] 经过 render_toml 后结构不变\"\"\"\n src = \"\"\"\n[models.chat.pool]\nenabled = true\nstrategy = \"round_robin\"\n\n[[models.chat.pool.models]]\nmodel_name = \"gpt-4o\"\napi_url = \"https://api.openai.com/v1\"\napi_key = \"sk-a\"\n\n[[models.chat.pool.models]]\nmodel_name = \"deepseek-chat\"\napi_url = \"https://api.deepseek.com/v1\"\napi_key = \"sk-b\"\n\"\"\"\n data = _roundtrip(src)\n pool = data[\"models\"][\"chat\"][\"pool\"]\n assert pool[\"enabled\"] is True\n assert pool[\"strategy\"] == \"round_robin\"\n assert len(pool[\"models\"]) == 2\n assert pool[\"models\"][0][\"model_name\"] == \"gpt-4o\"\n assert pool[\"models\"][1][\"api_key\"] == \"sk-b\"\n\n def test_empty_list_stays_inline(self) -> None:\n \"\"\"空列表仍渲染为内联数组\"\"\"\n rendered = render_toml({\"allowed\": []})\n assert \"allowed = []\" in rendered\n\n def test_scalar_list_stays_inline(self) -> None:\n \"\"\"标量列表仍渲染为内联数组\"\"\"\n data = _roundtrip(\"ids = [1, 2, 3]\")\n assert data[\"ids\"] == [1, 2, 3]\n\n def test_aot_not_rendered_as_string(self) -> None:\n \"\"\"list[dict] 不能被渲染成字符串形式\"\"\"\n src = \"\"\"\n[[items]]\nname = \"a\"\n[[items]]\nname = \"b\"\n\"\"\"\n rendered = render_toml(tomllib.loads(src))\n assert '\"{' not in rendered\n assert \"[[items]]\" in rendered\n\n def test_pool_model_request_params_roundtrip(self) -> None:\n \"\"\"模型池条目下的 request_params 嵌套结构应完整往返\"\"\"\n src = \"\"\"\n[models.chat.pool]\nenabled = true\n\n[[models.chat.pool.models]]\nmodel_name = \"gpt-5\"\napi_url = \"https://api.openai.com/v1\"\napi_key = \"sk-a\"\napi_mode = \"responses\"\nthinking_tool_call_compat = true\nresponses_tool_choice_compat = true\nresponses_force_stateless_replay = true\nreasoning_enabled = true\nreasoning_effort = \"high\"\nstream_enabled = true\n\n[models.chat.pool.models.request_params]\ntemperature = 0.7\n\n[models.chat.pool.models.request_params.metadata]\nsource = \"webui\"\n\n[[models.chat.pool.models.request_params.tags]]\nname = \"alpha\"\n\n[[models.chat.pool.models.request_params.tags]]\nname = \"beta\"\n\"\"\"\n data = _roundtrip(src)\n model = data[\"models\"][\"chat\"][\"pool\"][\"models\"][0]\n assert model[\"api_mode\"] == \"responses\"\n assert model[\"thinking_tool_call_compat\"] is True\n assert model[\"responses_tool_choice_compat\"] is True\n assert model[\"responses_force_stateless_replay\"] is True\n assert model[\"reasoning_enabled\"] is True\n assert model[\"reasoning_effort\"] == \"high\"\n assert model[\"stream_enabled\"] is True\n params = model[\"request_params\"]\n assert params[\"temperature\"] == 0.7\n assert params[\"metadata\"][\"source\"] == \"webui\"\n assert [item[\"name\"] for item in params[\"tags\"]] == [\"alpha\", \"beta\"]\n\n def test_nested_aot_child_tables_roundtrip(self) -> None:\n \"\"\"数组表项下的嵌套表与子数组表不能在渲染时丢失\"\"\"\n src = \"\"\"\n[[items]]\nname = \"root\"\n\n[items.meta]\nenabled = true\n\n[[items.meta.children]]\nname = \"child-a\"\n\n[[items.meta.children]]\nname = \"child-b\"\n\"\"\"\n data = _roundtrip(src)\n item = data[\"items\"][0]\n assert item[\"meta\"][\"enabled\"] is True\n assert [child[\"name\"] for child in item[\"meta\"][\"children\"]] == [\n \"child-a\",\n \"child-b\",\n ]\n\n def test_render_comments_and_empty_table(self) -> None:\n \"\"\"带注释的空表应被完整渲染出来\"\"\"\n src = \"\"\"\n# zh: 主配置\n# en: Main section\n[models.chat.request_params]\n\"\"\"\n comments = parse_comment_map_text(src)\n rendered = render_toml(\n {\"models\": {\"chat\": {\"request_params\": {}}}}, comments=comments\n )\n assert \"# zh: 主配置\" in rendered\n assert \"[models.chat.request_params]\" in rendered\n\n def test_render_comments_before_scalar_keys(self) -> None:\n \"\"\"标量字段前应写出示例注释\"\"\"\n comments = {\n \"core.bot_qq\": {\n \"zh\": \"机器人QQ号。\",\n \"en\": \"Bot QQ number.\",\n }\n }\n rendered = render_toml({\"core\": {\"bot_qq\": 1}}, comments=comments)\n assert \"# zh: 机器人QQ号。\" in rendered\n assert \"# en: Bot QQ number.\" in rendered\n assert \"bot_qq = 1\" in rendered\n\n def test_multiline_comments_preserved(self) -> None:\n \"\"\"多行 zh/en 注释应保留为多行而非压成一行\"\"\"\n src = (\n \"# zh: 第一行\\n\"\n \"# zh: 第二行\\n\"\n \"# en: Line one\\n\"\n \"# en: Line two\\n\"\n \"enabled = false\\n\"\n )\n comments = parse_comment_map_text(src)\n rendered = render_toml({\"enabled\": False}, comments=comments)\n assert \"# zh: 第一行\" in rendered\n assert \"# zh: 第二行\" in rendered\n assert \"# en: Line one\" in rendered\n assert \"# en: Line two\" in rendered\n\n def test_multiline_string_roundtrip(self) -> None:\n \"\"\"多行字符串应被渲染成合法 TOML,并可完整往返\"\"\"\n original = \"第一行\\n第二行\\n第三行\"\n rendered = render_toml(\n {\"models\": {\"embedding\": {\"query_instruction\": original}}}\n )\n parsed = tomllib.loads(rendered)\n assert parsed[\"models\"][\"embedding\"][\"query_instruction\"] == original\n assert \"\\n\" in rendered\n\n def test_multiline_string_with_quotes_and_backslashes_roundtrip(self) -> None:\n \"\"\"带引号与反斜杠的多行字符串也必须是合法 TOML\"\"\"\n original = 'prefix \"quoted\"\\npath\\\\to\\\\file\\nline3'\n rendered = render_toml(\n {\"models\": {\"embedding\": {\"document_instruction\": original}}}\n )\n parsed = tomllib.loads(rendered)\n assert parsed[\"models\"][\"embedding\"][\"document_instruction\"] == original\n"}, "87d5523663b77ba06d91a0e1e0d63ae5582923d8": {"t": 1785773609.6254287, "n": 5849, "h": "4517ab419a6abe03", "c": "\"\"\"render_toml array-of-tables 单元测试\"\"\"\n\nimport tomllib\n\nfrom Undefined.webui.utils import parse_comment_map_text, render_toml\n\n\ndef _roundtrip(toml_str: str) -> dict: # type: ignore[type-arg]\n data = tomllib.loads(toml_str)\n rendered = render_toml(data)\n return tomllib.loads(rendered)\n\n\nclass TestRenderTomlArrayOfTables:\n def test_pool_models_roundtrip(self) -> None:\n \"\"\"[[models.chat.pool.models]] 经过 render_toml 后结构不变\"\"\"\n src = \"\"\"\n[models.chat.pool]\nenabled = true\nstrategy = \"round_robin\"\n\n[[models.chat.pool.models]]\nmodel_name = \"gpt-4o\"\napi_url = \"https://api.openai.com/v1\"\napi_key = \"sk-a\"\n\n[[models.chat.pool.models]]\nmodel_name = \"deepseek-chat\"\napi_url = \"https://api.deepseek.com/v1\"\napi_key = \"sk-b\"\n\"\"\"\n data = _roundtrip(src)\n pool = data[\"models\"][\"chat\"][\"pool\"]\n assert pool[\"enabled\"] is True\n assert pool[\"strategy\"] == \"round_robin\"\n assert len(pool[\"models\"]) == 2\n assert pool[\"models\"][0][\"model_name\"] == \"gpt-4o\"\n assert pool[\"models\"][1][\"api_key\"] == \"sk-b\"\n\n def test_empty_list_stays_inline(self) -> None:\n \"\"\"空列表仍渲染为内联数组\"\"\"\n rendered = render_toml({\"allowed\": []})\n assert \"allowed = []\" in rendered\n\n def test_scalar_list_stays_inline(self) -> None:\n \"\"\"标量列表仍渲染为内联数组\"\"\"\n data = _roundtrip(\"ids = [1, 2, 3]\")\n assert data[\"ids\"] == [1, 2, 3]\n\n def test_aot_not_rendered_as_string(self) -> None:\n \"\"\"list[dict] 不能被渲染成字符串形式\"\"\"\n src = \"\"\"\n[[items]]\nname = \"a\"\n[[items]]\nname = \"b\"\n\"\"\"\n rendered = render_toml(tomllib.loads(src))\n assert '\"{' not in rendered\n assert \"[[items]]\" in rendered\n\n def test_pool_model_request_params_roundtrip(self) -> None:\n \"\"\"模型池条目下的 request_params 嵌套结构应完整往返\"\"\"\n src = \"\"\"\n[models.chat.pool]\nenabled = true\n\n[[models.chat.pool.models]]\nmodel_name = \"gpt-5\"\napi_url = \"https://api.openai.com/v1\"\napi_key = \"sk-a\"\napi_mode = \"responses\"\nthinking_tool_call_compat = true\nresponses_tool_choice_compat = true\nresponses_force_stateless_replay = true\nreasoning_enabled = true\nreasoning_effort = \"high\"\nstream_enabled = true\n\n[models.chat.pool.models.request_params]\ntemperature = 0.7\n\n[models.chat.pool.models.request_params.metadata]\nsource = \"webui\"\n\n[[models.chat.pool.models.request_params.tags]]\nname = \"alpha\"\n\n[[models.chat.pool.models.request_params.tags]]\nname = \"beta\"\n\"\"\"\n data = _roundtrip(src)\n model = data[\"models\"][\"chat\"][\"pool\"][\"models\"][0]\n assert model[\"api_mode\"] == \"responses\"\n assert model[\"thinking_tool_call_compat\"] is True\n assert model[\"responses_tool_choice_compat\"] is True\n assert model[\"responses_force_stateless_replay\"] is True\n assert model[\"reasoning_enabled\"] is True\n assert model[\"reasoning_effort\"] == \"high\"\n assert model[\"stream_enabled\"] is True\n params = model[\"request_params\"]\n assert params[\"temperature\"] == 0.7\n assert params[\"metadata\"][\"source\"] == \"webui\"\n assert [item[\"name\"] for item in params[\"tags\"]] == [\"alpha\", \"beta\"]\n\n def test_nested_aot_child_tables_roundtrip(self) -> None:\n \"\"\"数组表项下的嵌套表与子数组表不能在渲染时丢失\"\"\"\n src = \"\"\"\n[[items]]\nname = \"root\"\n\n[items.meta]\nenabled = true\n\n[[items.meta.children]]\nname = \"child-a\"\n\n[[items.meta.children]]\nname = \"child-b\"\n\"\"\"\n data = _roundtrip(src)\n item = data[\"items\"][0]\n assert item[\"meta\"][\"enabled\"] is True\n assert [child[\"name\"] for child in item[\"meta\"][\"children\"]] == [\n \"child-a\",\n \"child-b\",\n ]\n\n def test_render_comments_and_empty_table(self) -> None:\n \"\"\"带注释的空表应被完整渲染出来\"\"\"\n src = \"\"\"\n# zh: 主配置\n# en: Main section\n[models.chat.request_params]\n\"\"\"\n comments = parse_comment_map_text(src)\n rendered = render_toml(\n {\"models\": {\"chat\": {\"request_params\": {}}}}, comments=comments\n )\n assert \"# zh: 主配置\" in rendered\n assert \"[models.chat.request_params]\" in rendered\n\n def test_render_comments_before_scalar_keys(self) -> None:\n \"\"\"标量字段前应写出示例注释\"\"\"\n comments = {\n \"core.bot_qq\": {\n \"zh\": \"机器人QQ号。\",\n \"en\": \"Bot QQ number.\",\n }\n }\n rendered = render_toml({\"core\": {\"bot_qq\": 1}}, comments=comments)\n assert \"# zh: 机器人QQ号。\" in rendered\n assert \"# en: Bot QQ number.\" in rendered\n assert \"bot_qq = 1\" in rendered\n\n def test_multiline_comments_preserved(self) -> None:\n \"\"\"多行 zh/en 注释应保留为多行而非压成一行\"\"\"\n src = (\n \"# zh: 第一行\\n\"\n \"# zh: 第二行\\n\"\n \"# en: Line one\\n\"\n \"# en: Line two\\n\"\n \"enabled = false\\n\"\n )\n comments = parse_comment_map_text(src)\n rendered = render_toml({\"enabled\": False}, comments=comments)\n assert \"# zh: 第一行\" in rendered\n assert \"# zh: 第二行\" in rendered\n assert \"# en: Line one\" in rendered\n assert \"# en: Line two\" in rendered\n\n def test_multiline_string_roundtrip(self) -> None:\n \"\"\"多行字符串应被渲染成合法 TOML,并可完整往返\"\"\"\n original = \"第一行\\n第二行\\n第三行\"\n rendered = render_toml(\n {\"models\": {\"embedding\": {\"query_instruction\": original}}}\n )\n parsed = tomllib.loads(rendered)\n assert parsed[\"models\"][\"embedding\"][\"query_instruction\"] == original\n assert \"\\n\" in rendered\n\n def test_multiline_string_with_quotes_and_backslashes_roundtrip(self) -> None:\n \"\"\"带引号与反斜杠的多行字符串也必须是合法 TOML\"\"\"\n original = 'prefix \"quoted\"\\npath\\\\to\\\\file\\nline3'\n rendered = render_toml(\n {\"models\": {\"embedding\": {\"document_instruction\": original}}}\n )\n parsed = tomllib.loads(rendered)\n assert parsed[\"models\"][\"embedding\"][\"document_instruction\"] == original\n"}, "a0ca0447dc98867bf243dc520b2ce4be0dc842bb": {"t": 1785773611.9698875, "n": 5780, "h": "aea27559152ef1e2", "c": "\"\"\"render_toml array-of-tables 单元测试\"\"\"\n\nimport tomllib\n\nfrom Undefined.webui.utils import parse_comment_map_text, render_toml\n\n\ndef _roundtrip(toml_str: str) -> dict: # type: ignore[type-arg]\n data = tomllib.loads(toml_str)\n rendered = render_toml(data)\n return tomllib.loads(rendered)\n\n\nclass TestRenderTomlArrayOfTables:\n def test_pool_models_roundtrip(self) -> None:\n \"\"\"[[models.chat.pool.models]] 经过 render_toml 后结构不变\"\"\"\n src = \"\"\"\n[models.chat.pool]\nenabled = true\nstrategy = \"round_robin\"\n\n[[models.chat.pool.models]]\nmodel_name = \"gpt-4o\"\napi_url = \"https://api.openai.com/v1\"\napi_key = \"sk-a\"\n\n[[models.chat.pool.models]]\nmodel_name = \"deepseek-chat\"\napi_url = \"https://api.deepseek.com/v1\"\napi_key = \"sk-b\"\n\"\"\"\n data = _roundtrip(src)\n pool = data[\"models\"][\"chat\"][\"pool\"]\n assert pool[\"enabled\"] is True\n assert pool[\"strategy\"] == \"round_robin\"\n assert len(pool[\"models\"]) == 2\n assert pool[\"models\"][0][\"model_name\"] == \"gpt-4o\"\n assert pool[\"models\"][1][\"api_key\"] == \"sk-b\"\n\n def test_empty_list_stays_inline(self) -> None:\n \"\"\"空列表仍渲染为内联数组\"\"\"\n rendered = render_toml({\"allowed\": []})\n assert \"allowed = []\" in rendered\n\n def test_scalar_list_stays_inline(self) -> None:\n \"\"\"标量列表仍渲染为内联数组\"\"\"\n data = _roundtrip(\"ids = [1, 2, 3]\")\n assert data[\"ids\"] == [1, 2, 3]\n\n def test_aot_not_rendered_as_string(self) -> None:\n \"\"\"list[dict] 不能被渲染成字符串形式\"\"\"\n src = \"\"\"\n[[items]]\nname = \"a\"\n[[items]]\nname = \"b\"\n\"\"\"\n rendered = render_toml(tomllib.loads(src))\n assert '\"{' not in rendered\n assert \"[[items]]\" in rendered\n\n def test_pool_model_request_params_roundtrip(self) -> None:\n \"\"\"模型池条目下的 request_params 嵌套结构应完整往返\"\"\"\n src = \"\"\"\n[models.chat.pool]\nenabled = true\n\n[[models.chat.pool.models]]\nmodel_name = \"gpt-5\"\napi_url = \"https://api.openai.com/v1\"\napi_key = \"sk-a\"\napi_mode = \"responses\"\nthinking_tool_call_compat = true\nresponses_tool_choice_compat = true\nresponses_force_stateless_replay = true\nreasoning_enabled = true\nreasoning_effort = \"high\"\n\n[models.chat.pool.models.request_params]\ntemperature = 0.7\n\n[models.chat.pool.models.request_params.metadata]\nsource = \"webui\"\n\n[[models.chat.pool.models.request_params.tags]]\nname = \"alpha\"\n\n[[models.chat.pool.models.request_params.tags]]\nname = \"beta\"\n\"\"\"\n data = _roundtrip(src)\n model = data[\"models\"][\"chat\"][\"pool\"][\"models\"][0]\n assert model[\"api_mode\"] == \"responses\"\n assert model[\"thinking_tool_call_compat\"] is True\n assert model[\"responses_tool_choice_compat\"] is True\n assert model[\"responses_force_stateless_replay\"] is True\n assert model[\"reasoning_enabled\"] is True\n assert model[\"reasoning_effort\"] == \"high\"\n params = model[\"request_params\"]\n assert params[\"temperature\"] == 0.7\n assert params[\"metadata\"][\"source\"] == \"webui\"\n assert [item[\"name\"] for item in params[\"tags\"]] == [\"alpha\", \"beta\"]\n\n def test_nested_aot_child_tables_roundtrip(self) -> None:\n \"\"\"数组表项下的嵌套表与子数组表不能在渲染时丢失\"\"\"\n src = \"\"\"\n[[items]]\nname = \"root\"\n\n[items.meta]\nenabled = true\n\n[[items.meta.children]]\nname = \"child-a\"\n\n[[items.meta.children]]\nname = \"child-b\"\n\"\"\"\n data = _roundtrip(src)\n item = data[\"items\"][0]\n assert item[\"meta\"][\"enabled\"] is True\n assert [child[\"name\"] for child in item[\"meta\"][\"children\"]] == [\n \"child-a\",\n \"child-b\",\n ]\n\n def test_render_comments_and_empty_table(self) -> None:\n \"\"\"带注释的空表应被完整渲染出来\"\"\"\n src = \"\"\"\n# zh: 主配置\n# en: Main section\n[models.chat.request_params]\n\"\"\"\n comments = parse_comment_map_text(src)\n rendered = render_toml(\n {\"models\": {\"chat\": {\"request_params\": {}}}}, comments=comments\n )\n assert \"# zh: 主配置\" in rendered\n assert \"[models.chat.request_params]\" in rendered\n\n def test_render_comments_before_scalar_keys(self) -> None:\n \"\"\"标量字段前应写出示例注释\"\"\"\n comments = {\n \"core.bot_qq\": {\n \"zh\": \"机器人QQ号。\",\n \"en\": \"Bot QQ number.\",\n }\n }\n rendered = render_toml({\"core\": {\"bot_qq\": 1}}, comments=comments)\n assert \"# zh: 机器人QQ号。\" in rendered\n assert \"# en: Bot QQ number.\" in rendered\n assert \"bot_qq = 1\" in rendered\n\n def test_multiline_comments_preserved(self) -> None:\n \"\"\"多行 zh/en 注释应保留为多行而非压成一行\"\"\"\n src = (\n \"# zh: 第一行\\n\"\n \"# zh: 第二行\\n\"\n \"# en: Line one\\n\"\n \"# en: Line two\\n\"\n \"enabled = false\\n\"\n )\n comments = parse_comment_map_text(src)\n rendered = render_toml({\"enabled\": False}, comments=comments)\n assert \"# zh: 第一行\" in rendered\n assert \"# zh: 第二行\" in rendered\n assert \"# en: Line one\" in rendered\n assert \"# en: Line two\" in rendered\n\n def test_multiline_string_roundtrip(self) -> None:\n \"\"\"多行字符串应被渲染成合法 TOML,并可完整往返\"\"\"\n original = \"第一行\\n第二行\\n第三行\"\n rendered = render_toml(\n {\"models\": {\"embedding\": {\"query_instruction\": original}}}\n )\n parsed = tomllib.loads(rendered)\n assert parsed[\"models\"][\"embedding\"][\"query_instruction\"] == original\n assert \"\\n\" in rendered\n\n def test_multiline_string_with_quotes_and_backslashes_roundtrip(self) -> None:\n \"\"\"带引号与反斜杠的多行字符串也必须是合法 TOML\"\"\"\n original = 'prefix \"quoted\"\\npath\\\\to\\\\file\\nline3'\n rendered = render_toml(\n {\"models\": {\"embedding\": {\"document_instruction\": original}}}\n )\n parsed = tomllib.loads(rendered)\n assert parsed[\"models\"][\"embedding\"][\"document_instruction\"] == original\n"}, "0be20a1cec27620c9fbfe393a4bf693c757ac9ad": {"t": 1785773613.63121, "n": 5229, "h": "e402a095db788e65", "c": "\"\"\"render_toml array-of-tables 单元测试\"\"\"\n\nimport tomllib\n\nfrom Undefined.webui.utils import parse_comment_map_text, render_toml\n\n\ndef _roundtrip(toml_str: str) -> dict: # type: ignore[type-arg]\n data = tomllib.loads(toml_str)\n rendered = render_toml(data)\n return tomllib.loads(rendered)\n\n\nclass TestRenderTomlArrayOfTables:\n def test_pool_models_roundtrip(self) -> None:\n \"\"\"[[models.chat.pool.models]] 经过 render_toml 后结构不变\"\"\"\n src = \"\"\"\n[models.chat.pool]\nenabled = true\nstrategy = \"round_robin\"\n\n[[models.chat.pool.models]]\nmodel_name = \"gpt-4o\"\napi_url = \"https://api.openai.com/v1\"\napi_key = \"sk-a\"\n\n[[models.chat.pool.models]]\nmodel_name = \"deepseek-chat\"\napi_url = \"https://api.deepseek.com/v1\"\napi_key = \"sk-b\"\n\"\"\"\n data = _roundtrip(src)\n pool = data[\"models\"][\"chat\"][\"pool\"]\n assert pool[\"enabled\"] is True\n assert pool[\"strategy\"] == \"round_robin\"\n assert len(pool[\"models\"]) == 2\n assert pool[\"models\"][0][\"model_name\"] == \"gpt-4o\"\n assert pool[\"models\"][1][\"api_key\"] == \"sk-b\"\n\n def test_empty_list_stays_inline(self) -> None:\n \"\"\"空列表仍渲染为内联数组\"\"\"\n rendered = render_toml({\"allowed\": []})\n assert \"allowed = []\" in rendered\n\n def test_scalar_list_stays_inline(self) -> None:\n \"\"\"标量列表仍渲染为内联数组\"\"\"\n data = _roundtrip(\"ids = [1, 2, 3]\")\n assert data[\"ids\"] == [1, 2, 3]\n\n def test_aot_not_rendered_as_string(self) -> None:\n \"\"\"list[dict] 不能被渲染成字符串形式\"\"\"\n src = \"\"\"\n[[items]]\nname = \"a\"\n[[items]]\nname = \"b\"\n\"\"\"\n rendered = render_toml(tomllib.loads(src))\n assert '\"{' not in rendered\n assert \"[[items]]\" in rendered\n\n def test_pool_model_request_params_roundtrip(self) -> None:\n \"\"\"模型池条目下的 request_params 嵌套结构应完整往返\"\"\"\n src = \"\"\"\n[models.chat.pool]\nenabled = true\n\n[[models.chat.pool.models]]\nmodel_name = \"gpt-5\"\napi_url = \"https://api.openai.com/v1\"\napi_key = \"sk-a\"\napi_mode = \"responses\"\nthinking_tool_call_compat = true\nresponses_tool_choice_compat = true\nresponses_force_stateless_replay = true\nreasoning_enabled = true\nreasoning_effort = \"high\"\n\n[models.chat.pool.models.request_params]\ntemperature = 0.7\n\n[models.chat.pool.models.request_params.metadata]\nsource = \"webui\"\n\n[[models.chat.pool.models.request_params.tags]]\nname = \"alpha\"\n\n[[models.chat.pool.models.request_params.tags]]\nname = \"beta\"\n\"\"\"\n data = _roundtrip(src)\n model = data[\"models\"][\"chat\"][\"pool\"][\"models\"][0]\n assert model[\"api_mode\"] == \"responses\"\n assert model[\"thinking_tool_call_compat\"] is True\n assert model[\"responses_tool_choice_compat\"] is True\n assert model[\"responses_force_stateless_replay\"] is True\n assert model[\"reasoning_enabled\"] is True\n assert model[\"reasoning_effort\"] == \"high\"\n params = model[\"request_params\"]\n assert params[\"temperature\"] == 0.7\n assert params[\"metadata\"][\"source\"] == \"webui\"\n assert [item[\"name\"] for item in params[\"tags\"]] == [\"alpha\", \"beta\"]\n\n def test_nested_aot_child_tables_roundtrip(self) -> None:\n \"\"\"数组表项下的嵌套表与子数组表不能在渲染时丢失\"\"\"\n src = \"\"\"\n[[items]]\nname = \"root\"\n\n[items.meta]\nenabled = true\n\n[[items.meta.children]]\nname = \"child-a\"\n\n[[items.meta.children]]\nname = \"child-b\"\n\"\"\"\n data = _roundtrip(src)\n item = data[\"items\"][0]\n assert item[\"meta\"][\"enabled\"] is True\n assert [child[\"name\"] for child in item[\"meta\"][\"children\"]] == [\n \"child-a\",\n \"child-b\",\n ]\n\n def test_render_comments_and_empty_table(self) -> None:\n \"\"\"带注释的空表应被完整渲染出来\"\"\"\n src = \"\"\"\n# zh: 主配置\n# en: Main section\n[models.chat.request_params]\n\"\"\"\n comments = parse_comment_map_text(src)\n rendered = render_toml(\n {\"models\": {\"chat\": {\"request_params\": {}}}}, comments=comments\n )\n assert \"# zh: 主配置\" in rendered\n assert \"[models.chat.request_params]\" in rendered\n\n def test_render_comments_before_scalar_keys(self) -> None:\n \"\"\"标量字段前应写出示例注释\"\"\"\n comments = {\n \"core.bot_qq\": {\n \"zh\": \"机器人QQ号。\",\n \"en\": \"Bot QQ number.\",\n }\n }\n rendered = render_toml({\"core\": {\"bot_qq\": 1}}, comments=comments)\n assert \"# zh: 机器人QQ号。\" in rendered\n assert \"# en: Bot QQ number.\" in rendered\n assert \"bot_qq = 1\" in rendered\n\n def test_multiline_string_roundtrip(self) -> None:\n \"\"\"多行字符串应被渲染成合法 TOML,并可完整往返\"\"\"\n original = \"第一行\\n第二行\\n第三行\"\n rendered = render_toml(\n {\"models\": {\"embedding\": {\"query_instruction\": original}}}\n )\n parsed = tomllib.loads(rendered)\n assert parsed[\"models\"][\"embedding\"][\"query_instruction\"] == original\n assert \"\\n\" in rendered\n\n def test_multiline_string_with_quotes_and_backslashes_roundtrip(self) -> None:\n \"\"\"带引号与反斜杠的多行字符串也必须是合法 TOML\"\"\"\n original = 'prefix \"quoted\"\\npath\\\\to\\\\file\\nline3'\n rendered = render_toml(\n {\"models\": {\"embedding\": {\"document_instruction\": original}}}\n )\n parsed = tomllib.loads(rendered)\n assert parsed[\"models\"][\"embedding\"][\"document_instruction\"] == original\n"}, "a0a20421f77748e281bfe2e195f5be4798ca4a00": {"t": 1785773614.7903802, "n": 1660, "h": "aa835a3ba9189494", "c": "\"\"\"render_toml array-of-tables 单元测试\"\"\"\n\nimport tomllib\n\nfrom Undefined.webui.utils import render_toml\n\n\ndef _roundtrip(toml_str: str) -> dict: # type: ignore[type-arg]\n data = tomllib.loads(toml_str)\n rendered = render_toml(data)\n return tomllib.loads(rendered)\n\n\nclass TestRenderTomlArrayOfTables:\n def test_pool_models_roundtrip(self) -> None:\n \"\"\"[[models.chat.pool.models]] 经过 render_toml 后结构不变\"\"\"\n src = \"\"\"\n[models.chat.pool]\nenabled = true\nstrategy = \"round_robin\"\n\n[[models.chat.pool.models]]\nmodel_name = \"gpt-4o\"\napi_url = \"https://api.openai.com/v1\"\napi_key = \"sk-a\"\n\n[[models.chat.pool.models]]\nmodel_name = \"deepseek-chat\"\napi_url = \"https://api.deepseek.com/v1\"\napi_key = \"sk-b\"\n\"\"\"\n data = _roundtrip(src)\n pool = data[\"models\"][\"chat\"][\"pool\"]\n assert pool[\"enabled\"] is True\n assert pool[\"strategy\"] == \"round_robin\"\n assert len(pool[\"models\"]) == 2\n assert pool[\"models\"][0][\"model_name\"] == \"gpt-4o\"\n assert pool[\"models\"][1][\"api_key\"] == \"sk-b\"\n\n def test_empty_list_stays_inline(self) -> None:\n \"\"\"空列表仍渲染为内联数组\"\"\"\n rendered = render_toml({\"allowed\": []})\n assert \"allowed = []\" in rendered\n\n def test_scalar_list_stays_inline(self) -> None:\n \"\"\"标量列表仍渲染为内联数组\"\"\"\n data = _roundtrip(\"ids = [1, 2, 3]\")\n assert data[\"ids\"] == [1, 2, 3]\n\n def test_aot_not_rendered_as_string(self) -> None:\n \"\"\"list[dict] 不能被渲染成字符串形式\"\"\"\n src = \"\"\"\n[[items]]\nname = \"a\"\n[[items]]\nname = \"b\"\n\"\"\"\n rendered = render_toml(tomllib.loads(src))\n assert '\"{' not in rendered\n assert \"[[items]]\" in rendered\n"}}}}