mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-15 02:16:08 +00:00
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:
1 parent
3e7f1f91b4
commit
574f96341e
984 files changed
+9847
-9682
No files matched your search
+38
-38
@@ -15,9 +15,9 @@ def _patch_base_db(conn):
|
||||
yield conn
|
||||
|
||||
with patch(
|
||||
"application.api.user.base.db_session", _yield
|
||||
"docsgpt.api.user.base.db_session", _yield
|
||||
), patch(
|
||||
"application.api.user.base.db_readonly", _yield
|
||||
"docsgpt.api.user.base.db_readonly", _yield
|
||||
):
|
||||
yield
|
||||
|
||||
@@ -27,7 +27,7 @@ class TestTimeRangeGenerators:
|
||||
pass
|
||||
|
||||
def test_generate_minute_range(self):
|
||||
from application.api.user.base import generate_minute_range
|
||||
from docsgpt.api.user.base import generate_minute_range
|
||||
|
||||
start = datetime.datetime(2024, 1, 1, 10, 0, 0)
|
||||
end = datetime.datetime(2024, 1, 1, 10, 5, 0)
|
||||
@@ -40,7 +40,7 @@ class TestTimeRangeGenerators:
|
||||
assert all(val == 0 for val in result.values())
|
||||
|
||||
def test_generate_hourly_range(self):
|
||||
from application.api.user.base import generate_hourly_range
|
||||
from docsgpt.api.user.base import generate_hourly_range
|
||||
|
||||
start = datetime.datetime(2024, 1, 1, 10, 0, 0)
|
||||
end = datetime.datetime(2024, 1, 1, 15, 0, 0)
|
||||
@@ -53,7 +53,7 @@ class TestTimeRangeGenerators:
|
||||
assert all(val == 0 for val in result.values())
|
||||
|
||||
def test_generate_date_range(self):
|
||||
from application.api.user.base import generate_date_range
|
||||
from docsgpt.api.user.base import generate_date_range
|
||||
|
||||
start = datetime.date(2024, 1, 1)
|
||||
end = datetime.date(2024, 1, 5)
|
||||
@@ -66,7 +66,7 @@ class TestTimeRangeGenerators:
|
||||
assert all(val == 0 for val in result.values())
|
||||
|
||||
def test_single_minute_range(self):
|
||||
from application.api.user.base import generate_minute_range
|
||||
from docsgpt.api.user.base import generate_minute_range
|
||||
|
||||
time = datetime.datetime(2024, 1, 1, 10, 30, 0)
|
||||
result = generate_minute_range(time, time)
|
||||
@@ -84,7 +84,7 @@ class TestResolveToolDetails:
|
||||
pass
|
||||
|
||||
def test_empty_tool_ids_list(self, mock_mongo_db):
|
||||
from application.api.user.base import resolve_tool_details
|
||||
from docsgpt.api.user.base import resolve_tool_details
|
||||
|
||||
result = resolve_tool_details([])
|
||||
|
||||
@@ -95,9 +95,9 @@ class TestResolveToolDetails:
|
||||
class TestGetVectorStore:
|
||||
pass
|
||||
|
||||
@patch("application.api.user.base.VectorCreator.create_vectorstore")
|
||||
@patch("docsgpt.api.user.base.VectorCreator.create_vectorstore")
|
||||
def test_creates_vector_store(self, mock_create):
|
||||
from application.api.user.base import get_vector_store
|
||||
from docsgpt.api.user.base import get_vector_store
|
||||
|
||||
mock_store = Mock()
|
||||
mock_create.return_value = mock_store
|
||||
@@ -128,7 +128,7 @@ class TestHandleImageUpload:
|
||||
return cls._image_bytes()
|
||||
|
||||
def test_returns_existing_url_when_no_file(self, flask_app):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
with flask_app.test_request_context():
|
||||
mock_request = Mock()
|
||||
@@ -144,7 +144,7 @@ class TestHandleImageUpload:
|
||||
assert error is None
|
||||
|
||||
def test_uploads_new_image(self, flask_app):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
with flask_app.test_request_context():
|
||||
mock_file = FileStorage(
|
||||
@@ -166,7 +166,7 @@ class TestHandleImageUpload:
|
||||
mock_storage.save_file.assert_called_once()
|
||||
|
||||
def test_accepts_multi_picture_jpeg(self, flask_app):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
# Pillow reports multi-picture JPEGs (e.g. iPhone portrait photos) as
|
||||
# MPO; they must still be accepted under a .jpg extension.
|
||||
@@ -189,7 +189,7 @@ class TestHandleImageUpload:
|
||||
mock_storage.save_file.assert_called_once()
|
||||
|
||||
def test_uploads_image_with_non_ascii_basename(self, flask_app):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
with flask_app.test_request_context():
|
||||
mock_file = FileStorage(
|
||||
@@ -206,7 +206,7 @@ class TestHandleImageUpload:
|
||||
mock_storage.save_file.assert_called_once()
|
||||
|
||||
def test_ignores_empty_filename(self, flask_app):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
with flask_app.test_request_context():
|
||||
mock_file = Mock()
|
||||
@@ -225,7 +225,7 @@ class TestHandleImageUpload:
|
||||
mock_storage.save_file.assert_not_called()
|
||||
|
||||
def test_handles_upload_error(self, flask_app):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
with flask_app.app_context():
|
||||
mock_file = FileStorage(
|
||||
@@ -245,7 +245,7 @@ class TestHandleImageUpload:
|
||||
assert error.status_code == 400
|
||||
|
||||
def test_rejects_non_image_content(self, flask_app):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
with flask_app.app_context():
|
||||
mock_file = FileStorage(
|
||||
@@ -263,11 +263,11 @@ class TestHandleImageUpload:
|
||||
mock_storage.save_file.assert_not_called()
|
||||
|
||||
def test_accepts_image_at_encoded_byte_limit(self, flask_app):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
payload = self._png_bytes()
|
||||
with patch(
|
||||
"application.api.user.base.settings.AGENT_IMAGE_MAX_BYTES",
|
||||
"docsgpt.api.user.base.settings.AGENT_IMAGE_MAX_BYTES",
|
||||
len(payload),
|
||||
), flask_app.app_context():
|
||||
mock_file = FileStorage(
|
||||
@@ -284,11 +284,11 @@ class TestHandleImageUpload:
|
||||
mock_storage.save_file.assert_called_once()
|
||||
|
||||
def test_rejects_image_over_encoded_byte_limit(self, flask_app):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
payload = self._png_bytes()
|
||||
with patch(
|
||||
"application.api.user.base.settings.AGENT_IMAGE_MAX_BYTES",
|
||||
"docsgpt.api.user.base.settings.AGENT_IMAGE_MAX_BYTES",
|
||||
len(payload) - 1,
|
||||
), flask_app.app_context():
|
||||
mock_file = FileStorage(
|
||||
@@ -311,11 +311,11 @@ class TestHandleImageUpload:
|
||||
def test_enforces_decoded_pixel_limit(
|
||||
self, flask_app, width, height, expected_status
|
||||
):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
payload = self._image_bytes(width, height)
|
||||
with patch(
|
||||
"application.api.user.base.settings.AGENT_IMAGE_MAX_PIXELS", 16
|
||||
"docsgpt.api.user.base.settings.AGENT_IMAGE_MAX_PIXELS", 16
|
||||
), flask_app.app_context():
|
||||
mock_file = FileStorage(
|
||||
stream=io.BytesIO(payload), filename="dimensions.png"
|
||||
@@ -338,7 +338,7 @@ class TestHandleImageUpload:
|
||||
def test_rejects_image_whose_content_does_not_match_extension(
|
||||
self, flask_app
|
||||
):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
with flask_app.app_context():
|
||||
mock_file = FileStorage(
|
||||
@@ -355,7 +355,7 @@ class TestHandleImageUpload:
|
||||
mock_storage.save_file.assert_not_called()
|
||||
|
||||
def test_sanitizes_user_directory_component(self, flask_app):
|
||||
from application.api.user.base import handle_image_upload
|
||||
from docsgpt.api.user.base import handle_image_upload
|
||||
|
||||
with flask_app.app_context():
|
||||
mock_file = FileStorage(
|
||||
@@ -379,7 +379,7 @@ class TestRequireAgentDecorator:
|
||||
pass
|
||||
|
||||
def test_returns_400_for_missing_token(self, flask_app):
|
||||
from application.api.user.base import require_agent
|
||||
from docsgpt.api.user.base import require_agent
|
||||
|
||||
with flask_app.app_context():
|
||||
|
||||
@@ -400,7 +400,7 @@ class TestRequireAgentDecorator:
|
||||
|
||||
class TestEnsureUserDocPgConn:
|
||||
def test_creates_new_user_doc(self, pg_conn):
|
||||
from application.api.user.base import ensure_user_doc
|
||||
from docsgpt.api.user.base import ensure_user_doc
|
||||
|
||||
with _patch_base_db(pg_conn):
|
||||
doc = ensure_user_doc("brand-new-user")
|
||||
@@ -410,8 +410,8 @@ class TestEnsureUserDocPgConn:
|
||||
assert prefs.get("shared_with_me") == []
|
||||
|
||||
def test_preserves_existing_prefs(self, pg_conn):
|
||||
from application.api.user.base import ensure_user_doc
|
||||
from application.storage.db.repositories.users import UsersRepository
|
||||
from docsgpt.api.user.base import ensure_user_doc
|
||||
from docsgpt.storage.db.repositories.users import UsersRepository
|
||||
|
||||
user = "existing-user"
|
||||
UsersRepository(pg_conn).upsert(user)
|
||||
@@ -425,18 +425,18 @@ class TestEnsureUserDocPgConn:
|
||||
|
||||
class TestResolveToolDetailsPgConn:
|
||||
def test_empty_list_returns_empty(self, pg_conn):
|
||||
from application.api.user.base import resolve_tool_details
|
||||
from docsgpt.api.user.base import resolve_tool_details
|
||||
with _patch_base_db(pg_conn):
|
||||
assert resolve_tool_details([]) == []
|
||||
|
||||
def test_none_entries_filtered_out(self, pg_conn):
|
||||
from application.api.user.base import resolve_tool_details
|
||||
from docsgpt.api.user.base import resolve_tool_details
|
||||
with _patch_base_db(pg_conn):
|
||||
assert resolve_tool_details([None, ""]) == []
|
||||
|
||||
def test_resolves_known_uuid_ids(self, pg_conn):
|
||||
from application.api.user.base import resolve_tool_details
|
||||
from application.storage.db.repositories.user_tools import (
|
||||
from docsgpt.api.user.base import resolve_tool_details
|
||||
from docsgpt.storage.db.repositories.user_tools import (
|
||||
UserToolsRepository,
|
||||
)
|
||||
|
||||
@@ -452,7 +452,7 @@ class TestResolveToolDetailsPgConn:
|
||||
assert got[0]["display_name"] == "Custom"
|
||||
|
||||
def test_unknown_ids_skipped(self, pg_conn):
|
||||
from application.api.user.base import resolve_tool_details
|
||||
from docsgpt.api.user.base import resolve_tool_details
|
||||
with _patch_base_db(pg_conn):
|
||||
got = resolve_tool_details(
|
||||
["00000000-0000-0000-0000-000000000000"]
|
||||
@@ -460,8 +460,8 @@ class TestResolveToolDetailsPgConn:
|
||||
assert got == []
|
||||
|
||||
def test_legacy_ids_lookup(self, pg_conn):
|
||||
from application.api.user.base import resolve_tool_details
|
||||
from application.storage.db.repositories.user_tools import (
|
||||
from docsgpt.api.user.base import resolve_tool_details
|
||||
from docsgpt.storage.db.repositories.user_tools import (
|
||||
UserToolsRepository,
|
||||
)
|
||||
|
||||
@@ -479,7 +479,7 @@ class TestResolveToolDetailsPgConn:
|
||||
|
||||
class TestRequireAgentPgConn:
|
||||
def test_returns_404_invalid_token(self, pg_conn, flask_app):
|
||||
from application.api.user.base import require_agent
|
||||
from docsgpt.api.user.base import require_agent
|
||||
|
||||
@require_agent
|
||||
def fn(webhook_token=None, agent=None, agent_id_str=None):
|
||||
@@ -490,8 +490,8 @@ class TestRequireAgentPgConn:
|
||||
assert result.status_code == 404
|
||||
|
||||
def test_injects_agent_when_valid(self, pg_conn, flask_app):
|
||||
from application.api.user.base import require_agent
|
||||
from application.storage.db.repositories.agents import AgentsRepository
|
||||
from docsgpt.api.user.base import require_agent
|
||||
from docsgpt.storage.db.repositories.agents import AgentsRepository
|
||||
|
||||
agent = AgentsRepository(pg_conn).create(
|
||||
"owner", "wh-agent", "published",
|
||||
|
||||
Reference in new issue
Block a user