187 lines
5.8 KiB
Python
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
|