chore(lint): apply ruff --fix (4443 auto-fixes)

Auto-fixed categories:
- F401: unused imports removed
- I001: import blocks sorted
- W293: trailing whitespace stripped
- UP035: deprecated typing imports replaced
- SIM: simplify suggestions applied
- ARG: unused args prefixed with underscore
- T201: print statements removed
- F841: unused variables removed
- RUF059: unpacked variables prefixed

Remaining ~1500 unfixable errors (C901, B904, N806, E402) require manual work.

Backend smoke tests: 13/13 passed.
This commit is contained in:
2026-05-14 11:20:17 +03:00
parent a9a5eff518
commit c6189876b3
337 changed files with 4677 additions and 4515 deletions

View File

@@ -7,8 +7,8 @@ from __future__ import annotations
import argparse
import json
from datetime import date, datetime, timezone
from typing import Any, Dict, List, Optional
from datetime import UTC, date, datetime
from typing import Any
from ..core.cot_logger import seed_trace_id
from ..models.clean_release import CandidateArtifact, ReleaseCandidate
@@ -119,7 +119,7 @@ def run_candidate_register(args: argparse.Namespace) -> int:
version=args.version,
source_snapshot_ref=args.source_snapshot_ref,
created_by=args.created_by,
created_at=datetime.now(timezone.utc),
created_at=datetime.now(UTC),
status=CandidateStatus.DRAFT.value,
)
repository.save_candidate(candidate)
@@ -216,7 +216,7 @@ def run_compliance_run(args: argparse.Namespace) -> int:
requested_by=args.actor,
manifest_id=args.manifest_id,
)
except Exception as exc: # noqa: BLE001
except Exception as exc:
print(json.dumps({"status": "error", "message": str(exc)}))
return 2
@@ -272,7 +272,7 @@ def run_compliance_status(args: argparse.Namespace) -> int:
# @BRIEF Serialize domain models for CLI JSON output across SQLAlchemy/Pydantic variants.
# @PRE: value is serializable model or primitive object.
# @POST: Returns dictionary payload without mutating value.
def _to_payload(value: Any) -> Dict[str, Any]:
def _to_payload(value: Any) -> dict[str, Any]:
def _normalize(raw: Any) -> Any:
if isinstance(raw, datetime):
return raw.isoformat()
@@ -366,7 +366,7 @@ def run_approve(args: argparse.Namespace) -> int:
decided_by=args.actor,
comment=args.comment,
)
except Exception as exc: # noqa: BLE001
except Exception as exc:
print(json.dumps({"status": "error", "message": str(exc)}))
return 2
@@ -397,7 +397,7 @@ def run_reject(args: argparse.Namespace) -> int:
decided_by=args.actor,
comment=args.comment,
)
except Exception as exc: # noqa: BLE001
except Exception as exc:
print(json.dumps({"status": "error", "message": str(exc)}))
return 2
@@ -429,7 +429,7 @@ def run_publish(args: argparse.Namespace) -> int:
target_channel=args.target_channel,
publication_ref=args.publication_ref,
)
except Exception as exc: # noqa: BLE001
except Exception as exc:
print(json.dumps({"status": "error", "message": str(exc)}))
return 2
@@ -455,7 +455,7 @@ def run_revoke(args: argparse.Namespace) -> int:
revoked_by=args.actor,
comment=args.comment,
)
except Exception as exc: # noqa: BLE001
except Exception as exc:
print(json.dumps({"status": "error", "message": str(exc)}))
return 2
@@ -468,7 +468,7 @@ def run_revoke(args: argparse.Namespace) -> int:
# #region main [TYPE Function]
# @BRIEF CLI entrypoint for clean release commands.
def main(argv: Optional[List[str]] = None) -> int:
def main(argv: list[str] | None = None) -> int:
seed_trace_id()
parser = build_parser()
args = parser.parse_args(argv)

View File

@@ -9,9 +9,9 @@ import curses
import json
import os
import sys
from datetime import datetime, timezone
from datetime import UTC, datetime
from types import SimpleNamespace
from typing import List, Optional, Any, Dict
from typing import Any
# Standardize sys.path for direct execution from project root or scripts dir.
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -28,11 +28,11 @@ from src.models.clean_release import (
CleanProfilePolicy,
ComplianceViolation,
ProfileType,
RegistryStatus,
ReleaseCandidate,
ReleaseCandidateStatus,
ResourceSourceEntry,
ResourceSourceRegistry,
RegistryStatus,
ReleaseCandidateStatus,
)
from src.services.clean_release.approval_service import approve_candidate
from src.services.clean_release.artifact_catalog_loader import load_bootstrap_artifacts
@@ -124,7 +124,7 @@ class TuiFacadeAdapter:
created_by=actor,
)
def get_overview(self, *, candidate_id: str) -> Dict[str, Any]:
def get_overview(self, *, candidate_id: str) -> dict[str, Any]:
candidate = self.repository.get_candidate(candidate_id)
manifests = self.repository.get_manifests_by_candidate(candidate_id)
latest_manifest = (
@@ -206,11 +206,11 @@ class CleanReleaseTUI:
self.facade = TuiFacadeAdapter(self.repo)
self.candidate_id = self._resolve_candidate_id()
self.status: Any = "READY"
self.checks_progress: List[Dict[str, Any]] = []
self.violations_list: List[ComplianceViolation] = []
self.report_id: Optional[str] = None
self.last_error: Optional[str] = None
self.overview: Dict[str, Any] = {}
self.checks_progress: list[dict[str, Any]] = []
self.violations_list: list[ComplianceViolation] = []
self.report_id: str | None = None
self.last_error: str | None = None
self.overview: dict[str, Any] = {}
self.refresh_overview()
curses.start_color()
@@ -230,7 +230,7 @@ class CleanReleaseTUI:
return repo
def _bootstrap_demo_repository(self, repository: CleanReleaseRepository) -> None:
now = datetime.now(timezone.utc)
now = datetime.now(UTC)
policy = CleanProfilePolicy(
policy_id="POL-ENT-CLEAN",
policy_version="1",
@@ -240,7 +240,7 @@ class CleanReleaseTUI:
prohibited_artifact_categories=["test-data"],
effective_from=now,
)
setattr(policy, "immutable", True)
policy.immutable = True
repository.save_policy(policy)
registry = ResourceSourceRegistry(
@@ -257,10 +257,10 @@ class CleanReleaseTUI:
updated_at=now,
updated_by="system",
)
setattr(registry, "immutable", True)
setattr(registry, "allowed_hosts", ["internal-repo.company.com"])
setattr(registry, "allowed_schemes", ["https"])
setattr(registry, "allowed_source_types", ["artifactory"])
registry.immutable = True
registry.allowed_hosts = ["internal-repo.company.com"]
registry.allowed_schemes = ["https"]
registry.allowed_source_types = ["artifactory"]
repository.save_registry(registry)
candidate = ReleaseCandidate(
id="2026.03.03-rc1",
@@ -307,10 +307,10 @@ class CleanReleaseTUI:
if not bootstrap_path:
return
with open(bootstrap_path, "r", encoding="utf-8") as bootstrap_file:
with open(bootstrap_path, encoding="utf-8") as bootstrap_file:
payload = json.load(bootstrap_file)
now = datetime.now(timezone.utc)
now = datetime.now(UTC)
candidate = ReleaseCandidate(
id=payload.get("candidate_id", "candidate-1"),
version=payload.get("version", "1.0.0"),
@@ -523,7 +523,7 @@ class CleanReleaseTUI:
result = self.facade.run_compliance(
candidate_id=self.candidate_id, actor="operator"
)
except Exception as exc: # noqa: BLE001
except Exception as exc:
self.status = CheckFinalStatus.FAILED
self.last_error = str(exc)
self.refresh_screen()
@@ -563,7 +563,7 @@ class CleanReleaseTUI:
self.violations_list = []
self.checks_progress = []
self.last_error = f"Manifest built: {manifest.id}"
except Exception as exc: # noqa: BLE001
except Exception as exc:
self.last_error = str(exc)
self.refresh_overview()
self.refresh_screen()
@@ -585,7 +585,7 @@ class CleanReleaseTUI:
try:
self.facade.approve_latest(candidate_id=self.candidate_id, actor="operator")
self.last_error = None
except Exception as exc: # noqa: BLE001
except Exception as exc:
self.last_error = str(exc)
self.refresh_overview()
self.refresh_screen()
@@ -598,7 +598,7 @@ class CleanReleaseTUI:
try:
self.facade.publish_latest(candidate_id=self.candidate_id, actor="operator")
self.last_error = None
except Exception as exc: # noqa: BLE001
except Exception as exc:
self.last_error = str(exc)
self.refresh_overview()
self.refresh_screen()
@@ -611,7 +611,7 @@ class CleanReleaseTUI:
try:
self.facade.publish_latest(candidate_id=self.candidate_id, actor="operator")
self.last_error = None
except Exception as exc: # noqa: BLE001
except Exception as exc:
self.last_error = str(exc)
self.refresh_overview()
self.refresh_screen()

View File

@@ -8,18 +8,18 @@
#
# @INVARIANT: Admin user must have the "Admin" role.
import sys
import argparse
import sys
from pathlib import Path
# Add src to path
sys.path.append(str(Path(__file__).parent.parent.parent))
from src.core.database import AuthSessionLocal, init_db
from src.core.auth.security import get_password_hash
from src.models.auth import User, Role
from src.core.logger import logger, belief_scope
from src.core.cot_logger import seed_trace_id
from src.core.database import AuthSessionLocal, init_db
from src.core.logger import belief_scope, logger
from src.models.auth import Role, User
# #region create_admin [TYPE Function]

View File

@@ -14,10 +14,10 @@ from pathlib import Path
# Add src to path
sys.path.append(str(Path(__file__).parent.parent.parent))
from src.core.cot_logger import seed_trace_id
from src.core.database import init_db
from src.core.encryption_key import ensure_encryption_key
from src.core.logger import logger, belief_scope
from src.core.cot_logger import seed_trace_id
from src.core.logger import belief_scope, logger
from src.scripts.seed_permissions import seed_permissions

View File

@@ -14,15 +14,15 @@ import argparse
import json
import os
import sqlite3
from collections.abc import Iterable
from pathlib import Path
from typing import Any, Dict, Iterable, Optional
from typing import Any
from sqlalchemy import create_engine, text
from sqlalchemy.exc import SQLAlchemyError
from src.core.logger import belief_scope, logger
from src.core.cot_logger import seed_trace_id
from src.core.logger import belief_scope, logger
# #region Constants [TYPE Section]
DEFAULT_TARGET_URL = os.getenv(
@@ -62,7 +62,7 @@ def _json_load_if_needed(value: Any) -> Any:
# #region _find_legacy_config_path [TYPE Function]
# @BRIEF Resolves the existing legacy config.json path from candidates.
def _find_legacy_config_path(explicit_path: Optional[str]) -> Optional[Path]:
def _find_legacy_config_path(explicit_path: str | None) -> Path | None:
with belief_scope("_find_legacy_config_path"):
if explicit_path:
p = Path(explicit_path)
@@ -162,7 +162,7 @@ def _ensure_target_schema(engine) -> None:
# #region _migrate_config [TYPE Function]
# @BRIEF Migrates legacy config.json into app_configurations(global).
def _migrate_config(engine, legacy_config_path: Optional[Path]) -> int:
def _migrate_config(engine, legacy_config_path: Path | None) -> int:
with belief_scope("_migrate_config"):
if legacy_config_path is None:
logger.reason(
@@ -196,7 +196,7 @@ def _migrate_config(engine, legacy_config_path: Optional[Path]) -> int:
# #region _migrate_tasks_and_logs [TYPE Function]
# @BRIEF Migrates task_records and task_logs from SQLite into PostgreSQL.
def _migrate_tasks_and_logs(engine, sqlite_conn: sqlite3.Connection) -> Dict[str, int]:
def _migrate_tasks_and_logs(engine, sqlite_conn: sqlite3.Connection) -> dict[str, int]:
with belief_scope("_migrate_tasks_and_logs"):
stats = {
"task_records_total": 0,
@@ -326,8 +326,8 @@ def _migrate_tasks_and_logs(engine, sqlite_conn: sqlite3.Connection) -> Dict[str
# #region run_migration [TYPE Function]
# @BRIEF Orchestrates migration from SQLite/file to PostgreSQL.
def run_migration(
sqlite_path: Path, target_url: str, legacy_config_path: Optional[Path]
) -> Dict[str, int]:
sqlite_path: Path, target_url: str, legacy_config_path: Path | None
) -> dict[str, int]:
seed_trace_id()
with belief_scope("run_migration"):
logger.reason(

View File

@@ -15,11 +15,11 @@ from pathlib import Path
# Add src to path
sys.path.append(str(Path(__file__).parent.parent.parent))
from src.core.database import AuthSessionLocal
from src.models.auth import Permission, Role
from src.core.auth.repository import AuthRepository
from src.core.logger import logger, belief_scope
from src.core.cot_logger import seed_trace_id
from src.core.database import AuthSessionLocal
from src.core.logger import belief_scope, logger
from src.models.auth import Permission, Role
# #region INITIAL_PERMISSIONS [C:3] [TYPE Constant]
# @BRIEF Canonical bootstrap permission tuples seeded into auth storage.

View File

@@ -12,14 +12,13 @@ import random
import sys
import uuid
from pathlib import Path
from typing import Dict, List, Optional
sys.path.append(str(Path(__file__).parent.parent.parent))
from src.core.config_manager import ConfigManager
from src.core.config_models import Environment
from src.core.logger import belief_scope, logger
from src.core.cot_logger import seed_trace_id
from src.core.logger import belief_scope, logger
from src.core.superset_client import SupersetClient
@@ -71,7 +70,7 @@ def _parse_args() -> argparse.Namespace:
# @BRIEF Normalizes Superset API payloads that may be wrapped in `result`.
# @PRE: payload is a JSON-decoded API response.
# @POST: Returns the unwrapped object when present.
def _extract_result_payload(payload: Dict) -> Dict:
def _extract_result_payload(payload: dict) -> dict:
result = payload.get("result")
if isinstance(result, dict):
return result
@@ -85,7 +84,7 @@ def _extract_result_payload(payload: Dict) -> Dict:
# @BRIEF Extracts object ID from create/update API response.
# @PRE: payload is a JSON-decoded API response.
# @POST: Returns integer object ID or None if missing.
def _extract_created_id(payload: Dict) -> Optional[int]:
def _extract_created_id(payload: dict) -> int | None:
direct_id = payload.get("id")
if isinstance(direct_id, int):
return direct_id
@@ -142,10 +141,10 @@ def _generate_unique_name(prefix: str, used_names: set[str], rng: random.Random)
# @BRIEF Resolves requested environment IDs from configuration.
# @PRE: env_ids is non-empty.
# @POST: Returns mapping env_id -> configured environment object.
def _resolve_target_envs(env_ids: List[str]) -> Dict[str, Environment]:
def _resolve_target_envs(env_ids: list[str]) -> dict[str, Environment]:
config_manager = ConfigManager()
configured = {env.id: env for env in config_manager.get_environments()}
resolved: Dict[str, Environment] = {}
resolved: dict[str, Environment] = {}
if not configured:
for config_path in [Path("config.json"), Path("backend/config.json")]:
@@ -181,7 +180,7 @@ def _resolve_target_envs(env_ids: List[str]) -> Dict[str, Environment]:
# @POST: Returns non-empty list of chart payload templates.
def _build_chart_template_pool(
client: SupersetClient, pool_size: int, rng: random.Random
) -> List[Dict]:
) -> list[dict]:
list_query = {
"page": 0,
"page_size": 1000,
@@ -209,7 +208,7 @@ def _build_chart_template_pool(
if len(candidates) <= pool_size
else rng.sample(candidates, pool_size)
)
templates: List[Dict] = []
templates: list[dict] = []
for row in selected:
chart_id = int(row["id"])
@@ -255,15 +254,15 @@ def _build_chart_template_pool(
# @PRE: Target environments must be reachable and authenticated.
# @POST: Returns execution statistics dictionary.
# @SIDE_EFFECT: Creates objects in Superset environments.
def seed_superset_load_data(args: argparse.Namespace) -> Dict:
def seed_superset_load_data(args: argparse.Namespace) -> dict:
seed_trace_id()
rng = random.Random(args.seed)
env_map = _resolve_target_envs(args.envs)
clients: Dict[str, SupersetClient] = {}
templates_by_env: Dict[str, List[Dict]] = {}
created_dashboards: Dict[str, List[int]] = {env_id: [] for env_id in env_map}
created_charts: Dict[str, List[int]] = {env_id: [] for env_id in env_map}
clients: dict[str, SupersetClient] = {}
templates_by_env: dict[str, list[dict]] = {}
created_dashboards: dict[str, list[int]] = {env_id: [] for env_id in env_map}
created_charts: dict[str, list[int]] = {env_id: [] for env_id in env_map}
used_chart_names: set[str] = set()
used_dashboard_names: set[str] = set()

View File

@@ -15,46 +15,46 @@ from pathlib import Path
# Add src to path (parent of scripts directory)
sys.path.append(str(Path(__file__).parent.parent.parent))
from src.core.superset_client import SupersetClient
from src.core.config_manager import ConfigManager
from src.core.logger import logger
from src.core.cot_logger import seed_trace_id
from src.core.logger import logger
from src.core.superset_client import SupersetClient
def test_dashboard_dataset_relations():
"""Test fetching dataset-to-dashboard relationships."""
seed_trace_id()
# Load environment from existing config
config_manager = ConfigManager()
environments = config_manager.get_environments()
if not environments:
logger.error("No environments configured!")
return
# Use first available environment
env = environments[0]
logger.info(f"Using environment: {env.name} ({env.url})")
client = SupersetClient(env)
try:
# Authenticate
logger.info("Authenticating to Superset...")
client.authenticate()
logger.info("Authentication successful!")
# Test dashboard ID 13
dashboard_id = 13
logger.info(f"\n=== Fetching Dashboard {dashboard_id} ===")
dashboard = client.network.request(method="GET", endpoint=f"/dashboard/{dashboard_id}")
print("\nDashboard structure:")
print(f" ID: {dashboard.get('id')}")
print(f" Title: {dashboard.get('dashboard_title')}")
print(f" Published: {dashboard.get('published')}")
# Check for slices/charts
if 'slices' in dashboard:
logger.info(f"\n Found {len(dashboard['slices'])} slices/charts in dashboard")
@@ -72,21 +72,21 @@ def test_dashboard_dataset_relations():
else:
logger.warning(" No 'slices' field found in dashboard response")
logger.info(f" Available fields: {list(dashboard.keys())}")
# Test dataset ID 26
dataset_id = 26
logger.info(f"\n=== Fetching Dataset {dataset_id} ===")
dataset = client.get_dataset(dataset_id)
print("\nDataset structure:")
print(f" ID: {dataset.get('id')}")
print(f" Table Name: {dataset.get('table_name')}")
print(f" Schema: {dataset.get('schema')}")
print(f" Database: {dataset.get('database', {}).get('database_name', 'Unknown')}")
# Check for dashboards that use this dataset
logger.info(f"\n=== Finding Dashboards using Dataset {dataset_id} ===")
# Method: Use Superset's related_objects API
try:
logger.info(f" Using /api/v1/dataset/{dataset_id}/related_objects endpoint...")
@@ -94,15 +94,15 @@ def test_dashboard_dataset_relations():
method="GET",
endpoint=f"/dataset/{dataset_id}/related_objects"
)
logger.info(f" Related objects response type: {type(related_objects)}")
logger.info(f" Related objects keys: {list(related_objects.keys()) if isinstance(related_objects, dict) else 'N/A'}")
# Check for dashboards in related objects
if 'dashboards' in related_objects:
dashboards = related_objects['dashboards']
logger.info(f" Found {len(dashboards)} dashboards using this dataset:")
for dash in dashboards:
if isinstance(dash, dict):
logger.info(f" - Dashboard ID {dash.get('id')}: {dash.get('dashboard_title', dash.get('title', 'Unknown'))}")
@@ -114,27 +114,27 @@ def test_dashboard_dataset_relations():
if 'dashboards' in result:
dashboards = result['dashboards']
logger.info(f" Found {len(dashboards)} dashboards using this dataset:")
for dash in dashboards:
logger.info(f" - Dashboard ID {dash.get('id')}: {dash.get('dashboard_title', dash.get('title', 'Unknown'))}")
else:
logger.warning(f" No 'dashboards' key in result. Keys: {list(result.keys())}")
else:
logger.warning(f" No 'dashboards' key in response. Available keys: {list(related_objects.keys())}")
logger.info(f" Full related_objects response:")
logger.info(" Full related_objects response:")
print(json.dumps(related_objects, indent=2, default=str)[:1000])
except Exception as e:
logger.error(f" Error fetching related objects: {e}")
import traceback
traceback.print_exc()
# Method 2: Try to use the position_json from dashboard
logger.info(f"\n=== Analyzing Dashboard Position JSON ===")
logger.info("\n=== Analyzing Dashboard Position JSON ===")
if 'position_json' in dashboard:
position_data = json.loads(dashboard['position_json'])
logger.info(f" Position data type: {type(position_data)}")
# Look for datasource references
datasource_ids = set()
if isinstance(position_data, dict):
@@ -148,10 +148,10 @@ def test_dashboard_dataset_relations():
if isinstance(item, dict):
if 'datasource_id' in item:
datasource_ids.add(item['datasource_id'])
if datasource_ids:
logger.info(f" Found datasource IDs: {datasource_ids}")
# Save full response for analysis
output_file = Path(__file__).parent / "dataset_dashboard_analysis.json"
with open(output_file, 'w') as f:
@@ -160,7 +160,7 @@ def test_dashboard_dataset_relations():
'dataset': dataset
}, f, indent=2, default=str)
logger.info(f"\nFull response saved to: {output_file}")
except Exception as e:
logger.error(f"Error: {e}", exc_info=True)
raise