From 7d82d30889545bf96b94ce5f02888e922abd21d6 Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Sat, 9 May 2026 17:58:31 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E4=BD=BFsdk=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E7=AC=A6=E5=90=88=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pytests/test_plugin_runtime.py | 89 ++++++++++++++++++++++++- src/plugin_runtime/capabilities/data.py | 10 +-- 2 files changed, 91 insertions(+), 8 deletions(-) diff --git a/pytests/test_plugin_runtime.py b/pytests/test_plugin_runtime.py index c8daff96..4cfef8da 100644 --- a/pytests/test_plugin_runtime.py +++ b/pytests/test_plugin_runtime.py @@ -2890,22 +2890,105 @@ class TestIntegration: monkeypatch.setattr(real_database_service, "db_get", fake_db_get) monkeypatch.setattr(real_db_models, "DemoTable", DummyModel, raising=False) - result = await integration_module.PluginRuntimeManager._cap_database_get( + manager = object.__new__(integration_module.PluginRuntimeManager) + result = await manager._cap_database_get( "plugin_a", "database.get", { - "table": "DemoTable", + "model_name": "DemoTable", "filters": {"status": "active"}, "limit": 5, }, ) - assert result == {"success": True, "result": [{"id": 1}]} + assert result == [{"id": 1}] assert captured["model_class"] is DummyModel assert captured["filters"] == {"status": "active"} assert captured["limit"] == 5 assert captured["single_result"] is False + @pytest.mark.asyncio + async def test_cap_database_get_response_is_not_double_wrapped(self, monkeypatch): + from src.plugin_runtime import integration as integration_module + import src.common.database.database_model as real_db_models + from src.plugin_runtime.host.capability_service import CapabilityService + from src.plugin_runtime.protocol.envelope import CapabilityRequestPayload, Envelope, MessageType + from src.services import database_service as real_database_service + + class AllowAllAuthorization: + def check_capability(self, plugin_id, capability): + return True, "" + + class DummyModel: + pass + + async def fake_db_get(model_class, filters=None, limit=None, order_by=None, single_result=False): + return {"id": 1, "full_path": "E:\\test.png"} + + monkeypatch.setattr(real_database_service, "db_get", fake_db_get) + monkeypatch.setattr(real_db_models, "DemoTable", DummyModel, raising=False) + + manager = object.__new__(integration_module.PluginRuntimeManager) + service = CapabilityService(AllowAllAuthorization()) + service.register_capability("database.get", manager._cap_database_get) + + request = Envelope( + request_id=1, + message_type=MessageType.REQUEST, + method="cap.call", + plugin_id="plugin_a", + payload=CapabilityRequestPayload( + capability="database.get", + args={"model_name": "DemoTable", "single_result": True}, + ).model_dump(), + ) + + response = await service.handle_capability_request(request) + + assert response.payload == { + "success": True, + "result": {"id": 1, "full_path": "E:\\test.png"}, + } + + @pytest.mark.asyncio + async def test_cap_database_success_handlers_return_raw_results(self, monkeypatch): + from src.plugin_runtime import integration as integration_module + import src.common.database.database_model as real_db_models + from src.services import database_service as real_database_service + + class DummyModel: + pass + + async def fake_db_get(**kwargs): + return [{"id": 1}] + + async def fake_db_save(**kwargs): + return {"id": 2} + + async def fake_db_delete(**kwargs): + return 3 + + async def fake_db_count(**kwargs): + return 4 + + monkeypatch.setattr(real_database_service, "db_get", fake_db_get) + monkeypatch.setattr(real_database_service, "db_save", fake_db_save) + monkeypatch.setattr(real_database_service, "db_delete", fake_db_delete) + monkeypatch.setattr(real_database_service, "db_count", fake_db_count) + monkeypatch.setattr(real_db_models, "DemoTable", DummyModel, raising=False) + + manager = object.__new__(integration_module.PluginRuntimeManager) + base_args = {"model_name": "DemoTable"} + + assert await manager._cap_database_query("plugin_a", "database.query", base_args) == [{"id": 1}] + assert await manager._cap_database_save( + "plugin_a", "database.save", {**base_args, "data": {"name": "demo"}} + ) == {"id": 2} + assert await manager._cap_database_delete( + "plugin_a", "database.delete", {**base_args, "filters": {"id": 2}} + ) == 3 + assert await manager._cap_database_count("plugin_a", "database.count", base_args) == 4 + @pytest.mark.asyncio async def test_component_enable_rejects_ambiguous_short_name(self, monkeypatch): from src.plugin_runtime import integration as integration_module diff --git a/src/plugin_runtime/capabilities/data.py b/src/plugin_runtime/capabilities/data.py index 616dc9b3..8762ace4 100644 --- a/src/plugin_runtime/capabilities/data.py +++ b/src/plugin_runtime/capabilities/data.py @@ -110,7 +110,7 @@ class RuntimeDataCapabilityMixin: result = await database_service.db_count(model_class=model_class, filters=args.get("filters")) else: return {"success": False, "error": f"不支持的 query_type: {query_type}"} - return {"success": True, "result": result} + return result except Exception as e: logger.error(f"[cap.database.query] 执行失败: {e}", exc_info=True) return {"success": False, "error": str(e)} @@ -136,7 +136,7 @@ class RuntimeDataCapabilityMixin: key_field=args.get("key_field"), key_value=args.get("key_value"), ) - return {"success": True, "result": result} + return result except Exception as e: logger.error(f"[cap.database.save] 执行失败: {e}", exc_info=True) return {"success": False, "error": str(e)} @@ -162,7 +162,7 @@ class RuntimeDataCapabilityMixin: order_by=args.get("order_by"), single_result=args.get("single_result", False), ) - return {"success": True, "result": result} + return result except Exception as e: logger.error(f"[cap.database.get] 执行失败: {e}", exc_info=True) return {"success": False, "error": str(e)} @@ -185,7 +185,7 @@ class RuntimeDataCapabilityMixin: return {"success": False, "error": f"未找到数据模型: {model_name}"} result = await database_service.db_delete(model_class=model_class, filters=filters) - return {"success": True, "result": result} + return result except Exception as e: logger.error(f"[cap.database.delete] 执行失败: {e}", exc_info=True) return {"success": False, "error": str(e)} @@ -205,7 +205,7 @@ class RuntimeDataCapabilityMixin: return {"success": False, "error": f"未找到数据模型: {model_name}"} result = await database_service.db_count(model_class=model_class, filters=args.get("filters")) - return {"success": True, "count": result} + return result except Exception as e: logger.error(f"[cap.database.count] 执行失败: {e}", exc_info=True) return {"success": False, "error": str(e)}