После «Закрыть только GUI» окно просто пропадало, а после «Закрыть и остановить DPI» стояло как было, пока останавливался обход; уборка при выходе шла при видимом окне, и оно на это время замирало. Теперь между командой и исчезновением окна поверх него проступает экран (ui/exit_screen.py): медоед, заголовок, который прямо говорит, что происходит («Окно закрывается», «Останавливаем обход», «Обход остановлен»), и лёгкая строка под ним. Строка берётся из общего набора шуток ui/fun_phrases (блоки exit_keep, exit_idle, exit_stopping, exit_stopped); пока блока нет — простая запасная фраза. Затем прозрачность окна плавно уходит в ноль, и только после этого программа закрывается: уборка идёт при невидимом окне. Экран показывает единственный владелец выхода — ApplicationLifecycle, через window_port.begin_exit_screen. Это украшение, а не шаг выхода: если окна нет на экране или экран не удалось показать, программа закрывается сразу; если остановка обхода не сообщила о себе за 20 секунд, экран убирается. Выход ради установки обновления (farewell=False) и завершение сеанса Windows идут без экрана. Проверено на настоящей сборке на win10 (нажатие кнопок окна «Закрыть приложение» через средства доступности): окно отвечает всё время показа (самая долгая заминка 42 мс), прозрачность уходит 255 → 0 без скачка, окно исчезает сразу после. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
29 lines
1.2 KiB
Python
29 lines
1.2 KiB
Python
from __future__ import annotations
|
|
|
|
"""Устройство установки: страница только показывает, работой владеют сервисы."""
|
|
|
|
import inspect
|
|
import unittest
|
|
|
|
from updater.download import service as install_service
|
|
from updater.ui import page
|
|
|
|
|
|
class UpdaterInstallArchitectureTest(unittest.TestCase):
|
|
def test_page_owns_no_download_dpi_or_installer_work(self) -> None:
|
|
source = inspect.getsource(page)
|
|
|
|
for forbidden in ("shutdown_sync", "restart(", "start_supervised_installation", "download_artifact", "QThread"):
|
|
self.assertNotIn(forbidden, source)
|
|
|
|
def test_installer_success_requests_exit_on_main_thread(self) -> None:
|
|
source = inspect.getsource(install_service.UpdateInstallService._on_task_done)
|
|
|
|
self.assertIn("QTimer.singleShot", source)
|
|
# Без прощального экрана: программа закрывается не по команде человека.
|
|
self.assertIn("request_exit(stop_dpi=False, farewell=False)", source)
|
|
self.assertNotIn("os._exit", inspect.getsource(install_service))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|