Могу ли я получить ошибку lint при неявном соединении строк в python?

Есть ли способ получить ошибку lint при пропущенных запятых в литеральном списке строк?

Пример:

exceptions = ["banana", "pineapple", "apple"
              "pen"]

Вы можете подумать, что этот список содержит 4 предмета, но нужно сказать правду! "яблоко" и "перо" объединены в "аппендикс".

Я боюсь этих пропущенных запятых. Есть ли какой-нибудь инструмент для линта, который поможет мне найти их?

Пример 2:

exceptions = ["Carmichael",
              "Vanessa"      # <--- Spot the missing comma
              "Ford"]

Ответ 1

Я не уверен, какой инструмент анализа исходного кода вы используете, поэтому я могу предложить только предложение. Тем не менее, это слишком долго для комментария, поэтому я написал доказательство концепции script.

Идея состоит в том, чтобы посмотреть исходный код с модулем Python tokenize, который генерирует токены из выражений Python. Если хорошо сформированный код Python содержит неявно продолжающиеся строковые литералы, он будет отображаться как токен STRING, за которым следует NL.

Например, позвольте использовать в качестве тестового примера следующий исходный файл source.py.

x = ("a"
        "b"  # some trailing spaces
# Coment line
"c"
""
     # The following is an explicit continuation
  "d" \
     "e")

Запуск команды python check.py < source.py в файле генерирует:

1:8: implicit continuation: 
x = ("a"

     ~~~^
2:35: implicit continuation: 
        "b"  # some trailing spaces

                                ~~~^
4:3: implicit continuation: 
"c"

~~~^
5:2: implicit continuation: 
""

  ^

Программа check.py является просто доказательством концепции и не проверяет синтаксические ошибки или другие случаи:

import sys
import tokenize


LOOKNEXT = False
tok_gen = tokenize.generate_tokens(sys.stdin.readline)
for tok, tok_str, start, end, line_text in tok_gen:
    if tok == tokenize.STRING:
        LOOKNEXT = True
        continue
    if LOOKNEXT and (tok == tokenize.NL):
            warn_header = "%d:%d: implicit continuation: " % start
            print >> sys.stderr, warn_header
            print >> sys.stderr, line_text
            indents = start[1] - 3
            if indents >= 0:
                print >> sys.stderr, "%s~~~^" % (" " * indents)
            else:
                print >> sys.stderr, "%s^" % (" " * start[1])
    LOOKNEXT = False

Надеюсь, эта идея поможет вам расширить свой инструмент для линта или IDE для вашей цели.

Ответ 2

SublimeText3 с плагином flake8, который является оберткой других плагинов python, может исправить его.

В противном случае вы можете сделать script, который подсчитывает ((число ")/2) -1 и запятые в строке, и если результат не совпадает, добавьте кому.

ИЗМЕНИТЬ:

Объяснение того, что я говорю:

    def countQuotes(string):
        return string.count('"')
    def countCommas(string):
        return string.count(',')
    files = os.listdir('your/directory')
    for filename in files:
    if filename.endswith(".py"):
        with fileinput.FileInput("your/directory"+"/"+filename, inplace=True, backup='.bak') as fileContent:
        for line in fileContent:
            if '"' in line:
                numQuotes = countQuotes(line)
                numCommas = countCommas(line)
                if(numQuotes == 2 and ']' in line):
                    if(numCommas != 0):
                        #error, must delete a comma in right place and print line
                    else:
                        print(line)
                if(numQuotes == 2 and ']' not in line):
                    if(numCommas != 1):
                        #error, must add a comma in right place and print line
                    else:
                        print(line)
                if(numQuotes > 2):
                    if(numCommas > (numQuotes//2)-1)
                        #error, must delete a comma in right place and print line
                    elif(numCommas < (numQuotes//2)-1)
                        #error, must add a comma in right place and print line
                    else:
                        print(line)
           else:
                print(line)

Этот метод должен работать, просто подумайте, где вы должны вставить или удалить запятую, чтобы, наконец, получить желаемый формат.