Skip to content

Commit 1ad1991

Browse files
authored
Merge pull request #137 from Nerixyz/chore/more-linting
Fix remaining Ruff lints and (most) type errors
2 parents 50001b3 + 87a563c commit 1ad1991

File tree

3 files changed

+64
-71
lines changed

3 files changed

+64
-71
lines changed

post/clang_tidy_review/clang_tidy_review/__init__.py

+59-65
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import base64
88
import contextlib
99
import fnmatch
10-
import glob
1110
import io
1211
import itertools
1312
import json
@@ -19,13 +18,15 @@
1918
import textwrap
2019
import zipfile
2120
from operator import itemgetter
22-
from typing import Dict, List, Optional, TypedDict
21+
from pathlib import Path
22+
from typing import Any, Dict, List, Optional, TypedDict
2323

2424
import unidiff
2525
import urllib3
2626
import yaml
2727
from github import Auth, Github
2828
from github.PaginatedList import PaginatedList
29+
from github.PullRequest import ReviewComment
2930
from github.Requester import Requester
3031
from github.WorkflowRun import WorkflowRun
3132

@@ -46,20 +47,10 @@ class Metadata(TypedDict):
4647
pr_number: int
4748

4849

49-
class PRReviewComment(TypedDict):
50-
path: str
51-
position: Optional[int]
52-
body: str
53-
line: Optional[int]
54-
side: Optional[str]
55-
start_line: Optional[int]
56-
start_side: Optional[str]
57-
58-
5950
class PRReview(TypedDict):
6051
body: str
6152
event: str
62-
comments: List[PRReviewComment]
53+
comments: list[ReviewComment]
6354

6455

6556
class HashableComment:
@@ -125,7 +116,7 @@ def add_auth_arguments(parser: argparse.ArgumentParser):
125116
group_app.add_argument("--installation-id", type=int, help="app installation ID")
126117

127118

128-
def get_auth_from_arguments(args: argparse.Namespace) -> Auth:
119+
def get_auth_from_arguments(args: argparse.Namespace) -> Auth.Auth:
129120
if args.token:
130121
return Auth.Token(args.token)
131122

@@ -251,7 +242,7 @@ def config_file_or_checks(
251242
def load_clang_tidy_warnings():
252243
"""Read clang-tidy warnings from FIXES_FILE. Can be produced by build_clang_tidy_warnings"""
253244
try:
254-
with open(FIXES_FILE) as fixes_file:
245+
with Path(FIXES_FILE).open() as fixes_file:
255246
return yaml.safe_load(fixes_file)
256247
except FileNotFoundError:
257248
return {}
@@ -260,7 +251,7 @@ def load_clang_tidy_warnings():
260251
class PullRequest:
261252
"""Add some convenience functions not in PyGithub"""
262253

263-
def __init__(self, repo: str, pr_number: Optional[int], auth: Auth) -> None:
254+
def __init__(self, repo: str, pr_number: Optional[int], auth: Auth.Auth) -> None:
264255
self.repo_name = repo
265256
self.pr_number = pr_number
266257
self.auth = auth
@@ -402,12 +393,12 @@ def make_file_offset_lookup(filenames):
402393
lookup = {}
403394

404395
for filename in filenames:
405-
with open(filename) as file:
396+
with Path(filename).open() as file:
406397
lines = file.readlines()
407398
# Length of each line
408399
line_lengths = map(len, lines)
409400
# Cumulative sum of line lengths => offset at end of each line
410-
lookup[os.path.abspath(filename)] = [
401+
lookup[Path(filename).resolve().as_posix()] = [
411402
0,
412403
*list(itertools.accumulate(line_lengths)),
413404
]
@@ -427,22 +418,21 @@ def get_diagnostic_file_path(clang_tidy_diagnostic, build_dir):
427418
file_path = clang_tidy_diagnostic["DiagnosticMessage"]["FilePath"]
428419
if file_path == "":
429420
return ""
430-
if os.path.isabs(file_path):
431-
return os.path.normpath(os.path.abspath(file_path))
421+
file_path = Path(file_path)
422+
if file_path.is_absolute():
423+
return os.path.normpath(file_path.resolve())
432424
if "BuildDirectory" in clang_tidy_diagnostic:
433425
return os.path.normpath(
434-
os.path.abspath(
435-
os.path.join(clang_tidy_diagnostic["BuildDirectory"], file_path)
436-
)
426+
(Path(clang_tidy_diagnostic["BuildDirectory"]) / file_path).resolve()
437427
)
438-
return os.path.normpath(os.path.abspath(file_path))
428+
return os.path.normpath(file_path.resolve())
439429

440430
# Pre-clang-tidy-9 format
441431
if "FilePath" in clang_tidy_diagnostic:
442432
file_path = clang_tidy_diagnostic["FilePath"]
443433
if file_path == "":
444434
return ""
445-
return os.path.normpath(os.path.abspath(os.path.join(build_dir, file_path)))
435+
return os.path.normpath((Path(build_dir) / file_path).resolve())
446436

447437
return ""
448438

@@ -469,7 +459,7 @@ def find_line_number_from_offset(offset_lookup, filename, offset):
469459
def read_one_line(filename, line_offset):
470460
"""Read a single line from a source file"""
471461
# Could cache the files instead of opening them each time?
472-
with open(filename) as file:
462+
with Path(filename).open() as file:
473463
file.seek(line_offset)
474464
return file.readline().rstrip("\n")
475465

@@ -493,7 +483,7 @@ def collate_replacement_sets(diagnostic, offset_lookup):
493483
# from the FilePath and we'll end up looking for a path that's not in
494484
# the lookup dict
495485
# To fix this, we'll convert all the FilePaths to absolute paths
496-
replacement["FilePath"] = os.path.abspath(replacement["FilePath"])
486+
replacement["FilePath"] = Path(replacement["FilePath"]).resolve().as_posix()
497487

498488
# It's possible the replacement is needed in another file?
499489
# Not really sure how that could come about, but let's
@@ -540,7 +530,7 @@ def replace_one_line(replacement_set, line_num, offset_lookup):
540530
line_offset = offset_lookup[filename][line_num]
541531

542532
# List of (start, end) offsets from line_offset
543-
insert_offsets = [(0, 0)]
533+
insert_offsets: list[tuple[Optional[int], Optional[int]]] = [(0, 0)]
544534
# Read all the source lines into a dict so we only get one copy of
545535
# each line, though we might read the same line in multiple times
546536
source_lines = {}
@@ -661,7 +651,7 @@ def fix_absolute_paths(build_compile_commands, base_dir):
661651
print(f"Found '{build_compile_commands}', updating absolute paths")
662652
# We might need to change some absolute paths if we're inside
663653
# a docker container
664-
with open(build_compile_commands) as f:
654+
with Path(build_compile_commands).open() as f:
665655
compile_commands = json.load(f)
666656

667657
print(f"Replacing '{basedir}' with '{newbasedir}'", flush=True)
@@ -670,7 +660,7 @@ def fix_absolute_paths(build_compile_commands, base_dir):
670660
str(basedir), str(newbasedir)
671661
)
672662

673-
with open(build_compile_commands, "w") as f:
663+
with Path(build_compile_commands).open("w") as f:
674664
f.write(modified_compile_commands)
675665

676666

@@ -756,7 +746,7 @@ def create_review_file(
756746
if "Diagnostics" not in clang_tidy_warnings:
757747
return None
758748

759-
comments: List[PRReviewComment] = []
749+
comments: List[ReviewComment] = []
760750

761751
for diagnostic in clang_tidy_warnings["Diagnostics"]:
762752
try:
@@ -930,32 +920,34 @@ def create_review(
930920
files = filter_files(diff, include, exclude)
931921

932922
if files == []:
933-
with message_group("No files to check!"):
934-
with open(REVIEW_FILE, "w") as review_file:
935-
json.dump(
936-
{
937-
"body": "clang-tidy found no files to check",
938-
"event": "COMMENT",
939-
"comments": [],
940-
},
941-
review_file,
942-
)
923+
with message_group("No files to check!"), Path(REVIEW_FILE).open(
924+
"w"
925+
) as review_file:
926+
json.dump(
927+
{
928+
"body": "clang-tidy found no files to check",
929+
"event": "COMMENT",
930+
"comments": [],
931+
},
932+
review_file,
933+
)
943934
return None
944935

945936
print(f"Checking these files: {files}", flush=True)
946937

947938
line_ranges = get_line_ranges(diff, files)
948939
if line_ranges == "[]":
949-
with message_group("No lines added in this PR!"):
950-
with open(REVIEW_FILE, "w") as review_file:
951-
json.dump(
952-
{
953-
"body": "clang-tidy found no lines added",
954-
"event": "COMMENT",
955-
"comments": [],
956-
},
957-
review_file,
958-
)
940+
with message_group("No lines added in this PR!"), Path(REVIEW_FILE).open(
941+
"w"
942+
) as review_file:
943+
json.dump(
944+
{
945+
"body": "clang-tidy found no lines added",
946+
"event": "COMMENT",
947+
"comments": [],
948+
},
949+
review_file,
950+
)
959951
return None
960952

961953
print(f"Line filter for clang-tidy:\n{line_ranges}\n")
@@ -997,7 +989,7 @@ def create_review(
997989
review = create_review_file(
998990
clang_tidy_warnings, diff_lookup, offset_lookup, build_dir
999991
)
1000-
with open(REVIEW_FILE, "w") as review_file:
992+
with Path(REVIEW_FILE).open("w") as review_file:
1001993
json.dump(review, review_file)
1002994

1003995
return review
@@ -1049,7 +1041,7 @@ def load_metadata() -> Optional[Metadata]:
10491041
print(f"WARNING: Could not find metadata file ('{METADATA_FILE}')", flush=True)
10501042
return None
10511043

1052-
with open(METADATA_FILE) as metadata_file:
1044+
with Path(METADATA_FILE).open() as metadata_file:
10531045
return json.load(metadata_file)
10541046

10551047

@@ -1058,7 +1050,7 @@ def save_metadata(pr_number: int) -> None:
10581050

10591051
metadata: Metadata = {"pr_number": pr_number}
10601052

1061-
with open(METADATA_FILE, "w") as metadata_file:
1053+
with Path(METADATA_FILE).open("w") as metadata_file:
10621054
json.dump(metadata, metadata_file)
10631055

10641056

@@ -1069,15 +1061,15 @@ def load_review(review_file: pathlib.Path) -> Optional[PRReview]:
10691061
print(f"WARNING: Could not find review file ('{review_file}')", flush=True)
10701062
return None
10711063

1072-
with open(review_file) as review_file_handle:
1064+
with review_file.open() as review_file_handle:
10731065
payload = json.load(review_file_handle)
10741066
return payload or None
10751067

10761068

10771069
def load_and_merge_profiling() -> Dict:
10781070
result = {}
1079-
for profile_file in glob.iglob(os.path.join(PROFILE_DIR, "*.json")):
1080-
profile_dict = json.load(open(profile_file))
1071+
for profile_file in Path(PROFILE_DIR).glob("*.json"):
1072+
profile_dict = json.load(profile_file.open())
10811073
filename = profile_dict["file"]
10821074
current_profile = result.get(filename, {})
10831075
for check, timing in profile_dict["profile"].items():
@@ -1150,7 +1142,7 @@ def get_line_ranges(diff, files):
11501142
# Adding a copy of the line filters with backslashes allows for both cl.exe and clang.exe to work.
11511143
if os.path.sep == "\\":
11521144
# Converts name to backslashes for the cl.exe line filter.
1153-
name = os.path.join(*name.split("/"))
1145+
name = Path.joinpath(*name.split("/"))
11541146
line_filter_json.append({"name": name, "lines": lines})
11551147
return json.dumps(line_filter_json, separators=(",", ":"))
11561148

@@ -1196,7 +1188,7 @@ def set_output(key: str, val: str) -> bool:
11961188
return False
11971189

11981190
# append key-val pair to file
1199-
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
1191+
with Path(os.environ["GITHUB_OUTPUT"]).open("a") as f:
12001192
f.write(f"{key}={val}\n")
12011193

12021194
return True
@@ -1207,7 +1199,7 @@ def set_summary(val: str) -> bool:
12071199
return False
12081200

12091201
# append key-val pair to file
1210-
with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as f:
1202+
with Path(os.environ["GITHUB_STEP_SUMMARY"]).open("a") as f:
12111203
f.write(val)
12121204

12131205
return True
@@ -1223,10 +1215,10 @@ def decorate_check_names(comment: str) -> str:
12231215
url = f"https://clang.llvm.org/{version}/clang-tidy/checks"
12241216
regex = r"(\[((?:clang-analyzer)|(?:(?!clang)[\w]+))-([\.\w-]+)\]$)"
12251217
subst = f"[\\g<1>({url}/\\g<2>/\\g<3>.html)]"
1226-
return re.sub(regex, subst, comment, 1, re.MULTILINE)
1218+
return re.sub(regex, subst, comment, count=1, flags=re.MULTILINE)
12271219

12281220

1229-
def decorate_comment(comment: PRReviewComment) -> PRReviewComment:
1221+
def decorate_comment(comment: ReviewComment) -> ReviewComment:
12301222
comment["body"] = decorate_check_names(comment["body"])
12311223
return comment
12321224

@@ -1287,10 +1279,12 @@ def convert_comment_to_annotations(comment):
12871279
}
12881280

12891281

1290-
def post_annotations(pull_request: PullRequest, review: Optional[PRReview]) -> int:
1282+
def post_annotations(
1283+
pull_request: PullRequest, review: Optional[PRReview]
1284+
) -> Optional[int]:
12911285
"""Post the first 10 comments in the review as annotations"""
12921286

1293-
body = {
1287+
body: dict[str, Any] = {
12941288
"name": "clang-tidy-review",
12951289
"head_sha": pull_request.pull_request.head.sha,
12961290
"status": "completed",
@@ -1308,7 +1302,7 @@ def post_annotations(pull_request: PullRequest, review: Optional[PRReview]) -> i
13081302
for comment in review["comments"]:
13091303
first_line = comment["body"].splitlines()[0]
13101304
comments.append(
1311-
f"{comment['path']}:{comment.get('start_line', comment['line'])}: {first_line}"
1305+
f"{comment['path']}:{comment.get('start_line', comment.get('line', 0))}: {first_line}"
13121306
)
13131307

13141308
total_comments = len(review["comments"])

post/clang_tidy_review/clang_tidy_review/post.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def main() -> int:
105105
pull_request, review, args.max_comments, lgtm_comment_body, args.dry_run
106106
)
107107

108-
return exit_code if args.num_comments_as_exitcode else 0
108+
return (exit_code or 0) if args.num_comments_as_exitcode else 0
109109

110110

111111
if __name__ == "__main__":

post/clang_tidy_review/clang_tidy_review/review.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66
# See LICENSE for more information
77

88
import argparse
9-
import os
10-
import pathlib
119
import re
1210
import subprocess
11+
from pathlib import Path
1312

1413
from clang_tidy_review import (
1514
PullRequest,
@@ -39,7 +38,7 @@ def main():
3938
"--clang_tidy_binary",
4039
help="clang-tidy binary",
4140
default="clang-tidy-14",
42-
type=pathlib.Path,
41+
type=Path,
4342
)
4443
parser.add_argument(
4544
"--build_dir", help="Directory with compile_commands.json", default="."
@@ -145,7 +144,7 @@ def main():
145144
with message_group(f"Running cmake: {cmake_command}"):
146145
subprocess.run(cmake_command, shell=True, check=True)
147146

148-
elif os.path.exists(build_compile_commands):
147+
elif Path(build_compile_commands).exists():
149148
fix_absolute_paths(build_compile_commands, args.base_dir)
150149

151150
pull_request = PullRequest(args.repo, args.pr, get_auth_from_arguments(args))
@@ -165,7 +164,7 @@ def main():
165164

166165
if args.split_workflow:
167166
total_comments = 0 if review is None else len(review["comments"])
168-
set_output("total_comments", total_comments)
167+
set_output("total_comments", str(total_comments))
169168
print("split_workflow is enabled, not posting review")
170169
return
171170

0 commit comments

Comments
 (0)