Coverage for app.py: 68%

68 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-05-05 14:02 +0000

1""" 

2This module initializes a Flask application, connects to a MongoDB database, 

3and defines routes with login-required decorators. 

4""" 

5 

6from datetime import timedelta 

7import os 

8import sys 

9import signal 

10import threading 

11from dotenv import load_dotenv 

12from flask import Flask 

13from flask_caching import Cache 

14 

15from flask_compress import Compress # type: ignore 

16 

17sys.path.append(os.path.abspath(os.path.dirname(__file__))) 

18from core.configuration_settings import Config # noqa: E402 

19from core.database_mongo_manager import DatabaseMongoManager # noqa: E402 

20from core import handlers, shared # noqa: E402 

21 

22DATABASE_MANAGER = None 

23DEADLINE_MANAGER = None 

24CONFIG_MANAGER = None 

25 

26load_dotenv() 

27 

28 

29DATABASE = "cs3528_testing" 

30 

31if shared.getenv("IS_TEST") == "True": 

32 print("In test mode") 

33 DATABASE = shared.getenv("MONGO_DB_TEST", "") 

34else: 

35 print("In production mode") 

36 DATABASE = shared.getenv("MONGO_DB_PROD", "") 

37 

38DATABASE_MANAGER = DatabaseMongoManager(shared.getenv("MONGO_URI"), DATABASE) 

39 

40tables = [ 

41 "users", 

42 "students", 

43 "opportunities", 

44 "courses", 

45 "skills", 

46 "attempted_skills", 

47 "modules", 

48 "employers", 

49 "deadline", 

50 "config", 

51] 

52 

53for table in tables: 

54 DATABASE_MANAGER.add_table(table) 

55 

56CONFIG_MANAGER = Config(DATABASE_MANAGER) 

57 

58app = Flask(__name__) 

59PORT = int(shared.getenv("PORT", "5000")) 

60app.config["SECRET_KEY"] = shared.getenv("SECRET_KEY") 

61app.config["MAX_CONTENT_LENGTH"] = 16 * 1024 * 1024 # 16 MB 

62app.config["CACHE_TYPE"] = "SimpleCache" 

63app.config["CACHE_DEFAULT_TIMEOUT"] = 300 

64app.config["SESSION_COOKIE_SAMESITE"] = "Strict" 

65app.config["SESSION_COOKIE_SECURE"] = True 

66app.config["SESSION_COOKIE_HTTPONLY"] = True 

67app.permanent_session_lifetime = timedelta(minutes=30) 

68 

69 

70cache = Cache(app) 

71compress = Compress() 

72compress.init_app(app) 

73 

74 

75handlers.configure_routes(app, cache) 

76 

77from core.deadline_manager import DeadlineManager # noqa: E402 

78 

79DEADLINE_MANAGER = DeadlineManager() 

80 

81 

82def handle_kill_signal(_signum, _frame): 

83 """ 

84 Handle the kill signal to gracefully shut down the server. 

85 """ 

86 print("Kill signal received. Shutting down the server...") 

87 DATABASE_MANAGER.close_connection() 

88 sys.exit(0) 

89 

90 

91signal.signal(signal.SIGTERM, handle_kill_signal) 

92 

93 

94def run_app(): 

95 """Run the Flask application.""" 

96 try: 

97 app.run(port=PORT) 

98 except KeyboardInterrupt: 

99 DATABASE_MANAGER.close_connection() 

100 print("Shutting down the server...") 

101 except OSError: 

102 DATABASE_MANAGER.close_connection() 

103 print("Shutting down the server...") 

104 except RuntimeError as e: 

105 print(f"Runtime error: {e}") 

106 except ValueError as e: 

107 print(f"Value error: {e}") 

108 finally: 

109 DATABASE_MANAGER.close_connection() 

110 print("Shutting down the server...") 

111 

112 

113if __name__ == "__main__": 

114 app_thread = threading.Thread(target=run_app) 

115 app_thread.start() 

116 app_thread.join()