improved OptionalSetting
[pyvconv.git] / pyvconv.py
blobed8891aa1d86725df0bde971af79960d006eb536
1 import libxml2
2 import re
4 class Variable:
5 def __init__(self, namestr, defaultstr, exprstr):
6 self.namestr = namestr
7 self.defaultstr = defaultstr
8 self.exprstr = exprstr
10 def __str__(self):
11 return self.namestr
13 def has_value(self):
14 return self.defaultstr != None
16 def evaluate(self):
17 return self.exprstr
19 class OptionalSetting:
20 def __init__(self, namestr, exprstr):
21 self.namestr = namestr
22 self.exprstr = exprstr
24 def get_name(self):
25 return self.namestr
27 def evaluate(self, var_list):
28 instr = self.exprstr
29 for var in var_list:
30 if var_list[var].has_value():
31 p = re.compile( '\$\{' + var + '\}')
32 instr = p.sub( var_list[var].get_value(), instr)
33 if instr.find("$") != -1:
34 instr = "" # if not all variables were found, return empty option
35 return instr
37 class RenderCommand:
38 def __init__(self, namestr, callstr, var_list, optset_list):
39 self.namestr = namestr
40 self.callstr = callstr
41 self.var_list = var_list
42 self.optset_list = optset_list
44 def get_name(self):
45 return self.namestr
47 def evaluate(self):
48 instr = self.callstr
50 p = re.compile("\$\[(\w+)\]")
51 for o in p.findall(instr):
52 if o not in self.optset_list:
53 raise "Error: Optional variable not defined"
54 instr = p.sub(self.optset_list[o].evaluate(self.var_list), instr)
56 p = re.compile("\$\{(\w+)\}")
57 for o in p.findall(instr):
58 instr = p.sub(self.var_list[o].evaluate(), instr)
60 if instr.find("$") != -1:
61 raise "Error: all variables were not expanded"
62 return instr
64 class RenderCommands:
65 def __init__(self):
66 self.cmdcall_dict = {}
67 self._read_config()
69 def _read_properties(self, propnode, mand_propnames, opt_propnames = []):
70 propdict = {}
72 for p in propnode:
73 if p.name in mand_propnames:
74 propdict[p.name] = str(p.content)
75 elif p.name != "text" and p.name not in opt_propnames:
76 raise "Error parsing XML: only name and call are accepted properties in the element command, found " + str(p.name)
78 if len(mand_propnames) != len(propdict.keys()):
79 raise "Error parsing XML: must supply both name and call in element command"
81 for p in propnode:
82 if p.name in opt_propnames:
83 propdict[p.name] = str(p.content)
84 elif p.name != "text" and p.name not in mand_propnames:
85 raise "Error parsing XML: only name and call are accepted properties in the element command, found " + str(p.name)
87 return propdict
89 def _read_config(self):
90 doc = libxml2.parseFile("rendercommands.xml")
91 cmd_xmllist = doc.xpathEval( '//command')
93 # read all commands from XML description
94 for cmdnode in cmd_xmllist:
95 if cmdnode.type == "element" and cmdnode.name == "command":
97 if cmdnode.children:
98 for varsetnode in cmdnode.children:
99 var_list = {}
100 optset_list = {}
102 if varsetnode.type == "element" and varsetnode.name == "variable":
103 props = self._read_properties(varsetnode.properties, ["name", "expr"], ["default"])
104 defprop = None
105 if "default" in props:
106 defprop = props["default"]
107 var_list[props["name"]] = Variable(props["name"], defprop, props["expr"])
109 elif varsetnode.type == "element" and varsetnode.name == "optionalsetting":
110 props = self._read_properties(varsetnode.properties, ["name", "expr"])
111 optset_list[props["name"]] = OptionalSetting(props["name"], props["expr"])
113 elif varsetnode.name != "text":
114 raise "Error parsing XML: only variable and optionalsetting elements allowed in command"
116 props = self._read_properties(cmdnode.properties, ["name", "call"])
117 self.cmdcall_dict[props["name"]] = RenderCommand(props["name"], props["call"], var_list, optset_list)
119 else:
120 raise "Error parsing XML: only command elements are supported"
122 print self.cmdcall_dict
124 def main():
125 commands = RenderCommands()
127 if __name__ == "__main__":
128 main()