Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5148727
Create simple warning check tool and add to ubuntu build and test job
nohlson Jul 13, 2024
3bd5a10
Add flags to check warnings script to fail on regression or improvement
nohlson Jul 13, 2024
6813003
Remove redundant comment
nohlson Jul 13, 2024
ab4d754
Rename warnigore file to warningignore
nohlson Jul 13, 2024
615d228
Use regex to extract json arrays
nohlson Jul 13, 2024
fc0a60b
Trim whitespace
nohlson Jul 13, 2024
7793d80
Test on github unexpected improvement
nohlson Jul 13, 2024
99715d2
Add config for improve fail check
nohlson Jul 13, 2024
bc44ec2
Revert to prod check warning state
nohlson Jul 13, 2024
e2ca75f
📜🤖 Added by blurb_it.
blurb-it[bot] Jul 13, 2024
bd1634e
Refactor creating set of files with warnings to a dedicated function
nohlson Jul 17, 2024
b07b1d6
Move cflags configure option to top level build configuration
nohlson Jul 23, 2024
e1954a5
Add json diagnostics to ubuntu configuration as first argument
nohlson Jul 23, 2024
5935143
Add newline to news
nohlson Jul 23, 2024
7f1a238
Create simple warning check tool and add to ubuntu build and test job
nohlson Jul 13, 2024
144136e
Add macos warning checks to GitHub actions
nohlson Jul 22, 2024
3dd40fd
Revert reusable-macos.yml for environment variables
nohlson Jul 22, 2024
1158f53
Update paths
nohlson Jul 22, 2024
cb51b4f
Test unexpected improvement
nohlson Jul 22, 2024
77e0f6e
Remove warning ignore
nohlson Jul 22, 2024
3e1d75f
Add json output option to macos configure job
nohlson Jul 22, 2024
b5cd58a
Add common dictionary format when parsing warnings
nohlson Jul 23, 2024
02f313e
Remove configure option for macos job
nohlson Jul 23, 2024
83d1ed7
Print out json version of compiler output
nohlson Jul 23, 2024
08a6f6d
Remove old version of warning ignore file
nohlson Jul 23, 2024
7be8ee6
Remove compiler output print diagnostic
nohlson Jul 24, 2024
8b0a2ee
📜🤖 Added by blurb_it.
blurb-it[bot] Jul 24, 2024
49cbd87
Remove superfluous comment
nohlson Jul 24, 2024
522f27c
oMerge branch 'main' into add-macos-warnings-tracking-tooling
nohlson Jul 30, 2024
b654a84
Add period to news
nohlson Jul 30, 2024
7780da6
Merge branch 'main' into add-macos-warnings-tracking-tooling
nohlson Jul 31, 2024
3688c5c
Make warning ignore file optional
nohlson Jul 31, 2024
cb1f276
Add write compiler output to log and file
nohlson Jul 31, 2024
fb91e3e
Fix formatting and update regex
nohlson Jul 31, 2024
f35ba60
Fix comment formatting
nohlson Aug 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Create simple warning check tool and add to ubuntu build and test job
  • Loading branch information
nohlson committed Jul 23, 2024
commit 5148727e060c947a3fc0ebb942e4ce2dc2dad2e7
4 changes: 3 additions & 1 deletion .github/workflows/reusable-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,12 @@ jobs:
${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }}
- name: Build CPython out-of-tree
working-directory: ${{ env.CPYTHON_BUILDDIR }}
run: make -j4
run: make -j4 &> compiler_output.txt
- name: Display build info
working-directory: ${{ env.CPYTHON_BUILDDIR }}
run: make pythoninfo
- name: Check compiler warnings
run: python Tools/build/check_warnings.py --compiler-output-file-path=${{ env.CPYTHON_BUILDDIR }}/compiler_output.txt --warning-ignore-file-path ${GITHUB_WORKSPACE}/Tools/build/.warningignore_ubuntu
- name: Remount sources writable for tests
# some tests write to srcdir, lack of pyc files slows down testing
run: sudo mount $CPYTHON_RO_SRCDIR -oremount,rw
Expand Down
3 changes: 3 additions & 0 deletions Tools/build/.warnignore_ubuntu
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 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.
181 changes: 181 additions & 0 deletions Tools/build/check_warnings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
#!/usr/bin/env python3
import sys
from pathlib import Path
import argparse
import json


def extract_json_objects(compiler_output: str) -> list[dict]:

return json_objects


def extract_warnings_from_compiler_output(compiler_output: str) -> list[dict]:
"""
Extracts warnings from the compiler output when using -fdiagnostics-format=json

Compiler output as a whole is not a valid json document, but includes many json
objects and may include other output that is not json.
"""
# Extract JSON objects from the raw compiler output
compiler_output_json_objects = []
stack = []
start_index = None
for index, char in enumerate(compiler_output):
if char == '[':
if len(stack) == 0:
start_index = index # Start of a new JSON array
stack.append(char)
elif char == ']':
if len(stack) > 0:
stack.pop()
if len(stack) == 0 and start_index is not None:
try:
json_data = json.loads(compiler_output[start_index:index+1])
compiler_output_json_objects.extend(json_data)
start_index = None
except json.JSONDecodeError:
continue # Skip malformed JSON

compiler_warnings = [entry for entry in compiler_output_json_objects if entry.get('kind') == 'warning']

return compiler_warnings



def get_unexpected_warnings(
warnings: list[dict],
files_with_expected_warnings: set[str],
) -> int:
"""
Fails if there are unexpected warnings
"""
unexpected_warnings = []
for warning in warnings:
locations = warning['locations']
for location in locations:
for key in ['caret', 'start', 'end']:
if key in location:
filename = location[key]['file']
if filename not in files_with_expected_warnings:
unexpected_warnings.append(warning)

if unexpected_warnings:
print("Unexpected warnings:")
for warning in unexpected_warnings:
print(warning)
return 1


return 0


def get_unexpected_improvements(
warnings: list[dict],
files_with_expected_warnings: set[str],
) -> int:
"""
Fails if files that were expected to have warnings have no warnings
"""

# Create set of files with warnings
files_with_ewarnings = set()
for warning in warnings:
locations = warning['locations']
for location in locations:
for key in ['caret', 'start', 'end']:
if key in location:
filename = location[key]['file']
files_with_ewarnings.add(filename)



unexpected_improvements = []
for filename in files_with_expected_warnings:
if filename not in files_with_ewarnings:
unexpected_improvements.append(filename)

if unexpected_improvements:
print("Unexpected improvements:")
for filename in unexpected_improvements:
print(filename)
return 1


return 0






def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser()
parser.add_argument(
"--compiler-output-file-path",
type=str,
required=True,
help="Path to the file"
)
parser.add_argument(
"--warning-ignore-file-path",
type=str,
required=True,
Comment thread
nohlson marked this conversation as resolved.
Outdated
help="Path to the warning ignore file"
)


args = parser.parse_args(argv)

exit_code = 0

# Check that the compiler output file is a valid path
if not Path(args.compiler_output_file_path).is_file():
print(f"Compiler output file does not exist: {args.compiler_output_file_path}")
return 1

# Check that the warning ignore file is a valid path
if not Path(args.warning_ignore_file_path).is_file():
print(f"Warning ignore file does not exist: {args.warning_ignore_file_path}")
return 1

with Path(args.compiler_output_file_path).open(encoding="UTF-8") as f:
compiler_output_file_contents = f.read()

with Path(args.warning_ignore_file_path).open(encoding="UTF-8") as clean_files:
files_with_expected_warnings = {
filename.strip()
for filename in clean_files
if filename.strip() and not filename.startswith("#")
}


if len(compiler_output_file_contents) > 0:
print("Successfully got compiler output")
else:
exit_code = 1

if len(files_with_expected_warnings) > 0:
print("we have some exceptions")


warnings = extract_warnings_from_compiler_output(compiler_output_file_contents)

exit_code = get_unexpected_warnings(warnings, files_with_expected_warnings)

exit_code = get_unexpected_improvements(warnings, files_with_expected_warnings)




return exit_code








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