Сортировка (кириллица→латиница), нумерация и выбор форматтера жили внутри Celery-задачи с БД и не тестировались — хотя это порядок и вид готового списка литературы, который видит студент. Вынес в чистый app.bibliography.build_bibliography: - нумерация сквозная с 1; total = число записей; - сортировка по фамилии первого автора, кириллица раньше латиницы; - стиль 7.1 → полное описание (format_full), иначе 7.0.5 → краткая ссылка; - doc_id сохраняется в каждой записи; пустой список → total 0. ORM→dict конверсия осталась в задаче (она из БД), поведение сохранено 1:1. Добавлен в mypy-гейт. Тестов всего: 73 (indexer 24, gost 24, gpu 25). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
43 lines
1.8 KiB
Python
43 lines
1.8 KiB
Python
"""Сборка списка литературы по ГОСТ — чистая логика (без Celery/БД).
|
||
|
||
Сортирует источники (кириллица → латиница), нумерует и форматирует каждый по
|
||
выбранному стилю. Вынесено из Celery-задачи для изолированного тестирования
|
||
порядка и нумерации — того, что студент видит в готовом списке литературы.
|
||
"""
|
||
|
||
from collections.abc import Callable
|
||
from typing import Any
|
||
|
||
from app.formatters.gost_7_0_5 import GOST705Formatter
|
||
from app.formatters.gost_7_1 import GOST71Formatter, _get_sort_key
|
||
|
||
|
||
def build_bibliography(docs: list[dict[str, Any]], style: str = "7.1") -> dict[str, Any]:
|
||
"""Собрать нумерованный список литературы по ГОСТ.
|
||
|
||
Args:
|
||
docs: словари документов (title/authors/year/...); каждый должен иметь "id"
|
||
style: "7.1" (полное описание) или иначе — "7.0.5" (краткая ссылка)
|
||
|
||
Returns:
|
||
dict с полями:
|
||
bibliography: list of {"number", "citation", "doc_id"}
|
||
style: применённый стиль
|
||
total: число записей
|
||
"""
|
||
cite: Callable[[dict[str, Any]], str] = (
|
||
GOST71Formatter().format_full if style == "7.1" else GOST705Formatter().format_short
|
||
)
|
||
|
||
sorted_docs = sorted(docs, key=_get_sort_key)
|
||
bibliography = [
|
||
{"number": number, "citation": cite(doc), "doc_id": doc["id"]}
|
||
for number, doc in enumerate(sorted_docs, 1)
|
||
]
|
||
|
||
return {
|
||
"bibliography": bibliography,
|
||
"style": style,
|
||
"total": len(bibliography),
|
||
}
|