- 在 cli/configs/ 下创建 13 个 YAML 工作流配置, 覆盖 filedate/filelevel/folderback/ folderzip/autofmt/bumpversion/piptool/gittool/pdftool/screenshot/lscalc/ sshcopyid/packtool 工具, 共 51 个 job (cmd 与 fn 混合) - yaml_loader 模块级导入 _ops 子模块, 使 YAML fn 字段可引用注册函数, try/except 守卫避免最小安装场景下的 ImportError - 修复 test_registry 的 clear_registry fixture: 保存/恢复 _REGISTRY 原始状态, 避免 teardown 清空 _ops 自动注册的函数导致 TestOpsModules 失败
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
"""Placeholder for configs package."""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -0,0 +1,21 @@
|
||||
# autofmt - 自动格式化工具
|
||||
# 用法:
|
||||
# yamlrun autofmt.yaml --job fmt --var TARGET=.
|
||||
# yamlrun autofmt.yaml --job lint --var TARGET=.
|
||||
# yamlrun autofmt.yaml --job doc --var ROOT_DIR=.
|
||||
# yamlrun autofmt.yaml --job sync --var ROOT_DIR=.
|
||||
strategy: thread
|
||||
variables:
|
||||
TARGET: "."
|
||||
ROOT_DIR: "."
|
||||
jobs:
|
||||
fmt:
|
||||
cmd: ["ruff", "format", "${TARGET}"]
|
||||
lint:
|
||||
cmd: ["ruff", "check", "--fix", "--unsafe-fixes", "${TARGET}"]
|
||||
doc:
|
||||
fn: auto_add_docstrings
|
||||
args: ["${ROOT_DIR}"]
|
||||
sync:
|
||||
fn: sync_pyproject_config
|
||||
args: ["${ROOT_DIR}"]
|
||||
@@ -0,0 +1,11 @@
|
||||
# bumpversion - 版本号自动管理工具
|
||||
# 用法:
|
||||
# yamlrun bumpversion.yaml --var PART=patch
|
||||
# yamlrun bumpversion.yaml --var PART=minor
|
||||
strategy: sequential
|
||||
variables:
|
||||
PART: patch
|
||||
jobs:
|
||||
bump:
|
||||
fn: bump_file_version
|
||||
args: ["${FILE}", "${PART}"]
|
||||
@@ -0,0 +1,18 @@
|
||||
# filedate - 文件日期处理工具
|
||||
# 用法:
|
||||
# yamlrun filedate.yaml --var FILES='["file1.txt","file2.txt"]'
|
||||
# 或通过 Python 入口: filedate add file1.txt file2.txt
|
||||
strategy: thread
|
||||
variables:
|
||||
FILES: []
|
||||
jobs:
|
||||
add:
|
||||
fn: process_files_date
|
||||
args: ["${FILES}"]
|
||||
kwargs:
|
||||
clear: false
|
||||
clear:
|
||||
fn: process_files_date
|
||||
args: ["${FILES}"]
|
||||
kwargs:
|
||||
clear: true
|
||||
@@ -0,0 +1,11 @@
|
||||
# filelevel - 文件等级重命名工具
|
||||
# 用法:
|
||||
# yamlrun filelevel.yaml --var FILES='["file.txt"]' --var LEVEL=2
|
||||
strategy: thread
|
||||
variables:
|
||||
FILES: []
|
||||
LEVEL: 0
|
||||
jobs:
|
||||
set:
|
||||
fn: process_files_level
|
||||
args: ["${FILES}", "${LEVEL}"]
|
||||
@@ -0,0 +1,15 @@
|
||||
# folderback - 文件夹备份工具
|
||||
# 用法:
|
||||
# yamlrun folderback.yaml # 备份当前目录到 ./backup
|
||||
# yamlrun folderback.yaml --var SRC=./project --var DST=./backup
|
||||
strategy: thread
|
||||
variables:
|
||||
SRC: "."
|
||||
DST: "./backup"
|
||||
MAX_ZIP: 5
|
||||
jobs:
|
||||
backup:
|
||||
fn: backup_folder
|
||||
args: ["${SRC}", "${DST}"]
|
||||
kwargs:
|
||||
max_zip: ${MAX_ZIP}
|
||||
@@ -0,0 +1,11 @@
|
||||
# folderzip - 文件夹压缩工具
|
||||
# 用法:
|
||||
# yamlrun folderzip.yaml # 压缩当前目录下所有文件夹
|
||||
# yamlrun folderzip.yaml --var CWD=./project
|
||||
strategy: thread
|
||||
variables:
|
||||
CWD: "."
|
||||
jobs:
|
||||
zip:
|
||||
fn: zip_folders
|
||||
args: ["${CWD}"]
|
||||
@@ -0,0 +1,55 @@
|
||||
# gittool - Git 执行工具
|
||||
# 用法:
|
||||
# yamlrun gittool.yaml --job a # 添加并提交
|
||||
# yamlrun gittool.yaml --job c # 清理
|
||||
# yamlrun gittool.yaml --job i # 初始化、添加并提交
|
||||
# yamlrun gittool.yaml --job p # 推送
|
||||
strategy: thread
|
||||
jobs:
|
||||
a:
|
||||
needs: [add]
|
||||
cmd: ["git", "commit", "-m", "chore: update"]
|
||||
add:
|
||||
cmd: ["git", "add", "."]
|
||||
c:
|
||||
needs: [clean]
|
||||
cmd: ["git", "status", "--porcelain"]
|
||||
clean:
|
||||
cmd:
|
||||
- "git"
|
||||
- "clean"
|
||||
- "-xfd"
|
||||
- "-e"
|
||||
- ".vscode"
|
||||
- "-e"
|
||||
- ".idea"
|
||||
- "-e"
|
||||
- ".editorconfig"
|
||||
- "-e"
|
||||
- ".trae"
|
||||
- "-e"
|
||||
- ".qoder"
|
||||
- "-e"
|
||||
- ".venv"
|
||||
- "-e"
|
||||
- ".git"
|
||||
- "-e"
|
||||
- ".tox"
|
||||
- "-e"
|
||||
- ".pytest_cache"
|
||||
- "-e"
|
||||
- "node_modules"
|
||||
- "-e"
|
||||
- ".ruff_cache"
|
||||
i:
|
||||
needs: [init, add_all]
|
||||
cmd: ["git", "commit", "-m", "init commit"]
|
||||
init:
|
||||
cmd: ["git", "init"]
|
||||
add_all:
|
||||
needs: [init]
|
||||
cmd: ["git", "add", "."]
|
||||
p:
|
||||
cmd: ["git", "push"]
|
||||
pl:
|
||||
cmd: ["git", "pull"]
|
||||
@@ -0,0 +1,21 @@
|
||||
# lscalc - LS-DYNA 计算工具
|
||||
# 用法:
|
||||
# yamlrun lscalc.yaml --job run --var INPUT_FILE=input.k --var NCPU=4
|
||||
# yamlrun lscalc.yaml --job status
|
||||
strategy: thread
|
||||
variables:
|
||||
INPUT_FILE: input.k
|
||||
NCPU: 4
|
||||
jobs:
|
||||
run:
|
||||
fn: run_ls_dyna
|
||||
args: ["${INPUT_FILE}"]
|
||||
kwargs:
|
||||
ncpu: ${NCPU}
|
||||
mpi:
|
||||
fn: run_ls_dyna_mpi
|
||||
args: ["${INPUT_FILE}"]
|
||||
kwargs:
|
||||
ncpu: ${NCPU}
|
||||
status:
|
||||
fn: check_ls_dyna_status
|
||||
@@ -0,0 +1,32 @@
|
||||
# packtool - Python 打包工具
|
||||
# 用法:
|
||||
# yamlrun packtool.yaml --job src --var PROJECT_DIR=. --var OUTPUT_DIR=.pypack
|
||||
# yamlrun packtool.yaml --job wheel --var PROJECT_DIR=. --var OUTPUT_DIR=dist
|
||||
strategy: thread
|
||||
variables:
|
||||
PROJECT_DIR: "."
|
||||
OUTPUT_DIR: ".pypack"
|
||||
LIB_DIR: "libs"
|
||||
DEPENDENCIES: []
|
||||
VERSION: "3.10"
|
||||
OUTPUT_FILE: "package.zip"
|
||||
SOURCE_DIR: "."
|
||||
jobs:
|
||||
src:
|
||||
fn: pack_source
|
||||
args: ["${PROJECT_DIR}", "${OUTPUT_DIR}"]
|
||||
deps:
|
||||
fn: pack_dependencies
|
||||
args: ["${LIB_DIR}", "${DEPENDENCIES}"]
|
||||
wheel:
|
||||
fn: pack_wheel
|
||||
args: ["${PROJECT_DIR}", "${OUTPUT_DIR}"]
|
||||
embed:
|
||||
fn: install_embed_python
|
||||
args: ["${VERSION}", "${OUTPUT_DIR}"]
|
||||
zip:
|
||||
fn: create_zip_package
|
||||
args: ["${SOURCE_DIR}", "${OUTPUT_FILE}"]
|
||||
clean:
|
||||
fn: clean_build_dir
|
||||
args: ["${OUTPUT_DIR}"]
|
||||
@@ -0,0 +1,70 @@
|
||||
# pdftool - PDF 文件工具集
|
||||
# 用法:
|
||||
# yamlrun pdftool.yaml --job m --var INPUTS='["a.pdf","b.pdf"]' --var OUTPUT=merged.pdf
|
||||
# yamlrun pdftool.yaml --job c --var INPUT=input.pdf --var OUTPUT=compressed.pdf
|
||||
strategy: thread
|
||||
variables:
|
||||
INPUT: input.pdf
|
||||
INPUTS: []
|
||||
OUTPUT: output.pdf
|
||||
OUTPUT_DIR: output
|
||||
PASSWORD: ""
|
||||
TEXT: CONFIDENTIAL
|
||||
ROTATION: 90
|
||||
MARGINS: [10, 10, 10, 10]
|
||||
DPI: 300
|
||||
LANG: chi_sim+eng
|
||||
ORDER: []
|
||||
jobs:
|
||||
m:
|
||||
fn: pdf_merge
|
||||
args: ["${INPUTS}", "${OUTPUT}"]
|
||||
s:
|
||||
fn: pdf_split
|
||||
args: ["${INPUT}", "${OUTPUT_DIR}"]
|
||||
c:
|
||||
fn: pdf_compress
|
||||
args: ["${INPUT}", "${OUTPUT}"]
|
||||
e:
|
||||
fn: pdf_encrypt
|
||||
args: ["${INPUT}", "${OUTPUT}", "${PASSWORD}"]
|
||||
d:
|
||||
fn: pdf_decrypt
|
||||
args: ["${INPUT}", "${OUTPUT}", "${PASSWORD}"]
|
||||
xt:
|
||||
fn: pdf_extract_text
|
||||
args: ["${INPUT}", "${OUTPUT}"]
|
||||
xi:
|
||||
fn: pdf_extract_images
|
||||
args: ["${INPUT}", "${OUTPUT_DIR}"]
|
||||
w:
|
||||
fn: pdf_add_watermark
|
||||
args: ["${INPUT}", "${OUTPUT}"]
|
||||
kwargs:
|
||||
text: "${TEXT}"
|
||||
r:
|
||||
fn: pdf_rotate
|
||||
args: ["${INPUT}", "${OUTPUT}"]
|
||||
kwargs:
|
||||
rotation: ${ROTATION}
|
||||
crop:
|
||||
fn: pdf_crop
|
||||
args: ["${INPUT}", "${OUTPUT}"]
|
||||
kwargs:
|
||||
margins: "${MARGINS}"
|
||||
i:
|
||||
fn: pdf_info
|
||||
args: ["${INPUT}"]
|
||||
ocr:
|
||||
fn: pdf_ocr
|
||||
args: ["${INPUT}", "${OUTPUT}"]
|
||||
kwargs:
|
||||
lang: "${LANG}"
|
||||
img:
|
||||
fn: pdf_to_images
|
||||
args: ["${INPUT}", "${OUTPUT_DIR}"]
|
||||
kwargs:
|
||||
dpi: ${DPI}
|
||||
repair:
|
||||
fn: pdf_repair
|
||||
args: ["${INPUT}", "${OUTPUT}"]
|
||||
@@ -0,0 +1,29 @@
|
||||
# piptool - pip 包管理工具
|
||||
# 用法:
|
||||
# yamlrun piptool.yaml --job i --var PACKAGES='["requests"]'
|
||||
# yamlrun piptool.yaml --job u --var PACKAGES='["requests"]'
|
||||
# yamlrun piptool.yaml --job f
|
||||
strategy: thread
|
||||
variables:
|
||||
PACKAGES: []
|
||||
OFFLINE: false
|
||||
jobs:
|
||||
i:
|
||||
cmd: ["pip", "install", "${PACKAGES}"]
|
||||
u:
|
||||
fn: pip_uninstall
|
||||
args: ["${PACKAGES}"]
|
||||
r:
|
||||
fn: pip_reinstall
|
||||
args: ["${PACKAGES}"]
|
||||
kwargs:
|
||||
offline: ${OFFLINE}
|
||||
d:
|
||||
fn: pip_download
|
||||
args: ["${PACKAGES}"]
|
||||
kwargs:
|
||||
offline: ${OFFLINE}
|
||||
up:
|
||||
cmd: ["python", "-m", "pip", "install", "--upgrade", "pip"]
|
||||
f:
|
||||
fn: pip_freeze
|
||||
@@ -0,0 +1,16 @@
|
||||
# screenshot - 截图工具
|
||||
# 用法:
|
||||
# yamlrun screenshot.yaml --job full
|
||||
# yamlrun screenshot.yaml --job area --var FILENAME=custom.png
|
||||
strategy: thread
|
||||
variables:
|
||||
FILENAME: null
|
||||
jobs:
|
||||
full:
|
||||
fn: take_screenshot_full
|
||||
kwargs:
|
||||
filename: "${FILENAME}"
|
||||
area:
|
||||
fn: take_screenshot_area
|
||||
kwargs:
|
||||
filename: "${FILENAME}"
|
||||
@@ -0,0 +1,19 @@
|
||||
# sshcopyid - SSH 密钥部署工具
|
||||
# 用法:
|
||||
# yamlrun sshcopyid.yaml --var HOSTNAME=server --var USERNAME=user --var PASSWORD=pass
|
||||
strategy: thread
|
||||
variables:
|
||||
HOSTNAME: ""
|
||||
USERNAME: ""
|
||||
PASSWORD: ""
|
||||
PORT: 22
|
||||
KEYPATH: "~/.ssh/id_rsa.pub"
|
||||
TIMEOUT: 30
|
||||
jobs:
|
||||
deploy:
|
||||
fn: ssh_copy_id
|
||||
args: ["${HOSTNAME}", "${USERNAME}", "${PASSWORD}"]
|
||||
kwargs:
|
||||
port: ${PORT}
|
||||
keypath: "${KEYPATH}"
|
||||
timeout: ${TIMEOUT}
|
||||
@@ -106,6 +106,16 @@ from pyflowx.conditions import BuiltinConditions
|
||||
from pyflowx.registry import get_fn as _get_fn
|
||||
from pyflowx.task import Condition, RetryPolicy, TaskSpec
|
||||
|
||||
# 导入 _ops 模块以注册 CLI 工具函数, 使 YAML fn 字段可引用
|
||||
# 使用 try/except 避免最小安装场景下的导入失败
|
||||
try:
|
||||
from pyflowx.cli._ops import dev as _dev # noqa: F401
|
||||
from pyflowx.cli._ops import files as _files # noqa: F401
|
||||
from pyflowx.cli._ops import media as _media # noqa: F401
|
||||
from pyflowx.cli._ops import system as _system # noqa: F401
|
||||
except ImportError: # pragma: no cover
|
||||
pass
|
||||
|
||||
# 矩阵占位符: ${{ matrix.key }}
|
||||
_MATRIX_PLACEHOLDER = re.compile(r"\$\{\{\s*matrix\.(\w+)\s*\}\}")
|
||||
|
||||
|
||||
@@ -12,11 +12,17 @@ from pyflowx.registry import _REGISTRY, FnRegistry, get_fn, has_fn, register_fn
|
||||
|
||||
@pytest.fixture
|
||||
def clear_registry() -> Any:
|
||||
"""每个测试前后清空 registry, 避免测试间相互污染."""
|
||||
"""每个测试前后清空 registry, 但保留 _ops 模块自动注册的函数.
|
||||
|
||||
_ops 模块在首次导入时注册函数, 模块不会重新执行, 因此清空后无法重新注册.
|
||||
保存原始状态并在 teardown 时恢复, 确保 TestOpsModules 等不使用此 fixture 的
|
||||
测试仍能看到 _ops 的注册.
|
||||
"""
|
||||
saved = dict(_REGISTRY)
|
||||
_REGISTRY.clear()
|
||||
yield
|
||||
_REGISTRY.clear()
|
||||
_REGISTRY.update(saved)
|
||||
|
||||
|
||||
class TestRegisterFn:
|
||||
|
||||
Reference in New Issue
Block a user