Files
linuxcncWebWASM/scripts/verify_rtcp_beginner_pdf.py

42 lines
2.8 KiB
Python

"""Verify A4 page count, CJK text, embedded glyphs, bookmarks and source evidence."""
import hashlib
import json
import unicodedata
from pathlib import Path
from pypdf import PdfReader
ROOT=Path(__file__).resolve().parents[1]
OUT=ROOT/'docs/teaching/rtcp-beginners'
pdf=OUT/'五轴RTCP与工件坐标-初学者完整讲义.pdf'
r=PdfReader(pdf)
outline=json.loads((OUT/'outline.json').read_text())
layout=json.loads((OUT/'verification/layout.json').read_text())
numeric=json.loads((OUT/'gcode-evidence.json').read_text())
assert len(r.pages)==len(outline)==72
assert numeric['status']=='verified' and numeric['executed_program']['status']=='completed'
assert not layout['errors'] and all(not p['violations'] and not p['overflow'] for p in layout['pages'])
pages=[];fonts={}
normalize=lambda s:''.join(unicodedata.normalize('NFKC',s).split())
for i,page in enumerate(r.pages):
text=page.extract_text();assert len(text)>120,(i,len(text))
assert normalize(outline[i]['title']) in normalize(text),(i,outline[i]['title'])
assert abs(float(page.mediabox.width)-595.28)<1 and abs(float(page.mediabox.height)-841.89)<1
assert '\ufffd' not in text
for entry in page['/Resources'].get('/Font',{}).values():
font=entry.get_object()
for item in font.get('/DescendantFonts',[font]):
value=item.get_object();desc=value.get('/FontDescriptor')
if desc:
desc=desc.get_object();name=str(desc.get('/FontName'))
embedded=bool(value.get('/Subtype')=='/Type3' and value.get('/CharProcs')) or any(k in desc for k in ['/FontFile','/FontFile2','/FontFile3'])
fonts[name]=embedded
pages.append({'page':i+1,'characters':len(text),'title':outline[i]['title']})
assert fonts and all(fonts.values()) and any('CJK' in k for k in fonts)
def count_bookmarks(items):
return sum(count_bookmarks(item) if isinstance(item,list) else 1 for item in items)
bookmarks=count_bookmarks(r.outline)
assert bookmarks>=72
report={'report_id':'rtcp-beginners-pdf-v1','status':'verified','page_count':len(r.pages),'pdf':pdf.name,'bytes':pdf.stat().st_size,'sha256':hashlib.sha256(pdf.read_bytes()).hexdigest(),'pages':pages,'embedded_fonts':fonts,'bookmarks':bookmarks,'numeric_report':numeric['report_id'],'executed_program_status':numeric['executed_program']['status'],'wasm_sha256':numeric['wasm_sha256'],'evidence':[{'path':str(p.relative_to(OUT)),'sha256':hashlib.sha256(p.read_bytes()).hexdigest()} for p in [OUT/'handbook.html',OUT/'outline.json',OUT/'gcode-evidence.json',OUT/'verification/layout.json',*sorted((OUT/'assets').iterdir()),*sorted((OUT/'verification').glob('pdf-contact-*.png'))]]}
(OUT/'verification/acceptance.json').write_text(json.dumps(report,ensure_ascii=False,indent=2)+'\n')
print(json.dumps({k:report[k] for k in ['report_id','status','page_count','bytes','bookmarks']},ensure_ascii=False))