Skip to content

Commit e1aa571

Browse files
Split settings into package and refactor
Split the large src/api/settings.py into a settings package (endpoints, models, helpers, langflow_sync) and added src/api/settings/__init__.py to preserve the original public import surface. Renamed the original file to src/api/settings/endpoints.py and moved Pydantic models and Langflow/provider helper logic into dedicated modules. Updated imports and made numerous small formatting/rewrites (wrapping, logging, minor refactors) without behavioral changes. Also updated pyproject.toml to whitelist common FastAPI call-sites for Ruff/Bugbear and add a mypy override for api.settings.endpoints. Minor tweaks to src/api/router.py (spacing and traceback logging) included.
1 parent bfc2378 commit e1aa571

7 files changed

Lines changed: 1129 additions & 846 deletions

File tree

pyproject.toml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,26 @@ target-version = "py313"
9696
select = ["E", "F", "I", "B", "UP"]
9797
ignore = ["E501"] # line-length handled by formatter
9898

99+
# FastAPI's idiomatic dependency-injection pattern uses `Depends(...)` and
100+
# our `require_permission(...)` as call expressions in default-argument
101+
# position. B008 flags these as bugs ("function call in argument default")
102+
# but for FastAPI they are by design — the framework introspects them at
103+
# request time. Whitelist the call sites instead of sprinkling noqa
104+
# comments across every handler.
105+
[tool.ruff.lint.flake8-bugbear]
106+
extend-immutable-calls = [
107+
"fastapi.Depends",
108+
"fastapi.Query",
109+
"fastapi.Path",
110+
"fastapi.Body",
111+
"fastapi.Header",
112+
"fastapi.Cookie",
113+
"fastapi.File",
114+
"fastapi.Form",
115+
"fastapi.Security",
116+
"dependencies.require_permission",
117+
]
118+
99119
# `bootstrap` must be the first import in any module that uses it
100120
# (it loads .env and configures structlog before anything else can
101121
# read env vars or emit logs). Define it as its own isort section
@@ -120,4 +140,14 @@ ignore_missing_imports = true
120140
no_strict_optional = true
121141
warn_unused_ignores = true
122142

143+
# FastAPI handlers in this module declare a Pydantic response model as
144+
# their return type but legitimately return `JSONResponse(...)` on error
145+
# paths. The runtime accepts both, but the annotation can't be widened to
146+
# `SomeResponse | JSONResponse` because FastAPI then tries to derive an
147+
# OpenAPI schema from the union and fails. Suppress only the resulting
148+
# return-value mismatches in this one file.
149+
[[tool.mypy.overrides]]
150+
module = "api.settings.endpoints"
151+
disable_error_code = ["return-value"]
152+
123153

src/api/router.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ async def upload_ingest_router(
5050
logger.debug("Routing to traditional OpenRAG upload")
5151
# Route to traditional upload — just take the first file
5252
from api.upload import upload as traditional_upload_fn
53+
5354
return await traditional_upload_fn(
5455
file=file[0] if file else None,
5556
document_service=document_service,
@@ -154,13 +155,15 @@ async def _langflow_upload_ingest_task(
154155

155156
except Exception:
156157
from utils.file_utils import safe_unlink
158+
157159
for temp_path in temp_file_paths:
158160
safe_unlink(temp_path)
159161
raise
160162

161163
except Exception as e:
162164
logger.error("Task-based langflow upload_ingest failed", error=str(e))
163165
import traceback
166+
164167
logger.error("Full traceback", traceback=traceback.format_exc())
165168
error_msg = str(e)
166169
if "AuthenticationException" in error_msg or "access denied" in error_msg.lower():

src/api/settings/__init__.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
"""Settings/onboarding endpoint package.
2+
3+
The original `src/api/settings.py` (2081 lines) was split into focused
4+
submodules. This `__init__.py` preserves the public-import contract every
5+
external caller relies on:
6+
7+
* `src/app/routes/internal.py` registers each endpoint via
8+
`from api import settings; app.add_api_route(..., settings.<name>, ...)`.
9+
* `src/api/v1/settings.py` imports `SettingsUpdateBody` and (lazily)
10+
`update_settings`.
11+
* `src/services/startup_orchestrator.py` lazily imports
12+
`reapply_all_settings` for flow-reset re-sync.
13+
14+
Adding a new endpoint to this package: define it in `endpoints.py`, then
15+
re-export it here.
16+
"""
17+
18+
from api.settings.endpoints import (
19+
get_settings,
20+
onboarding,
21+
refresh_openrag_docs,
22+
rollback_onboarding,
23+
update_docling_preset,
24+
update_onboarding_state,
25+
update_settings,
26+
)
27+
from api.settings.langflow_sync import reapply_all_settings
28+
from api.settings.models import (
29+
AgentConfig,
30+
AnthropicProviderConfig,
31+
AssistantMessage,
32+
DoclingPresetBody,
33+
DoclingPresetResponse,
34+
IngestionDefaultsConfig,
35+
KnowledgeConfig,
36+
OllamaProviderConfig,
37+
OnboardingBody,
38+
OnboardingResponse,
39+
OnboardingStateBody,
40+
OnboardingStateConfig,
41+
OnboardingStateResponse,
42+
OpenAIProviderConfig,
43+
ProvidersConfig,
44+
RefreshOpenRAGDocsResponse,
45+
RollbackBody,
46+
RollbackResponse,
47+
SettingsResponse,
48+
SettingsUpdateBody,
49+
SettingsUpdateResponse,
50+
WatsonXProviderConfig,
51+
)
52+
53+
__all__ = [
54+
# Endpoints
55+
"get_settings",
56+
"update_settings",
57+
"onboarding",
58+
"update_onboarding_state",
59+
"rollback_onboarding",
60+
"update_docling_preset",
61+
"refresh_openrag_docs",
62+
# Internal orchestrator (called from services/startup_orchestrator.py)
63+
"reapply_all_settings",
64+
# Pydantic models (some are imported externally; re-export all for parity
65+
# with the pre-split flat module's surface)
66+
"SettingsUpdateBody",
67+
"OnboardingBody",
68+
"AssistantMessage",
69+
"OnboardingStateBody",
70+
"DoclingPresetBody",
71+
"OnboardingStateConfig",
72+
"OpenAIProviderConfig",
73+
"AnthropicProviderConfig",
74+
"WatsonXProviderConfig",
75+
"OllamaProviderConfig",
76+
"ProvidersConfig",
77+
"KnowledgeConfig",
78+
"AgentConfig",
79+
"IngestionDefaultsConfig",
80+
"SettingsResponse",
81+
"OnboardingResponse",
82+
"RefreshOpenRAGDocsResponse",
83+
"DoclingPresetResponse",
84+
"OnboardingStateResponse",
85+
"SettingsUpdateResponse",
86+
"RollbackResponse",
87+
"RollbackBody",
88+
]

0 commit comments

Comments
 (0)