mirror of https://github.com/python/cpython
gh-112301: Add warning count to warning check tooling (#122711)
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
This commit is contained in:
parent
8e2dc7f380
commit
1cf624be6d
|
@ -0,0 +1,2 @@
|
|||
Add ability to ignore warnings per file with warning count in warning checking tooling.
|
||||
Patch by Nate Ohlson.
|
|
@ -1,3 +1,5 @@
|
|||
# Files listed will be ignored by the compiler warning checker
|
||||
# for the macOS/build and test job.
|
||||
# Keep lines sorted lexicographically to help avoid merge conflicts.
|
||||
# Format example:
|
||||
# /path/to/file (number of warnings in file)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# Files listed will be ignored by the compiler warning checker
|
||||
# for the Ubuntu/build and test job.
|
||||
# Keep lines sorted lexicographically to help avoid merge conflicts.
|
||||
# Format example:
|
||||
# /path/to/file (number of warnings in file)
|
||||
|
|
|
@ -9,6 +9,11 @@ import json
|
|||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import NamedTuple
|
||||
|
||||
class FileWarnings(NamedTuple):
|
||||
name: str
|
||||
count: int
|
||||
|
||||
|
||||
def extract_warnings_from_compiler_output_clang(
|
||||
|
@ -19,7 +24,8 @@ def extract_warnings_from_compiler_output_clang(
|
|||
"""
|
||||
# Regex to find warnings in the compiler output
|
||||
clang_warning_regex = re.compile(
|
||||
r"(?P<file>.*):(?P<line>\d+):(?P<column>\d+): warning: (?P<message>.*)"
|
||||
r"(?P<file>.*):(?P<line>\d+):(?P<column>\d+): warning: "
|
||||
r"(?P<message>.*) (?P<option>\[-[^\]]+\])$"
|
||||
)
|
||||
compiler_warnings = []
|
||||
for line in compiler_output.splitlines():
|
||||
|
@ -30,6 +36,7 @@ def extract_warnings_from_compiler_output_clang(
|
|||
"line": match.group("line"),
|
||||
"column": match.group("column"),
|
||||
"message": match.group("message"),
|
||||
"option": match.group("option").lstrip("[").rstrip("]"),
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -49,9 +56,7 @@ def extract_warnings_from_compiler_output_json(
|
|||
"""
|
||||
# Regex to find json arrays at the top level of the file
|
||||
# in the compiler output
|
||||
json_arrays = re.findall(
|
||||
r"\[(?:[^[\]]|\[[^\]]*\])*\]", compiler_output
|
||||
)
|
||||
json_arrays = re.findall(r"\[(?:[^[\]]|\[[^]]*])*]", compiler_output)
|
||||
compiler_warnings = []
|
||||
for array in json_arrays:
|
||||
try:
|
||||
|
@ -74,6 +79,7 @@ def extract_warnings_from_compiler_output_json(
|
|||
"line": location[key]["line"],
|
||||
"column": location[key]["column"],
|
||||
"message": warning["message"],
|
||||
"option": warning["option"],
|
||||
}
|
||||
)
|
||||
# Found a caret, start, or end in location so
|
||||
|
@ -92,18 +98,26 @@ def extract_warnings_from_compiler_output_json(
|
|||
def get_warnings_by_file(warnings: list[dict]) -> dict[str, list[dict]]:
|
||||
"""
|
||||
Returns a dictionary where the key is the file and the data is the warnings
|
||||
in that file
|
||||
in that file. Does not include duplicate warnings for a file from list of
|
||||
provided warnings.
|
||||
"""
|
||||
warnings_by_file = defaultdict(list)
|
||||
warnings_added = set()
|
||||
for warning in warnings:
|
||||
warnings_by_file[warning["file"]].append(warning)
|
||||
warning_key = (
|
||||
f"{warning['file']}-{warning['line']}-"
|
||||
f"{warning['column']}-{warning['option']}"
|
||||
)
|
||||
if warning_key not in warnings_added:
|
||||
warnings_added.add(warning_key)
|
||||
warnings_by_file[warning["file"]].append(warning)
|
||||
|
||||
return warnings_by_file
|
||||
|
||||
|
||||
def get_unexpected_warnings(
|
||||
files_with_expected_warnings: set[str],
|
||||
files_with_warnings: dict[str, list[dict]],
|
||||
files_with_expected_warnings: set[FileWarnings],
|
||||
files_with_warnings: set[FileWarnings],
|
||||
) -> int:
|
||||
"""
|
||||
Returns failure status if warnings discovered in list of warnings
|
||||
|
@ -112,7 +126,14 @@ def get_unexpected_warnings(
|
|||
"""
|
||||
unexpected_warnings = []
|
||||
for file in files_with_warnings.keys():
|
||||
if file not in files_with_expected_warnings:
|
||||
found_file_in_ignore_list = False
|
||||
for ignore_file in files_with_expected_warnings:
|
||||
if file == ignore_file.name:
|
||||
if len(files_with_warnings[file]) > ignore_file.count:
|
||||
unexpected_warnings.extend(files_with_warnings[file])
|
||||
found_file_in_ignore_list = True
|
||||
break
|
||||
if not found_file_in_ignore_list:
|
||||
unexpected_warnings.extend(files_with_warnings[file])
|
||||
|
||||
if unexpected_warnings:
|
||||
|
@ -125,8 +146,8 @@ def get_unexpected_warnings(
|
|||
|
||||
|
||||
def get_unexpected_improvements(
|
||||
files_with_expected_warnings: set[str],
|
||||
files_with_warnings: dict[str, list[dict]],
|
||||
files_with_expected_warnings: set[FileWarnings],
|
||||
files_with_warnings: set[FileWarnings],
|
||||
) -> int:
|
||||
"""
|
||||
Returns failure status if there are no warnings in the list of warnings
|
||||
|
@ -134,13 +155,15 @@ def get_unexpected_improvements(
|
|||
"""
|
||||
unexpected_improvements = []
|
||||
for file in files_with_expected_warnings:
|
||||
if file not in files_with_warnings.keys():
|
||||
if file.name not in files_with_warnings.keys():
|
||||
unexpected_improvements.append(file)
|
||||
elif len(files_with_warnings[file.name]) < file.count:
|
||||
unexpected_improvements.append(file)
|
||||
|
||||
if unexpected_improvements:
|
||||
print("Unexpected improvements:")
|
||||
for file in unexpected_improvements:
|
||||
print(file)
|
||||
print(file.name)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
@ -214,8 +237,11 @@ def main(argv: list[str] | None = None) -> int:
|
|||
with Path(args.warning_ignore_file_path).open(
|
||||
encoding="UTF-8"
|
||||
) as clean_files:
|
||||
# Files with expected warnings are stored as a set of tuples
|
||||
# where the first element is the file name and the second element
|
||||
# is the number of warnings expected in that file
|
||||
files_with_expected_warnings = {
|
||||
file.strip()
|
||||
FileWarnings(file.strip().split()[0], int(file.strip().split()[1]))
|
||||
for file in clean_files
|
||||
if file.strip() and not file.startswith("#")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue