diff --git a/tools/create_childs.py b/tools/create_childs.py index 09d002ec2..c9f8bc9af 100644 --- a/tools/create_childs.py +++ b/tools/create_childs.py @@ -3,9 +3,10 @@ Options ------- - -P|--parents=NAME:VALUE,... specify parent property pattern to match - -C|--childs=NAME:VALUE,... specify child property list to assign - -N|--names=STRING specify object naming convention + -P|--parents=NAME:VALUE,... specify parent property pattern to match (required) + -C|--childs=NAME:VALUE,... specify child property list to assign (required) + -N|--names=STRING specify object naming convention (default is '{class}_{name}') + -M|--modules=NAME,... specify module names to use (defaults to those found) Description ----------- @@ -36,6 +37,8 @@ import json import re import datetime +import subprocess +import random EXENAME = os.path.splitext(os.path.basename(sys.argv[0]))[0] @@ -58,21 +61,58 @@ def error(msg,code=None): if type(code) is int: global EXITCODE EXITCODE = code - raise GldException(msg) + if DEBUG: + raise GldException(msg) + print("ERROR [create_childs]:",msg,file=sys.stderr) + exit(code) + + +def load(): + + if not INPUTFILE.endswith(".json"): + tmpfile = "." + while os.path.exists(tmpfile): + tmpfile = f"tmp{hex(random.randint(1e30,1e31))[2:]}.json" + try: + result = subprocess.run(["gridlabd","-C",INPUTFILE,"-o",tmpfile]) + assert(result.returncode==0) + with open(tmpfile,"r") as fh: + model = json.load(fh) + except: + raise + finally: + os.remove(tmpfile) + pass + else: + with open(INPUTFILE,"r") as fh: + model = json.load(fh) + return model + +def save(fh): + print(f"// generated by '{' '.join(sys.argv)}' at {datetime.datetime.now()}",file=fh) + for name in MODULES: + print(f"module {name};",file=fh) + classname = CHILDS["class"] + for obj,data in OBJECTS.items(): + print(f"object {classname} {{",file=fh) + for prop,value in data.items(): + print(f" {prop} \"{value}\";",file=fh) + print("}",file=fh) def main(): PATTERN = {} for name,pattern in PARENTS.items(): PATTERN[name] = re.compile(pattern) - OBJECTS = {} + if "class" not in CHILDS: error("you must include a class name in the child properties",E_INVALID) classname = CHILDS["class"] - - with open(INPUTFILE,"r") as fh: - model = json.load(fh) + model = load() assert(model['application']=='gridlabd') + global MODULES + if not MODULES: + MODULES = list(model['modules']) for obj,data in model['objects'].items(): data['name'] = obj @@ -88,13 +128,11 @@ def main(): if not prop in ["class"]: OBJECTS[name][prop] = value.format(**data) - with open(OUTPUTFILE,"w") as fh: - print(f"// generated by '{' '.join(sys.argv)}' at {datetime.datetime.now()}",file=fh) - for obj,data in OBJECTS.items(): - print(f"object {classname} {{",file=fh) - for prop,value in data.items(): - print(f" {prop} \"{value}\";",file=fh) - print("}",file=fh) + if OUTPUTFILE.endswith(".glm"): + with open(OUTPUTFILE,"w") as fh: + save(fh) + else: + error("invalid output file format") return E_OK @@ -103,6 +141,8 @@ def main(): PARENTS = None CHILDS = None NAMING = None +OBJECTS = {} +MODULES = [] if __name__ == "__main__": @@ -132,6 +172,8 @@ def main(): CHILDS = dict([x.split(":") for x in value.split(",")]) elif tag in ["-N","--names"]: NAMING = value + elif tag in ["-M","--modules"]: + MODULES = value.split(",") else: error(f"option '{arg}' is invalid",E_INVALID)