Coverage for app.py: 96%
54 statements
« prev ^ index » next coverage.py v7.9.2, created at 2026-07-24 16:42 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2026-07-24 16:42 +0000
1import logging
2from contextlib import asynccontextmanager
3import httpx
4from fastapi import FastAPI, Request
5from fastapi.encoders import jsonable_encoder
6from fastapi.responses import JSONResponse
7from fastapi.exceptions import RequestValidationError
8from config import settings
9from model import *
10from mongo import *
13@asynccontextmanager
14async def lifespan(app: FastAPI):
15 app.state.http_client = httpx.Client(timeout=httpx.Timeout(5.0, read=30.0))
16 yield
17 app.state.http_client.close()
20def create_app() -> FastAPI:
21 app = FastAPI(lifespan=lifespan)
23 from model.utils.response import NOJException
25 @app.exception_handler(NOJException)
26 async def noj_exception_handler(request: Request, exc: NOJException):
27 return JSONResponse(
28 {
29 'status': 'err',
30 'message': exc.message,
31 'data': exc.data,
32 },
33 status_code=exc.status_code,
34 )
36 @app.exception_handler(RequestValidationError)
37 async def validation_exception_handler(request: Request,
38 exc: RequestValidationError):
39 return JSONResponse(
40 {
41 'status': 'err',
42 'message': 'Invalid request body',
43 'data': jsonable_encoder(exc.errors()),
44 },
45 status_code=400,
46 )
48 app.include_router(auth_router, prefix='/auth')
49 app.include_router(profile_router, prefix='/profile')
50 app.include_router(problem_router, prefix='/problem')
51 app.include_router(submission_router, prefix='/submission')
52 app.include_router(course_router, prefix='/course')
53 app.include_router(homework_router, prefix='/homework')
54 app.include_router(test_router, prefix='/test')
55 app.include_router(ann_router, prefix='/ann')
56 app.include_router(ranking_router, prefix='/ranking')
57 app.include_router(post_router, prefix='/post')
58 app.include_router(copycat_router, prefix='/copycat')
59 app.include_router(health_router, prefix='/health')
60 app.include_router(user_router, prefix='/user')
61 app.include_router(user_options_router, prefix='/user')
63 _seed_db()
65 logger = logging.getLogger(__name__)
66 if settings.SMTP_SERVER is None:
67 logger.info(
68 "'SMTP_SERVER' is not set. email-related function will be disabled"
69 )
70 elif settings.SMTP_NOREPLY_PASSWORD is None:
71 logger.info("'SMTP_NOREPLY' set but 'SMTP_NOREPLY_PASSWORD' not")
73 return app
76def _seed_db():
77 if not User('first_admin'):
78 ADMIN = {
79 'username': 'first_admin',
80 'password': 'firstpasswordforadmin',
81 'email': 'i.am.first.admin@noj.tw',
82 }
83 PROFILE = {
84 'displayed_name': 'the first admin',
85 'bio': 'I am super good!!!!!',
86 }
87 admin = User.signup(**ADMIN)
88 admin.update(
89 active=True,
90 role=0,
91 profile=PROFILE,
92 )
93 if not Course('Public'):
94 Course.add_course('Public', 'first_admin')
97app = create_app()