Skip to content

Commit 6651650

Browse files
fix: resolve 23 of 29 remaining SonarQube code smells
Python S3776 (14): split agent tool builders, extract flow/route helpers TypeScript (9): extract useCockpitData/TopologyView/App helpers
1 parent 3a59501 commit 6651650

File tree

9 files changed

+748
-604
lines changed

9 files changed

+748
-604
lines changed

apps/api/app/routes/twin.py

Lines changed: 177 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,50 @@ def _find_misplaced_nodes(
17241724
]
17251725

17261726

1727+
def _build_community_points(
1728+
ordered_communities: list[dict[str, Any]],
1729+
node_by_id: dict,
1730+
positions: dict[str, tuple[float, float]],
1731+
) -> list[dict[str, Any]]:
1732+
"""Build community point dicts from ordered communities."""
1733+
points: list[dict[str, Any]] = []
1734+
for community in ordered_communities:
1735+
member_ids = list(community.get("member_node_ids", []))
1736+
member_nodes = [node_by_id[nid] for nid in member_ids if nid in node_by_id]
1737+
profile = _community_profile(member_nodes)
1738+
dominant_domain = profile["dominant_domain"]
1739+
dominant_ratio = float(profile["dominant_ratio"])
1740+
misplaced_nodes = _find_misplaced_nodes(
1741+
member_nodes, dominant_domain, dominant_ratio, profile["node_domain_by_id"]
1742+
)
1743+
x, y = positions.get(str(community["id"]), (0.0, 0.0))
1744+
sample_nodes = community.get("sample_nodes") or []
1745+
anchor = str(sample_nodes[0]["id"]) if sample_nodes else ""
1746+
points.append(
1747+
{
1748+
"id": str(community["id"]),
1749+
"label": str(community["label"]),
1750+
"x": x,
1751+
"y": y,
1752+
"member_count": int(community["size"]),
1753+
"cohesion": float(community["cohesion"]),
1754+
"top_kinds": profile["top_kinds"],
1755+
"domain_counts": profile["domain_counts"],
1756+
"dominant_domain": dominant_domain,
1757+
"dominant_ratio": dominant_ratio,
1758+
"summary": None,
1759+
"anchor_node_id": anchor,
1760+
"sample_nodes": list(sample_nodes),
1761+
"member_node_ids": [str(mid) for mid in community.get("member_node_ids", [])],
1762+
"vector": [],
1763+
"source_refs": profile["source_refs"],
1764+
"name_tokens": profile["name_tokens"],
1765+
"misplaced_nodes": misplaced_nodes,
1766+
}
1767+
)
1768+
return points
1769+
1770+
17271771
async def _build_structural_community_points(
17281772
db: Any,
17291773
*,
@@ -1796,45 +1840,7 @@ async def _build_structural_community_points(
17961840
}
17971841
positions = _layout_code_structure_points(point_ids, scoped_weights)
17981842

1799-
points: list[dict[str, Any]] = []
1800-
for community in ordered_communities:
1801-
member_ids = list(community.get("member_node_ids", []))
1802-
member_nodes = [node_by_id[node_id] for node_id in member_ids if node_id in node_by_id]
1803-
profile = _community_profile(member_nodes)
1804-
dominant_domain = profile["dominant_domain"]
1805-
dominant_ratio = float(profile["dominant_ratio"])
1806-
misplaced_nodes = _find_misplaced_nodes(
1807-
member_nodes, dominant_domain, dominant_ratio, profile["node_domain_by_id"]
1808-
)
1809-
1810-
x, y = positions.get(str(community["id"]), (0.0, 0.0))
1811-
points.append(
1812-
{
1813-
"id": str(community["id"]),
1814-
"label": str(community["label"]),
1815-
"x": x,
1816-
"y": y,
1817-
"member_count": int(community["size"]),
1818-
"cohesion": float(community["cohesion"]),
1819-
"top_kinds": profile["top_kinds"],
1820-
"domain_counts": profile["domain_counts"],
1821-
"dominant_domain": dominant_domain,
1822-
"dominant_ratio": dominant_ratio,
1823-
"summary": None,
1824-
"anchor_node_id": str(community["sample_nodes"][0]["id"])
1825-
if community.get("sample_nodes")
1826-
else "",
1827-
"sample_nodes": list(community.get("sample_nodes", [])),
1828-
"member_node_ids": [
1829-
str(member_node_id) for member_node_id in community.get("member_node_ids", [])
1830-
],
1831-
"vector": [],
1832-
"source_refs": profile["source_refs"],
1833-
"name_tokens": profile["name_tokens"],
1834-
"misplaced_nodes": misplaced_nodes,
1835-
}
1836-
)
1837-
1843+
points = _build_community_points(ordered_communities, node_by_id, positions)
18381844
_normalize_xy(points)
18391845
return points, warnings
18401846

@@ -3250,6 +3256,33 @@ async def ports_adapters_view(
32503256
}
32513257

32523258

3259+
def _resolve_table_name(col: KnowledgeNode) -> str:
3260+
"""Resolve the table name from a column node's metadata or natural key."""
3261+
meta = col.meta if isinstance(col.meta, dict) else {}
3262+
return meta.get("table") or _parse_db_table_from_natural_key(col.natural_key) or "unknown"
3263+
3264+
3265+
def _build_fk_row(
3266+
edge: KnowledgeEdge,
3267+
column_by_id: dict[uuid.UUID, KnowledgeNode],
3268+
) -> dict[str, Any] | None:
3269+
"""Build a foreign-key row dict from an edge, or return None if columns are missing."""
3270+
source_col = column_by_id.get(edge.source_node_id)
3271+
target_col = column_by_id.get(edge.target_node_id)
3272+
if not source_col or not target_col:
3273+
return None
3274+
return {
3275+
"id": str(edge.id),
3276+
"fk_name": (edge.meta or {}).get("fk_name"),
3277+
"source_table": _resolve_table_name(source_col),
3278+
"source_column": source_col.name,
3279+
"target_table": _resolve_table_name(target_col),
3280+
"target_column": target_col.name,
3281+
"source_column_node_id": str(source_col.id),
3282+
"target_column_node_id": str(target_col.id),
3283+
}
3284+
3285+
32533286
def _process_erm_edges(
32543287
edges: list[KnowledgeEdge],
32553288
table_by_id: dict[uuid.UUID, KnowledgeNode],
@@ -3267,28 +3300,9 @@ def _process_erm_edges(
32673300
columns_by_table[source.id].append(target)
32683301
continue
32693302

3270-
source_col = column_by_id.get(edge.source_node_id)
3271-
target_col = column_by_id.get(edge.target_node_id)
3272-
if not source_col or not target_col:
3273-
continue
3274-
source_meta = source_col.meta if isinstance(source_col.meta, dict) else {}
3275-
target_meta = target_col.meta if isinstance(target_col.meta, dict) else {}
3276-
fk_rows.append(
3277-
{
3278-
"id": str(edge.id),
3279-
"fk_name": (edge.meta or {}).get("fk_name"),
3280-
"source_table": source_meta.get("table")
3281-
or _parse_db_table_from_natural_key(source_col.natural_key)
3282-
or "unknown",
3283-
"source_column": source_col.name,
3284-
"target_table": target_meta.get("table")
3285-
or _parse_db_table_from_natural_key(target_col.natural_key)
3286-
or "unknown",
3287-
"target_column": target_col.name,
3288-
"source_column_node_id": str(source_col.id),
3289-
"target_column_node_id": str(target_col.id),
3290-
}
3291-
)
3303+
fk_row = _build_fk_row(edge, column_by_id)
3304+
if fk_row:
3305+
fk_rows.append(fk_row)
32923306

32933307
return columns_by_table, fk_rows
32943308

@@ -5456,6 +5470,100 @@ async def _export_mermaid_c4_format(
54565470
}
54575471

54585472

5473+
async def _generate_export_content(
5474+
db: Any,
5475+
scenario: Any,
5476+
projection: GraphProjection,
5477+
body: Any,
5478+
) -> tuple[dict | None, str, Any, str, GraphProjection]:
5479+
"""Dispatch to the correct export format and return (early_return, content, kind, name, projection)."""
5480+
if body.format == "lpg_jsonl":
5481+
if projection == GraphProjection.CODE_SYMBOL:
5482+
content = await export_lpg_jsonl(db, scenario.id)
5483+
else:
5484+
graph = await get_full_scenario_graph(
5485+
session=db,
5486+
scenario_id=scenario.id,
5487+
layer=None,
5488+
projection=projection,
5489+
entity_level=body.entity_level,
5490+
)
5491+
content = export_lpg_jsonl_from_graph(scenario.id, graph)
5492+
return (
5493+
None,
5494+
content,
5495+
KnowledgeArtifactKind.LPG_JSONL,
5496+
f"{scenario.name}.lpg.jsonl",
5497+
projection,
5498+
)
5499+
if body.format == "cc_json":
5500+
if projection == GraphProjection.CODE_SYMBOL:
5501+
projection = GraphProjection.CODE_FILE
5502+
content = await export_codecharta_json(
5503+
db,
5504+
scenario.id,
5505+
projection=projection,
5506+
entity_level=body.entity_level,
5507+
)
5508+
return None, content, KnowledgeArtifactKind.CC_JSON, f"{scenario.name}.cc.json", projection
5509+
if body.format == "cx2":
5510+
if projection == GraphProjection.CODE_SYMBOL:
5511+
content = await export_cx2(db, scenario.id)
5512+
else:
5513+
graph = await get_full_scenario_graph(
5514+
session=db,
5515+
scenario_id=scenario.id,
5516+
layer=None,
5517+
projection=projection,
5518+
entity_level=body.entity_level,
5519+
)
5520+
content = export_cx2_from_graph(scenario.id, graph)
5521+
return None, content, KnowledgeArtifactKind.CX2, f"{scenario.name}.cx2.json", projection
5522+
if body.format == "jgf":
5523+
if projection == GraphProjection.CODE_SYMBOL:
5524+
content = await export_jgf(db, scenario.id)
5525+
else:
5526+
graph = await get_full_scenario_graph(
5527+
session=db,
5528+
scenario_id=scenario.id,
5529+
layer=None,
5530+
projection=projection,
5531+
entity_level=body.entity_level,
5532+
)
5533+
content = export_jgf_from_graph(scenario.id, graph)
5534+
return None, content, KnowledgeArtifactKind.JGF, f"{scenario.name}.jgf.json", projection
5535+
if body.format == "twin_manifest":
5536+
content = await export_twin_manifest(db, scenario.id)
5537+
return (
5538+
None,
5539+
content,
5540+
KnowledgeArtifactKind.TWIN_MANIFEST,
5541+
f"{scenario.name}.twin_manifest.json",
5542+
projection,
5543+
)
5544+
# Mermaid C4 or other format
5545+
result = await _export_mermaid_c4_format(db, scenario, body)
5546+
if result is not None:
5547+
return result, "", None, "", projection
5548+
selected_c4_view = _parse_c4_view(body.c4_view)
5549+
selected_c4_scope = _parse_c4_scope(body.c4_scope)
5550+
selected_max_nodes = body.max_nodes or 120
5551+
content = await export_mermaid_c4(
5552+
db,
5553+
scenario.id,
5554+
entity_level=body.entity_level or "container",
5555+
c4_view=selected_c4_view,
5556+
c4_scope=selected_c4_scope,
5557+
max_nodes=selected_max_nodes,
5558+
)
5559+
kind = (
5560+
KnowledgeArtifactKind.MERMAID_C4_ASIS
5561+
if scenario.is_as_is
5562+
else KnowledgeArtifactKind.MERMAID_C4_TOBE
5563+
)
5564+
return None, content, kind, f"{scenario.name}.mmd", projection
5565+
5566+
54595567
@router.post(
54605568
"/scenarios/{scenario_id}/exports",
54615569
responses={
@@ -5475,85 +5583,11 @@ async def create_export(request: Request, scenario_id: str, body: ExportRequest)
54755583
GraphProjection(body.projection) if body.projection else GraphProjection.ARCHITECTURE
54765584
)
54775585

5478-
if body.format == "lpg_jsonl":
5479-
if projection == GraphProjection.CODE_SYMBOL:
5480-
content = await export_lpg_jsonl(db, scenario.id)
5481-
else:
5482-
graph = await get_full_scenario_graph(
5483-
session=db,
5484-
scenario_id=scenario.id,
5485-
layer=None,
5486-
projection=projection,
5487-
entity_level=body.entity_level,
5488-
)
5489-
content = export_lpg_jsonl_from_graph(scenario.id, graph)
5490-
kind = KnowledgeArtifactKind.LPG_JSONL
5491-
name = f"{scenario.name}.lpg.jsonl"
5492-
elif body.format == "cc_json":
5493-
if projection == GraphProjection.CODE_SYMBOL:
5494-
projection = GraphProjection.CODE_FILE
5495-
content = await export_codecharta_json(
5496-
db,
5497-
scenario.id,
5498-
projection=projection,
5499-
entity_level=body.entity_level,
5500-
)
5501-
kind = KnowledgeArtifactKind.CC_JSON
5502-
name = f"{scenario.name}.cc.json"
5503-
elif body.format == "cx2":
5504-
if projection == GraphProjection.CODE_SYMBOL:
5505-
content = await export_cx2(db, scenario.id)
5506-
else:
5507-
graph = await get_full_scenario_graph(
5508-
session=db,
5509-
scenario_id=scenario.id,
5510-
layer=None,
5511-
projection=projection,
5512-
entity_level=body.entity_level,
5513-
)
5514-
content = export_cx2_from_graph(scenario.id, graph)
5515-
kind = KnowledgeArtifactKind.CX2
5516-
name = f"{scenario.name}.cx2.json"
5517-
elif body.format == "jgf":
5518-
if projection == GraphProjection.CODE_SYMBOL:
5519-
content = await export_jgf(db, scenario.id)
5520-
else:
5521-
graph = await get_full_scenario_graph(
5522-
session=db,
5523-
scenario_id=scenario.id,
5524-
layer=None,
5525-
projection=projection,
5526-
entity_level=body.entity_level,
5527-
)
5528-
content = export_jgf_from_graph(scenario.id, graph)
5529-
kind = KnowledgeArtifactKind.JGF
5530-
name = f"{scenario.name}.jgf.json"
5531-
elif body.format == "twin_manifest":
5532-
content = await export_twin_manifest(db, scenario.id)
5533-
kind = KnowledgeArtifactKind.TWIN_MANIFEST
5534-
name = f"{scenario.name}.twin_manifest.json"
5535-
else:
5536-
result = await _export_mermaid_c4_format(db, scenario, body)
5537-
if result is not None:
5538-
return result
5539-
5540-
selected_c4_view = _parse_c4_view(body.c4_view)
5541-
selected_c4_scope = _parse_c4_scope(body.c4_scope)
5542-
selected_max_nodes = body.max_nodes or 120
5543-
content = await export_mermaid_c4(
5544-
db,
5545-
scenario.id,
5546-
entity_level=body.entity_level or "container",
5547-
c4_view=selected_c4_view,
5548-
c4_scope=selected_c4_scope,
5549-
max_nodes=selected_max_nodes,
5550-
)
5551-
kind = (
5552-
KnowledgeArtifactKind.MERMAID_C4_ASIS
5553-
if scenario.is_as_is
5554-
else KnowledgeArtifactKind.MERMAID_C4_TOBE
5555-
)
5556-
name = f"{scenario.name}.mmd"
5586+
early_return, content, kind, name, projection = await _generate_export_content(
5587+
db, scenario, projection, body
5588+
)
5589+
if early_return is not None:
5590+
return early_return
55575591

55585592
meta: dict = {
55595593
"scenario_id": str(scenario.id),
@@ -5562,9 +5596,9 @@ async def create_export(request: Request, scenario_id: str, body: ExportRequest)
55625596
"entity_level": body.entity_level,
55635597
}
55645598
if body.format == "mermaid_c4":
5565-
meta["c4_view"] = selected_c4_view
5566-
meta["c4_scope"] = selected_c4_scope
5567-
meta["max_nodes"] = selected_max_nodes
5599+
meta["c4_view"] = _parse_c4_view(body.c4_view)
5600+
meta["c4_scope"] = _parse_c4_scope(body.c4_scope)
5601+
meta["max_nodes"] = body.max_nodes or 120
55685602
artifact = await _upsert_artifact(
55695603
db,
55705604
collection_id=scenario.collection_id,

0 commit comments

Comments
 (0)