diff --git a/src/plugins/github/plugins/publish/validation.py b/src/plugins/github/plugins/publish/validation.py index dbfec6a3..44843af3 100644 --- a/src/plugins/github/plugins/publish/validation.py +++ b/src/plugins/github/plugins/publish/validation.py @@ -1,4 +1,3 @@ -import json import re from typing import Any @@ -11,6 +10,7 @@ from src.plugins.github.utils import extract_issue_info_from_issue from src.providers.constants import DOCKER_IMAGES from src.providers.docker_test import DockerPluginTest, Metadata +from src.providers.utils import load_json5_from_file from src.providers.validation import PublishType, ValidationDict, validate_info from .constants import ( @@ -65,8 +65,7 @@ async def validate_plugin_info_from_issue( test_config: str = raw_data.get("test_config", "") # 获取插件上次的数据 - with plugin_config.input_config.plugin_path.open("r", encoding="utf-8") as f: - previous_data: list[dict[str, Any]] = json.load(f) + previous_data = load_json5_from_file(plugin_config.input_config.plugin_path) # 决定是否跳过插件测试 # 因为在上一步可能已经知道了是否跳过插件测试,所以这里可以传入 @@ -148,8 +147,7 @@ async def validate_adapter_info_from_issue(issue: Issue) -> ValidationDict: ) raw_data.update(AuthorInfo.from_issue(issue).model_dump()) - with plugin_config.input_config.adapter_path.open("r", encoding="utf-8") as f: - previous_data: list[dict[str, str]] = json.load(f) + previous_data = load_json5_from_file(plugin_config.input_config.adapter_path) return validate_info(PublishType.ADAPTER, raw_data, previous_data) @@ -169,7 +167,6 @@ async def validate_bot_info_from_issue(issue: Issue) -> ValidationDict: raw_data.update(AuthorInfo.from_issue(issue).model_dump()) - with plugin_config.input_config.bot_path.open("r", encoding="utf-8") as f: - previous_data: list[dict[str, str]] = json.load(f) + previous_data = load_json5_from_file(plugin_config.input_config.bot_path) return validate_info(PublishType.BOT, raw_data, previous_data) diff --git a/tests/conftest.py b/tests/conftest.py index 260eef6f..83419779 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,3 @@ -import json from pathlib import Path from typing import TYPE_CHECKING @@ -46,53 +45,52 @@ def load_plugin(nonebug_init: None) -> set["Plugin"]: @pytest.fixture async def app(app: App, tmp_path: Path, mocker: MockerFixture): from src.plugins.github import plugin_config + from src.providers.utils import dump_json5 - adapter_path = tmp_path / "adapters.json" - with adapter_path.open("w") as f: - json.dump( - [ - { - "module_name": "module_name1", - "project_link": "project_link1", - "name": "name", - "desc": "desc", - "author_id": 1, - "homepage": "https://v2.nonebot.dev", - "tags": [], - "is_official": False, - } - ], - f, - ) - bot_path = tmp_path / "bots.json" - with bot_path.open("w") as f: - json.dump( - [ - { - "name": "name", - "desc": "desc", - "author_id": 1, - "homepage": "https://v2.nonebot.dev", - "tags": [], - "is_official": False, - } - ], - f, - ) - plugin_path = tmp_path / "plugins.json" - with plugin_path.open("w") as f: - json.dump( - [ - { - "module_name": "module_name1", - "project_link": "project_link1", - "author_id": 1, - "tags": [], - "is_official": False, - } - ], - f, - ) + adapter_path = tmp_path / "adapters.json5" + dump_json5( + adapter_path, + [ + { + "module_name": "module_name1", + "project_link": "project_link1", + "name": "name", + "desc": "desc", + "author_id": 1, + "homepage": "https://v2.nonebot.dev", + "tags": [], + "is_official": False, + } + ], + ) + bot_path = tmp_path / "bots.json5" + dump_json5( + bot_path, + [ + { + "name": "name", + "desc": "desc", + "author_id": 1, + "homepage": "https://v2.nonebot.dev", + "tags": [], + "is_official": False, + } + ], + ) + + plugin_path = tmp_path / "plugins.json5" + dump_json5( + plugin_path, + [ + { + "module_name": "module_name1", + "project_link": "project_link1", + "author_id": 1, + "tags": [], + "is_official": False, + } + ], + ) mocker.patch.object(plugin_config.input_config, "adapter_path", adapter_path) mocker.patch.object(plugin_config.input_config, "bot_path", bot_path) diff --git a/tests/github/publish/process/test_publish_check.py b/tests/github/publish/process/test_publish_check.py index fc12c3e9..00f4b1ab 100644 --- a/tests/github/publish/process/test_publish_check.py +++ b/tests/github/publish/process/test_publish_check.py @@ -54,7 +54,7 @@ async def test_bot_process_publish_check( mock_pulls_resp = mocker.MagicMock() mock_pulls_resp.parsed_data = mock_pull - with open(tmp_path / "bots.json", "w") as f: + with open(tmp_path / "bots.json5", "w") as f: json.dump([], f) check_json_data(plugin_config.input_config.bot_path, []) @@ -245,7 +245,7 @@ async def test_adapter_process_publish_check( mock_pulls_resp = mocker.MagicMock() mock_pulls_resp.parsed_data = mock_pull - with open(tmp_path / "adapters.json", "w") as f: + with open(tmp_path / "adapters.json5", "w") as f: json.dump([], f) check_json_data(plugin_config.input_config.adapter_path, []) @@ -458,7 +458,7 @@ async def test_edit_title( mock_pulls_resp = mocker.MagicMock() mock_pulls_resp.parsed_data = [mock_pull] - with open(tmp_path / "bots.json", "w") as f: + with open(tmp_path / "bots.json5", "w") as f: json.dump([], f) check_json_data(plugin_config.input_config.bot_path, []) @@ -678,7 +678,7 @@ async def test_edit_title_too_long( mock_pulls_resp = mocker.MagicMock() mock_pulls_resp.parsed_data = [] - with open(tmp_path / "bots.json", "w") as f: + with open(tmp_path / "bots.json5", "w") as f: json.dump([], f) check_json_data(plugin_config.input_config.bot_path, []) @@ -809,7 +809,7 @@ async def test_process_publish_check_not_pass( mock_list_comments_resp = mocker.MagicMock() mock_list_comments_resp.parsed_data = [mock_comment] - with open(tmp_path / "bots.json", "w") as f: + with open(tmp_path / "bots.json5", "w") as f: json.dump([], f) check_json_data(plugin_config.input_config.bot_path, []) @@ -1057,7 +1057,7 @@ async def test_skip_plugin_check( mock_pulls_resp = mocker.MagicMock() mock_pulls_resp.parsed_data = [] - with open(tmp_path / "plugins.json", "w") as f: + with open(tmp_path / "plugins.json5", "w") as f: json.dump([], f) check_json_data(plugin_config.input_config.plugin_path, []) @@ -1261,7 +1261,7 @@ async def test_convert_pull_request_to_draft( mock_list_comments_resp = mocker.MagicMock() mock_list_comments_resp.parsed_data = [mock_comment] - with open(tmp_path / "bots.json", "w") as f: + with open(tmp_path / "bots.json5", "w") as f: json.dump([], f) check_json_data(plugin_config.input_config.bot_path, []) @@ -1404,7 +1404,7 @@ async def test_process_publish_check_ready_for_review( mock_pulls_resp = mocker.MagicMock() mock_pulls_resp.parsed_data = [mock_pull] - with open(tmp_path / "bots.json", "w") as f: + with open(tmp_path / "bots.json5", "w") as f: json.dump([], f) check_json_data(plugin_config.input_config.bot_path, []) diff --git a/tests/github/publish/utils/test_publish_resolve_conflict_pull_requests.py b/tests/github/publish/utils/test_publish_resolve_conflict_pull_requests.py index 7907d365..e79381cd 100644 --- a/tests/github/publish/utils/test_publish_resolve_conflict_pull_requests.py +++ b/tests/github/publish/utils/test_publish_resolve_conflict_pull_requests.py @@ -1,4 +1,3 @@ -import json from pathlib import Path import pytest @@ -31,6 +30,7 @@ async def test_resolve_conflict_pull_requests_adapter( from src.plugins.github import plugin_config from src.plugins.github.models import GithubHandler, RepoInfo from src.plugins.github.plugins.publish.utils import resolve_conflict_pull_requests + from src.providers.utils import dump_json5 mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -49,23 +49,21 @@ async def test_resolve_conflict_pull_requests_adapter( mock_pull.labels = [mock_label] - with open(tmp_path / "adapters.json", "w", encoding="utf-8") as f: - json.dump( - [ - { - "module_name": "nonebot.adapters.onebot.v11", - "project_link": "nonebot-adapter-onebot", - "name": "OneBot V11", - "desc": "OneBot V11 协议", - "author_id": 1, - "homepage": "https://onebot.adapters.nonebot.dev/", - "tags": [], - "is_official": True, - } - ], - f, - ensure_ascii=False, - ) + dump_json5( + tmp_path / "adapters.json5", + [ + { + "module_name": "nonebot.adapters.onebot.v11", + "project_link": "nonebot-adapter-onebot", + "name": "OneBot V11", + "desc": "OneBot V11 协议", + "author_id": 1, + "homepage": "https://onebot.adapters.nonebot.dev/", + "tags": [], + "is_official": True, + } + ], + ) async with app.test_api() as ctx: adapter, bot = get_github_bot(ctx) @@ -166,6 +164,7 @@ async def test_resolve_conflict_pull_requests_bot( from src.plugins.github import plugin_config from src.plugins.github.models import GithubHandler, RepoInfo from src.plugins.github.plugins.publish.utils import resolve_conflict_pull_requests + from src.providers.utils import dump_json5 mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -184,21 +183,19 @@ async def test_resolve_conflict_pull_requests_bot( mock_pull.labels = [mock_label] - with open(tmp_path / "bots.json", "w", encoding="utf-8") as f: - json.dump( - [ - { - "name": "CoolQBot", - "desc": "基于 NoneBot2 的聊天机器人", - "author_id": 1, - "homepage": "https://github.com/he0119/CoolQBot", - "tags": [], - "is_official": False, - } - ], - f, - ensure_ascii=False, - ) + dump_json5( + tmp_path / "bots.json5", + [ + { + "name": "CoolQBot", + "desc": "基于 NoneBot2 的聊天机器人", + "author_id": 1, + "homepage": "https://github.com/he0119/CoolQBot", + "tags": [], + "is_official": False, + } + ], + ) async with app.test_api() as ctx: adapter, bot = get_github_bot(ctx) @@ -297,6 +294,7 @@ async def test_resolve_conflict_pull_requests_plugin( from src.plugins.github.models import GithubHandler, RepoInfo from src.plugins.github.plugins.publish.utils import resolve_conflict_pull_requests from src.providers.docker_test import Metadata + from src.providers.utils import dump_json5 mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -332,20 +330,18 @@ async def test_resolve_conflict_pull_requests_plugin( mock_docker = mocker.patch("src.providers.docker_test.DockerPluginTest.run") mock_docker.return_value = mock_test_result - with open(tmp_path / "plugins.json", "w", encoding="utf-8") as f: - json.dump( - [ - { - "module_name": "nonebot_plugin_treehelp", - "project_link": "nonebot-plugin-treehelp", - "author_id": 1, - "tags": [], - "is_official": True, - } - ], - f, - ensure_ascii=False, - ) + dump_json5( + tmp_path / "plugins.json5", + [ + { + "module_name": "nonebot_plugin_treehelp", + "project_link": "nonebot-plugin-treehelp", + "author_id": 1, + "tags": [], + "is_official": True, + } + ], + ) async with app.test_api() as ctx: adapter, bot = get_github_bot(ctx) @@ -447,6 +443,7 @@ async def test_resolve_conflict_pull_requests_draft( from src.plugins.github import plugin_config from src.plugins.github.models import GithubHandler, RepoInfo from src.plugins.github.plugins.publish.utils import resolve_conflict_pull_requests + from src.providers.utils import dump_json5 mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -460,21 +457,19 @@ async def test_resolve_conflict_pull_requests_draft( mock_pull.draft = True mock_pull.labels = [mock_label] - with open(tmp_path / "bots.json", "w", encoding="utf-8") as f: - json.dump( - [ - { - "name": "CoolQBot", - "desc": "基于 NoneBot2 的聊天机器人", - "author_id": 1, - "homepage": "https://github.com/he0119/CoolQBot", - "tags": [], - "is_official": False, - } - ], - f, - ensure_ascii=False, - ) + dump_json5( + tmp_path / "bots.json5", + [ + { + "name": "CoolQBot", + "desc": "基于 NoneBot2 的聊天机器人", + "author_id": 1, + "homepage": "https://github.com/he0119/CoolQBot", + "tags": [], + "is_official": False, + } + ], + ) async with app.test_api() as ctx: adapter, bot = get_github_bot(ctx) @@ -510,6 +505,7 @@ async def test_resolve_conflict_pull_requests_ref( from src.plugins.github import plugin_config from src.plugins.github.models import GithubHandler, RepoInfo from src.plugins.github.plugins.publish.utils import resolve_conflict_pull_requests + from src.providers.utils import dump_json5 mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -523,21 +519,19 @@ async def test_resolve_conflict_pull_requests_ref( mock_pull.draft = False mock_pull.labels = [mock_label] - with open(tmp_path / "bots.json", "w", encoding="utf-8") as f: - json.dump( - [ - { - "name": "CoolQBot", - "desc": "基于 NoneBot2 的聊天机器人", - "author_id": 1, - "homepage": "https://github.com/he0119/CoolQBot", - "tags": [], - "is_official": False, - } - ], - f, - ensure_ascii=False, - ) + dump_json5( + tmp_path / "bots.json5", + [ + { + "name": "CoolQBot", + "desc": "基于 NoneBot2 的聊天机器人", + "author_id": 1, + "homepage": "https://github.com/he0119/CoolQBot", + "tags": [], + "is_official": False, + } + ], + ) async with app.test_api() as ctx: adapter, bot = get_github_bot(ctx) diff --git a/tests/github/remove/process/test_remove_check.py b/tests/github/remove/process/test_remove_check.py index 7f33e873..db47ca19 100644 --- a/tests/github/remove/process/test_remove_check.py +++ b/tests/github/remove/process/test_remove_check.py @@ -1,4 +1,3 @@ -import json from pathlib import Path from inline_snapshot import snapshot @@ -30,6 +29,7 @@ async def test_process_remove_bot_check( ): """测试正常的删除流程""" from src.plugins.github import plugin_config + from src.providers.utils import dump_json5 data = [ { @@ -70,8 +70,8 @@ async def test_process_remove_bot_check( mock_pulls_resp_list = mocker.MagicMock() mock_pulls_resp_list.parsed_data = [mock_pull] - with open(tmp_path / "bots.json", "w") as f: - json.dump(data, f) + + dump_json5(tmp_path / "bots.json5", data) check_json_data(plugin_config.input_config.bot_path, data) @@ -231,6 +231,7 @@ async def test_process_remove_plugin_check( ): """测试正常的删除流程""" from src.plugins.github import plugin_config + from src.providers.utils import dump_json5 data = [ { @@ -273,8 +274,7 @@ async def test_process_remove_plugin_check( mock_pulls_resp_list = mocker.MagicMock() mock_pulls_resp_list.parsed_data = [mock_pull] - with open(tmp_path / "plugins.json", "w") as f: - json.dump(data, f) + dump_json5(tmp_path / "plugins.json5", data) check_json_data(plugin_config.input_config.plugin_path, data) @@ -436,6 +436,7 @@ async def test_process_remove_not_found_check( ): """要删除的包不在数据文件中的情况""" from src.plugins.github import plugin_config + from src.providers.utils import dump_json5 mock_subprocess_run = mocker.patch( "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock() @@ -465,8 +466,7 @@ async def test_process_remove_not_found_check( mock_pulls_resp = mocker.MagicMock() mock_pulls_resp.parsed_data = mock_pull - with open(tmp_path / "bots.json", "w") as f: - json.dump([], f) + dump_json5(tmp_path / "bots.json5", []) check_json_data(plugin_config.input_config.bot_path, []) @@ -547,6 +547,7 @@ async def test_process_remove_author_info_not_eq( ): """删除包时作者信息不相等的问题""" from src.plugins.github import plugin_config + from src.providers.utils import dump_json5 bot_data = [ { @@ -588,8 +589,7 @@ async def test_process_remove_author_info_not_eq( mock_pulls_resp = mocker.MagicMock() mock_pulls_resp.parsed_data = mock_pull - with open(tmp_path / "bots.json", "w") as f: - json.dump(bot_data, f) + dump_json5(tmp_path / "bots.json5", bot_data) check_json_data(plugin_config.input_config.bot_path, bot_data) @@ -670,6 +670,7 @@ async def test_process_remove_issue_info_not_found( ): """删除包时无法从议题获取信息的测试""" from src.plugins.github import plugin_config + from src.providers.utils import dump_json5 bot_data = [ { @@ -709,8 +710,7 @@ async def test_process_remove_issue_info_not_found( mock_pulls_resp = mocker.MagicMock() mock_pulls_resp.parsed_data = mock_pull - with open(tmp_path / "bots.json", "w") as f: - json.dump(bot_data, f) + dump_json5(tmp_path / "bots.json5", bot_data) check_json_data(plugin_config.input_config.bot_path, bot_data) diff --git a/tests/github/remove/utils/test_remove_resolve_pull_requests.py b/tests/github/remove/utils/test_remove_resolve_pull_requests.py index beecba64..4744861b 100644 --- a/tests/github/remove/utils/test_remove_resolve_pull_requests.py +++ b/tests/github/remove/utils/test_remove_resolve_pull_requests.py @@ -1,6 +1,4 @@ -import json from pathlib import Path -from typing import Any import pytest from inline_snapshot import snapshot @@ -11,6 +9,7 @@ from tests.github.utils import ( MockIssue, MockUser, + check_json_data, generate_issue_body_remove, get_github_bot, ) @@ -25,11 +24,6 @@ def get_issue_labels(mocker: MockerFixture, labels: list[str]): return mocker_labels -def check_json_data(file: Path, data: Any) -> None: - with open(file, encoding="utf-8") as f: - assert json.load(f) == data - - @pytest.fixture def mock_pull(mocker: MockerFixture): mock_pull = mocker.MagicMock() @@ -45,6 +39,7 @@ async def test_resolve_conflict_pull_requests_bot( from src.plugins.github import plugin_config from src.plugins.github.models import GithubHandler, RepoInfo from src.plugins.github.plugins.remove.utils import resolve_conflict_pull_requests + from src.providers.utils import dump_json5 mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -62,21 +57,19 @@ async def test_resolve_conflict_pull_requests_bot( mock_pull.labels = get_issue_labels(mocker, ["Bot", "Remove"]) - with open(tmp_path / "bots.json", "w", encoding="utf-8") as f: - json.dump( - [ - { - "name": "CoolQBot", - "desc": "基于 NoneBot2 的聊天机器人", - "author_id": 1, - "homepage": "https://github.com/he0119/CoolQBot", - "tags": [], - "is_official": False, - } - ], - f, - ensure_ascii=False, - ) + dump_json5( + tmp_path / "bots.json5", + [ + { + "name": "CoolQBot", + "desc": "基于 NoneBot2 的聊天机器人", + "author_id": 1, + "homepage": "https://github.com/he0119/CoolQBot", + "tags": [], + "is_official": False, + } + ], + ) async with app.test_api() as ctx: adapter, bot = get_github_bot(ctx) @@ -150,6 +143,7 @@ async def test_resolve_conflict_pull_requests_plugin( from src.plugins.github import plugin_config from src.plugins.github.models import GithubHandler, RepoInfo from src.plugins.github.plugins.remove.utils import resolve_conflict_pull_requests + from src.providers.utils import dump_json5 mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -173,20 +167,18 @@ async def test_resolve_conflict_pull_requests_plugin( mock_list_comments_resp = mocker.MagicMock() mock_list_comments_resp.parsed_data = [mock_comment] - with open(tmp_path / "plugins.json", "w", encoding="utf-8") as f: - json.dump( - [ - { - "module_name": "nonebot_plugin_treehelp", - "project_link": "nonebot-plugin-treehelp", - "author_id": 1, - "tags": [], - "is_official": True, - } - ], - f, - ensure_ascii=False, - ) + dump_json5( + tmp_path / "plugins.json5", + [ + { + "module_name": "nonebot_plugin_treehelp", + "project_link": "nonebot-plugin-treehelp", + "author_id": 1, + "tags": [], + "is_official": True, + } + ], + ) async with app.test_api() as ctx: adapter, bot = get_github_bot(ctx) @@ -261,6 +253,7 @@ async def test_resolve_conflict_pull_requests_not_found( from src.plugins.github import plugin_config from src.plugins.github.models import GithubHandler, RepoInfo from src.plugins.github.plugins.remove.utils import resolve_conflict_pull_requests + from src.providers.utils import dump_json5 mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -284,12 +277,7 @@ async def test_resolve_conflict_pull_requests_not_found( mock_list_comments_resp = mocker.MagicMock() mock_list_comments_resp.parsed_data = [mock_comment] - with open(tmp_path / "plugins.json", "w", encoding="utf-8") as f: - json.dump( - [], - f, - ensure_ascii=False, - ) + dump_json5(tmp_path / "plugins.json5", []) async with app.test_api() as ctx: adapter, bot = get_github_bot(ctx) diff --git a/tests/github/remove/utils/test_update_file.py b/tests/github/remove/utils/test_update_file.py index e2cf5ee1..a571eca0 100644 --- a/tests/github/remove/utils/test_update_file.py +++ b/tests/github/remove/utils/test_update_file.py @@ -1,4 +1,3 @@ -import json from pathlib import Path from nonebug import App @@ -13,6 +12,7 @@ async def test_update_file( ) -> None: from src.plugins.github import plugin_config from src.plugins.github.plugins.remove.utils import update_file + from src.providers.utils import dump_json5 from src.providers.validation.models import PublishType data = [ @@ -33,8 +33,7 @@ async def test_update_file( "is_official": False, }, ] - with open(tmp_path / "bots.json", "w", encoding="utf-8") as f: - json.dump(data, f) + dump_json5(tmp_path / "bots.json5", data) check_json_data(plugin_config.input_config.bot_path, data)