"""Preserve exact id/text string fields, including leading/trailing whitespace."""
import argparse,csv,json,io
from pathlib import Path
def unique(pairs):
    d={}
    for k,v in pairs:
        if k in d:raise ValueError('duplicate key')
        d[k]=v
    return d
def constant(v):raise ValueError('nonstandard constant')
def export(source,target):
    with Path(source).open('rb') as f:raw=f.read(1000001)
    if len(raw)>1000000:raise ValueError('demo input byte policy exceeded')
    rows=json.loads(raw.decode('utf-8'),object_pairs_hook=unique,parse_constant=constant)
    if not isinstance(rows,list):raise ValueError('array required')
    values=[]
    for r in rows:
        if not isinstance(r,dict) or set(r)!={'id','text'}:raise ValueError('id/text schema required')
        if not all(isinstance(r[k],str) for k in ['id','text']):raise ValueError('string fields required')
        for v in r.values():v.encode('utf-8',errors='strict')
        values.append([r['id'],r['text']])
    s=io.StringIO(newline='');w=csv.writer(s);w.writerow(['id','text']);w.writerows(values)
    with Path(target).open('x',encoding='utf-8',newline='') as f:f.write(s.getvalue())
    with Path(target).open(encoding='utf-8',newline='') as f:
        recovered=list(csv.reader(f,skipinitialspace=False,strict=True))
    if recovered!=[['id','text']]+values:raise ValueError('exact field comparison failed')
    print(json.dumps({'records':len(values),'exact_fields':True}))
if __name__=='__main__':
    p=argparse.ArgumentParser();p.add_argument('source');p.add_argument('target');a=p.parse_args()
    try:export(a.source,a.target)
    except (ValueError,OSError,csv.Error) as error:p.exit(1,type(error).__name__+': '+str(error)+'\n')
