python-code-style

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Python Code Style

Python代码风格

Single owner of "what does well-styled Python look like in this stack": ruff (lint + format) and numpydoc docstrings. This skill is explicitly manual — Claude runs ruff on the files it has just touched, no hook involved.
本技能是此技术栈中“规范Python代码风格”的唯一负责人:使用ruff(代码检查+格式化)和numpydoc文档字符串规范。本技能明确为手动触发——由Claude对刚修改的文件运行ruff检查,不使用钩子机制。

Stop conditions — read before anything else

停止条件——运行前务必阅读

  • Do not configure a PostToolUse / PreToolUse hook for ruff. This skill is intentionally manual. A hook tightens the loop in ways that bite (every micro-edit triggers a fix cycle, partial files fail D-rule checks mid-write, retries can stall the turn). If the user explicitly asks for an automated hook later, redirect to
    update-config
    — but the default is "Claude runs ruff itself."
  • Do not substitute ruff with
    black
    /
    isort
    /
    flake8
    /
    pydocstyle
    /
    pylint
    .
    Ruff is the canonical linter in this stack (
    data-science-python-stack
    Tier 1). If
    import ruff
    /
    pixi run ruff --version
    fails, route through
    python-env-manager
    to install — don't silently fall back.
  • One fix attempt per file, then surface. If
    ruff check
    reports issues after Claude's first fix, address them once. If the same issue persists after the second pass, stop editing that file and surface the remaining diagnostics + diff to the user. This is the anti-infinite-loop guardrail — do not enter a third cycle on the same warning.
  • Don't lint files outside the user's code. The hook scope is
    src/<pkg>/
    ,
    experiments/
    ,
    audit/
    , top-level
    *.py
    scripts, and any package directory the user owns. Skip vendored paths, generated files, and anything under
    .pixi/
    ,
    .venv/
    ,
    node_modules/
    , etc.
  • Never write
    ruff.toml
    from memory.
    The bundled
    templates/ruff.toml
    is the single source of truth — it encodes the per-file ignores (
    experiments/**
    ), the numpydoc convention, and the rule selection this stack expects. Initial setup requires
    Read .agents/skills/python-code-style/templates/ruff.toml
    this turn, then
    Write <project-root>/ruff.toml
    verbatim from that file's content. Authoring a custom
    ruff.toml
    from training- data memory drops half the contract silently. If you catch yourself typing
    [lint]
    /
    [format]
    /
    select = [...]
    without having read the template this turn, STOP and
    Read
    it first.
  • Don't call
    warnings.filterwarnings(...)
    unless the user explicitly asks for it.
    Same for
    warnings.simplefilter
    ,
    @pytest.mark.filterwarnings
    , and
    filterwarnings = [...]
    in
    pytest.ini
    /
    pyproject.toml
    . Warnings are signal in this stack.
  • 请勿为ruff配置PostToolUse/PreToolUse钩子。本技能特意设计为手动触发。钩子会收紧执行循环,引发诸多问题:每次微小编辑都会触发修复循环、编写过程中的不完整文件会触发D规则检查失败、重试可能导致任务停滞。如果用户后续明确要求自动化钩子,引导至
    update-config
    技能——但默认方式为“Claude手动运行ruff”。
  • 请勿用
    black
    /
    isort
    /
    flake8
    /
    pydocstyle
    /
    pylint
    替代ruff
    。ruff是此技术栈(
    data-science-python-stack
    一级规范)中的标准代码检查工具。如果
    import ruff
    pixi run ruff --version
    执行失败,通过
    python-env-manager
    技能进行安装——请勿静默切换至其他工具。
  • 每个文件仅尝试修复一次,之后告知用户。如果Claude首次修复后
    ruff check
    仍报告问题,再修复一次。如果同一问题在第二次修复后仍存在,停止编辑该文件并向用户展示剩余诊断信息和差异内容。这是防止无限循环的防护机制——请勿对同一警告进行第三次修复尝试。
  • 请勿检查用户代码之外的文件。检查范围为
    src/<pkg>/
    experiments/
    audit/
    目录、顶层
    *.py
    脚本,以及用户拥有的任何包目录。跳过供应商路径、生成文件,以及
    .pixi/
    .venv/
    node_modules/
    等目录下的内容。
  • 切勿凭记忆编写
    ruff.toml
    。捆绑的
    templates/ruff.toml
    是唯一的权威来源——它定义了按文件忽略规则(
    experiments/**
    )、numpydoc规范以及此技术栈要求的规则集。初始设置时必须在本次任务中读取
    .agents/skills/python-code-style/templates/ruff.toml
    ,然后将内容原封不动地写入
    <project-root>/ruff.toml
    。凭训练数据记忆编写自定义
    ruff.toml
    会悄无声息地违反一半的规范。如果发现自己未读取模板就开始输入
    [lint]
    /
    [format]
    /
    select = [...]
    ,请立即停止并先读取模板文件。
  • 除非用户明确要求,否则请勿调用
    warnings.filterwarnings(...)
    warnings.simplefilter
    @pytest.mark.filterwarnings
    以及
    pytest.ini
    /
    pyproject.toml
    中的
    filterwarnings = [...]
    也同理。在此技术栈中,警告是重要的信号。

Pre-flight — emit this checklist as visible text before running ruff

飞行前检查——运行ruff前需将此清单作为可见文本输出

Pre-flight (python-code-style):
- [ ] ruff importable in the project's env (`pixi run ruff --version`
      succeeds, per `data-science-python-stack` Tier 1)
- [ ] `ruff.toml` present at project root.
      If absent AND stack + workspace are already set up: the
      bundled template MUST be read **this turn** before being
      written verbatim.
      Evidence: Read .agents/skills/python-code-style/templates/ruff.toml
                (this turn) + Write <project-root>/ruff.toml (this turn)
                | "n/a — ruff.toml already at project root"
      **Inline-authored ruff.toml from memory is NOT evidence.**
- [ ] File list ready: <abs paths of .py files touched this turn>
- [ ] Decision recorded: this is the first ruff pass on these files
      (proceed) | second pass (proceed but stop on persistent
      issues) | third pass on same warning (STOP, surface to user)
- [ ] One-fix-per-file rule acknowledged: max two passes per warning,
      then surface remaining diagnostics + diff to the user.
Pre-flight (python-code-style):
- [ ] ruff可在项目环境中导入(`pixi run ruff --version`执行成功,符合`data-science-python-stack`一级规范)
- [ ] `ruff.toml`已存在于项目根目录。
      若不存在且技术栈+工作区已搭建完成:必须**在本次任务中读取**捆绑模板,再原封不动地写入。
      验证依据:读取.agents/skills/python-code-style/templates/ruff.toml
                (本次任务)+ 写入<project-root>/ruff.toml(本次任务)
                | "不适用——ruff.toml已存在于项目根目录"
      **凭记忆手动编写的ruff.toml不视为有效依据。**
- [ ] 文件列表已准备好:<本次任务中修改的.py文件绝对路径>
- [ ] 已记录决策:这是对这些文件的首次ruff检查(继续执行)| 第二次检查(继续执行但遇到持续问题时停止)| 对同一警告的第三次检查(停止,告知用户)
- [ ] 已确认“每个文件仅修复一次”规则:每个警告最多检查两次,之后向用户展示剩余诊断信息和差异内容。

Scope

适用范围

  • In scope: running
    ruff format
    +
    ruff check --fix
    +
    ruff check
    on Python files Claude has just generated or edited; authoring numpydoc docstrings on public functions and classes; dropping the
    ruff.toml
    template into a fresh project.
  • Out of scope: type hints (mypy / pyright are not in the stack); naming conventions ruff doesn't enforce; setting up PostToolUse / PreToolUse hooks; linting non-Python files.
  • 适用场景:对Claude刚生成或编辑的Python文件运行
    ruff format
    +
    ruff check --fix
    +
    ruff check
    ;为公共函数和类编写numpydoc格式的文档字符串;为新项目添加
    ruff.toml
    模板文件。
  • 不适用场景:类型提示(mypy/pyright不在此技术栈中);ruff未强制执行的命名规范;设置PostToolUse/PreToolUse钩子;检查非Python文件。

What to run, in what order

执行步骤及顺序

For every Python file touched this turn (call them
<files>
), run inside the project's environment manager —
pixi run
for pixi projects, equivalent for uv / poetry / conda (per
python-env-manager
):
bash
pixi run ruff format <files>
pixi run ruff check --fix <files>
pixi run ruff check <files>
Three steps, in order:
  1. ruff format
    — applies the formatter (line length, quoting, trailing commas, blank lines around defs). Idempotent.
  2. ruff check --fix
    — auto-fixes everything ruff knows how to fix in place: import sorting (
    I
    ), legacy syntax (
    UP
    ), detectable bug patterns (
    B
    ).
  3. ruff check
    (no
    --fix
    ) — final pass. Anything reported here needs Claude's attention: missing docstrings (
    D
    ), undefined names (
    F
    ), code structure issues. Address them, then re-run the trio. Apply the one-fix-per-file rule from Stop conditions.
If a file under
experiments/
or
audit/
has a
D100
("missing module docstring") or
D103
("missing function docstring") warning, that's expected for
# %%
cells; the bundled
ruff.toml
per-file-ignores
D100
+
D103
(and
E402
,
B018
) for both
experiments/**
and
audit/**
. If you're seeing them, the
ruff.toml
isn't loaded — check that it lives at the project root.
Audit files (
audit/<NN>_<short_name>.py
, owned by
audit-ml-pipeline
) lint the same way as experiment files: same
# %%
cell convention, same per-file ignores, same NumPyDoc convention for any helper functions. After writing or editing an audit file, run the same trio (
ruff format
ruff check --fix
ruff check
).
对于本次任务中修改的所有Python文件(记为
<files>
),在项目环境管理器中运行以下命令——pixi项目使用
pixi run
,uv/poetry/conda项目使用对应命令(遵循
python-env-manager
技能规范):
bash
pixi run ruff format <files>
pixi run ruff check --fix <files>
pixi run ruff check <files>
分为三个步骤,按顺序执行:
  1. ruff format
    ——应用格式化规则(行长度、引号、末尾逗号、函数定义周围的空行)。此操作具有幂等性。
  2. ruff check --fix
    ——自动修复所有ruff可处理的问题:导入排序(
    I
    规则)、遗留语法(
    UP
    规则)、可检测的bug模式(
    B
    规则)。
  3. ruff check
    (不带
    --fix
    参数)——最终检查。在此步骤中报告的问题需要Claude手动处理:缺失文档字符串(
    D
    规则)、未定义名称(
    F
    规则)、代码结构问题。处理这些问题后,重新运行上述三个步骤。遵循“停止条件”中的“每个文件仅修复一次”规则。
如果
experiments/
audit/
目录下的文件出现
D100
(“缺失模块文档字符串”)或
D103
(“缺失函数文档字符串”)警告,这对于
# %%
单元格是正常情况;捆绑的
ruff.toml
已按文件忽略
experiments/**
audit/**
目录的
D100
+
D103
(以及
E402
B018
)规则。如果仍看到这些警告,说明
ruff.toml
未被加载——检查它是否位于项目根目录。
审计文件(
audit/<NN>_<short_name>.py
,由
audit-ml-pipeline
技能生成)的代码检查方式与实验文件相同:采用相同的
# %%
单元格规范、相同的按文件忽略规则、相同的NumPyDoc规范用于辅助函数。编写或编辑审计文件后,运行相同的三个步骤(
ruff format
ruff check --fix
ruff check
)。

Numpydoc — the docstring convention

Numpydoc——文档字符串规范

Public functions and classes carry numpydoc-format docstrings; ruff's
D
rules with
pydocstyle.convention = "numpy"
enforce the shape.
A bare one-line summary is NOT sufficient for public functions. The
Parameters
/
Returns
(and
Raises
when applicable) sections are mandatory — even when the function is small, even when the user says "just the summary is fine". Approving a one-line docstring on a public function silently fails the contract this skill enforces; the function looks
D
-rule-clean (D100/D103 don't fire) but the parameter shapes and return type that callers actually need are missing. Private helpers (
_leading_underscore
) are the only exception: the default
D
rules allow them to omit docstrings, but public callable surfaces always carry the full numpydoc shape.
Skeleton:
python
def predict_price(X, model, *, n_jobs=1):
    """Predict option prices from a feature matrix.

    Parameters
    ----------
    X : pandas.DataFrame
        Feature matrix with one row per option.
    model : sklearn.base.BaseEstimator
        Fitted estimator with a ``predict`` method.
    n_jobs : int, default=1
        Number of parallel jobs.

    Returns
    -------
    numpy.ndarray of shape (n_samples,)
        Predicted prices, one per row of ``X``.
    """
Conventions worth surfacing because they're non-obvious:
  • One-line summary on the first line, in the imperative mood ("Predict ..." not "Predicts ..."). No trailing period in the summary line if D400 is enabled — but in
    numpy
    convention it is, so write the period.
  • Blank line between summary and the rest.
  • Parameter shapes go in the type slot, not the description, e.g.
    X : ndarray of shape (n_samples, n_features)
    .
  • Returns
    section
    lists the return value; if there are multiple returns, list each on its own row. Don't omit the type.
  • Private helpers (
    _leading_underscore
    ) don't need a docstring under the default
    D
    rules — ruff allows that.
  • Modules (top of file) should start with a one-line summary. Skipped under
    experiments/**
    per the bundled
    ruff.toml
    .
公共函数和类需使用numpydoc格式的文档字符串;ruff的
D
规则通过
pydocstyle.convention = "numpy"
参数强制执行此格式。
公共函数仅写一行摘要并不符合要求。必须包含
Parameters
/
Returns
(必要时包含
Raises
)部分——即使函数很小,即使用户说“只需要摘要即可”。批准公共函数仅使用一行文档字符串会悄无声息地违反本技能的规范;此时函数看起来符合
D
规则(D100/D103不会触发),但调用者实际需要的参数格式和返回类型信息缺失。私有辅助函数(以下划线
_
开头)是唯一例外:默认
D
规则允许它们省略文档字符串,但公共可调用接口必须始终包含完整的numpydoc格式内容。
示例骨架:
python
def predict_price(X, model, *, n_jobs=1):
    """根据特征矩阵预测期权价格。

    参数
    ----------
    X : pandas.DataFrame
        每行对应一个期权的特征矩阵。
    model : sklearn.base.BaseEstimator
        已拟合的估算器,具备``predict``方法。
    n_jobs : int, default=1
        并行作业数量。

    返回
    -------
    numpy.ndarray of shape (n_samples,)
        预测价格,与``X``的每行一一对应。
    """
以下规范因不明显需特别注意:
  • 第一行是单行摘要,使用祈使语气(“Predict...”而非“Predicts...”)。如果启用D400规则,摘要行末尾无需句号——但在numpy规范中需要,因此请添加句号。
  • 摘要与后续内容之间需空一行
  • 参数格式写在类型字段中,而非描述字段,例如
    X : ndarray of shape (n_samples, n_features)
  • Returns
    部分
    列出返回值;如果有多个返回值,每行列出一个。请勿省略类型。
  • 私有辅助函数(以下划线
    _
    开头)在默认
    D
    规则下无需文档字符串——ruff允许此操作。
  • 模块(文件顶部)应以单行摘要开头。根据捆绑的
    ruff.toml
    规则,
    experiments/**
    目录下的模块可省略此摘要。

Initial setup — dropping the
ruff.toml
template

初始设置——添加
ruff.toml
模板

When this skill is invoked on a fresh project that has no
ruff.toml
at its root and the stack + workspace have been scaffolded by their respective skills:
  1. Read the bundled template with the file-reading tool this turn:
    Read .agents/skills/python-code-style/templates/ruff.toml
    . The pre-flight Evidence row for the
    ruff.toml present
    check requires this read; an inline-authored config from memory does not satisfy it.
  2. Write the content verbatim to
    <project-root>/ruff.toml
    . No edits, no "improvements", no rule additions. The template encodes the per-file ignores (
    experiments/**
    ), the
    pydocstyle.convention = "numpy"
    setting, and the rule selection this stack expects. Diverging from it drops half the contract.
  3. Verify ruff picks it up:
    pixi run ruff check --show-settings .
    should report the
    numpy
    convention and the
    select
    list from the template.
Do not fold ruff config into
pyproject.toml
automatically — the project may not have one, or the user may prefer a separate file. The standalone
ruff.toml
is unambiguous.
Forbidden shortcuts:
ShortcutWhy it's wrong
"I know what ruff.toml should contain" → author from memoryThe bundled template carries
experiments/**
per-file ignores, the numpydoc convention, and a curated rule selection. Memory misses these and the contract silently breaks
Read this skill's SKILL.md text describing the template → write from thatThe SKILL.md describes; the template file is. Read the file itself, write it verbatim
当在全新项目中调用此技能,且项目根目录下尚未存在
ruff.toml
,同时技术栈+工作区已由对应技能搭建完成时:
  1. 读取捆绑模板:在本次任务中使用文件读取工具读取
    .agents/skills/python-code-style/templates/ruff.toml
    。“飞行前检查”中“ruff.toml已存在”项的验证依据要求必须执行此读取操作;凭记忆手动编写的配置不满足要求。
  2. 原封不动写入内容:将读取到的内容写入
    <project-root>/ruff.toml
    。请勿编辑、“改进”或添加规则。模板已定义按文件忽略规则(
    experiments/**
    )、
    pydocstyle.convention = "numpy"
    设置以及此技术栈要求的规则集。偏离模板会违反一半的规范。
  3. 验证ruff已加载配置:运行
    pixi run ruff check --show-settings .
    应显示模板中的numpy规范和
    select
    规则列表。
请勿自动将ruff配置合并到
pyproject.toml
中——项目可能没有该文件,或者用户可能偏好单独的配置文件。独立的
ruff.toml
更清晰明确。
禁止的捷径:
捷径错误原因
“我知道ruff.toml应该包含什么内容”→凭记忆编写捆绑模板包含
experiments/**
按文件忽略规则、numpydoc规范以及精心挑选的规则集。凭记忆编写会遗漏这些内容,悄无声息地违反规范
读取本技能的SKILL.md中描述模板的文本→据此编写SKILL.md仅作描述;模板文件才是权威来源。请直接读取文件并原封不动写入

When ruff finds something Claude didn't write

当ruff发现Claude未编写的问题时

A common case: Claude edits one function in a file that already had unrelated
D
-rule violations. Ruff will report those too.
  • In scope of this turn: the lines Claude touched. Fix those.
  • Out of scope: pre-existing warnings in untouched code. Mention them in the response so the user can choose to address them, but don't drag every warning into the current task.
This keeps PR scope tight and avoids "while I was here" expansion that the user didn't ask for.
常见场景:Claude编辑了文件中的一个函数,但文件中原本就存在无关的
D
规则违规项。ruff会同时报告这些问题。
  • 本次任务处理范围:Claude修改的代码行。仅修复这些部分。
  • 本次任务不处理范围:未修改代码中已存在的警告。在回复中提及这些警告,以便用户选择是否处理,但请勿将所有警告都纳入当前任务。
这样可以保持PR范围紧凑,避免未经用户请求就扩大任务范围。

Companion skills

配套技能

  • data-science-python-stack
    — owns the decision that ruff is Tier 1 mandatory; this skill assumes ruff is already installed. If
    pixi run ruff --version
    fails, return there for the install.
  • python-env-manager
    — turns "ruff is missing" into the right install command for the project's manager. Don't run
    pip install ruff
    in a pixi project.
  • organize-ml-workspace
    — sets up the directory layout that the bundled
    ruff.toml
    's per-file ignores (
    experiments/**
    and
    audit/**
    ) reference. Drop the template after this skill has run, so the paths it ignores actually exist.
  • audit-ml-pipeline
    — generates audit files at
    audit/<NN>_<short_name>.py
    . This skill's per-file ignores cover the audit/ path the same way they cover experiments/.
  • update-config
    — only relevant if the user explicitly asks for an automated lint hook later. Default is no hook.
  • data-science-python-stack
    ——负责指定ruff为一级强制工具;本技能假设ruff已安装。如果
    pixi run ruff --version
    执行失败,返回此技能进行安装。
  • python-env-manager
    ——将“缺失ruff”问题转换为适合项目环境管理器的安装命令。请勿在pixi项目中运行
    pip install ruff
  • organize-ml-workspace
    ——搭建目录结构,捆绑的
    ruff.toml
    中的按文件忽略规则(
    experiments/**
    audit/**
    )会引用这些目录。请在该技能运行完成后再添加模板,确保它忽略的路径实际存在。
  • audit-ml-pipeline
    ——生成位于
    audit/<NN>_<short_name>.py
    的审计文件。本技能的按文件忽略规则对audit/目录的覆盖方式与experiments/目录相同。
  • update-config
    ——仅当用户明确要求自动化代码检查钩子时相关。默认不使用钩子。

Conventions

规范总结

  • Manual, not automatic. Claude calls ruff itself, file by file. No hook.
  • One-fix-per-file rule. Hard cap on retries — second pass max, then surface.
  • Project-root config only.
    ruff.toml
    lives at the project root and is the single source of truth. Don't add per-directory overrides unless the user asks.
  • Don't widen scope on touched files. Fix what Claude wrote; surface (don't auto-fix) pre-existing issues elsewhere.
  • 手动触发,而非自动。由Claude逐个文件调用ruff。不使用钩子。
  • 每个文件仅修复一次规则。严格限制重试次数——最多两次检查,之后告知用户。
  • 仅在项目根目录配置
    ruff.toml
    位于项目根目录,是唯一的权威配置。除非用户要求,否则请勿添加按目录的覆盖配置。
  • 请勿扩大修改文件的处理范围。仅修复Claude编写的内容;对于已存在的问题,仅告知用户(不自动修复)。