Найти дубликаты строк в Python файле для рефакторинга - PullRequest
0 голосов
/ 22 апреля 2020

Чтобы создать более чистый код (и в сочетании с проверками 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
...