re-structure

This commit is contained in:
Yaojia Wang
2026-02-01 22:55:31 +01:00
parent 400b12a967
commit b602d0a340
176 changed files with 856 additions and 853 deletions

View File

@@ -10,12 +10,12 @@ from uuid import UUID
import pytest
from inference.data.async_request_db import ApiKeyConfig, AsyncRequestDB
from inference.data.models import AsyncRequest
from inference.web.workers.async_queue import AsyncTask, AsyncTaskQueue
from inference.web.services.async_processing import AsyncProcessingService
from inference.web.config import AsyncConfig, StorageConfig
from inference.web.core.rate_limiter import RateLimiter
from backend.data.async_request_db import ApiKeyConfig, AsyncRequestDB
from backend.data.models import AsyncRequest
from backend.web.workers.async_queue import AsyncTask, AsyncTaskQueue
from backend.web.services.async_processing import AsyncProcessingService
from backend.web.config import AsyncConfig, StorageConfig
from backend.web.core.rate_limiter import RateLimiter
@pytest.fixture

View File

@@ -14,7 +14,7 @@ class TestTaskStatus:
def test_task_status_basic_fields(self) -> None:
"""TaskStatus has all required fields."""
from inference.web.core.task_interface import TaskStatus
from backend.web.core.task_interface import TaskStatus
status = TaskStatus(
name="test_runner",
@@ -29,7 +29,7 @@ class TestTaskStatus:
def test_task_status_with_error(self) -> None:
"""TaskStatus can include optional error message."""
from inference.web.core.task_interface import TaskStatus
from backend.web.core.task_interface import TaskStatus
status = TaskStatus(
name="failed_runner",
@@ -42,7 +42,7 @@ class TestTaskStatus:
def test_task_status_default_error_is_none(self) -> None:
"""TaskStatus error defaults to None."""
from inference.web.core.task_interface import TaskStatus
from backend.web.core.task_interface import TaskStatus
status = TaskStatus(
name="test",
@@ -54,7 +54,7 @@ class TestTaskStatus:
def test_task_status_is_frozen(self) -> None:
"""TaskStatus is immutable (frozen dataclass)."""
from inference.web.core.task_interface import TaskStatus
from backend.web.core.task_interface import TaskStatus
status = TaskStatus(
name="test",
@@ -71,20 +71,20 @@ class TestTaskRunnerInterface:
def test_cannot_instantiate_directly(self) -> None:
"""TaskRunner is abstract and cannot be instantiated."""
from inference.web.core.task_interface import TaskRunner
from backend.web.core.task_interface import TaskRunner
with pytest.raises(TypeError):
TaskRunner() # type: ignore[abstract]
def test_is_abstract_base_class(self) -> None:
"""TaskRunner inherits from ABC."""
from inference.web.core.task_interface import TaskRunner
from backend.web.core.task_interface import TaskRunner
assert issubclass(TaskRunner, ABC)
def test_subclass_missing_name_cannot_instantiate(self) -> None:
"""Subclass without name property cannot be instantiated."""
from inference.web.core.task_interface import TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskRunner, TaskStatus
class MissingName(TaskRunner):
def start(self) -> None:
@@ -105,7 +105,7 @@ class TestTaskRunnerInterface:
def test_subclass_missing_start_cannot_instantiate(self) -> None:
"""Subclass without start method cannot be instantiated."""
from inference.web.core.task_interface import TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskRunner, TaskStatus
class MissingStart(TaskRunner):
@property
@@ -127,7 +127,7 @@ class TestTaskRunnerInterface:
def test_subclass_missing_stop_cannot_instantiate(self) -> None:
"""Subclass without stop method cannot be instantiated."""
from inference.web.core.task_interface import TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskRunner, TaskStatus
class MissingStop(TaskRunner):
@property
@@ -149,7 +149,7 @@ class TestTaskRunnerInterface:
def test_subclass_missing_is_running_cannot_instantiate(self) -> None:
"""Subclass without is_running property cannot be instantiated."""
from inference.web.core.task_interface import TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskRunner, TaskStatus
class MissingIsRunning(TaskRunner):
@property
@@ -170,7 +170,7 @@ class TestTaskRunnerInterface:
def test_subclass_missing_get_status_cannot_instantiate(self) -> None:
"""Subclass without get_status method cannot be instantiated."""
from inference.web.core.task_interface import TaskRunner
from backend.web.core.task_interface import TaskRunner
class MissingGetStatus(TaskRunner):
@property
@@ -192,7 +192,7 @@ class TestTaskRunnerInterface:
def test_complete_subclass_can_instantiate(self) -> None:
"""Complete subclass implementing all methods can be instantiated."""
from inference.web.core.task_interface import TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskRunner, TaskStatus
class CompleteRunner(TaskRunner):
def __init__(self) -> None:
@@ -240,7 +240,7 @@ class TestTaskManager:
def test_register_runner(self) -> None:
"""Can register a task runner."""
from inference.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
class MockRunner(TaskRunner):
@property
@@ -268,14 +268,14 @@ class TestTaskManager:
def test_get_runner_returns_none_for_unknown(self) -> None:
"""get_runner returns None for unknown runner name."""
from inference.web.core.task_interface import TaskManager
from backend.web.core.task_interface import TaskManager
manager = TaskManager()
assert manager.get_runner("unknown") is None
def test_start_all_runners(self) -> None:
"""start_all starts all registered runners."""
from inference.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
class MockRunner(TaskRunner):
def __init__(self, runner_name: str) -> None:
@@ -315,7 +315,7 @@ class TestTaskManager:
def test_stop_all_runners(self) -> None:
"""stop_all stops all registered runners."""
from inference.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
class MockRunner(TaskRunner):
def __init__(self, runner_name: str) -> None:
@@ -355,7 +355,7 @@ class TestTaskManager:
def test_get_all_status(self) -> None:
"""get_all_status returns status of all runners."""
from inference.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
class MockRunner(TaskRunner):
def __init__(self, runner_name: str, pending: int) -> None:
@@ -391,14 +391,14 @@ class TestTaskManager:
def test_get_all_status_empty_when_no_runners(self) -> None:
"""get_all_status returns empty dict when no runners registered."""
from inference.web.core.task_interface import TaskManager
from backend.web.core.task_interface import TaskManager
manager = TaskManager()
assert manager.get_all_status() == {}
def test_runner_names_property(self) -> None:
"""runner_names returns list of all registered runner names."""
from inference.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
class MockRunner(TaskRunner):
def __init__(self, runner_name: str) -> None:
@@ -430,7 +430,7 @@ class TestTaskManager:
def test_stop_all_with_timeout_distribution(self) -> None:
"""stop_all distributes timeout across runners."""
from inference.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
received_timeouts: list[float | None] = []
@@ -467,7 +467,7 @@ class TestTaskManager:
def test_start_all_skips_runners_requiring_arguments(self) -> None:
"""start_all skips runners that require arguments."""
from inference.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
from backend.web.core.task_interface import TaskManager, TaskRunner, TaskStatus
no_args_started = []
with_args_started = []
@@ -521,7 +521,7 @@ class TestTaskManager:
def test_stop_all_with_no_runners(self) -> None:
"""stop_all does nothing when no runners registered."""
from inference.web.core.task_interface import TaskManager
from backend.web.core.task_interface import TaskManager
manager = TaskManager()
# Should not raise any exception
@@ -535,23 +535,23 @@ class TestTrainingSchedulerInterface:
def test_training_scheduler_is_task_runner(self) -> None:
"""TrainingScheduler inherits from TaskRunner."""
from inference.web.core.scheduler import TrainingScheduler
from inference.web.core.task_interface import TaskRunner
from backend.web.core.scheduler import TrainingScheduler
from backend.web.core.task_interface import TaskRunner
scheduler = TrainingScheduler()
assert isinstance(scheduler, TaskRunner)
def test_training_scheduler_name(self) -> None:
"""TrainingScheduler has correct name."""
from inference.web.core.scheduler import TrainingScheduler
from backend.web.core.scheduler import TrainingScheduler
scheduler = TrainingScheduler()
assert scheduler.name == "training_scheduler"
def test_training_scheduler_get_status(self) -> None:
"""TrainingScheduler provides status via get_status."""
from inference.web.core.scheduler import TrainingScheduler
from inference.web.core.task_interface import TaskStatus
from backend.web.core.scheduler import TrainingScheduler
from backend.web.core.task_interface import TaskStatus
scheduler = TrainingScheduler()
# Mock the training tasks repository
@@ -572,29 +572,29 @@ class TestAutoLabelSchedulerInterface:
def test_autolabel_scheduler_is_task_runner(self) -> None:
"""AutoLabelScheduler inherits from TaskRunner."""
from inference.web.core.autolabel_scheduler import AutoLabelScheduler
from inference.web.core.task_interface import TaskRunner
from backend.web.core.autolabel_scheduler import AutoLabelScheduler
from backend.web.core.task_interface import TaskRunner
with patch("inference.web.core.autolabel_scheduler.get_storage_helper"):
with patch("backend.web.core.autolabel_scheduler.get_storage_helper"):
scheduler = AutoLabelScheduler()
assert isinstance(scheduler, TaskRunner)
def test_autolabel_scheduler_name(self) -> None:
"""AutoLabelScheduler has correct name."""
from inference.web.core.autolabel_scheduler import AutoLabelScheduler
from backend.web.core.autolabel_scheduler import AutoLabelScheduler
with patch("inference.web.core.autolabel_scheduler.get_storage_helper"):
with patch("backend.web.core.autolabel_scheduler.get_storage_helper"):
scheduler = AutoLabelScheduler()
assert scheduler.name == "autolabel_scheduler"
def test_autolabel_scheduler_get_status(self) -> None:
"""AutoLabelScheduler provides status via get_status."""
from inference.web.core.autolabel_scheduler import AutoLabelScheduler
from inference.web.core.task_interface import TaskStatus
from backend.web.core.autolabel_scheduler import AutoLabelScheduler
from backend.web.core.task_interface import TaskStatus
with patch("inference.web.core.autolabel_scheduler.get_storage_helper"):
with patch("backend.web.core.autolabel_scheduler.get_storage_helper"):
with patch(
"inference.web.core.autolabel_scheduler.get_pending_autolabel_documents"
"backend.web.core.autolabel_scheduler.get_pending_autolabel_documents"
) as mock_get:
mock_get.return_value = [MagicMock(), MagicMock(), MagicMock()]
@@ -612,23 +612,23 @@ class TestAsyncTaskQueueInterface:
def test_async_queue_is_task_runner(self) -> None:
"""AsyncTaskQueue inherits from TaskRunner."""
from inference.web.workers.async_queue import AsyncTaskQueue
from inference.web.core.task_interface import TaskRunner
from backend.web.workers.async_queue import AsyncTaskQueue
from backend.web.core.task_interface import TaskRunner
queue = AsyncTaskQueue()
assert isinstance(queue, TaskRunner)
def test_async_queue_name(self) -> None:
"""AsyncTaskQueue has correct name."""
from inference.web.workers.async_queue import AsyncTaskQueue
from backend.web.workers.async_queue import AsyncTaskQueue
queue = AsyncTaskQueue()
assert queue.name == "async_task_queue"
def test_async_queue_get_status(self) -> None:
"""AsyncTaskQueue provides status via get_status."""
from inference.web.workers.async_queue import AsyncTaskQueue
from inference.web.core.task_interface import TaskStatus
from backend.web.workers.async_queue import AsyncTaskQueue
from backend.web.core.task_interface import TaskStatus
queue = AsyncTaskQueue()
status = queue.get_status()
@@ -645,23 +645,23 @@ class TestBatchTaskQueueInterface:
def test_batch_queue_is_task_runner(self) -> None:
"""BatchTaskQueue inherits from TaskRunner."""
from inference.web.workers.batch_queue import BatchTaskQueue
from inference.web.core.task_interface import TaskRunner
from backend.web.workers.batch_queue import BatchTaskQueue
from backend.web.core.task_interface import TaskRunner
queue = BatchTaskQueue()
assert isinstance(queue, TaskRunner)
def test_batch_queue_name(self) -> None:
"""BatchTaskQueue has correct name."""
from inference.web.workers.batch_queue import BatchTaskQueue
from backend.web.workers.batch_queue import BatchTaskQueue
queue = BatchTaskQueue()
assert queue.name == "batch_task_queue"
def test_batch_queue_get_status(self) -> None:
"""BatchTaskQueue provides status via get_status."""
from inference.web.workers.batch_queue import BatchTaskQueue
from inference.web.core.task_interface import TaskStatus
from backend.web.workers.batch_queue import BatchTaskQueue
from backend.web.core.task_interface import TaskStatus
queue = BatchTaskQueue()
status = queue.get_status()

View File

@@ -9,10 +9,10 @@ from uuid import UUID
from fastapi import HTTPException
from inference.data.admin_models import AdminAnnotation, AdminDocument
from backend.data.admin_models import AdminAnnotation, AdminDocument
from shared.fields import FIELD_CLASSES
from inference.web.api.v1.admin.annotations import _validate_uuid, create_annotation_router
from inference.web.schemas.admin import (
from backend.web.api.v1.admin.annotations import _validate_uuid, create_annotation_router
from backend.web.schemas.admin import (
AnnotationCreate,
AnnotationUpdate,
AutoLabelRequest,
@@ -234,10 +234,10 @@ class TestAutoLabelFilePathResolution:
mock_storage.get_raw_pdf_local_path.return_value = mock_path
with patch(
"inference.web.services.storage_helpers.get_storage_helper",
"backend.web.services.storage_helpers.get_storage_helper",
return_value=mock_storage,
):
from inference.web.services.storage_helpers import get_storage_helper
from backend.web.services.storage_helpers import get_storage_helper
storage = get_storage_helper()
result = storage.get_raw_pdf_local_path("test.pdf")

View File

@@ -8,9 +8,9 @@ from unittest.mock import MagicMock, patch
from fastapi import HTTPException
from inference.data.repositories import TokenRepository
from inference.data.admin_models import AdminToken
from inference.web.core.auth import (
from backend.data.repositories import TokenRepository
from backend.data.admin_models import AdminToken
from backend.web.core.auth import (
get_token_repository,
reset_token_repository,
validate_admin_token,
@@ -81,7 +81,7 @@ class TestTokenRepository:
def test_is_valid_active_token(self):
"""Test valid active token."""
with patch("inference.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
with patch("backend.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
mock_session = MagicMock()
mock_ctx.return_value.__enter__.return_value = mock_session
@@ -98,7 +98,7 @@ class TestTokenRepository:
def test_is_valid_inactive_token(self):
"""Test inactive token."""
with patch("inference.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
with patch("backend.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
mock_session = MagicMock()
mock_ctx.return_value.__enter__.return_value = mock_session
@@ -115,7 +115,7 @@ class TestTokenRepository:
def test_is_valid_expired_token(self):
"""Test expired token."""
with patch("inference.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
with patch("backend.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
mock_session = MagicMock()
mock_ctx.return_value.__enter__.return_value = mock_session
@@ -138,7 +138,7 @@ class TestTokenRepository:
This verifies the fix for comparing timezone-aware and naive datetimes.
The auth API now creates tokens with timezone-aware expiration dates.
"""
with patch("inference.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
with patch("backend.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
mock_session = MagicMock()
mock_ctx.return_value.__enter__.return_value = mock_session
@@ -157,7 +157,7 @@ class TestTokenRepository:
def test_is_valid_not_expired_token_timezone_aware(self):
"""Test non-expired token with timezone-aware datetime."""
with patch("inference.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
with patch("backend.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
mock_session = MagicMock()
mock_ctx.return_value.__enter__.return_value = mock_session
@@ -175,7 +175,7 @@ class TestTokenRepository:
def test_is_valid_token_not_found(self):
"""Test token not found."""
with patch("inference.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
with patch("backend.data.repositories.token_repository.BaseRepository._session") as mock_ctx:
mock_session = MagicMock()
mock_ctx.return_value.__enter__.return_value = mock_session
mock_session.get.return_value = None

View File

@@ -12,9 +12,9 @@ from uuid import UUID
from fastapi import HTTPException
from fastapi.testclient import TestClient
from inference.data.admin_models import AdminDocument, AdminToken
from inference.web.api.v1.admin.documents import _validate_uuid, create_documents_router
from inference.web.config import StorageConfig
from backend.data.admin_models import AdminDocument, AdminToken
from backend.web.api.v1.admin.documents import _validate_uuid, create_documents_router
from backend.web.config import StorageConfig
# Test UUID
@@ -66,7 +66,7 @@ class TestCreateTokenEndpoint:
def test_create_token_success(self, mock_db):
"""Test successful token creation."""
from inference.web.schemas.admin import AdminTokenCreate
from backend.web.schemas.admin import AdminTokenCreate
request = AdminTokenCreate(name="Test Token", expires_in_days=30)

View File

@@ -9,9 +9,9 @@ from uuid import uuid4
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inference.web.api.v1.admin.documents import create_documents_router
from inference.web.config import StorageConfig
from inference.web.core.auth import (
from backend.web.api.v1.admin.documents import create_documents_router
from backend.web.config import StorageConfig
from backend.web.core.auth import (
validate_admin_token,
get_document_repository,
get_annotation_repository,

View File

@@ -1,33 +1,33 @@
"""
Tests to verify admin schemas split maintains backward compatibility.
All existing imports from inference.web.schemas.admin must continue to work.
All existing imports from backend.web.schemas.admin must continue to work.
"""
import pytest
class TestEnumImports:
"""All enums importable from inference.web.schemas.admin."""
"""All enums importable from backend.web.schemas.admin."""
def test_document_status(self):
from inference.web.schemas.admin import DocumentStatus
from backend.web.schemas.admin import DocumentStatus
assert DocumentStatus.PENDING == "pending"
def test_auto_label_status(self):
from inference.web.schemas.admin import AutoLabelStatus
from backend.web.schemas.admin import AutoLabelStatus
assert AutoLabelStatus.RUNNING == "running"
def test_training_status(self):
from inference.web.schemas.admin import TrainingStatus
from backend.web.schemas.admin import TrainingStatus
assert TrainingStatus.PENDING == "pending"
def test_training_type(self):
from inference.web.schemas.admin import TrainingType
from backend.web.schemas.admin import TrainingType
assert TrainingType.TRAIN == "train"
def test_annotation_source(self):
from inference.web.schemas.admin import AnnotationSource
from backend.web.schemas.admin import AnnotationSource
assert AnnotationSource.MANUAL == "manual"
@@ -35,12 +35,12 @@ class TestAuthImports:
"""Auth schemas importable."""
def test_admin_token_create(self):
from inference.web.schemas.admin import AdminTokenCreate
from backend.web.schemas.admin import AdminTokenCreate
token = AdminTokenCreate(name="test")
assert token.name == "test"
def test_admin_token_response(self):
from inference.web.schemas.admin import AdminTokenResponse
from backend.web.schemas.admin import AdminTokenResponse
assert AdminTokenResponse is not None
@@ -48,23 +48,23 @@ class TestDocumentImports:
"""Document schemas importable."""
def test_document_upload_response(self):
from inference.web.schemas.admin import DocumentUploadResponse
from backend.web.schemas.admin import DocumentUploadResponse
assert DocumentUploadResponse is not None
def test_document_item(self):
from inference.web.schemas.admin import DocumentItem
from backend.web.schemas.admin import DocumentItem
assert DocumentItem is not None
def test_document_list_response(self):
from inference.web.schemas.admin import DocumentListResponse
from backend.web.schemas.admin import DocumentListResponse
assert DocumentListResponse is not None
def test_document_detail_response(self):
from inference.web.schemas.admin import DocumentDetailResponse
from backend.web.schemas.admin import DocumentDetailResponse
assert DocumentDetailResponse is not None
def test_document_stats_response(self):
from inference.web.schemas.admin import DocumentStatsResponse
from backend.web.schemas.admin import DocumentStatsResponse
assert DocumentStatsResponse is not None
@@ -72,60 +72,60 @@ class TestAnnotationImports:
"""Annotation schemas importable."""
def test_bounding_box(self):
from inference.web.schemas.admin import BoundingBox
from backend.web.schemas.admin import BoundingBox
bb = BoundingBox(x=0, y=0, width=100, height=50)
assert bb.width == 100
def test_annotation_create(self):
from inference.web.schemas.admin import AnnotationCreate
from backend.web.schemas.admin import AnnotationCreate
assert AnnotationCreate is not None
def test_annotation_update(self):
from inference.web.schemas.admin import AnnotationUpdate
from backend.web.schemas.admin import AnnotationUpdate
assert AnnotationUpdate is not None
def test_annotation_item(self):
from inference.web.schemas.admin import AnnotationItem
from backend.web.schemas.admin import AnnotationItem
assert AnnotationItem is not None
def test_annotation_response(self):
from inference.web.schemas.admin import AnnotationResponse
from backend.web.schemas.admin import AnnotationResponse
assert AnnotationResponse is not None
def test_annotation_list_response(self):
from inference.web.schemas.admin import AnnotationListResponse
from backend.web.schemas.admin import AnnotationListResponse
assert AnnotationListResponse is not None
def test_annotation_lock_request(self):
from inference.web.schemas.admin import AnnotationLockRequest
from backend.web.schemas.admin import AnnotationLockRequest
assert AnnotationLockRequest is not None
def test_annotation_lock_response(self):
from inference.web.schemas.admin import AnnotationLockResponse
from backend.web.schemas.admin import AnnotationLockResponse
assert AnnotationLockResponse is not None
def test_auto_label_request(self):
from inference.web.schemas.admin import AutoLabelRequest
from backend.web.schemas.admin import AutoLabelRequest
assert AutoLabelRequest is not None
def test_auto_label_response(self):
from inference.web.schemas.admin import AutoLabelResponse
from backend.web.schemas.admin import AutoLabelResponse
assert AutoLabelResponse is not None
def test_annotation_verify_request(self):
from inference.web.schemas.admin import AnnotationVerifyRequest
from backend.web.schemas.admin import AnnotationVerifyRequest
assert AnnotationVerifyRequest is not None
def test_annotation_verify_response(self):
from inference.web.schemas.admin import AnnotationVerifyResponse
from backend.web.schemas.admin import AnnotationVerifyResponse
assert AnnotationVerifyResponse is not None
def test_annotation_override_request(self):
from inference.web.schemas.admin import AnnotationOverrideRequest
from backend.web.schemas.admin import AnnotationOverrideRequest
assert AnnotationOverrideRequest is not None
def test_annotation_override_response(self):
from inference.web.schemas.admin import AnnotationOverrideResponse
from backend.web.schemas.admin import AnnotationOverrideResponse
assert AnnotationOverrideResponse is not None
@@ -133,68 +133,68 @@ class TestTrainingImports:
"""Training schemas importable."""
def test_training_config(self):
from inference.web.schemas.admin import TrainingConfig
from backend.web.schemas.admin import TrainingConfig
config = TrainingConfig()
assert config.epochs == 100
def test_training_task_create(self):
from inference.web.schemas.admin import TrainingTaskCreate
from backend.web.schemas.admin import TrainingTaskCreate
assert TrainingTaskCreate is not None
def test_training_task_item(self):
from inference.web.schemas.admin import TrainingTaskItem
from backend.web.schemas.admin import TrainingTaskItem
assert TrainingTaskItem is not None
def test_training_task_list_response(self):
from inference.web.schemas.admin import TrainingTaskListResponse
from backend.web.schemas.admin import TrainingTaskListResponse
assert TrainingTaskListResponse is not None
def test_training_task_detail_response(self):
from inference.web.schemas.admin import TrainingTaskDetailResponse
from backend.web.schemas.admin import TrainingTaskDetailResponse
assert TrainingTaskDetailResponse is not None
def test_training_task_response(self):
from inference.web.schemas.admin import TrainingTaskResponse
from backend.web.schemas.admin import TrainingTaskResponse
assert TrainingTaskResponse is not None
def test_training_log_item(self):
from inference.web.schemas.admin import TrainingLogItem
from backend.web.schemas.admin import TrainingLogItem
assert TrainingLogItem is not None
def test_training_logs_response(self):
from inference.web.schemas.admin import TrainingLogsResponse
from backend.web.schemas.admin import TrainingLogsResponse
assert TrainingLogsResponse is not None
def test_export_request(self):
from inference.web.schemas.admin import ExportRequest
from backend.web.schemas.admin import ExportRequest
assert ExportRequest is not None
def test_export_response(self):
from inference.web.schemas.admin import ExportResponse
from backend.web.schemas.admin import ExportResponse
assert ExportResponse is not None
def test_training_document_item(self):
from inference.web.schemas.admin import TrainingDocumentItem
from backend.web.schemas.admin import TrainingDocumentItem
assert TrainingDocumentItem is not None
def test_training_documents_response(self):
from inference.web.schemas.admin import TrainingDocumentsResponse
from backend.web.schemas.admin import TrainingDocumentsResponse
assert TrainingDocumentsResponse is not None
def test_model_metrics(self):
from inference.web.schemas.admin import ModelMetrics
from backend.web.schemas.admin import ModelMetrics
assert ModelMetrics is not None
def test_training_model_item(self):
from inference.web.schemas.admin import TrainingModelItem
from backend.web.schemas.admin import TrainingModelItem
assert TrainingModelItem is not None
def test_training_models_response(self):
from inference.web.schemas.admin import TrainingModelsResponse
from backend.web.schemas.admin import TrainingModelsResponse
assert TrainingModelsResponse is not None
def test_training_history_item(self):
from inference.web.schemas.admin import TrainingHistoryItem
from backend.web.schemas.admin import TrainingHistoryItem
assert TrainingHistoryItem is not None
@@ -202,31 +202,31 @@ class TestDatasetImports:
"""Dataset schemas importable."""
def test_dataset_create_request(self):
from inference.web.schemas.admin import DatasetCreateRequest
from backend.web.schemas.admin import DatasetCreateRequest
assert DatasetCreateRequest is not None
def test_dataset_document_item(self):
from inference.web.schemas.admin import DatasetDocumentItem
from backend.web.schemas.admin import DatasetDocumentItem
assert DatasetDocumentItem is not None
def test_dataset_response(self):
from inference.web.schemas.admin import DatasetResponse
from backend.web.schemas.admin import DatasetResponse
assert DatasetResponse is not None
def test_dataset_detail_response(self):
from inference.web.schemas.admin import DatasetDetailResponse
from backend.web.schemas.admin import DatasetDetailResponse
assert DatasetDetailResponse is not None
def test_dataset_list_item(self):
from inference.web.schemas.admin import DatasetListItem
from backend.web.schemas.admin import DatasetListItem
assert DatasetListItem is not None
def test_dataset_list_response(self):
from inference.web.schemas.admin import DatasetListResponse
from backend.web.schemas.admin import DatasetListResponse
assert DatasetListResponse is not None
def test_dataset_train_request(self):
from inference.web.schemas.admin import DatasetTrainRequest
from backend.web.schemas.admin import DatasetTrainRequest
assert DatasetTrainRequest is not None
@@ -234,12 +234,12 @@ class TestForwardReferences:
"""Forward references resolve correctly."""
def test_document_detail_has_annotation_items(self):
from inference.web.schemas.admin import DocumentDetailResponse
from backend.web.schemas.admin import DocumentDetailResponse
fields = DocumentDetailResponse.model_fields
assert "annotations" in fields
assert "training_history" in fields
def test_dataset_train_request_has_config(self):
from inference.web.schemas.admin import DatasetTrainRequest, TrainingConfig
from backend.web.schemas.admin import DatasetTrainRequest, TrainingConfig
req = DatasetTrainRequest(name="test", config=TrainingConfig())
assert req.config.epochs == 100

View File

@@ -7,15 +7,15 @@ from datetime import datetime, timedelta
from unittest.mock import MagicMock, patch
from uuid import UUID
from inference.data.admin_models import TrainingTask, TrainingLog
from inference.web.api.v1.admin.training import _validate_uuid, create_training_router
from inference.web.core.scheduler import (
from backend.data.admin_models import TrainingTask, TrainingLog
from backend.web.api.v1.admin.training import _validate_uuid, create_training_router
from backend.web.core.scheduler import (
TrainingScheduler,
get_training_scheduler,
start_scheduler,
stop_scheduler,
)
from inference.web.schemas.admin import (
from backend.web.schemas.admin import (
TrainingConfig,
TrainingStatus,
TrainingTaskCreate,

View File

@@ -9,8 +9,8 @@ from uuid import uuid4
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inference.web.api.v1.admin.locks import create_locks_router
from inference.web.core.auth import (
from backend.web.api.v1.admin.locks import create_locks_router
from backend.web.core.auth import (
validate_admin_token,
get_document_repository,
)

View File

@@ -9,12 +9,12 @@ from uuid import uuid4
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inference.web.api.v1.admin.annotations import (
from backend.web.api.v1.admin.annotations import (
create_annotation_router,
get_doc_repository,
get_ann_repository,
)
from inference.web.core.auth import validate_admin_token
from backend.web.core.auth import validate_admin_token
class MockAdminDocument:

View File

@@ -11,7 +11,7 @@ from unittest.mock import MagicMock
import pytest
from inference.web.workers.async_queue import AsyncTask, AsyncTaskQueue
from backend.web.workers.async_queue import AsyncTask, AsyncTaskQueue
class TestAsyncTask:

View File

@@ -11,12 +11,12 @@ import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inference.data.async_request_db import ApiKeyConfig, AsyncRequest, AsyncRequestDB
from inference.web.api.v1.public.async_api import create_async_router, set_async_service
from inference.web.services.async_processing import AsyncSubmitResult
from inference.web.dependencies import init_dependencies
from inference.web.rate_limiter import RateLimiter, RateLimitStatus
from inference.web.schemas.inference import AsyncStatus
from backend.data.async_request_db import ApiKeyConfig, AsyncRequest, AsyncRequestDB
from backend.web.api.v1.public.async_api import create_async_router, set_async_service
from backend.web.services.async_processing import AsyncSubmitResult
from backend.web.dependencies import init_dependencies
from backend.web.rate_limiter import RateLimiter, RateLimitStatus
from backend.web.schemas.inference import AsyncStatus
# Valid UUID for testing
TEST_REQUEST_UUID = "550e8400-e29b-41d4-a716-446655440000"

View File

@@ -10,11 +10,11 @@ from unittest.mock import MagicMock, patch
import pytest
from inference.data.async_request_db import AsyncRequest
from inference.web.workers.async_queue import AsyncTask, AsyncTaskQueue
from inference.web.services.async_processing import AsyncProcessingService, AsyncSubmitResult
from inference.web.config import AsyncConfig, StorageConfig
from inference.web.rate_limiter import RateLimiter
from backend.data.async_request_db import AsyncRequest
from backend.web.workers.async_queue import AsyncTask, AsyncTaskQueue
from backend.web.services.async_processing import AsyncProcessingService, AsyncSubmitResult
from backend.web.config import AsyncConfig, StorageConfig
from backend.web.rate_limiter import RateLimiter
@pytest.fixture
@@ -231,7 +231,7 @@ class TestAsyncProcessingService:
mock_db.get_request.return_value = None
# Mock the storage helper to return the same directory as the fixture
with patch("inference.web.services.async_processing.get_storage_helper") as mock_storage:
with patch("backend.web.services.async_processing.get_storage_helper") as mock_storage:
mock_helper = MagicMock()
mock_helper.get_uploads_base_path.return_value = temp_dir
mock_storage.return_value = mock_helper

View File

@@ -10,8 +10,8 @@ from fastapi import FastAPI
from fastapi.testclient import TestClient
import numpy as np
from inference.web.api.v1.admin.augmentation import create_augmentation_router
from inference.web.core.auth import (
from backend.web.api.v1.admin.augmentation import create_augmentation_router
from backend.web.core.auth import (
validate_admin_token,
get_document_repository,
get_dataset_repository,
@@ -175,7 +175,7 @@ class TestAugmentationPreviewEndpoint:
fake_image = np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8)
with patch(
"inference.web.services.augmentation_service.AugmentationService._load_document_page"
"backend.web.services.augmentation_service.AugmentationService._load_document_page"
) as mock_load:
mock_load.return_value = fake_image
@@ -251,7 +251,7 @@ class TestAugmentationPreviewConfigEndpoint:
fake_image = np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8)
with patch(
"inference.web.services.augmentation_service.AugmentationService._load_document_page"
"backend.web.services.augmentation_service.AugmentationService._load_document_page"
) as mock_load:
mock_load.return_value = fake_image

View File

@@ -8,7 +8,7 @@ from pathlib import Path
from unittest.mock import Mock, MagicMock
from uuid import uuid4
from inference.web.services.autolabel import AutoLabelService
from backend.web.services.autolabel import AutoLabelService
class MockDocument:

View File

@@ -9,7 +9,7 @@ from uuid import uuid4
import pytest
from inference.web.workers.batch_queue import BatchTask, BatchTaskQueue
from backend.web.workers.batch_queue import BatchTask, BatchTaskQueue
class MockBatchService:

View File

@@ -11,10 +11,10 @@ import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inference.web.api.v1.batch.routes import router, get_batch_repository
from inference.web.core.auth import validate_admin_token
from inference.web.workers.batch_queue import init_batch_queue, shutdown_batch_queue
from inference.web.services.batch_upload import BatchUploadService
from backend.web.api.v1.batch.routes import router, get_batch_repository
from backend.web.core.auth import validate_admin_token
from backend.web.workers.batch_queue import init_batch_queue, shutdown_batch_queue
from backend.web.services.batch_upload import BatchUploadService
class MockBatchUploadRepository:

View File

@@ -9,7 +9,7 @@ from uuid import uuid4
import pytest
from inference.web.services.batch_upload import BatchUploadService
from backend.web.services.batch_upload import BatchUploadService
@pytest.fixture

View File

@@ -28,7 +28,7 @@ class TestAnnotationCompletenessLogic:
def test_document_with_invoice_number_and_bankgiro_is_complete(self):
"""Document with invoice_number + bankgiro should be complete."""
from inference.web.services.dashboard_service import is_annotation_complete
from backend.web.services.dashboard_service import is_annotation_complete
annotations = [
{"class_id": 0, "class_name": "invoice_number"},
@@ -39,7 +39,7 @@ class TestAnnotationCompletenessLogic:
def test_document_with_ocr_number_and_plusgiro_is_complete(self):
"""Document with ocr_number + plusgiro should be complete."""
from inference.web.services.dashboard_service import is_annotation_complete
from backend.web.services.dashboard_service import is_annotation_complete
annotations = [
{"class_id": 3, "class_name": "ocr_number"},
@@ -50,7 +50,7 @@ class TestAnnotationCompletenessLogic:
def test_document_with_invoice_number_and_plusgiro_is_complete(self):
"""Document with invoice_number + plusgiro should be complete."""
from inference.web.services.dashboard_service import is_annotation_complete
from backend.web.services.dashboard_service import is_annotation_complete
annotations = [
{"class_id": 0, "class_name": "invoice_number"},
@@ -61,7 +61,7 @@ class TestAnnotationCompletenessLogic:
def test_document_with_ocr_number_and_bankgiro_is_complete(self):
"""Document with ocr_number + bankgiro should be complete."""
from inference.web.services.dashboard_service import is_annotation_complete
from backend.web.services.dashboard_service import is_annotation_complete
annotations = [
{"class_id": 3, "class_name": "ocr_number"},
@@ -72,7 +72,7 @@ class TestAnnotationCompletenessLogic:
def test_document_with_only_identifier_is_incomplete(self):
"""Document with only identifier field should be incomplete."""
from inference.web.services.dashboard_service import is_annotation_complete
from backend.web.services.dashboard_service import is_annotation_complete
annotations = [
{"class_id": 0, "class_name": "invoice_number"},
@@ -82,7 +82,7 @@ class TestAnnotationCompletenessLogic:
def test_document_with_only_payment_is_incomplete(self):
"""Document with only payment field should be incomplete."""
from inference.web.services.dashboard_service import is_annotation_complete
from backend.web.services.dashboard_service import is_annotation_complete
annotations = [
{"class_id": 4, "class_name": "bankgiro"},
@@ -92,13 +92,13 @@ class TestAnnotationCompletenessLogic:
def test_document_with_no_annotations_is_incomplete(self):
"""Document with no annotations should be incomplete."""
from inference.web.services.dashboard_service import is_annotation_complete
from backend.web.services.dashboard_service import is_annotation_complete
assert is_annotation_complete([]) is False
def test_document_with_other_fields_only_is_incomplete(self):
"""Document with only non-essential fields should be incomplete."""
from inference.web.services.dashboard_service import is_annotation_complete
from backend.web.services.dashboard_service import is_annotation_complete
annotations = [
{"class_id": 1, "class_name": "invoice_date"},
@@ -109,7 +109,7 @@ class TestAnnotationCompletenessLogic:
def test_document_with_all_fields_is_complete(self):
"""Document with all fields should be complete."""
from inference.web.services.dashboard_service import is_annotation_complete
from backend.web.services.dashboard_service import is_annotation_complete
annotations = [
{"class_id": 0, "class_name": "invoice_number"},
@@ -178,7 +178,7 @@ class TestDashboardSchemas:
def test_dashboard_stats_response_schema(self):
"""Test DashboardStatsResponse schema validation."""
from inference.web.schemas.admin import DashboardStatsResponse
from backend.web.schemas.admin import DashboardStatsResponse
response = DashboardStatsResponse(
total_documents=38,
@@ -195,10 +195,10 @@ class TestDashboardSchemas:
assert response.completeness_rate == 75.76
def test_active_model_response_schema(self):
"""Test ActiveModelResponse schema with null model."""
from inference.web.schemas.admin import ActiveModelResponse
"""Test DashboardActiveModelResponse schema with null model."""
from backend.web.schemas.admin import DashboardActiveModelResponse
response = ActiveModelResponse(
response = DashboardActiveModelResponse(
model=None,
running_training=None,
)
@@ -208,7 +208,7 @@ class TestDashboardSchemas:
def test_active_model_info_schema(self):
"""Test ActiveModelInfo schema validation."""
from inference.web.schemas.admin import ActiveModelInfo
from backend.web.schemas.admin import ActiveModelInfo
model = ActiveModelInfo(
version_id=TEST_MODEL_UUID,
@@ -227,7 +227,7 @@ class TestDashboardSchemas:
def test_running_training_info_schema(self):
"""Test RunningTrainingInfo schema validation."""
from inference.web.schemas.admin import RunningTrainingInfo
from backend.web.schemas.admin import RunningTrainingInfo
task = RunningTrainingInfo(
task_id=TEST_TASK_UUID,
@@ -243,7 +243,7 @@ class TestDashboardSchemas:
def test_activity_item_schema(self):
"""Test ActivityItem schema validation."""
from inference.web.schemas.admin import ActivityItem
from backend.web.schemas.admin import ActivityItem
activity = ActivityItem(
type="model_activated",
@@ -258,7 +258,7 @@ class TestDashboardSchemas:
def test_recent_activity_response_schema(self):
"""Test RecentActivityResponse schema with empty activities."""
from inference.web.schemas.admin import RecentActivityResponse
from backend.web.schemas.admin import RecentActivityResponse
response = RecentActivityResponse(activities=[])
@@ -270,7 +270,7 @@ class TestDashboardRouterCreation:
def test_creates_router_with_expected_endpoints(self):
"""Test router is created with expected endpoint paths."""
from inference.web.api.v1.admin.dashboard import create_dashboard_router
from backend.web.api.v1.admin.dashboard import create_dashboard_router
router = create_dashboard_router()
@@ -282,7 +282,7 @@ class TestDashboardRouterCreation:
def test_router_has_correct_prefix(self):
"""Test router has /admin/dashboard prefix."""
from inference.web.api.v1.admin.dashboard import create_dashboard_router
from backend.web.api.v1.admin.dashboard import create_dashboard_router
router = create_dashboard_router()
@@ -290,7 +290,7 @@ class TestDashboardRouterCreation:
def test_router_has_dashboard_tag(self):
"""Test router uses Dashboard tag."""
from inference.web.api.v1.admin.dashboard import create_dashboard_router
from backend.web.api.v1.admin.dashboard import create_dashboard_router
router = create_dashboard_router()
@@ -302,7 +302,7 @@ class TestFieldClassIds:
def test_identifier_class_ids(self):
"""Test identifier field class IDs."""
from inference.web.services.dashboard_service import IDENTIFIER_CLASS_IDS
from backend.web.services.dashboard_service import IDENTIFIER_CLASS_IDS
# invoice_number = 0, ocr_number = 3
assert 0 in IDENTIFIER_CLASS_IDS
@@ -310,7 +310,7 @@ class TestFieldClassIds:
def test_payment_class_ids(self):
"""Test payment field class IDs."""
from inference.web.services.dashboard_service import PAYMENT_CLASS_IDS
from backend.web.services.dashboard_service import PAYMENT_CLASS_IDS
# bankgiro = 4, plusgiro = 5
assert 4 in PAYMENT_CLASS_IDS

View File

@@ -12,7 +12,7 @@ from uuid import uuid4
import pytest
from inference.data.admin_models import (
from backend.data.admin_models import (
AdminAnnotation,
AdminDocument,
TrainingDataset,
@@ -105,7 +105,7 @@ class TestDatasetBuilder:
sample_documents, sample_annotations
):
"""Dataset builder should create images/ and labels/ with train/val/test subdirs."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
dataset_dir = tmp_path / "datasets" / "test"
builder = DatasetBuilder(
@@ -141,7 +141,7 @@ class TestDatasetBuilder:
sample_documents, sample_annotations
):
"""Images should be copied from admin_images to dataset folder."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -177,7 +177,7 @@ class TestDatasetBuilder:
sample_documents, sample_annotations
):
"""YOLO label files should be generated with correct format."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -221,7 +221,7 @@ class TestDatasetBuilder:
sample_documents, sample_annotations
):
"""data.yaml should be generated with correct field classes."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -257,7 +257,7 @@ class TestDatasetBuilder:
sample_documents, sample_annotations
):
"""Documents should be split into train/val/test according to ratios."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -294,7 +294,7 @@ class TestDatasetBuilder:
sample_documents, sample_annotations
):
"""After successful build, dataset status should be updated to 'ready'."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -327,7 +327,7 @@ class TestDatasetBuilder:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""If build fails, dataset status should be set to 'failed'."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -357,7 +357,7 @@ class TestDatasetBuilder:
sample_documents, sample_annotations
):
"""Same seed should produce same splits."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
results = []
for _ in range(2):
@@ -405,7 +405,7 @@ class TestAssignSplitsByGroup:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""Documents with unique group_key are distributed across splits."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -433,7 +433,7 @@ class TestAssignSplitsByGroup:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""Documents with null/empty group_key are each treated as independent single-doc groups."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -461,7 +461,7 @@ class TestAssignSplitsByGroup:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""Documents with same group_key should be assigned to the same split."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -494,7 +494,7 @@ class TestAssignSplitsByGroup:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""Multi-doc groups should be split according to train/val/test ratios."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -536,7 +536,7 @@ class TestAssignSplitsByGroup:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""Mix of single-doc and multi-doc groups should be handled correctly."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -574,7 +574,7 @@ class TestAssignSplitsByGroup:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""Same seed should produce same split assignments."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -601,7 +601,7 @@ class TestAssignSplitsByGroup:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""Different seeds should potentially produce different split assignments."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -627,7 +627,7 @@ class TestAssignSplitsByGroup:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""Every document should be assigned a split."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -654,7 +654,7 @@ class TestAssignSplitsByGroup:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""Empty document list should return empty result."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -671,7 +671,7 @@ class TestAssignSplitsByGroup:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""When all groups have multiple docs, splits should follow ratios."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -707,7 +707,7 @@ class TestAssignSplitsByGroup:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""When all groups have single doc, they are distributed across splits."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
builder = DatasetBuilder(
datasets_repo=mock_datasets_repo,
@@ -798,7 +798,7 @@ class TestBuildDatasetWithGroupKey:
mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""build_dataset should use group_key for split assignment."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
tmp_path, docs = grouped_documents
@@ -847,7 +847,7 @@ class TestBuildDatasetWithGroupKey:
self, tmp_path, mock_datasets_repo, mock_documents_repo, mock_annotations_repo
):
"""All docs with same group_key should go to same split."""
from inference.web.services.dataset_builder import DatasetBuilder
from backend.web.services.dataset_builder import DatasetBuilder
# Create 5 docs all with same group_key
docs = []

View File

@@ -9,9 +9,9 @@ from datetime import datetime, timezone
from unittest.mock import MagicMock, patch
from uuid import UUID
from inference.data.admin_models import TrainingDataset, DatasetDocument
from inference.web.api.v1.admin.training import create_training_router
from inference.web.schemas.admin import (
from backend.data.admin_models import TrainingDataset, DatasetDocument
from backend.web.api.v1.admin.training import create_training_router
from backend.web.schemas.admin import (
DatasetCreateRequest,
DatasetTrainRequest,
TrainingConfig,
@@ -130,10 +130,10 @@ class TestCreateDatasetRoute:
)
with patch(
"inference.web.services.dataset_builder.DatasetBuilder",
"backend.web.services.dataset_builder.DatasetBuilder",
return_value=mock_builder,
), patch(
"inference.web.api.v1.admin.training.datasets.get_storage_helper"
"backend.web.api.v1.admin.training.datasets.get_storage_helper"
) as mock_storage:
mock_storage.return_value.get_datasets_base_path.return_value = "/data/datasets"
mock_storage.return_value.get_admin_images_base_path.return_value = "/data/admin_images"
@@ -222,10 +222,10 @@ class TestCreateDatasetRoute:
)
with patch(
"inference.web.services.dataset_builder.DatasetBuilder",
"backend.web.services.dataset_builder.DatasetBuilder",
return_value=mock_builder,
), patch(
"inference.web.api.v1.admin.training.datasets.get_storage_helper"
"backend.web.api.v1.admin.training.datasets.get_storage_helper"
) as mock_storage:
mock_storage.return_value.get_datasets_base_path.return_value = "/data/datasets"
mock_storage.return_value.get_admin_images_base_path.return_value = "/data/admin_images"

View File

@@ -27,7 +27,7 @@ class TestTrainingDatasetModel:
def test_training_dataset_has_training_status_field(self):
"""TrainingDataset model should have training_status field."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
dataset = TrainingDataset(
name="test-dataset",
@@ -37,7 +37,7 @@ class TestTrainingDatasetModel:
def test_training_dataset_has_active_training_task_id_field(self):
"""TrainingDataset model should have active_training_task_id field."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
task_id = uuid4()
dataset = TrainingDataset(
@@ -48,7 +48,7 @@ class TestTrainingDatasetModel:
def test_training_dataset_defaults(self):
"""TrainingDataset should have correct defaults for new fields."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
dataset = TrainingDataset(name="test-dataset")
assert dataset.training_status is None
@@ -71,7 +71,7 @@ class TestDatasetRepositoryTrainingStatus:
def test_update_training_status_sets_status(self, mock_session):
"""update_training_status should set training_status."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
dataset_id = uuid4()
dataset = TrainingDataset(
@@ -81,10 +81,10 @@ class TestDatasetRepositoryTrainingStatus:
)
mock_session.get.return_value = dataset
with patch("inference.data.repositories.dataset_repository.get_session_context") as mock_ctx:
with patch("backend.data.repositories.dataset_repository.get_session_context") as mock_ctx:
mock_ctx.return_value.__enter__.return_value = mock_session
from inference.data.repositories import DatasetRepository
from backend.data.repositories import DatasetRepository
repo = DatasetRepository()
repo.update_training_status(
@@ -98,7 +98,7 @@ class TestDatasetRepositoryTrainingStatus:
def test_update_training_status_sets_task_id(self, mock_session):
"""update_training_status should set active_training_task_id."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
dataset_id = uuid4()
task_id = uuid4()
@@ -109,10 +109,10 @@ class TestDatasetRepositoryTrainingStatus:
)
mock_session.get.return_value = dataset
with patch("inference.data.repositories.dataset_repository.get_session_context") as mock_ctx:
with patch("backend.data.repositories.dataset_repository.get_session_context") as mock_ctx:
mock_ctx.return_value.__enter__.return_value = mock_session
from inference.data.repositories import DatasetRepository
from backend.data.repositories import DatasetRepository
repo = DatasetRepository()
repo.update_training_status(
@@ -127,7 +127,7 @@ class TestDatasetRepositoryTrainingStatus:
self, mock_session
):
"""update_training_status should update main status to 'trained' when completed."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
dataset_id = uuid4()
dataset = TrainingDataset(
@@ -137,10 +137,10 @@ class TestDatasetRepositoryTrainingStatus:
)
mock_session.get.return_value = dataset
with patch("inference.data.repositories.dataset_repository.get_session_context") as mock_ctx:
with patch("backend.data.repositories.dataset_repository.get_session_context") as mock_ctx:
mock_ctx.return_value.__enter__.return_value = mock_session
from inference.data.repositories import DatasetRepository
from backend.data.repositories import DatasetRepository
repo = DatasetRepository()
repo.update_training_status(
@@ -156,7 +156,7 @@ class TestDatasetRepositoryTrainingStatus:
self, mock_session
):
"""update_training_status should clear task_id when training completes."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
dataset_id = uuid4()
task_id = uuid4()
@@ -169,10 +169,10 @@ class TestDatasetRepositoryTrainingStatus:
)
mock_session.get.return_value = dataset
with patch("inference.data.repositories.dataset_repository.get_session_context") as mock_ctx:
with patch("backend.data.repositories.dataset_repository.get_session_context") as mock_ctx:
mock_ctx.return_value.__enter__.return_value = mock_session
from inference.data.repositories import DatasetRepository
from backend.data.repositories import DatasetRepository
repo = DatasetRepository()
repo.update_training_status(
@@ -187,10 +187,10 @@ class TestDatasetRepositoryTrainingStatus:
"""update_training_status should handle missing dataset gracefully."""
mock_session.get.return_value = None
with patch("inference.data.repositories.dataset_repository.get_session_context") as mock_ctx:
with patch("backend.data.repositories.dataset_repository.get_session_context") as mock_ctx:
mock_ctx.return_value.__enter__.return_value = mock_session
from inference.data.repositories import DatasetRepository
from backend.data.repositories import DatasetRepository
repo = DatasetRepository()
# Should not raise
@@ -213,7 +213,7 @@ class TestDatasetDetailResponseTrainingStatus:
def test_dataset_detail_response_includes_training_status(self):
"""DatasetDetailResponse schema should include training_status field."""
from inference.web.schemas.admin.datasets import DatasetDetailResponse
from backend.web.schemas.admin.datasets import DatasetDetailResponse
response = DatasetDetailResponse(
dataset_id=str(uuid4()),
@@ -240,7 +240,7 @@ class TestDatasetDetailResponseTrainingStatus:
def test_dataset_detail_response_allows_null_training_status(self):
"""DatasetDetailResponse should allow null training_status."""
from inference.web.schemas.admin.datasets import DatasetDetailResponse
from backend.web.schemas.admin.datasets import DatasetDetailResponse
response = DatasetDetailResponse(
dataset_id=str(uuid4()),
@@ -294,7 +294,7 @@ class TestSchedulerDatasetStatusUpdates:
def test_scheduler_sets_running_status_on_task_start(self, mock_datasets_repo, mock_training_tasks_repo):
"""Scheduler should set dataset training_status to 'running' when task starts."""
from inference.web.core.scheduler import TrainingScheduler
from backend.web.core.scheduler import TrainingScheduler
with patch.object(TrainingScheduler, "_run_yolo_training") as mock_train:
mock_train.return_value = {"model_path": "/path/to/model.pt", "metrics": {}}
@@ -333,35 +333,35 @@ class TestDatasetStatusValues:
def test_dataset_status_building(self):
"""Dataset can have status 'building'."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
dataset = TrainingDataset(name="test", status="building")
assert dataset.status == "building"
def test_dataset_status_ready(self):
"""Dataset can have status 'ready'."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
dataset = TrainingDataset(name="test", status="ready")
assert dataset.status == "ready"
def test_dataset_status_trained(self):
"""Dataset can have status 'trained'."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
dataset = TrainingDataset(name="test", status="trained")
assert dataset.status == "trained"
def test_dataset_status_failed(self):
"""Dataset can have status 'failed'."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
dataset = TrainingDataset(name="test", status="failed")
assert dataset.status == "failed"
def test_training_status_values(self):
"""Training status can have various values."""
from inference.data.admin_models import TrainingDataset
from backend.data.admin_models import TrainingDataset
valid_statuses = ["pending", "scheduled", "running", "completed", "failed", "cancelled"]
for status in valid_statuses:

View File

@@ -10,7 +10,7 @@ from datetime import datetime
from unittest.mock import MagicMock
from uuid import UUID, uuid4
from inference.data.admin_models import AdminDocument
from backend.data.admin_models import AdminDocument
# Test constants
@@ -76,7 +76,7 @@ class TestDocumentCategoryInReadModel:
def test_admin_document_read_has_category(self):
"""Test AdminDocumentRead includes category field."""
from inference.data.admin_models import AdminDocumentRead
from backend.data.admin_models import AdminDocumentRead
# Check the model has category field in its schema
assert "category" in AdminDocumentRead.model_fields
@@ -94,7 +94,7 @@ class TestDocumentCategoryAPI:
def test_upload_document_with_category(self, mock_admin_db):
"""Test uploading document with category parameter."""
from inference.web.schemas.admin import DocumentUploadResponse
from backend.web.schemas.admin import DocumentUploadResponse
# Verify response schema supports category
response = DocumentUploadResponse(
@@ -110,7 +110,7 @@ class TestDocumentCategoryAPI:
def test_list_documents_returns_category(self, mock_admin_db):
"""Test list documents endpoint returns category."""
from inference.web.schemas.admin import DocumentItem
from backend.web.schemas.admin import DocumentItem
item = DocumentItem(
document_id=TEST_DOC_UUID,
@@ -127,7 +127,7 @@ class TestDocumentCategoryAPI:
def test_document_detail_includes_category(self, mock_admin_db):
"""Test document detail response includes category."""
from inference.web.schemas.admin import DocumentDetailResponse
from backend.web.schemas.admin import DocumentDetailResponse
# Check schema has category
assert "category" in DocumentDetailResponse.model_fields
@@ -167,14 +167,14 @@ class TestDocumentCategoryUpdate:
def test_update_document_category_schema(self):
"""Test update document request supports category."""
from inference.web.schemas.admin import DocumentUpdateRequest
from backend.web.schemas.admin import DocumentUpdateRequest
request = DocumentUpdateRequest(category="letter")
assert request.category == "letter"
def test_update_document_category_optional(self):
"""Test category is optional in update request."""
from inference.web.schemas.admin import DocumentUpdateRequest
from backend.web.schemas.admin import DocumentUpdateRequest
# Should not raise - category is optional
request = DocumentUpdateRequest()
@@ -186,7 +186,7 @@ class TestDatasetWithCategory:
def test_dataset_create_with_category_filter(self):
"""Test creating dataset can filter by document category."""
from inference.web.schemas.admin import DatasetCreateRequest
from backend.web.schemas.admin import DatasetCreateRequest
request = DatasetCreateRequest(
name="Invoice Training Set",
@@ -197,7 +197,7 @@ class TestDatasetWithCategory:
def test_dataset_create_category_is_optional(self):
"""Test category filter is optional when creating dataset."""
from inference.web.schemas.admin import DatasetCreateRequest
from backend.web.schemas.admin import DatasetCreateRequest
request = DatasetCreateRequest(
name="Mixed Training Set",

View File

@@ -23,7 +23,7 @@ class TestGetCategoriesEndpoint:
def test_categories_endpoint_returns_list(self):
"""Test categories endpoint returns list of available categories."""
from inference.web.schemas.admin import DocumentCategoriesResponse
from backend.web.schemas.admin import DocumentCategoriesResponse
# Test schema exists and works
response = DocumentCategoriesResponse(
@@ -35,7 +35,7 @@ class TestGetCategoriesEndpoint:
def test_categories_response_schema(self):
"""Test DocumentCategoriesResponse schema structure."""
from inference.web.schemas.admin import DocumentCategoriesResponse
from backend.web.schemas.admin import DocumentCategoriesResponse
assert "categories" in DocumentCategoriesResponse.model_fields
assert "total" in DocumentCategoriesResponse.model_fields
@@ -69,7 +69,7 @@ class TestDocumentListFilterByCategory:
"""Test list documents endpoint accepts category query parameter."""
# The endpoint should accept ?category=invoice parameter
# This test verifies the schema/query parameter exists
from inference.web.schemas.admin import DocumentListResponse
from backend.web.schemas.admin import DocumentListResponse
# Schema should work with category filter applied
assert DocumentListResponse is not None
@@ -93,7 +93,7 @@ class TestDocumentUploadWithCategory:
def test_upload_response_includes_category(self):
"""Test upload response includes the category that was set."""
from inference.web.schemas.admin import DocumentUploadResponse
from backend.web.schemas.admin import DocumentUploadResponse
response = DocumentUploadResponse(
document_id=TEST_DOC_UUID,
@@ -108,7 +108,7 @@ class TestDocumentUploadWithCategory:
def test_upload_defaults_to_invoice_category(self):
"""Test upload defaults to 'invoice' if no category specified."""
from inference.web.schemas.admin import DocumentUploadResponse
from backend.web.schemas.admin import DocumentUploadResponse
response = DocumentUploadResponse(
document_id=TEST_DOC_UUID,
@@ -127,14 +127,14 @@ class TestDocumentRepositoryCategoryMethods:
def test_get_categories_method_exists(self):
"""Test DocumentRepository has get_categories method."""
from inference.data.repositories import DocumentRepository
from backend.data.repositories import DocumentRepository
repo = DocumentRepository()
assert hasattr(repo, "get_categories")
def test_get_paginated_accepts_category_filter(self):
"""Test get_paginated method accepts category parameter."""
from inference.data.repositories import DocumentRepository
from backend.data.repositories import DocumentRepository
import inspect
repo = DocumentRepository()
@@ -152,14 +152,14 @@ class TestUpdateDocumentCategory:
def test_update_category_method_exists(self):
"""Test DocumentRepository has method to update document category."""
from inference.data.repositories import DocumentRepository
from backend.data.repositories import DocumentRepository
repo = DocumentRepository()
assert hasattr(repo, "update_category")
def test_update_request_schema(self):
"""Test DocumentUpdateRequest can update category."""
from inference.web.schemas.admin import DocumentUpdateRequest
from backend.web.schemas.admin import DocumentUpdateRequest
request = DocumentUpdateRequest(category="receipt")
assert request.category == "receipt"

View File

@@ -11,8 +11,8 @@ from fastapi.testclient import TestClient
from PIL import Image
import io
from inference.web.app import create_app
from inference.web.config import ModelConfig, StorageConfig, AppConfig
from backend.web.app import create_app
from backend.web.config import ModelConfig, StorageConfig, AppConfig
@pytest.fixture
@@ -87,8 +87,8 @@ class TestHealthEndpoint:
class TestInferEndpoint:
"""Test /api/v1/infer endpoint."""
@patch('inference.pipeline.pipeline.InferencePipeline')
@patch('inference.pipeline.yolo_detector.YOLODetector')
@patch('backend.pipeline.pipeline.InferencePipeline')
@patch('backend.pipeline.yolo_detector.YOLODetector')
def test_infer_accepts_png_file(
self,
mock_yolo_detector,
@@ -150,8 +150,8 @@ class TestInferEndpoint:
assert response.status_code == 422 # Unprocessable Entity
@patch('inference.pipeline.pipeline.InferencePipeline')
@patch('inference.pipeline.yolo_detector.YOLODetector')
@patch('backend.pipeline.pipeline.InferencePipeline')
@patch('backend.pipeline.yolo_detector.YOLODetector')
def test_infer_returns_cross_validation_if_available(
self,
mock_yolo_detector,
@@ -210,8 +210,8 @@ class TestInferEndpoint:
# This test documents that it should be added
@patch('inference.pipeline.pipeline.InferencePipeline')
@patch('inference.pipeline.yolo_detector.YOLODetector')
@patch('backend.pipeline.pipeline.InferencePipeline')
@patch('backend.pipeline.yolo_detector.YOLODetector')
def test_infer_handles_processing_errors_gracefully(
self,
mock_yolo_detector,
@@ -263,7 +263,7 @@ class TestResultsEndpoint:
# Mock the storage helper to return our test file path
with patch(
"inference.web.api.v1.public.inference.get_storage_helper"
"backend.web.api.v1.public.inference.get_storage_helper"
) as mock_storage:
mock_helper = Mock()
mock_helper.get_result_local_path.return_value = result_file
@@ -285,15 +285,15 @@ class TestInferenceServiceImports:
This test will fail if there are ImportError issues like:
- from ..inference.pipeline (wrong relative import)
- from inference.web.inference (non-existent module)
- from backend.web.inference (non-existent module)
It ensures the imports are correct before runtime.
"""
from inference.web.services.inference import InferenceService
from backend.web.services.inference import InferenceService
# Import the modules that InferenceService tries to import
from inference.pipeline.pipeline import InferencePipeline
from inference.pipeline.yolo_detector import YOLODetector
from backend.pipeline.pipeline import InferencePipeline
from backend.pipeline.yolo_detector import YOLODetector
from shared.pdf.renderer import render_pdf_to_images
# If we got here, all imports work correctly

View File

@@ -10,8 +10,8 @@ from unittest.mock import Mock, patch
from PIL import Image
import io
from inference.web.services.inference import InferenceService
from inference.web.config import ModelConfig, StorageConfig
from backend.web.services.inference import InferenceService
from backend.web.config import ModelConfig, StorageConfig
@pytest.fixture
@@ -72,8 +72,8 @@ class TestInferenceServiceInitialization:
gpu_available = inference_service.gpu_available
assert isinstance(gpu_available, bool)
@patch('inference.pipeline.pipeline.InferencePipeline')
@patch('inference.pipeline.yolo_detector.YOLODetector')
@patch('backend.pipeline.pipeline.InferencePipeline')
@patch('backend.pipeline.yolo_detector.YOLODetector')
def test_initialize_imports_correctly(
self,
mock_yolo_detector,
@@ -102,8 +102,8 @@ class TestInferenceServiceInitialization:
mock_yolo_detector.assert_called_once()
mock_pipeline.assert_called_once()
@patch('inference.pipeline.pipeline.InferencePipeline')
@patch('inference.pipeline.yolo_detector.YOLODetector')
@patch('backend.pipeline.pipeline.InferencePipeline')
@patch('backend.pipeline.yolo_detector.YOLODetector')
def test_initialize_sets_up_pipeline(
self,
mock_yolo_detector,
@@ -135,8 +135,8 @@ class TestInferenceServiceInitialization:
enable_fallback=True,
)
@patch('inference.pipeline.pipeline.InferencePipeline')
@patch('inference.pipeline.yolo_detector.YOLODetector')
@patch('backend.pipeline.pipeline.InferencePipeline')
@patch('backend.pipeline.yolo_detector.YOLODetector')
def test_initialize_idempotent(
self,
mock_yolo_detector,
@@ -161,8 +161,8 @@ class TestInferenceServiceInitialization:
class TestInferenceServiceProcessing:
"""Test inference processing methods."""
@patch('inference.pipeline.pipeline.InferencePipeline')
@patch('inference.pipeline.yolo_detector.YOLODetector')
@patch('backend.pipeline.pipeline.InferencePipeline')
@patch('backend.pipeline.yolo_detector.YOLODetector')
@patch('ultralytics.YOLO')
def test_process_image_basic_flow(
self,
@@ -197,8 +197,8 @@ class TestInferenceServiceProcessing:
assert result.confidence == {"InvoiceNumber": 0.95}
assert result.processing_time_ms > 0
@patch('inference.pipeline.pipeline.InferencePipeline')
@patch('inference.pipeline.yolo_detector.YOLODetector')
@patch('backend.pipeline.pipeline.InferencePipeline')
@patch('backend.pipeline.yolo_detector.YOLODetector')
def test_process_image_handles_errors(
self,
mock_yolo_detector,
@@ -228,8 +228,8 @@ class TestInferenceServiceProcessing:
class TestInferenceServicePDFRendering:
"""Test PDF rendering imports."""
@patch('inference.pipeline.pipeline.InferencePipeline')
@patch('inference.pipeline.yolo_detector.YOLODetector')
@patch('backend.pipeline.pipeline.InferencePipeline')
@patch('backend.pipeline.yolo_detector.YOLODetector')
@patch('shared.pdf.renderer.render_pdf_to_images')
@patch('ultralytics.YOLO')
def test_pdf_visualization_imports_correctly(

View File

@@ -9,9 +9,9 @@ from uuid import UUID
import pytest
from inference.data.admin_models import ModelVersion
from inference.web.api.v1.admin.training import create_training_router
from inference.web.schemas.admin import (
from backend.data.admin_models import ModelVersion
from backend.web.api.v1.admin.training import create_training_router
from backend.web.schemas.admin import (
ModelVersionCreateRequest,
ModelVersionUpdateRequest,
)
@@ -173,13 +173,16 @@ class TestGetActiveModelRoute:
def test_get_active_model_when_exists(self, mock_models_repo):
fn = _find_endpoint("get_active_model")
mock_models_repo.get_active.return_value = _make_model_version(status="active", is_active=True)
mock_model = _make_model_version(status="active", is_active=True)
mock_models_repo.get_active.return_value = mock_model
result = asyncio.run(fn(admin_token=TEST_TOKEN, models=mock_models_repo))
assert result.has_active_model is True
assert result.model is not None
# model is now a ModelVersionItem, not ModelVersion
assert result.model.is_active is True
assert result.model.version == "1.0.0"
def test_get_active_model_when_none(self, mock_models_repo):
fn = _find_endpoint("get_active_model")

View File

@@ -8,8 +8,8 @@ from unittest.mock import MagicMock
import pytest
from inference.data.async_request_db import ApiKeyConfig
from inference.web.rate_limiter import RateLimiter, RateLimitConfig, RateLimitStatus
from backend.data.async_request_db import ApiKeyConfig
from backend.web.rate_limiter import RateLimiter, RateLimitConfig, RateLimitStatus
class TestRateLimiter:

View File

@@ -3,7 +3,7 @@
import pytest
from unittest.mock import MagicMock, patch
from inference.web.services.storage_helpers import StorageHelper, get_storage_helper
from backend.web.services.storage_helpers import StorageHelper, get_storage_helper
from shared.storage import PREFIXES
@@ -402,10 +402,10 @@ class TestGetStorageHelper:
def test_returns_helper_instance(self) -> None:
"""Should return a StorageHelper instance."""
with patch("inference.web.services.storage_helpers.get_default_storage") as mock_get:
with patch("backend.web.services.storage_helpers.get_default_storage") as mock_get:
mock_get.return_value = MagicMock()
# Reset the global helper
import inference.web.services.storage_helpers as module
import backend.web.services.storage_helpers as module
module._default_helper = None
helper = get_storage_helper()
@@ -414,9 +414,9 @@ class TestGetStorageHelper:
def test_returns_same_instance(self) -> None:
"""Should return the same instance on subsequent calls."""
with patch("inference.web.services.storage_helpers.get_default_storage") as mock_get:
with patch("backend.web.services.storage_helpers.get_default_storage") as mock_get:
mock_get.return_value = MagicMock()
import inference.web.services.storage_helpers as module
import backend.web.services.storage_helpers as module
module._default_helper = None
helper1 = get_storage_helper()

View File

@@ -18,7 +18,7 @@ class TestStorageBackendInitialization:
"""Test that get_storage_backend returns a StorageBackend instance."""
from shared.storage.base import StorageBackend
from inference.web.config import get_storage_backend
from backend.web.config import get_storage_backend
env = {
"STORAGE_BACKEND": "local",
@@ -36,7 +36,7 @@ class TestStorageBackendInitialization:
"""Test that storage config file is used when present."""
from shared.storage.local import LocalStorageBackend
from inference.web.config import get_storage_backend
from backend.web.config import get_storage_backend
config_file = tmp_path / "storage.yaml"
storage_path = tmp_path / "storage"
@@ -55,7 +55,7 @@ local:
"""Test fallback to environment variables when no config file."""
from shared.storage.local import LocalStorageBackend
from inference.web.config import get_storage_backend
from backend.web.config import get_storage_backend
env = {
"STORAGE_BACKEND": "local",
@@ -71,7 +71,7 @@ local:
"""Test that AppConfig can be created with storage backend."""
from shared.storage.base import StorageBackend
from inference.web.config import AppConfig, create_app_config
from backend.web.config import AppConfig, create_app_config
env = {
"STORAGE_BACKEND": "local",
@@ -103,7 +103,7 @@ class TestStorageBackendInDocumentUpload:
# Create a mock upload file
pdf_content = b"%PDF-1.4 test content"
from inference.web.services.document_service import DocumentService
from backend.web.services.document_service import DocumentService
service = DocumentService(admin_db=mock_admin_db, storage_backend=backend)
@@ -130,7 +130,7 @@ class TestStorageBackendInDocumentUpload:
pdf_content = b"%PDF-1.4 test content"
from inference.web.services.document_service import DocumentService
from backend.web.services.document_service import DocumentService
service = DocumentService(admin_db=mock_admin_db, storage_backend=backend)
@@ -163,7 +163,7 @@ class TestStorageBackendInDocumentDownload:
doc_path = "documents/test-doc.pdf"
backend.upload_bytes(b"%PDF-1.4 test", doc_path)
from inference.web.services.document_service import DocumentService
from backend.web.services.document_service import DocumentService
service = DocumentService(admin_db=mock_admin_db, storage_backend=backend)
@@ -188,7 +188,7 @@ class TestStorageBackendInDocumentDownload:
original_content = b"%PDF-1.4 test content"
backend.upload_bytes(original_content, doc_path)
from inference.web.services.document_service import DocumentService
from backend.web.services.document_service import DocumentService
service = DocumentService(admin_db=mock_admin_db, storage_backend=backend)
@@ -214,7 +214,7 @@ class TestStorageBackendInImageServing:
image_path = "images/doc-123/page_1.png"
backend.upload_bytes(b"fake png content", image_path)
from inference.web.services.document_service import DocumentService
from backend.web.services.document_service import DocumentService
service = DocumentService(admin_db=mock_admin_db, storage_backend=backend)
@@ -233,7 +233,7 @@ class TestStorageBackendInImageServing:
storage_path.mkdir(parents=True, exist_ok=True)
backend = LocalStorageBackend(str(storage_path))
from inference.web.services.document_service import DocumentService
from backend.web.services.document_service import DocumentService
service = DocumentService(admin_db=mock_admin_db, storage_backend=backend)
@@ -261,7 +261,7 @@ class TestStorageBackendInDocumentDeletion:
doc_path = "documents/test-doc.pdf"
backend.upload_bytes(b"%PDF-1.4 test", doc_path)
from inference.web.services.document_service import DocumentService
from backend.web.services.document_service import DocumentService
service = DocumentService(admin_db=mock_admin_db, storage_backend=backend)
@@ -284,7 +284,7 @@ class TestStorageBackendInDocumentDeletion:
backend.upload_bytes(b"img1", f"images/{doc_id}/page_1.png")
backend.upload_bytes(b"img2", f"images/{doc_id}/page_2.png")
from inference.web.services.document_service import DocumentService
from backend.web.services.document_service import DocumentService
service = DocumentService(admin_db=mock_admin_db, storage_backend=backend)

View File

@@ -9,8 +9,8 @@ from uuid import uuid4
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inference.web.api.v1.admin.training import create_training_router
from inference.web.core.auth import (
from backend.web.api.v1.admin.training import create_training_router
from backend.web.core.auth import (
validate_admin_token,
get_document_repository,
get_annotation_repository,