Files
Balsam_167/UKSSTMS320F28335/prepare_identity.py
T
Andrey f741741cf8 Сохранить русские комментарии и настройки проекта в UTF-8
Добавить пояснения к исходникам, заголовкам TI, настройкам CCS и существующим проверкам. Зафиксировать правила кодировки, обзор модулей и аудит комментариев.
2026-10-12 12:24:48 +03:00

91 lines
8.2 KiB
Python

# Настройки и интерфейс prepare_identity. Комментарии и исходный текст в UTF-8.
# Продолжает текущий вызов, список или выражение: """Generate build identity using the release version from firmware_version.h."""; порядок аргументов сохраняется.
"""Generate build identity using the release version from firmware_version.h."""
# Подключает модуль argparse для этой проверки или подготовки сборки.
import argparse
# Подключает модуль importlib.util для этой проверки или подготовки сборки.
import importlib.util
# Подключает модуль json для этой проверки или подготовки сборки.
import json
# Импортирует необходимые имена: from pathlib import Path.
from pathlib import Path
# Подключает модуль re для этой проверки или подготовки сборки.
import re
# Подключает модуль tempfile для этой проверки или подготовки сборки.
import tempfile
# Объявляет функцию read_version и её входные параметры.
def read_version(header):
# Читает исходный файл или образ для последующей проверки и разбора.
text = header.read_text(encoding="utf-8-sig")
# Задаёт text по выражению справа; значение используется последующими операциями.
text = re.sub(r"/\*.*?\*/|//[^\n]*", "", text, flags=re.S)
# Задаёт version по выражению справа; значение используется последующими операциями.
version = []
# Перебирает part, limit in (("MAJOR", 255), ("MINOR", 255), ("PATCH", 999)) в указанном порядке.
for part, limit in (("MAJOR", 255), ("MINOR", 255), ("PATCH", 999)):
# Задаёт name по выражению справа; значение используется последующими операциями.
name = "FIRMWARE_VERSION_" + part
# Задаёт definitions по выражению справа; значение используется последующими операциями.
definitions = re.findall(r"^\s*#\s*define\s+" + name + r"\b([^\n]*)", text, re.M)
# Проверяет условие if len(definitions) != 1 перед выполнением следующего блока.
if len(definitions) != 1:
# Останавливает текущую операцию с исключением ValueError(f"{header}: define {name} exactly once").
raise ValueError(f"{header}: define {name} exactly once")
# Задаёт value по выражению справа; значение используется последующими операциями.
value = definitions[0].strip()
# Проверяет условие if not re.fullmatch(r"(?:0|[1-9][0-9]*)[uU]?", value) перед выполнением следующего блока.
if not re.fullmatch(r"(?:0|[1-9][0-9]*)[uU]?", value):
# Останавливает текущую операцию с исключением ValueError(f"{header}: {name} must be a decimal integer").
raise ValueError(f"{header}: {name} must be a decimal integer")
# Задаёт number по выражению справа; значение используется последующими операциями.
number = int(value.rstrip("uU"))
# Проверяет условие if not 0 <= number <= limit перед выполнением следующего блока.
if not 0 <= number <= limit:
# Останавливает текущую операцию с исключением ValueError(f"{header}: {name} must be in 0..{limit}").
raise ValueError(f"{header}: {name} must be in 0..{limit}")
# Продолжает текущий вызов, список или выражение: version.append(number); порядок аргументов сохраняется.
version.append(number)
# Возвращает version вызывающему коду и завершает функцию.
return version
# Объявляет функцию prepare и её входные параметры.
def prepare(project, templates, output):
# Читает исходный файл или образ для последующей проверки и разбора.
settings = json.loads((project / "firmware_identity.json").read_text(encoding="utf-8-sig"))
# Задаёт settings["version"] по выражению справа; значение используется последующими операциями.
settings["version"] = read_version(project / "firmware_version.h")
# Задаёт spec по выражению справа; значение используется последующими операциями.
spec = importlib.util.spec_from_file_location("shared_firmware_identity", templates / "c/firmware-info/tools/identity.py")
# Задаёт identity по выражению справа; значение используется последующими операциями.
identity = importlib.util.module_from_spec(spec)
# Продолжает текущий вызов, список или выражение: spec.loader.exec_module(identity); порядок аргументов сохраняется.
spec.loader.exec_module(identity)
# The source header owns SemVer; retain the shared generator and manifest format.
# Открывает управляемый ресурс tempfile.TemporaryDirectory(prefix="balsam-identity-") as directory с автоматическим освобождением.
with tempfile.TemporaryDirectory(prefix="balsam-identity-") as directory:
# Задаёт config по выражению справа; значение используется последующими операциями.
config = Path(directory) / "config.json"
# Сохраняет подготовленный файл в указанном формате для следующего шага.
config.write_text(json.dumps(settings), encoding="utf-8")
# Возвращает identity.prepare(project, templates, config, output) вызывающему коду и завершает функцию.
return identity.prepare(project, templates, config, output)
# Проверяет условие if __name__ == "__main__" перед выполнением следующего блока.
if __name__ == "__main__":
# Задаёт parser по выражению справа; значение используется последующими операциями.
parser = argparse.ArgumentParser(description=__doc__)
# Задаёт parser.add_argument("--project", type по выражению справа; значение используется последующими операциями.
parser.add_argument("--project", type=Path, required=True)
# Задаёт parser.add_argument("--templates", type по выражению справа; значение используется последующими операциями.
parser.add_argument("--templates", type=Path, required=True)
# Задаёт parser.add_argument("--output", type по выражению справа; значение используется последующими операциями.
parser.add_argument("--output", type=Path, required=True)
# Задаёт args по выражению справа; значение используется последующими операциями.
args = parser.parse_args()
# Продолжает текущий вызов, список или выражение: print(json.dumps(prepare(args.project, args.templates, args.output))); порядок аргументов сохраняется.
print(json.dumps(prepare(args.project, args.templates, args.output)))