Cat Feeder  1.0.0
The Cat feeder project
Loading...
Searching...
No Matches
__main__.py
Go to the documentation of this file.
1r"""
2# +==== BEGIN CatFeeder =================+
3# LOGO:
4# ..............(..../\
5# ...............)..(.')
6# ..............(../..)
7# ...............\‍(__)|
8# Inspired by Joan Stark
9# source https://www.asciiart.eu/
10# animals/cats
11# /STOP
12# PROJECT: CatFeeder
13# FILE: __main__.py
14# CREATION DATE: 11-10-2025
15# LAST Modified: 14:53:47 19-12-2025
16# DESCRIPTION:
17# This is the backend server in charge of making the actual website work.
18# /STOP
19# COPYRIGHT: (c) Cat Feeder
20# PURPOSE: The file in charge of allowing the files in this folder to be run as is, without any issues.
21# // AR
22# +==== END CatFeeder =================+
23"""
24
25import os
26import sys
27import time
28from pathlib import Path
29# Terminal Logging
30from display_tty import Disp, initialise_logger
31
32# File Logging functionalities
33from rotary_logger import RotaryLogger, RL_CONST
34LOG_PATH: Path = Path(__file__).parent.parent
35MERGE_STREAMS: bool = os.environ.get(
36 "MERGE_STREAMS",
37 "false"
38).lower() in ("1", "true", "yes")
39INSTANCE = RotaryLogger(
40 merge_streams=MERGE_STREAMS,
41 log_to_file=RL_CONST.LOG_TO_FILE_ENV,
42 raw_log_folder=str(LOG_PATH),
43 default_log_folder=LOG_PATH
44)
45INSTANCE.start_logging()
46
47# Server name (local setting)
48SERVER_NAME = "CatFeeder"
49
50# Initialising the logger
51IDISP: Disp = initialise_logger(f"'{SERVER_NAME}'", False)
52
53# Startup message
54IDISP.append_run_date()
55IDISP.log_info(f"LOG_PATH: {LOG_PATH}")
56IDISP.disp_message_box(f"Starting '{SERVER_NAME}'")
57IDISP.log_info(f"Caller: '{sys.executable}")
58IDISP.log_info(f"Caller prefix: '{sys.exec_prefix}'")
59IDISP.log_info(f"Provided arguments: '{sys.argv}'")
60IDISP.log_info(f"Argument count: '{len(sys.argv)}'")
61IDISP.log_info(f"Python version: '{sys.version}")
62IDISP.log_info(f"Byteorder: '{sys.byteorder}")
63IDISP.log_info(f"Base exec prefix: '{sys.base_exec_prefix}'")
64IDISP.log_info(
65 f"Don't write bytecode: {'True' if sys.dont_write_bytecode else 'False'}"
66)
67
68
69IDISP.log_info("Attempting to import required dependencies...")
70try:
71 from .server_main import Main, CONST
72except ImportError:
73 from server_main import Main, CONST
74IDISP.log_info("Required dependencies imported")
75
76IDISP.log_info("Initialising the Main class...")
77MI = Main(
78 success=CONST.SUCCESS,
79 error=CONST.ERROR
80)
81IDISP.log_info("Main class initialised")
82IDISP.log_info("Calling main function...")
83
84STATUS = CONST.ERROR
85try:
86 STATUS = MI.main()
87 IDISP.log_info("Main function called")
88except SystemExit as e:
89 IDISP.log_info(f"SystemExit caught with code: {e.code}")
90 STATUS = e.code if isinstance(e.code, int) else CONST.ERROR
91except KeyboardInterrupt:
92 IDISP.log_info("KeyboardInterrupt caught (Ctrl+C)")
93 STATUS = CONST.SUCCESS
94except Exception as e:
95 IDISP.log_error(f"Unhandled exception: {type(e).__name__}: {e}")
96 STATUS = CONST.ERROR
97 raise
98finally:
99 # Shutdown message
100 IDISP.log_info("Shutting down...")
101 IDISP.append_run_date()
102 IDISP.disp_message_box("The server has shut down")
103
104 IDISP.log_info("Stopping rotary file logging...")
105 try:
106 INSTANCE.stop_logging()
107 IDISP.log_info("Stopped rotary file logging")
108 except Exception as cleanup_error:
109 IDISP.log_error(f"Error during logging cleanup: {cleanup_error}")
110
111 # Ensure all logs are flushed before exit
112 sys.stdout.flush()
113 sys.stderr.flush()
114 time.sleep(0.1) # Small delay to ensure filesystem writes complete
115
116# Only exit if we're not re-raising an exception
117sys.exit(STATUS)