Чтобы создать более чистый код (и в сочетании с проверками PEP 8), я создал скрипт python, который проверяет любой файл на предмет дублирования в строках кода. Вы можете установить минимальное количество последовательных строк, необходимое для того, чтобы он был помечен как дубликат (чтобы избежать чрезмерных предупреждений о операторах возврата или других таких распространенных однострочных). Он может захватывать целые блоки дублирования, отображать количество повторений и номера строк.
Хотя код выполняет свою работу, он довольно сложный, и я боюсь, что большие файлы будут сканироваться очень медленно из-за использования счетчика. Есть ли лучший (более простой и особенно эффективный) способ выполнения sh этого?
Мой код:
import sys
from collections import Counter
from os.path import isfile
def checkForDuplicates(minConsecutiveLines, fileName):
rawLines = open(fileName).readlines()
checkLines = list(rawLines)
duplicateLines = []
skipLines = ['', '"""']
skipIfBeginsWith = ['import', 'from', '#']
for line in rawLines:
if line.strip() in skipLines or line.split(' ')[0] in skipIfBeginsWith:
checkLines.pop(checkLines.index(line))
lineCounts = list(Counter(checkLines).items())
lineNumber = 0
while lineNumber < len(lineCounts):
lines = [lineCounts[lineNumber]]
count = lines[0][1]
duplicate = True if count > 1 else False
while count > 1:
lineNumber += 1
if lineNumber == len(lineCounts):
break
content, count = lineCounts[lineNumber]
if count > 1:
lines.append([content, count])
if len(lines) < minConsecutiveLines:
duplicate = False
if duplicate:
lineInd = rawLines.index(lines[0][0]) + 1
lastLineInd = rawLines.index(lines[-1][0]) + 1
duplicateLines.append([lineInd, lastLineInd, lines[0][1]])
content = lines[0][0].strip()
for line in lines[1:]:
content += '\n\t\t' + line[0].strip()
duplicateLines[-1].append(content)
lineNumber += 1
if len(duplicateLines) == 0:
print('No duplication found.')
return 0
print('Duplication found in {0}:'.format(fileName))
for duplicateSet in duplicateLines:
print('\tLines {0} - {1} (Count = {2}):\n\t\t{3}'.format(
*duplicateSet))
return 1
if __name__ == '__main__':
if len(sys.argv) < 3:
print('Need number of minimum consecutive lines and '
'at least one file name.')
sys.exit(1)
results = []
minConsecutiveLines = sys.argv[1]
try:
minConsecutiveLines = int(minConsecutiveLines)
except ValueError:
print('First arguemnt must be '
'the number of minimum consecutive lines.')
sys.exit(1)
for fileName in sys.argv[2:]:
if not isfile(fileName):
print('{0} cannot be located.'.format(fileName))
sys.exit(1)
for fileName in sys.argv[2:]:
results.append(checkForDuplicates(minConsecutiveLines, fileName))
if 1 in results:
sys.exit(1)
else:
sys.exit(0)
Пример вывода:
> python CheckDuplication.py 2 Working\UserProfile.py
Duplication found in Working\UserProfile.py:
Lines 107 - 113 (Count = 2):
Examples:
hoursName = 'credit hours'
hoursVar = 'creditHours'
hoursToAdd = self.checkNumeric(hoursToAdd)
if hoursToAdd is None:
return hoursName.capitalize() + ' to earn or use must be a number.'
Lines 118 - 119 (Count = 2):
if limitFailure is not None:
return hoursName.capitalize() + ' ' + limitFailure