lintro-add

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Adding a New Tool to Lintro

为Lintro添加新工具

Lintro is a unified CLI for code linting/formatting with a plugin architecture: tools are defined in
lintro/tools/definitions/<tool>.py
(via
@register_tool
), parsed by
lintro/parsers/<tool>/
, tested in
tests/unit/
, with sample violation files in
test_samples/tools/
.
Lintro是一款采用插件架构的代码检查/格式化统一CLI工具:工具定义在
lintro/tools/definitions/<tool>.py
中(通过
@register_tool
装饰器),由
lintro/parsers/<tool>/
解析,在
tests/unit/
中进行测试,示例违规文件存放于
test_samples/tools/

Related Skills

相关技能

  • stand-py
    : Python coding standards (type hints, docstrings, trailing commas)
  • test
    : pytest best practices (no classes, use fixtures, parametrize)
  • commit
    : semantic commit format when committing changes
  • stand-py
    :Python编码规范(类型提示、文档字符串、尾随逗号)
  • test
    :pytest最佳实践(不使用类、使用fixture、参数化)
  • commit
    :提交变更时遵循语义化提交格式

How to Implement: Copy a Reference, Don't Write From Scratch

实现方式:参考现有实现,不要从零编写

Do NOT write plugin/parser/test code from a template. Pick the closest existing implementation, read all of its files (definition, issue class, parser, parser
__init__.py
, sample violation file, parser tests, plugin tests), and mirror that structure exactly for the new tool:
  • Simple tool (no fix):
    lintro/tools/definitions/actionlint.py
    ,
    hadolint.py
  • Tool with fix support:
    lintro/tools/definitions/ruff.py
    ,
    black.py
  • Security scanner:
    lintro/tools/definitions/bandit.py
    ,
    semgrep.py
  • Shell tools:
    lintro/tools/definitions/shellcheck.py
    ,
    shfmt.py
The parser lives in
lintro/parsers/<reference-tool>/
and its tests in
tests/unit/parsers/
and
tests/unit/tools/<reference-tool>/
— copy the pattern from the same reference tool so imports, mocking, and naming stay consistent.
请勿从模板编写插件/解析器/测试代码。选择最接近的现有实现,阅读其所有文件(定义、问题类、解析器、解析器
__init__.py
、示例违规文件、解析器测试、插件测试),并完全镜像该结构来实现新工具:
  • 无修复功能的简单工具
    lintro/tools/definitions/actionlint.py
    hadolint.py
  • 支持修复功能的工具
    lintro/tools/definitions/ruff.py
    black.py
  • 安全扫描工具
    lintro/tools/definitions/bandit.py
    semgrep.py
  • Shell工具
    lintro/tools/definitions/shellcheck.py
    shfmt.py
解析器位于
lintro/parsers/<reference-tool>/
,其测试文件在
tests/unit/parsers/
tests/unit/tools/<reference-tool>/
中——复制同一参考工具的模式,确保导入、模拟和命名保持一致。

Quick Reference

快速参考

New files (paths)

新增文件(路径)

text
lintro/parsers/<tool>/__init__.py
lintro/parsers/<tool>/<tool>_issue.py
lintro/parsers/<tool>/<tool>_parser.py
lintro/tools/definitions/<tool>.py
test_samples/tools/<category>/<tool>/<tool>_violations.<ext>
tests/unit/parsers/test_<tool>_parser.py
tests/unit/tools/<tool>/__init__.py
tests/unit/tools/<tool>/test_<tool>_plugin.py
text
lintro/parsers/<tool>/__init__.py
lintro/parsers/<tool>/<tool>_issue.py
lintro/parsers/<tool>/<tool>_parser.py
lintro/tools/definitions/<tool>.py
test_samples/tools/<category>/<tool>/<tool>_violations.<ext>
tests/unit/parsers/test_<tool>_parser.py
tests/unit/tools/<tool>/__init__.py
tests/unit/tools/<tool>/test_<tool>_plugin.py

Updated files (paths)

需要更新的文件(路径)

text
lintro/enums/tool_name.py              # Add to ToolName enum (alphabetical)
lintro/tools/core/version_parsing.py   # Add to TOOLS_WITH_SIMPLE_VERSION_PATTERN
lintro/tools/core/version_checking.py  # Add install hints in get_install_hints()
lintro/_tool_versions.py               # Add version (external tools only)
lintro/tools/manifest.json             # Add tool entry (version MUST match _tool_versions.py)
lintro/cli_utils/commands/doctor.py    # Add to TOOL_COMMANDS for health check
package.json                           # Add version for npm tools (must match _tool_versions.py)
renovate.json                          # Add custom managers for BOTH _tool_versions.py AND manifest.json
pyproject.toml                         # Add parser package + [tool.lintro.versions] entry
Dockerfile                             # Add to verification steps (root AND non-root blocks)
Dockerfile.tools                       # Add to verification step (tool --version)
scripts/utils/install-tools.sh         # Add installation command (external tools)
scripts/ci/homebrew/templates/lintro.rb.template  # Add depends_on + update caveats (if Homebrew-installable)
For every updated file, find an existing tool's entry in that file and add the new tool the same way (alphabetical order where the file is ordered).
text
lintro/enums/tool_name.py              # 按字母顺序添加至ToolName枚举
lintro/tools/core/version_parsing.py   # 添加至TOOLS_WITH_SIMPLE_VERSION_PATTERN
lintro/tools/core/version_checking.py  # 在get_install_hints()中添加安装提示
lintro/_tool_versions.py               # 添加版本号(仅限外部工具)
lintro/tools/manifest.json             # 添加工具条目(版本必须与_tool_versions.py匹配)
lintro/cli_utils/commands/doctor.py    # 添加至TOOL_COMMANDS以支持健康检查
package.json                           # 为npm工具添加版本号(必须与_tool_versions.py匹配)
renovate.json                          # 为_tool_versions.py和manifest.json添加自定义管理器
pyproject.toml                         # 添加解析器包 + [tool.lintro.versions]条目
Dockerfile                             # 添加至验证步骤(root和非root代码块)
Dockerfile.tools                       # 添加至验证步骤(tool --version)
scripts/utils/install-tools.sh         # 添加安装命令(仅限外部工具)
scripts/ci/homebrew/templates/lintro.rb.template  # 添加depends_on + 更新说明(如果支持Homebrew安装)
对于每个需要更新的文件,找到现有工具的条目,以相同方式添加新工具(文件按顺序排列时需保持字母顺序)。

Version Consistency (CRITICAL for external tools)

版本一致性(外部工具至关重要)

For external tools (not bundled Python packages), versions must be consistent across:
  1. lintro/_tool_versions.py
    — source of truth for install-tools.sh
  2. lintro/tools/manifest.json
    — must match
    _tool_versions.py
    for binary/cargo/rustup tools
  3. package.json
    — for npm tools, must match
    _tool_versions.py
  4. Plugin
    min_version
    — in the tool definition, should match or be <=
    _tool_versions.py
  5. renovate.json
    — must have custom regex managers updating BOTH
    _tool_versions.py
    AND
    manifest.json
    (copy an existing tool's pair of entries and adjust the package name and datasource)
CI enforces manifest/version sync with the manifest generator run in
--check
mode (the generate-with---check pattern from
stand-ci
— no separate verify script). PRs fail if versions drift between these files. Run the generator with
--check
locally before pushing.
对于外部工具(非捆绑Python包),版本必须在以下文件中保持一致:
  1. lintro/_tool_versions.py
    —— install-tools.sh的版本数据源
  2. lintro/tools/manifest.json
    —— 对于二进制/cargo/rustup工具,必须与
    _tool_versions.py
    匹配
  3. package.json
    —— 对于npm工具,必须与
    _tool_versions.py
    匹配
  4. 插件
    min_version
    —— 在工具定义中,应等于或小于
    _tool_versions.py
    中的版本
  5. renovate.json
    —— 必须包含自定义正则管理器,同时更新
    _tool_versions.py
    manifest.json
    (复制现有工具的条目对,调整包名和数据源)
CI会通过
--check
模式运行的清单生成器来强制清单与版本同步(采用
stand-ci
的generate-with---check模式,无需单独的验证脚本)。如果这些文件之间版本不一致,PR将失败。推送前请在本地运行带
--check
参数的生成器。

Homebrew Formula (for Homebrew-installable tools)

Homebrew公式(支持Homebrew安装的工具)

  • Add
    depends_on "<tool>"
    to
    scripts/ci/homebrew/templates/lintro.rb.template
    and list the tool in the caveats under the appropriate category.
  • Bundled Python tools (ruff, black, mypy, bandit, yamllint) are excluded from the Homebrew venv via
    generate_resources.py --exclude
    ; they install as separate Homebrew formulae and are discovered via PATH (
    shutil.which
    ), NOT
    python -m
    .
    PythonBundledBuilder
    in
    command_builders.py
    handles this automatically.
  • scripts/ci/homebrew/templates/lintro.rb.template
    中添加
    depends_on "<tool>"
    ,并在对应分类的说明中列出该工具。
  • 捆绑的Python工具(ruff、black、mypy、bandit、yamllint)通过
    generate_resources.py --exclude
    排除在Homebrew虚拟环境之外;它们作为独立的Homebrew公式安装,并通过PATH(
    shutil.which
    )被发现,而非
    python -m
    command_builders.py
    中的
    PythonBundledBuilder
    会自动处理此逻辑。

ToolType Options

ToolType选项

python
ToolType.LINTER          # Code quality checker
ToolType.FORMATTER       # Code formatter
ToolType.TYPE_CHECKER    # Type checking (mypy)
ToolType.DOCUMENTATION   # Doc checker (darglint)
ToolType.SECURITY        # Security scanner (bandit, semgrep, gitleaks)
ToolType.INFRASTRUCTURE  # IaC linter (hadolint, actionlint)
ToolType.TEST_RUNNER     # Test framework (pytest)
Can be combined:
ToolType.LINTER | ToolType.FORMATTER
python
ToolType.LINTER          # 代码质量检查器
ToolType.FORMATTER       # 代码格式化工具
ToolType.TYPE_CHECKER    # 类型检查工具(如mypy)
ToolType.DOCUMENTATION   # 文档检查工具(如darglint)
ToolType.SECURITY        # 安全扫描工具(如bandit、semgrep、gitleaks)
ToolType.INFRASTRUCTURE  # IaC检查工具(如hadolint、actionlint)
ToolType.TEST_RUNNER     # 测试框架(如pytest)
可组合使用:
ToolType.LINTER | ToolType.FORMATTER

Common Gotchas

常见注意事项

  1. Version command variations: some tools use
    version
    instead of
    --version
    (e.g.,
    gitleaks version
    ). Check the tool's CLI.
  2. ToolResult invariant for fix operations:
    initial_issues_count = fixed_issues_count + remaining_issues_count
    .
  3. Test mocking: mock the version check with
    patch("lintro.plugins.execution_preparation.verify_tool_version", return_value=None)
    and subprocess calls with
    patch.object(plugin, "_run_subprocess", ...)
    — copy the patterns from a reference tool's plugin tests.
  4. File discovery:
    _prepare_execution()
    handles filtering by
    file_patterns
    ; use
    ctx.rel_files
    for the filtered list.
  5. Subprocess safety: always use list args, never
    shell=True
    ; add
    # nosec B404
    on the subprocess import.
  6. Return early: if
    ctx.should_skip
    is True, return
    ctx.early_result
    .
  7. Parser function naming: must be
    parse_<tool>_output(output: str | None) -> list[<Tool>Issue]
    .
  8. Issue class: must inherit from
    BaseIssue
    ; use
    DISPLAY_FIELD_MAP
    for custom field name mappings.
  1. 版本命令差异:部分工具使用
    version
    而非
    --version
    (例如
    gitleaks version
    )。请检查工具的CLI文档。
  2. 修复操作的ToolResult不变量
    initial_issues_count = fixed_issues_count + remaining_issues_count
  3. 测试模拟:使用
    patch("lintro.plugins.execution_preparation.verify_tool_version", return_value=None)
    模拟版本检查,使用
    patch.object(plugin, "_run_subprocess", ...)
    模拟子进程调用——复制参考工具插件测试中的模式。
  4. 文件发现
    _prepare_execution()
    会根据
    file_patterns
    处理过滤;使用
    ctx.rel_files
    获取过滤后的文件列表。
  5. 子进程安全:始终使用列表参数,切勿使用
    shell=True
    ;在子进程导入时添加
    # nosec B404
  6. 提前返回:如果
    ctx.should_skip
    为True,返回
    ctx.early_result
  7. 解析器函数命名:必须为
    parse_<tool>_output(output: str | None) -> list[<Tool>Issue]
    格式。
  8. 问题类:必须继承自
    BaseIssue
    ;使用
    DISPLAY_FIELD_MAP
    自定义字段名称映射。

Deprecated Patterns to Avoid

需避免的已弃用模式

  • Do NOT create tool-specific formatters (use the unified formatter)
  • Do NOT modify
    lintro/tools/tool_enum.py
    (deleted — registry is automatic)
  • Do NOT modify
    lintro/tools/core/tool_base.py
    (deleted — use BaseToolPlugin)
  • 请勿创建工具专属格式化器(使用统一格式化器)
  • 请勿修改
    lintro/tools/tool_enum.py
    (已删除——注册为自动机制)
  • 请勿修改
    lintro/tools/core/tool_base.py
    (已删除——使用BaseToolPlugin)

Verification Checklist

验证清单

  • uv run lintro tools
    shows the new tool
  • uv run lintro check --tools <tool> .
    runs without error — single-tool runs are normally banned by the
    lint
    skill; this is the explicit sanctioned exception for verifying a tool under development. Still finish with a full
    uv run lintro chk
    .
  • uv run lintro doctor
    shows the tool with correct version (no "No cmd defined")
  • Tool detects violations in the sample file
  • Parser unit tests pass:
    pytest tests/unit/parsers/test_<tool>_parser.py -v
  • Plugin unit tests pass:
    pytest tests/unit/tools/<tool>/ -v
  • Coverage >80% on new code
  • No linting errors:
    uv run lintro fmt && uv run lintro chk
  • Manifest generator passes in
    --check
    mode (no version drift)
  • Tool added to
    Dockerfile
    (root and non-root blocks) and
    Dockerfile.tools
  • Tool added to
    install-tools.sh
    (external tools only)
  • Tool added to
    lintro/tools/manifest.json
    (version matches
    _tool_versions.py
    )
  • Renovate managers added for BOTH
    _tool_versions.py
    and
    manifest.json
  • Homebrew template updated with
    depends_on
    + caveats (if Homebrew-installable)
  • Docker image builds:
    docker build -t py-lintro:test .
Use the
lintro-verify
skill for the full post-implementation review.
  • uv run lintro tools
    显示新工具
  • uv run lintro check --tools <tool> .
    可正常运行无错误——通常
    lint
    技能禁止单工具运行;这是验证开发中工具的明确例外。完成后仍需运行完整的
    uv run lintro chk
  • uv run lintro doctor
    显示工具及其正确版本(无"No cmd defined"提示)
  • 工具可检测到示例文件中的违规内容
  • 解析器单元测试通过:
    pytest tests/unit/parsers/test_<tool>_parser.py -v
  • 插件单元测试通过:
    pytest tests/unit/tools/<tool>/ -v
  • 新增代码覆盖率>80%
  • 无代码检查错误:
    uv run lintro fmt && uv run lintro chk
  • 清单生成器在
    --check
    模式下通过(无版本不一致)
  • 工具已添加至
    Dockerfile
    (root和非root代码块)和
    Dockerfile.tools
  • 工具已添加至
    install-tools.sh
    (仅限外部工具)
  • 工具已添加至
    lintro/tools/manifest.json
    (版本与
    _tool_versions.py
    匹配)
  • 已为
    _tool_versions.py
    manifest.json
    添加Renovate管理器
  • Homebrew模板已更新
    depends_on
    + 说明(如果支持Homebrew安装)
  • Docker镜像可构建:
    docker build -t py-lintro:test .
使用
lintro-verify
技能进行完整的实现后审查。