Files
jobtrackingapp/docs/redesign/phase-9/p9-sec-02/model/parser_probe.py
T
cesnimda 30e251a593
MariaDB persistence qualification / mariadb (push) Has been cancelled
fix: qualify patched Python model and cache dependencies
2026-10-25 08:18:21 +01:00

77 lines
5.3 KiB
Python

"""Resource-bounded actual document/OCR children and real local HTTP startup."""
from pathlib import Path
import hashlib
import json
import os
import subprocess
import sys
import tempfile
import time
from urllib import request, error
from PIL import Image, ImageDraw, ImageFont
from verify import verify_fixture
HERE = Path(__file__).resolve().parent
manifest = json.loads((HERE / 'ARTIFACTS.json').read_text())['safetensors']
verify_fixture('/fixture', manifest)
results = []
with tempfile.TemporaryDirectory(prefix='jt-parsers-') as temporary:
directory = Path(temporary)
image = Image.new('RGB', (1000, 180), 'white')
ImageDraw.Draw(image).text((40, 50), 'PYTHON CAREER 2026', fill='black', font=ImageFont.load_default(size=48))
image.save(directory / 'ocr.png'); image.save(directory / 'ocr.pdf', resolution=150)
for file in [*(HERE / 'data').glob('benign.*'), directory / 'ocr.png', directory / 'ocr.pdf']:
output = directory / (file.name + '.json')
args = [sys.executable, '/app/parser_child.py', '--input', str(file), '--output', str(output), '--extension', file.suffix, '--cpu-seconds', '10', '--memory-bytes', str(512 * 1024 * 1024)]
result = subprocess.run(args, capture_output=True, text=True, timeout=20)
assert result.returncode == 0, (file.name, result.stdout, result.stderr, output.read_text() if output.exists() else '')
parsed = json.loads(output.read_text())
assert parsed['ok'] and parsed['text']
if file.name.startswith('ocr'):
assert all(token in parsed['text'] for token in ['PYTHON','CAREER','2026'])
assert parsed['ocr_used'] is True
else:
assert all(token in parsed['text'] for token in ['Åse','Østby','Python','C#'])
results.append({'file':file.name,'sha256':hashlib.sha256(file.read_bytes()).hexdigest(),'text':parsed['text'],'ocrUsed':parsed['ocr_used'],'childExitCode':result.returncode})
env = os.environ.copy()
env.update(AI_SERVICE_SKIP_MODEL_LOAD='0', AI_SERVICE_EAGER_MODEL_LOAD='0', AI_SERVICE_TOKEN='p9-local-qualification-only')
code = "import sys;sys.path.insert(0,'/app');import app,uvicorn;app.MODEL_NAME='/fixture';uvicorn.run(app.app,host='127.0.0.1',port=18081,log_level='warning')"
with Path('/evidence/server.log').open('w') as log:
server = subprocess.Popen([sys.executable,'-c',code],env=env,stdout=log,stderr=subprocess.STDOUT)
try:
deadline=time.monotonic()+30
while True:
try:
with request.urlopen('http://127.0.0.1:18081/health',timeout=1) as response:health=json.load(response)
break
except (OSError,error.URLError):
assert server.poll() is None,'Server exited before readiness'
assert time.monotonic()<deadline,'Server readiness deadline exceeded'
time.sleep(.1)
assert health['model_loaded'] is False
body=json.dumps({'text':'Python engineers build reliable accessible career software.','max_length':24,'min_length':8}).encode()
try:request.urlopen(request.Request('http://127.0.0.1:18081/summarize',data=body,headers={'Content-Type':'application/json'}),timeout=10)
except error.HTTPError as failure:assert failure.code==401
else:raise AssertionError('Missing service token accepted')
headers={'Content-Type':'application/json','X-Ai-Service-Token':'p9-local-qualification-only'}
replies=[]
for _ in range(2):
with request.urlopen(request.Request('http://127.0.0.1:18081/summarize',data=body,headers=headers),timeout=20) as response:replies.append(json.load(response))
assert replies[0]['cached'] is False and replies[1]['cached'] is True
assert replies[0]['summary']==replies[1]['summary']
boundary='JtSyntheticQualification'
upload=(f'--{boundary}\r\nContent-Disposition: form-data; name="file"; filename="synthetic.txt"\r\nContent-Type: text/plain\r\n\r\n'.encode()+(HERE/'data/benign.txt').read_bytes()+f'\r\n--{boundary}--\r\n'.encode())
with request.urlopen(request.Request('http://127.0.0.1:18081/extract-text',data=upload,headers={'Content-Type':'multipart/form-data; boundary='+boundary,'X-Ai-Service-Token':'p9-local-qualification-only'}),timeout=20) as response:extracted=json.load(response)
assert 'Åse' in extracted['text'] and 'C#' in extracted['text']
results.append({'case':'real-http-startup','health200':True,'unauthenticated401':True,'realSummary200':True,'repeatCache':True,'actualUploadExtraction200':True})
finally:
server.terminate()
try:server.wait(timeout=5)
except subprocess.TimeoutExpired:server.kill();server.wait(timeout=5)
assert server.poll() is not None
data=Path('/usr/share/tesseract-ocr/5/tessdata/eng.traineddata')
record={'status':'PASS','cases':results,'tesseractVersion':subprocess.check_output(['tesseract','--version'],text=True).splitlines()[0],'englishDataSha256':hashlib.sha256(data.read_bytes()).hexdigest(),'englishDataBytes':data.stat().st_size,'offline':True,'serverStopped':True,'limits':'Synthetic TXT/DOCX/PDF/image/OCR and small BART CPU HTTP contracts; no production documents, full-size model, GPU, external provider or semantic quality.'}
print(json.dumps(record),flush=True)