Skip to content

Commit a155893

Browse files
committed
initial commit
The pylint maintainers decided that the interaction with an external standard and validation using a somewhat large schema (whether vendored or downloaded on the fly) risked slowing down and hindering the main project a bit too much so this makes more sense as a separate project, even if it ends up under the pylint-dev umbrella. Setup loosely inspired by emmanuel-ferdman/pylint-qt. Fixes pylint-dev/pylint#5493 Obsoletes pylint-dev/pylint#10759
0 parents  commit a155893

8 files changed

Lines changed: 717 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
permissions: {}
8+
9+
jobs:
10+
lint:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
14+
with:
15+
persist-credentials: false
16+
- uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
17+
with:
18+
python-version: 3.10
19+
- uses: uv run ruff check
20+
- if: always()
21+
uses: uv run ruff format --diff
22+
- if: always()
23+
uses: uv run mypy .
24+
25+
test:
26+
runs-on: ubuntu-latest
27+
steps:
28+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
29+
with:
30+
persist-credentials: false
31+
- uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
32+
with:
33+
python-version: 3.10
34+
- uses: uv run pytest
35+
36+
zizmor:
37+
runs-on: ubuntu-latest
38+
39+
permissions:
40+
security-events: write
41+
42+
steps:
43+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
44+
with:
45+
persist-credentials: false
46+
- uses: zizmorcore/zizmor-action@0dce2577a4760a2749d8cfb7a84b7d5585ebcb7d # v0.5.0

.gitignore

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Python-generated files
2+
__pycache__/
3+
*.py[oc]
4+
build/
5+
dist/
6+
wheels/
7+
*.egg-info
8+
9+
.python-version
10+
uv.lock
11+
12+
# Virtual environments
13+
.venv
14+
15+
# misc
16+
.pytest_cache
17+
.idea

README.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# pylint-sarif
2+
3+
pylint-sarif is a [pylint](http://pylint.org) plugin which allows outputting
4+
[SARIF][] report files.
5+
6+
[SARIF][] is a standardized structured interchange format used to exchange
7+
information between static analysis and security tools (e.g. pylint) and
8+
various types of alert systems, formatters, aggregators, ...
9+
10+
## Usage
11+
12+
pylint --load-plugins=pylint_sarif --output=format=sarif <path to source>
13+
14+
or in `pyproject.toml`:
15+
16+
[tool.pylint.main]
17+
load-plugins = ["pylint_sarif"]
18+
19+
then pass the `--output-format` still.
20+
21+
Note that pylint supports [multi-output configurations][] so it's possible
22+
to output both a machine-readable report to a file and a human-readable
23+
output to stdout.
24+
25+
## Limitations
26+
27+
[SARIF][] is a massive format, consumers only implements the bits they
28+
care about (which makes sense), but some of them may require properties
29+
which are optional per-standard, this reporter primarily targets GitHub
30+
with the official [SARIF validator][] being a secondary goal[^2].
31+
32+
Other *production* consumers should have the same status as GitHub (unless
33+
they are kind enough to remove their extra requirements). One might hope
34+
they would contribute their requirements as a validation rule but that
35+
seems challenging[^1].
36+
37+
### On URIs
38+
39+
The reporter makes use of URIs for artifacts (~files). Per
40+
["guidance on the use of artifactLocation objects"][3.4.7], `uri` *should*
41+
capture the deterministic part `of` the artifact location and `uriBaseId`
42+
*should* capture the non-deterministic part. However as far as I can tell
43+
pylint has no requirement (and no clean way to require) consistent resolution
44+
roots: `path` is just relative to the cwd, and there is no requirement to
45+
have project-level files to use pylint. This makes the use of relative uris
46+
dodgy, but absolute uris are pretty much always broken for the purpose of
47+
*interchange* so they're not really any better.
48+
49+
As a side-note, Github [asserts][relative-uri-guidance]
50+
51+
> While this [nb: `originalUriBaseIds`] is not required by GitHub for the
52+
> code scanning results to be displayed correctly, it is required to produce
53+
> a valid SARIF output when using relative URI references.
54+
55+
However per [3.4.4][] this is incorrect, the `uriBaseId` can be resolved
56+
through end-user configuration, `originalUriBaseIds`, external information
57+
(e.g. envvars), or heuristics.
58+
59+
It would be nice to document the "relative root" via `originalUriBaseIds`
60+
(which may be omitted for that purpose per [3.14.14][], but per the above
61+
claiming a consistent project root is dodgy.
62+
63+
We *could* resolve known project files (e.g. pyproject.toml, tox.ini, etc...)
64+
in order to find a consistent root (project root, repo root, ...) and
65+
set / use that for relative URIs but that's a lot of additional complexity
66+
which I'm not sure is warranted.
67+
68+
## ???
69+
70+
- [pylint2sarif](https://github.com/GrammaTech/pylint-sarif) by @fishoak
71+
(Paul Anderson, member of the SARIF committee)
72+
- [`Sarif.Multitool convert`][] advertises pylint json input
73+
74+
## TODO
75+
76+
- Validation test via the official validator?
77+
78+
It's a bit difficult as `Sarif.Multitool` is a C# utility distributed via
79+
nuget, there is also a distribution via npm (`@microsoft/sarif-multitool`)
80+
but it's just an installation convenience, it fetches and runs the C#
81+
package (including a redistributable C# runtime, see
82+
`@microsoft/sarif-multitool-linux`)
83+
84+
[^1]: the validator seems like a pretty complicated C# project, the
85+
[Contributing a SARIF Validation Rule](https://github.com/microsoft/sarif-sdk/blob/main/docs/Contributing%20a%20SARIF%20Validation%20Rule.md)
86+
document is all dead links, and requests have mostly been rotting:
87+
right now there are 14 "New rule" issues open (8 fixed) and
88+
9 "RULE REQUEST" issues (3 fixed, 1 closed as duplicate), looks
89+
like the primary rules contributor / driver has deleted their
90+
account and the rest have generally moved away from the project
91+
(or at least reduced their activity on it)
92+
[^2]: but it's got a bunch of weird rules which either are nonsensical
93+
or are not really provided-for by pylint
94+
95+
[SARIF]: https://sarif.info/
96+
[SARIF validator]: https://sarif.info/Validation
97+
[multi-output configurations]:
98+
https://pylint.readthedocs.io/en/stable/user_guide/usage/output.html#output-options
99+
[`Sarif.Multitool convert`]:
100+
https://github.com/microsoft/sarif-sdk/blob/main/docs/multitool-usage.md
101+
[3.4.4]:
102+
https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10540869
103+
[3.4.7]:
104+
https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10540872
105+
[3.14.14]:
106+
https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10540936
107+
[relative-uri-guidance]:
108+
https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning#relative-uri-guidance-for-sarif-producers

pyproject.toml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
[build-system]
2+
requires = ["uv_build>=0.9.25,<0.10.0"]
3+
build-backend = "uv_build"
4+
5+
[project]
6+
name = "pylint-sarif"
7+
version = "0.1.0"
8+
license = "GPL-2.0-only"
9+
description = "SARIF reporter for PyLint"
10+
readme = "README.md"
11+
authors = [
12+
{ name = "Xavier Morel", email = "[email protected]" }
13+
]
14+
keywords = ["pylint", "plugin", "reporter", "sarif"]
15+
classifiers = [
16+
"Development Status :: 4 - Beta",
17+
"Environment :: Plugins",
18+
"Intended Audience :: Developers",
19+
"Operating System :: OS Independent",
20+
"Programming Language :: Python :: 3",
21+
"Programming Language :: Python :: 3.10",
22+
"Programming Language :: Python :: 3.11",
23+
"Programming Language :: Python :: 3.12",
24+
"Programming Language :: Python :: 3.13",
25+
"Programming Language :: Python :: 3.14",
26+
"Topic :: Software Development :: Quality Assurance",
27+
]
28+
requires-python = ">=3.10"
29+
dependencies = [
30+
"pylint>=3.0,<5",
31+
]
32+
33+
[dependency-groups]
34+
dev = [
35+
"tox",
36+
{include-group = "lint"},
37+
{include-group = "typecheck"},
38+
{include-group = "test"},
39+
]
40+
lint = ["ruff"]
41+
typecheck = [
42+
"mypy",
43+
"types-requests",
44+
{include-group = "test"}
45+
]
46+
test = [
47+
"pytest",
48+
"requests",
49+
"jsonschema",
50+
]
51+
52+
[tool.pytest.ini_options]
53+
testpaths = ["tests"]
54+
addopts = "-v"
55+
56+
[tool.ruff]
57+
target-version = "py310"
58+
lint = {"select" = ["E", "F", "W", "I", "UP", "B", "RUF"]}
59+
60+
[tool.mypy]
61+
python_version = "3.10"
62+
strict = true
63+
warn_unreachable = true
64+
show_error_codes = true
65+
exclude = [
66+
"^.venv",
67+
"^build/",
68+
"^dist/",
69+
]
70+
71+
[[tool.mypy.overrides]]
72+
module = [
73+
"astroid.*",
74+
"pylint.*",
75+
]
76+
ignore_missing_imports = true

0 commit comments

Comments
 (0)