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

+11 -11
View File
@@ -3,7 +3,7 @@
import pytest
from unittest.mock import patch
from application.core.url_validation import (
from docsgpt.core.url_validation import (
SSRFError,
validate_url,
validate_url_safe,
@@ -62,13 +62,13 @@ class TestValidateUrl:
"""Tests for validate_url function."""
def test_adds_scheme_if_missing(self):
with patch("application.core.url_validation.resolve_hostname") as mock_resolve:
with patch("docsgpt.core.url_validation.resolve_hostname") as mock_resolve:
mock_resolve.return_value = "93.184.216.34" # Public IP
result = validate_url("example.com")
assert result == "http://example.com"
def test_preserves_https_scheme(self):
with patch("application.core.url_validation.resolve_hostname") as mock_resolve:
with patch("docsgpt.core.url_validation.resolve_hostname") as mock_resolve:
mock_resolve.return_value = "93.184.216.34"
result = validate_url("https://example.com")
assert result == "https://example.com"
@@ -129,14 +129,14 @@ class TestValidateUrl:
assert "scheme" in str(exc_info.value).lower()
def test_blocks_hostname_resolving_to_private_ip(self):
with patch("application.core.url_validation.resolve_hostname") as mock_resolve:
with patch("docsgpt.core.url_validation.resolve_hostname") as mock_resolve:
mock_resolve.return_value = "192.168.1.1"
with pytest.raises(SSRFError) as exc_info:
validate_url("http://internal.example.com")
assert "private" in str(exc_info.value).lower() or "internal" in str(exc_info.value).lower()
def test_blocks_hostname_resolving_to_metadata_ip(self):
with patch("application.core.url_validation.resolve_hostname") as mock_resolve:
with patch("docsgpt.core.url_validation.resolve_hostname") as mock_resolve:
mock_resolve.return_value = "169.254.169.254"
with pytest.raises(SSRFError) as exc_info:
validate_url("http://evil.example.com")
@@ -147,13 +147,13 @@ class TestValidateUrl:
assert result == "http://8.8.8.8"
def test_allows_public_hostname(self):
with patch("application.core.url_validation.resolve_hostname") as mock_resolve:
with patch("docsgpt.core.url_validation.resolve_hostname") as mock_resolve:
mock_resolve.return_value = "93.184.216.34"
result = validate_url("https://example.com")
assert result == "https://example.com"
def test_raises_on_unresolvable_hostname(self):
with patch("application.core.url_validation.resolve_hostname") as mock_resolve:
with patch("docsgpt.core.url_validation.resolve_hostname") as mock_resolve:
mock_resolve.return_value = None
with pytest.raises(SSRFError) as exc_info:
validate_url("http://nonexistent.invalid")
@@ -177,7 +177,7 @@ class TestValidateUrlSafe:
"""Tests for validate_url_safe non-throwing function."""
def test_returns_tuple_on_success(self):
with patch("application.core.url_validation.resolve_hostname") as mock_resolve:
with patch("docsgpt.core.url_validation.resolve_hostname") as mock_resolve:
mock_resolve.return_value = "93.184.216.34"
is_valid, url, error = validate_url_safe("https://example.com")
assert is_valid is True
@@ -197,7 +197,7 @@ class TestValidateUrlSafe:
assert "private" in error.lower() or "internal" in error.lower()
def test_adds_scheme_when_missing(self):
with patch("application.core.url_validation.resolve_hostname") as mock_resolve:
with patch("docsgpt.core.url_validation.resolve_hostname") as mock_resolve:
mock_resolve.return_value = "93.184.216.34"
is_valid, url, error = validate_url_safe("example.com")
assert is_valid is True
@@ -235,7 +235,7 @@ class TestValidateUrlExtended:
validate_url("http://metadata")
def test_allows_localhost_with_flag(self):
with patch("application.core.url_validation.resolve_hostname") as mock_resolve:
with patch("docsgpt.core.url_validation.resolve_hostname") as mock_resolve:
mock_resolve.return_value = "192.168.1.1"
result = validate_url(
"http://internal.local", allow_localhost=True
@@ -251,7 +251,7 @@ class TestValidateUrlExtended:
validate_url("http://[fd00:ec2::254]")
def test_blocks_hostname_resolving_to_loopback(self):
with patch("application.core.url_validation.resolve_hostname") as mock_resolve:
with patch("docsgpt.core.url_validation.resolve_hostname") as mock_resolve:
mock_resolve.return_value = "127.0.0.1"
with pytest.raises(SSRFError):
validate_url("http://sneaky.example.com")