Coverage for narrative_harm_classifier/api/main.py: 78%

23 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-20 13:25 +0000

1""" 

2api/main.py — FastAPI application entry point. 

3""" 

4 

5from fastapi import FastAPI 

6from contextlib import asynccontextmanager 

7import logging 

8 

9from narrative_harm_classifier.core.config import get_settings 

10from narrative_harm_classifier.api.routes import classify, validate, health, tracking, benchmark 

11 

12logger = logging.getLogger(__name__) 

13 

14 

15@asynccontextmanager 

16async def lifespan(app: FastAPI): 

17 settings = get_settings() 

18 logger.info(f"Starting {settings.app_name} v{settings.app_version}") 

19 logger.info(f"Taxonomy: {settings.taxonomy_config_path} v{settings.taxonomy_version}") 

20 yield 

21 logger.info("Shutting down") 

22 

23 

24def create_app() -> FastAPI: 

25 settings = get_settings() 

26 

27 app = FastAPI( 

28 title=settings.app_name, 

29 version=settings.app_version, 

30 description=( 

31 "Narrative Harm Classification API\n\n" 

32 "Implements the D2.4a classification specification with multi-dimensional " 

33 "rule-based logic across targets, identities, harm mechanisms, and " 

34 "decision thresholds. Azure Text Analytics integrated for optional NLP signal " 

35 "amplification. Also provides escalation-chain tracking across sources over time " 

36 "and a templated benchmark suite for credible precision/recall reporting." 

37 ), 

38 lifespan=lifespan, 

39 ) 

40 

41 app.include_router(health.router, tags=["Health"]) 

42 app.include_router(classify.router, prefix="/classify", tags=["Classification"]) 

43 app.include_router(validate.router, prefix="/validate", tags=["Validation"]) 

44 app.include_router(tracking.router, prefix="/tracking", tags=["Escalation Tracking"]) 

45 app.include_router(benchmark.router, prefix="/benchmark", tags=["Benchmark"]) 

46 

47 return app 

48 

49 

50app = create_app()