nodeslicer/infra/error_reporting/formatter.py
2026-10-15 14:13:39 +03:00

58 lines
2.2 KiB
Python

from __future__ import annotations
from typing import Any
def _format_node_description(node: Any) -> str:
"""Formats a human-readable node name and type label."""
if node is None:
return ""
name = getattr(node, "name", "")
bl_label = getattr(node, "bl_label", "")
bl_idname = getattr(node, "bl_idname", "") or type(node).__name__
label = bl_label or bl_idname
if name and label and name != label:
return f"'{name}' ({label})"
elif name:
return f"'{name}'"
elif label:
return f"'{label}'"
return str(node)
def get_node_input_names(node: Any, fallback_inputs: list[str] | None = None) -> list[str]:
"""Retrieves all input socket names for a node, preserving order without duplicates."""
names: list[str] = []
inputs = getattr(node, "inputs", None)
if inputs:
for s in inputs:
s_name = getattr(s, "name", "")
if s_name and s_name not in names:
names.append(s_name)
elif not s_name:
ident = getattr(s, "identifier", "")
if ident and ident not in names:
names.append(ident)
if not names and fallback_inputs:
for s_name in fallback_inputs:
if s_name and s_name not in names:
names.append(s_name)
if not names:
mapping = getattr(node, "list_socket_mapping", None)
if mapping:
for item in mapping:
m_in = item[0] if isinstance(item, (list, tuple)) and item else None
if m_in and m_in not in names:
names.append(m_in)
return names
def format_node_failure_message(node: Any, exc_or_msg: Any, fallback_inputs: list[str] | None = None) -> str:
"""Formats a concise, informative execution failure message specifying the node and input names."""
node_str = _format_node_description(node) or "Unknown Node"
input_names = get_node_input_names(node, fallback_inputs=fallback_inputs)
inputs_str = ", ".join(input_names) if input_names else "(None)"
msg = str(exc_or_msg)
if msg.startswith("Execution failed at node "):
return msg
return f"Execution failed at node {node_str} [Inputs: {inputs_str}]: {msg}"