SFM/scripts/local_zip_test_app.py
2026-09-14 17:25:05 +03:00

113 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Тестовая страница: прикрепляете .zip с XML, он распаковывается,
обрабатывается тем же парсером, что и прод, а готовый отчёт/протокол/лог
грузятся в OpenCloud. Без SMB на входе — специально для локального теста
всей цепочки целиком.
Не трогает main.py и основной SMB-пайплайн.
Запуск:
streamlit run scripts/local_zip_test_app.py
Токен/папку можно один раз прописать в .env (см. .env.example) — поля
на странице предзаполнятся, но их всегда можно поменять руками.
"""
from __future__ import annotations
import os
import sys
import tempfile
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
import streamlit as st
from dotenv import load_dotenv
from app.opencloud_access import OpenCloudDriveResolutionError, resolve_personal_drive
from app.pipeline.service import run_local_zip_batch
load_dotenv()
st.set_page_config(page_title="СФМ — локальный тест", page_icon="📦")
st.title("Локальный тест: zip → обработка → OpenCloud")
st.caption(
"Прикрепляете .zip с XML-файлами, он распаковывается и обрабатывается "
"тем же кодом парсинга, что и прод (app/pipeline/parser.py), а отчёт, "
"протокол и лог грузятся в OpenCloud (app/opencloud_access.py). "
"SMB тут не используется вообще."
)
access_token = st.text_input(
"Access token",
value=os.getenv("SFM_OPENCLOUD_ACCESS_TOKEN", ""),
type="password",
help="Bearer-токен из Keycloak. Можно прописать в .env как SFM_OPENCLOUD_ACCESS_TOKEN.",
)
space_id_override = st.text_input(
"SPACE_ID (переопределить вручную, необязательно)",
value=os.getenv("SFM_OPENCLOUD_SPACE_ID", ""),
help=(
"Если оставить пустым — личное пространство определится "
"автоматически по токену через resolve_personal_drive()."
),
)
launcher = st.text_input("Запустил (для протокола)", value="local-test")
uploaded_zip = st.file_uploader("Архив с XML-файлами (.zip)", type=["zip"])
if st.button("Начать обработку", type="primary", use_container_width=True):
if not access_token:
st.error("Укажите access token.")
elif uploaded_zip is None:
st.error("Прикрепите .zip-архив.")
else:
space_id = space_id_override
if not space_id:
try:
drive = resolve_personal_drive(access_token)
except OpenCloudDriveResolutionError as exc:
st.error(f"Не удалось определить личное пространство: {exc}")
space_id = None
else:
space_id = drive["id"]
st.info(
f"Найдено личное пространство: id={drive['id']!r}, "
f"webDavUrl={drive.get('web_dav_url')!r}"
)
if space_id:
with tempfile.TemporaryDirectory() as tmp_dir:
zip_path = Path(tmp_dir) / uploaded_zip.name
zip_path.write_bytes(uploaded_zip.getvalue())
with st.spinner("Распаковываем, обрабатываем, грузим в OpenCloud..."):
result = run_local_zip_batch(
zip_path=zip_path,
launcher=launcher or "local-test",
opencloud_space_id=space_id,
opencloud_access_token=access_token,
)
if result.status == "success":
st.success("Обработка завершена успешно.")
elif result.status == "partial":
st.warning("Обработка завершена частично.")
else:
st.error("Обработка завершена с ошибками.")
st.write(
{
"processed": result.processed,
"partial": result.partial,
"errors": result.errors,
"report_path": result.report_path,
"protocol_path": result.protocol_path,
"log_path": result.log_path,
"duration_seconds": result.duration_seconds,
}
)
if result.messages:
st.caption("Сообщения обработки:")
for message in result.messages:
st.write(f"- {message}")