MicroPython 代码规范与提交约定全指南:从 Commit Message 到自动格式化
2026/9/20 21:35:02 网站建设 项目流程
  • 嵌入式
  • 语言运行时
  • 编程语言
  • 解释器
  • 编译器
  • 物联网
  • 系统编程

【免费下载链接】micropython

MicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems

项目地址:https://gitcode.com/gh_mirrors/mi/micropython
点击查看免费下载

本指南完整解析 MicroPython 仓库的 CODECONVENTIONS.md,覆盖 Git 提交信息规范、C/Python 代码风格、tools/codeformat.py格式化流程、uncrustify/ruff 工具链、codespell 拼写检查以及 pre-commit 钩子的安装与使用。读完本文,你将掌握向 MicroPython 提交高质量 PR 的全部前置动作:写出一行符合 72 字符约束并带 Signed-off-by 的提交信息,用正确的工具版本完成 C 与 Python 代码的自动格式化,并在本地一键复现 CI 的全部检查项。

一、Git Commit 约定:前缀、主语与 Sign-off

MicroPython 采用单一代码库(monorepo)结构,py/extmod/ports/docs/drivers/shared/tools/tests/等目录并存,因此提交信息的第一行必须能让人一眼看出改动影响范围。

1.1 路径前缀:指明改动所属区域

每个提交信息必须以目录路径或完整文件路径开头:

  • 改动只涉及单个文件时,优先使用文件路径作为前缀;
  • 改动涉及某子目录下的少量文件时,可以使用子目录作为前缀;
  • 路径较长时可以省略中间层级,但省略后仍须保留足够的上下文提示;
  • 允许去掉文件扩展名。

文档中给出的四个正面示例(这些也是仓库中真实存在的提交风格):

py/objstr: Add splitlines() method. py: Rename FOO to BAR. docs/machine: Fix typo in reset() description. ports: Switch to use lib/foo instead of duplicated code.

对应到当前仓库的实际提交,例如最新一次提交的主旨行即为:

rp2: Keep machine.RTC ticking while in lightsleep().

前缀rp2对应 ports/rp2 端口目录,主旨描述了具体行为变更,句尾带句号,完全符合规范。

1.2 主旨行要求

  • 在路径前缀之后,主旨行应清晰、切中要点地描述本次改动;
  • 必须是语法完整的句子并以英文句号.结尾;
  • 整行(含前缀)不得超过 72 个字符

这些约束并非仅靠自觉,仓库提供了机器校验脚本 tools/verifygitlog.py,其中的正则^[^!]+: [A-Z]+.+ \.+$会检查主旨行必须形如path: Subject.,并且:

  • 前缀不能以./开头、不能以/结尾;
  • 前缀不能以ports/开头,而应直接使用端口名(如esp32stm32);
  • 前缀不能以.c.h.cpp.js.rst.md等扩展名结尾;
  • 主旨行超过 72 字符会报错(Subject line must be 72 or fewer characters);
  • 主旨行之后若还有内容,第二行必须为空行,用于分隔主旨与正文。

1.3 正文与行宽

主旨行之后空一行,再按需补充详细说明,正文每行不超过 75 个字符(URL 等无法断行的长条目除外)。改动超过 5 行时,通常就需要撰写详细正文。正文中,以Co-authored-by:Signed-off-by:开头的行以及包含://的 URL 行不受 75 字符限制(见 tools/verifygitlog.py)。

1.4 Signed-off-by:法律意义上的签署

每次提交都必须签署:在提交信息末尾添加Signed-off-by:行,最简单的方式是使用git commit -s。签署即代表你确认以下事项:

  1. 代码是你本人所写,或取自许可兼容的项目(后者须在提交信息乃至源码中注明来源并致谢原作者);
  2. 你有权将这些改动发布到开源项目(例如第三方付费工作期间的成果可能需要该第三方明确批准);
  3. 你(或你的雇主)同意以 MicroPython 的 MIT 许可证发布这些改动。你保留对改动的版权(小改动通过提交信息体现版权;若对某源码模块做了显著改动,欢迎在文件头添加你的名字);
  4. 你的贡献(包括提交信息)将公开且长期可访问,任何人可按项目许可证条款获取与再分发;
  5. 你的签名即Signed-off-by行,其中必须包含你的真实全名有效、可联系的邮箱地址

verifygitlog.py会强制校验最后一行是否以Signed-off-by:开头且包含@,同时会拒绝包含noreply字样的作者/提交者邮箱。

1.5 实践建议与 WIP 机制

  • 想获取优秀提交范例,直接浏览仓库的git log
  • 提交信息被 pre-commit 拒绝时,可用git commit -n(即--no-verify)单次跳过检查;
  • 需要临时绕过提交信息格式检查时,可将主旨行以WIP开头(verifygitlog.py--ignore-rebase模式会跳过squash!fixup!amend!WIP前缀的提交)。

二、代码自动格式化总览

MicroPython 对 C 与 Python 代码的格式实行统一管控:

  • C 代码:使用 tools/codeformat.py 驱动 uncrustify 配置;
  • Python 代码:使用 ruff 与ruff format进行 lint 与格式化。

改动完成、提交之前,运行tools/codeformat.py重新格式化 C 代码,对 Python 代码运行ruff format。不带参数执行时工具会格式化全部源码(耗时较长);也可以把改动的文件作为参数传入,仅格式化这些文件。

从 tools/codeformat.py 的源码可以看到默认扫描范围:drivers/**/*.[ch]examples/**/*.[ch]extmod/**/*.[ch]mpy-cross/*.[ch]ports/**/*.[ch]py/**/*.[ch]shared/**/*.[ch]以及lib/mbedtls_errors/tester.c;同时有一组排除项(如shared/readline/*.[ch]drivers/cc3100ports/cc3200ports/nrf部分目录、ports/stm32/usbdevports/stm32/usbhost及构建产物ports/*/build*),这些多是尚未完全格式化或第三方代码。

工具支持的关键命令行参数:

参数作用
-c仅格式化 C 代码
-p仅格式化 Python 代码
-v输出详细信息
-f对命令行传入的文件按默认清单过滤(只检查清单内文件)
files指定要格式化的文件 glob,缺省为全部默认路径

C 代码处理分两步:先用uncrustify -c tools/uncrustify.cfg -lC --no-backup批量格式化(每 200 个文件一批,避免命令行过长),再执行fixup_c()做预处理指令缩进修正——它会把#if/#ifdef/#else/#endif的缩进与其后代码行对齐(tools/codeformat.py)。Python 侧则在仓库根目录执行ruff format(配置见 pyproject.toml)。

三、uncrustify 版本要求与安装

MicroPython 只支持 uncrustify v0.71 或 v0.72。不同版本的 uncrustify 输出略有差异,且配置文件格式往往互不兼容;v0.73 及更新版本将无法工作

如果你的操作系统包管理器提供兼容的预编译版本,可以直接安装;否则推荐通过 PyPI 安装官方封装的兼容版本。

3.1 使用 pip 安装(推荐配合虚拟环境)

pip install micropython-uncrustify

该包安装的是一个以 Python 可执行程序形式交付的原生编译 uncrustify 二进制,因此可以装进 virtualenv,随 venv 管理版本。

3.2 使用 pipx 安装

若不使用虚拟环境,可通过 pipx 安装:

pipx install micropython-uncrustify

在 pre-commit 配置中,本地钩子codeformat正是依赖micropython-uncrustify==1.0.0.post1来保证所用 uncrustify 版本一致(见 .pre-commit-config.yaml)。

四、代码拼写检查:codespell

MicroPython 使用 codespell 做代码拼写检查,并作为 GitHub Action 在 CI 中运行。codespell 通过 pyproject.toml 配置以避免误报:ignore-words-list列出了需要忽略的单词(如ansdequessertechnicure等常见于嵌入式领域的标识符),ignore-regex忽略全大写的三字母缩写,skip排除了./lib./tests、第三方驱动与构建产物等目录。

手动安装并运行:

$ pip install codespell tomli $ codespell

tomli用于让 codespell 读取 TOML 格式的配置。仓库建议在提交 PR 前先跑一遍 codespell;为简化流程,它已被配置为 pre-commit 钩子,执行pre-commit install后即会自动生效。

五、pre-commit 自动钩子:本地复现 CI 检查

仓库提供 .pre-commit-config.yaml,将代码格式与提交信息约定检查接入 pre-commit 工具。pre-commit 会自动安装正确版本的依赖(codespell、uncrustify、ruff 等)。

5.1 安装 pre-commit 本体

可从系统包管理器或 pip 安装,通过 pip 安装时建议使用虚拟环境:

$ apt install pre-commit # Ubuntu, Debian $ pacman -Sy python-precommit # Arch Linux $ brew install pre-commit # Brew $ pip install pre-commit # PyPI

5.2 注册钩子

在 MicroPython 仓库根目录执行:

$ pre-commit install --hook-type pre-commit --hook-type commit-msg

此后git commit时会自动对代码提交信息执行格式检查。具体而言,配置中注册了四个钩子:

  • 本地钩子codeformat:对改动的 C 文件运行tools/codeformat.py -v -c -f
  • 本地钩子verifygitlog:在commit-msg阶段运行tools/verifygitlog.py --check-file --ignore-rebase校验提交信息格式;
  • ruffruff-format(rev v0.11.6):对 Python 文件做 lint 与格式化;
  • codespell(rev v2.4.1):对改动文件做拼写检查。

CI 会对提交到 MicroPython 的每个 Pull Request 运行同样的格式化检查;pre-commit 能让你更快发现失败,且多数情况下会在本地工作副本中自动修正格式。

5.3 卸载与使用技巧

卸载钩子:

$ pre-commit uninstall --hook-type pre-commit --hook-type commit-msg

实用技巧:

  • 单次提交跳过 pre-commit 检查:git commit -n--no-verify);
  • 临时忽略提交信息格式检查:主旨行以WIP开头。

5.4 手动运行 pre-commit

钩子安装后也可按需手动运行:

$ pre-commit run --all-files # 修正代码库全部文件 $ pre-commit run --file ./path/to/my/file # 只处理单个文件 $ pre-commit run --file ./path/to/my/folder/* # 只处理某个目录

六、Python 代码约定

Python 代码遵循 PEP 8,并使用ruff format自动格式化,行宽为 99 字符(见 pyproject.toml 的line-length = 99)。

命名约定:

  • 模块名:简短且全小写,如pybstm
  • 类名:CamelCase,缩写保持全大写,如I2C而不是I2c
  • 函数与方法名:全小写,必要时用单个下划线分隔单词提升可读性,如mem_read
  • 常量:全大写,单词间用单个下划线分隔,如GPIO_IDR

ruff 配置中还包含若干针对 MicroPython 的定制:builtins声明了ptrptr8uintmicropythonconstexecfile等 MicroPython 特有内建名;mccabe.max-complexity = 40放宽圈复杂度阈值;tests/**/*.py整体豁免 lint(部分测试文件因故意违反语法或依赖 REPL 行为,也被ruff.format排除,见 pyproject.toml)。

七、C 代码约定

C 代码由 uncrustify 依据 tools/uncrustify.cfg 自动格式化,并辅以 tools/codeformat.py 的少量修正。编写新 C 代码时请遵循既有风格,并用tools/codeformat.py校验改动。

需要说明的是:MicroPython 代码库已有十余年历史,并非每个源文件都完全符合这些约定。对既有代码做小幅修改时,跟随该文件现有风格通常即可;新代码或大规模改动则应遵循以下约定。

7.1 空白(White space)

  • 制表符展开为 4 个空格;
  • 行尾不得留尾随空白;
  • 控制块(ifforwhile)关键字与左括号之间留 1 个空格;
  • 逗号后留 1 个空格,运算符两侧各留 1 个空格。

7.2 花括号(Braces)

  • 所有块都必须使用花括号,即使只有一行代码;
  • 左花括号放在所属行的行尾(Allman 风格不被接受),不另起新行;
  • else与前一个右花括号同行。

7.3 头文件

  • 头文件必须用#if预处理指令防止重复包含(include guard),命名方式参考现有头文件。

7.4 命名(Names)

  • 所有名称使用underscore_case,不使用 camelCase;
  • 枚举与宏使用CAPS_WITH_UNDERSCORE
  • 定义类型时使用underscore_case并在末尾加_t

公共名称(声明在头文件中)

  • MicroPython 特有名称(尤其是声明在py/extmod/目录中的)一般以mp_MP_开头。例如 py/obj.h 中声明的一众对象构造接口:mp_obj_new_intmp_obj_new_int_from_uintmp_obj_new_floatmp_obj_new_bool等;
  • 头文件中声明的函数与变量通常共享一个较长的公共前缀,且前缀一般与文件名一致。例如定义在 py/obj.c 中的条目声明于 py/obj.h,前缀为mp_obj_。也存在例外,比如一个头文件为方便起见集中声明了多个源文件中的实现。

私有名称(仅限单个 .c 文件)

  • 对暴露给 Python 的静态函数与变量(即以MP_DEFINE_CONST_FUN_...包装并挂载到模块上的静态 C 函数),使用文件级公共前缀命名,即按“非静态”的规则命名;
  • 其他仅在本 .c 文件内使用的静态定义不需要任何前缀(明确禁止s__前缀,一般也避免添加文件级公共前缀)。

7.5 整数类型

MicroPython 运行在 16 位、32 位与 64 位机器上,必须使用大小与符号正确的整数类型:

  • 大多数场景使用mp_int_t(有符号)与mp_uint_t(无符号),二者保证为机器字宽,足以容纳 MicroPython small-int 对象的值;
  • 统计字节数/对象大小时使用size_t
  • 可以使用int/uint,但需牢记它们可能是 16 位宽;
  • 不确定时,使用mp_int_t/mp_uint_t

7.6 注释

  • 保持简洁,只为不明显的内容写注释;
  • 使用//前缀,不使用/* ... */;不写多余废话。

7.7 内存分配

  • 使用m_newm_renewm_del及其系列宏分配与释放堆内存,这些宏定义在 py/misc.h。例如m_new(type, num)展开为m_malloc(sizeof(type) * (num)),另有m_new0(清零)、m_new_objm_new_obj_var(含可变长尾部字段的对象)等变体;
  • 之所以统一走这些宏,是因为它们在所有端口上路由到 MicroPython 的 GC 分配器,保证内存管理与平台无关。

7.8 风格示例

花括号、空格、命名与注释:

#define TO_ADD (123) // This function will always recurse indefinitely and is only used to show // coding style int foo_function(int x, int some_value) { if (x < some_value) { foo(some_value, x); } else { foo(x + TO_ADD, some_value - 1); } for (int my_counter = 0; my_counter < x; ++my_counter) { } }

类型声明:

typedef struct _my_struct_t { int member; void *data; } my_struct_t;

注意结构体标签_my_struct_t与 typedef 名my_struct_t的配套写法,这也是整个代码库统一的结构体命名模式。

八、文档编写约定

MicroPython 文档总体上跟随 CPython 的文档流程与约定,使用 reStructuredText(reST)语法书写(文档源文件位于 docs 目录)。

8.1 参数引用与通用描述

*标记引用函数参数,例如 docs/library/select.rst 中真实的写法:

.. method:: poll.unregister(obj) Unregister *obj* from polling.

当多个元素需要共用一段描述时:

.. function:: foo(x) bar(y) Description common to foo() and bar().

8.2 交叉引用语法

:func:`foo` - function foo in current module :func:`module1.foo` - function foo in module "module1" (similarly for other referent types) :class:`Foo` - class Foo :meth:`Class.method1` - method1 in Class :meth:`~Class.method1` - method1 in Class, but rendered just as "method1()", not "Class.method1()" :meth:`title <method1>` - reference method1, but render as "title" (use only if really needed) :mod:`module1` - module module1

symbol是通用 xref 语法,可在无歧义时替代上述任意形式;若存在歧义,文档生成时会给出警告,需要用上面的精确语法修正。

8.3 锚点引用与外部链接

交叉引用任意位置(若 xref 目标后紧跟章节标题,可直接写:ref:xref_target``):

.. _xref_target: Normal non-indented text. This is :ref:`reference <xref_target>`.

链接到外部 URL:

`link text <http://foo.com/...>`_

8.4 内建单例对象

引用NoneTrueFalse等内建单例对象时使用双反引号字面量:

``None``, ``True``, ``False``

九、与 CI 的联动:一次提交如何通过全部检查

综合全仓库的配置,一个合规的 MicroPython 提交需要同时满足以下链路(全部可在本地通过 pre-commit 复现):

  1. 代码格式:C 文件经 uncrustify v0.71/v0.72 + tools/codeformat.py 格式化;Python 文件经ruff format(99 字符行宽)格式化;
  2. 静态检查:Python 代码经 ruff lint(豁免项见 pyproject.toml);C 代码遵循 tools/uncrustify.cfg 的风格约定;
  3. 拼写检查:codespell 按 pyproject.toml 的忽略清单扫描;
  4. 提交信息:tools/verifygitlog.py 校验前缀、句号结尾、72 字符主旨行、75 字符正文行、第二行空行、Signed-off-by签名与有效邮箱;
  5. Git 钩子pre-commit install --hook-type pre-commit --hook-type commit-msg将上述检查注册到本地,与 CI 保持同版本依赖。

由于git commit会触发commit-msg阶段的verifygitlog钩子,最常见的失败场景是提交信息不合规;此时按钩子输出的错误逐条修正(例如补充句号、缩短主旨行、加上Signed-off-by行)即可。提交前养成“先tools/codeformat.py <改动文件>格式化、再pre-commit run --file <改动文件>复查”的习惯,就能在本地提前消除绝大多数 CI 报错。

十、进一步阅读

  • CONTRIBUTING.md:贡献入口,指向贡献者指南与本规范;
  • .pre-commit-config.yaml:四个钩子(codeformat、verifygitlog、ruff、codespell)的版本与参数定义;
  • tools/codeformat.py:C/Python 格式化脚本的完整实现与默认扫描/排除路径;
  • tools/verifygitlog.py:提交信息校验脚本的完整规则实现;
  • tools/uncrustify.cfg:C 格式化配置;
  • pyproject.toml:ruff 与 codespell 的集中配置;
  • docs 目录:reST 文档源码,可用于对照第八节中的交叉引用与描述约定。

对于新手贡献者,最稳妥的路径是:先浏览git log观察既有提交风格 → 用git commit -s书写带前缀、句号与 Signed-off-by 的提交信息 → 运行tools/codeformat.pypre-commit run --all-files完成本地检查 → 再提交 Pull Request。这套流程覆盖了 CI 中除实际编译与测试外的全部格式类检查,能显著减少来回 review 的成本。

  • 嵌入式
  • 语言运行时
  • 编程语言
  • 解释器
  • 编译器
  • 物联网
  • 系统编程

【免费下载链接】micropython

MicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems

项目地址:https://gitcode.com/gh_mirrors/mi/micropython
点击查看免费下载
上一篇:PrivateGPT API客户端开发:Python/JavaScript实战教程
下一篇:打造统一视觉体验:Dracula Theme图标与UI组件库开发指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询