Skip to content

Commit ff990c0

Browse files
committed
chore(codeql): break static model import cycles
- Keep AuditReport assembly imports deferred and dynamic - Preserve the existing AuditReport.from_audits API while keeping models import-light Tests: python3 -m pytest -q -p no:cacheprovider; ruff check src/ tests/
1 parent 4a96e76 commit ff990c0

1 file changed

Lines changed: 25 additions & 28 deletions

File tree

src/models.py

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import dataclasses
4+
import importlib
45
from dataclasses import dataclass, field
56
from datetime import datetime
67
from typing import Optional
@@ -266,20 +267,12 @@ def from_audits(
266267
) -> AuditReport:
267268
"""Construct an AuditReport with all derived statistics."""
268269
now = datetime.now(tz=__import__("datetime").timezone.utc)
269-
from src.implementation_hotspots import (
270-
build_implementation_hotspots_summary,
271-
build_portfolio_implementation_hotspots,
272-
)
273-
from src.portfolio_intelligence import (
274-
DEFAULT_PROFILES,
275-
REPORT_SCHEMA_VERSION,
276-
build_default_collections,
277-
build_portfolio_hotspots,
278-
build_portfolio_lens_summary,
279-
build_portfolio_security_governance_preview,
280-
build_portfolio_security_posture,
281-
build_scenario_summary,
282-
)
270+
# AuditReport assembly needs portfolio/scoring modules that depend on these core
271+
# dataclasses. Import them dynamically at call time so the model layer stays
272+
# import-light and does not form static import cycles.
273+
implementation_hotspots = importlib.import_module("src.implementation_hotspots")
274+
portfolio_intelligence = importlib.import_module("src.portfolio_intelligence")
275+
scorer = importlib.import_module("src.scorer")
283276

284277
# Tier distribution
285278
tier_dist: dict[str, int] = {}
@@ -311,9 +304,7 @@ def _activity_score(audit: RepoAudit) -> float:
311304
most_neglected = [a.metadata.name for a in sorted_by_activity[-5:]]
312305

313306
# Portfolio grade (nuanced formula)
314-
from src.scorer import compute_portfolio_grade
315-
316-
p_grade, p_health = compute_portfolio_grade(audits)
307+
p_grade, p_health = scorer.compute_portfolio_grade(audits)
317308

318309
# Tech stack summary
319310
tech_stack: dict[str, dict] = {}
@@ -340,14 +331,20 @@ def _activity_score(audit: RepoAudit) -> float:
340331
audits, key=lambda a: a.overall_score * 0.6 + a.interest_score * 0.4, reverse=True
341332
)
342333
best_work = [a.metadata.name for a in best[:5]]
343-
portfolio_lenses = build_portfolio_lens_summary(audits)
344-
portfolio_hotspots = build_portfolio_hotspots(audits)
345-
implementation_hotspots = build_portfolio_implementation_hotspots(audits)
346-
implementation_hotspots_summary = build_implementation_hotspots_summary(audits)
347-
portfolio_security = build_portfolio_security_posture(audits)
348-
security_governance_preview = build_portfolio_security_governance_preview(audits)
349-
collections = build_default_collections(audits)
350-
scenario_summary = build_scenario_summary(audits)
334+
portfolio_lenses = portfolio_intelligence.build_portfolio_lens_summary(audits)
335+
portfolio_hotspots = portfolio_intelligence.build_portfolio_hotspots(audits)
336+
portfolio_implementation_hotspots = (
337+
implementation_hotspots.build_portfolio_implementation_hotspots(audits)
338+
)
339+
implementation_hotspots_summary = (
340+
implementation_hotspots.build_implementation_hotspots_summary(audits)
341+
)
342+
portfolio_security = portfolio_intelligence.build_portfolio_security_posture(audits)
343+
security_governance_preview = (
344+
portfolio_intelligence.build_portfolio_security_governance_preview(audits)
345+
)
346+
collections = portfolio_intelligence.build_default_collections(audits)
347+
scenario_summary = portfolio_intelligence.build_scenario_summary(audits)
351348
action_backlog = sorted(
352349
[
353350
{
@@ -386,10 +383,10 @@ def _activity_score(audit: RepoAudit) -> float:
386383
else len(audits),
387384
baseline_signature=baseline_signature,
388385
baseline_context=baseline_context or {},
389-
schema_version=REPORT_SCHEMA_VERSION,
386+
schema_version=portfolio_intelligence.REPORT_SCHEMA_VERSION,
390387
lenses=portfolio_lenses,
391388
hotspots=portfolio_hotspots,
392-
implementation_hotspots=implementation_hotspots,
389+
implementation_hotspots=portfolio_implementation_hotspots,
393390
implementation_hotspots_summary=implementation_hotspots_summary,
394391
portfolio_outcomes_summary={},
395392
operator_effectiveness_summary={},
@@ -415,7 +412,7 @@ def _activity_score(audit: RepoAudit) -> float:
415412
security_posture=portfolio_security,
416413
security_governance_preview=security_governance_preview,
417414
collections=collections,
418-
profiles=DEFAULT_PROFILES,
415+
profiles=portfolio_intelligence.DEFAULT_PROFILES,
419416
scenario_summary=scenario_summary,
420417
action_backlog=action_backlog,
421418
campaign_summary={},

0 commit comments

Comments
 (0)