SXXXXXXX_PyBusMonitor1553/pybusmonitor1553/gui/monitor_helpers.py
2025-12-17 13:39:10 +01:00

187 lines
5.8 KiB
Python

"""Helper utilities extracted from monitor.py for formatting and enum lookups.
These functions are UI-agnostic and can be unit-tested independently.
"""
import importlib
import sys
UNSET_TEXT = "<unset>"
def fmt_enum(val, enum_names):
"""Format numeric `val` with possible enum name(s)."""
try:
enums_mod = None
try:
enums_mod = importlib.import_module('Grifo_E_1553lib.data_types.enums')
except Exception:
try:
enums_mod = importlib.import_module('pybusmonitor1553.Grifo_E_1553lib.data_types.enums')
except Exception:
enums_mod = None
if enums_mod is None:
return str(val)
for name in enum_names:
enum_cls = getattr(enums_mod, name, None)
if enum_cls is not None:
try:
v = int(val)
try:
enum_name = enum_cls(v).name
except Exception:
enum_name = str(getattr(enum_cls, v, ''))
try:
if not enum_name or str(enum_name).lower() == 'none':
return str(v)
except Exception:
pass
return f"{v} ({enum_name})"
except Exception:
continue
except Exception:
pass
return str(val)
def get_enum_items(class_name):
"""Return list of (name, value) tuples for enum class, or None."""
try:
enums_mod = None
try:
enums_mod = importlib.import_module('Grifo_E_1553lib.data_types.enums')
except Exception:
try:
enums_mod = importlib.import_module('pybusmonitor1553.Grifo_E_1553lib.data_types.enums')
except Exception:
enums_mod = None
if enums_mod is None:
return None
enum_cls = getattr(enums_mod, class_name, None)
if enum_cls is None:
return None
items = []
if hasattr(enum_cls, '__members__'):
for name, member in enum_cls.__members__.items():
try:
items.append((name, int(member.value)))
except Exception:
try:
items.append((name, int(member)))
except Exception:
pass
return items
for a in dir(enum_cls):
if not a.isupper():
continue
try:
v = getattr(enum_cls, a)
if isinstance(v, int):
items.append((a, int(v)))
except Exception:
continue
return items if items else None
except Exception:
return None
def format_ctypes_obj(obj, indent=0, max_depth=3):
pad = ' ' * indent
if obj is None:
return f"{pad}{UNSET_TEXT}\n"
try:
if hasattr(obj, 'value') and not hasattr(obj, '__dict__'):
try:
return f"{pad}{int(obj.value)}\n"
except Exception:
return f"{pad}{obj}\n"
if isinstance(obj, (int, float, str)):
return f"{pad}{obj}\n"
except Exception:
pass
if hasattr(obj, 'raw') and not hasattr(obj, '__dict__'):
try:
raw = int(obj.raw)
cls_name = obj.__class__.__name__
enum_str = fmt_enum(raw, [cls_name])
if enum_str == str(raw):
return f"{pad}{raw}\n"
else:
return f"{pad}{enum_str}\n"
except Exception:
return f"{repr(obj)}\n"
if max_depth <= 0:
return f"{pad}{obj}\n"
names = [n for n in dir(obj) if not n.startswith('_')]
simple_fields = []
for n in names:
try:
v = getattr(obj, n)
except Exception:
continue
if callable(v):
continue
if isinstance(v, (int, float, str)) or hasattr(v, 'raw') or hasattr(v, 'value'):
try:
nested = format_ctypes_obj(v, indent=indent+1, max_depth=max_depth-1)
simple_fields.append(f"{pad}{n}:\n{nested}")
except Exception:
simple_fields.append(f"{pad}{n}: <error>\n")
else:
try:
nested = format_ctypes_obj(v, indent=indent+1, max_depth=max_depth-1)
simple_fields.append(f"{pad}{n}:\n{nested}")
except Exception:
simple_fields.append(f"{pad}{n}: <error>\n")
if simple_fields:
return '\n'.join(simple_fields) + '\n'
return f"{pad}{repr(obj)}\n"
def format_value_for_table(val):
try:
if val is None:
return UNSET_TEXT
if isinstance(val, (int, float, str)):
return str(val)
if hasattr(val, 'raw'):
try:
return fmt_enum(int(getattr(val, 'raw')), [val.__class__.__name__])
except Exception:
try:
return str(getattr(val, 'raw'))
except Exception:
return repr(val)
if hasattr(val, 'value'):
try:
return str(int(val.value))
except Exception:
try:
return str(val.value)
except Exception:
return repr(val)
try:
s = format_ctypes_obj(val, indent=0, max_depth=1)
return s.strip().splitlines()[0]
except Exception:
return repr(val)
except Exception:
return '<unrepresentable>'
def coerce_text_to_type(text: str):
try:
if text.startswith('0x'):
return int(text, 16)
except Exception:
pass
try:
return int(text)
except Exception:
try:
return float(text)
except Exception:
return text