from pathlib import Path
import xml.etree.ElementTree as E
import json,re,hashlib,csv
p=Path(__file__).resolve().parent;r=E.parse(p/'motor_A82_netlist.xml')
cs={c.attrib['ref']:c for c in r.findall('./components/comp')}
assert cs['R2'].findtext('value')=='0R'
assert cs['C14'].findtext('value')=='100n 16V'
assert cs['R3'].find("property[@name='dnp']") is not None
nets={n.attrib['name']:{(x.attrib['ref'],x.attrib['pin']) for x in n.findall('node')} for n in r.findall('./nets/net')}
assert {('R2','1'),('U1','25')}<=nets['/DRV_AVDD']
assert {('R2','2'),('U1','37'),('C14','1'),('R3','1')}==nets['/ILIM_SET']
assert {('C14','2'),('R3','2')}<=nets['/GND']
s=(p/'drill_motor_evt_a4_bus_divider.kicad_pcb').read_text()
def endblock(s,start):
 depth=0;quoted=False;escaped=False
 for i in range(start,len(s)):
  c=s[i]
  if quoted:
   if escaped:escaped=False
   elif c=='\\':escaped=True
   elif c=='"':quoted=False
  elif c=='"':quoted=True
  elif c=='(':depth+=1
  elif c==')':
   depth-=1
   if depth==0:return i+1
 raise ValueError('unbalanced')
found={}
for m in re.finditer(r'\(footprint\s+"',s):
 block=s[m.start():endblock(s,m.start())];ref=re.search(r'\(property "Reference" "([^"]+)"',block)
 if ref:found[ref[1]]=block
for ref,val in [('R2','0R'),('C14','100n 16V')]:assert f'(property "Value" "{val}"' in found[ref]
assert re.search(r'\(attr[^)]*\bdnp\b',found['R3'])
assert 'Errors 0  Warnings 0' in (p/'ERC_A82.rpt').read_text()
drc=(p/'DRC_A82.rpt').read_text();assert 'Found 0 DRC violations' in drc and 'Found 0 unconnected pads' in drc
assert drc.count('[extra_footprint]')==4 and all('Footprint '+x in drc for x in ['MH1','MH2','MH3','MH4'])
with (p/'BOM-A82-values-DNP-review.csv').open('w',newline='') as f:
 w=csv.writer(f);w.writerow(['Reference','Value','Footprint','DNP','MPN_status'])
 for ref,c in sorted(cs.items()):w.writerow([ref,c.findtext('value'),c.findtext('footprint'),c.find("property[@name='dnp']") is not None,'NOT_FULLY_SOURCED_NO_FACTORY_QUOTE'])
receipt={'status':'A82_CAD_VREF_FEEDBACK_PROFILE_PASS_NOT_PHYSICAL','changes':{'R2':'0R AVDD to legacy ILIM_SET net (now VREF)','R3':'DNP','C14':'100n 16V'},'feedback_PWM_MODE':0,'SOx_gain_nominal_V_per_A':0.3,'minimum_VREF_required_V':2.8,'CBC_current_limit_available':False,'2A_system_current_protection_qualified':False,'ERC_violations':0,'DRC_violations':0,'unconnected':0,'schematic_parity_warnings':'four pre-existing MH1..MH4 only','physical_validation':False,'DFM_factory_approved':False,'manufacturing':'HOLD','source_sha256':{n:hashlib.sha256((p/n).read_bytes()).hexdigest() for n in ['drill_motor_evt_a4_bus_divider.kicad_pcb','drill_motor_evt_a4_bus_divider.kicad_sch','motor_A82_netlist.xml']}}
(p/'hardware_profile_verification_A82.json').write_text(json.dumps(receipt,indent=2)+'\n');print(receipt['status'])
