Skip to content

Commit 3ec4ff0

Browse files
committed
feat: implement API module with FastAPI and initial route handlers
1 parent eee346e commit 3ec4ff0

File tree

10 files changed

+764
-87
lines changed

10 files changed

+764
-87
lines changed

main.py

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,21 @@
33
import logging
44
import os
55
from pathlib import Path
6-
from typing import Optional
7-
8-
# Configure logging
9-
logging.basicConfig(
10-
level=logging.INFO,
11-
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
12-
)
13-
logger = logging.getLogger(__name__)
14-
15-
16-
def setup_environment() -> dict[str, str]:
17-
"""Load environment variables from .env file."""
18-
env_vars = {}
19-
env_path = Path(".env")
20-
21-
if env_path.exists():
22-
with env_path.open() as f:
23-
for line in f:
24-
line = line.strip()
25-
if line and not line.startswith("#"):
26-
key, value = line.split("=", 1)
27-
env_vars[key.strip()] = value.strip()
28-
29-
return env_vars
6+
from typing import Dict
7+
308

319

32-
def main() -> None:
33-
"""Main application entry point."""
34-
try:
35-
# Load environment variables
36-
env_vars = setup_environment()
37-
app_name = env_vars.get("APP_NAME", "template-python")
38-
env = env_vars.get("ENV", "development")
39-
debug = env_vars.get("DEBUG", "false").lower() == "true"
4010

41-
# Configure logging level based on debug setting
42-
if debug:
43-
logging.getLogger().setLevel(logging.DEBUG)
44-
logger.debug("Debug mode enabled")
4511

46-
logger.info(f"Starting {app_name} in {env} environment")
4712

48-
# Your application initialization code here
49-
# For example:
50-
# app = create_app()
51-
# app.run()
13+
def main() -> None:
14+
"""Main application entry point."""
15+
try:
16+
print("Start app...")
17+
import src.modules.api
5218

5319
except Exception as e:
54-
logger.error(f"Application failed to start: {e}", exc_info=True)
20+
print(f"Application failed to start: {e}", exc_info=True)
5521
raise
5622

5723

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ description = "Add your description here"
55
readme = "README.md"
66
requires-python = ">=3.11"
77
dependencies = [
8+
"fastapi[standard]>=0.115.8",
89
"ipykernel>=6.29.5",
910
"numpy>=2.2.3",
1011
"pytest>=8.3.4",

src/modules/api/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""API module initialization."""
2+
print("API module loaded.")
3+
import src.modules.api.index

src/modules/api/app.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""FastAPI application factory."""
2+
3+
from fastapi import FastAPI
4+
from fastapi.middleware.cors import CORSMiddleware
5+
6+
from .routes import v1_router
7+
8+
def create_app() -> FastAPI:
9+
"""Create and configure the FastAPI application."""
10+
app = FastAPI(
11+
12+
)
13+
14+
# Add CORS middleware
15+
app.add_middleware(
16+
CORSMiddleware,
17+
allow_origins=["*"],
18+
allow_credentials=True,
19+
allow_methods=["*"],
20+
allow_headers=["*"],
21+
)
22+
23+
# Include routers
24+
app.include_router(v1_router)
25+
26+
@app.on_event("startup")
27+
async def startup_event():
28+
"""Run startup events."""
29+
pass
30+
31+
@app.on_event("shutdown")
32+
async def shutdown_event():
33+
"""Run shutdown events."""
34+
pass
35+
36+
return app
37+
38+
# Create default app instance
39+
app = create_app()

src/modules/api/index.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import uvicorn
2+
from .app import app as api_app
3+
4+
def main():
5+
"""Main application entry point."""
6+
try:
7+
print("Start api...")
8+
uvicorn.run(
9+
api_app,
10+
host="0.0.0.0",
11+
port=8800,
12+
reload=False,
13+
)
14+
except Exception as e:
15+
print(f"Application failed to start: {e}", exc_info=True)
16+
raise
17+
main()

src/modules/api/routes.py

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/modules/api/routes/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""API routes package."""
2+
3+
from .v1 import router as v1_router
4+
5+
__all__ = ["v1_router"]

src/modules/api/routes/v1.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""API v1 route handlers."""
2+
3+
from fastapi import APIRouter
4+
from typing import Dict, List
5+
6+
7+
# Create v1 router
8+
router = APIRouter(prefix='/v1', tags=['v1'])
9+
10+
@router.get("/hello")
11+
async def hello_world() -> Dict[str, str]:
12+
"""Hello world endpoint."""
13+
return {"message": "Hello, World!"}
14+
15+
@router.get("/health")
16+
async def health_check() -> Dict[str, str]:
17+
"""Health check endpoint."""
18+
return {"status": "healthy"}
19+
20+
@router.get("/metrics")
21+
async def metrics() -> Dict[str, int]:
22+
"""Application metrics endpoint."""
23+
return {
24+
"total_routes": len(router.routes),
25+
"api_version": 1
26+
}

src/utils/loader.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""Module loader utilities."""
2+
3+
import logging
4+
import uvicorn
5+
from typing import Any, Optional
6+
7+
from src.modules.api.app import app as api_app
8+
from src.modules.api.core.config import settings
9+
10+
logger = logging.getLogger(__name__)
11+
12+
class ModuleLoader:
13+
"""Utility class for loading and running modules."""
14+
15+
@staticmethod
16+
def load_api(
17+
host: str = "0.0.0.0",
18+
port: int = 8000,
19+
reload: bool = False,
20+
**kwargs: Any
21+
) -> None:
22+
"""Load and run the API module.
23+
24+
Args:
25+
host: Host to bind the server to
26+
port: Port to bind the server to
27+
reload: Enable auto-reload for development
28+
**kwargs: Additional uvicorn configuration
29+
"""
30+
logger.info(f"Starting API server on {host}:{port}")
31+
logger.debug(f"API Settings: {settings.dict()}")
32+
33+
config = uvicorn.Config(
34+
api_app,
35+
host=host,
36+
port=port,
37+
reload=reload,
38+
log_level="debug" if settings.debug else "info",
39+
**kwargs
40+
)
41+
42+
server = uvicorn.Server(config)
43+
server.run()
44+
45+
@classmethod
46+
def load_module(
47+
cls,
48+
module_name: str,
49+
**kwargs: Any
50+
) -> Optional[Any]:
51+
"""Generic module loader.
52+
53+
Args:
54+
module_name: Name of the module to load
55+
**kwargs: Module-specific configuration
56+
57+
Returns:
58+
Optional[Any]: Module instance if applicable
59+
"""
60+
if module_name == "api":
61+
cls.load_api(**kwargs)
62+
return api_app
63+
else:
64+
logger.error(f"Unknown module: {module_name}")
65+
return None

0 commit comments

Comments
 (0)