From 61948a9dee8ada0d01e1fe7b71c4fe3e2c0d2fb6 Mon Sep 17 00:00:00 2001 From: yiwuerxin <72354522+yiwuerxin@users.noreply.github.com> Date: Tue, 28 Jul 2026 00:40:56 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix(self-update):=20=E5=89=8D=E7=BC=80?= =?UTF-8?q?=E4=BB=A3=E7=90=86URL=E8=B5=B0pip=E9=81=BF=E5=85=8Duv=20panic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-proxy 风格前缀代理产生含多个 :// 的套娃 URL,uv 解析 git+套娃URL@ref 时其 URL 解析器 panic (AmbiguousAuthority)。检测套娃 URL (count(://) > 1) 时走 pip;干净 URL (直连/CNB镜像) 保留 uv。 新增 test_build_self_update_command_uses_pip_for_prefix_proxy。 --- pyproject.toml | 4 ++-- src/nonebot_plugin_mimo_console/store.py | 12 +++++++++++- tests/test_store.py | 20 ++++++++++++++++++++ uv.lock | 2 +- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ef4c6c3..938672b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "nonebot-plugin-mimo-console" -version = "0.1.6" +version = "0.1.7" description = "A premium WebUI management console for NoneBot2" readme = "README.md" requires-python = ">=3.10" @@ -54,7 +54,7 @@ requires = ["uv_build>=0.10.0,<0.12.0"] build-backend = "uv_build" [tool.bumpversion] -current_version = "0.1.6" +current_version = "0.1.7" commit = true message = "chore: 发布 v{new_version}" tag = true diff --git a/src/nonebot_plugin_mimo_console/store.py b/src/nonebot_plugin_mimo_console/store.py index 78784ee..335846a 100644 --- a/src/nonebot_plugin_mimo_console/store.py +++ b/src/nonebot_plugin_mimo_console/store.py @@ -106,7 +106,17 @@ def build_self_update_command( if not SAFE_NAME_RE.fullmatch(project_name): raise ValueError("插件包名不合法") uv = uv_executable if uv_executable is not None else _find_uv_executable() - if uv and (project_root / "pyproject.toml").is_file(): + # gh-proxy 风格前缀会把代理前缀拼在 GitHub URL 之前,形成含多个 "://" 的套娃 URL + # (如 https://gh-proxy.com/https://github.com/...)。uv 解析 + # "git+<套娃URL>@" 时其 URL 解析器会 panic(AmbiguousAuthority), + # 而 pip 直接交给 git clone,对套娃 URL 鲁棒。因此前缀代理走 pip; + # 干净 URL(直连或 CNB 镜像仓库地址)仍走 uv。 + is_prefix_proxy_url = git_url.count("://") > 1 + if ( + uv + and (project_root / "pyproject.toml").is_file() + and not is_prefix_proxy_url + ): return [ uv, "add", diff --git a/tests/test_store.py b/tests/test_store.py index 2f2b6aa..ff64684 100644 --- a/tests/test_store.py +++ b/tests/test_store.py @@ -68,6 +68,26 @@ def test_build_self_update_command_falls_back_to_pip(self) -> None: command[-1], "git+https://github.com/MimoKit/nonebot-plugin-mimo-console.git" ) + def test_build_self_update_command_uses_pip_for_prefix_proxy(self) -> None: + # gh-proxy 风格前缀会把代理前缀拼在 GitHub URL 前,形成含多个 "://" 的套娃 + # URL(如 https://gh-proxy.com/https://github.com/...)。即便项目用 uv 管理, + # 此种 URL 也必须走 pip——uv 解析 "git+<套娃URL>@" 会让解析器 panic。 + with tempfile.TemporaryDirectory() as temp: + root = Path(temp) + (root / "pyproject.toml").write_text("[project]\nname='bot'\n", encoding="utf-8") + command = store.build_self_update_command( + root, + "nonebot-plugin-mimo-console", + "https://gh-proxy.com/https://github.com/MimoKit/nonebot-plugin-mimo-console.git", + uv_executable="/usr/bin/uv", + ) + self.assertNotEqual(command[0], "/usr/bin/uv") + self.assertEqual(command[:4], [sys.executable, "-m", "pip", "install"]) + self.assertEqual( + command[-1], + "git+https://gh-proxy.com/https://github.com/MimoKit/nonebot-plugin-mimo-console.git", + ) + def test_registry_item_validation(self) -> None: valid = { "module_name": "nonebot_plugin_status", diff --git a/uv.lock b/uv.lock index c44f34d..a0c2734 100644 --- a/uv.lock +++ b/uv.lock @@ -832,7 +832,7 @@ wheels = [ [[package]] name = "nonebot-plugin-mimo-console" -version = "0.1.6" +version = "0.1.7" source = { editable = "." } dependencies = [ { name = "httpx" }, From 2c2a22a2da83da43558dc9f566786e730915cf08 Mon Sep 17 00:00:00 2001 From: yiwuerxin <72354522+yiwuerxin@users.noreply.github.com> Date: Tue, 28 Jul 2026 00:45:22 +0800 Subject: [PATCH 2/2] style: apply ruff format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit store.py: build_self_update_command 的 if 条件压单行(本 PR 代码)。api.py: 顺带 format master 既有 _re.match/raw_url(上游 format 债,非本 PR 引入,让 prek --all-files 过)。 --- src/nonebot_plugin_mimo_console/api.py | 9 +++++---- src/nonebot_plugin_mimo_console/store.py | 6 +----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/nonebot_plugin_mimo_console/api.py b/src/nonebot_plugin_mimo_console/api.py index 8e1fd57..01b2efb 100644 --- a/src/nonebot_plugin_mimo_console/api.py +++ b/src/nonebot_plugin_mimo_console/api.py @@ -267,9 +267,8 @@ async def store_plugin_readme( if not homepage: return {"ok": False, "content": "", "detail": "该插件未提供主页链接"} import re as _re - match = _re.match( - r"https?://github\.com/([^/]+)/([^/?#]+)", homepage - ) + + match = _re.match(r"https?://github\.com/([^/]+)/([^/?#]+)", homepage) if not match: return {"ok": False, "content": "", "detail": "主页不是 GitHub 仓库,无法获取 README"} owner, repo = match.group(1), match.group(2).removesuffix(".git") @@ -282,7 +281,9 @@ async def store_plugin_readme( if proxy and not is_mirror_repo(proxy): raw_url = f"{proxy}https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{filename}" else: - raw_url = f"https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{filename}" + raw_url = ( + f"https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{filename}" + ) try: resp = await client.get( raw_url, diff --git a/src/nonebot_plugin_mimo_console/store.py b/src/nonebot_plugin_mimo_console/store.py index 335846a..d042489 100644 --- a/src/nonebot_plugin_mimo_console/store.py +++ b/src/nonebot_plugin_mimo_console/store.py @@ -112,11 +112,7 @@ def build_self_update_command( # 而 pip 直接交给 git clone,对套娃 URL 鲁棒。因此前缀代理走 pip; # 干净 URL(直连或 CNB 镜像仓库地址)仍走 uv。 is_prefix_proxy_url = git_url.count("://") > 1 - if ( - uv - and (project_root / "pyproject.toml").is_file() - and not is_prefix_proxy_url - ): + if uv and (project_root / "pyproject.toml").is_file() and not is_prefix_proxy_url: return [ uv, "add",