Когда проект на python долгое время живет без правил по формату строк, то в один прекрасный момент оказывается, что 90% кода используют одинарные кавычки, а 10% - двойные.
Добавление flake8-quotes с соответствующими правилами перестало пускать новый код с двойными кавычками дальше пул-реквеста, но начало требовать ручной правки формата в уже существующем коде, чего хотелось бы избежать.
Первой мыслью было задействовать black, но предлагаемый им формат предполагает исключительно использование двойных кавычек. В 2018 в github black был запрос Single quotes option формата строк, обсуждение было жарким, но закончилось оно лишь введением опции --skip-string-normalization
, позволявшей не трогать формат строк в проверяемом коде.
Самым простым в данной ситуации было просто согласиться с black, но команда и бóльшая часть кода были против. Пришлось искать другое решение, которое оказалось в модификации исходного кода black.
Сразу скажу, что все правила реализовать не получилось, так как в flake8-quotes можно задать разные правила для docstring и остальных многострочных строк, а логика black их, насколько удалось разобраться, не различает.
Тем не менее, с двойными кавычками в простых строках справиться удалось,
и вот что для этого потребовалось:
-
были скачаны исходники black 22.1.0 (это первая не-бета версия black и наш CI в данный момент использует эту версию в режиме проверки кода).
-
установлены необходимые ему библиотеки
Для Python 3.8:
click 8.1.3
colorama 0.4.4
mypy-extensions 0.4.3
pathspec 0.9.0
pip 21.3.1
platformdirs 2.5.2
tomli 2.0.1
typing_extensions 4.2.0
wheel 0.37.1
-
добавлен модуль
src/black/_black_version.py
c содержимымversion = '22.1.0'
Основные правки оказались сконцентрированы в методе normalize_string_quotes
модуля src/black/stringы.py
:
Условие на входе метода
if value[:3] == '"""':
return s
elif value[:3] == "'''":
orig_quote = "'''"
new_quote = '"""'
elif value[0] == '"':
orig_quote = '"'
new_quote = "'"
else:
orig_quote = "'"
new_quote = '"'
заменил на
if value[:3] == '"""':
return s
elif value[:3] == "'''":
return s # оставляем как есть и строки с ''', и строки с """
elif value[0] == '"':
orig_quote = '"'
new_quote = "'"
else:
orig_quote = "'"
new_quote = '"'
а условие на выходе метода
if new_escape_count == orig_escape_count and orig_quote == '"':
return s # Prefer double quotes
заменил на
if new_escape_count == orig_escape_count and orig_quote == "'":
return s # Prefer single quotes
Через несколько минут работы модифицированного black проблема двойных кавычек в нашем проекте была решена (хорошо, остался еще этап ручного исправления """
в многострочных строках на '''
, но он тоже не занял много времени).
Из приятного. В коде нашлось несколько строк вида u'xa0'
- видимо скопированных из советов для python 2 - и исправилось (удалило u в начале). Также исправились сами экранированные строки """
в '"'
Из неожиданного. Строки fr'abc'
заменило на rf'abc'
. Таких правок при необходимости легко было избежав закомментировав вызов метода normalize_string_prefix.
В итоге хотелось бы сказать, что пока все это делал, почти согласился с идеологией black, хотя доводы апологетов одинарных кавычек - они не требуют нажатия Shift для ввода, сам интерпретатор Python в консоли использует именно их, код выглядит прозрачней и тем самым более pythonic - тоже заслуживают внимания.
Что же касается opensource проектов, тут, я полагаю, все уже давно решено и black с его двойными кавычками победил.
Автор:
57an