Сохранить русские комментарии и настройки проекта в UTF-8
Добавить пояснения к исходникам, заголовкам TI, настройкам CCS и существующим проверкам. Зафиксировать правила кодировки, обзор модулей и аудит комментариев.
This commit is contained in:
@@ -0,0 +1,262 @@
|
||||
# Проверка comments на модели пк. Комментарии и исходный текст в UTF-8.
|
||||
# Продолжает текущий вызов, список или выражение: """Проверка UTF-8 и русских пояснений к каждой строке исходного кода."""; порядок аргументов сохраняется.
|
||||
"""Проверка UTF-8 и русских пояснений к каждой строке исходного кода."""
|
||||
# Подключает модуль argparse для этой проверки или подготовки сборки.
|
||||
import argparse
|
||||
# Подключает модуль io для этой проверки или подготовки сборки.
|
||||
import io
|
||||
# Импортирует необходимые имена: from pathlib import Path.
|
||||
from pathlib import Path
|
||||
# Подключает модуль re для этой проверки или подготовки сборки.
|
||||
import re
|
||||
# Подключает модуль subprocess для этой проверки или подготовки сборки.
|
||||
import subprocess
|
||||
# Подключает модуль tokenize для этой проверки или подготовки сборки.
|
||||
import tokenize
|
||||
|
||||
# Задаёт ROOT по выражению справа; значение используется последующими операциями.
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
# Задаёт RUSSIAN по выражению справа; значение используется последующими операциями.
|
||||
RUSSIAN = re.compile("[А-Яа-яЁё]")
|
||||
# Задаёт C_SUFFIXES по выражению справа; значение используется последующими операциями.
|
||||
C_SUFFIXES = {".c", ".h", ".cmd", ".inc"}
|
||||
# Задаёт TEXT_SUFFIXES по выражению справа; значение используется последующими операциями.
|
||||
TEXT_SUFFIXES = C_SUFFIXES | {".asm", ".py", ".md", ".bat", ".old", ".prefs", ".json", ".pjt", ".lkf"}
|
||||
# Задаёт TEXT_NAMES по выражению справа; значение используется последующими операциями.
|
||||
TEXT_NAMES = {".project", ".cproject", ".ccsproject", ".gitignore", ".editorconfig"}
|
||||
|
||||
# Объявляет функцию c_code_lines и её входные параметры.
|
||||
def c_code_lines(text):
|
||||
# Задаёт block по выражению справа; значение используется последующими операциями.
|
||||
block = False
|
||||
# Перебирает line in text.splitlines() в указанном порядке.
|
||||
for line in text.splitlines():
|
||||
# Задаёт out по выражению справа; значение используется последующими операциями.
|
||||
out = []
|
||||
# Задаёт i по выражению справа; значение используется последующими операциями.
|
||||
i = 0
|
||||
# Задаёт quote по выражению справа; значение используется последующими операциями.
|
||||
quote = None
|
||||
# Повторяет блок при выполнении i < len(line).
|
||||
while i < len(line):
|
||||
# Проверяет условие if block перед выполнением следующего блока.
|
||||
if block:
|
||||
# Задаёт end по выражению справа; значение используется последующими операциями.
|
||||
end = line.find("*/", i)
|
||||
# Проверяет условие if end < 0 перед выполнением следующего блока.
|
||||
if end < 0:
|
||||
# Продолжает текущий вызов, список или выражение: break; порядок аргументов сохраняется.
|
||||
break
|
||||
# Задаёт block по выражению справа; значение используется последующими операциями.
|
||||
block = False
|
||||
# Задаёт i по выражению справа; значение используется последующими операциями.
|
||||
i = end + 2
|
||||
# Продолжает текущий вызов, список или выражение: out.append(" "); порядок аргументов сохраняется.
|
||||
out.append(" ")
|
||||
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
|
||||
continue
|
||||
# Задаёт c по выражению справа; значение используется последующими операциями.
|
||||
c = line[i]
|
||||
# Проверяет условие if quote перед выполнением следующего блока.
|
||||
if quote:
|
||||
# Продолжает текущий вызов, список или выражение: out.append(c); порядок аргументов сохраняется.
|
||||
out.append(c)
|
||||
# Проверяет условие if c == "\\" and i + 1 < len(line) перед выполнением следующего блока.
|
||||
if c == "\\" and i + 1 < len(line):
|
||||
# Задаёт i + по выражению справа; значение используется последующими операциями.
|
||||
i += 1
|
||||
# Продолжает текущий вызов, список или выражение: out.append(line[i]); порядок аргументов сохраняется.
|
||||
out.append(line[i])
|
||||
# Проверяет условие elif c == quote перед выполнением следующего блока.
|
||||
elif c == quote:
|
||||
# Задаёт quote по выражению справа; значение используется последующими операциями.
|
||||
quote = None
|
||||
# Задаёт i + по выражению справа; значение используется последующими операциями.
|
||||
i += 1
|
||||
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
|
||||
continue
|
||||
# Проверяет условие if line.startswith("//", i) перед выполнением следующего блока.
|
||||
if line.startswith("//", i):
|
||||
# Продолжает текущий вызов, список или выражение: break; порядок аргументов сохраняется.
|
||||
break
|
||||
# Проверяет условие if line.startswith("/*", i) перед выполнением следующего блока.
|
||||
if line.startswith("/*", i):
|
||||
# Задаёт block по выражению справа; значение используется последующими операциями.
|
||||
block = True
|
||||
# Задаёт i + по выражению справа; значение используется последующими операциями.
|
||||
i += 2
|
||||
# Продолжает текущий вызов, список или выражение: out.append(" "); порядок аргументов сохраняется.
|
||||
out.append(" ")
|
||||
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
|
||||
continue
|
||||
# Проверяет условие if c in "\"'" перед выполнением следующего блока.
|
||||
if c in "\"'":
|
||||
# Задаёт quote по выражению справа; значение используется последующими операциями.
|
||||
quote = c
|
||||
# Продолжает текущий вызов, список или выражение: out.append(c); порядок аргументов сохраняется.
|
||||
out.append(c)
|
||||
# Задаёт i + по выражению справа; значение используется последующими операциями.
|
||||
i += 1
|
||||
# Продолжает текущий вызов, список или выражение: yield "".join(out).strip(); порядок аргументов сохраняется.
|
||||
yield "".join(out).strip()
|
||||
|
||||
# Объявляет функцию python_code_lines и её входные параметры.
|
||||
def python_code_lines(text):
|
||||
# Задаёт active по выражению справа; значение используется последующими операциями.
|
||||
active = set()
|
||||
# Задаёт strings по выражению справа; значение используется последующими операциями.
|
||||
strings = set()
|
||||
# Перебирает token in tokenize.generate_tokens(io.StringIO(text).readline) в указанном порядке.
|
||||
for token in tokenize.generate_tokens(io.StringIO(text).readline):
|
||||
# Проверяет условие if token.type == tokenize.STRING and token.end[0] > token.start[0] перед выполнением следующего блока.
|
||||
if token.type == tokenize.STRING and token.end[0] > token.start[0]:
|
||||
# Продолжает текущий вызов, список или выражение: strings.update(range(token.start[0] + 1, token.end[0] + 1)); порядок аргументов сохраняется.
|
||||
strings.update(range(token.start[0] + 1, token.end[0] + 1))
|
||||
# Проверяет условие if token.type not in {tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT, tokenize.ENDMARKER} перед выполнением следующего блока.
|
||||
if token.type not in {tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT, tokenize.ENDMARKER}:
|
||||
# Продолжает текущий вызов, список или выражение: active.add(token.start[0]); порядок аргументов сохраняется.
|
||||
active.add(token.start[0])
|
||||
# Задаёт lines по выражению справа; значение используется последующими операциями.
|
||||
lines = text.splitlines()
|
||||
# Возвращает [line.strip() if n in active and n not in strings else "" for n, line in enumerate(lines, 1)] вызывающему коду и завершает функцию.
|
||||
return [line.strip() if n in active and n not in strings else "" for n, line in enumerate(lines, 1)]
|
||||
|
||||
# Объявляет функцию audit и её входные параметры.
|
||||
def audit(path, text):
|
||||
# Задаёт lines по выражению справа; значение используется последующими операциями.
|
||||
lines = text.splitlines()
|
||||
# Проверяет условие if path.suffix in C_SUFFIXES перед выполнением следующего блока.
|
||||
if path.suffix in C_SUFFIXES:
|
||||
# Задаёт code по выражению справа; значение используется последующими операциями.
|
||||
code = list(c_code_lines(text))
|
||||
# Проверяет условие elif path.suffix == ".asm" перед выполнением следующего блока.
|
||||
elif path.suffix == ".asm":
|
||||
# Задаёт code по выражению справа; значение используется последующими операциями.
|
||||
code = [line.split(";")[0].strip() for line in lines]
|
||||
# Проверяет условие elif path.suffix == ".py" перед выполнением следующего блока.
|
||||
elif path.suffix == ".py":
|
||||
# Задаёт code по выражению справа; значение используется последующими операциями.
|
||||
code = python_code_lines(text)
|
||||
# Обрабатывает альтернативу предыдущего условия.
|
||||
else:
|
||||
# Возвращает 0, [] вызывающему коду и завершает функцию.
|
||||
return 0, []
|
||||
# Задаёт missing по выражению справа; значение используется последующими операциями.
|
||||
missing = []
|
||||
# Задаёт count по выражению справа; значение используется последующими операциями.
|
||||
count = 0
|
||||
# Перебирает i, value in enumerate(code) в указанном порядке.
|
||||
for i, value in enumerate(code):
|
||||
# Проверяет условие if not value перед выполнением следующего блока.
|
||||
if not value:
|
||||
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
|
||||
continue
|
||||
# Задаёт count + по выражению справа; значение используется последующими операциями.
|
||||
count += 1
|
||||
# Проверяет условие if RUSSIAN.search(lines[i]) or (i and RUSSIAN.search(lines[i-1])) перед выполнением следующего блока.
|
||||
if RUSSIAN.search(lines[i]) or (i and RUSSIAN.search(lines[i-1])):
|
||||
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
|
||||
continue
|
||||
# Явное продолжение Python-выражения относится к пояснённой начальной строке.
|
||||
# Проверяет условие if path.suffix == ".py" and i and lines[i-1].rstrip().endswith("\\") перед выполнением следующего блока.
|
||||
if path.suffix == ".py" and i and lines[i-1].rstrip().endswith("\\"):
|
||||
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
|
||||
continue
|
||||
# Продолжает текущий вызов, список или выражение: missing.append(i+1); порядок аргументов сохраняется.
|
||||
missing.append(i+1)
|
||||
# Возвращает count, missing вызывающему коду и завершает функцию.
|
||||
return count, missing
|
||||
|
||||
# Объявляет функцию main и её входные параметры.
|
||||
def main():
|
||||
# Задаёт parser по выражению справа; значение используется последующими операциями.
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
# Задаёт parser.add_argument("--report", type по выражению справа; значение используется последующими операциями.
|
||||
parser.add_argument("--report", type=Path, help="Сохранить таблицу покрытия в Markdown")
|
||||
# Задаёт args по выражению справа; значение используется последующими операциями.
|
||||
args = parser.parse_args()
|
||||
# Задаёт names по выражению справа; значение используется последующими операциями.
|
||||
names = subprocess.check_output(["git", "ls-files", "-z"], cwd=ROOT).decode("utf-8").split("\0")
|
||||
# Задаёт names по выражению справа; значение используется последующими операциями.
|
||||
names = sorted(set(filter(None, names)) | {"tests/comments/run_test.py", ".editorconfig"})
|
||||
# Задаёт rows по выражению справа; значение используется последующими операциями.
|
||||
rows = []
|
||||
# Задаёт errors по выражению справа; значение используется последующими операциями.
|
||||
errors = []
|
||||
# Задаёт checked по выражению справа; значение используется последующими операциями.
|
||||
checked = 0
|
||||
# Перебирает name in names в указанном порядке.
|
||||
for name in names:
|
||||
# Задаёт path по выражению справа; значение используется последующими операциями.
|
||||
path = ROOT / name
|
||||
# Проверяет условие if path.suffix.lower() not in TEXT_SUFFIXES and path.name not in TEXT_NAMES перед выполнением следующего блока.
|
||||
if path.suffix.lower() not in TEXT_SUFFIXES and path.name not in TEXT_NAMES:
|
||||
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
|
||||
continue
|
||||
# Начинает блок обработки возможной ошибки.
|
||||
try:
|
||||
# Читает исходный файл или образ для последующей проверки и разбора.
|
||||
text = path.read_text(encoding="utf-8")
|
||||
# Перехватывает указанный тип ошибки и выполняет обработку.
|
||||
except UnicodeError as error:
|
||||
# Продолжает текущий вызов, список или выражение: errors.append(f"{name}: неверная кодировка UTF-8: {error}"); порядок аргументов сохраняется.
|
||||
errors.append(f"{name}: неверная кодировка UTF-8: {error}")
|
||||
# Продолжает текущий вызов, список или выражение: continue; порядок аргументов сохраняется.
|
||||
continue
|
||||
# Задаёт checked + по выражению справа; значение используется последующими операциями.
|
||||
checked += 1
|
||||
# Задаёт count, missing по выражению справа; значение используется последующими операциями.
|
||||
count, missing = audit(path, text)
|
||||
# Проверяет условие if missing перед выполнением следующего блока.
|
||||
if missing:
|
||||
# Продолжает текущий вызов, список или выражение: errors.append(f"{name}: нет русского пояснения, строки {missing[:20]}"); порядок аргументов сохраняется.
|
||||
errors.append(f"{name}: нет русского пояснения, строки {missing[:20]}")
|
||||
# Проверяет условие if path.suffix in C_SUFFIXES or path.suffix in {".asm", ".py"} перед выполнением следующего блока.
|
||||
if path.suffix in C_SUFFIXES or path.suffix in {".asm", ".py"}:
|
||||
# Продолжает текущий вызов, список или выражение: rows.append((name, count, count-len(missing))); порядок аргументов сохраняется.
|
||||
rows.append((name, count, count-len(missing)))
|
||||
# Проверяет условие if args.report перед выполнением следующего блока.
|
||||
if args.report:
|
||||
# Задаёт report по выражению справа; значение используется последующими операциями.
|
||||
report = [
|
||||
# Продолжает текущий вызов, список или выражение: "# Проверка комментариев и кодировки",; порядок аргументов сохраняется.
|
||||
"# Проверка комментариев и кодировки",
|
||||
# Продолжает текущий вызов, список или выражение: "",; порядок аргументов сохраняется.
|
||||
"",
|
||||
# Продолжает текущий вызов, список или выражение: "Проверка относится к редактируемым исходникам C/H, ASM, CMD, тестовым INC и Python.",; порядок аргументов сохраняется.
|
||||
"Проверка относится к редактируемым исходникам C/H, ASM, CMD, тестовым INC и Python.",
|
||||
# Продолжает текущий вызов, список или выражение: "Каждая непустая строка кода имеет русское пояснение перед ней или на ней. Пустые строки,",; порядок аргументов сохраняется.
|
||||
"Каждая непустая строка кода имеет русское пояснение перед ней или на ней. Пустые строки,",
|
||||
# Продолжает текущий вызов, список или выражение: "текст существующих комментариев и содержимое многострочных строк данных не считаются кодом.",; порядок аргументов сохраняется.
|
||||
"текст существующих комментариев и содержимое многострочных строк данных не считаются кодом.",
|
||||
# Продолжает текущий вызов, список или выражение: "Исходные уведомления TI сохранены. JSON-паспорта, индексы IDE, таблицы XLS и двоичные",; порядок аргументов сохраняется.
|
||||
"Исходные уведомления TI сохранены. JSON-паспорта, индексы IDE, таблицы XLS и двоичные",
|
||||
# Продолжает текущий вызов, список или выражение: "результаты сборки не допускают исходных комментариев; их назначение описано в документации.",; порядок аргументов сохраняется.
|
||||
"результаты сборки не допускают исходных комментариев; их назначение описано в документации.",
|
||||
# Продолжает текущий вызов, список или выражение: "",; порядок аргументов сохраняется.
|
||||
"",
|
||||
# Продолжает текущий вызов, список или выражение: f"UTF-8 проверен в {checked} текстовых файлах. Строк кода: {sum(r[1] for r in rows)}.",; порядок аргументов сохраняется.
|
||||
f"UTF-8 проверен в {checked} текстовых файлах. Строк кода: {sum(r[1] for r in rows)}.",
|
||||
# Продолжает текущий вызов, список или выражение: "",; порядок аргументов сохраняется.
|
||||
"",
|
||||
# Продолжает текущий вызов, список или выражение: "| Файл | Строк кода | С русским пояснением |",; порядок аргументов сохраняется.
|
||||
"| Файл | Строк кода | С русским пояснением |",
|
||||
# Продолжает текущий вызов, список или выражение: "| --- | ---: | ---: |",; порядок аргументов сохраняется.
|
||||
"| --- | ---: | ---: |",
|
||||
# Продолжает текущий вызов, список или выражение: ]; порядок аргументов сохраняется.
|
||||
]
|
||||
# Задаёт report + по выражению справа; значение используется последующими операциями.
|
||||
report += [f"| {name} | {count} | {covered} |" for name,count,covered in rows]
|
||||
# Сохраняет подготовленный файл в указанном формате для следующего шага.
|
||||
args.report.write_text("\n".join(report)+"\n", encoding="utf-8")
|
||||
# Проверяет условие if errors перед выполнением следующего блока.
|
||||
if errors:
|
||||
# Останавливает текущую операцию с исключением SystemExit("\n".join(errors)).
|
||||
raise SystemExit("\n".join(errors))
|
||||
# Продолжает текущий вызов, список или выражение: print(f"PASS UTF-8: {checked} files; Russian comments: {len(rows)} source files, {sum(r[1] for r in rows)} code lines"); порядок аргументов сохраняется.
|
||||
print(f"PASS UTF-8: {checked} files; Russian comments: {len(rows)} source files, {sum(r[1] for r in rows)} code lines")
|
||||
|
||||
# Проверяет условие if __name__ == "__main__" перед выполнением следующего блока.
|
||||
if __name__ == "__main__":
|
||||
# Продолжает текущий вызов, список или выражение: main(); порядок аргументов сохраняется.
|
||||
main()
|
||||
Reference in New Issue
Block a user