Автоматическое заполнение ревью в Ревизоре Яндекс Практикума
Консольная утилита, преобразующая архив с ДЗ в новый архив, который Ревизор готов принять и перенести из него комменты в исходные файлы.
Запуск
python autorv.py путь-к-домашке.zip
создаст (перезапишет!) файл путь-к-домашке.N-E!F+G.zip
, который можно передать Ревизору.
Вместо N
, E
, F
, G
будут подставлены числа, отражающие результат работы:
N
- число файлов, в которые попали комменты,E
- число ошибок (Надо исправить),F
- число неточностей (Можно лучше),G
- число удач (Отлично).
Пример. Фрагмент
group = models.ForeignKey(…
¬°
related_name=†!<groups¦group>!†
используется так:
- Ищется объявление поля группы.
- Учитывается, что строка может заканчиваться на дополнительные пробелы (это
…
). - Потом допускается пропуск нескольких (от 0) строк с двойным сдвигом (из-за
¬°
) до ближайшего параметраrelated_name
. - Ищется один из вариантов (это из-за
!<¦>!
) значения, заключенный в какие-то кавычки (это†
).
«шаблон»
- "регулярка" - поисковый фрагмент на языке re-выражений Питона.- "Сахар", то есть сокращения для re-выражений
(‡)
[‡]
{‡}
- "парные скобки", то есть от открывающей до ее парной закрывающей.‡
- "стяжка", то есть минимальный заполняющий текст (возможно пустой), в том числе с концами строк.‡‡
- "часть имени", то есть текст (возможно пустой) из букв/цифр/_/точки.■
- "заполнитель", то есть любой непустой текст в пределах строки.□
- "заполнитель", то есть любой текст в пределах строки.○
- "пробельные символы", то есть пробелов/табов/EOL (может быть 0).▫
- "пробелы", то есть несколько пробелов (может быть 0).▪
- "обязательные пробелы", то есть несколько пробелов/табов или\n
.†
- "кавычка", то есть либо'
, либо"
.¬°
- Фрагмент из нескольких строк (м.б. 0) с такими же сдвигами.!<так¦этак¦эдак>!
- "варианты".╠фраза╣
- "лишний текст", которого не должно быть перед следующим подходящим символом.
↓1
- Сохранение номеров строк, которые можно вставлять в комментарий. Там они будут доступны под такими же обозначениями. Но если поисковых шаблонов несколько, то еще и под уточненными именами↓1_2
(↓2
из второго шаблона).
Применяются такие регулярные выражения
Символ | Его выражение/замена | Комментарий |
---|---|---|
† |
[\'\"] |
|
□ |
.* |
Мнемоника: пустой символ = "от 0" |
▬ ■ |
.+ |
Мнемоника: непустой символ = "от 1" |
○ |
\s* |
Мнемоника: пустой символ = "от 0" |
¶± ▪ |
\s+ |
Мнемоника: непустой символ = "от 1" |
… ▫ |
* |
Мнемоника: пустой символ = "от 0" |
‡‡ |
[\w\.]* |
Может быть другой знак |
‡ |
(?s:.*?) |
Общий знак ‡ тут и ниже |
(‡) |
\([^\(\)]*?(?:\([^\(\)]*?(?:\([^\(\)]*?\)[^\(\)]*?)*?\)[^\(\)]*?)*?\) |
Глубина вложенности <3 |
[‡] |
\[[^\[\]]*?(?:\[[^\[\]]*?(?:\[[^\[\]]*?\][^\[\]]*?)*?\][^\[\]]*?)*?\] |
Глубина вложенности <3 |
{‡} |
\{[^\{\}]*?(?:\{[^\{\}]*?(?:\{[^\{\}]*?\}[^\{\}]*?)*?\}[^\{\}]*?)*?\} |
Глубина вложенности <3 |
¬° |
\n( *)¬° заменяется на (\n\\1.*)* |
|
!< ¦ >! |
!<([^¦]+)¦([^>!]+)>! заменяется на ((\\1)|(\\2)) (остальные аналогично) |
Ожидаются <10 вариантов |
╠ ╣ |
╠ заменяется на (?<! , ╣ заменяется на ) |
|
↓0 ↓1 ... |
↓(\d+) заменяется на (?P<p\1>(?<!↓)) |
Не будет найденных символов |
levl
со значениями'G'
Good, "Отлично",'F'
False, "Можно лучше",'E'
Error, "Надо исправить".
pttn
с одним или несколькими искомыми фрагментами.note
с текстом коммента.
Пример. Словарь
dict(levl='F',
pttn='''
group = models.ForeignKey(…
¬°
related_name=†!<groups¦group>!†
'''
note='Неудачное имя для поля связи.',
)
{
'hw02_community-master/yatube/posts/admin.py':[...],
'hw02_community-master/yatube/posts/models.py':[...],
...
}
Этот набор (фактически словарь) хранится в файле, который в настройках привязывается к архиву, например, этот к такому
kvichans__hw02_community_1639562917.zip
- Код имеет умолчательные настройки, которые могут быть изменены в любой части через внешний json.
- Каждый из символов в спец.разметке может быть заменен на любую строку (но не всякая строках, конечно, уместна, так как поиски будут вестись через регулярки).
- С каждым из файлов в архиве может быть связан произвольный файл (или несколько) с наборами рв-словарей.
- Файлы с наборами рв-словарей могут быть
- в виде питон-кода
{'hw02_community-master/yatube/posts/models.py':[dict(...), dict(...),]}
- в виде yaml
- в виде питон-кода
"hw02_community-master/yatube/posts/models.py":
- levl: F
pttn: |2-
group = models.ForeignKey(…
¬°
related_name=†!<groups¦group>!†
note: "Неудачное имя для поля связи."
- в виде json (м.б. кому-то это окажется полезно)
- Можно разместить общие рв-словари для нескольких файлов в по укороченному пути.
Например, для
index.html
получиться два рв-словаря при такой настройке
{
'hw02_community-master/yatube/templates/posts/':[
dict(levl='E', pttn='{{title}}', note='Лишняя контекстная переменная.',)
]
'hw02_community-master/yatube/templates/posts/index.html':[
dict(levl='F', pttn='{% if post.group.slug %}', note='Лучше писать `{% if post.group %}`.',)
]
}
- Если указан не один фрамент, а несколько в виде
pttn=['...','...']
, то полезны дополнительные ключи:'frml'
, например,frml='m_0 and m_1'
- логическая формула из результатов поисков каждого из фрагментов. Умолчание: один из поисков успешен.'posi'
, например,posi='max(p_0, p_1)'
- выражение из строк найденных фрагментов. Задает строку для размещения коммента. Умолчание: максимальная из строк во всех поисках.- Весь поиск будет успешным, если
eval(frml)
будет истинным. - Их применение свободное. Например, можно выяснить, что первый фрагмент не найден, поставить комментарий у второго найденного фрагмента.
- Ключ
rpts
- настройка повторений при вставке коммента. Ожидаются значения:'one'
- создавать один коммент на файл у первого найденного случая.'all'
- создавать комменты у каждого найденного случая.- если не задан - применять
'one'
для всех кроме поиска с перечислением вариантов (!<раз¦два>!
), для которого'all'
.
При запуске
autorv -m папка-с-именами-студентов
происходит зацикливание, при котором АР наблюдает за указанной папкой и папками вхоженными в нее.
Отслеживаются:
- Создание новой подпапки (добавился студент).
- Появление в подпапке нового zip (скачана новая домашка).
Действия при появлении нового zip регулируюсят через настройку opts.monitor
.
Умолчательный набор действий зашит в код АР. Он включает
- Распаковку zip-а.
- Запуск АР для создания нового zip-а.
- Запуск сравнивающей две папки утилиты (типа WinMerge), если есть папка с предыдущей итерацией (в том числе из предыдущего ДЗ).
При запуске
python autorv.py -ds путь-файла-знаний::путь-по-знаниям
из json-данных в указанном файле будет извлечено значение и после замены сахара на регулярки выдано в соседний файл
путь-файла-знаний.desugar_ГГ-ММ-ДД_ЧЧ-ММ-СС.py
Путь внутри json записывается с разделителем |
.
- Спуск в словаре выглядит так
-
путь-до-словаря|ключ
-
- Спуск в списке выглядит так
-
путь-до-словаря|номер-позиции
-
Пример. В знаниях к ДЗ-2 hw02_skills.py
есть
'posts/models.py':[
dict(levl='G',
frml='ITER < 2 and m_0',
pttn='''
group = models.ForeignKey(‡
on_delete=models.SET_NULL''',
note='''Удачно.''',
),
dict(levl='G',
pttn='''
group = models.ForeignKey(‡
related_name=†posts†''',
note='''Правильно!''',
),
После запуска
python autorv.py -ds path/hw02_skills.py::posts/models.py|1|ptth
появится файл
path/hw02_skills.py.desugar_23-01-14_01-27-07.py
с готовой для тестирования регуляркой. Содержимое файла
import re
# Регулярка c сахаром
pttn = r"""{pttn}"""
# Регулярка без сахара
pttn = r"""{dspttn}"""
# Задайте тестируемый текст из ДЗ
src = """ """
#src = open(r'путь к исходнику в ДЗ', encoding='utf8').read()
# Запуск теста
mt = re.search(pttn, src)
if not mt:return print('fail')
print(mt.groupdict())
-
Ревизор глотает начальные пробелы в комментах. Поэтому autorv меняет левый пробел на символ
·
. В результате примеры кодов/разметки в комментах оказываются некорректными. Ждем исправления Ревизора. -
Взаимодействие настроек
rpts='all'
(=комментировать все найденные в файле фрагменты),note=['...', '...']
(=искать разные фрагменты),note='...!<...¦...>!...'
(=искать варианты)
сейчас запутанное и иногда нелогичное. Будет переделка.
- Обмен вычисленными значениями между найденными случаями.
- Добавить в формулу для позиции
posi
найденные↓
.
- [+] Добавлен ключ
pttn_wo_strip
, чтобы исключить умолчательные удаления пробельных символов из значения(ий)pttn
. - [+] Добавлена возможность задавать список для
note
. Из него будут извлекаться последовательные значения для найденных случаев. А последнее значение будет использоваться для всех остальных случаев. - [+] Добавлены новые "сахарные" знаки:
‡‡
– для заполнителя из букв/цифр/_/точки (м.б. пустого).(‡)
,[‡]
,{‡}
– для заполнителя до парной скобки.▬
– для заполнителя "в пределах строки" (непустого).
- [*] Добавлена возможность ставить пробелы вокрут
>
и?
при объединении "знаний". - [+] В формулах
frml
добавлены "внешние" значенияSRC_PATH
- полный путь к комментируемому файлу в zip.SRC_FN
- имя комментируемого файла в zip.
- [+] В рв-словаре ожидается ключ
LOG=1
, который запускает логгирование работы с этим словарем при каждом его применении. - [+] Добавлены новые "сахарные" знаки:
□
– для заполнителя "в пределах строки" (м.б. пустого).■
– для заполнителя "в пределах строки" (непустого). Синоним к▬
.▫
– для пробелов (м.б. пустого набора). Синоним к…
.▪
– для пробельных символов (непустого набора). Синоним 궱
.
- [+] В формулах
frml
добавлены "внешние" значения, которые расчитываются от имени zip-файла. Это дает возможность делать разные комменты для разных итераций ревью. Эти значения задаются в настройках. По умолчанию задаютсяITER
, которые извлекаются из конца имени:name-7.zip
даетITER
со значением 7. - [+] Добавлено ожидание в рв-словаре ключа
brief
для формирования общего коммента. Составленный общий коммент попадает (пока) в лог. - [*] Исправлено формирование архива для Ревизора
- К имени (до расширения) дописывается статистика:
name.5-4!3+2.zip
- комменты в 5 файлах, 4/3/2 на уровне ошибка/неточность/удача. - Включено сжатие.
- Включено сохранение дат файлов.
- К имени (до расширения) дописывается статистика:
- [+] Добавлены новые "сахарные" знаки:
○
– для заполнителя из пробельных символов (м.б. пустого).
- [*] Исправлено применение espanso. Теперь нет ожидания, что ключ будет завершаться пробелом.
- [*] Исправлена работа с путями к zip, содержащими пробелы.
- [+] Добавлена возможность указывать сразу несколько файлов/папок для списка рв-словарей:
{(файл_1, файл_2):[dict(...), dict(...)]}
. Это предоставляет способ для синхронного комментирования в разных папках, а также для избирательного комментирования в нужных файлах. - [+] Появились параметры для запуска в консоли. См параметр
-h
. - [+] Монитор объединен с АвтоРевьювером. Запуск
autorv -m папка
. - [+] Добавлен третий слой для настройки. При запуске
autorv -g файл.json ...
умолчательные настройки будут перекрыты сначала изautorv.py.json
, потом из указанногофайл.json
. - [*] АвтоРевьювер теперь выводит лог и в поток печати, и в файл
autorv.py.log
. Монитор выводит лог только в поток печати.
- [+] Добавлено заглядывание в zip для выяснения "какая это домашка": словарь
opts.re4hwdir_to_skill_key
. Cловарьopts.re4zipname_to_skill_key
для анализ имени zip-файла теперь не обязателен. - [+] Добавлена реакция на пустой непоследний коммент в списке
note
из рв-словаря. Коммент пропускается. - [+] Добавлена реакция на пустой последний коммент в списке
note
из рв-словаря. Этот и случай ниже (в этом же файле) не комментируются. Это позволяет сделать гибче и разнообразнее комменты к одинаковым случаям.
- [+] Добавлены заготовки для работы с ДЗ-16/17/18/19/20.
- [+] Добавлен отдельный "сахарный" знак (умолчание
‡‡
) для "Имя с точками". До этого использовалось удвоение знака "Стяжка" (умолчание‡
). - [*] Исправлена работа шаблонами вида
'p!<p1¦p2>! m !<a1¦a2>!.a'
(спасибо @EugeneSal). - [*] Исправлен костыль для сохранения начальных пробелов. Теперь в комменте всегда первый пробел заменяется на
·
(ранее искались только наборы из четырех пробелов).
- [+] Добавлена возможность указывать "подпись" АР для всех комментариев.
- Внутри любого "знания" теперь ожидается ключ
end_sign
. - Его значение будут добавлено в конец к содержимому от ключа
note
. - Можно задать
end_sign
один раз на весь модуль - в корневом словаре через'end_sign':'???'
. - Заданное в корне значение будет использовано во всех "знаниях", кроме тех, где новый ключ задан явно.
- Пример
hw02_skills.py
уже содержит применение нового ключа.
- Внутри любого "знания" теперь ожидается ключ
- [*] Исправлена ошибка, из-за которой был пустой набор комментов при похожих именах ожидаемых главных папок в zip-ах.
- [+] Добавлена возможность получать все замены espanso через cli-запрос (спасибо @theoden-dd):
- вместо
"espanso:": "path/default.yml",
(файла с заменами) - указать
"espanso:": "[path/]espanso.exe",
(запускаемое имя cli-клиента еспансы).
- вместо
- [*] Переработан автомат для Монитора который обновляет наборы снипов при изменении исходников:
-
Появился новый ключ
ready_notes_sources
в настройках АР"monitor":{"ready_notes_sources": {}}
-
Для каждого префикса (пока ожидается только
"espanso:"
) указывается список файлов со снипами. -
Полная структура настроек
"monitor":{ "ready_notes_sources": { "espanso:": [ "путь/файл1.yml", "путь/файл2.yml", ], } }
-
- [-] Прекращена поддержка тестов внутри Знаний. Рекомендую удалить ключи
tsts
.
- [+] Добавлена возможность "удалять сахар" через вызов:
-
python autorv.py -ds путь-файла-знаний::путь-по-знаниям
- Из json-данных в указанном файле будет извлечено значение и после замены сахара на регулярки выдано в соседний файл
-
путь-файла-знаний.desugar_ГГ-ММ-ДД_ЧЧ-ММ-СС.py
-