certflow.controllers.output_controller 源代码

# src/certflow/controllers/output_controller.py
"""统一输出控制器(§11.8 阶段4 控制器收敛)。

聚合打印 / 扫描两控制器,对外提供单一调度入口 ``OutputController.run(target, action, **kwargs)``,
避免 ``OutputView`` / ``main_window`` 直接散落多处控制器引用。各子目标仍由既有
``PrinterController`` / ``ScanController`` 承担实际工作(蓝图 §11.8 阶段4『或保留
PrinterController/ScanController 被 dispatch 调』),本类只做统一路由 + 显式 dispatch 表。

设计要点:
- 打印机控制器(PrinterController)跨打印 / 扫描共享一份(它内部以 worker 列表承载并发,
  共享安全);扫描控制器(ScanController)由 *前台 ScanView* 持有,PrintView 的后台扫描
  仍使用其独立实例(避免与前台任务互相 cancel / 信号交叉)。
- dispatch 表为目标驱动的显式映射,便于后续接入 ``output.targets.<t>.run`` 配置键。
"""

from __future__ import annotations

from collections.abc import Callable
from typing import Any

from certflow.controllers.printer_controller import PrinterController
from certflow.controllers.scan_controller import ScanController


[文档] class OutputController: """打印 / 扫描统一调度控制器(§11.8 阶段4)。""" def __init__( self, session: Any = None, printer_name: str | None = None, printer_controller: PrinterController | None = None, scan_controller: ScanController | None = None, ) -> None: """初始化统一输出控制器。 Args: session: SQLAlchemy 会话(供 ScanController 使用;为 None 时 scan 不可用)。 printer_name: 指定打印机名;None 则使用系统默认(仅当未注入 printer_controller)。 printer_controller: 注入既有打印机控制器(共享);None 则新建。 scan_controller: 注入既有扫描控制器(共享);None 则按需新建(需 session)。 """ self._session = session self._printer_controller = printer_controller or PrinterController() if printer_name and printer_controller is None: self._printer_controller.set_printer(printer_name) self._scan_controller = scan_controller or ( ScanController(session) if session is not None else None ) # ---- 显式 dispatch 表:target -> {action: bound method} ---- @property def _dispatch(self) -> dict[str, dict[str, Callable[..., Any]]]: table: dict[str, dict[str, Callable[..., Any]]] = { "print": { "print": self._printer_controller.print_certificate, }, } if self._scan_controller is not None: table["scan"] = { "generate": self._scan_controller.generate_scans, "load": self._scan_controller.load_certificates, } return table
[文档] def run(self, target: str, action: str = "print", **kwargs: Any) -> Any: """按 (target, action) 显式 dispatch 到对应控制器方法。 Args: target: "print" / "scan" action: 目标内的动作键(见 ``_dispatch`` 表) **kwargs: 透传给具体控制器方法 Returns: 被调方法的返回值(generate_scans 返回 task_id;print_certificate 为 None) Raises: KeyError: target/action 不在 dispatch 表中 """ table = self._dispatch if target not in table or action not in table[target]: raise KeyError(f"未支持的 output 调度: target={target!r} action={action!r}") return table[target][action](**kwargs)
@property def printer_controller(self) -> PrinterController: return self._printer_controller @property def scan_controller(self) -> ScanController: if self._scan_controller is None: raise RuntimeError("OutputController 未绑定 session,无法使用扫描控制器") return self._scan_controller
[文档] def get_controller(self, target: str) -> Any: """按目标取对应控制器(统一出口)。""" if target == "scan": return self.scan_controller return self._printer_controller
# 打印机状态查询统一出口(供设置页 / 状态栏复用)
[文档] def get_printers(self) -> list[str]: return self._printer_controller.get_printers()
@property def current_printer(self) -> str: return self._printer_controller.current_printer
[文档] def get_printer_status(self) -> bool: return self._printer_controller.get_printer_status()