"""Read-only verification of emitted per-pier caches and all summary SUM rows.""" import zipfile,re,json,sys from pathlib import Path from xml.etree import ElementTree as E S={'s':'http://schemas.openxmlformats.org/spreadsheetml/2006/main'} def check(path,expected): z=zipfile.ZipFile(path);assert z.testzip() is None wb=E.fromstring(z.read('xl/workbook.xml'));sheets=wb.find('s:sheets',S);names=[s.get('name') for s in sheets] assert not any('_ex)' in n or '미사용' in n for n in names) detail=[n for n in names if n.startswith('3.3 수량산출_')];assert len(detail)==expected,(detail,expected) rels={r.get('Id'):r.get('Target') for r in E.fromstring(z.read('xl/_rels/workbook.xml.rels'))} allcells={} for sheet in sheets: path='xl/'+rels[sheet.get('{http://schemas.openxmlformats.org/officeDocument/2006/relationships}id')] root=E.fromstring(z.read(path));allcells[sheet.get('name')]={c.get('r'):c for c in root.findall('.//s:c',S)} for f in root.findall('.//s:f',S):assert '_ex)' not in (f.text or '') summary=allcells['1. 수량집계'];checks=0 for ref,c in summary.items(): f=c.find('s:f',S) if not ref.startswith('K') or f is None or not (f.text or '').startswith('SUM('):continue values=[] for cellref in f.text.removeprefix('SUM(').removesuffix(')').split(','): cell=summary[cellref];rf=cell.find('s:f',S).text m=re.match(r"'(.+)'!([A-Z]+\d+)",rf);assert m and m[1] in detail,rf source=allcells[m[1]][m[2]] a=float(source.find('s:v',S).text);b=float(cell.find('s:v',S).text);assert abs(a-b)<1e-8 values.append(a) assert len(values)==expected assert abs(sum(values)-float(c.find('s:v',S).text))<1e-7 checks+=1 assert checks==53,checks return {'piers':expected,'sheets':len(sheets),'summary_rows_checked':checks,'source_formula_links':checks*expected,'example_removed':True,'cache_differences':0} if __name__=='__main__':print(json.dumps(check(sys.argv[1],int(sys.argv[2])),ensure_ascii=False))