Première version de la moulinette : que des tests sur des lignes
This commit is contained in:
commit
0d3fc15df6
154
moulinette.py
Executable file
154
moulinette.py
Executable file
@ -0,0 +1,154 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
import signal
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
def onSignal(signal, frame):
|
||||||
|
print("Bye!")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, onSignal)
|
||||||
|
|
||||||
|
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage:\t{0} FILE...".format(sys.argv[0]))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def printError(file, type, line = -1):
|
||||||
|
if line >= 0:
|
||||||
|
print("{0} in {1}:{2}".format(type, file, line))
|
||||||
|
else:
|
||||||
|
print("{0} for {1}".format(type, file))
|
||||||
|
|
||||||
|
def checkFile(path):
|
||||||
|
if os.path.isdir(path):
|
||||||
|
checkDir(path)
|
||||||
|
else:
|
||||||
|
baseName = os.path.basename(path)
|
||||||
|
if baseName.upper == "AUTHORS":
|
||||||
|
if baseName != "AUTHORS":
|
||||||
|
printError(path, "Bad filename")
|
||||||
|
checkAuthors(path)
|
||||||
|
|
||||||
|
if baseName[len(baseName)-1] == '~' or baseName[len(baseName)-1] == '#'\
|
||||||
|
or baseName[0] == '#':
|
||||||
|
printError(path, "This is a temporary file")
|
||||||
|
|
||||||
|
iExt = baseName.rfind('.')
|
||||||
|
if iExt > 0:
|
||||||
|
ext = baseName[iExt:]
|
||||||
|
|
||||||
|
if ext == ".c":
|
||||||
|
checkCFile(path)
|
||||||
|
elif ext == ".h":
|
||||||
|
checkHFile(path)
|
||||||
|
else:
|
||||||
|
checkOtherFile(path)
|
||||||
|
|
||||||
|
def checkDir(path):
|
||||||
|
dirList = os.listdir(path)
|
||||||
|
filesList = []
|
||||||
|
for f in dirList:
|
||||||
|
basename = os.path.basename(f)
|
||||||
|
if os.path.isdir(f):
|
||||||
|
if basename == ".git" or basename == ".hg":
|
||||||
|
printError(path, "There is a {0} repository".format(basename))
|
||||||
|
else:
|
||||||
|
if basename[0] == '.':
|
||||||
|
printError(path + '/' + basename, "Hidden directory")
|
||||||
|
checkDir(path + '/' + f)
|
||||||
|
else:
|
||||||
|
if basename[0] == '.':
|
||||||
|
printError(path + '/' + basename, "Hidden file")
|
||||||
|
checkFile(path + '/' + f)
|
||||||
|
|
||||||
|
def check80cols(path, line, num):
|
||||||
|
if len(line) > 80:
|
||||||
|
printError(path, "80 columns exceeded", num)
|
||||||
|
|
||||||
|
def checkTrailingWhitespace(path, line, num):
|
||||||
|
if len(line) > 1 and line[len(line)-1] == ' ':
|
||||||
|
printError(path, "Trailing whitespace", num)
|
||||||
|
|
||||||
|
def checkCLang(path, line, num):
|
||||||
|
txt = line.strip()
|
||||||
|
if re.match("^#define", txt) is not None and \
|
||||||
|
re.match("^#define +[A-Z0-9_]+[ \(]", txt) is None:
|
||||||
|
printError(path, "Constant or macro without full uppercase", num)
|
||||||
|
elif re.match("^struct", txt) is not None and \
|
||||||
|
re.match("^(typedef +)?struct +s_", txt) is None:
|
||||||
|
printError(path, "New struct without s_ name", num)
|
||||||
|
elif re.match("^typedef", txt) is not None and \
|
||||||
|
re.match("^typedef +(unsigned )?[a-z_\*] +t_", txt) is None:
|
||||||
|
printError(path, "New type without t_ name", num)
|
||||||
|
elif re.match("^(if|else|elseif|for|while|do|typedef|struct|return|sizeof)", txt) is not None and \
|
||||||
|
re.match("^(if|else|elseif|for|while|do|typedef|struct|return|sizeof) ", txt) is None:
|
||||||
|
printError(path, "Forgotten space after keyword", num)
|
||||||
|
elif re.match("^(if|else|elseif|for|while|do|typedef|struct)", txt) is not None and \
|
||||||
|
re.match("^(if|else|elseif|for|while|do|typedef|struct).*{", txt) is None:
|
||||||
|
printError(path, "{ on the same lime of instruction", num)
|
||||||
|
elif re.match("(^/\*|\*/$)", txt) is not None and \
|
||||||
|
re.match("^(/\*|\*/)$", txt) is None:
|
||||||
|
printError(path, "First and last big comment lines aren't empty", num)
|
||||||
|
elif re.match("^for", txt) is not None and \
|
||||||
|
re.match("^for \(.*; .*; .*\)", txt) is None:
|
||||||
|
printError(path, "Bad syntax for a for", num)
|
||||||
|
elif re.match("^return", txt) is not None and \
|
||||||
|
re.match("^return \(.*\)", txt) is None:
|
||||||
|
printError(path, "Bad syntax for return", num)
|
||||||
|
elif re.match(".*=.*;", txt) is not None and \
|
||||||
|
re.match(".* [&%\+\*/-]= .*", txt) is None:
|
||||||
|
printError(path, "Bad syntax for an affectation", num)
|
||||||
|
|
||||||
|
def checkHFile(path):
|
||||||
|
checkCFile(path)
|
||||||
|
|
||||||
|
def checkCFile(path):
|
||||||
|
num = 0
|
||||||
|
with open(path, "r") as fp:
|
||||||
|
lines = fp.read().split('\n')
|
||||||
|
for line in lines:
|
||||||
|
num += 1
|
||||||
|
line = line.replace(" ", " ")
|
||||||
|
|
||||||
|
check80cols(path, line, num)
|
||||||
|
checkTrailingWhitespace(path, line, num)
|
||||||
|
checkCLang(path, line, num)
|
||||||
|
|
||||||
|
def checkOtherFile(path):
|
||||||
|
num = 0
|
||||||
|
with open(path, "r") as fp:
|
||||||
|
lines = fp.read().split('\n')
|
||||||
|
for line in lines:
|
||||||
|
num += 1
|
||||||
|
line = line.replace(" ", " ")
|
||||||
|
|
||||||
|
checkTrailingWhitespace(path, line, num)
|
||||||
|
|
||||||
|
def checkAuthors(path):
|
||||||
|
num = 0
|
||||||
|
with open(path, "r") as fp:
|
||||||
|
fullContent = fp.read()
|
||||||
|
|
||||||
|
if fullContent < 1 or fullContent[len(fullContent)-1] != '\n':
|
||||||
|
printError(path, "No empty line at the end of file")
|
||||||
|
|
||||||
|
lines = fullContent.split('\n')
|
||||||
|
for line in lines:
|
||||||
|
num += 1
|
||||||
|
checkTrailingWhitespace(path, line, num)
|
||||||
|
if re.match("^\* [a-z0-9-]{1,6}_[a-z0-9-]$", line) is None:
|
||||||
|
printError(path, "Bad author format", num)
|
||||||
|
|
||||||
|
|
||||||
|
#Define some constants
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
i = 1
|
||||||
|
while i < len(sys.argv):
|
||||||
|
checkFile(sys.argv[i])
|
||||||
|
i += 1
|
||||||
|
|
Reference in New Issue
Block a user