15 个版本 (5 个重大更新)

0.8.0 2022年5月6日
0.5.3 2021年11月17日
0.4.3 2021年11月12日
0.3.0 2021年11月4日
0.1.1 2021年10月22日

#1867开发工具

每月39 次下载

BSD-3-Clause

78KB
1.5K SLoC

Lintrunner

概述

lintrunner 是一个运行代码检查的工具。它负责

  • 决定哪些文件需要进行代码检查。
  • 根据通用协议调用代码检查器。
  • 收集结果并向用户展示。

目的是提供一个通用的方式来配置和调用代码检查器,这在大型多语言项目中非常有用。

lintrunner 的设计受到了 Meta 内部项目 linttool 的极大启发。

安装

pip install lintrunner

使用方法

首先,您需要将配置文件添加到您的代码库中。有关更多信息,请参阅代码检查配置部分。

然后,只需运行 lintrunner 来检查您的更改!

如何控制 lintrunner 检查的路径

当不带参数运行时,lintrunner 将检查

  • HEAD 提交中更改的文件。
  • 用户工作树中更改的文件。

它不会检查

  • 任何未被 git 跟踪的文件;通过 git add 将它们添加到代码检查。

有多种方法可以自定义路径的检查方式

将路径作为位置参数传递

例如

lintrunner foo.py bar.cpp

这自然与 xargs 结合使用,例如检查代码库中每个路径的规范方式是

git grep -Il . | xargs lintrunner

--paths-cmd

某些调用 xargs 的方式会导致运行多个 lintrunner 进程,从而增加代码检查时间(特别是在大型路径集上)。作为替代方案,您可以使用 --paths-cmd 来使 lintrunner 控制并行化。如果指定了 --paths-cmd,则 lintrunner 将执行该命令,并将其 stdout 的每一行视为一个要检查的文件。

例如,上面的相同命令将是

lintrunner --paths-cmd='git grep -Il .'

--paths-file

如果指定了此选项,lintrunner将从给定文件中读取路径,每行一个,并检查这些路径。如果您有一些非常复杂的逻辑来确定要检查的路径,这可能会很有用。

--revision

此值可以是git diff-tree接受的任何<tree-ish>,例如提交哈希或revspec。如果指定了此选项,lintrunner将检查

  • <tree-ish>HEAD的所有已更改路径
  • 用户工作树中的所有已更改路径。

--merge-base-with

--revision类似,但版本是通过计算HEAD和提供的<tree-ish>的merge-base来确定的。这对于检查特定拉取请求中的所有提交很有用。例如,对于一个针对master的拉取请求,您可以运行

lintrunner -m master

代码检查器配置

lintrunner通过查看配置文件来确定要运行哪些代码检查器和如何运行,配置文件通常命名为.lintrunner.toml

以下是一个代码检查器配置示例

[[linter]]
name = 'FLAKE8'
include_patterns = [
  'src/**/*.py',  # unix-style globs supported
  'test/**/*.py',
]
exclude_patterns = ['src/my_bad_file.py']
command = [
  'python3',
  'flake8_linter.py',
  '—-',
  # {{PATHSFILE}} gets rewritten to a tmpfile containing all paths to lint
  '@{{PATHSFILE}}',
]

配置架构的完整描述可以在这里找到。

代码检查器协议

大多数代码检查器都有自己的输出格式和参数。为了在代码检查器调用和输出上强制一致性,lintrunner实现了一个它期望代码检查器遵守的协议。在大多数情况下,需要一个小的脚本(称为代码检查器适配器)来实现特定外部代码检查器的协议。您可以在examples/中查看一些示例适配器。

调用

代码检查器将根据它们的配置中指定的command被调用。每个代码检查运行只调用一次。

如果代码检查器需要知道要运行的路径,它应接受一个{{PATHSFILE}}参数。在调用期间,字符串{{PATHSFILE}}将被替换为包含代码检查器应运行的路径的临时文件名,每行一个路径。

在代码检查器适配器中实现此功能的一种常见方法是使用argparsefromfile_prefix_chars功能。在上面的Flake8示例中,我们使用@作为fromfile_prefix_chars参数,因此argparse将自动读取{{PATHSFILE}}并将内容作为参数列表提供。

输出

任何linter想要向用户传达的lint信息都必须表示为 LintMessage。linter必须将LintMessage作为JSON Lines打印到stdout,每行一个信息。输出到stderr的内容将被忽略。

关于LintMessage模式的完整描述可以在这里找到:这里

退出

linter应该始终以代码0退出。即使在报告lint错误的情况下也是如此;lintrunner本身将根据linter的报告来决定如何退出。

为了表示一个通用的linter失败(理想情况下不应该发生!),linter可以返回一个具有path = NoneLintMessage

如果linter以非零退出,它将被lintrunner捕获,并作为一个“通用的linter失败”呈现给用户,同时将stdout/stderr展示给用户。这应该被认为是linter实现此协议的bug。

依赖关系

~11–22MB
~326K SLoC