Skip to content

Latest commit

 

History

History
175 lines (130 loc) · 7.64 KB

File metadata and controls

175 lines (130 loc) · 7.64 KB

PyriteCLI 接入 mPyMacro 改造指导

本文档是给 ~/Pyrite-Project/pyrite-cli 的改造清单。当前阶段不执行(等 mPyMacro 发布到 PyPI org 后再动手)。所有行号基于编写本文档时的 pyrite-cli 代码,实际改动前请重新核对。

目标

让 pyrite-cli 把条件编译能力外置为对 mpymacro 包的依赖,删除内部重复实现,同时保留 pyrite 自身的设备 I/O 优势(板型自动识别、自动编译、串口刷写)。

改造后职责边界:

能力 归属 说明
@feature/@target 源码级裁剪 mPyMacro preprocess()
manifest 文件级过滤 mPyMacro load_manifest()
machine/platform 字符串 → tags 映射 mPyMacro resolve_board_tags()(纯逻辑)
target/feature/no_feature 合并 mPyMacro resolve_active_tags()
board_tags 配置加载 两者兼容 读同一份 pyproject.toml [tool.pyrite.board_tags]
读串口/设备 uname pyrite detect_tags()self.run(...) 部分保留
自动编译 .py→.mpy pyrite mpy-cross 调用保留
串口刷写 pyrite flash_file/flash_entries 保留

前置条件

mPyMacro >=0.2.0 已可安装(PyPI 或本地 pip install -e),暴露:

from mpymacro import (
    preprocess, load_manifest, build_project,
    resolve_active_tags, resolve_board_tags, load_board_tags,
    DEFAULT_BOARD_TAGS,
)

签名与 pyrite 现有内部实现完全一致,故多数接入点是「改 import」级改动:

  • preprocess(source, active_tags, filename="") -> str
  • load_manifest(manifest_path, active_tags, base_dir=None) -> list[tuple[str, str]]

改动清单

1. 依赖与文件删除

pyproject.toml

dependencies = [
    # ... 现有依赖 ...
    "mpymacro>=0.2.0",   # 新增
    # libcst 可移除——已由 mpymacro 间接依赖;如其它模块直接用 libcst 则保留
]

删除以下文件(逻辑已迁入 mpymacro):

  • cli/utils/preprocessor.py
  • cli/utils/manifest_loader.py

cli/project/feature_stub.pyi 可保留随包,或改由 mpymacro stub -o cli/project/feature_stub.pyi 生成。

对应地从 pyproject.toml[tool.pytest.ini_options].testpaths 移除 test/test_preprocessor.pytest/test_manifest_loader.py(这些用例已在 mPyMacro 仓库内覆盖)。

2. preprocess 接入点(2 处,改 import 即可)

cli/utils/flash/core.py:1336-1346flash_file)与 1540-1555flash_entries):

# 改前
from ..preprocessor import preprocess
# 改后
from mpymacro import preprocess

调用代码、参数、临时目录写出逻辑一律不动——preprocess(source, active_tags, filename) 签名一致。auto_compile(mpy-cross)仍在 preprocess 之后执行,顺序不变。

3. load_manifest 接入点(2 处,改 import 即可)

  • cli/utils/flash/core.py:1764flash_program
  • cli/project/sync.py:57ProjectSyncManager._collect_project_files
# 改前
from ..manifest_loader import load_manifest   # 或对应相对路径
# 改后
from mpymacro import load_manifest

4. detect_tags() —— 拆分 I/O 与纯逻辑(core.py:1809-1830

保留设备读取(这是 pyrite 的板型自动识别优势),仅把字符串→tags 的纯映射委托给 mpymacro:

def detect_tags(self) -> Set[str]:
    """从设备读取 board 信息,返回 active_tags 集合。"""
    from mpymacro import resolve_board_tags
    try:
        out = self.run(
            "import os,sys\nprint(os.uname().machine)\nprint(sys.platform)",
        )
    except Exception as e:
        log.debug("设备 tag 检测失败: %s", e)
        return set()

    lines = [l.strip() for l in out.strip().splitlines() if l.strip()]
    machine = lines[0] if lines else ""
    platform = lines[1] if len(lines) > 1 else ""
    # 纯映射逻辑外置到 mpymacro
    return resolve_board_tags(machine, platform, self.config.board_tags)

注意 resolve_board_tags 把 machine+platform 拼接后大写匹配关键字,并追加 platform 自身(大写)——与原 detect_tags 行为等价。

5. target/feature/no_feature 合并 —— 7 处重复收敛为一处

原代码在 main.py 中重复约 7 处,全部替换为对 resolve_active_tags 的调用:

  • main.py:319-330flash
  • main.py:388-400flash_program
  • main.py:1188-1199project flash
  • main.py:1332-1343project run
  • main.py:1234-1244project status
  • main.py:1279-1295project pull特殊:未指定任何选项时 active_tags=None
  • main.py:1480-1496_build_tag_args,被 fs put 使用)

通用替换(适用于前 5 处):

from mpymacro import resolve_active_tags

active_tags = resolve_active_tags(
    target=target,
    detected=(mp.detect_tags() if not target else None),
    feature=feature,
    no_feature=no_feature,
    board_tags=mp.config.board_tags,
)
# 原 "无法识别设备 target" 的报错逻辑(detect 返回空集时)按需保留在调用处:
if not target and not active_tags:
    log.error("无法识别设备 target,请使用 --target 手动指定")
    raise typer.Exit(1)

建议把上面这段封装进现有的 _build_tag_args(mp, target, feature, no_feature),让全部 5 处都调它,消除重复。

project pull 的特殊语义main.py:1279-1295)必须保留:未指定 target/feature/no_feature 时 active_tags=None(表示"拉取全部、不裁剪")。resolve_active_tags 在无任何输入时返回空集而非 None,故这一处需要单独处理:

if not target and not feature and not no_feature:
    active_tags = None   # pull 全部,不做过滤/裁剪
else:
    active_tags = resolve_active_tags(
        target=target,
        detected=(set() if (feature or no_feature) and not target else None),
        feature=feature, no_feature=no_feature,
        board_tags=mp.config.board_tags,
    )

6. 配置兼容(无需改动,天然一致)

pyrite 继续用自己的 cli/utils/config.py 加载 board_tags。mPyMacro 的 load_board_tags() 复刻了相同语义(读 pyproject.toml [tool.pyrite.board_tags],大写 key 合并进同一份默认表),因此:

  • 用户在项目 pyproject.toml 写一次 [tool.pyrite.board_tags]
  • 经 pyrite-cli 刷写、或用独立 mpymacro CLI 处理,得到的 active_tags 一致

无需让 pyrite 改用 load_board_tags;但如果希望进一步减少重复,可让 pyrite 的 config.py 内部调用 mpymacro.load_board_tags(defaults=_DEFAULT_BOARD_TAGS) 来填充 cfg.board_tags(可选,非必须)。

验证清单(改造后在 pyrite-cli 仓库执行)

  1. pip install -e . 能拉到 mpymacro 依赖。
  2. pyrite 现有非删除测试仍通过:test/test_config.py(board_tags 加载不变)、其余 flash/protocol 测试不受影响。
  3. 端到端:对一个含 @feature/@targetmanifest.py(features=...) 的项目执行 pyrcli flash-program,对照改造前的输出字节码一致。
  4. 板型识别:连真实设备 pyrcli flash-program(不带 --target),确认 detect_tags() 仍能识别并裁剪。
  5. 离线一致性:mpymacro build -m manifest.py -o /tmp/dist --target ESP32 的产物,与 pyrite 在同 target 下刷入的内容逐文件一致。

回滚

改动集中在「删 2 文件 + 改 4 处 import + 改 1 个 detect_tags + 收敛 7 处 tag 合并」。如需回滚,恢复被删的 preprocessor.py/manifest_loader.py 并还原 import 即可——mpymacro 与原实现 API 同构,不存在数据格式迁移。