Skip to content

Commit 87fc976

Browse files
authored
Align backend data models with expanded paper schema (#9)
* Adapt models to new paper schema * Normalize username identifier * add DatabaseConstants * Fix pylint warnings and migrate legacy users table * add pylint ignore * fix pylint GitHub workflow * adapt encoding of .pylintrc * introduce services and repositories and refactor code * fix pylint issues * adapt __init__.py files for services and repositories * pylint * adapt to code comments * adapt backend-lint.yml to check return types * fix backend-lint.yml * add mypy to workflow * add mypy.ini * add missing return types
1 parent 9f0e833 commit 87fc976

24 files changed

Lines changed: 447 additions & 127 deletions

.github/workflows/backend-lint.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Backend Lint
2+
3+
on: [push]
4+
5+
jobs:
6+
pylint:
7+
runs-on: ubuntu-latest
8+
9+
steps:
10+
- name: Checkout repository
11+
uses: actions/checkout@v4
12+
13+
- name: Set up Python
14+
uses: actions/setup-python@v6
15+
with:
16+
python-version: "3.14"
17+
18+
- name: Install dependencies
19+
working-directory: backend
20+
run: |
21+
python -m pip install --upgrade pip
22+
pip install -r requirements.txt
23+
pip install pylint
24+
25+
- name: Run Pylint
26+
working-directory: backend
27+
run: |
28+
pylint --rcfile=../.pylintrc $(git ls-files '*.py')
29+
30+
mypy:
31+
runs-on: ubuntu-latest
32+
33+
steps:
34+
- name: Checkout repository
35+
uses: actions/checkout@v4
36+
37+
- name: Set up Python
38+
uses: actions/setup-python@v6
39+
with:
40+
python-version: "3.14"
41+
42+
- name: Install MyPy and dependencies
43+
working-directory: backend
44+
run: |
45+
python -m pip install --upgrade pip
46+
pip install -r requirements.txt
47+
pip install mypy
48+
49+
- name: Run MyPy
50+
run: |
51+
mypy backend

.github/workflows/pylint.yml

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

.pylintrc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[MASTER]
2+
ignore=inquiro-env, __pycache__, build, dist
3+
4+
[MESSAGES CONTROL]
5+
disable =
6+
too-few-public-methods,
7+
not-callable,
8+
missing-module-docstring,
9+
10+
11+
[TYPECHECK]
12+
ignored-modules =
13+
sqlalchemy.sql.functions

backend/app/constants/__init__.py

Whitespace-only changes.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""Enumerations shared across database models."""
2+
3+
from enum import Enum
4+
5+
6+
class PaperSource(Enum):
7+
"""Supported sources for fetching papers."""
8+
9+
ARXIV = "ARXIV"
10+
11+
12+
class PaperType(Enum):
13+
"""High-level classifications for scholarly papers."""
14+
15+
JOURNAL = "JOURNAL"
16+
CONFERENCE = "CONFERENCE"
17+
PREPRINT = "PREPRINT"
18+
WORKSHOP = "WORKSHOP"
19+
THESIS = "THESIS"
20+
OTHER = "OTHER"

backend/app/core/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ class Settings(BaseSettings):
3030
)
3131

3232

33-
settings = Settings()
33+
settings = Settings() # type: ignore[call-arg]

backend/app/core/database.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
import logging
44
from importlib import import_module
5+
from typing import Any, Generator
56

67
from sqlalchemy import create_engine
7-
from sqlalchemy.orm import declarative_base, sessionmaker
8+
from sqlalchemy.orm import declarative_base, sessionmaker, Session
89

910
from app.core.config import settings
1011

@@ -22,13 +23,20 @@
2223

2324
def init_db() -> None:
2425
"""Automatically create or update tables based on SQLAlchemy models."""
25-
import_module("app.models.user")
26+
27+
for module in (
28+
"app.models.user",
29+
"app.models.project",
30+
"app.models.paper",
31+
"app.models.project_paper",
32+
):
33+
import_module(module)
2634
logger.info("🔄 Creating / updating database schema...")
2735
Base.metadata.create_all(bind=engine)
2836
logger.info("✅ Database schema up to date.")
2937

3038

31-
def get_db():
39+
def get_db() -> Generator[Session, Any, None]:
3240
"""Yield a database session for FastAPI routes."""
3341
db = SESSION_LOCAL()
3442
try:

backend/app/core/security.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def create_access_token(data: Dict[str, Any], expires_delta: Optional[timedelta]
1919

2020
to_encode = data.copy()
2121
expire = datetime.now(timezone.utc) + (
22-
expires_delta or timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
22+
expires_delta or timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
2323
)
2424
to_encode.update({"exp": expire})
2525
return jwt.encode(to_encode, settings.JWT_SECRET_KEY, algorithm=ALGORITHM)
@@ -30,7 +30,7 @@ def create_refresh_token(data: Dict[str, Any], expires_delta: Optional[timedelta
3030

3131
to_encode = data.copy()
3232
expire = datetime.now(timezone.utc) + (
33-
expires_delta or timedelta(days=settings.REFRESH_TOKEN_EXPIRE_DAYS)
33+
expires_delta or timedelta(days=settings.REFRESH_TOKEN_EXPIRE_DAYS)
3434
)
3535
to_encode.update({"exp": expire, "type": "refresh"})
3636
return jwt.encode(to_encode, settings.JWT_SECRET_KEY, algorithm=ALGORITHM)

backend/app/main.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
"""Application entry point for the Inquiro FastAPI service."""
2-
31
import logging
42
from contextlib import asynccontextmanager
3+
from typing import Any, AsyncGenerator
54

65
from fastapi import FastAPI
76
from starlette.middleware.cors import CORSMiddleware
@@ -24,7 +23,7 @@
2423
# Lifespan Event Handlers (Modern FastAPI)
2524
# ---------------------------------------------------------
2625
@asynccontextmanager
27-
async def lifespan(_app: FastAPI):
26+
async def lifespan(_app: FastAPI) -> AsyncGenerator[None, Any]:
2827
"""Initialize and tear down application resources."""
2928

3029
logger.info("🚀 Starting Inquiro API in '%s' mode...", settings.ENVIRONMENT)
@@ -48,7 +47,6 @@ async def lifespan(_app: FastAPI):
4847
lifespan=lifespan,
4948
)
5049

51-
5250
# ---------------------------------------------------------
5351
# Development-only CORS configuration
5452
# ---------------------------------------------------------
@@ -65,7 +63,6 @@ async def lifespan(_app: FastAPI):
6563
allow_headers=["*"],
6664
)
6765

68-
6966
# ---------------------------------------------------------
7067
# Register Routers
7168
# ---------------------------------------------------------

backend/app/models/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""Expose SQLAlchemy models for convenient imports."""
2+
3+
from .paper import Paper, PaperSource, PaperType
4+
from .project import Project
5+
from .project_paper import ProjectPaper
6+
from .user import User
7+
8+
__all__ = [
9+
"Paper",
10+
"PaperSource",
11+
"PaperType",
12+
"Project",
13+
"ProjectPaper",
14+
"User",
15+
]

0 commit comments

Comments
 (0)