Coverage for src / local_deep_research / web / app.py: 22%
40 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-25 01:07 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-25 01:07 +0000
1import atexit
2from loguru import logger
4from ..__version__ import __version__
5from ..utilities.log_utils import config_logger, flush_log_queue
6from .app_factory import create_app
7from .server_config import load_server_config
10@logger.catch
11def main():
12 """
13 Entry point for the web application when run as a command.
14 This function is needed for the package's entry point to work properly.
15 """
16 # Configure logging with milestone level
17 config = load_server_config()
18 config_logger("ldr_web", debug=config["debug"])
19 logger.info(f"Starting Local Deep Research v{__version__}")
21 # Register atexit handler to flush logs on exit
22 def flush_logs_on_exit():
23 """Flush any pending logs when the program exits."""
24 try:
25 # Create a minimal Flask app context to allow database access
26 from flask import Flask
28 app = Flask(__name__)
29 with app.app_context():
30 flush_log_queue()
31 except Exception:
32 logger.exception("Failed to flush logs on exit")
34 atexit.register(flush_logs_on_exit)
35 logger.debug("Registered atexit handler for log flushing")
37 # Create the Flask app and SocketIO instance
38 app, socket_service = create_app()
40 # Get web server settings from configuration file or environment
41 # This allows settings to be configured through the web UI
42 host = config["host"]
43 port = config["port"]
44 debug = config["debug"]
45 use_https = config["use_https"]
47 if use_https:
48 # For development, use self-signed certificate
49 logger.info("Starting server with HTTPS (self-signed certificate)")
50 # Note: SocketIOService doesn't support SSL context directly
51 # For production, use a reverse proxy like nginx for HTTPS
52 logger.warning(
53 "HTTPS requested but not supported directly. Use a reverse proxy for HTTPS."
54 )
56 # Register shutdown handler for scheduler
57 def shutdown_scheduler():
58 if hasattr(app, "news_scheduler") and app.news_scheduler:
59 try:
60 app.news_scheduler.stop()
61 logger.info("News subscription scheduler stopped gracefully")
62 except Exception:
63 logger.exception("Error stopping scheduler")
65 atexit.register(shutdown_scheduler)
67 # Use the SocketIOService's run method which properly runs the socketio server
68 socket_service.run(host=host, port=port, debug=debug)
71if __name__ == "__main__": 71 ↛ 72line 71 didn't jump to line 72 because the condition on line 71 was never true
72 main()