refactor(cli): 统一使用@px.task装饰器定义任务,重构任务注册和别名管理
1. 将folderzip/folderback/gittool中的旧TaskSpec定义替换为@px.task装饰器 2. 重构pymake模块,将maturin_build_cmd转为常量定义,合并别名配置 3. 精简测试文件中的冗余测试用例
This commit is contained in:
@@ -66,19 +66,10 @@ def backup_folder(src: str, dst: str, max_zip: int = 5) -> None:
|
|||||||
zip_target(src_path, dst_path, max_zip)
|
zip_target(src_path, dst_path, max_zip)
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
@px.task
|
||||||
# TaskSpec 定义
|
def folderback_default() -> None:
|
||||||
# ============================================================================
|
"""备份当前目录到 ./backup."""
|
||||||
|
backup_folder(".", "./backup", 5)
|
||||||
folderback_default: px.TaskSpec = px.TaskSpec(
|
|
||||||
"folderback_default",
|
|
||||||
fn=lambda: backup_folder(".", "./backup", 5),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# CLI Runner
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
|||||||
@@ -57,16 +57,10 @@ def zip_folders(cwd: str = ".") -> None:
|
|||||||
archive_folder(dir_path)
|
archive_folder(dir_path)
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
@px.task
|
||||||
# TaskSpec 定义
|
def folderzip_default() -> None:
|
||||||
# ============================================================================
|
"""压缩当前目录下的所有文件夹."""
|
||||||
|
zip_folders(".")
|
||||||
folderzip_default: px.TaskSpec = px.TaskSpec("folderzip_default", fn=lambda: zip_folders("."))
|
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# CLI Runner
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
|||||||
@@ -46,7 +46,12 @@ def init_sub_dirs() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
isub: px.TaskSpec = px.TaskSpec("isub", fn=init_sub_dirs)
|
@px.task(name="isub")
|
||||||
|
def isub() -> None:
|
||||||
|
"""初始化子目录的Git仓库."""
|
||||||
|
init_sub_dirs()
|
||||||
|
|
||||||
|
|
||||||
push: px.TaskSpec = px.TaskSpec("push", cmd=["git", "push"])
|
push: px.TaskSpec = px.TaskSpec("push", cmd=["git", "push"])
|
||||||
pull: px.TaskSpec = px.TaskSpec("pull", cmd=["git", "pull"])
|
pull: px.TaskSpec = px.TaskSpec("pull", cmd=["git", "pull"])
|
||||||
kill_tgit: px.TaskSpec = px.TaskSpec("task_kill", cmd=["taskkill", "/f", "/t", "/im", "tgitcache.exe"])
|
kill_tgit: px.TaskSpec = px.TaskSpec("task_kill", cmd=["taskkill", "/f", "/t", "/im", "tgitcache.exe"])
|
||||||
@@ -73,11 +78,11 @@ def main() -> None:
|
|||||||
px.TaskSpec("add", cmd=["git", "add", "."], conditions=(lambda _: has_files(),)),
|
px.TaskSpec("add", cmd=["git", "add", "."], conditions=(lambda _: has_files(),)),
|
||||||
px.TaskSpec("commit", cmd=["git", "commit", "-m", "chore: update"], depends_on=("add",)),
|
px.TaskSpec("commit", cmd=["git", "commit", "-m", "chore: update"], depends_on=("add",)),
|
||||||
]),
|
]),
|
||||||
# 清理
|
# 清理(chain: clean → status)
|
||||||
"c": px.Graph.from_specs([
|
"c": px.Graph().chain(
|
||||||
px.TaskSpec("clean", cmd=["git", "clean", "-xfd", *EXCLUDE_CMDS]),
|
px.TaskSpec("clean", cmd=["git", "clean", "-xfd", *EXCLUDE_CMDS]),
|
||||||
px.TaskSpec("status", cmd=["git", "status", "--porcelain"], depends_on=("clean",)),
|
px.TaskSpec("status", cmd=["git", "status", "--porcelain"]),
|
||||||
]),
|
),
|
||||||
# 初始化、添加并提交
|
# 初始化、添加并提交
|
||||||
"i": px.Graph.from_specs([
|
"i": px.Graph.from_specs([
|
||||||
px.TaskSpec("init", cmd=["git", "init"], conditions=(lambda _: not_has_git_repo(),)),
|
px.TaskSpec("init", cmd=["git", "init"], conditions=(lambda _: not_has_git_repo(),)),
|
||||||
|
|||||||
+32
-50
@@ -9,25 +9,14 @@ from __future__ import annotations
|
|||||||
import pyflowx as px
|
import pyflowx as px
|
||||||
from pyflowx.conditions import Constants
|
from pyflowx.conditions import Constants
|
||||||
|
|
||||||
|
MATURIN_BUILD_COMMAND = ["maturin", "build", "-r"]
|
||||||
def maturin_build_cmd() -> list[str]:
|
|
||||||
"""获取 maturin 构建命令(根据平台自动添加参数).
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
list[str]
|
|
||||||
完整的 maturin 构建命令列表.
|
|
||||||
"""
|
|
||||||
command = ["maturin", "build", "-r"].copy()
|
|
||||||
if Constants.IS_WINDOWS:
|
if Constants.IS_WINDOWS:
|
||||||
command.extend(["--target", "x86_64-win7-windows-msvc", "-Zbuild-std", "-i", "python3.8"])
|
MATURIN_BUILD_COMMAND.extend(["--target", "x86_64-win7-windows-msvc", "-Zbuild-std", "-i", "python3.8"])
|
||||||
return command
|
|
||||||
|
|
||||||
|
|
||||||
# 扁平注册所有任务(px.cmd 自动从命令前两段推导 name)
|
# 扁平注册所有任务(px.cmd 自动从命令前两段推导 name)
|
||||||
tasks: list[px.TaskSpec] = [
|
tasks: list[px.TaskSpec] = [
|
||||||
px.cmd(["uv", "build"]),
|
px.cmd(["uv", "build"]),
|
||||||
px.cmd(maturin_build_cmd(), name="maturin_build"),
|
px.cmd(MATURIN_BUILD_COMMAND),
|
||||||
px.cmd(["uv", "sync"]),
|
px.cmd(["uv", "sync"]),
|
||||||
px.cmd(["gitt", "c"], name="git_clean"),
|
px.cmd(["gitt", "c"], name="git_clean"),
|
||||||
px.cmd(
|
px.cmd(
|
||||||
@@ -42,20 +31,40 @@ tasks: list[px.TaskSpec] = [
|
|||||||
["pytest", "--cov", "-n", "8", "--dist", "loadfile", "--tb=short", "-v", "--color=yes", "--durations=10"],
|
["pytest", "--cov", "-n", "8", "--dist", "loadfile", "--tb=short", "-v", "--color=yes", "--durations=10"],
|
||||||
name="test_coverage",
|
name="test_coverage",
|
||||||
),
|
),
|
||||||
px.cmd(["pyrefly", "check", "."], name="pyrefly_check"),
|
px.cmd(["pyrefly", "check", "."]),
|
||||||
px.cmd(["git", "add", "-A"], name="git_add_all"),
|
px.cmd(["git", "add", "-A"], name="git_add_all"),
|
||||||
px.cmd(["bumpversion"], name="bumpversion"),
|
px.cmd(["bumpversion"]),
|
||||||
px.cmd(["bumpversion", "minor"], name="bumpversion_minor"),
|
px.cmd(["bumpversion", "minor"]),
|
||||||
px.cmd(["git", "push"], name="git_push"),
|
px.cmd(["git", "push"]),
|
||||||
px.cmd(["git", "push", "--tags"], name="git_push_tags"),
|
px.cmd(["git", "push", "--tags"], name="git_push_tags"),
|
||||||
px.cmd(["hatch", "publish"], name="publish_python"),
|
px.cmd(["hatch", "publish"], name="publish_python"),
|
||||||
px.cmd(["twine", "upload", "--disable-progress-bar"], name="twine_publish"),
|
px.cmd(["twine", "upload", "--disable-progress-bar"], name="twine_publish"),
|
||||||
]
|
]
|
||||||
|
|
||||||
# 单任务别名(alias 名与任务名相同):直接用 TaskSpec,避免 str 自引用
|
# 单任务别名(alias 名与任务名相同):直接内联 TaskSpec,避免 str 自引用
|
||||||
_doc = px.cmd(["sphinx-build", "-b", "html", "docs", "docs/_build"], name="doc")
|
aliases: dict[str, str | list[str | px.TaskSpec] | px.TaskSpec | px.Graph] = {
|
||||||
_lint = px.cmd(["ruff", "check", "--fix", "--unsafe-fixes"], name="lint")
|
# 构建命令
|
||||||
_tox = px.cmd(["tox", "-p", "auto"], name="tox")
|
"b": "uv_build",
|
||||||
|
"bc": "maturin_build",
|
||||||
|
"ba": ["b", "bc"],
|
||||||
|
# 安装命令
|
||||||
|
"sync": "uv_sync",
|
||||||
|
# 清理命令
|
||||||
|
"c": "git_clean",
|
||||||
|
# 开发工具
|
||||||
|
"bump": ["c", "tc", "git_add_all", "bumpversion"],
|
||||||
|
"bumpmi": "bumpversion_minor",
|
||||||
|
"cov": ["git_clean", "test_coverage"],
|
||||||
|
"doc": px.cmd(["sphinx-build", "-b", "html", "docs", "docs/_build"], name="doc"),
|
||||||
|
"lint": px.cmd(["ruff", "check", "--fix", "--unsafe-fixes"], name="lint"),
|
||||||
|
"pb": ["twine_publish", "publish_python"],
|
||||||
|
"t": "test",
|
||||||
|
"tf": "test_fast",
|
||||||
|
"tc": ["pyrefly_check", "lint"],
|
||||||
|
"tox": px.cmd(["tox", "-p", "auto"], name="tox"),
|
||||||
|
# 发布命令
|
||||||
|
"p": ["git_clean", "git_push", "git_push_tags"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
@@ -103,32 +112,5 @@ def main() -> None:
|
|||||||
pymake lint # 格式化代码
|
pymake lint # 格式化代码
|
||||||
pymake type # 类型检查
|
pymake type # 类型检查
|
||||||
"""
|
"""
|
||||||
runner = px.CliRunner(
|
runner = px.CliRunner(strategy="sequential", description="PyMake - Python 构建工具", tasks=tasks, aliases=aliases)
|
||||||
strategy="sequential",
|
|
||||||
description="PyMake - Python 构建工具",
|
|
||||||
tasks=tasks,
|
|
||||||
aliases={
|
|
||||||
# 构建命令
|
|
||||||
"b": "uv_build",
|
|
||||||
"bc": "maturin_build",
|
|
||||||
"ba": ["b", "bc"],
|
|
||||||
# 安装命令
|
|
||||||
"sync": "uv_sync",
|
|
||||||
# 清理命令
|
|
||||||
"c": "git_clean",
|
|
||||||
# 开发工具
|
|
||||||
"bump": ["c", "tc", "git_add_all", "bumpversion"],
|
|
||||||
"bumpmi": "bumpversion_minor",
|
|
||||||
"cov": ["git_clean", "test_coverage"],
|
|
||||||
"doc": _doc,
|
|
||||||
"lint": _lint,
|
|
||||||
"pb": ["twine_publish", "publish_python"],
|
|
||||||
"t": "test",
|
|
||||||
"tf": "test_fast",
|
|
||||||
"tc": ["pyrefly_check", "lint"],
|
|
||||||
"tox": _tox,
|
|
||||||
# 发布命令
|
|
||||||
"p": ["git_clean", "git_push", "git_push_tags"],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
runner.run_cli()
|
runner.run_cli()
|
||||||
|
|||||||
@@ -7,78 +7,20 @@ from unittest.mock import patch
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from pyflowx.cli import pymake
|
from pyflowx.cli import pymake
|
||||||
from pyflowx.conditions import Constants
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
# maturin_build_cmd
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
class TestMaturinBuildCmd:
|
|
||||||
"""Test maturin_build_cmd function."""
|
|
||||||
|
|
||||||
def test_returns_list(self) -> None:
|
|
||||||
"""Should return a list."""
|
|
||||||
cmd = pymake.maturin_build_cmd()
|
|
||||||
assert isinstance(cmd, list)
|
|
||||||
|
|
||||||
def test_contains_maturin_build(self) -> None:
|
|
||||||
"""Should contain 'maturin' and 'build'."""
|
|
||||||
cmd = pymake.maturin_build_cmd()
|
|
||||||
assert "maturin" in cmd
|
|
||||||
assert "build" in cmd
|
|
||||||
|
|
||||||
def test_contains_release_flag(self) -> None:
|
|
||||||
"""Should contain release flag '-r'."""
|
|
||||||
cmd = pymake.maturin_build_cmd()
|
|
||||||
assert "-r" in cmd
|
|
||||||
|
|
||||||
def test_windows_includes_target(self) -> None:
|
|
||||||
"""On Windows, should include target-specific flags."""
|
|
||||||
cmd = pymake.maturin_build_cmd()
|
|
||||||
if Constants.IS_WINDOWS:
|
|
||||||
assert "--target" in cmd
|
|
||||||
assert "x86_64-win7-windows-msvc" in cmd
|
|
||||||
assert "-Zbuild-std" in cmd
|
|
||||||
assert "-i" in cmd
|
|
||||||
assert "python3.8" in cmd
|
|
||||||
else:
|
|
||||||
# On non-Windows, should not include Windows-specific flags
|
|
||||||
assert "--target" not in cmd
|
|
||||||
|
|
||||||
def test_does_not_mutate_on_multiple_calls(self) -> None:
|
|
||||||
"""Multiple calls should return independent lists."""
|
|
||||||
cmd1 = pymake.maturin_build_cmd()
|
|
||||||
cmd2 = pymake.maturin_build_cmd()
|
|
||||||
assert cmd1 == cmd2
|
|
||||||
# Mutating one should not affect the other
|
|
||||||
cmd1.append("extra")
|
|
||||||
assert "extra" not in cmd2
|
|
||||||
|
|
||||||
def test_non_windows_excludes_target_flags(self) -> None:
|
|
||||||
"""On non-Windows, should not include Windows-specific flags (覆盖 22->32 分支)."""
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
with patch.object(pymake.Constants, "IS_WINDOWS", False):
|
|
||||||
cmd = pymake.maturin_build_cmd()
|
|
||||||
assert "maturin" in cmd
|
|
||||||
assert "build" in cmd
|
|
||||||
assert "-r" in cmd
|
|
||||||
assert "--target" not in cmd
|
|
||||||
assert "-Zbuild-std" not in cmd
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
# TaskSpec definitions
|
# TaskSpec definitions
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
def _find_task(name: str) -> pymake.px.TaskSpec:
|
def _find_task(name: str) -> pymake.px.TaskSpec:
|
||||||
"""从 pymake.tasks 或单任务别名变量中查找指定名称的 TaskSpec."""
|
"""从 pymake.tasks 或 aliases 中查找指定名称的 TaskSpec."""
|
||||||
for spec in pymake.tasks:
|
for spec in pymake.tasks:
|
||||||
if spec.name == name:
|
if spec.name == name:
|
||||||
return spec
|
return spec
|
||||||
# 单任务别名变量(_doc/_lint/_tox)
|
# 单任务别名(doc/lint/tox)内联在 aliases dict 中
|
||||||
alias_map = {"doc": pymake._doc, "lint": pymake._lint, "tox": pymake._tox}
|
value = pymake.aliases.get(name)
|
||||||
if name in alias_map:
|
if isinstance(value, pymake.px.TaskSpec):
|
||||||
return alias_map[name]
|
return value
|
||||||
raise KeyError(f"任务 {name!r} 未找到")
|
raise KeyError(f"任务 {name!r} 未找到")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user