chore: eliminate all deprecation warnings from tests and linter
Warnings fixed: - datetime.utcnow() → datetime.now(UTC) across 48+ files (src/ + tests/) - datetime.utcnow (callback ref) → lambda: datetime.now(UTC) in model fields (18 files) - Pydantic class Config → model_config = ConfigDict(...) (16 files) - Pydantic .dict() → .model_dump() (8 files) - ConfigDict(allow_population_by_field_name=True) → validate_by_name=True - SQLAlchemy declarative_base() import path updated - FastAPI on_event → lifespan context manager (app.py) - Import sorting (ruff I001) auto-fixed across all files - Fixed broken re-export chains that ruff F401 cleanup broke: _validate_bcp47: service.py now imports from dictionary_validation directly job_to_response: _job_routes.py and test imports from service_utils directly fetch_datasource_metadata: restored re-export in service.py - Added missing TranslateJobService import in _job_routes.py (was deleted by F401) - Added ConfigDict(protected_namespaces=()) for DashboardDatasetItem schema field - pytest.ini: replaced deprecated importmode with asyncio_mode All 440 tests pass with zero deprecation warnings.
This commit is contained in:
@@ -10,20 +10,13 @@
|
||||
# @TEST_EDGE: missing_tables -> 422 validation error
|
||||
# @TEST_EDGE: end_time_before_start_time -> 400 validation error
|
||||
# @TEST_EDGE: non_existent_event_end -> 404 not found
|
||||
import json
|
||||
import os
|
||||
import uuid
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, MagicMock, patch, PropertyMock
|
||||
|
||||
from datetime import UTC, datetime, timedelta
|
||||
import pytest
|
||||
from fastapi import status
|
||||
|
||||
# Patch GitService at module level to prevent /app/storage/repositories error
|
||||
# This patches the base module BEFORE any imports can reach it
|
||||
import sys
|
||||
from unittest.mock import MagicMock
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
_mock_git_svc_cls = MagicMock()
|
||||
_mock_git_svc_cls.return_value = MagicMock()
|
||||
@@ -37,6 +30,7 @@ sys.modules['src.services.git_service'] = MagicMock(GitService=_mock_git_svc_cls
|
||||
def client():
|
||||
"""Create a TestClient with all dependencies mocked."""
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from src.app import app
|
||||
return TestClient(app)
|
||||
|
||||
@@ -44,10 +38,10 @@ def client():
|
||||
@pytest.fixture(autouse=True)
|
||||
def auth_mock(client, mock_db):
|
||||
"""Create a valid API key with maintenance permissions and mock JWT user."""
|
||||
from src.core.auth.api_key import generate_api_key
|
||||
from src.models.api_key import APIKey
|
||||
from src.dependencies import get_current_user
|
||||
from src.app import app
|
||||
from src.core.auth.api_key import generate_api_key
|
||||
from src.dependencies import get_current_user
|
||||
from src.models.api_key import APIKey
|
||||
|
||||
# Create API key for mutation endpoints
|
||||
raw, prefix, key_hash = generate_api_key()
|
||||
@@ -93,11 +87,12 @@ def mock_db():
|
||||
Creates all tables on the shared Base.metadata.
|
||||
"""
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker, Session as SASession
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.pool import StaticPool
|
||||
from src.models.mapping import Base
|
||||
|
||||
from src.dependencies import get_db
|
||||
from src.models.maintenance import MaintenanceSettings, DashboardScope
|
||||
from src.models.maintenance import DashboardScope, MaintenanceSettings
|
||||
from src.models.mapping import Base
|
||||
|
||||
# StaticPool ensures all sessions share the same in-memory connection
|
||||
engine = create_engine(
|
||||
@@ -165,8 +160,8 @@ class TestStartEndpoint:
|
||||
"/api/maintenance/start",
|
||||
json={
|
||||
"tables": ["raw.sales"],
|
||||
"start_time": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),
|
||||
"end_time": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(),
|
||||
"start_time": (datetime.now(UTC) + timedelta(hours=1)).isoformat(),
|
||||
"end_time": (datetime.now(UTC) + timedelta(hours=3)).isoformat(),
|
||||
"message": "Test maintenance",
|
||||
"environment_id": "test-env",
|
||||
},
|
||||
@@ -184,7 +179,7 @@ class TestStartEndpoint:
|
||||
response = client.post(
|
||||
"/api/maintenance/start",
|
||||
json={
|
||||
"start_time": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),
|
||||
"start_time": (datetime.now(UTC) + timedelta(hours=1)).isoformat(),
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
@@ -197,8 +192,8 @@ class TestStartEndpoint:
|
||||
"/api/maintenance/start",
|
||||
json={
|
||||
"tables": ["raw.sales"],
|
||||
"start_time": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(),
|
||||
"end_time": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),
|
||||
"start_time": (datetime.now(UTC) + timedelta(hours=3)).isoformat(),
|
||||
"end_time": (datetime.now(UTC) + timedelta(hours=1)).isoformat(),
|
||||
"environment_id": "test-env",
|
||||
},
|
||||
)
|
||||
@@ -213,7 +208,7 @@ class TestStartEndpoint:
|
||||
"/api/maintenance/start",
|
||||
json={
|
||||
"tables": tables,
|
||||
"start_time": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),
|
||||
"start_time": (datetime.now(UTC) + timedelta(hours=1)).isoformat(),
|
||||
"environment_id": "test-env",
|
||||
},
|
||||
)
|
||||
@@ -227,8 +222,8 @@ class TestStartEndpoint:
|
||||
|
||||
payload = {
|
||||
"tables": ["raw.sales"],
|
||||
"start_time": (datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),
|
||||
"end_time": (datetime.now(timezone.utc) + timedelta(hours=3)).isoformat(),
|
||||
"start_time": (datetime.now(UTC) + timedelta(hours=1)).isoformat(),
|
||||
"end_time": (datetime.now(UTC) + timedelta(hours=3)).isoformat(),
|
||||
"environment_id": "test-env",
|
||||
}
|
||||
|
||||
@@ -266,7 +261,7 @@ class TestEndEndpoint:
|
||||
|
||||
event = MaintenanceEvent(
|
||||
tables=["raw.sales"],
|
||||
start_time=datetime.now(timezone.utc),
|
||||
start_time=datetime.now(UTC),
|
||||
status=MaintenanceEventStatus.ACTIVE,
|
||||
environment_id="test-env",
|
||||
)
|
||||
@@ -315,7 +310,7 @@ class TestEventsEndpoint:
|
||||
|
||||
active = MaintenanceEvent(
|
||||
tables=["raw.active"],
|
||||
start_time=datetime.now(timezone.utc),
|
||||
start_time=datetime.now(UTC),
|
||||
status=MaintenanceEventStatus.ACTIVE,
|
||||
environment_id="test-env",
|
||||
)
|
||||
@@ -323,7 +318,7 @@ class TestEventsEndpoint:
|
||||
|
||||
completed = MaintenanceEvent(
|
||||
tables=["raw.done"],
|
||||
start_time=datetime.now(timezone.utc),
|
||||
start_time=datetime.now(UTC),
|
||||
status=MaintenanceEventStatus.COMPLETED,
|
||||
environment_id="test-env",
|
||||
)
|
||||
@@ -340,13 +335,14 @@ class TestEventsEndpoint:
|
||||
# #region test_expired_event_auto_ends [C:2] [TYPE Function]
|
||||
# @BRIEF Event past end_time with ACTIVE status → create_task called with auto-end params.
|
||||
def test_expired_event_auto_ends(self, client, mock_db, mock_task_manager):
|
||||
from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus
|
||||
from datetime import timedelta
|
||||
|
||||
from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus
|
||||
|
||||
event = MaintenanceEvent(
|
||||
tables=["raw.sales"],
|
||||
start_time=datetime.now(timezone.utc) - timedelta(hours=2),
|
||||
end_time=datetime.now(timezone.utc) - timedelta(hours=1),
|
||||
start_time=datetime.now(UTC) - timedelta(hours=2),
|
||||
end_time=datetime.now(UTC) - timedelta(hours=1),
|
||||
message="Expired maintenance",
|
||||
status=MaintenanceEventStatus.ACTIVE,
|
||||
environment_id="test-env",
|
||||
@@ -371,13 +367,14 @@ class TestEventsEndpoint:
|
||||
# #region test_future_end_time_skipped [C:2] [TYPE Function]
|
||||
# @BRIEF Event with future end_time → no task created, skipped by < now filter.
|
||||
def test_future_end_time_skipped(self, client, mock_db, mock_task_manager):
|
||||
from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus
|
||||
from datetime import timedelta
|
||||
|
||||
from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus
|
||||
|
||||
event = MaintenanceEvent(
|
||||
tables=["raw.sales"],
|
||||
start_time=datetime.now(timezone.utc) + timedelta(hours=1),
|
||||
end_time=datetime.now(timezone.utc) + timedelta(hours=3),
|
||||
start_time=datetime.now(UTC) + timedelta(hours=1),
|
||||
end_time=datetime.now(UTC) + timedelta(hours=3),
|
||||
message="Future maintenance",
|
||||
status=MaintenanceEventStatus.ACTIVE,
|
||||
environment_id="test-env",
|
||||
@@ -394,12 +391,13 @@ class TestEventsEndpoint:
|
||||
# #region test_no_end_time_skipped [C:2] [TYPE Function]
|
||||
# @BRIEF Event with end_time=None → no task created, skipped by isnot(None) filter.
|
||||
def test_no_end_time_skipped(self, client, mock_db, mock_task_manager):
|
||||
from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus
|
||||
from datetime import timedelta
|
||||
|
||||
from src.models.maintenance import MaintenanceEvent, MaintenanceEventStatus
|
||||
|
||||
event = MaintenanceEvent(
|
||||
tables=["raw.sales"],
|
||||
start_time=datetime.now(timezone.utc) - timedelta(hours=2),
|
||||
start_time=datetime.now(UTC) - timedelta(hours=2),
|
||||
end_time=None,
|
||||
message="No end time",
|
||||
status=MaintenanceEventStatus.ACTIVE,
|
||||
|
||||
Reference in New Issue
Block a user