Skip to content

Commit d3d5372

Browse files
deduplicate code in src/server/routers/ingest.py
1 parent 2a329bd commit d3d5372

File tree

3 files changed

+79
-109
lines changed

3 files changed

+79
-109
lines changed

src/server/routers/ingest.py

Lines changed: 24 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,18 @@
44
from fastapi.responses import FileResponse, JSONResponse
55

66
from gitingest.config import TMP_BASE_PATH
7-
from server.models import IngestErrorResponse, IngestRequest, IngestSuccessResponse
8-
from server.query_processor import process_query
7+
from server.models import IngestRequest
8+
from server.routers_uitls import COMMON_INGEST_RESPONSES, _perform_ingestion
99
from server.server_config import MAX_DISPLAY_SIZE
1010
from server.server_utils import limiter
1111

1212
router = APIRouter()
1313

1414

15-
@router.post(
16-
"/api/ingest",
17-
responses={
18-
status.HTTP_200_OK: {"model": IngestSuccessResponse, "description": "Successful ingestion"},
19-
status.HTTP_400_BAD_REQUEST: {"model": IngestErrorResponse, "description": "Bad request or processing error"},
20-
status.HTTP_500_INTERNAL_SERVER_ERROR: {"model": IngestErrorResponse, "description": "Internal server error"},
21-
},
22-
)
15+
@router.post("/api/ingest", responses=COMMON_INGEST_RESPONSES)
2316
@limiter.limit("10/minute")
2417
async def api_ingest(
25-
request: Request, # noqa: ARG001
18+
request: Request, # noqa: ARG001 (unused-function-argument) # pylint: disable=unused-argument
2619
ingest_request: IngestRequest,
2720
) -> JSONResponse:
2821
"""Ingest a Git repository and return processed content.
@@ -39,61 +32,20 @@ async def api_ingest(
3932
4033
- **JSONResponse**: Success response with ingestion results or error response with appropriate HTTP status code
4134
42-
""" # pylint: disable=unused-argument
43-
try:
44-
result = await process_query(
45-
input_text=ingest_request.input_text,
46-
slider_position=ingest_request.max_file_size,
47-
pattern_type=ingest_request.pattern_type,
48-
pattern=ingest_request.pattern,
49-
token=ingest_request.token,
50-
)
51-
52-
if isinstance(result, IngestErrorResponse):
53-
# Return structured error response with 400 status code
54-
return JSONResponse(
55-
status_code=status.HTTP_400_BAD_REQUEST,
56-
content=result.model_dump(),
57-
)
58-
59-
# Return structured success response with 200 status code
60-
return JSONResponse(
61-
status_code=status.HTTP_200_OK,
62-
content=result.model_dump(),
63-
)
64-
65-
except ValueError as ve:
66-
# Handle validation errors with 400 status code
67-
error_response = IngestErrorResponse(
68-
error=f"Validation error: {ve!s}",
69-
)
70-
return JSONResponse(
71-
status_code=status.HTTP_400_BAD_REQUEST,
72-
content=error_response.model_dump(),
73-
)
74-
75-
except Exception as exc:
76-
# Handle unexpected errors with 500 status code
77-
error_response = IngestErrorResponse(
78-
error=f"Internal server error: {exc!s}",
79-
)
80-
return JSONResponse(
81-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
82-
content=error_response.model_dump(),
83-
)
84-
85-
86-
@router.get(
87-
"/api/{user}/{repository}",
88-
responses={
89-
status.HTTP_200_OK: {"model": IngestSuccessResponse, "description": "Successful ingestion"},
90-
status.HTTP_400_BAD_REQUEST: {"model": IngestErrorResponse, "description": "Bad request or processing error"},
91-
status.HTTP_500_INTERNAL_SERVER_ERROR: {"model": IngestErrorResponse, "description": "Internal server error"},
92-
},
93-
)
35+
"""
36+
return await _perform_ingestion(
37+
input_text=ingest_request.input_text,
38+
max_file_size=ingest_request.max_file_size,
39+
pattern_type=ingest_request.pattern_type,
40+
pattern=ingest_request.pattern,
41+
token=ingest_request.token,
42+
)
43+
44+
45+
@router.get("/api/{user}/{repository}", responses=COMMON_INGEST_RESPONSES)
9446
@limiter.limit("10/minute")
9547
async def api_ingest_get(
96-
request: Request, # noqa: ARG001
48+
request: Request, # noqa: ARG001 (unused-function-argument) # pylint: disable=unused-argument
9749
user: str,
9850
repository: str,
9951
max_file_size: int = MAX_DISPLAY_SIZE,
@@ -119,45 +71,14 @@ async def api_ingest_get(
11971
12072
**Returns**
12173
- **JSONResponse**: Success response with ingestion results or error response with appropriate HTTP status code
122-
""" # pylint: disable=unused-argument
123-
try:
124-
effective_input_text = f"{user}/{repository}"
125-
result = await process_query(
126-
input_text=effective_input_text,
127-
slider_position=max_file_size,
128-
pattern_type=pattern_type,
129-
pattern=pattern,
130-
token=token or None,
131-
)
132-
133-
if isinstance(result, IngestErrorResponse):
134-
return JSONResponse(
135-
status_code=status.HTTP_400_BAD_REQUEST,
136-
content=result.model_dump(),
137-
)
138-
139-
return JSONResponse(
140-
status_code=status.HTTP_200_OK,
141-
content=result.model_dump(),
142-
)
143-
144-
except ValueError as ve:
145-
error_response = IngestErrorResponse(
146-
error=f"Validation error: {ve!s}",
147-
)
148-
return JSONResponse(
149-
status_code=status.HTTP_400_BAD_REQUEST,
150-
content=error_response.model_dump(),
151-
)
152-
153-
except Exception as exc:
154-
error_response = IngestErrorResponse(
155-
error=f"Internal server error: {exc!s}",
156-
)
157-
return JSONResponse(
158-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
159-
content=error_response.model_dump(),
160-
)
74+
"""
75+
return await _perform_ingestion(
76+
input_text=f"{user}/{repository}",
77+
max_file_size=max_file_size,
78+
pattern_type=pattern_type,
79+
pattern=pattern,
80+
token=token or None,
81+
)
16182

16283

16384
@router.get("/api/download/file/{ingest_id}", response_class=FileResponse)

src/server/routers_uitls.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""Utility functions for the ingest endpoints."""
2+
3+
from __future__ import annotations
4+
5+
from typing import Any
6+
7+
from fastapi import status
8+
from fastapi.responses import JSONResponse
9+
10+
from server.models import IngestErrorResponse, IngestSuccessResponse
11+
from server.query_processor import process_query
12+
13+
COMMON_INGEST_RESPONSES: dict[int | str, dict[str, Any]] = {
14+
status.HTTP_200_OK: {"model": IngestSuccessResponse, "description": "Successful ingestion"},
15+
status.HTTP_400_BAD_REQUEST: {"model": IngestErrorResponse, "description": "Bad request or processing error"},
16+
status.HTTP_500_INTERNAL_SERVER_ERROR: {"model": IngestErrorResponse, "description": "Internal server error"},
17+
}
18+
19+
20+
async def _perform_ingestion(
21+
input_text: str,
22+
max_file_size: int,
23+
pattern_type: str,
24+
pattern: str,
25+
token: str | None,
26+
) -> JSONResponse:
27+
"""Run ``process_query`` and wrap the result in a ``FastAPI`` ``JSONResponse``.
28+
29+
Consolidates error handling shared by the ``POST`` and ``GET`` ingest endpoints.
30+
"""
31+
try:
32+
result = await process_query(
33+
input_text=input_text,
34+
slider_position=max_file_size,
35+
pattern_type=pattern_type,
36+
pattern=pattern,
37+
token=token,
38+
)
39+
40+
if isinstance(result, IngestErrorResponse):
41+
# Return structured error response with 400 status code
42+
return JSONResponse(status_code=status.HTTP_400_BAD_REQUEST, content=result.model_dump())
43+
44+
# Return structured success response with 200 status code
45+
return JSONResponse(status_code=status.HTTP_200_OK, content=result.model_dump())
46+
47+
except ValueError as ve:
48+
# Handle validation errors with 400 status code
49+
error_response = IngestErrorResponse(error=f"Validation error: {ve!s}")
50+
return JSONResponse(status_code=status.HTTP_400_BAD_REQUEST, content=error_response.model_dump())
51+
52+
except Exception as exc:
53+
# Handle unexpected errors with 500 status code
54+
error_response = IngestErrorResponse(error=f"Internal server error: {exc!s}")
55+
return JSONResponse(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content=error_response.model_dump())

0 commit comments

Comments
 (0)