"""合成离线样本检查。与同名 JSON 及文中列出的附件放在同一目录运行。"""
from pathlib import Path, PurePosixPath
import base64, hashlib, io, inspect, json, math, re, subprocess, sys, tempfile, wave, zipfile
from collections import Counter, defaultdict
from datetime import date, datetime
from decimal import Decimal
sys.dont_write_bytecode=True

def sha(b): return hashlib.sha256(b).hexdigest()
def rejected(fn):
    try: fn()
    except (ValueError,TypeError,KeyError,UnicodeError,OverflowError): return True
    return False

def git(root,*args,input=None,check=True):
    r=subprocess.run(['git','-c','core.autocrlf=false',*args],cwd=root,input=input,capture_output=True,check=check)
    return r

def verify(d,base):
    from pathlib import PurePath,PureWindowsPath
    def encode(x):
        if x is None or type(x) in (str,int,bool):return x
        if type(x) is float:
            if not math.isfinite(x):raise ValueError('非有限数字')
            return x
        if isinstance(x,datetime):raise TypeError('datetime 需要另外约定时区')
        if isinstance(x,date):return {'kind':'date','value':x.isoformat()}
        if isinstance(x,Decimal):
            if not x.is_finite():raise ValueError('非有限小数')
            return {'kind':'decimal','value':str(x)}
        if isinstance(x,PurePath):return {'kind':'path','value':x.as_posix()}
        if isinstance(x,list):return [encode(v) for v in x]
        if isinstance(x,dict):
            if not all(isinstance(k,str) for k in x):raise TypeError('键必须是字符串')
            return {k:encode(v) for k,v in x.items()}
        raise TypeError('未登记类型')
    value={'when':date.fromisoformat(d['date']),'amount':Decimal(d['decimal']),'path':PurePosixPath(d['path'])}
    out=encode(value);assert out==d['expected'];assert json.loads(json.dumps(out))==out
    constructors={'Path':Path,'PureWindowsPath':PureWindowsPath,'PurePosixPath':PurePosixPath};paths=[]
    for c in d['path_cases']:
        result=encode(constructors[c['constructor']](c['text']))
        assert result=={'kind':'path','value':c['expected']}
        paths.append({'constructor':c['constructor'],'input':c['text'],'encoded':result})
    assert rejected(lambda:encode(object())) and rejected(lambda:encode({1,2}))
    assert rejected(lambda:encode(Decimal('NaN')))
    return {'encoded':out,'path_cases':paths,'unknown_and_set_rejected':True,'opened_paths':0}

if __name__=='__main__':
    base=Path(__file__).resolve().parent
    data=json.loads((base/'a026.json').read_text('utf-8'))
    result=verify(data,base)
    print(json.dumps({'id':'A026','passed':True,'result':result},ensure_ascii=True))
