80 lines
2.6 KiB
Python
80 lines
2.6 KiB
Python
# backend/serializer.py
|
|
import pcbnew
|
|
|
|
class Serializer:
|
|
@staticmethod
|
|
def serialize(item):
|
|
"""
|
|
Returns (sexpr_string, error_message).
|
|
"""
|
|
if not item: return None, "Item is None"
|
|
|
|
last_error = ""
|
|
|
|
# Method 1: PCB_IO_KICAD_SEXPR (Robust, KiCad 6+)
|
|
try:
|
|
sf = pcbnew.STRING_FORMATTER()
|
|
plugin = pcbnew.PCB_IO_KICAD_SEXPR()
|
|
plugin.SetOutputFormatter(sf)
|
|
plugin.Format(item)
|
|
res = sf.GetString()
|
|
if res and len(res) > 0:
|
|
return res, None
|
|
else:
|
|
last_error = "Format returned empty string"
|
|
except Exception as e:
|
|
last_error = str(e)
|
|
|
|
# Method 2: Fallback to direct Serialize
|
|
try:
|
|
sf = pcbnew.STRING_FORMATTER()
|
|
if hasattr(item, 'Serialize'):
|
|
item.Serialize(sf)
|
|
res = sf.GetString()
|
|
if res and len(res) > 0:
|
|
return res, None
|
|
except Exception as e:
|
|
last_error = f"{last_error} | Fallback: {str(e)}"
|
|
|
|
return None, last_error
|
|
|
|
@staticmethod
|
|
def deserialize(data, board):
|
|
"""
|
|
Returns (item, error_message).
|
|
"""
|
|
if not data: return None, "No data provided"
|
|
cls_name = data.get('class')
|
|
sexpr = data.get('sexpr')
|
|
if not cls_name or not sexpr: return None, "Missing class or sexpr"
|
|
|
|
try:
|
|
if not hasattr(pcbnew, cls_name):
|
|
return None, f"Class {cls_name} not found in pcbnew"
|
|
|
|
cls = getattr(pcbnew, cls_name)
|
|
item = None
|
|
|
|
# Instantiate item
|
|
try:
|
|
item = cls(board)
|
|
except:
|
|
try:
|
|
item = cls()
|
|
except Exception as e:
|
|
return None, f"Constructor failed for {cls_name}: {e}"
|
|
|
|
# Deserialize with KiCad version compatibility
|
|
# KiCad 9+ requires (data, source_name), older versions take (data)
|
|
try:
|
|
lr = pcbnew.STRING_LINE_READER(sexpr, "restore")
|
|
except:
|
|
try:
|
|
lr = pcbnew.STRING_LINE_READER(sexpr)
|
|
except Exception as e:
|
|
return None, f"STRING_LINE_READER init failed: {e}"
|
|
|
|
item.Deserialize(lr)
|
|
return item, None
|
|
except Exception as e:
|
|
return None, f"Deserialization error for {cls_name}: {e}" |