1
0
mirror of https://github.com/esphome/esphome.git synced 2025-02-25 14:28:14 +00:00
esphome/script/lint-python
2025-02-21 13:02:55 -06:00

158 lines
4.1 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import os
import re
import sys
import colorama
from helpers import (
filter_changed,
get_err,
get_output,
git_ls_files,
print_error_for_file,
styled,
)
curfile = None
def print_error(file, lineno, msg):
global curfile # noqa: PLW0603
if curfile != file:
print_error_for_file(file, None)
curfile = file
if lineno is not None:
print(f"{styled(colorama.Style.BRIGHT, f'{file}:{lineno}:')} {msg}")
else:
print(f"{styled(colorama.Style.BRIGHT, f'{file}:')} {msg}")
def split_args_platform_compatible(args):
if os.name == "posix":
return [args]
char_length = 0
argsets = []
for index, arg in enumerate(args):
# Windows is techincally 8191, but we need to leave some room for the command itself
if char_length + len(arg) > 8000:
argsets.append(args[:index])
args = args[index:]
char_length = 0
char_length += len(arg)
return argsets
def main():
colorama.init()
parser = argparse.ArgumentParser()
parser.add_argument(
"files", nargs="*", default=[], help="files to be processed (regex on path)"
)
parser.add_argument(
"-c", "--changed", action="store_true", help="Only run on changed files"
)
parser.add_argument(
"-a",
"--apply",
action="store_true",
help="Apply changes to files where possible",
)
args = parser.parse_args()
files = []
for path in git_ls_files():
filetypes = (".py",)
ext = os.path.splitext(path)[1]
if ext in filetypes and path.startswith("esphome"):
path = os.path.relpath(path, os.getcwd())
files.append(path)
# Match against re
file_name_re = re.compile("|".join(args.files))
files = [p for p in files if file_name_re.search(p)]
if args.changed:
files = filter_changed(files)
files.sort()
if not files:
sys.exit(0)
errors = 0
# Needed to get around command-line string limits in Windows.
filesets = split_args_platform_compatible(files)
print("Running ruff...")
print()
for fileset in filesets:
cmd = ["ruff", "format"] + ([] if args.apply else ["--check"]) + fileset
log = get_err(*cmd)
for line in log.splitlines():
WOULD_REFORMAT = "would reformat"
if line.startswith(WOULD_REFORMAT):
file_ = line[len(WOULD_REFORMAT) + 1 :]
print_error(
file_, None, "Please format this file with the ruff formatter"
)
errors += 1
print()
print("Running flake8...")
print()
for files in filesets:
cmd = ["flake8"] + files
log = get_output(*cmd)
for line in log.splitlines():
line = line.split(":", 4)
if len(line) < 4:
continue
file_ = line[0]
linno = line[1]
msg = (":".join(line[3:])).strip()
print_error(file_, linno, msg)
errors += 1
print()
print("Running pylint...")
print()
for files in filesets:
cmd = ["pylint", "-f", "parseable", "--persistent=n"] + files
log = get_output(*cmd)
for line in log.splitlines():
line = line.split(":", 3)
if len(line) < 3:
continue
file_ = line[0]
linno = line[1]
msg = (":".join(line[2:])).strip()
print_error(file_, linno, msg)
errors += 1
print()
print("Running pyupgrade...")
print()
PYUPGRADE_TARGET = "--py39-plus"
for files in filesets:
cmd = ["pyupgrade", PYUPGRADE_TARGET] + files
log = get_err(*cmd)
for line in log.splitlines():
REWRITING = "Rewriting"
if line.startswith(REWRITING):
file_ = line[len(REWRITING) + 1 :]
print_error(
file_, None, f"Please run pyupgrade {PYUPGRADE_TARGET} on this file"
)
errors += 1
sys.exit(errors)
if __name__ == "__main__":
main()