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)}