# 编写文档字符串

LeRobot 的 API 参考文档直接由 `src/lerobot/` 中的 docstring 生成。docstring 并非注释，而是该对象的正式文档，以下格式是渲染器和 CI 检查所解析的内容。

此页面即为约定。如果您要在 `src/lerobot/` 中添加或编辑任何公开内容，请遵循此约定。

> [!IMPORTANT]
> **未记录的公开方法就是不可见的方法。** `[[autodoc]]` 会静默跳过没有文档字符串的成员——没有警告，没有错误，它只是不会出现在渲染后的页面上。覆盖率和 API 参考的完整性是同一个问题。

## 一个示例中的格式

Google 章节标题，Hugging Face 类型格式。两者兼备，而非二选一。

````python
def send_action(self, action: RobotAction, rate_hz: float = 30.0) -> RobotAction:
    """Command the robot to move to a target joint configuration.

    Values are clipped by the configured maximum relative target before reaching the motors, so the
    returned action may differ from the requested one.

    Args:
        action (`dict[str, float]`):
            Target values keyed by motor name, e.g. `{"shoulder_pan.pos": 0.0}`. Keys must match the
            robot's action features.
        rate_hz (`float`, *optional*, defaults to `30.0`):
            Control loop frequency.

    Returns:
        `dict[str, float]`: The action actually written to the motors after safety clipping.

    Raises:
        DeviceNotConnectedError: If the robot has not been connected.

    Example:
        ```python
        >>> from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
        >>> robot = SO101Follower(SO101FollowerConfig(port="/dev/ttyACM0"))  # doctest: +SKIP
        >>> robot.connect()  # doctest: +SKIP
        >>> robot.send_action({"shoulder_pan.pos": 0.0})  # doctest: +SKIP
        ```
    """
````

本页示例中省略了交叉引用——有关其语法以及为何无法在代码块中显示，请参阅[交叉引用](#cross-references)。

## 规则

### 章节

`Args:` · `Returns:` · `Raises:` · `Yields:` · `Example:` · `Note:`

按此顺序。不要使用其他章节标题。首先是一行摘要，然后是可选的自由格式描述，最后是各个章节。

### `Args:` 行会被机器解析

```
name (`type`, *optional*, defaults to `X`):
    Description, indented on its own line.
```

The `*optional*, defaults to` clause is **checked against the real signature default** by `make check-docstrings`. It is not decorative — if you write a default that has drifted from the code, CI fails. Omit the clause entirely for required parameters:

```python
    Args:
        port (`str`):
            Serial port the arm is connected to, e.g. `/dev/ttyACM0`.
        max_relative_target (`float | dict[str, float]`, *optional*):
            Caps the magnitude of the relative positional target vector. `None` disables clipping.
        use_degrees (`bool`, *optional*, defaults to `True`):
            Keep `True` for backward compatibility with existing policies and datasets.
```

类型应使用反引号。当默认值为 `None` 或无需重复说明时，请使用 `*optional*`，而不使用 `defaults to`。

### `Returns:` 类型优先

缩进一行的格式，先输入类型，然后输入冒号，最后输入描述：

```python
    Returns:
        `dict[str, float]`: The action actually written to the motors after safety clipping.
```

`Yields:` 形状相同。

### `**Attributes**:`，切勿使用 `Attributes:`

doc-builder 会将单独的 `Attributes:` 解析为 **`Parameters:` 的同义词**，因此您的属性会被渲染为构造函数参数。这种处理是静默的且错误的。只要属性与构造函数参数不同，请使用带有 `--` 分隔符的粗体形式：

```python
class Robot(abc.ABC):
    """The base abstract class for all LeRobot-compatible robots.

    **Attributes**:
        - **config_class** (`type[RobotConfig]`) -- The expected configuration class for this robot.
        - **name** (`str`) -- The unique robot name used to identify this robot type.
    """
```

注意 `--`，而不是 `:`。

### 交叉引用

使用 doc-builder 的括号语法：用方括号括起来的反引号路径。**不支持 Sphinx 角色（`:pymeth:`、`:pyattr:`）**，它们会在页面上以纯文本形式显示。

| 想要                         | 写入                               |
| ---------------------------- | ----------------------------------- |
| 主包中的类    | &#91;`Robot`&#93;                   |
| 方法，显示完整路径   | &#91;`Robot.connect`&#93;           |
| 方法，显示裸名称   | &#91;`~Robot.connect`&#93;          |
| 嵌套路径                  | &#91;`~robots.Robot.connect`&#93;   |
| 另一个 HF 库中的对象 | &#91;`~accelerate.Accelerator`&#93; |

`~` 仅从 **链接文本** 中去除路径；链接仍会解析为完整路径。

> [!NOTE]
> doc-builder 会在页面的所有位置解析此语法——包括围栏代码块内部。这就是为什么本页上的 docstring 示例使用普通文本而非交叉引用：包含交叉引用的代码块会渲染出解析后的链接，而不是你需要输入的语法。在你自己的 docstring 中，请自由使用交叉引用；此限制仅影响关于该语法的文档 _about_。

### 提示

使用 GitHub 风格的引用块：

```markdown
> [!TIP]
> Call this once at startup — it takes about two seconds.

> [!WARNING]
> Torque is disabled on disconnect. The arm will drop if it is holding a load.
```

`<Tip>` 组件在 doc-builder 中属于遗留组件，请勿再添加新的此类组件。

### 示例必须使用围栏

An example lives inside a fenced `  DOCBUILDER_CODE_7 `python Example:
        ```python
        >>> from lerobot.robots.so_follower import SO101FollowerConfig
        >>> cfg = SO101FollowerConfig(port="/dev/ttyACM0")
        >>> cfg.use_degrees
        True
        ```
````

> [!WARNING]
> An unfenced `>>>` is still collected — doctest finds prompts anywhere in a docstring. What you lose is the
> rendering, so it shows up as a wall of prose on the page. Every example needs the fence.

Every example either executes in CI or carries `# doctest: +SKIP`. Anything that touches hardware, a GPU, or
downloads from the Hub gets `+SKIP`:

````python
    Example:
        ```python
        >>> robot.connect()  # doctest: +SKIP
        >>> policy = ACTPolicy.from_pretrained("lerobot/act_aloha_sim_transfer_cube_human")  # doctest: +SKIP
        ```
````

将包含可运行示例的文件添加到 `utils/documentation_tests.txt` 中。

将示例放在模块的三个到五个真正的入口点上。在琐碎的访问器上放置示例只会带来噪音。

## 你会经常遇到的三种模式

### 配置数据类

配置字段在历史上是通过每个字段上方的 `#` 注释来记录的。**doc-builder 无法识别行内注释**——这样的类在渲染时会列出所有字段，但没有任何描述。请将它们移到类文档字符串中的 `Args:` 块中：

```python
@dataclass
class SOFollowerConfig:
    """Configuration for SO-family follower arms.

    Args:
        port (`str`):
            Serial port the arm is connected to, e.g. `/dev/ttyACM0`.
        max_relative_target (`float | dict[str, float]`, *optional*):
            Caps the magnitude of the relative positional target vector. A scalar applies to all motors;
            a dict maps motor name to a per-motor cap. `None` disables clipping.
        use_degrees (`bool`, *optional*, defaults to `True`):
            Keep `True` for backward compatibility with existing policies and datasets.
    """

    port: str
    max_relative_target: float | dict[str, float] | None = None
    use_degrees: bool = True
```

> [!IMPORTANT]
> **doc-builder 不会从基类继承 docstring。**LeRobot 中注册的配置类通常是采用多重继承的薄封装层：
>
> ```python
> @RobotConfig.register_subclass("so101_follower")
> @dataclass
> class SOFollowerRobotConfig(RobotConfig, SOFollowerConfig):
>     pass
> ```
>
> 该类会渲染**所有**字段——包括继承的字段——且完全不带任何描述，无论基类的文档写得多么完善。`Args:` 块必须位于 `[[autodoc]]` 所指定的具体类中，并且必须涵盖继承的字段。

### 基类，然后是具体的子类

抽象基类承载了规范契约。子类只需记录偏离之处——端口语义、校准特性、电机布局、支持的功能键。切勿将基类契约复制到每个子类中。

`Robot`、`Teleoperator`、`Camera`、`MotorsBusBase`、`ProcessorStep` 和 `PreTrainedPolicy` 都遵循此结构。

### 模块级别名

多个公开名称是别名，而非独立的类：

```python
SO100FollowerConfig = SOFollowerRobotConfig
SO101FollowerConfig = SOFollowerRobotConfig
```

`[[autodoc]]` 会解析别名并渲染**规范**类名，因此`## SO101FollowerConfig`标题在正文中会显示为`class lerobot.robots.so_follower.SOFollowerRobotConfig`。只需为规范类编写一次文档，并在页面的正文中提及别名，而不是为每个别名单独设置一个 autodoc 块。

## 不应记录的内容

- **私有成员。** 以 `_` 开头的任何内容都不属于公共 API。
- **以文字形式重述的类型注解。** `port (`str`): A string.` 没有提供任何信息。请说明它的用途。
- **来自上游的内置代码。** `src/lerobot/policies/molmoact2/molmoact2_hf_model/` 是从 `transformers` 内置的，并且已经带有上游风格的文档字符串。请保持原样——重新调整其格式只会导致下次同步时产生冲突。该部分已被排除在 API 参考和文档字符串检查之外。

## 此规则如何强制执行

| 检查                     | 它能捕获的内容                                                                                            |
| ------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `make check-docstrings`   | `Args:` 条目与签名不匹配；文档中记录的默认值与实际值不一致 |
| `make doctest`            | 不再运行的示例                                                                                |
| `make check-doctest-list` | `utils/documentation_tests.txt` 中的过期或未排序条目                                               |
| `ruff`（`D` 规则）        | Google 规范风格的违规                                                                         |
| `interrogate`             | Docstring 覆盖率低于当前阈值                                                     |
| doc-builder               | 指向不存在内容的 `[[autodoc]]` 路径——这会导致文档构建失败              |

在提交 PR 之前，请一起运行它们：

```bash
make check-docstrings && make doctest && pre-commit run --all-files
```

然后渲染页面并实际查看它：

```bash
doc-builder build lerobot docs/source/ --build_dir /tmp/doc-build
```

## 检查清单

- [ ] 您修改过的每个公共成员都有文档字符串。
- [ ] 每个 `Args:` 条目都与签名匹配，包括 `*optional*, defaults to` 子句。
- [ ] `Returns:` 在缩进一行的位置，类型在前。
- [ ] 不要使用裸露的 `Attributes:` — 请使用 `**Attributes**:` 并配合 `--` 分隔符。
- [ ] 不使用 Sphinx 角色 — 交叉引用使用 &#91;`~module.Class.method`&#93;。
- [ ] 示例位于 ` ```python ` 代码块中，并且要么在 CI 中运行，要么带有 `# doctest: +SKIP`。
- [ ] Config 数据类字段位于具体类的 `Args:` 块中，而不是 `#` 注释。
- [ ] 已目视检查渲染后的页面。

