refactor: rename the application package to docsgpt

The backend import package is now docsgpt, the name it will carry on PyPI;
application was far too generic to install into anyone's site-packages.
git mv plus a mechanical rewrite of every import, dotted string and path
reference: 734 Python files, the compose files, Dockerfile, workflows, docs,
setup scripts, devcontainer, k8s manifests, vscode config, pytest and coverage
config, .gitignore. Behaviour is unchanged.

Kept for one release:
- A top-level application package whose meta-path finder resolves
  application.x.y to the already-imported docsgpt.x.y object, so old imports
  and entry points (celery -A application.app.celery,
  uvicorn application.asgi:asgi_app) keep working with a FutureWarning.
- Celery registers every application.* task name as an alias of its
  docsgpt.* task on start-up, so messages queued by the previous release still
  run. The redbeat key prefix moves to redbeat:docsgpt:v2: so schedule entries
  the previous release wrote are left unread instead of firing twice.

The backend image builds from the repository root (docker build -f
docsgpt/Dockerfile .) so it can ship the alias package; a root .dockerignore
allow-lists docsgpt/ and application/ and keeps caches, local data, .env
files, the sample index files and the Dockerfile out. Compose and the image
workflows point at the new context.
This commit is contained in:
Alex committed 2026-09-07 10:20:43 +01:00
1 parent 3e7f1f91b4
commit 574f96341e
984 files changed
+9847 -9682

No files matched your search

@@ -9,11 +9,11 @@ from __future__ import annotations
from datetime import datetime, timedelta, timezone
from application.storage.db.repositories.admin_stats import AdminStatsRepository
from application.storage.db.repositories.auth_events import AuthEventsRepository
from application.storage.db.repositories.token_usage import TokenUsageRepository
from application.storage.db.repositories.user_roles import UserRolesRepository
from application.storage.db.repositories.users import UsersRepository
from docsgpt.storage.db.repositories.admin_stats import AdminStatsRepository
from docsgpt.storage.db.repositories.auth_events import AuthEventsRepository
from docsgpt.storage.db.repositories.token_usage import TokenUsageRepository
from docsgpt.storage.db.repositories.user_roles import UserRolesRepository
from docsgpt.storage.db.repositories.users import UsersRepository
class TestOverview:
@@ -3,7 +3,7 @@
from __future__ import annotations
from application.storage.db.repositories.agent_folders import AgentFoldersRepository
from docsgpt.storage.db.repositories.agent_folders import AgentFoldersRepository
def _repo(conn) -> AgentFoldersRepository:
+7 -7
View File
@@ -4,7 +4,7 @@ from __future__ import annotations
import pytest
from application.storage.db.repositories.agents import AgentsRepository
from docsgpt.storage.db.repositories.agents import AgentsRepository
def _repo(conn) -> AgentsRepository:
@@ -183,7 +183,7 @@ class TestPart1bFields:
assert agent["allow_system_prompt_override"] is False
def test_extra_source_ids_round_trip(self, pg_conn):
from application.storage.db.repositories.sources import SourcesRepository
from docsgpt.storage.db.repositories.sources import SourcesRepository
sources = SourcesRepository(pg_conn)
s1 = sources.create("s1", user_id="u")
@@ -199,7 +199,7 @@ class TestPart1bFields:
assert str(agent["source_id"]) == str(s1["id"])
def test_workflow_id_fk(self, pg_conn):
from application.storage.db.repositories.workflows import WorkflowsRepository
from docsgpt.storage.db.repositories.workflows import WorkflowsRepository
wf = WorkflowsRepository(pg_conn).create("u", "wf")
repo = _repo(pg_conn)
@@ -212,7 +212,7 @@ class TestPart1bFields:
def test_workflow_id_set_null_on_workflow_delete(self, pg_conn):
"""ON DELETE SET NULL on agents.workflow_id."""
from application.storage.db.repositories.workflows import WorkflowsRepository
from docsgpt.storage.db.repositories.workflows import WorkflowsRepository
wfr = WorkflowsRepository(pg_conn)
wf = wfr.create("u", "wf")
@@ -339,7 +339,7 @@ class TestDelete:
class TestSetFolder:
def test_assigns_folder(self, pg_conn):
from application.storage.db.repositories.agent_folders import AgentFoldersRepository
from docsgpt.storage.db.repositories.agent_folders import AgentFoldersRepository
folder_repo = AgentFoldersRepository(pg_conn)
folder = folder_repo.create("user-1", "f")
@@ -350,7 +350,7 @@ class TestSetFolder:
assert str(fetched["folder_id"]) == str(folder["id"])
def test_clear_folder(self, pg_conn):
from application.storage.db.repositories.agent_folders import AgentFoldersRepository
from docsgpt.storage.db.repositories.agent_folders import AgentFoldersRepository
folder_repo = AgentFoldersRepository(pg_conn)
folder = folder_repo.create("user-1", "f")
@@ -363,7 +363,7 @@ class TestSetFolder:
class TestClearFolderForAll:
def test_clears_folder_from_all_agents(self, pg_conn):
from application.storage.db.repositories.agent_folders import AgentFoldersRepository
from docsgpt.storage.db.repositories.agent_folders import AgentFoldersRepository
folder_repo = AgentFoldersRepository(pg_conn)
folder = folder_repo.create("user-1", "f")
+11 -11
View File
@@ -8,9 +8,9 @@ import pytest
from sqlalchemy import text
from sqlalchemy.exc import IntegrityError
from application.storage.db.repositories.agents import AgentsRepository
from application.storage.db.repositories.artifacts import ArtifactsRepository
from application.storage.db.repositories.conversations import ConversationsRepository
from docsgpt.storage.db.repositories.agents import AgentsRepository
from docsgpt.storage.db.repositories.artifacts import ArtifactsRepository
from docsgpt.storage.db.repositories.conversations import ConversationsRepository
def _repo(conn) -> ArtifactsRepository:
@@ -366,7 +366,7 @@ class TestQuotaEnforcement:
repo.create_artifact("alice", "document", conversation_id=_conversation_id(), size=size)
def test_under_quota_passes(self, pg_conn, monkeypatch):
from application.sandbox import artifacts_capture as ac
from docsgpt.sandbox import artifacts_capture as ac
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_COUNT_PER_USER", 10, raising=False)
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_TOTAL_BYTES_PER_USER", 10_000, raising=False)
@@ -376,7 +376,7 @@ class TestQuotaEnforcement:
ac._enforce_user_quota(_repo(pg_conn), "alice", 100, new_artifact=True)
def test_over_count_quota_raises(self, pg_conn, monkeypatch):
from application.sandbox import artifacts_capture as ac
from docsgpt.sandbox import artifacts_capture as ac
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_COUNT_PER_USER", 2, raising=False)
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_TOTAL_BYTES_PER_USER", 10_000_000, raising=False)
@@ -386,7 +386,7 @@ class TestQuotaEnforcement:
ac._enforce_user_quota(_repo(pg_conn), "alice", 10, new_artifact=True)
def test_count_quota_ignored_when_appending_version(self, pg_conn, monkeypatch):
from application.sandbox import artifacts_capture as ac
from docsgpt.sandbox import artifacts_capture as ac
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_COUNT_PER_USER", 2, raising=False)
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_TOTAL_BYTES_PER_USER", 10_000_000, raising=False)
@@ -396,7 +396,7 @@ class TestQuotaEnforcement:
ac._enforce_user_quota(_repo(pg_conn), "alice", 10, new_artifact=False)
def test_over_total_bytes_quota_raises(self, pg_conn, monkeypatch):
from application.sandbox import artifacts_capture as ac
from docsgpt.sandbox import artifacts_capture as ac
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_COUNT_PER_USER", 10_000, raising=False)
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_TOTAL_BYTES_PER_USER", 500, raising=False)
@@ -406,7 +406,7 @@ class TestQuotaEnforcement:
ac._enforce_user_quota(_repo(pg_conn), "alice", 100, new_artifact=True) # 450 + 100 > 500
def test_single_artifact_too_large_raises(self, pg_conn, monkeypatch):
from application.sandbox import artifacts_capture as ac
from docsgpt.sandbox import artifacts_capture as ac
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_COUNT_PER_USER", 10_000, raising=False)
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_TOTAL_BYTES_PER_USER", 10_000_000, raising=False)
@@ -415,7 +415,7 @@ class TestQuotaEnforcement:
ac._enforce_user_quota(_repo(pg_conn), "alice", 1001, new_artifact=True)
def test_zero_settings_disable_enforcement(self, pg_conn, monkeypatch):
from application.sandbox import artifacts_capture as ac
from docsgpt.sandbox import artifacts_capture as ac
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_COUNT_PER_USER", 0, raising=False)
monkeypatch.setattr(ac.settings, "ARTIFACT_MAX_TOTAL_BYTES_PER_USER", 0, raising=False)
@@ -574,7 +574,7 @@ class TestStableRefSeq:
repo.resolve_id_by_ref_seq(1)
def test_resolver_resolves_a_n_by_stable_seq_after_delete(self, pg_conn):
from application.agents.tools.artifact_ref import resolve_artifact_id
from docsgpt.agents.tools.artifact_ref import resolve_artifact_id
repo = _repo(pg_conn)
conv = _conversation_id()
@@ -585,7 +585,7 @@ class TestStableRefSeq:
assert resolve_artifact_id(repo, "A2", conversation_id=conv) == b["id"]
def test_legacy_row_without_ref_seq_falls_back_to_position(self, pg_conn):
from application.agents.tools.artifact_ref import resolve_artifact_id
from docsgpt.agents.tools.artifact_ref import resolve_artifact_id
repo = _repo(pg_conn)
conv = _conversation_id()
@@ -3,7 +3,7 @@
from __future__ import annotations
from application.storage.db.repositories.attachments import AttachmentsRepository
from docsgpt.storage.db.repositories.attachments import AttachmentsRepository
def _repo(conn) -> AttachmentsRepository:
@@ -4,19 +4,19 @@
class TestResolveIds:
def test_empty_ids_returns_empty_dict(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
assert AttachmentsRepository(pg_conn).resolve_ids([]) == {}
def test_filters_none_values(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
assert AttachmentsRepository(pg_conn).resolve_ids([None]) == {}
def test_dedupes_ids(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
@@ -28,7 +28,7 @@ class TestResolveIds:
assert got[pk] == pk
def test_legacy_preferred_over_pk(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
@@ -47,7 +47,7 @@ class TestResolveIds:
class TestGetByLegacyId:
def test_returns_none_when_not_found(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
assert (
@@ -56,7 +56,7 @@ class TestGetByLegacyId:
)
def test_with_user_scope(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
repo = AttachmentsRepository(pg_conn)
@@ -71,7 +71,7 @@ class TestGetByLegacyId:
class TestAttachmentsUpdate:
def test_update_no_filtered_fields_returns_false(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
att = AttachmentsRepository(pg_conn).create("u", "f.txt", "/p")
@@ -81,7 +81,7 @@ class TestAttachmentsUpdate:
assert got is False
def test_update_sets_scalar_fields(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
att = AttachmentsRepository(pg_conn).create("u", "f.txt", "/p")
@@ -92,7 +92,7 @@ class TestAttachmentsUpdate:
assert got is True
def test_update_any_with_uuid(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
repo = AttachmentsRepository(pg_conn)
@@ -100,7 +100,7 @@ class TestAttachmentsUpdate:
assert repo.update_any(str(att["id"]), "u", {"openai_file_id": "x"}) is True
def test_update_any_falls_back_to_legacy(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
repo = AttachmentsRepository(pg_conn)
@@ -114,7 +114,7 @@ class TestAttachmentsUpdate:
)
def test_update_by_legacy_id_no_fields(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
repo = AttachmentsRepository(pg_conn)
@@ -123,7 +123,7 @@ class TestAttachmentsUpdate:
assert got is False
def test_update_by_legacy_id_not_found(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
got = AttachmentsRepository(pg_conn).update_by_legacy_id(
@@ -134,7 +134,7 @@ class TestAttachmentsUpdate:
def test_update_by_legacy_id_wrong_user_leaves_row_untouched(self, pg_conn):
"""IDOR regression: a caller with user B's id must not be able to
mutate user A's attachment by guessing/reusing its legacy id."""
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
repo = AttachmentsRepository(pg_conn)
@@ -152,7 +152,7 @@ class TestAttachmentsUpdate:
assert row["openai_file_id"] == "original"
def test_update_by_legacy_id_same_user_succeeds(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
repo = AttachmentsRepository(pg_conn)
@@ -170,7 +170,7 @@ class TestAttachmentsUpdate:
assert row["openai_file_id"] == "updated"
def test_update_by_legacy_id_rejects_none_user(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
repo = AttachmentsRepository(pg_conn)
@@ -200,7 +200,7 @@ class TestAttachmentsShapeGate:
assert conn.execute(_text("SELECT 1")).scalar() == 1
def test_get_any_legacy_shape_txn_survives(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
repo = AttachmentsRepository(pg_conn)
@@ -209,7 +209,7 @@ class TestAttachmentsShapeGate:
self._assert_txn_alive(pg_conn)
def test_update_any_unknown_legacy_id_txn_survives(self, pg_conn):
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
repo = AttachmentsRepository(pg_conn)
@@ -3,7 +3,7 @@
from __future__ import annotations
from application.storage.db.repositories.connector_sessions import ConnectorSessionsRepository
from docsgpt.storage.db.repositories.connector_sessions import ConnectorSessionsRepository
def _repo(conn) -> ConnectorSessionsRepository:
@@ -4,7 +4,7 @@
class TestGetByUserAndProvider:
def test_not_found_returns_none(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
assert (
@@ -15,7 +15,7 @@ class TestGetByUserAndProvider:
)
def test_with_server_url_filter(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -30,7 +30,7 @@ class TestGetByUserAndProvider:
assert str(got["id"]) == str(row["id"])
def test_with_mismatched_server_url(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -46,7 +46,7 @@ class TestGetByUserAndProvider:
class TestGetByUserAndServerUrl:
def test_returns_row(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -59,7 +59,7 @@ class TestGetByUserAndServerUrl:
assert str(got["id"]) == str(row["id"])
def test_not_found(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
got = ConnectorSessionsRepository(pg_conn).get_by_user_and_server_url(
@@ -70,14 +70,14 @@ class TestGetByUserAndServerUrl:
class TestGetByLegacyId:
def test_not_found(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
got = ConnectorSessionsRepository(pg_conn).get_by_legacy_id("x")
assert got is None
def test_with_user_scope(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -96,7 +96,7 @@ class TestMergeSessionData:
``get_by_user_and_server_url`` (``NULL = 'x'`` is UNKNOWN)."""
def test_insert_populates_scalar_server_url(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -117,7 +117,7 @@ class TestMergeSessionData:
"""Legacy callers still embed ``server_url`` in the patch — the
scalar column is authoritative so the key should be discarded
rather than duplicated into the JSONB payload."""
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -133,7 +133,7 @@ class TestMergeSessionData:
assert "server_url" not in (inserted["session_data"] or {})
def test_shallow_merge_preserves_other_keys(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -156,7 +156,7 @@ class TestMergeSessionData:
}
def test_none_valued_keys_are_dropped(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -183,7 +183,7 @@ class TestMergeSessionData:
class TestConnectorSessionsUpdate:
def test_no_filtered_fields_returns_false(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -192,7 +192,7 @@ class TestConnectorSessionsUpdate:
assert got is False
def test_updates_status_and_token(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -204,7 +204,7 @@ class TestConnectorSessionsUpdate:
assert got is True
def test_updates_token_info_jsonb(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -216,7 +216,7 @@ class TestConnectorSessionsUpdate:
assert got is True
def test_update_by_legacy_no_fields(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
got = ConnectorSessionsRepository(pg_conn).update_by_legacy_id(
@@ -225,7 +225,7 @@ class TestConnectorSessionsUpdate:
assert got is False
def test_update_by_legacy_no_match(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
got = ConnectorSessionsRepository(pg_conn).update_by_legacy_id(
@@ -235,7 +235,7 @@ class TestConnectorSessionsUpdate:
assert got is False
def test_update_by_legacy_updates_match(self, pg_conn):
from application.storage.db.repositories.connector_sessions import (
from docsgpt.storage.db.repositories.connector_sessions import (
ConnectorSessionsRepository,
)
repo = ConnectorSessionsRepository(pg_conn)
@@ -7,7 +7,7 @@ from datetime import datetime, timezone
from sqlalchemy import text
from application.storage.db.repositories.conversations import (
from docsgpt.storage.db.repositories.conversations import (
ConversationsRepository,
MessageUpdateOutcome,
)
@@ -32,7 +32,7 @@ class TestCreate:
assert doc["_id"] == doc["id"]
def test_create_with_agent(self, pg_conn):
from application.storage.db.repositories.agents import AgentsRepository
from docsgpt.storage.db.repositories.agents import AgentsRepository
agent_repo = AgentsRepository(pg_conn)
agent = agent_repo.create("user-1", "a", "active")
@@ -440,7 +440,7 @@ class TestResolveAgentRef:
ObjectId-era conversation service doesn't silently lose rows."""
def test_create_translates_objectid_agent_id(self, pg_conn):
from application.storage.db.repositories.agents import AgentsRepository
from docsgpt.storage.db.repositories.agents import AgentsRepository
agent_repo = AgentsRepository(pg_conn)
legacy_oid = "507f1f77bcf86cd799439099"
@@ -452,7 +452,7 @@ class TestResolveAgentRef:
assert str(conv["agent_id"]) == agent["id"]
def test_create_passes_through_uuid_agent_id(self, pg_conn):
from application.storage.db.repositories.agents import AgentsRepository
from docsgpt.storage.db.repositories.agents import AgentsRepository
agent_repo = AgentsRepository(pg_conn)
agent = agent_repo.create("user-1", "a", "active")
@@ -477,7 +477,7 @@ class TestResolveAttachmentRefs:
whole message."""
def _create_attachment(self, pg_conn, legacy: str) -> str:
from application.storage.db.repositories.attachments import (
from docsgpt.storage.db.repositories.attachments import (
AttachmentsRepository,
)
@@ -14,7 +14,7 @@ import uuid
from sqlalchemy import text
from application.storage.db.repositories.idempotency import IdempotencyRepository
from docsgpt.storage.db.repositories.idempotency import IdempotencyRepository
def _repo(conn) -> IdempotencyRepository:
@@ -4,7 +4,7 @@ from __future__ import annotations
from sqlalchemy import text
from application.storage.db.repositories.ingest_chunk_progress import (
from docsgpt.storage.db.repositories.ingest_chunk_progress import (
IngestChunkProgressRepository,
)
@@ -7,7 +7,7 @@ from __future__ import annotations
from sqlalchemy import text
from application.storage.db.repositories.memories import MemoriesRepository
from docsgpt.storage.db.repositories.memories import MemoriesRepository
def _repo(conn) -> MemoriesRepository:
@@ -133,7 +133,7 @@ class TestDefaultToolMemories:
"""Synthetic-id memory writes work; real-tool delete still cascades via trigger."""
def test_synthetic_tool_id_memory_write_succeeds(self, pg_conn):
from application.agents.default_tools import default_tool_id
from docsgpt.agents.default_tools import default_tool_id
repo = _repo(pg_conn)
synthetic_id = default_tool_id("memory")
@@ -143,7 +143,7 @@ class TestDefaultToolMemories:
assert got is not None and got["content"] == "built-in"
def test_built_in_and_explicit_memory_are_separate_stores(self, pg_conn):
from application.agents.default_tools import default_tool_id
from docsgpt.agents.default_tools import default_tool_id
repo = _repo(pg_conn)
synthetic_id = default_tool_id("memory")
@@ -193,7 +193,7 @@ class TestDeleteOrphans:
assert repo.get_by_path("u-live", tool_id, "/keep.txt") is not None
def test_keeps_synthetic_default_tool_memory(self, pg_conn):
from application.agents.default_tools import default_tool_id
from docsgpt.agents.default_tools import default_tool_id
repo = _repo(pg_conn)
synthetic_id = default_tool_id("memory")
@@ -205,7 +205,7 @@ class TestDeleteOrphans:
def test_sweeps_orphan_but_spares_synthetic_and_live(self, pg_conn):
import uuid
from application.agents.default_tools import default_tool_id
from docsgpt.agents.default_tools import default_tool_id
repo = _repo(pg_conn)
synthetic_id = default_tool_id("memory")
@@ -14,7 +14,7 @@ import pytest
from sqlalchemy import text
from sqlalchemy.exc import IntegrityError
from application.storage.db.repositories.message_events import (
from docsgpt.storage.db.repositories.message_events import (
MessageEventsRepository,
)
+1 -1
View File
@@ -7,7 +7,7 @@ from __future__ import annotations
from sqlalchemy import text
from application.storage.db.repositories.notes import NotesRepository
from docsgpt.storage.db.repositories.notes import NotesRepository
def _repo(conn) -> NotesRepository:
@@ -4,8 +4,8 @@ from __future__ import annotations
from sqlalchemy import text
from application.storage.db.repositories.conversations import ConversationsRepository
from application.storage.db.repositories.pending_tool_state import PendingToolStateRepository
from docsgpt.storage.db.repositories.conversations import ConversationsRepository
from docsgpt.storage.db.repositories.pending_tool_state import PendingToolStateRepository
def _conv(conn) -> dict:
@@ -3,7 +3,7 @@
from __future__ import annotations
from application.storage.db.repositories.prompts import PromptsRepository
from docsgpt.storage.db.repositories.prompts import PromptsRepository
def _repo(conn) -> PromptsRepository:
@@ -6,10 +6,10 @@ import json
from sqlalchemy import text
from application.storage.db.repositories.conversations import (
from docsgpt.storage.db.repositories.conversations import (
ConversationsRepository,
)
from application.storage.db.repositories.reconciliation import (
from docsgpt.storage.db.repositories.reconciliation import (
ReconciliationRepository,
)
@@ -13,11 +13,11 @@ import json
from sqlalchemy import text
from application.storage.db.repositories.conversations import (
from docsgpt.storage.db.repositories.conversations import (
ConversationsRepository,
MessageUpdateOutcome,
)
from application.storage.db.repositories.reconciliation import (
from docsgpt.storage.db.repositories.reconciliation import (
ReconciliationRepository,
)
@@ -6,10 +6,10 @@ from datetime import datetime, timedelta, timezone
from sqlalchemy import text
from application.storage.db.repositories.schedule_runs import (
from docsgpt.storage.db.repositories.schedule_runs import (
ScheduleRunsRepository,
)
from application.storage.db.repositories.schedules import SchedulesRepository
from docsgpt.storage.db.repositories.schedules import SchedulesRepository
def _now() -> datetime:
@@ -6,7 +6,7 @@ from datetime import datetime, timedelta, timezone
from sqlalchemy import text
from application.storage.db.repositories.schedules import SchedulesRepository
from docsgpt.storage.db.repositories.schedules import SchedulesRepository
def _insert_agent(conn, user_id: str = "u1") -> str:
@@ -3,8 +3,8 @@
from __future__ import annotations
from application.storage.db.repositories.conversations import ConversationsRepository
from application.storage.db.repositories.shared_conversations import SharedConversationsRepository
from docsgpt.storage.db.repositories.conversations import ConversationsRepository
from docsgpt.storage.db.repositories.shared_conversations import SharedConversationsRepository
def _conv(conn) -> dict:
@@ -3,7 +3,7 @@
from __future__ import annotations
from application.storage.db.repositories.sources import SourcesRepository
from docsgpt.storage.db.repositories.sources import SourcesRepository
def _repo(conn) -> SourcesRepository:
@@ -4,7 +4,7 @@ from __future__ import annotations
from sqlalchemy import text
from application.storage.db.repositories.stack_logs import StackLogsRepository
from docsgpt.storage.db.repositories.stack_logs import StackLogsRepository
def _repo(conn) -> StackLogsRepository:
@@ -8,20 +8,20 @@ from __future__ import annotations
import uuid
from application.api.user.team_sharing import (
from docsgpt.api.user.team_sharing import (
can_access,
effective_write_owner,
owns_resource,
team_access_for,
visible_with_access,
)
from application.storage.db.repositories.team_scope import TeamScopeRepository
from application.storage.db.repositories.agents import AgentsRepository
from application.storage.db.repositories.team_members import TeamMembersRepository
from application.storage.db.repositories.team_resource_grants import (
from docsgpt.storage.db.repositories.team_scope import TeamScopeRepository
from docsgpt.storage.db.repositories.agents import AgentsRepository
from docsgpt.storage.db.repositories.team_members import TeamMembersRepository
from docsgpt.storage.db.repositories.team_resource_grants import (
TeamResourceGrantsRepository,
)
from application.storage.db.repositories.teams import TeamsRepository
from docsgpt.storage.db.repositories.teams import TeamsRepository
def _team(conn, owner="alice"):
@@ -2,9 +2,9 @@
from __future__ import annotations
from application.storage.db.repositories.prompts import PromptsRepository
from application.storage.db.repositories.sources import SourcesRepository
from application.storage.db.repositories.user_tools import UserToolsRepository
from docsgpt.storage.db.repositories.prompts import PromptsRepository
from docsgpt.storage.db.repositories.sources import SourcesRepository
from docsgpt.storage.db.repositories.user_tools import UserToolsRepository
class TestPromptsSharing:
+6 -6
View File
@@ -8,14 +8,14 @@ from __future__ import annotations
import uuid
from application.storage.db.repositories.agents import AgentsRepository
from application.storage.db.repositories.team_members import TeamMembersRepository
from application.storage.db.repositories.team_resource_grants import (
from docsgpt.storage.db.repositories.agents import AgentsRepository
from docsgpt.storage.db.repositories.team_members import TeamMembersRepository
from docsgpt.storage.db.repositories.team_resource_grants import (
TeamResourceGrantsRepository,
)
from application.storage.db.repositories.team_scope import TeamScopeRepository
from application.storage.db.repositories.teams import TeamsRepository
from application.storage.db.repositories.users import UsersRepository
from docsgpt.storage.db.repositories.team_scope import TeamScopeRepository
from docsgpt.storage.db.repositories.teams import TeamsRepository
from docsgpt.storage.db.repositories.users import UsersRepository
def _new_team(conn, name="Acme", slug=None, owner="alice"):
+1 -1
View File
@@ -7,7 +7,7 @@ from __future__ import annotations
from sqlalchemy import text
from application.storage.db.repositories.todos import TodosRepository
from docsgpt.storage.db.repositories.todos import TodosRepository
def _repo(conn) -> TodosRepository:
@@ -7,7 +7,7 @@ from datetime import datetime, timedelta, timezone
import pytest
from sqlalchemy import text
from application.storage.db.repositories.token_usage import TokenUsageRepository
from docsgpt.storage.db.repositories.token_usage import TokenUsageRepository
def _repo(conn) -> TokenUsageRepository:
@@ -4,7 +4,7 @@ from __future__ import annotations
from sqlalchemy import text
from application.storage.db.repositories.tool_call_attempts import (
from docsgpt.storage.db.repositories.tool_call_attempts import (
ToolCallAttemptsRepository,
)
@@ -11,7 +11,7 @@ from __future__ import annotations
from sqlalchemy import text
from application.storage.db.repositories.conversations import (
from docsgpt.storage.db.repositories.conversations import (
ConversationsRepository,
MessageUpdateOutcome,
)
@@ -2,7 +2,7 @@
from __future__ import annotations
from application.storage.db.repositories.user_custom_models import (
from docsgpt.storage.db.repositories.user_custom_models import (
UserCustomModelsRepository,
)
@@ -9,7 +9,7 @@ from __future__ import annotations
from sqlalchemy import text
from application.storage.db.repositories.user_logs import UserLogsRepository
from docsgpt.storage.db.repositories.user_logs import UserLogsRepository
def _rows(conn, user_id):
@@ -2,7 +2,7 @@
from __future__ import annotations
from application.storage.db.repositories.user_roles import UserRolesRepository
from docsgpt.storage.db.repositories.user_roles import UserRolesRepository
def _repo(conn) -> UserRolesRepository:
@@ -4,7 +4,7 @@ from __future__ import annotations
import pytest
from application.storage.db.repositories.user_tools import UserToolsRepository
from docsgpt.storage.db.repositories.user_tools import UserToolsRepository
def _repo(conn) -> UserToolsRepository:
+2 -2
View File
@@ -7,7 +7,7 @@ in the parent conftest) so no data leaks between tests.
from __future__ import annotations
from application.storage.db.repositories.users import UsersRepository
from docsgpt.storage.db.repositories.users import UsersRepository
# ------------------------------------------------------------------
@@ -371,7 +371,7 @@ class TestListPaginated:
assert total >= 2
assert {"page-a", "page-b"} <= {r["user_id"] for r in rows}
sample = next(r for r in rows if r["user_id"] == "page-a")
# the keys application/api/admin/routes.py projects must be real columns
# the keys docsgpt/api/admin/routes.py projects must be real columns
assert "active" in sample and "created_at" in sample
def test_first_positional_arg_is_the_filter(self, pg_conn):
@@ -8,8 +8,8 @@ from __future__ import annotations
import pytest
from application.storage.db.repositories.sources import SourcesRepository
from application.storage.db.repositories.wiki_pages import (
from docsgpt.storage.db.repositories.sources import SourcesRepository
from docsgpt.storage.db.repositories.wiki_pages import (
WikiPageConflict,
WikiPagesRepository,
build_wiki_directory_structure,
@@ -3,9 +3,9 @@
from __future__ import annotations
from application.storage.db.repositories.workflows import WorkflowsRepository
from application.storage.db.repositories.workflow_nodes import WorkflowNodesRepository
from application.storage.db.repositories.workflow_edges import WorkflowEdgesRepository
from docsgpt.storage.db.repositories.workflows import WorkflowsRepository
from docsgpt.storage.db.repositories.workflow_nodes import WorkflowNodesRepository
from docsgpt.storage.db.repositories.workflow_edges import WorkflowEdgesRepository
def _setup(conn) -> tuple[dict, dict, dict]:
@@ -3,8 +3,8 @@
from __future__ import annotations
from application.storage.db.repositories.workflows import WorkflowsRepository
from application.storage.db.repositories.workflow_nodes import WorkflowNodesRepository
from docsgpt.storage.db.repositories.workflows import WorkflowsRepository
from docsgpt.storage.db.repositories.workflow_nodes import WorkflowNodesRepository
def _wf(conn) -> dict:
@@ -5,8 +5,8 @@ from __future__ import annotations
from datetime import datetime, timedelta, timezone
from application.storage.db.repositories.workflows import WorkflowsRepository
from application.storage.db.repositories.workflow_runs import WorkflowRunsRepository
from docsgpt.storage.db.repositories.workflows import WorkflowsRepository
from docsgpt.storage.db.repositories.workflow_runs import WorkflowRunsRepository
def _wf(conn) -> dict:
@@ -3,7 +3,7 @@
from __future__ import annotations
from application.storage.db.repositories.workflows import WorkflowsRepository
from docsgpt.storage.db.repositories.workflows import WorkflowsRepository
def _repo(conn) -> WorkflowsRepository:
@@ -113,9 +113,9 @@ class TestDelete:
def test_delete_reaps_run_artifacts(self, pg_conn, monkeypatch):
# Run artifacts have no FK cascade off the workflow, so deleting the
# workflow must explicitly reclaim their rows (quota) and bytes.
from application.storage.db.repositories.artifacts import ArtifactsRepository
from application.storage.db.repositories.workflow_runs import WorkflowRunsRepository
from application.storage.storage_creator import StorageCreator
from docsgpt.storage.db.repositories.artifacts import ArtifactsRepository
from docsgpt.storage.db.repositories.workflow_runs import WorkflowRunsRepository
from docsgpt.storage.storage_creator import StorageCreator
deleted_paths: list[str] = []
@@ -148,8 +148,8 @@ class TestDelete:
def test_delete_wrong_user_keeps_run_artifacts(self, pg_conn):
# The ownership guard must run before any artifact cleanup, so a
# non-owner delete can never reap another user's run artifacts.
from application.storage.db.repositories.artifacts import ArtifactsRepository
from application.storage.db.repositories.workflow_runs import WorkflowRunsRepository
from docsgpt.storage.db.repositories.artifacts import ArtifactsRepository
from docsgpt.storage.db.repositories.workflow_runs import WorkflowRunsRepository
repo = _repo(pg_conn)
artifacts = ArtifactsRepository(pg_conn)
@@ -3,7 +3,7 @@
class TestWorkflowsDeleteByLegacy:
def test_delete_by_legacy_id_returns_true(self, pg_conn):
from application.storage.db.repositories.workflows import (
from docsgpt.storage.db.repositories.workflows import (
WorkflowsRepository,
)
repo = WorkflowsRepository(pg_conn)
@@ -14,7 +14,7 @@ class TestWorkflowsDeleteByLegacy:
assert got is True
def test_delete_by_legacy_id_no_match(self, pg_conn):
from application.storage.db.repositories.workflows import (
from docsgpt.storage.db.repositories.workflows import (
WorkflowsRepository,
)
got = WorkflowsRepository(pg_conn).delete_by_legacy_id(
@@ -23,7 +23,7 @@ class TestWorkflowsDeleteByLegacy:
assert got is False
def test_delete_by_legacy_id_wrong_user(self, pg_conn):
from application.storage.db.repositories.workflows import (
from docsgpt.storage.db.repositories.workflows import (
WorkflowsRepository,
)
repo = WorkflowsRepository(pg_conn)
@@ -14,15 +14,15 @@ from unittest.mock import MagicMock, patch
import pytest
from application.storage.db.bootstrap import ensure_vector_schema
from docsgpt.storage.db.bootstrap import ensure_vector_schema
_APP_PY = Path(__file__).resolve().parents[3] / "application" / "app.py"
_APP_PY = Path(__file__).resolve().parents[3] / "docsgpt" / "app.py"
@pytest.fixture
def vector_settings(monkeypatch):
"""Settings configured for a pgvector deployment."""
from application.core import settings as settings_module
from docsgpt.core import settings as settings_module
settings = settings_module.settings
monkeypatch.setattr(settings, "VECTOR_STORE", "pgvector", raising=False)
@@ -74,17 +74,17 @@ class TestEnsureVectorSchemaCreates:
cursor = MagicMock()
conn.cursor.return_value = cursor
with patch("psycopg.connect", return_value=conn) as connect, patch(
"application.vectorstore.model_registry.dimension_for",
"docsgpt.vectorstore.model_registry.dimension_for",
return_value=dimension,
), patch(
"application.vectorstore.pgvector.PGVectorStore.create_schema"
"docsgpt.vectorstore.pgvector.PGVectorStore.create_schema"
) as vector_schema, patch(
"application.vectorstore.pgvector.PGVectorStore.table_dimension",
"docsgpt.vectorstore.pgvector.PGVectorStore.table_dimension",
return_value=table_dimension,
), patch(
"application.graphrag.store.GraphStore.create_schema"
"docsgpt.graphrag.store.GraphStore.create_schema"
) as graph_schema, patch(
"application.vectorstore.pgvector._pool_for"
"docsgpt.vectorstore.pgvector._pool_for"
) as pool_for:
ensure_vector_schema()
return connect, conn, cursor, vector_schema, graph_schema, pool_for
@@ -130,10 +130,10 @@ class TestEnsureVectorSchemaDimensionCheck:
):
conn = MagicMock()
with patch("psycopg.connect", return_value=conn), patch(
"application.vectorstore.model_registry.dimension_for",
"docsgpt.vectorstore.model_registry.dimension_for",
return_value=1536,
), patch("application.vectorstore.pgvector.PGVectorStore.create_schema"), patch(
"application.vectorstore.pgvector.PGVectorStore.table_dimension",
), patch("docsgpt.vectorstore.pgvector.PGVectorStore.create_schema"), patch(
"docsgpt.vectorstore.pgvector.PGVectorStore.table_dimension",
return_value=768,
):
with pytest.raises(RuntimeError) as excinfo:
@@ -151,11 +151,11 @@ class TestEnsureVectorSchemaDimensionCheck:
stub = MagicMock()
del stub.dimension
with patch("psycopg.connect", return_value=conn), patch(
"application.vectorstore.base.get_embeddings", return_value=stub
"docsgpt.vectorstore.base.get_embeddings", return_value=stub
), patch(
"application.vectorstore.pgvector.PGVectorStore.create_schema"
"docsgpt.vectorstore.pgvector.PGVectorStore.create_schema"
) as vector_schema, patch(
"application.vectorstore.pgvector.PGVectorStore.table_dimension",
"docsgpt.vectorstore.pgvector.PGVectorStore.table_dimension",
return_value=1536,
):
ensure_vector_schema() # must not raise
@@ -165,12 +165,12 @@ class TestEnsureVectorSchemaDimensionCheck:
def test_skips_the_check_when_the_model_cannot_be_loaded(self, vector_settings):
conn = MagicMock()
with patch("psycopg.connect", return_value=conn), patch(
"application.vectorstore.base.get_embeddings",
"docsgpt.vectorstore.base.get_embeddings",
side_effect=RuntimeError("no model"),
), patch(
"application.vectorstore.pgvector.PGVectorStore.create_schema"
"docsgpt.vectorstore.pgvector.PGVectorStore.create_schema"
) as vector_schema, patch(
"application.vectorstore.pgvector.PGVectorStore.table_dimension",
"docsgpt.vectorstore.pgvector.PGVectorStore.table_dimension",
return_value=1536,
):
ensure_vector_schema() # must not raise
@@ -182,7 +182,7 @@ class TestEnsureVectorSchemaDimensionCheck:
class TestBootGating:
"""The boot hook must stay behind AUTO_VECTOR_SCHEMA.
Asserted on the source because importing ``application.app`` runs the hook,
Asserted on the source because importing ``docsgpt.app`` runs the hook,
and a test that imports it cannot observe the gate it just executed.
"""
@@ -216,7 +216,7 @@ class TestBootGating:
), "ensure_vector_schema() at import time must be wrapped in try/except"
def test_setting_defaults_on(self):
from application.core.settings import Settings
from docsgpt.core.settings import Settings
assert Settings.model_fields["AUTO_VECTOR_SCHEMA"].default is True
@@ -241,14 +241,14 @@ class TestBootDoesNotLoadTheModel:
conn = MagicMock()
conn.cursor.return_value = MagicMock()
with patch("psycopg.connect", return_value=conn), patch(
"application.vectorstore.model_registry.dimension_for",
"docsgpt.vectorstore.model_registry.dimension_for",
return_value=registry_dim,
), patch(
"application.vectorstore.base.build_local_embeddings", loader
"docsgpt.vectorstore.base.build_local_embeddings", loader
), patch(
"application.vectorstore.pgvector.PGVectorStore.create_schema"
"docsgpt.vectorstore.pgvector.PGVectorStore.create_schema"
) as vector_schema, patch(
"application.vectorstore.pgvector.PGVectorStore.table_dimension",
"docsgpt.vectorstore.pgvector.PGVectorStore.table_dimension",
return_value=None,
):
ensure_vector_schema()
@@ -280,13 +280,13 @@ class TestUnknownWidthIsProbed:
conn = MagicMock()
conn.cursor.return_value = MagicMock()
with patch("psycopg.connect", return_value=conn), patch(
"application.vectorstore.model_registry.dimension_for", return_value=None
"docsgpt.vectorstore.model_registry.dimension_for", return_value=None
), patch(
"application.vectorstore.base.build_local_embeddings", return_value=remote
"docsgpt.vectorstore.base.build_local_embeddings", return_value=remote
), patch(
"application.vectorstore.pgvector.PGVectorStore.create_schema"
"docsgpt.vectorstore.pgvector.PGVectorStore.create_schema"
) as vector_schema, patch(
"application.vectorstore.pgvector.PGVectorStore.table_dimension",
"docsgpt.vectorstore.pgvector.PGVectorStore.table_dimension",
return_value=table_dimension,
):
try:
@@ -340,7 +340,7 @@ class TestBootLoadedModelIsReleased:
"""
def _run(self, vector_settings, *, delegate, base_url=None):
from application.vectorstore.base import EmbeddingsSingleton
from docsgpt.vectorstore.base import EmbeddingsSingleton
monkeyed = _embeddings(1024)
conn = MagicMock()
@@ -356,13 +356,13 @@ class TestBootLoadedModelIsReleased:
), patch.object(
vector_settings, "EMBEDDINGS_BASE_URL", base_url
), patch("psycopg.connect", return_value=conn), patch(
"application.vectorstore.model_registry.dimension_for", return_value=None
"docsgpt.vectorstore.model_registry.dimension_for", return_value=None
), patch(
"application.vectorstore.base.build_local_embeddings", side_effect=_build
"docsgpt.vectorstore.base.build_local_embeddings", side_effect=_build
), patch(
"application.vectorstore.pgvector.PGVectorStore.create_schema"
"docsgpt.vectorstore.pgvector.PGVectorStore.create_schema"
) as vector_schema, patch(
"application.vectorstore.pgvector.PGVectorStore.table_dimension",
"docsgpt.vectorstore.pgvector.PGVectorStore.table_dimension",
return_value=1024,
):
ensure_vector_schema()
+5 -5
View File
@@ -4,13 +4,13 @@ from unittest.mock import MagicMock, patch
import pytest
from application.storage.db import embeddings_pin
from application.storage.db.embeddings_pin import (
from docsgpt.storage.db import embeddings_pin
from docsgpt.storage.db.embeddings_pin import (
NOTICE_KEY,
PIN_KEY,
resolve_embeddings_pin,
)
from application.vectorstore.model_registry import DEFAULT_LEGACY, DEFAULT_NEW_INSTALL
from docsgpt.vectorstore.model_registry import DEFAULT_LEGACY, DEFAULT_NEW_INSTALL
@pytest.fixture
@@ -62,7 +62,7 @@ class TestExistingInstall:
def test_the_notice_names_the_migration_command(self, store, capsys):
_run(store, has_sources=True)
out = capsys.readouterr().out
assert "application.scripts.reembed" in out
assert "docsgpt.scripts.reembed" in out
assert DEFAULT_NEW_INSTALL in out
def test_the_notice_is_shown_only_once(self, store, capsys):
@@ -112,7 +112,7 @@ class TestSourceModelMismatch:
self._run([(DEFAULT_LEGACY, 28)], DEFAULT_NEW_INSTALL, log)
message = log.warning.call_args.args[0] % log.warning.call_args.args[1:]
assert "28 built with" in message
assert "application.scripts.reembed" in message
assert "docsgpt.scripts.reembed" in message
def test_an_alias_is_not_a_mismatch(self):
"""A stored alias and the canonical name are the same model."""
+2 -2
View File
@@ -15,7 +15,7 @@ pytestmark = pytest.mark.integration
def _alembic_ini() -> Path:
return Path(__file__).resolve().parents[3] / "application" / "alembic.ini"
return Path(__file__).resolve().parents[3] / "docsgpt" / "alembic.ini"
def _run_alembic(url: str, *args: str) -> None:
@@ -123,7 +123,7 @@ class TestMigration0009RoundTrip:
def test_downgrade_purges_synthetic_id_memory_rows(self, pg_engine):
"""Downgrade DELETEs synthetic-id memory rows so the FK can be restored."""
from application.agents.default_tools import default_tool_id
from docsgpt.agents.default_tools import default_tool_id
url = pg_engine.url.render_as_string(hide_password=False)
# Land on 0009 so synthetic-id rows are insertable (no FK yet).
+1 -1
View File
@@ -15,7 +15,7 @@ pytestmark = pytest.mark.integration
def _alembic_ini() -> Path:
return Path(__file__).resolve().parents[3] / "application" / "alembic.ini"
return Path(__file__).resolve().parents[3] / "docsgpt" / "alembic.ini"
def _run_alembic(url: str, *args: str) -> None:
+1 -1
View File
@@ -15,7 +15,7 @@ pytestmark = pytest.mark.integration
def _alembic_ini() -> Path:
return Path(__file__).resolve().parents[3] / "application" / "alembic.ini"
return Path(__file__).resolve().parents[3] / "docsgpt" / "alembic.ini"
def _run_alembic(url: str, *args: str) -> None:
+1 -1
View File
@@ -15,7 +15,7 @@ pytestmark = pytest.mark.integration
def _alembic_ini() -> Path:
return Path(__file__).resolve().parents[3] / "application" / "alembic.ini"
return Path(__file__).resolve().parents[3] / "docsgpt" / "alembic.ini"
def _run_alembic(url: str, *args: str) -> None:
+1 -1
View File
@@ -15,7 +15,7 @@ pytestmark = pytest.mark.integration
def _alembic_ini() -> Path:
return Path(__file__).resolve().parents[3] / "application" / "alembic.ini"
return Path(__file__).resolve().parents[3] / "docsgpt" / "alembic.ini"
def _run_alembic(url: str, *args: str) -> None:
+1 -1
View File
@@ -15,7 +15,7 @@ pytestmark = pytest.mark.integration
def _alembic_ini() -> Path:
return Path(__file__).resolve().parents[3] / "application" / "alembic.ini"
return Path(__file__).resolve().parents[3] / "docsgpt" / "alembic.ini"
def _run_alembic(url: str, *args: str) -> None:
+13 -13
View File
@@ -18,7 +18,7 @@ _0029 = "0029_agent_guardrails"
def _alembic_ini() -> Path:
return Path(__file__).resolve().parents[3] / "application" / "alembic.ini"
return Path(__file__).resolve().parents[3] / "docsgpt" / "alembic.ini"
def _run_alembic(url: str, *args: str) -> None:
@@ -88,7 +88,7 @@ class TestMigration0029RoundTrip:
def test_existing_agents_default_to_empty_config(self, pg_engine):
"""The server default must backfill, so old agents parse as disabled."""
from application.guardrails.config import AgentConfig
from docsgpt.guardrails.config import AgentConfig
with pg_engine.begin() as conn:
conn.execute(
@@ -158,7 +158,7 @@ class TestMigration0029RoundTrip:
class TestAgentConfigPersistence:
def test_config_round_trips_through_the_repository(self, pg_engine):
from application.storage.db.repositories.agents import AgentsRepository
from docsgpt.storage.db.repositories.agents import AgentsRepository
config = {
"guardrails": {
@@ -188,8 +188,8 @@ class TestAgentConfigPersistence:
assert reread["config"] == {"guardrails": {}}
def test_config_survives_a_parse_round_trip(self, pg_engine):
from application.guardrails.config import AgentConfig
from application.storage.db.repositories.agents import AgentsRepository
from docsgpt.guardrails.config import AgentConfig
from docsgpt.storage.db.repositories.agents import AgentsRepository
raw = AgentConfig.model_validate(
{
@@ -211,10 +211,10 @@ class TestAgentConfigPersistence:
class TestGuardrailEventsRepository:
def test_record_and_read_back(self, pg_engine):
from application.storage.db.repositories.guardrail_events import (
from docsgpt.storage.db.repositories.guardrail_events import (
GuardrailEventsRepository,
)
from application.storage.db.repositories.agents import AgentsRepository
from docsgpt.storage.db.repositories.agents import AgentsRepository
with pg_engine.begin() as conn:
agent = AgentsRepository(conn).create("u-ev", "a", "published")
@@ -256,7 +256,7 @@ class TestGuardrailEventsRepository:
assert summary["totals"]["flagged"] == 0
def test_empty_batch_is_a_noop(self, pg_engine):
from application.storage.db.repositories.guardrail_events import (
from docsgpt.storage.db.repositories.guardrail_events import (
GuardrailEventsRepository,
)
@@ -264,8 +264,8 @@ class TestGuardrailEventsRepository:
assert GuardrailEventsRepository(conn).record_many([]) == 0
def test_events_are_scoped_to_the_requesting_user(self, pg_engine):
from application.storage.db.repositories.agents import AgentsRepository
from application.storage.db.repositories.guardrail_events import (
from docsgpt.storage.db.repositories.agents import AgentsRepository
from docsgpt.storage.db.repositories.guardrail_events import (
GuardrailEventsRepository,
)
@@ -290,8 +290,8 @@ class TestGuardrailEventsRepository:
def test_listing_never_exposes_the_key_or_scanned_text(self, pg_engine):
"""``api_key`` is the agent's raw key and ``matched_value`` is raw PII."""
from application.storage.db.repositories.agents import AgentsRepository
from application.storage.db.repositories.guardrail_events import (
from docsgpt.storage.db.repositories.agents import AgentsRepository
from docsgpt.storage.db.repositories.guardrail_events import (
GuardrailEventsRepository,
)
@@ -314,7 +314,7 @@ class TestGuardrailEventsRepository:
assert "ada@example.com" not in str(rows[0])
def test_purge_respects_the_window(self, pg_engine):
from application.storage.db.repositories.guardrail_events import (
from docsgpt.storage.db.repositories.guardrail_events import (
GuardrailEventsRepository,
)
+1 -1
View File
@@ -15,7 +15,7 @@ pytestmark = pytest.mark.integration
def _alembic_ini() -> Path:
return Path(__file__).resolve().parents[3] / "application" / "alembic.ini"
return Path(__file__).resolve().parents[3] / "docsgpt" / "alembic.ini"
def _run_alembic(url: str, *args: str) -> None:
+2 -2
View File
@@ -7,7 +7,7 @@ from uuid import UUID, uuid4
import pytest
from application.storage.db.serialization import (
from docsgpt.storage.db.serialization import (
PGNativeJSONEncoder,
coerce_pg_native,
decode_base64_bytes,
@@ -132,7 +132,7 @@ class TestPGNativeJSONEncoder:
class TestDecodeBase64Bytes:
def test_roundtrip(self):
b = b"\x00\x10\x20\xff"
from application.storage.db.serialization import _coerce_scalar
from docsgpt.storage.db.serialization import _coerce_scalar
encoded = _coerce_scalar(b)
assert decode_base64_bytes(encoded) == b
+4 -4
View File
@@ -1,4 +1,4 @@
"""Guardrail tests for :mod:`application.storage.db.session`.
"""Guardrail tests for :mod:`docsgpt.storage.db.session`.
Two invariants are covered here:
@@ -19,9 +19,9 @@ import pytest
from sqlalchemy import text
from sqlalchemy.exc import DBAPIError, InternalError, OperationalError
from application.storage.db import engine as engine_module
from application.storage.db.engine import STATEMENT_TIMEOUT_MS
from application.storage.db.session import db_readonly, db_session
from docsgpt.storage.db import engine as engine_module
from docsgpt.storage.db.engine import STATEMENT_TIMEOUT_MS
from docsgpt.storage.db.session import db_readonly, db_session
# ---------------------------------------------------------------------------
+1 -1
View File
@@ -5,7 +5,7 @@ from __future__ import annotations
import pytest
from pydantic import ValidationError
from application.storage.db.source_config import (
from docsgpt.storage.db.source_config import (
ChunkingConfig,
GraphConfig,
PreScreenConfig,
+1 -1
View File
@@ -3,7 +3,7 @@ import os
from unittest.mock import MagicMock, mock_open, patch
import pytest
from application.storage.local import LocalStorage
from docsgpt.storage.local import LocalStorage
@pytest.fixture
+6 -6
View File
@@ -5,7 +5,7 @@ from unittest.mock import MagicMock, patch
import pytest
from application.storage.s3 import S3Storage
from docsgpt.storage.s3 import S3Storage
from botocore.exceptions import ClientError
@@ -45,7 +45,7 @@ class TestS3StorageInitialization:
def test_init_creates_boto3_client_with_s3_credentials(self):
"""Should create boto3 S3 client with dedicated S3_* credentials."""
with patch("boto3.client") as mock_client, patch(
"application.storage.s3.settings"
"docsgpt.storage.s3.settings"
) as mock_settings:
mock_settings.S3_BUCKET_NAME = "docsgpt-test-bucket"
@@ -71,8 +71,8 @@ class TestS3StorageInitialization:
def test_init_falls_back_to_sagemaker_credentials(self):
"""Should fall back to deprecated SAGEMAKER_* credentials when S3_* unset."""
with patch("boto3.client") as mock_client, patch(
"application.storage.s3.settings"
) as mock_settings, patch("application.storage.s3.logger") as mock_logger:
"docsgpt.storage.s3.settings"
) as mock_settings, patch("docsgpt.storage.s3.logger") as mock_logger:
mock_settings.S3_BUCKET_NAME = "docsgpt-test-bucket"
mock_settings.S3_ACCESS_KEY_ID = None
@@ -98,7 +98,7 @@ class TestS3StorageInitialization:
def test_init_with_custom_endpoint_and_path_style(self):
"""Should pass endpoint_url and path-style config for S3-compatible services."""
with patch("boto3.client") as mock_client, patch(
"application.storage.s3.settings"
"docsgpt.storage.s3.settings"
) as mock_settings:
mock_settings.S3_BUCKET_NAME = "my-bucket"
@@ -149,7 +149,7 @@ class TestS3StorageSaveFile:
file_data = io.BytesIO(b"test content")
path = "documents/test.txt"
with patch("application.storage.s3.settings") as mock_settings:
with patch("docsgpt.storage.s3.settings") as mock_settings:
mock_settings.SAGEMAKER_REGION = "us-east-1"
s3_storage.save_file(file_data, path, storage_class="STANDARD")
mock_boto3_client.upload_fileobj.assert_called_once_with(