refactor(cli): 重构清屏和which命令实现

1. 提取清屏、设置环境变量、命令查找逻辑到system任务模块
2. 统一命令行工具的任务实现方式,减少重复代码
3. 修正pyproject.toml中的cli命令名拼写错误
4. 移除过时的测试用例代码
This commit is contained in:
2026-06-26 23:27:45 +08:00
parent 194cf3c343
commit 10bbc07118
6 changed files with 46 additions and 82 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ version = "0.2.5"
[project.scripts]
autofmt = "pyflowx.cli.autofmt:main"
bumpversion = "pyflowx.cli.bumpversion:main"
cls = "pyflowx.cli.clearscreen:main"
clr = "pyflowx.cli.clearscreen:main"
emlman = "pyflowx.cli.emlmanager:main"
envdev = "pyflowx.cli.envdev:main"
envpy = "pyflowx.cli.envpy:main"
+2 -6
View File
@@ -6,14 +6,10 @@
from __future__ import annotations
import pyflowx as px
from pyflowx.conditions import Constants
from pyflowx.tasks.system import CLR
def main() -> None:
"""清屏工具主函数."""
graph = px.Graph.from_specs([
px.TaskSpec("cls_win", cmd=["cmd", "/c", "cls"], conditions=(lambda: Constants.IS_WINDOWS,)),
px.TaskSpec("cls_unix", cmd=["clear"], conditions=(lambda: not Constants.IS_WINDOWS,)),
px.TaskSpec("cls_ascii", fn=lambda: print("\033[2J\033[H", end="")),
])
graph = px.Graph.from_specs([CLR()])
px.run(graph, strategy="thread")
+5 -35
View File
@@ -6,46 +6,16 @@
from __future__ import annotations
import argparse
import shutil
from pathlib import Path
import pyflowx as px
def which_command(command: str) -> Path | None:
"""查找命令路径.
Parameters
----------
command : str
命令名称
Returns
-------
Path | None
命令路径, 如果未找到则返回 None
"""
cmd_path = shutil.which(command)
if cmd_path:
print(f"匹配路径: - {cmd_path}")
return Path(cmd_path)
else:
print(f"{command}: 未找到")
return None
from pyflowx.tasks.system import WHICH
def main() -> None:
"""命令查找工具主函数."""
parser = argparse.ArgumentParser(
description="Which - 命令查找工具",
usage="which <command> [command ...]",
)
parser.add_argument(
"commands",
type=str,
nargs="+",
help="要查找的命令名称 (如: python pip node npm git uv rustc cargo)",
)
parser = argparse.ArgumentParser(description="Which - 命令查找工具")
parser.add_argument("commands", nargs="+", help="要查找的命令名称, 如: python ls ps gcc...")
args = parser.parse_args()
graph = px.Graph.from_specs([px.TaskSpec(f"which_{cmd}", fn=which_command, args=(cmd,)) for cmd in args.commands])
graph = px.Graph.from_specs([WHICH(cmd) for cmd in args.commands])
px.run(graph, strategy="thread")
View File
+38
View File
@@ -0,0 +1,38 @@
import pyflowx as px
def CLR():
"""清屏."""
import subprocess
from pyflowx.conditions import Constants
return px.TaskSpec(
"clear_screen", fn=lambda: subprocess.run(["cls"] if Constants.IS_WINDOWS else ["clear"], check=True)
)
def SETENV(name: str, value: str):
"""设置环境变量."""
import os
return px.TaskSpec("set_env", fn=lambda: os.environ.setdefault(name, value))
def WHICH(cmd: str):
"""查找命令路径."""
import subprocess
def find_command() -> str | None:
"""查找命令并返回路径, 找不到时返回 None."""
result = subprocess.run(["which", cmd], capture_output=True, text=True, check=False)
if result.returncode == 0:
path = result.stdout.strip()
print(f"{cmd:<8} -> {path}")
return path
print(f"{cmd:<8} -> 未找到命令")
return None
return px.TaskSpec(f"which_{cmd}", fn=find_command)
-40
View File
@@ -3,7 +3,6 @@
from __future__ import annotations
import shutil
from pathlib import Path
from unittest.mock import patch
import pytest
@@ -12,45 +11,6 @@ import pyflowx as px
from pyflowx.cli import which
# ---------------------------------------------------------------------- #
# which_command
# ---------------------------------------------------------------------- #
class TestWhichCommand:
"""Test which_command function."""
def test_returns_path_when_command_found(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Should return Path when command is found."""
with patch.object(shutil, "which", return_value="/usr/bin/python"):
result = which.which_command("python")
assert result == Path("/usr/bin/python")
captured = capsys.readouterr()
assert "匹配路径" in captured.out
assert "/usr/bin/python" in captured.out
def test_returns_none_when_command_not_found(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Should return None when command is not found."""
with patch.object(shutil, "which", return_value=None):
result = which.which_command("nonexistent_cmd")
assert result is None
captured = capsys.readouterr()
assert "未找到" in captured.out
assert "nonexistent_cmd" in captured.out
def test_prints_match_path_on_success(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Should print '匹配路径: - <path>' on success."""
with patch.object(shutil, "which", return_value="C:\\Python\\python.exe"):
_ = which.which_command("python")
captured = capsys.readouterr()
assert "匹配路径: - C:\\Python\\python.exe" in captured.out
def test_prints_not_found_on_failure(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Should print '<command>: 未找到' on failure."""
with patch.object(shutil, "which", return_value=None):
_ = which.which_command("missing")
captured = capsys.readouterr()
assert "missing: 未找到" in captured.out
# ---------------------------------------------------------------------- #
# main function
# ---------------------------------------------------------------------- #