40-validation/validate-relationship-types.py

#!/usr/bin/env python3
import argparse,json
from pathlib import Path
def validate(catalog_path,relationships_path):
 errors=[]
 try:catalog=json.loads(catalog_path.read_text());data=json.loads(relationships_path.read_text())
 except Exception as e:return {"status":"FAILED","errors":[{"code":"INVALID_INPUT","message":str(e)}]}
 legacy=set(catalog.get("legacy",[]));extensions=catalog.get("extensions",{});allowed=legacy|set(extensions);rels=data.get("relationships",[]);temporal=0
 for i,r in enumerate(rels):
  loc=f"relationships[{i}]";source=r.get("source");target=r.get("target");kind=r.get("type")
  if not isinstance(source,str) or not source:errors.append({"code":"MISSING_SOURCE","location":loc})
  if not isinstance(target,str) or not target:errors.append({"code":"MISSING_TARGET","location":loc})
  if kind not in allowed:errors.append({"code":"UNKNOWN_RELATIONSHIP_TYPE","location":loc,"type":kind});continue
  if kind in extensions:
   temporal+=1
   if source==target:errors.append({"code":"INVALID_TEMPORAL_SELF_RELATION","location":loc,"type":kind})
   required=extensions[kind].get("targetKind")
   if required and r.get("targetKind")!=required:errors.append({"code":"INVALID_TEMPORAL_TARGET","location":loc,"expected":required})
 return {"schemaVersion":"1.0","workItem":"SE-0028","status":"FAILED" if errors else "PASSED","catalog":{"legacy":len(legacy),"extensions":len(extensions),"allowed":len(allowed)},"relationships":len(rels),"temporalOrEvolutionRelationships":temporal,"errors":errors}
def main():
 p=argparse.ArgumentParser();p.add_argument("--catalog",type=Path,required=True);p.add_argument("--relationships",type=Path,required=True);p.add_argument("--output",type=Path);a=p.parse_args();r=validate(a.catalog,a.relationships);text=json.dumps(r,ensure_ascii=False,indent=2)+"\n"
 if a.output:a.output.parent.mkdir(parents=True,exist_ok=True);a.output.write_text(text)
 else:print(text,end="")
 raise SystemExit(0 if r["status"]=="PASSED" else 1)
if __name__=="__main__":main()