From 3eccbca2c9645c5f7e2f4efa70b89d6ae79a2b99 Mon Sep 17 00:00:00 2001 From: LIghtJUNction Date: Tue, 31 Mar 2026 20:15:28 +0800 Subject: [PATCH] refactor(i18n): improve type safety and code quality in i18n_utils - Add type guard function for str-keyed dicts - Add I18nGroup TypedDict for better type checking - Replace isinstance checks with TypeGuard-based validation - Improve type annotations throughout --- astrbot/core/config/i18n_utils.py | 64 +++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/astrbot/core/config/i18n_utils.py b/astrbot/core/config/i18n_utils.py index d8bb5045a..d277b275a 100644 --- a/astrbot/core/config/i18n_utils.py +++ b/astrbot/core/config/i18n_utils.py @@ -4,7 +4,16 @@ 提供配置元数据的国际化键转换功能 """ -from typing import Any +from typing import TypedDict, TypeGuard + + +def _is_str_keyed_dict(value: object) -> TypeGuard[dict[str, object]]: + return isinstance(value, dict) and all(isinstance(key, str) for key in value) + + +class I18nGroup(TypedDict): + name: str + metadata: dict[str, object] class ConfigMetadataI18n: @@ -30,7 +39,7 @@ class ConfigMetadataI18n: return f"{group}.{section}.{attr}" @staticmethod - def convert_to_i18n_keys(metadata: dict[str, Any]) -> dict[str, Any]: + def convert_to_i18n_keys(metadata: dict[str, object]) -> dict[str, I18nGroup]: """ 将配置元数据转换为使用国际化键 @@ -40,22 +49,22 @@ class ConfigMetadataI18n: Returns: 使用国际化键的配置元数据字典 """ - result = {} + result: dict[str, I18nGroup] = {} def convert_items( - group: str, section: str, items: dict[str, Any], prefix: str = "" - ) -> dict[str, Any]: - items_result: dict[str, Any] = {} + group: str, section: str, items: dict[str, object], prefix: str = "" + ) -> dict[str, object]: + items_result: dict[str, object] = {} for field_key, field_data in items.items(): - if not isinstance(field_data, dict): + if not _is_str_keyed_dict(field_data): items_result[field_key] = field_data continue field_name = field_key field_path = f"{prefix}.{field_name}" if prefix else field_name - field_result = { + field_result: dict[str, object] = { key: value for key, value in field_data.items() if key not in {"description", "hint", "labels", "name"} @@ -72,18 +81,18 @@ class ConfigMetadataI18n: if "name" in field_data: field_result["name"] = f"{group}.{section}.{field_path}.name" - if "items" in field_data and isinstance(field_data["items"], dict): + field_items = field_data.get("items") + if _is_str_keyed_dict(field_items): field_result["items"] = convert_items( - group, section, field_data["items"], field_path + group, section, field_items, field_path ) - if "template_schema" in field_data and isinstance( - field_data["template_schema"], dict - ): + template_schema = field_data.get("template_schema") + if _is_str_keyed_dict(template_schema): field_result["template_schema"] = convert_items( group, section, - field_data["template_schema"], + template_schema, f"{field_path}.template_schema", ) @@ -92,13 +101,25 @@ class ConfigMetadataI18n: return items_result for group_key, group_data in metadata.items(): - group_result = { + if not _is_str_keyed_dict(group_data): + continue + + group_metadata: dict[str, object] = {} + group_result: I18nGroup = { "name": f"{group_key}.name", - "metadata": {}, + "metadata": group_metadata, } - for section_key, section_data in group_data.get("metadata", {}).items(): - section_result = { + metadata_sections = group_data.get("metadata") + if not _is_str_keyed_dict(metadata_sections): + result[group_key] = group_result + continue + + for section_key, section_data in metadata_sections.items(): + if not _is_str_keyed_dict(section_data): + continue + + section_result: dict[str, object] = { key: value for key, value in section_data.items() if key not in {"description", "hint", "labels", "name"} @@ -108,12 +129,13 @@ class ConfigMetadataI18n: if "hint" in section_data: section_result["hint"] = f"{group_key}.{section_key}.hint" - if "items" in section_data and isinstance(section_data["items"], dict): + section_items = section_data.get("items") + if _is_str_keyed_dict(section_items): section_result["items"] = convert_items( - group_key, section_key, section_data["items"] + group_key, section_key, section_items ) - group_result["metadata"][section_key] = section_result + group_metadata[section_key] = section_result result[group_key] = group_result