Skip to main content

NPU operator build & test framework

Project description

forge

NPU 算子编译测试框架。通过 JSON 配置文件驱动,统一管理不同代码仓的算子编译和测试流程,支持精度测试、性能测试和 git bisect 问题定位。

新增算子仓只需添加一个 JSON 配置文件,无需修改任何代码。

零第三方运行依赖,仅使用 Python 标准库。

安装

系统依赖

  • Python >= 3.9
  • Git(bisect 功能需要)

Python 依赖

运行时无需任何第三方库,仅使用 Python 标准库(argparse、json、csv、subprocess 等)。

开发依赖:pytest >= 7.0(仅运行测试需要)

安装步骤

方式一:venv 虚拟环境

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

方式二:conda 环境

# 在已有 conda 环境中安装
conda activate your_env
pip install -e ".[dev]"

# 或者新建专用环境
conda create -n forge python=3.9 -y
conda activate forge
pip install -e ".[dev]"

仅安装(不含 pytest):

pip install -e .

架构

用户 CLI 命令
    │
    ▼
cli.py ─── 解析参数,分派命令(argparse)
    │
    ▼
config.py ─── 加载 JSON 配置,校验字段,替换占位符
    │
    ├──▶ task.py ─── 通用任务执行引擎(TaskRunner 基类)
    │        ├─ 单步/多步执行、skip 检查、capture 变量传递
    │        ├─ 日志记录、超时控制、ignore_failure
    │        └─ 子类通过 _post_step/_make_result 扩展
    │
    ├──▶ builder.py ─── 编译任务(BuildRunner → TaskRunner)
    │        ├─ _post_step: 产物检查(存在性、非空、时效性)
    │        └─ 支持 checkout 到指定 commit 编译(自动 stash/恢复)
    │
    ├──▶ tester.py ─── 测试任务(TestRunner → TaskRunner)
    │        ├─ _post_step: 结果提取(stdout 正则 / CSV 文件)
    │        └─ source_env 环境注入、repeat 重复聚合
    │
    ├──▶ result.py ─── 结果持久化(~/.forge/results/)与对比
    │
    └──▶ bisector.py ─── 二分查找问题 commit
             └─ 循环:checkout → build → test → 判断 good/bad

项目结构

forge/
├── forge/
│   ├── cli.py          # argparse CLI 入口
│   ├── config.py       # 配置加载、校验、占位符替换
│   ├── executor.py     # 通用子进程执行器(超时、输出捕获、实时流式输出)
│   ├── task.py         # 通用任务执行引擎(TaskRunner 基类 + 共享工具函数)
│   ├── builder.py      # 编译任务(BuildRunner 子类 + git checkout/restore)
│   ├── tester.py       # 测试任务(TestRunner 子类 + 结果提取 + repeat 聚合)
│   ├── result.py       # 结果持久化与对比
│   ├── bisector.py     # Git bisect 编排
│   ├── log.py          # 日志系统(文件持久化 + 屏幕输出)
│   └── formatter.py    # ASCII 表格格式化(bisect 结果输出)
├── configs/            # 算子仓配置文件(JSON)
├── tests/              # 测试用例(213 个,含端到端测试)
└── pyproject.toml

核心模块职责

模块 职责
config.py 加载 JSON、校验必填字段、{placeholder} 替换、路径解析
executor.py subprocess 封装:超时控制、环境变量注入、输出捕获、实时流式输出
task.py 通用任务执行引擎(TaskRunner 基类),封装单步/多步执行、skip、capture、日志等公共流程
builder.py BuildRunner 子类:产物检查(_post_step)+ git checkout/restore
tester.py TestRunner 子类:结果提取(_post_step)+ source_env + repeat 聚合
result.py 测试结果 JSON 持久化到 ~/.forge/results/,支持按 commit 加载和结果对比
bisector.py 在 good/bad commit 之间二分,协调 build → test → 判断,支持 skip 和分支恢复
log.py 日志文件持久化到 ~/.forge/logs/,控制屏幕输出级别

配置文件

每个算子仓对应一个 JSON 文件,放在 configs/ 目录下(或通过 --config-dir / OPTOOL_CONFIG_DIR 指定其他目录)。

完整示例

{
  "name": "my_repo",
  "description": "Ascend 910 算子库",
  "repo_path": "/home/user/repos/my_repo",

  "env": {
    "http_proxy": "http://proxy.example.com:8080"
  },

  "build": {
    "command": "bash build.sh",
    "args": ["--target=ascend910", "--build-type=Release"],
    "working_dir": ".",
    "env": {
      "ASCEND_HOME": "/usr/local/Ascend"
    },
    "timeout": 600,
    "success_pattern": "Build succeeded",
    "artifacts": ["output/libkernel.so", "output/op_*.bin"]
  },

  "tests": {
    "accuracy": {
      "command": "python run_accuracy.py",
      "args": ["--op", "{op_name}"],
      "working_dir": "tests/",
      "timeout": 300,
      "success_pattern": "PASS",
      "result": {
        "type": "stdout",
        "pattern": "accuracy: ([0-9.]+)"
      }
    },
    "performance": {
      "command": "bash run_perf.sh",
      "args": ["--op", "{op_name}"],
      "working_dir": "tests/",
      "timeout": 0,
      "result": {
        "type": "file",
        "path": "output/perf_result.csv",
        "format": "csv",
        "value_column": 3,
        "op_column": 0,
        "header": true,
        "delimiter": ","
      }
    }
  },

  "bisect": {
    "build_before_test": true,
    "regression": 15.0,
    "threshold": null
  }
}

字段说明

字段 必填 说明
name 仓库唯一标识
description 描述信息
repo_path 仓库路径(绝对路径,或相对于配置文件所在目录)
vars 自定义变量字典,可在所有占位符中使用。CLI --arg 可覆盖
env 全局环境变量字典,所有任务继承。task/step 级别的 env 可覆盖
test_path 测试工程路径,test 中 working_dir 相对于此路径。绝对路径或相对于 repo_path,默认等于 repo_path
source_env 测试前 source 的环境变量脚本(绝对路径,支持 {placeholder})。优先级:tests.<type> > tests > 顶层
build.command 编译命令
build.args 命令参数列表
build.working_dir 工作目录,相对于 repo_path,默认 "."
build.env 额外环境变量
build.timeout 超时秒数,默认 600。设为 0null 不限时
build.success_pattern 正则匹配 stdout 判断成功,支持字符串或数组(AND)。不配置则仅依赖退出码
build.artifacts 编译产物路径列表,支持 glob 通配符(如 output/op_*.bin)。检查文件存在、非空、且修改时间在本次编译之后
tests.<type>.command 测试命令
tests.<type>.source_env 该测试类型专用的 source_env,覆盖上层配置
tests.source_env 所有测试类型共用的 source_env
tests.<type>.result.type "stdout""file"
tests.<type>.result.pattern stdout 时必填 正则表达式,第一个捕获组为数值
tests.<type>.result.path file 时必填 CSV 文件路径,相对于 working_dir
tests.<type>.result.value_column file 时必填 数值所在列(从 0 开始)
tests.<type>.result.op_column 算子名所在列
tests.<type>.result.header 是否有表头行,默认 true
tests.<type>.result.delimiter CSV 分隔符,默认 ","
tests.<type>.result.aggregate 多行聚合方式:avglastminmax,不配置则取最后一行
tests.<type>.result.op_filter CSV 算子名匹配模板,支持 {placeholder} 和通配符。不配置则直接用 --op 值匹配
tests.<type>.repeat 性能测试重复次数。CLI --repeat 优先。精度测试忽略此项
tests.<type>.repeat_agg 重复测试聚合方式:avg(默认)或 max。CLI --repeat-agg 优先
bisect.build_before_test bisect 每步是否先编译,默认 true
bisect.regression 性能退化阈值百分比,默认 10。CLI --regression 优先
bisect.threshold 绝对性能阈值,不配置则使用百分比模式。CLI --threshold 优先

全局环境变量(env)

顶层 env 字段定义全局环境变量,所有任务自动继承:

{
  "env": {
    "http_proxy": "http://proxy.example.com:8080",
    "https_proxy": "http://proxy.example.com:8080"
  },
  "tasks": {
    "build": {"command": "bash build.sh"},
    "deploy": {
      "command": "bash deploy.sh",
      "env": {"DEBUG": "1"}
    }
  }
}

优先级(高到低): step env > task env > 顶层 env > source_env

环境变量注入(source_env)

安装算子后通常需要 source 一个脚本设置环境变量,供测试使用。可在顶层或 tests.<type> 下配置,test 级别优先:

{
  "name": "my_repo",
  "repo_path": "/path/to/repo",
  "tests": {
    "accuracy": {
      "source_env": "{install_path}/{commit}/set_env.bash",
      "steps": [...]
    }
  }
}

流程: 执行测试前,框架先 source <script>,捕获新增/修改的环境变量,注入到测试命令的环境中。

  • 必须是绝对路径(替换占位符后),相对路径会报错
  • 支持 {placeholder} 替换(如 {install_path}{commit}
  • tests.<type>.source_env 优先于顶层 source_env
  • 环境变量对所有测试步骤生效
  • 步骤级别的 env 配置优先于 source_env

占位符

配置中的 commandargsresult.pathartifacts 支持占位符,运行时自动替换。

内置占位符:

占位符 来源 说明
{repo_path} 配置文件 仓库绝对路径
{test_path} 配置文件 测试工程路径(未配置则等于 repo_path)
{commit} --commit 或自动检测 当前 git commit hash(未指定 --commit 时自动获取 HEAD)
{timestamp} 自动生成 当前时间戳,格式 20260327_103000,用于区分同名文件

自定义占位符:

通过配置文件 vars 字段预定义常用变量,避免每次 CLI 传入:

{
  "name": "my_repo",
  "repo_path": "/path/to/repo",
  "vars": {
    "install_path": "/usr/local/Ascend",
    "target": "ascend910"
  },
  "build": {
    "command": "bash build.sh",
    "args": ["--target={target}"]
  }
}

也可通过 --arg KEY=VALUE 在 CLI 传入或覆盖配置中的变量:

# 传入自定义变量
forge build my_repo --arg op_name=matmul --arg target=ascend910

# 快捷方式
# --op  → --arg op_name=VALUE
# --cs  → --arg case=VALUE
# --ip  → --arg install_path=VALUE
forge build my_repo --op matmul
forge test my_repo -t acc --cs case1
forge build my_repo --ip /usr/local/Ascend

# CLI 覆盖配置中的 vars(target 从 ascend910 变为 ascend310)
forge build my_repo --arg target=ascend310

优先级(高到低): CLI --arg > capture(运行时捕获) > 配置 vars > 内置变量

变量预检查: 执行前自动扫描配置中所有占位符,缺失则报错。通过检查后打印变量表:

Variables:
  op_name = matmul
  commit = abc1234567890

配置文件中使用:

"build": {
  "command": "bash build.sh",
  "args": ["--op", "{op_name}", "--target", "{target}"]
}

buildtestbisect 三个命令均支持 --arg--op。若配置中使用了占位符但未通过 CLI 传入,会报错提示。

多步骤编译流程

编译可以由多个步骤组成(如编译 → 安装),使用 steps 列表:

"build": {
  "steps": [
    {
      "name": "compile",
      "command": "bash build.sh",
      "args": ["--ops={op_name}"],
      "working_dir": ".",
      "timeout": 600,
      "success_pattern": "Build succeeded",
      "artifacts": ["output/libkernel.so"]
    },
    {
      "name": "install",
      "command": "bash install.sh",
      "working_dir": ".",
      "timeout": 120,
      "success_pattern": "Install succeeded"
    }
  ]
}

规则:

  • 步骤按顺序执行,任一步骤失败则整体失败,后续步骤不执行
  • 每个步骤可独立设置 commandargsworking_dirtimeoutsuccess_patternartifactscapture
  • skip_if_exists:指定产物路径(字符串或数组),支持 glob 和 {placeholder},所有文件存在且非空则跳过
  • skip_if_artifacts_exist: true:复用该步骤的 artifacts 列表作为跳过检查条件
  • artifacts 检查在对应步骤执行后进行
  • 向后兼容:不使用 steps 时,原有单 command 写法不受影响

步骤跳过示例

{
  "name": "compile",
  "command": "bash build.sh",
  "artifacts": ["output/libkernel.so", "output/op_*.bin"],
  "skip_if_artifacts_exist": true
}

等价于:

{
  "name": "compile",
  "command": "bash build.sh",
  "skip_if_exists": ["output/libkernel.so", "output/op_*.bin"]
}

产物已存在且非空时输出:Skipped (artifacts exist)

步骤间变量传递(capture)

步骤可以从 stdout 中提取值,存为变量供后续步骤使用:

"steps": [
  {
    "name": "get version",
    "command": "cat version.txt",
    "capture": {
      "version": "v([0-9.]+)"
    }
  },
  {
    "name": "install",
    "command": "bash install.sh",
    "args": ["--version", "{version}", "--path", "{install_path}"]
  }
]

规则:

  • capture 是一个 dict,key 为变量名,value 为正则表达式(第一个捕获组)
  • 从步骤的 stdout 中匹配,成功后注入到 variables,后续步骤可用 {变量名} 引用
  • 匹配失败会打印 warning,不中断执行
  • 变量预检查时会识别 capture 定义的变量,不会误报缺失

输出示例:

  Step 1/2: get version
    Captured: version = 2.5.1
  Step 2/2: install
    Command: bash install.sh --version 2.5.1 --path /usr/local

成功判断逻辑

  1. 检查进程退出码,非 0 即失败
  2. 若配置了 success_pattern,退出码为 0 时额外匹配 stdout,不匹配也判定失败
    • 字符串:单个正则匹配
    • 数组:所有正则都需匹配(AND 逻辑),如 ["Build succeeded", "Install succeeded"]
  3. 若配置了 artifacts,检查每个产物文件存在、非空、且修改时间在本次编译之后
  4. 以上均为可选,不配置则仅依赖退出码

结果提取

精度测试和性能测试统一使用 result 配置块,支持两种方式:

从标准输出提取:

{
  "result": {
    "type": "stdout",
    "pattern": "accuracy: ([0-9.]+)"
  }
}

从 CSV 文件提取:

{
  "result": {
    "type": "file",
    "path": "output/result.csv",
    "format": "csv",
    "value_column": 3,
    "op_column": 0,
    "header": true,
    "delimiter": ",",
    "aggregate": "avg"
  }
}

聚合方式(aggregate 字段): 同一算子有多行数据时的聚合策略:

说明
avg 平均值
last 最后一行
min 最小值
max 最大值
不配置 取最后一行(向后兼容)

算子名通配符匹配: --op 支持 fnmatch 通配符(*?[seq]):

# 匹配所有 matmul 变体
forge test my_repo --type performance --op "matmul*"

# 匹配 add_v1, add_v2(不匹配 add_v10)
forge test my_repo --type performance --op "add_v?"

多步骤测试流程

测试可以由多个步骤组成,按顺序执行。使用 steps 列表替代单个 command

"tests": {
  "accuracy": {
    "steps": [
      {
        "name": "generate input",
        "command": "python gen_input.py",
        "args": ["--op", "{op_name}"],
        "working_dir": "tests/"
      },
      {
        "name": "run operator",
        "command": "bash run_op.sh",
        "args": ["{op_name}"],
        "working_dir": "."
      },
      {
        "name": "compare result",
        "command": "python compare.py",
        "args": ["--op", "{op_name}"],
        "working_dir": "tests/",
        "success_pattern": "PASS",
        "result": {
          "type": "stdout",
          "pattern": "accuracy: ([0-9.]+)"
        }
      }
    ],
    "timeout": 300
  }
}

规则:

  • 步骤按顺序执行,任一步骤失败则整体失败,后续步骤不执行
  • 每个步骤可独立设置 commandargsworking_dirsuccess_patterntimeoutcapture
  • skip_if_exists:指定产物路径(字符串或数组),支持 glob 和 {placeholder},所有文件存在且非空则跳过
  • skip_if_artifacts_exist: true:复用该步骤的 artifacts 列表作为跳过检查条件
  • result 配置放在需要提取结果的步骤上(通常是最后一步)
  • timeout 可在顶层设(所有步骤共享),也可每步单独设
  • 向后兼容:不使用 steps 时,原有单 command 写法不受影响

CLI 使用

全局选项必须放在子命令前面:

forge [--config-dir PATH] [-v/--verbose] <command> [options]

短选项速查

短选项 长选项 适用命令
-v --verbose 全局
-t --type test, run, bisect
-c --commit build, test, run
-s --step build, run
-b --baseline test, run
-g --good bisect
-b --bad bisect

--type 支持缩写:acc = accuracyperf = performance

Daemon 和 Task 子命令

命令 说明
forge daemon start [--foreground] 启动 daemon(后台运行)
forge daemon stop 停止 daemon
forge daemon status 查看 daemon 状态和任务统计
forge daemon install 安装 systemd 服务(需 sudo)
forge daemon uninstall 卸载 systemd 服务(需 sudo)
forge task list [--all|--running|--completed] 列出任务
forge task show <id> [--tail N] [--follow] 查看任务输出
forge task cancel <id> 取消任务
forge task resume <id> 恢复被中断的任务

查看配置

# 列出所有已配置的算子仓
forge list

# 查看某个仓库的完整配置
forge show my_repo

# 校验配置文件是否合法
forge validate my_repo

# 使用自定义配置目录
forge --config-dir /path/to/configs list

编译

# 编译当前 HEAD
forge build my_repo

# 编译指定 commit(自动 stash 未提交更改,编译后恢复)
forge build my_repo --commit abc123

# 编译指定算子
forge build my_repo --op matmul

# 传入多个自定义参数
forge build my_repo --arg op_name=matmul --arg target=ascend910

# 只执行指定步骤(多步骤配置时)
forge build my_repo --step install     # 只安装,跳过编译
forge build my_repo --step compile     # 只编译,跳过安装

测试

# 精度测试
forge test my_repo --type accuracy

# 性能测试
forge test my_repo --type performance

# 测试特定算子
forge test my_repo --type accuracy --op matmul

# 在指定 commit 上测试(自动编译)
forge test my_repo --type performance --commit abc123

# 与指定 commit 的历史结果对比
forge test my_repo --type performance --baseline abc123

# 与上次保存的结果对比
forge test my_repo --type performance --compare-last

# 性能测试跑 3 次取平均值
forge test my_repo -t perf --op matmul --repeat 3

# 性能测试跑 3 次取最大值
forge test my_repo -t perf --op matmul --repeat 3 --repeat-agg max

编译+测试(run)

一个命令完成 build → test,build 失败则不执行 test。

# 编译后跑精度测试
forge run my_repo --type accuracy --op matmul

# 编译后跑性能测试,并与上次结果对比
forge run my_repo --type performance --op matmul --compare-last

# 在指定 commit 上编译+测试
forge run my_repo --type accuracy --commit abc123

# 只执行指定编译步骤后测试
forge run my_repo --type accuracy --step install

自定义任务

配置文件中可通过 tasks 定义任意名称的任务:

{
  "tasks": {
    "deploy": {
      "command": "bash deploy.sh",
      "artifacts": ["lib/libkernel.so"]
    },
    "lint": {
      "steps": [
        {"name": "check", "command": "flake8 .", "success_pattern": "0 errors"},
        {"name": "format", "command": "black --check ."}
      ]
    }
  }
}
# 运行自定义任务
forge task my_repo deploy
forge task my_repo lint

# 支持所有通用选项
forge task my_repo deploy --arg key=val --op matmul

自定义任务支持所有步骤特性:commandargsworking_dirtimeoutenvsuccess_patternartifactsresultcaptureskip_if_existssteps

向后兼容: 旧的 buildtests 配置自动映射为任务(buildbuildtests.accuracytest_accuracy)。forge buildforge testforge runforge bisect 命令不受影响。

Workflow(任务编排)

通过 workflows 定义多个任务的串行执行序列:

{
  "tasks": {
    "build": {"command": "bash build.sh"},
    "deploy": {"command": "bash deploy.sh"},
    "verify": {"command": "bash verify.sh"}
  },
  "workflows": {
    "full_deploy": ["build", "deploy", "verify"],
    "ci": ["build", "test_accuracy", "test_performance"]
  }
}
# 运行 workflow
forge workflow my_repo full_deploy
forge workflow my_repo ci --arg op_name=matmul

按顺序执行,任一任务失败则停止。

Bisect 问题定位

在 good 和 bad 两个 commit 之间自动二分查找引入问题的 commit。

# 精度 bisect:找到精度测试开始失败的 commit
forge bisect my_repo --good abc123 --bad def456 --type accuracy

# 性能 bisect:找到性能退化的 commit
forge bisect my_repo --good abc123 --bad def456 --type performance --op matmul

# 自定义退化阈值(默认 10%)
forge bisect my_repo --good abc123 --bad def456 --type performance --regression 20

# 使用绝对阈值(耗时超过 15 即判定为 bad)
forge bisect my_repo --good abc123 --bad def456 --type performance --threshold 15

Bisect 流程:

  1. 获取 good..bad 之间的 commit 列表
  2. 性能测试时,先在 good commit 上运行测试获取基线值
  3. 二分查找:checkout → build → test → 判断 good/bad
  4. 精度 bisect:退出码 + success_pattern 判断
  5. 性能 bisect:与基线对比,超过退化阈值判定为 bad
  6. 编译失败或测试超时的 commit 自动跳过
  7. 跳过超过总步数 50% 时中止
  8. 完成后自动恢复原始分支

环境变量

变量 说明
OPTOOL_CONFIG_DIR 配置文件目录路径,等价于 --config-dir

后台任务(Daemon 模式)

Daemon 是一个常驻的后台进程,管理和执行提交的后台任务,支持任务持久化和自动恢复。

启动和停止

# 启动 daemon(后台运行,自动 fork)
forge daemon start

# 前台运行(调试用)
forge daemon start --foreground

# 停止 daemon
forge daemon stop

# 查看状态
forge daemon status

提交后台任务

任意命令加上 --daemon 即可后台运行:

# 后台编译
forge build my_repo --daemon

# 后台测试
forge test my_repo --type accuracy --daemon

# 后台 bisect
forge bisect my_repo --good abc --bad def --type accuracy --daemon

提交后立即返回 task_id:Task submitted: task_abc123 (running in background)

管理任务

# 查看运行中的任务(默认)
forge task list

# 查看所有任务
forge task list --all

# 查看已完成的任务
forge task list --completed

# 取消任务
forge task cancel task_abc123

# 恢复被中断的任务
forge task resume task_abc123

查看任务输出

# 查看累积输出(默认最近 100 行)
forge task show task_abc123

# 指定行数
forge task show task_abc123 --tail 50

# 实时跟踪(Ctrl+C 停止)
forge task show task_abc123 --follow

输出文件保存在 ~/.forge/logs/task_{task_id}.log,任务结束后保留。

自动恢复

Daemon 重启后自动恢复被中断的任务(最多重试 3 次)。

systemd 服务

# 安装为系统服务(需 root)
sudo forge daemon install

# 卸载服务
sudo forge daemon uninstall

安装后 daemon 随系统自动启动。

结果存储

测试结果自动保存到 ~/.forge/results/<repo_name>/,JSON 格式:

{
  "repo": "my_repo",
  "commit": "abc1234",
  "timestamp": "2026-03-23T10:00:00",
  "type": "performance",
  "results": {
    "matmul": 12.3,
    "add": 0.8
  }
}

可通过 --compare-last--baseline 与历史结果对比。

日志系统

每次编译和测试的完整输出自动保存到日志文件,方便问题定位。

日志文件位置

~/.forge/logs/<repo_name>/
├── build_2026-03-24T10-30-00.log
├── test_accuracy_2026-03-24T10-35-00.log
└── test_performance_2026-03-24T10-40-00.log

日志内容

每个日志文件包含:

  • 执行时间、完整命令、工作目录
  • 退出码、是否超时、是否成功
  • 编译/测试脚本的 完整 stdout 和 stderr

屏幕输出

# 默认模式:打印执行的命令和工作目录,失败时打印 stderr
forge build my_repo

# verbose 模式:实时逐行打印脚本的 stdout/stderr
forge --verbose build my_repo
forge --verbose test my_repo --type accuracy

排查编译/测试失败

  1. --verbose 查看实时输出:forge --verbose build my_repo
  2. 查看日志文件:cat ~/.forge/logs/my_repo/build_*.log
  3. 检查日志中的 stderr 和退出码
  4. 对比手动执行时的环境变量(配置文件中 build.env 是否缺失关键变量)

扩展

  • 新增算子仓:在 configs/ 下添加一个 JSON 文件即可,无需改代码
  • 新增测试类型:在配置文件的 tests 下新增 key(如 stress),框架通用处理
  • 新增结果文件格式:在 tester.pyextract_result_from_file 中扩展解析器
  • 新增任务类型:继承 TaskRunner,覆盖 _post_step()_make_result() 即可。执行引擎(单步/多步、skip、capture、日志等)自动继承

开发

# 运行测试
source .venv/bin/activate
python -m pytest tests/ -v

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ascend_forge-0.1.0.tar.gz (65.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ascend_forge-0.1.0-py3-none-any.whl (50.0 kB view details)

Uploaded Python 3

File details

Details for the file ascend_forge-0.1.0.tar.gz.

File metadata

  • Download URL: ascend_forge-0.1.0.tar.gz
  • Upload date:
  • Size: 65.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for ascend_forge-0.1.0.tar.gz
Algorithm Hash digest
SHA256 68956b50b408d7e5496b0f861f457cf0259c458a65ea91cbaf420beabf2bef59
MD5 8df9ae2b0adfe367be03d9b98969f93c
BLAKE2b-256 6b91dcdf2797c91242efaefe78ebaa462f24dece1e815d33342214e73127386e

See more details on using hashes here.

File details

Details for the file ascend_forge-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ascend_forge-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 50.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for ascend_forge-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 118b5b101e2239516d36f69eab7a69c8ea8c96dfee08f46193ea986b09076a33
MD5 50c24ae80fad1c8d1e5cc2089012bf7f
BLAKE2b-256 d6a1e47c701829cdf22f4b2f7faa1cae85c695c4944680e2585fd30c0574506a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page