Skip to content

Commit

Permalink
Add support for ruff
Browse files Browse the repository at this point in the history
  • Loading branch information
FrostyX committed Aug 24, 2024
1 parent 20ac0f7 commit f1926fc
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 1 deletion.
22 changes: 21 additions & 1 deletion vcs-diff-lint
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ CSDIFF_PYLINT = os.path.realpath(os.path.join(os.path.dirname(__file__),
CSDIFF_MYPY = os.path.realpath(os.path.join(os.path.dirname(__file__),
'vcs-diff-lint-csdiff-mypy'))

CSDIFF_RUFF = os.path.realpath(
os.path.join(os.path.dirname(__file__), 'vcs-diff-lint-csdiff-ruff'))


def _run_csdiff(old, new, msg):
popen_diff = Popen(['csdiff', '-c', old, new],
Expand Down Expand Up @@ -170,6 +173,23 @@ class MypyLinter(_Linter):
return cmd, {}


class RuffLinter(_Linter):
"""
Generate Ruff error output compatible with 'csdiff'.
"""
linter_tags = [
"ruff",
"python",
]

def is_compatible(self, file):
return file.type == 'python'

def command(self, projectdir, filenames):
cmd = [CSDIFF_RUFF] + filenames
return cmd, {}


def get_rename_map(options, subdir):
"""
Using the os.getcwd() and 'git diff --namestatus', generate list of
Expand Down Expand Up @@ -213,7 +233,7 @@ class _Worker: # pylint: disable=too-few-public-methods
projectsubdir = None
workdir = None
checkout = None
linters = [PylintLinter, MypyLinter]
linters = [PylintLinter, MypyLinter, RuffLinter]

def __init__(self, options):
self.options = options
Expand Down
64 changes: 64 additions & 0 deletions vcs-diff-lint-csdiff-ruff
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#! /usr/bin/python3

"""
The csdiff tool doesn't support the Ruff's JSON output yet. So this just a
trivial wrapper which reads Ruff's report and transforms it to JSON which is
supported by csdiff.
The script accepts the same parameters as `ruff check` itself.
"""

import os
import sys
import json
from subprocess import Popen, PIPE


def ruff_check():
"""
Run `ruff check` and return a dict with its results
"""
cmd = ["ruff", "check", "--output-format=json"] + sys.argv[1:]
proc = Popen(cmd, stdout=PIPE)
out, _err = proc.communicate(timeout=60)
return json.loads(out)


def ruff_code_to_name(code):
"""
Convert noqa code e.g. F401 to its human-readable name, e.g. unused-import
"""
# This implementation will likely kill all ruff performance benefits
cmd = ["ruff", "rule", code, "--output-format=json"]
proc = Popen(cmd, stdout=PIPE)
out, _err = proc.communicate(timeout=60)
data = json.loads(out)
return data["name"]


def main():
"""
The main fuction
"""
defects = ruff_check()
for defect in defects:
path = os.path.relpath(defect["filename"])
column = defect["location"]["column"] or ""
colsep = ":" if column else ""
event = "{0}[{1}]".format(
defect["code"], ruff_code_to_name(defect["code"]))

print("Error: RUFF_WARNING:")
print("{file}:{line}{colsep}{column}: {event}: {msg}".format(
file=path,
line=defect["location"]["row"],
colsep=colsep,
column=column,
event=event,
msg=defect["message"],
))
print()


if __name__ == "__main__":
sys.exit(main())

0 comments on commit f1926fc

Please sign in to comment.