SXXXXXXX_PyMsc/pymsc/core/introspection.py
2025-12-02 11:21:05 +01:00

85 lines
3.3 KiB
Python

import ctypes
from enum import Enum
def inspect_structure(obj):
"""
Analizza ricorsivamente una struttura o unione ctypes e ritorna un dizionario
che descrive la gerarchia dei dati, i valori attuali e i metadati per la GUI.
"""
# 1. Gestione Smart Types (es. Velocity, Semicircle)
# Se la classe ha una property 'value' o 'degrees', la trattiamo come un valore singolo
cls = obj.__class__
if hasattr(cls, 'value') and isinstance(getattr(cls, 'value'), property):
return {
"type": "smart_value",
"value": obj.value,
"obj_ref": obj, # Riferimento all'oggetto per il setter
"attr_name": "value" # Nome dell'attributo da settare
}
if hasattr(cls, 'degrees') and isinstance(getattr(cls, 'degrees'), property):
return {
"type": "smart_angle",
"value": obj.degrees,
"obj_ref": obj,
"attr_name": "degrees"
}
# 2. Gestione Strutture Complesse (Structure o Union)
if hasattr(obj, "_fields_"):
children = {}
# Recuperiamo eventuali metadati per gli Enum definiti nella classe
# Esempio: _enums_ = {"target_history": TargetHistory}
enums_map = getattr(obj, "_enums_", {})
for field_desc in obj._fields_:
field_name = field_desc[0]
field_type = field_desc[1]
# Saltiamo i campi 'raw' se esiste una vista 'bits' o 'fields' (tipico delle Union)
if field_name == "raw" and (hasattr(obj, "bits") or hasattr(obj, "fields")):
continue
field_val = getattr(obj, field_name)
# Caso A: Campo mappato su Enum
if field_name in enums_map:
enum_cls = enums_map[field_name]
try:
current_enum = enum_cls(field_val)
except ValueError:
# Se il valore raw non è nell'enum, gestiamo l'errore o usiamo un fallback
current_enum = field_val
children[field_name] = {
"type": "enum",
"value": current_enum,
"enum_cls": enum_cls,
"obj_ref": obj,
"attr_name": field_name
}
# Caso B: Altra Struttura/Union (Ricorsione)
elif hasattr(field_val, "_fields_"):
children[field_name] = inspect_structure(field_val)
# Caso C: Primitiva (int, float, array fissi)
else:
# Gestione array ctypes semplici
if hasattr(field_type, "_length_"):
# Per ora semplifichiamo gli array come stringa o lista non editabile
val_repr = str(list(field_val))
children[field_name] = {"type": "readonly", "value": val_repr}
else:
children[field_name] = {
"type": "primitive",
"value": field_val,
"obj_ref": obj,
"attr_name": field_name
}
return {"type": "compound", "children": children}
# Fallback
return {"type": "unknown", "value": str(obj)}