[clang-tools-extra] [run-clang-tidy.py] Refactor, add progress indicator, add type hints (PR #89490)
Julian Schmidt via cfe-commits
cfe-commits at lists.llvm.org
Sat Jun 15 07:52:32 PDT 2024
================
@@ -501,70 +506,72 @@ def main():
# Build up a big regexy filter from all command line arguments.
file_name_re = re.compile("|".join(args.files))
+ files = {f for f in files if file_name_re.search(f)}
- return_code = 0
+ returncode = 0
try:
- # Spin up a bunch of tidy-launching threads.
- task_queue = queue.Queue(max_task)
- # List of files with a non-zero return code.
- failed_files = []
- lock = threading.Lock()
- for _ in range(max_task):
- t = threading.Thread(
- target=run_tidy,
- args=(
- args,
- clang_tidy_binary,
- export_fixes_dir,
- build_path,
- task_queue,
- lock,
- failed_files,
- ),
+ semaphore = asyncio.Semaphore(max_task)
+ tasks = [
+ run_with_semaphore(
+ semaphore,
+ run_tidy,
+ args,
+ f,
+ clang_tidy_binary,
+ export_fixes_dir,
+ build_path,
)
- t.daemon = True
- t.start()
-
- # Fill the queue with files.
- for name in files:
- if file_name_re.search(name):
- task_queue.put(name)
-
- # Wait for all threads to be done.
- task_queue.join()
- if len(failed_files):
- return_code = 1
-
+ for f in files
+ ]
+
+ for i, coro in enumerate(asyncio.as_completed(tasks)):
+ name, process_returncode, stdout, stderr = await coro
+ if process_returncode != 0:
+ returncode = 1
+ if process_returncode < 0:
+ stderr += f"{name}: terminated by signal {-process_returncode}\n"
+ print(f"[{i + 1}/{len(files)}] {name}")
+ if stdout:
+ print(stdout)
+ if stderr:
+ print(stderr, file=sys.stderr)
except KeyboardInterrupt:
# This is a sad hack. Unfortunately subprocess goes
# bonkers with ctrl-c and we start forking merrily.
print("\nCtrl-C detected, goodbye.")
if delete_fixes_dir:
+ assert export_fixes_dir
shutil.rmtree(export_fixes_dir)
os.kill(0, 9)
if combine_fixes:
- print("Writing fixes to " + args.export_fixes + " ...")
+ print(f"Writing fixes to {args.export_fixes} ...")
try:
+ assert export_fixes_dir
merge_replacement_files(export_fixes_dir, args.export_fixes)
except:
print("Error exporting fixes.\n", file=sys.stderr)
traceback.print_exc()
- return_code = 1
+ returncode = 1
if args.fix:
print("Applying fixes ...")
try:
+ assert export_fixes_dir
apply_fixes(args, clang_apply_replacements_binary, export_fixes_dir)
except:
print("Error applying fixes.\n", file=sys.stderr)
traceback.print_exc()
- return_code = 1
+ returncode = 1
if delete_fixes_dir:
+ assert export_fixes_dir
shutil.rmtree(export_fixes_dir)
- sys.exit(return_code)
+ sys.exit(returncode)
if __name__ == "__main__":
- main()
+ # FIXME Python 3.7: This can be simplified by asyncio.run(main()).
+ loop = asyncio.new_event_loop()
+ loop.run_until_complete(main())
+ loop.close()
----------------
5chmidti wrote:
Sure, but why does `main` need to be `async` at all?
I.e.
```python
async def main():
pass
if __name__ == "__main__":
# FIXME Python 3.7: This can be simplified by asyncio.run(main()).
loop = asyncio.new_event_loop()
loop.run_until_complete(main())
loop.close()
```
vs.
```python
def main():
pass
if __name__ == "__main__":
main()
```
https://github.com/llvm/llvm-project/pull/89490
More information about the cfe-commits
mailing list