1
0
mirror of https://pagure.io/fedora-qa/os-autoinst-distri-fedora.git synced 2025-09-11 17:05:48 +00:00
os-autoinst-distri-fedora/perllint.py
Adam Williamson 0d0c79eecc Add an indent checker, fix some lines that break it
This is pretty dumb and breaks on valid code, but it's okay
enough for our purposes I think. If I made it any more complex
I'd want to start looking for a third party parser.

Signed-off-by: Adam Williamson <awilliam@redhat.com>
2022-07-28 12:45:52 -07:00

150 lines
5.1 KiB
Python
Executable File

#!/usr/bin/python3
# Copyright Red Hat
#
# This file is part of os-autoinst-distri-fedora.
#
# os-autoinst-distri-fedora is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation, either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Author: Adam Williamson <awilliam@redhat.com>
"""This is a simple linter for perl files in the repository. It fails
if any line contains a tab, ends with whitespace characters (which
includes lines containing *only* whitespace characters), or starts
with a number of spaces that is not divisible by four. If run with
--write, it will strip trailing whitespace (including turning lines
that contain only whitespace into blank lines) and correct indentation
(including removing tabs in indentation). It does not do anything
with tabs found outside of leading indentation.
"""
import glob
import os
import re
import sys
HEREDOCRE = re.compile(r"<<['\"]?(\w*)['\"]?;\s*$")
def run(write):
"""
Main run function.
"""
exitcode = 0
scriptloc = os.path.dirname(os.path.realpath(__file__))
filenames = glob.glob(f"{scriptloc}/**/*.pm", recursive=True)
for filename in filenames:
if check_file(filename, write):
exitcode = 1
if exitcode == 0:
print("No errors found!")
sys.exit(exitcode)
def check_file(filename, write):
"""
Do the checks. Returns false if there is no failure, true if there
is a failure.
"""
failed = False
with open(filename, "r", encoding="UTF-8") as readfh:
lines = readfh.readlines()
newlines = []
indent = 0
# indicator whether we're in a heredoc block
heredoc = None
for (num, line) in enumerate(lines, 1):
# if we're in a heredoc, skip all checks, and see if we
# ended it
if heredoc:
if line.strip(" \t").rstrip(" \t\n") == heredoc:
heredoc = None
# write the line back to newlines
if write:
newlines.append(line)
continue
# trailing whitespace check and replace
newline = line.rstrip("\n").rstrip(" \t") + "\n"
if newline != line:
print(f"Line {num} of file {filename} ends with a space or tab!")
failed = True
if write:
# if we're writing changes, feed the *changed* line
# to the next checks
line = newline
# correct number of starting spaces check
# skip non-indented comment lines
if line.startswith("# "):
# write the line back to newlines
if write:
newlines.append(line)
continue
# first update indent if line closes a block
if line.strip(" \t").startswith("}") or line.strip(" \t").startswith(")"):
indent -= 4
spaces = 0
for char in line:
if char != " ":
break
spaces += 1
if spaces != indent and line != "\n":
print(
f"Line {num} of file {filename} starts with an invalid number of spaces! Expected {indent} got {spaces}"
)
failed = True
if write:
line = line.lstrip()
if line.startswith("\t"):
print(f"Line {num} of file {filename} has a tab in leading whitespace!")
line = line.strip(" \t")
line = " " * indent + line
# now update indent if line opens a block (and isn't a comment)
if not line.strip(" \t").startswith("#"):
if line.rstrip(" \t\n").endswith("{") or line.rstrip(" \t\n").endswith("("):
indent += 4
# tab check
if "\t" in line:
print(f"Line {num} of file {filename} contains a tab!")
failed = True
# did the line start a heredoc?
herematch = HEREDOCRE.search(line)
if herematch:
heredoc = herematch.group(1)
# write the line back to newlines
if write:
newlines.append(line)
if write and newlines != lines:
with open(filename, "w", encoding="UTF-8") as writefh:
writefh.writelines(newlines)
return failed
# Parse args and call run().
if len(sys.argv) > 2:
sys.exit("Too many arguments!")
if len(sys.argv) > 1:
if sys.argv[1] == "--write":
run(write=True)
else:
sys.exit("Invalid argument! Only valid argument is --write")
# no args
run(write=False)