110 lines
4.0 KiB
Python
110 lines
4.0 KiB
Python
"""Локальный прогон пайплайна без SMB и без Streamlit UI.
|
||
|
||
Берёт XML-файлы из указанной локальной папки, парсит их и формирует
|
||
report.xlsx + protocol.xlsx в текущей рабочей директории (или в папке,
|
||
заданной через --out).
|
||
|
||
Пример:
|
||
python scripts/run_local.py /path/to/xml_folder
|
||
python scripts/run_local.py /path/to/xml_folder --out /tmp/result
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import getpass
|
||
import sys
|
||
from datetime import datetime
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parent
|
||
if str(ROOT) not in sys.path:
|
||
sys.path.insert(0, str(ROOT))
|
||
|
||
from app.pipeline.parser import parse_xml_content # noqa: E402
|
||
from app.pipeline.protocol import ProtocolRow, write_protocol # noqa: E402
|
||
from app.pipeline.report import ReportRow, StreamingReportWriter # noqa: E402
|
||
from app.pipeline.service import ( # noqa: E402 # переиспользуем логику статуса
|
||
_resolve_parse_status,
|
||
)
|
||
|
||
|
||
def main() -> int:
|
||
parser = argparse.ArgumentParser(description=__doc__)
|
||
parser.add_argument("input_dir", type=Path, help="Локальная папка с XML-файлами")
|
||
parser.add_argument(
|
||
"--out",
|
||
type=Path,
|
||
default=Path.cwd(),
|
||
help="Куда сохранить report.xlsx/protocol.xlsx (по умолчанию — текущая директория)",
|
||
)
|
||
parser.add_argument(
|
||
"--launcher",
|
||
default=getpass.getuser(),
|
||
help="Имя запустившего (для протокола); по умолчанию — текущий пользователь ОС",
|
||
)
|
||
args = parser.parse_args()
|
||
|
||
input_dir: Path = args.input_dir
|
||
out_dir: Path = args.out
|
||
if not input_dir.is_dir():
|
||
print(f"Папка не найдена: {input_dir}", file=sys.stderr)
|
||
return 1
|
||
out_dir.mkdir(parents=True, exist_ok=True)
|
||
|
||
xml_paths = sorted(input_dir.rglob("*.xml"))
|
||
if not xml_paths:
|
||
print(f"В {input_dir} не найдено XML-файлов.")
|
||
return 1
|
||
|
||
report_writer = StreamingReportWriter()
|
||
protocol_rows: list[ProtocolRow] = []
|
||
|
||
for xml_path in xml_paths:
|
||
file_name = xml_path.name
|
||
content = xml_path.read_bytes()
|
||
parse_result = parse_xml_content(file_name=file_name, xml_content=content)
|
||
|
||
for row in parse_result.rows:
|
||
report_writer.append_row(
|
||
ReportRow(
|
||
file_name=row.file_name,
|
||
record_id=row.record_id,
|
||
operation_index=row.operation_index,
|
||
operation_fields=row.operation_fields,
|
||
participant_fields=row.participant_fields,
|
||
is_continuation=row.is_continuation,
|
||
)
|
||
)
|
||
|
||
status, message = _resolve_parse_status(parse_result)
|
||
protocol_rows.append(
|
||
ProtocolRow(
|
||
file_name=file_name,
|
||
status=status,
|
||
message=message,
|
||
operations_total=parse_result.total_operations,
|
||
rows_written=len(parse_result.rows),
|
||
launcher=args.launcher,
|
||
processed_at=datetime.now(),
|
||
)
|
||
)
|
||
print(f"{file_name}: {status} — {message}")
|
||
|
||
report_path = out_dir / "report.xlsx"
|
||
protocol_path = out_dir / "protocol.xlsx"
|
||
report_writer.save(report_path)
|
||
write_protocol(protocol_rows, protocol_path)
|
||
|
||
processed = sum(1 for r in protocol_rows if r.status == "success")
|
||
partial = sum(1 for r in protocol_rows if r.status == "partial")
|
||
errors = sum(1 for r in protocol_rows if r.status == "error")
|
||
print(f"\nГотово: успешно={processed}, частично={partial}, с ошибками={errors}.")
|
||
print(f"Отчёт: {report_path}")
|
||
print(f"Протокол: {protocol_path}")
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main())
|