--- a/PLCControler.py Wed Aug 28 11:43:51 2013 +0200
+++ b/PLCControler.py Wed Aug 28 11:53:50 2013 +0200
@@ -29,7 +29,7 @@
import datetime
from time import localtime
-from plcopen import plcopen
+from plcopen import PLCOpenParser, LoadProject, SaveProject
from plcopen.structures import *
from graphics.GraphicCommons import *
from PLCGenerator import *
@@ -66,14 +66,14 @@
ITEM_VAR_INOUT
] = range(17, 24)
-VAR_CLASS_INFOS = {"Local" : (plcopen.interface_localVars, ITEM_VAR_LOCAL),
- "Global" : (plcopen.interface_globalVars, ITEM_VAR_GLOBAL),
- "External" : (plcopen.interface_externalVars, ITEM_VAR_EXTERNAL),
- "Temp" : (plcopen.interface_tempVars, ITEM_VAR_TEMP),
- "Input" : (plcopen.interface_inputVars, ITEM_VAR_INPUT),
- "Output" : (plcopen.interface_outputVars, ITEM_VAR_OUTPUT),
- "InOut" : (plcopen.interface_inOutVars, ITEM_VAR_INOUT)
- }
+VAR_CLASS_INFOS = {
+ "Local": ("localVars", ITEM_VAR_LOCAL),
+ "Global": ("globalVars", ITEM_VAR_GLOBAL),
+ "External": ("externalVars", ITEM_VAR_EXTERNAL),
+ "Temp": ("tempVars", ITEM_VAR_TEMP),
+ "Input": ("inputVars", ITEM_VAR_INPUT),
+ "Output": ("outputVars", ITEM_VAR_OUTPUT),
+ "InOut": ("inOutVars", ITEM_VAR_INOUT)}
POU_TYPES = {"program": ITEM_PROGRAM,
"functionBlock": ITEM_FUNCTIONBLOCK,
@@ -234,16 +234,20 @@
# Create a new project by replacing the current one
def CreateNewProject(self, properties):
# Create the project
- self.Project = plcopen.project()
+ self.Project = PLCOpenParser.CreateRoot()
properties["creationDateTime"] = datetime.datetime(*localtime()[:6])
self.Project.setfileHeader(properties)
self.Project.setcontentHeader(properties)
self.SetFilePath("")
+
+ ## To remove when project buffering ready
+ self.ProjectBufferEnabled = False
+
# Initialize the project buffer
self.CreateProjectBuffer(False)
self.ProgramChunks = []
self.ProgramOffset = 0
- self.NextCompiledProject = self.Copy(self.Project)
+ self.NextCompiledProject = self.Project #self.Copy(self.Project)
self.CurrentCompiledProject = None
self.Buffering = False
@@ -390,8 +394,9 @@
def GetPouVariableInfos(self, project, variable, var_class, debug=False):
vartype_content = variable.gettype().getcontent()
- if vartype_content["name"] == "derived":
- var_type = vartype_content["value"].getname()
+ vartype_content_type = vartype_content.getLocalTag()
+ if vartype_content_type == "derived":
+ var_type = vartype_content.getname()
pou_type = None
pou = project.getpou(var_type)
if pou is not None:
@@ -419,15 +424,15 @@
"class": var_class,
"edit": False,
"debug": False}
- elif vartype_content["name"] in ["string", "wstring"]:
+ elif vartype_content_type in ["string", "wstring"]:
return {"name": variable.getname(),
- "type": vartype_content["name"].upper(),
+ "type": vartype_content_type.upper(),
"class": var_class,
"edit": False,
"debug": True}
else:
return {"name": variable.getname(),
- "type": vartype_content["name"],
+ "type": vartype_content_type,
"class": var_class,
"edit": False,
"debug": True}
@@ -556,9 +561,9 @@
for varlist in varlists:
for variable in varlist.getvariable():
vartype_content = variable.gettype().getcontent()
- if vartype_content["name"] == "derived":
+ if vartype_content.getLocalTag() == "derived":
var_path = "%s.%s" % (parent_path, variable.getname())
- var_type = vartype_content["value"].getname()
+ var_type = vartype_content.getname()
if var_type == pou_type:
instances.append(var_path)
else:
@@ -625,7 +630,7 @@
for variable in varlist.getvariable():
if variable.getname() == parts[0]:
vartype_content = variable.gettype().getcontent()
- if vartype_content["name"] == "derived":
+ if vartype_content.getLocalTag() == "derived":
return self.RecursiveGetPouInstanceTagName(
project,
vartype_content["value"].getname(),
@@ -656,14 +661,14 @@
for variable in varlist.getvariable():
if variable.getname() == parts[0]:
vartype_content = variable.gettype().getcontent()
- if vartype_content["name"] == "derived":
+ if vartype_content.getLocalTag() == "derived":
if len(parts) == 1:
return self.ComputePouName(
- vartype_content["value"].getname())
+ vartype_content.getname())
else:
return self.RecursiveGetPouInstanceTagName(
project,
- vartype_content["value"].getname(),
+ vartype_content.getname(),
parts[1:], debug)
return None
@@ -1170,9 +1175,9 @@
current_type = next_type
infos = VAR_CLASS_INFOS.get(var["Class"], None)
if infos is not None:
- current_varlist = infos[0]()
+ current_varlist = PLCOpenParser.CreateElement(infos[0], "interface")
else:
- current_varlist = plcopen.varList()
+ current_varlist = PLCOpenParser.CreateElement("varList")
varlist_list.append((var["Class"], current_varlist))
if var["Option"] == "Constant":
current_varlist.setconstant(True)
@@ -1181,14 +1186,14 @@
elif var["Option"] == "Non-Retain":
current_varlist.setnonretain(True)
# Create variable and change its properties
- tempvar = plcopen.varListPlain_variable()
+ tempvar = PLCOpenParser.CreateElement("variable", "varListPlain")
tempvar.setname(var["Name"])
- var_type = plcopen.dataType()
+ var_type = PLCOpenParser.CreateElement("type", "variable")
if isinstance(var["Type"], TupleType):
if var["Type"][0] == "array":
array_type, base_type_name, dimensions = var["Type"]
- array = plcopen.derivedTypes_array()
+ array = PLCOpenParser.CreateElement("array", "dataType")
for i, dimension in enumerate(dimensions):
dimension_range = plcopen.rangeSigned()
dimension_range.setlower(dimension[0])
@@ -1198,32 +1203,28 @@
else:
array.appenddimension(dimension_range)
if base_type_name in self.GetBaseTypes():
- if base_type_name == "STRING":
- array.baseType.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()})
- elif base_type_name == "WSTRING":
- array.baseType.setcontent({"name" : "wstring", "value" : plcopen.wstring()})
- else:
- array.baseType.setcontent({"name" : base_type_name, "value" : None})
+ array.baseType.setcontent(PLCOpenParser.CreateElement(
+ base_type_name.lower()
+ if base_type_name in ["STRING", "WSTRING"]
+ else base_type_name, "dataType"))
else:
- derived_datatype = plcopen.derivedTypes_derived()
+ derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
derived_datatype.setname(base_type_name)
- array.baseType.setcontent({"name" : "derived", "value" : derived_datatype})
- var_type.setcontent({"name" : "array", "value" : array})
+ array.baseType.setcontent(derived_datatype)
+ var_type.setcontent(array)
elif var["Type"] in self.GetBaseTypes():
- if var["Type"] == "STRING":
- var_type.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()})
- elif var["Type"] == "WSTRING":
- var_type.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()})
- else:
- var_type.setcontent({"name" : var["Type"], "value" : None})
+ var_type.setcontent(PLCOpenParser.CreateElement(
+ var["Type"].lower()
+ if var["Type"] in ["STRING", "WSTRING"]
+ else var["Type"], "dataType"))
else:
- derived_type = plcopen.derivedTypes_derived()
+ derived_type = PLCOpenParser.CreateElement("derived", "dataType")
derived_type.setname(var["Type"])
- var_type.setcontent({"name" : "derived", "value" : derived_type})
+ var_type.setcontent(derived_type)
tempvar.settype(var_type)
if var["Initial Value"] != "":
- value = plcopen.value()
+ value = PLCOpenParser.CreateElement("initialValue", "variable")
value.setvalue(var["Initial Value"])
tempvar.setinitialValue(value)
if var["Location"] != "":
@@ -1232,7 +1233,7 @@
tempvar.setaddress(None)
if var['Documentation'] != "":
ft = plcopen.formattedText()
- ft.settext(var['Documentation'])
+ ft.setanyText(var['Documentation'])
tempvar.setdocumentation(ft)
# Add variable to varList
@@ -1248,27 +1249,27 @@
tempvar = {"Name": var.getname()}
vartype_content = var.gettype().getcontent()
- if vartype_content["name"] == "derived":
- tempvar["Type"] = vartype_content["value"].getname()
- elif vartype_content["name"] == "array":
+ vartype_content_type = vartype_content.getLocalTag()
+ if vartype_content_type == "derived":
+ tempvar["Type"] = vartype_content.getname()
+ elif vartype_content_type == "array":
dimensions = []
- for dimension in vartype_content["value"].getdimension():
+ for dimension in vartype_content.getdimension():
dimensions.append((dimension.getlower(), dimension.getupper()))
- base_type = vartype_content["value"].baseType.getcontent()
- if base_type["value"] is None or base_type["name"] in ["string", "wstring"]:
- base_type_name = base_type["name"].upper()
+ base_type = vartype_content.baseType.getcontent()
+ base_type_type = base_type.getLocalTag()
+ if base_type is None or base_type_type in ["string", "wstring"]:
+ base_type_name = base_type_type.upper()
else:
- base_type_name = base_type["value"].getname()
+ base_type_name = base_type.getname()
tempvar["Type"] = ("array", base_type_name, dimensions)
- elif vartype_content["name"] in ["string", "wstring"]:
- tempvar["Type"] = vartype_content["name"].upper()
else:
- tempvar["Type"] = vartype_content["name"]
-
+ tempvar["Type"] = vartype_content_type.upper()
+
tempvar["Edit"] = True
initial = var.getinitialValue()
- if initial:
+ if initial is not None:
tempvar["Initial Value"] = initial.getvalue()
else:
tempvar["Initial Value"] = ""
@@ -1289,8 +1290,8 @@
tempvar["Option"] = ""
doc = var.getdocumentation()
- if doc:
- tempvar["Documentation"] = doc.gettext()
+ if doc is not None:
+ tempvar["Documentation"] = doc.getanyText()
else:
tempvar["Documentation"] = ""
@@ -1313,9 +1314,9 @@
configuration = self.Project.getconfiguration(name)
if configuration is not None:
# Set configuration global vars
- configuration.setglobalVars([])
- for vartype, varlist in self.ExtractVarLists(vars):
- configuration.globalVars.append(varlist)
+ configuration.setglobalVars([
+ varlist for vartype, varlist
+ in self.ExtractVarLists(vars)])
# Return the configuration globalvars
def GetConfigurationGlobalVars(self, name, debug = False):
@@ -1354,9 +1355,9 @@
resource = self.Project.getconfigurationResource(config_name, name)
# Set resource global vars
if resource is not None:
- resource.setglobalVars([])
- for vartype, varlist in self.ExtractVarLists(vars):
- resource.globalVars.append(varlist)
+ resource.setglobalVars([
+ varlist for vartype, varlist
+ in self.ExtractVarLists(vars)])
# Return the resource globalvars
def GetConfigurationResourceGlobalVars(self, config_name, name, debug = False):
@@ -1415,25 +1416,27 @@
if datatype is not None:
tree = []
basetype_content = datatype.baseType.getcontent()
- if basetype_content["name"] == "derived":
- return self.GenerateVarTree(basetype_content["value"].getname())
- elif basetype_content["name"] == "array":
+ basetype_content_type = basetype_content.getLocalTag()
+ if basetype_content_type == "derived":
+ return self.GenerateVarTree(basetype_content.getname())
+ elif basetype_content_type == "array":
dimensions = []
- base_type = basetype_content["value"].baseType.getcontent()
- if base_type["name"] == "derived":
- tree = self.GenerateVarTree(base_type["value"].getname())
+ base_type = basetype_content.baseType.getcontent()
+ if base_type.getLocalTag() == "derived":
+ tree = self.GenerateVarTree(base_type.getname())
if len(tree[1]) == 0:
tree = tree[0]
- for dimension in basetype_content["value"].getdimension():
+ for dimension in basetype_content.getdimension():
dimensions.append((dimension.getlower(), dimension.getupper()))
return tree, dimensions
- elif basetype_content["name"] == "struct":
- for element in basetype_content["value"].getvariable():
+ elif basetype_content_type == "struct":
+ for element in basetype_content.getvariable():
element_type = element.type.getcontent()
- if element_type["name"] == "derived":
- tree.append((element.getname(), element_type["value"].getname(), self.GenerateVarTree(element_type["value"].getname())))
+ element_type_type = element_type.getLocalTag()
+ if element_type_type == "derived":
+ tree.append((element.getname(), element_type.getname(), self.GenerateVarTree(element_type.getname())))
else:
- tree.append((element.getname(), element_type["name"], ([], [])))
+ tree.append((element.getname(), element_type_type, ([], [])))
return tree, []
return [], []
@@ -1451,7 +1454,7 @@
tempvar["Tree"] = ([], [])
vartype_content = var.gettype().getcontent()
- if vartype_content["name"] == "derived":
+ if vartype_content.getLocalTag() == "derived":
tempvar["Edit"] = not pou.hasblock(tempvar["Name"])
tempvar["Tree"] = self.GenerateVarTree(tempvar["Type"], debug)
@@ -1465,36 +1468,34 @@
pou = self.Project.getpou(name)
if pou is not None:
if pou.interface is None:
- pou.interface = plcopen.pou_interface()
+ pou.interface = PLCOpenParser.CreateElement("interface", "pou")
# Set Pou interface
- pou.setvars(self.ExtractVarLists(vars))
+ pou.setvars([varlist for varlist_type, varlist in self.ExtractVarLists(vars)])
self.Project.RefreshElementUsingTree()
self.Project.RefreshCustomBlockTypes()
# Replace the return type of the pou given by its name (only for functions)
- def SetPouInterfaceReturnType(self, name, type):
+ def SetPouInterfaceReturnType(self, name, return_type):
if self.Project is not None:
pou = self.Project.getpou(name)
if pou is not None:
if pou.interface is None:
- pou.interface = plcopen.pou_interface()
+ pou.interface = PLCOpenParser.CreateElement("interface", "pou")
# If there isn't any return type yet, add it
- return_type = pou.interface.getreturnType()
- if not return_type:
- return_type = plcopen.dataType()
- pou.interface.setreturnType(return_type)
+ return_type_obj = pou.interface.getreturnType()
+ if not return_type_obj:
+ return_type_obj = PLCOpenParser.CreateElement("returnType", "interface")
+ pou.interface.setreturnType(return_type_obj)
# Change return type
- if type in self.GetBaseTypes():
- if type == "STRING":
- return_type.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()})
- elif type == "WSTRING":
- return_type.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()})
- else:
- return_type.setcontent({"name" : type, "value" : None})
+ if return_type in self.GetBaseTypes():
+ return_type_obj.setcontent(PLCOpenParser.CreateElement(
+ return_type.lower()
+ if return_type in ["STRING", "WSTRING"]
+ else return_type, "dataType"))
else:
- derived_type = plcopen.derivedTypes_derived()
- derived_type.setname(type)
- return_type.setcontent({"name" : "derived", "value" : derived_type})
+ derived_type = PLCOpenParser.CreateElement("derived", "dataType")
+ derived_type.setname(return_type)
+ return_type.setcontent(derived_type)
self.Project.RefreshElementUsingTree()
self.Project.RefreshCustomBlockTypes()
@@ -1523,14 +1524,13 @@
if pou.interface is not None:
# Return the return type if there is one
return_type = pou.interface.getreturnType()
- if return_type:
+ if return_type is not None:
returntype_content = return_type.getcontent()
- if returntype_content["name"] == "derived":
- return returntype_content["value"].getname()
- elif returntype_content["name"] in ["string", "wstring"]:
- return returntype_content["name"].upper()
+ returntype_content_type = returntype_content.getLocalTag()
+ if returntype_content_type == "derived":
+ return returntype_content.getname()
else:
- return returntype_content["name"]
+ return returntype_content_type.upper()
return None
# Function that add a new confnode to the confnode list
@@ -1577,25 +1577,23 @@
def GetConfigurationExtraVariables(self):
global_vars = []
for var_name, var_type, var_initial in self.GetConfNodeGlobalInstances():
- tempvar = plcopen.varListPlain_variable()
+ tempvar = PLCOpenParser.CreateElement("variable", "globalVars")
tempvar.setname(var_name)
- tempvartype = plcopen.dataType()
+ tempvartype = PLCOpenParser.CreateElement("dataType", "variable")
if var_type in self.GetBaseTypes():
- if var_type == "STRING":
- tempvartype.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()})
- elif var_type == "WSTRING":
- tempvartype.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()})
- else:
- tempvartype.setcontent({"name" : var_type, "value" : None})
+ tempvar.setcontent(PLCOpenParser.CreateElement(
+ var_type.lower()
+ if var_type in ["STRING", "WSTRING"]
+ else var_type, "dataType"))
else:
- tempderivedtype = plcopen.derivedTypes_derived()
+ tempderivedtype = PLCOpenParser.CreateElement("derived", "dataType")
tempderivedtype.setname(var_type)
- tempvartype.setcontent({"name" : "derived", "value" : tempderivedtype})
+ tempvartype.setcontent(tempderivedtype)
tempvar.settype(tempvartype)
if var_initial != "":
- value = plcopen.value()
+ value = PLCOpenParser.CreateElement("initialValue", "variable")
value.setvalue(var_initial)
tempvar.setinitialValue(value)
@@ -1764,7 +1762,7 @@
datatype = self.GetConfNodeDataType(type)
if datatype is not None:
basetype_content = datatype.baseType.getcontent()
- return basetype_content["name"] == "enum"
+ return basetype_content.getLocalTag() == "enum"
return False
def IsNumType(self, type, debug = False):
@@ -1859,62 +1857,64 @@
if datatype is None:
return None
basetype_content = datatype.baseType.getcontent()
- if basetype_content["value"] is None or basetype_content["name"] in ["string", "wstring"]:
- infos["type"] = "Directly"
- infos["base_type"] = basetype_content["name"].upper()
- elif basetype_content["name"] == "derived":
- infos["type"] = "Directly"
- infos["base_type"] = basetype_content["value"].getname()
- elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]:
+ basetype_content_type = basetype_content.getLocalTag()
+ if basetype_content_type in ["subrangeSigned", "subrangeUnsigned"]:
infos["type"] = "Subrange"
- infos["min"] = basetype_content["value"].range.getlower()
- infos["max"] = basetype_content["value"].range.getupper()
- base_type = basetype_content["value"].baseType.getcontent()
- if base_type["value"] is None:
- infos["base_type"] = base_type["name"]
- else:
- infos["base_type"] = base_type["value"].getname()
- elif basetype_content["name"] == "enum":
+ infos["min"] = basetype_content.range.getlower()
+ infos["max"] = basetype_content.range.getupper()
+ base_type = basetype_content.baseType.getcontent()
+ base_type_type = base_type.getLocalTag()
+ infos["base_type"] = (base_type.getname()
+ if base_type_type == "derived"
+ else base_type_type)
+ elif basetype_content_type == "enum":
infos["type"] = "Enumerated"
infos["values"] = []
- for value in basetype_content["value"].values.getvalue():
+ for value in basetype_content.xpath("ppx:values/ppx:value", namespaces=PLCOpenParser.NSMAP):
infos["values"].append(value.getname())
- elif basetype_content["name"] == "array":
+ elif basetype_content_type == "array":
infos["type"] = "Array"
infos["dimensions"] = []
- for dimension in basetype_content["value"].getdimension():
+ for dimension in basetype_content.getdimension():
infos["dimensions"].append((dimension.getlower(), dimension.getupper()))
- base_type = basetype_content["value"].baseType.getcontent()
- if base_type["value"] is None or base_type["name"] in ["string", "wstring"]:
- infos["base_type"] = base_type["name"].upper()
- else:
- infos["base_type"] = base_type["value"].getname()
- elif basetype_content["name"] == "struct":
+ base_type = basetype_content.baseType.getcontent()
+ base_type_type = base_type.getLocalTag()
+ infos["base_type"] = (base_type.getname()
+ if base_type_type == "derived"
+ else base_type_type.upper())
+ elif basetype_content_type == "struct":
infos["type"] = "Structure"
infos["elements"] = []
- for element in basetype_content["value"].getvariable():
+ for element in basetype_content.getvariable():
element_infos = {}
element_infos["Name"] = element.getname()
element_type = element.type.getcontent()
- if element_type["value"] is None or element_type["name"] in ["string", "wstring"]:
- element_infos["Type"] = element_type["name"].upper()
- elif element_type["name"] == "array":
+ element_type_type = element_type.getLocalTag()
+ if element_type_type == "array":
dimensions = []
- for dimension in element_type["value"].getdimension():
+ for dimension in element_type.getdimension():
dimensions.append((dimension.getlower(), dimension.getupper()))
- base_type = element_type["value"].baseType.getcontent()
- if base_type["value"] is None or base_type["name"] in ["string", "wstring"]:
- base_type_name = base_type["name"].upper()
- else:
- base_type_name = base_type["value"].getname()
- element_infos["Type"] = ("array", base_type_name, dimensions)
+ base_type = element_type.baseType.getcontent()
+ base_type_type = element_type.getLocalTag()
+ element_infos["Type"] = ("array",
+ base_type.getname()
+ if base_type_type == "derived"
+ else base_type_type.upper(), dimensions)
+ elif element_type_type == "derived":
+ element_infos["Type"] = element_type.getname()
else:
- element_infos["Type"] = element_type["value"].getname()
+ element_infos["Type"] = element_type_type.upper()
if element.initialValue is not None:
element_infos["Initial Value"] = str(element.initialValue.getvalue())
else:
element_infos["Initial Value"] = ""
infos["elements"].append(element_infos)
+ else:
+ infos["type"] = "Directly"
+ infos["base_type"] = (basetype_content.getname()
+ if basetype_content_type == "derived"
+ else basetype_content_type.upper())
+
if datatype.initialValue is not None:
infos["initial"] = str(datatype.initialValue.getvalue())
else:
@@ -1929,45 +1929,44 @@
datatype = self.Project.getdataType(words[1])
if infos["type"] == "Directly":
if infos["base_type"] in self.GetBaseTypes():
- if infos["base_type"] == "STRING":
- datatype.baseType.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()})
- elif infos["base_type"] == "WSTRING":
- datatype.baseType.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()})
- else:
- datatype.baseType.setcontent({"name" : infos["base_type"], "value" : None})
+ datatype.baseType.setcontent(PLCOpenParser.CreateElement(
+ infos["base_type"].lower()
+ if infos["base_type"] in ["STRING", "WSTRING"]
+ else infos["base_type"], "dataType"))
else:
- derived_datatype = plcopen.derivedTypes_derived()
+ derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
derived_datatype.setname(infos["base_type"])
- datatype.baseType.setcontent({"name" : "derived", "value" : derived_datatype})
+ datatype.baseType.setcontent(derived_datatype)
elif infos["type"] == "Subrange":
- if infos["base_type"] in GetSubTypes("ANY_UINT"):
- subrange = plcopen.derivedTypes_subrangeUnsigned()
- datatype.baseType.setcontent({"name" : "subrangeUnsigned", "value" : subrange})
- else:
- subrange = plcopen.derivedTypes_subrangeSigned()
- datatype.baseType.setcontent({"name" : "subrangeSigned", "value" : subrange})
+ datatype.baseType.setcontent(PLCOpenParser.CreateElement(
+ "subrangeUnsigned"
+ if infos["base_type"] in GetSubTypes("ANY_UINT")
+ else "subrangeSigned", "dataType"))
subrange.range.setlower(infos["min"])
subrange.range.setupper(infos["max"])
if infos["base_type"] in self.GetBaseTypes():
- subrange.baseType.setcontent({"name" : infos["base_type"], "value" : None})
+ subrange.baseType.setcontent(
+ PLCOpenParser.CreateElement(infos["base_type"]))
else:
- derived_datatype = plcopen.derivedTypes_derived()
+ derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
derived_datatype.setname(infos["base_type"])
- subrange.baseType.setcontent({"name" : "derived", "value" : derived_datatype})
+ subrange.baseType.setcontent(derived_datatype)
elif infos["type"] == "Enumerated":
- enumerated = plcopen.derivedTypes_enum()
+ enumerated = PLCOpenParser.CreateElement("enum", "dataType")
+ values = PLCOpenParser.CreateElement("values", "enum")
+ enumerated.setvalues(values)
for i, enum_value in enumerate(infos["values"]):
- value = plcopen.values_value()
+ value = PLCOpenParser.CreateElement("value", "values")
value.setname(enum_value)
if i == 0:
- enumerated.values.setvalue([value])
+ values.setvalue([value])
else:
- enumerated.values.appendvalue(value)
- datatype.baseType.setcontent({"name" : "enum", "value" : enumerated})
+ values.appendvalue(value)
+ datatype.baseType.setcontent(enumerated)
elif infos["type"] == "Array":
- array = plcopen.derivedTypes_array()
+ array = PLCOpenParser.CreateElement("array", "dataType")
for i, dimension in enumerate(infos["dimensions"]):
- dimension_range = plcopen.rangeSigned()
+ dimension_range = PLCOpenParser.CreateElement("dimension", "array")
dimension_range.setlower(dimension[0])
dimension_range.setupper(dimension[1])
if i == 0:
@@ -1975,28 +1974,27 @@
else:
array.appenddimension(dimension_range)
if infos["base_type"] in self.GetBaseTypes():
- if infos["base_type"] == "STRING":
- array.baseType.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()})
- elif infos["base_type"] == "WSTRING":
- array.baseType.setcontent({"name" : "wstring", "value" : plcopen.wstring()})
- else:
- array.baseType.setcontent({"name" : infos["base_type"], "value" : None})
+ array.baseType.setcontent(PLCOpenParser.CreateElement(
+ infos["base_type"].lower()
+ if infos["base_type"] in ["STRING", "WSTRING"]
+ else infos["base_type"], "dataType"))
else:
- derived_datatype = plcopen.derivedTypes_derived()
+ derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
derived_datatype.setname(infos["base_type"])
- array.baseType.setcontent({"name" : "derived", "value" : derived_datatype})
- datatype.baseType.setcontent({"name" : "array", "value" : array})
+ array.baseType.setcontent(derived_datatype)
+ datatype.baseType.setcontent(array)
elif infos["type"] == "Structure":
- struct = plcopen.varListPlain()
+ struct = PLCOpenParser.CreateElement("struct", "dataType")
for i, element_infos in enumerate(infos["elements"]):
- element = plcopen.varListPlain_variable()
+ element = PLCOpenParser.CreateElement("variable", "struct")
element.setname(element_infos["Name"])
+ element_type = PLCOpenParser.CreateElement("type", "variable")
if isinstance(element_infos["Type"], TupleType):
if element_infos["Type"][0] == "array":
array_type, base_type_name, dimensions = element_infos["Type"]
- array = plcopen.derivedTypes_array()
+ array = PLCOpenParser.CreateElement("array", "dataType")
for j, dimension in enumerate(dimensions):
- dimension_range = plcopen.rangeSigned()
+ dimension_range = PLCOpenParser.CreateElement("dimension", "array")
dimension_range.setlower(dimension[0])
dimension_range.setupper(dimension[1])
if j == 0:
@@ -2004,40 +2002,38 @@
else:
array.appenddimension(dimension_range)
if base_type_name in self.GetBaseTypes():
- if base_type_name == "STRING":
- array.baseType.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()})
- elif base_type_name == "WSTRING":
- array.baseType.setcontent({"name" : "wstring", "value" : plcopen.wstring()})
- else:
- array.baseType.setcontent({"name" : base_type_name, "value" : None})
+ array.baseType.setcontent(PLCOpenParser.CreateElement(
+ base_type_name.lower()
+ if base_type_name in ["STRING", "WSTRING"]
+ else base_type_name, "dataType"))
else:
- derived_datatype = plcopen.derivedTypes_derived()
+ derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
derived_datatype.setname(base_type_name)
- array.baseType.setcontent({"name" : "derived", "value" : derived_datatype})
- element.type.setcontent({"name" : "array", "value" : array})
+ array.baseType.setcontent(derived_datatype)
+ element_type.setcontent(array)
elif element_infos["Type"] in self.GetBaseTypes():
- if element_infos["Type"] == "STRING":
- element.type.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()})
- elif element_infos["Type"] == "WSTRING":
- element.type.setcontent({"name" : "wstring", "value" : plcopen.wstring()})
- else:
- element.type.setcontent({"name" : element_infos["Type"], "value" : None})
+ element_type.setcontent(
+ PLCOpenParser.CreateElement(
+ element_infos["Type"].lower()
+ if element_infos["Type"] in ["STRING", "WSTRING"]
+ else element_infos["Type"], "dataType"))
else:
- derived_datatype = plcopen.derivedTypes_derived()
+ derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
derived_datatype.setname(element_infos["Type"])
- element.type.setcontent({"name" : "derived", "value" : derived_datatype})
+ element_type.setcontent(derived_datatype)
+ element.settype(element_type)
if element_infos["Initial Value"] != "":
- value = plcopen.value()
+ value = PLCOpenParser.CreateElement("initialValue", "variable")
value.setvalue(element_infos["Initial Value"])
element.setinitialValue(value)
if i == 0:
struct.setvariable([element])
else:
struct.appendvariable(element)
- datatype.baseType.setcontent({"name" : "struct", "value" : struct})
+ datatype.baseType.setcontent(struct)
if infos["initial"] != "":
if datatype.initialValue is None:
- datatype.initialValue = plcopen.value()
+ datatype.initialValue = PLCOpenParser.CreateElement("initialValue", "dataType")
datatype.initialValue.setvalue(infos["initial"])
else:
datatype.initialValue = None
@@ -2201,9 +2197,10 @@
element = self.GetEditedElement(tagname, debug)
if element is not None and element.getbodyType() not in ["ST", "IL"]:
for instance in element.getinstances():
- if isinstance(instance, (plcopen.sfcObjects_step,
- plcopen.commonObjects_connector,
- plcopen.commonObjects_continuation)):
+ if isinstance(instance,
+ (PLCOpenParser.GetElementClass("step", "sfcObjects"),
+ PLCOpenParser.GetElementClass("connector", "commonObjects"),
+ PLCOpenParser.GetElementClass("continuation", "commonObjects"))):
names[instance.getname().upper()] = True
else:
project = self.GetProject(debug)
@@ -2392,12 +2389,11 @@
for var in varlist.getvariable():
if var.getname() == varname:
vartype_content = var.gettype().getcontent()
- if vartype_content["name"] == "derived":
- return vartype_content["value"].getname()
- elif vartype_content["name"] in ["string", "wstring"]:
- return vartype_content["name"].upper()
+ vartype_content_type = vartype_content.getLocalTag()
+ if vartype_content_type == "derived":
+ return vartype_content.getname()
else:
- return vartype_content["name"]
+ return vartype_content_type.upper()
return None
def SetConnectionWires(self, connection, connector):
@@ -2457,7 +2453,7 @@
def AddEditedElementBlock(self, tagname, id, blocktype, blockname = None):
element = self.GetEditedElement(tagname)
if element is not None:
- block = plcopen.fbdObjects_block()
+ block = PLCOpenParser.CreateElement("block", "fbdObjects")
block.setlocalId(id)
block.settypeName(blocktype)
blocktype_infos = self.GetBlockType(blocktype)
@@ -3136,31 +3132,27 @@
return tasks_data, instances_data
def OpenXMLFile(self, filepath):
- xmlfile = open(filepath, 'r')
- tree = minidom.parse(xmlfile)
- xmlfile.close()
+ try:
+ self.Project = LoadProject(filepath)
+ except Exception, e:
+ return _("Project file syntax error:\n\n") + str(e)
+ self.SetFilePath(filepath)
+ self.Project.RefreshElementUsingTree()
+ self.Project.RefreshDataTypeHierarchy()
+ self.Project.RefreshCustomBlockTypes()
- self.Project = plcopen.project()
- for child in tree.childNodes:
- if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "project":
- try:
- result = self.Project.loadXMLTree(child)
- except ValueError, e:
- return _("Project file syntax error:\n\n") + str(e)
- self.SetFilePath(filepath)
- self.Project.RefreshElementUsingTree()
- self.Project.RefreshDataTypeHierarchy()
- self.Project.RefreshCustomBlockTypes()
- self.CreateProjectBuffer(True)
- self.ProgramChunks = []
- self.ProgramOffset = 0
- self.NextCompiledProject = self.Copy(self.Project)
- self.CurrentCompiledProject = None
- self.Buffering = False
- self.CurrentElementEditing = None
- return None
- return _("No PLC project found")
-
+ ## To remove when project buffering ready
+ self.ProjectBufferEnabled = False
+
+ self.CreateProjectBuffer(True)
+ self.ProgramChunks = []
+ self.ProgramOffset = 0
+ self.NextCompiledProject = self.Project ## self.Copy(self.Project)
+ self.CurrentCompiledProject = None
+ self.Buffering = False
+ self.CurrentElementEditing = None
+ return None
+
def SaveXMLFile(self, filepath = None):
if not filepath and self.FilePath == "":
return False
@@ -3168,19 +3160,11 @@
contentheader = {"modificationDateTime": datetime.datetime(*localtime()[:6])}
self.Project.setcontentHeader(contentheader)
- text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- extras = {"xmlns" : "http://www.plcopen.org/xml/tc6.xsd",
- "xmlns:xhtml" : "http://www.w3.org/1999/xhtml",
- "xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance",
- "xsi:schemaLocation" : "http://www.plcopen.org/xml/tc6.xsd"}
- text += self.Project.generateXMLText("project", 0, extras)
+ if filepath:
+ SaveProject(self.Project, filepath)
+ else:
+ SaveProject(self.Project, self.FilePath)
- if filepath:
- xmlfile = open(filepath,"w")
- else:
- xmlfile = open(self.FilePath,"w")
- xmlfile.write(text.encode("utf-8"))
- xmlfile.close()
self.MarkProjectAsSaved()
if filepath:
self.SetFilePath(filepath)
--- a/plcopen/plcopen.py Wed Aug 28 11:43:51 2013 +0200
+++ b/plcopen/plcopen.py Wed Aug 28 11:53:50 2013 +0200
@@ -26,6 +26,7 @@
from structures import *
from types import *
import os, re
+from lxml import etree
from collections import OrderedDict
"""
Dictionary that makes the relation between var names in plcopen and displayed values
@@ -122,11 +123,29 @@
result = criteria["pattern"].search(text, result.end())
return test_result
-PLCOpenClasses = GenerateClassesFromXSD(os.path.join(os.path.split(__file__)[0], "tc6_xml_v201.xsd"))
-
-ElementNameToClass = {}
-
-cls = PLCOpenClasses.get("formattedText", None)
+PLCOpenParser = GenerateParserFromXSD(os.path.join(os.path.split(__file__)[0], "tc6_xml_v201.xsd"))
+
+def LoadProject(filepath):
+ project_file = open(filepath)
+ project_xml = project_file.read()\
+ .replace("http://www.plcopen.org/xml/tc6.xsd",
+ "http://www.plcopen.org/xml/tc6_0201")\
+ .replace("<![CDATA[", "<xhtml:p><![CDATA[")\
+ .replace("]]>", "]]></xhtml:p>")
+ project_file.close()
+
+ return etree.fromstring(project_xml, PLCOpenParser)
+
+def SaveProject(project, filepath):
+ project_file = open(filepath, 'w')
+ project_file.write(etree.tostring(
+ project,
+ pretty_print=True,
+ xml_declaration=True,
+ encoding='utf-8'))
+ project_file.close()
+
+cls = PLCOpenParser.GetElementClass("formattedText")
if cls:
def updateElementName(self, old_name, new_name):
text = self.text
@@ -167,12 +186,11 @@
setattr(cls, "hasblock", hasblock)
def Search(self, criteria, parent_infos):
- return [(tuple(parent_infos),) + result for result in TestTextElement(self.gettext(), criteria)]
+ return [(tuple(parent_infos),) + result for result in TestTextElement(self.getanyText(), criteria)]
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("project", None)
-if cls:
- cls.singleLineAttributes = False
+cls = PLCOpenParser.GetElementClass("project")
+if cls:
cls.EnumeratedDataTypeValues = {}
cls.CustomDataTypeRange = {}
cls.CustomTypeHierarchy = {}
@@ -324,7 +342,7 @@
for configuration in self.instances.configurations.getconfiguration():
if configuration.getname() == name:
raise ValueError, _("\"%s\" configuration already exists !!!")%name
- new_configuration = PLCOpenClasses["configurations_configuration"]()
+ new_configuration = PLCOpenParser.CreateElement("configuration", "configurations")
new_configuration.setname(name)
self.instances.configurations.appendconfiguration(new_configuration)
setattr(cls, "addconfiguration", addconfiguration)
@@ -355,7 +373,7 @@
for resource in configuration.getresource():
if resource.getname() == name:
raise ValueError, _("\"%s\" resource already exists in \"%s\" configuration !!!")%(name, config_name)
- new_resource = PLCOpenClasses["configuration_resource"]()
+ new_resource = PLCOpenParser.CreateElement("resource", "configuration")
new_resource.setname(name)
configuration.appendresource(new_resource)
setattr(cls, "addconfigurationResource", addconfigurationResource)
@@ -416,25 +434,26 @@
def AddCustomDataType(self, datatype):
name = datatype.getname()
basetype_content = datatype.getbaseType().getcontent()
- if basetype_content["value"] is None:
- self.CustomTypeHierarchy[name] = basetype_content["name"]
- elif basetype_content["name"] in ["string", "wstring"]:
- self.CustomTypeHierarchy[name] = basetype_content["name"].upper()
- elif basetype_content["name"] == "derived":
- self.CustomTypeHierarchy[name] = basetype_content["value"].getname()
- elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]:
- range = (basetype_content["value"].range.getlower(),
- basetype_content["value"].range.getupper())
+ basetype_content_name = basetype_content.getLocalTag()
+ if basetype_content.__class__ == DefaultElementClass:
+ self.CustomTypeHierarchy[name] = basetype_content_name
+ elif basetype_content_name in ["string", "wstring"]:
+ self.CustomTypeHierarchy[name] = basetype_content_name.upper()
+ elif basetype_content_name == "derived":
+ self.CustomTypeHierarchy[name] = basetype_content.getname()
+ elif basetype_content_name in ["subrangeSigned", "subrangeUnsigned"]:
+ range = (basetype_content.range.getlower(),
+ basetype_content.range.getupper())
self.CustomDataTypeRange[name] = range
- base_type = basetype_content["value"].baseType.getcontent()
- if base_type["value"] is None:
- self.CustomTypeHierarchy[name] = base_type["name"]
+ base_type = basetype_content.baseType.getcontent()
+ if base_type.__class__ == DefaultElementClass:
+ self.CustomTypeHierarchy[name] = basetype.getLocalTag()
else:
- self.CustomTypeHierarchy[name] = base_type["value"].getname()
+ self.CustomTypeHierarchy[name] = base_type.getname()
else:
- if basetype_content["name"] == "enum":
+ if basetype_content_name == "enum":
values = []
- for value in basetype_content["value"].values.getvalue():
+ for value in basetype_content.xpath("ppx:values/ppx:value", namespaces=PLCOpenParser.NSMAP):
values.append(value.getname())
self.EnumeratedDataTypeValues[name] = values
self.CustomTypeHierarchy[name] = "ANY_DERIVED"
@@ -454,47 +473,51 @@
block_infos = {"name" : pou_name, "type" : pou_type, "extensible" : False,
"inputs" : [], "outputs" : [], "comment" : pou.getdescription(),
"generate" : generate_block, "initialise" : initialise_block}
- if pou.getinterface():
+ if pou.interface is not None:
return_type = pou.interface.getreturnType()
- if return_type:
+ if return_type is not None:
var_type = return_type.getcontent()
- if var_type["name"] == "derived":
- block_infos["outputs"].append(("OUT", var_type["value"].getname(), "none"))
- elif var_type["name"] in ["string", "wstring"]:
- block_infos["outputs"].append(("OUT", var_type["name"].upper(), "none"))
+ var_type_name = var_type.getLocalTag()
+ if var_type_name == "derived":
+ block_infos["outputs"].append(("OUT", var_type.getname(), "none"))
+ elif var_type_name in ["string", "wstring"]:
+ block_infos["outputs"].append(("OUT", var_type_name.upper(), "none"))
else:
- block_infos["outputs"].append(("OUT", var_type["name"], "none"))
+ block_infos["outputs"].append(("OUT", var_type_name, "none"))
for type, varlist in pou.getvars():
if type == "InOut":
for var in varlist.getvariable():
var_type = var.type.getcontent()
- if var_type["name"] == "derived":
- block_infos["inputs"].append((var.getname(), var_type["value"].getname(), "none"))
- block_infos["outputs"].append((var.getname(), var_type["value"].getname(), "none"))
- elif var_type["name"] in ["string", "wstring"]:
- block_infos["inputs"].append((var.getname(), var_type["name"].upper(), "none"))
- block_infos["outputs"].append((var.getname(), var_type["name"].upper(), "none"))
+ var_type_name = var_type.getLocalTag()
+ if var_type_name == "derived":
+ block_infos["inputs"].append((var.getname(), var_type.getname(), "none"))
+ block_infos["outputs"].append((var.getname(), var_type.getname(), "none"))
+ elif var_type_name in ["string", "wstring"]:
+ block_infos["inputs"].append((var.getname(), var_type_name.upper(), "none"))
+ block_infos["outputs"].append((var.getname(), var_type_name.upper(), "none"))
else:
- block_infos["inputs"].append((var.getname(), var_type["name"], "none"))
- block_infos["outputs"].append((var.getname(), var_type["name"], "none"))
+ block_infos["inputs"].append((var.getname(), var_type_name, "none"))
+ block_infos["outputs"].append((var.getname(), var_type_name, "none"))
elif type == "Input":
for var in varlist.getvariable():
var_type = var.type.getcontent()
- if var_type["name"] == "derived":
- block_infos["inputs"].append((var.getname(), var_type["value"].getname(), "none"))
- elif var_type["name"] in ["string", "wstring"]:
- block_infos["inputs"].append((var.getname(), var_type["name"].upper(), "none"))
+ var_type_name = var_type.getLocalTag()
+ if var_type_name == "derived":
+ block_infos["inputs"].append((var.getname(), var_type.getname(), "none"))
+ elif var_type_name in ["string", "wstring"]:
+ block_infos["inputs"].append((var.getname(), var_type_name.upper(), "none"))
else:
- block_infos["inputs"].append((var.getname(), var_type["name"], "none"))
+ block_infos["inputs"].append((var.getname(), var_type_name, "none"))
elif type == "Output":
for var in varlist.getvariable():
var_type = var.type.getcontent()
- if var_type["name"] == "derived":
- block_infos["outputs"].append((var.getname(), var_type["value"].getname(), "none"))
- elif var_type["name"] in ["string", "wstring"]:
- block_infos["outputs"].append((var.getname(), var_type["name"].upper(), "none"))
+ var_type_name = var_type.getLocalTag()
+ if var_type_name == "derived":
+ block_infos["outputs"].append((var.getname(), var_type.getname(), "none"))
+ elif var_type_name in ["string", "wstring"]:
+ block_infos["outputs"].append((var.getname(), var_type_name.upper(), "none"))
else:
- block_infos["outputs"].append((var.getname(), var_type["name"], "none"))
+ block_infos["outputs"].append((var.getname(), var_type_name, "none"))
block_infos["usage"] = "\n (%s) => (%s)" % (", ".join(["%s:%s" % (input[1], input[0]) for input in block_infos["inputs"]]),
", ".join(["%s:%s" % (output[1], output[0]) for output in block_infos["outputs"]]))
self.CustomBlockTypes[pou_name]=block_infos
@@ -509,34 +532,34 @@
def RefreshElementUsingTree(self):
# Reset the tree of user-defined element cross-use
self.ElementUsingTree = {}
- pous = self.getpous()
- datatypes = self.getdataTypes()
+
# Analyze each datatype
- for datatype in datatypes:
+ for datatype in self.getdataTypes():
name = datatype.getname()
basetype_content = datatype.baseType.getcontent()
- if basetype_content["name"] == "derived":
- self.AddElementUsingTreeInstance(name,
- basetype_content["value"])
- elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned", "array"]:
- base_type = basetype_content["value"].baseType.getcontent()
- if base_type["name"] == "derived":
- self.AddElementUsingTreeInstance(name, base_type["value"])
- elif basetype_content["name"] == "struct":
- for element in basetype_content["value"].getvariable():
+ basetype_content_name = basetype_content.getLocalTag()
+ if basetype_content_name == "derived":
+ self.AddElementUsingTreeInstance(name, basetype_content)
+ elif basetype_content_name in ["subrangeSigned", "subrangeUnsigned", "array"]:
+ base_type = basetype_content.baseType.getcontent()
+ if base_type.getLocalTag() == "derived":
+ self.AddElementUsingTreeInstance(name, base_type)
+ elif basetype_content_name == "struct":
+ for element in basetype_content.getvariable():
type_content = element.type.getcontent()
- if type_content["name"] == "derived":
- self.AddElementUsingTreeInstance(name, type_content["value"])
+ if type_content.getLocalTag() == "derived":
+ self.AddElementUsingTreeInstance(name, type_content)
+
# Analyze each pou
- for pou in pous:
+ for pou in self.getpous():
name = pou.getname()
- if pou.interface:
+ if pou.interface is not None:
# Extract variables from every varLists
- for type, varlist in pou.getvars():
+ for varlist_type, varlist in pou.getvars():
for var in varlist.getvariable():
vartype_content = var.gettype().getcontent()
- if vartype_content["name"] == "derived":
- self.AddElementUsingTreeInstance(name, vartype_content["value"])
+ if vartype_content.getLocalTag() == "derived":
+ self.AddElementUsingTreeInstance(name, vartype_content)
setattr(cls, "RefreshElementUsingTree", RefreshElementUsingTree)
@@ -689,16 +712,17 @@
# Return if Data Type can be used for located variables
def IsLocatableType(self, datatype):
basetype_content = datatype.baseType.getcontent()
- if basetype_content["name"] in ["enum", "struct"]:
+ basetype_content_name = basetype_content.getLocalTag()
+ if basetype_content_name in ["enum", "struct"]:
return False
- elif basetype_content["name"] == "derived":
- base_type = self.getdataType(basetype_content["value"].getname())
+ elif basetype_content_name == "derived":
+ base_type = self.getdataType(basetype_content.getname())
if base_type is not None:
return self.IsLocatableType(base_type)
- elif basetype_content["name"] == "array":
- array_base_type = basetype_content["value"].baseType.getcontent()
- if array_base_type["value"] is not None and array_base_type["name"] not in ["string", "wstring"]:
- base_type = self.getdataType(array_base_type["value"].getname())
+ elif basetype_content_name == "array":
+ array_base_type = basetype_content.baseType.getcontent()
+ if array_base_type == DefaultElementClass and array_base_type.getLocalTag() not in ["string", "wstring"]:
+ base_type = self.getdataType(array_base_type.getname())
if base_type is not None:
return self.IsLocatableType(base_type)
return True
@@ -711,13 +735,8 @@
return result
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("project_fileHeader", None)
-if cls:
- cls.singleLineAttributes = False
-
-cls = PLCOpenClasses.get("project_contentHeader", None)
-if cls:
- cls.singleLineAttributes = False
+cls = PLCOpenParser.GetElementClass("contentHeader", "project")
+if cls:
def setpageSize(self, width, height):
self.coordinateInfo.setpageSize(width, height)
@@ -740,7 +759,7 @@
return scaling
setattr(cls, "getscaling", getscaling)
-cls = PLCOpenClasses.get("contentHeader_coordinateInfo", None)
+cls = PLCOpenParser.GetElementClass("coordinateInfo", "contentHeader")
if cls:
def setpageSize(self, width, height):
if width == 0 and height == 0:
@@ -809,7 +828,7 @@
variables = varlist.getvariable()
for i in xrange(len(variables)-1, -1, -1):
if variables[i].getaddress() == address:
- variables.pop(i)
+ variables.remove(variables[i])
def _removeConfigurationResourceVariableByFilter(self, address_model):
for varlist in self.getglobalVars():
@@ -819,7 +838,7 @@
if var_address is not None:
result = address_model.match(var_address)
if result is not None:
- variables.pop(i)
+ variables.remove(variables[i])
def _SearchInConfigurationResource(self, criteria, parent_infos=[]):
search_result = _Search([("name", self.getname())], criteria, parent_infos)
@@ -839,33 +858,30 @@
var_number += 1
return search_result
-cls = PLCOpenClasses.get("configurations_configuration", None)
-if cls:
-
- def addglobalVar(self, type, name, location="", description=""):
+cls = PLCOpenParser.GetElementClass("configuration", "configurations")
+if cls:
+
+ def addglobalVar(self, var_type, name, location="", description=""):
globalvars = self.getglobalVars()
if len(globalvars) == 0:
- globalvars.append(PLCOpenClasses["varList"]())
- var = PLCOpenClasses["varListPlain_variable"]()
+ globalvars.append(PLCOpenParser.CreateElement("varList"))
+ var = PLCOpenParser.CreateElement("variable", "varListPlain")
var.setname(name)
- var_type = PLCOpenClasses["dataType"]()
- if type in [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]:
- if type == "STRING":
- var_type.setcontent({"name" : "string", "value" : PLCOpenClasses["elementaryTypes_string"]()})
- elif type == "WSTRING":
- var_type.setcontent({"name" : "wstring", "value" : PLCOpenClasses["elementaryTypes_wstring"]()})
- else:
- var_type.setcontent({"name" : type, "value" : None})
+ var_type_obj = PLCOpenParser.CreateElement("dataType")
+ if var_type in [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]:
+ var_type_obj.setcontent(PLCOpenParser.CreateElement(
+ var_type.lower() if var_type in ["STRING", "WSTRING"]
+ else vartype, "dataType"))
else:
- derived_type = PLCOpenClasses["derivedTypes_derived"]()
- derived_type.setname(type)
- var_type.setcontent({"name" : "derived", "value" : derived_type})
- var.settype(var_type)
+ derived_type = PLCOpenParser.CreateElement("derived", "dataType")
+ derived_type.setname(var_type)
+ var_type_obj.setcontent(derived_type)
+ var.settype(var_type_obj)
if location != "":
var.setaddress(location)
if description != "":
- ft = PLCOpenClasses["formattedText"]()
- ft.settext(description)
+ ft = PLCOpenParser.CreateElementClass("formattedText")
+ ft.setanyText(description)
var.setdocumentation(ft)
globalvars[-1].appendvariable(var)
setattr(cls, "addglobalVar", addglobalVar)
@@ -896,7 +912,7 @@
return search_result
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("configuration_resource", None)
+cls = PLCOpenParser.GetElementClass("resource", "configuration")
if cls:
def updateElementName(self, old_name, new_name):
_updateConfigurationResourceElementName(self, old_name, new_name)
@@ -937,7 +953,7 @@
return search_result
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("resource_task", None)
+cls = PLCOpenParser.GetElementClass("task", "resource")
if cls:
def compatibility(self, tree):
if tree.hasAttribute("interval"):
@@ -986,7 +1002,7 @@
criteria, parent_infos)
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("pouInstance", None)
+cls = PLCOpenParser.GetElementClass("pouInstance")
if cls:
def compatibility(self, tree):
if tree.hasAttribute("type"):
@@ -1004,31 +1020,33 @@
criteria, parent_infos)
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("varListPlain_variable", None)
+cls = PLCOpenParser.GetElementClass("variable", "varListPlain")
if cls:
def gettypeAsText(self):
vartype_content = self.gettype().getcontent()
+ vartype_content_name = vartype_content.getLocalTag()
# Variable type is a user data type
- if vartype_content["name"] == "derived":
- return vartype_content["value"].getname()
+ if vartype_content_name == "derived":
+ return vartype_content.getname()
# Variable type is a string type
- elif vartype_content["name"] in ["string", "wstring"]:
- return vartype_content["name"].upper()
+ elif vartype_content_name in ["string", "wstring"]:
+ return vartype_content_name.upper()
# Variable type is an array
- elif vartype_content["name"] == "array":
- base_type = vartype_content["value"].baseType.getcontent()
+ elif vartype_content_name == "array":
+ base_type = vartype_content.baseType.getcontent()
+ base_type_name = base_type.getLocalTag()
# Array derived directly from a user defined type
- if base_type["name"] == "derived":
- basetype_name = base_type["value"].getname()
+ if base_type_name == "derived":
+ basetype_name = base_type.getname()
# Array derived directly from a string type
- elif base_type["name"] in ["string", "wstring"]:
- basetype_name = base_type["name"].upper()
+ elif base_type_name in ["string", "wstring"]:
+ basetype_name = base_type_name.upper()
# Array derived directly from an elementary type
else:
- basetype_name = base_type["name"]
- return "ARRAY [%s] OF %s" % (",".join(map(lambda x : "%s..%s" % (x.getlower(), x.getupper()), vartype_content["value"].getdimension())), basetype_name)
+ basetype_name = base_type_name
+ return "ARRAY [%s] OF %s" % (",".join(map(lambda x : "%s..%s" % (x.getlower(), x.getupper()), vartype_content.getdimension())), basetype_name)
# Variable type is an elementary type
- return vartype_content["name"]
+ return vartype_content_name
setattr(cls, "gettypeAsText", gettypeAsText)
def Search(self, criteria, parent_infos=[]):
@@ -1045,7 +1063,7 @@
return search_result
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("project_types", None)
+cls = PLCOpenParser.GetElementClass("types", "project")
if cls:
def getdataTypeElements(self):
return self.dataTypes.getdataType()
@@ -1060,9 +1078,9 @@
setattr(cls, "getdataTypeElement", getdataTypeElement)
def appenddataTypeElement(self, name):
- new_datatype = PLCOpenClasses["dataTypes_dataType"]()
+ new_datatype = PLCOpenParser.CreateElement("dataType", "dataTypes")
new_datatype.setname(name)
- new_datatype.baseType.setcontent({"name" : "BOOL", "value" : None})
+ new_datatype.baseType.setcontent(PLCOpenParser.CreateElement("BOOL"))
self.dataTypes.appenddataType(new_datatype)
setattr(cls, "appenddataTypeElement", appenddataTypeElement)
@@ -1072,9 +1090,9 @@
def removedataTypeElement(self, name):
found = False
- for idx, element in enumerate(self.dataTypes.getdataType()):
+ for element in self.dataTypes.getdataType():
if element.getname() == name:
- self.dataTypes.removedataType(idx)
+ self.dataTypes.remove(element)
found = True
break
if not found:
@@ -1097,10 +1115,10 @@
for element in self.pous.getpou():
if element.getname() == name:
raise ValueError, _("\"%s\" POU already exists !!!")%name
- new_pou = PLCOpenClasses["pous_pou"]()
+ new_pou = PLCOpenParser.CreateElement("pou", "pous")
new_pou.setname(name)
new_pou.setpouType(pou_type)
- new_pou.appendbody(PLCOpenClasses["body"]())
+ new_pou.appendbody(PLCOpenParser.CreateElement("body"))
new_pou.setbodyType(body_type)
self.pous.appendpou(new_pou)
setattr(cls, "appendpouElement", appendpouElement)
@@ -1111,9 +1129,9 @@
def removepouElement(self, name):
found = False
- for idx, element in enumerate(self.pous.getpou()):
+ for element in self.pous.getpou():
if element.getname() == name:
- self.pous.removepou(idx)
+ self.pous.remove(element)
found = True
break
if not found:
@@ -1133,7 +1151,7 @@
def _updateBaseTypeElementName(self, old_name, new_name):
self.baseType.updateElementName(old_name, new_name)
-cls = PLCOpenClasses.get("dataTypes_dataType", None)
+cls = PLCOpenParser.GetElementClass("dataType", "dataTypes")
if cls:
setattr(cls, "updateElementName", _updateBaseTypeElementName)
@@ -1149,33 +1167,34 @@
return search_result
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("dataType", None)
+cls = PLCOpenParser.GetElementClass("dataType")
if cls:
def updateElementName(self, old_name, new_name):
- if self.content["name"] in ["derived", "array", "subrangeSigned", "subrangeUnsigned"]:
- self.content["value"].updateElementName(old_name, new_name)
- elif self.content["name"] == "struct":
- for element in self.content["value"].getvariable():
+ content_name = self.content.getLocalTag()
+ if content_name in ["derived", "array", "subrangeSigned", "subrangeUnsigned"]:
+ self.content.updateElementName(old_name, new_name)
+ elif content_name == "struct":
+ for element in self.content.getvariable():
element_type = element.type.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
def Search(self, criteria, parent_infos=[]):
search_result = []
- if self.content["name"] in ["derived", "array", "enum", "subrangeSigned", "subrangeUnsigned"]:
+ content_name = self.content.getLocalTag()
+ if content_name in ["derived", "array", "enum", "subrangeSigned", "subrangeUnsigned"]:
search_result.extend(self.content["value"].Search(criteria, parent_infos))
- elif self.content["name"] == "struct":
+ elif content_name == "struct":
for i, element in enumerate(self.content["value"].getvariable()):
search_result.extend(element.Search(criteria, parent_infos + ["struct", i]))
else:
- basetype = self.content["name"]
- if basetype in ["string", "wstring"]:
- basetype = basetype.upper()
- search_result.extend(_Search([("base", basetype)], criteria, parent_infos))
+ if content_name in ["string", "wstring"]:
+ content_name = content_name.upper()
+ search_result.extend(_Search([("base", content_name)], criteria, parent_infos))
return search_result
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("derivedTypes_array", None)
+cls = PLCOpenParser.GetElementClass("array", "dataType")
if cls:
setattr(cls, "updateElementName", _updateBaseTypeElementName)
@@ -1195,17 +1214,17 @@
criteria, parent_infos))
return search_result
-cls = PLCOpenClasses.get("derivedTypes_subrangeSigned", None)
+cls = PLCOpenParser.GetElementClass("subrangeSigned", "dataType")
if cls:
setattr(cls, "updateElementName", _updateBaseTypeElementName)
setattr(cls, "Search", _SearchInSubrange)
-cls = PLCOpenClasses.get("derivedTypes_subrangeUnsigned", None)
+cls = PLCOpenParser.GetElementClass("subrangeUnsigned", "dataType")
if cls:
setattr(cls, "updateElementName", _updateBaseTypeElementName)
setattr(cls, "Search", _SearchInSubrange)
-cls = PLCOpenClasses.get("derivedTypes_enum", None)
+cls = PLCOpenParser.GetElementClass("enum", "dataType")
if cls:
def updateElementName(self, old_name, new_name):
@@ -1220,43 +1239,35 @@
return search_result
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("pous_pou", None)
+cls = PLCOpenParser.GetElementClass("pou", "pous")
if cls:
def setdescription(self, description):
doc = self.getdocumentation()
if doc is None:
- doc = PLCOpenClasses["formattedText"]()
+ doc = PLCOpenParser.CreateElement("formattedText")
self.setdocumentation(doc)
- doc.settext(description)
+ doc.setanyText(description)
setattr(cls, "setdescription", setdescription)
def getdescription(self):
doc = self.getdocumentation()
if doc is not None:
- return doc.gettext()
+ return doc.getanyText()
return ""
setattr(cls, "getdescription", getdescription)
- def setbodyType(self, type):
+ def setbodyType(self, body_type):
if len(self.body) > 0:
- if type == "IL":
- self.body[0].setcontent({"name" : "IL", "value" : PLCOpenClasses["formattedText"]()})
- elif type == "ST":
- self.body[0].setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
- elif type == "LD":
- self.body[0].setcontent({"name" : "LD", "value" : PLCOpenClasses["body_LD"]()})
- elif type == "FBD":
- self.body[0].setcontent({"name" : "FBD", "value" : PLCOpenClasses["body_FBD"]()})
- elif type == "SFC":
- self.body[0].setcontent({"name" : "SFC", "value" : PLCOpenClasses["body_SFC"]()})
+ if body_type in ["IL", "ST", "LD", "FBD", "SFC"]:
+ self.body[0].setcontent(PLCOpenParser.CreateElementClass(body_type, "body"))
else:
raise ValueError, "%s isn't a valid body type!"%type
setattr(cls, "setbodyType", setbodyType)
def getbodyType(self):
if len(self.body) > 0:
- return self.body[0].getcontent()["name"]
+ return self.body[0].getcontent().getLocalTag()
setattr(cls, "getbodyType", getbodyType)
def resetexecutionOrder(self):
@@ -1326,57 +1337,53 @@
for name, value in VarTypes.items():
reverse_types[value] = name
for varlist in self.interface.getcontent():
- vars.append((reverse_types[varlist["name"]], varlist["value"]))
+ vars.append((reverse_types[varlist.getLocalTag()], varlist))
return vars
setattr(cls, "getvars", getvars)
def setvars(self, vars):
if self.interface is None:
- self.interface = PLCOpenClasses["pou_interface"]()
- self.interface.setcontent([])
- for vartype, varlist in vars:
- self.interface.appendcontent({"name" : VarTypes[vartype], "value" : varlist})
+ self.interface = PLCOpenParser.CreateElement("interface", "pou")
+ self.interface.setcontent(vars)
+ print self.interface.tostring()
setattr(cls, "setvars", setvars)
- def addpouLocalVar(self, type, name, location="", description=""):
- self.addpouVar(type, name, location=location, description=description)
+ def addpouLocalVar(self, var_type, name, location="", description=""):
+ self.addpouVar(var_type, name, location=location, description=description)
setattr(cls, "addpouLocalVar", addpouLocalVar)
- def addpouExternalVar(self, type, name):
+ def addpouExternalVar(self, var_type, name):
self.addpouVar(type, name, "externalVars")
setattr(cls, "addpouExternalVar", addpouExternalVar)
- def addpouVar(self, type, name, var_class="localVars", location="", description=""):
+ def addpouVar(self, var_type, name, var_class="localVars", location="", description=""):
if self.interface is None:
- self.interface = PLCOpenClasses["pou_interface"]()
+ self.interface = PLCOpenParser.CreateElement("interface", "pou")
content = self.interface.getcontent()
if len(content) == 0 or content[-1]["name"] != var_class:
- content.append({"name" : var_class, "value" : PLCOpenClasses["interface_%s" % var_class]()})
+ self.appendcontent(PLCOpenParser.CreateElement(var_class, "interface"))
else:
varlist = content[-1]["value"]
variables = varlist.getvariable()
if varlist.getconstant() or varlist.getretain() or len(variables) > 0 and variables[0].getaddress():
- content.append({"name" : var_class, "value" : PLCOpenClasses["interface_%s" % var_class]()})
- var = PLCOpenClasses["varListPlain_variable"]()
+ self.appendcontent(PLCOpenParser.CreateElementClass(var_class, "interface"))
+ var = PLCOpenParser.CreateElementClass("variable", "varListPlain")
var.setname(name)
- var_type = PLCOpenClasses["dataType"]()
- if type in [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]:
- if type == "STRING":
- var_type.setcontent({"name" : "string", "value" : PLCOpenClasses["elementaryTypes_string"]()})
- elif type == "WSTRING":
- var_type.setcontent({"name" : "wstring", "value" : PLCOpenClasses["elementaryTypes_wstring"]()})
- else:
- var_type.setcontent({"name" : type, "value" : None})
+ var_type_obj = PLCOpenParser.CreateElement("dataType")
+ if var_type in [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]:
+ var_type_obj.setcontent(PLCOpenParser.CreateElement(
+ var_type.lower() if var_type in ["STRING", "WSTRING"]
+ else var_type, "dataType"))
else:
- derived_type = PLCOpenClasses["derivedTypes_derived"]()
- derived_type.setname(type)
- var_type.setcontent({"name" : "derived", "value" : derived_type})
- var.settype(var_type)
+ derived_type = PLCOpenParser.CreateElement("derived", "dataType")
+ derived_type.setname(var_type)
+ var_type_obj.setcontent(derived_type)
+ var.settype(var_type_obj)
if location != "":
var.setaddress(location)
if description != "":
- ft = PLCOpenClasses["formattedText"]()
- ft.settext(description)
+ ft = PLCOpenParser.GetElementClass("formattedText")()
+ ft.setanyText(description)
var.setdocumentation(ft)
content[-1]["value"].appendvariable(var)
@@ -1390,24 +1397,23 @@
for var in variables:
if var.getname() == old_name:
vartype_content = var.gettype().getcontent()
- if vartype_content["name"] == "derived" and vartype_content["value"].getname() == old_type:
+ if vartype_content.getLocalTag() == "derived" and vartype_content.getname() == old_type:
var.setname(new_name)
- vartype_content["value"].setname(new_type)
+ vartype_content.setname(new_type)
return
setattr(cls, "changepouVar", changepouVar)
- def removepouVar(self, type, name):
+ def removepouVar(self, var_type, name):
if self.interface is not None:
content = self.interface.getcontent()
for varlist in content:
- variables = varlist["value"].getvariable()
- for var in variables:
+ for var in varlist.getvariable():
if var.getname() == name:
vartype_content = var.gettype().getcontent()
- if vartype_content["name"] == "derived" and vartype_content["value"].getname() == type:
- variables.remove(var)
+ if vartype_content.getLocalTag() == "derived" and vartype_content.getname() == var_type:
+ varlist.remove(var)
break
- if len(varlist["value"].getvariable()) == 0:
+ if len(varlist.getvariable()) == 0:
content.remove(varlist)
break
setattr(cls, "removepouVar", removepouVar)
@@ -1415,7 +1421,7 @@
def hasblock(self, name=None, block_type=None):
if self.getbodyType() in ["FBD", "LD", "SFC"]:
for instance in self.getinstances():
- if (isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and
+ if (isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")) and
(name and instance.getinstanceName() == name or
block_type and instance.gettypeName() == block_type)):
return True
@@ -1434,17 +1440,17 @@
return False
setattr(cls, "hasblock", hasblock)
- def addtransition(self, name, type):
+ def addtransition(self, name, body_type):
if not self.transitions:
self.addtransitions()
self.transitions.settransition([])
- transition = PLCOpenClasses["transitions_transition"]()
+ transition = PLCOpenParser.CreateElement("transition", "transitions")
transition.setname(name)
- transition.setbodyType(type)
- if type == "ST":
- transition.settext(":= ;")
- elif type == "IL":
- transition.settext("\tST\t%s"%name)
+ transition.setbodyType(body_type)
+ if body_type == "ST":
+ transition.setanyText(":= ;")
+ elif body_type == "IL":
+ transition.setanyText("\tST\t%s"%name)
self.transitions.appendtransition(transition)
setattr(cls, "addtransition", addtransition)
@@ -1464,30 +1470,28 @@
def removetransition(self, name):
if self.transitions:
- transitions = self.transitions.gettransition()
- i = 0
removed = False
- while i < len(transitions) and not removed:
- if transitions[i].getname() == name:
- if transitions[i].getbodyType() in ["FBD", "LD", "SFC"]:
- for instance in transitions[i].getinstances():
- if isinstance(instance, PLCOpenClasses["fbdObjects_block"]):
+ for transition in self.transitions.gettransition():
+ if transition.getname() == name:
+ if transition.getbodyType() in ["FBD", "LD", "SFC"]:
+ for instance in transition.getinstances():
+ if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")):
self.removepouVar(instance.gettypeName(),
instance.getinstanceName())
- transitions.pop(i)
+ self.transitions.remove(transition)
removed = True
- i += 1
+ break
if not removed:
raise ValueError, _("Transition with name %s doesn't exist!")%name
setattr(cls, "removetransition", removetransition)
- def addaction(self, name, type):
+ def addaction(self, name, body_type):
if not self.actions:
self.addactions()
self.actions.setaction([])
- action = PLCOpenClasses["actions_action"]()
+ action = PLCOpenParser.CreateElement("action", "actions")
action.setname(name)
- action.setbodyType(type)
+ action.setbodyType(body_type)
self.actions.appendaction(action)
setattr(cls, "addaction", addaction)
@@ -1507,19 +1511,17 @@
def removeaction(self, name):
if self.actions:
- actions = self.actions.getaction()
- i = 0
removed = False
- while i < len(actions) and not removed:
- if actions[i].getname() == name:
- if actions[i].getbodyType() in ["FBD", "LD", "SFC"]:
- for instance in actions[i].getinstances():
- if isinstance(instance, PLCOpenClasses["fbdObjects_block"]):
+ for action in self.actions.getaction():
+ if action.getname() == name:
+ if action.getbodyType() in ["FBD", "LD", "SFC"]:
+ for instance in action.getinstances():
+ if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")):
self.removepouVar(instance.gettypeName(),
instance.getinstanceName())
- actions.pop(i)
+ self.actions.remove(action)
removed = True
- i += 1
+ break
if not removed:
raise ValueError, _("Action with name %s doesn't exist!")%name
setattr(cls, "removeaction", removeaction)
@@ -1527,7 +1529,7 @@
def updateElementName(self, old_name, new_name):
if self.interface:
for content in self.interface.getcontent():
- for var in content["value"].getvariable():
+ for var in content.getvariable():
var_address = var.getaddress()
if var_address is not None:
if var_address == old_name:
@@ -1535,9 +1537,9 @@
if var.getname() == old_name:
var.setname(new_name)
var_type_content = var.gettype().getcontent()
- if var_type_content["name"] == "derived":
- if var_type_content["value"].getname() == old_name:
- var_type_content["value"].setname(new_name)
+ if var_type_content.getLocalTag() == "derived":
+ if var_type_content.getname() == old_name:
+ var_type_content.setname(new_name)
self.body[0].updateElementName(old_name, new_name)
for action in self.getactionList():
action.updateElementName(old_name, new_name)
@@ -1548,7 +1550,7 @@
def updateElementAddress(self, address_model, new_leading):
if self.interface:
for content in self.interface.getcontent():
- for var in content["value"].getvariable():
+ for var in content.getvariable():
var_address = var.getaddress()
if var_address is not None:
var.setaddress(update_address(var_address, address_model, new_leading))
@@ -1562,22 +1564,20 @@
def removeVariableByAddress(self, address):
if self.interface:
for content in self.interface.getcontent():
- variables = content["value"].getvariable()
- for i in xrange(len(variables)-1, -1, -1):
- if variables[i].getaddress() == address:
- variables.pop(i)
+ for variable in content.getvariable():
+ if variable.getaddress() == address:
+ content.remove(variable)
setattr(cls, "removeVariableByAddress", removeVariableByAddress)
def removeVariableByFilter(self, address_model):
if self.interface:
for content in self.interface.getcontent():
- variables = content["value"].getvariable()
- for i in xrange(len(variables)-1, -1, -1):
- var_address = variables[i].getaddress()
+ for variable in content.getvariable():
+ var_address = variable.getaddress()
if var_address is not None:
result = address_model.match(var_address)
if result is not None:
- variables.pop(i)
+ content.remove(variable)
setattr(cls, "removeVariableByFilter", removeVariableByFilter)
def Search(self, criteria, parent_infos=[]):
@@ -1589,11 +1589,11 @@
if self.interface is not None:
var_number = 0
for content in self.interface.getcontent():
- variable_type = searchResultVarTypes.get(content["value"], "var_local")
- variables = content["value"].getvariable()
- for modifier, has_modifier in [("constant", content["value"].getconstant()),
- ("retain", content["value"].getretain()),
- ("non_retain", content["value"].getnonretain())]:
+ variable_type = searchResultVarTypes.get(content, "var_local")
+ variables = content.getvariable()
+ for modifier, has_modifier in [("constant", content.getconstant()),
+ ("retain", content.getretain()),
+ ("non_retain", content.getnonretain())]:
if has_modifier:
for result in TestTextElement(modifier, criteria):
search_result.append((tuple(parent_infos + [variable_type, (var_number, var_number + len(variables)), modifier]),) + result)
@@ -1610,22 +1610,14 @@
return search_result
setattr(cls, "Search", Search)
-def setbodyType(self, type):
- if type == "IL":
- self.body.setcontent({"name" : "IL", "value" : PLCOpenClasses["formattedText"]()})
- elif type == "ST":
- self.body.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
- elif type == "LD":
- self.body.setcontent({"name" : "LD", "value" : PLCOpenClasses["body_LD"]()})
- elif type == "FBD":
- self.body.setcontent({"name" : "FBD", "value" : PLCOpenClasses["body_FBD"]()})
- elif type == "SFC":
- self.body.setcontent({"name" : "SFC", "value" : PLCOpenClasses["body_SFC"]()})
+def setbodyType(self, body_type):
+ if body_type in ["IL", "ST", "LD", "FBD", "SFC"]:
+ self.body.setcontent(PLCOpenParser.CreateElement(body_type, "body"))
else:
raise ValueError, "%s isn't a valid body type!"%type
def getbodyType(self):
- return self.body.getcontent()["name"]
+ return self.body.getcontent().getLocalTag()
def resetexecutionOrder(self):
self.body.resetexecutionOrder()
@@ -1663,7 +1655,7 @@
def hasblock(self, name=None, block_type=None):
if self.getbodyType() in ["FBD", "LD", "SFC"]:
for instance in self.getinstances():
- if (isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and
+ if (isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")) and
(name and instance.getinstanceName() == name or
block_type and instance.gettypeName() == block_type)):
return True
@@ -1678,7 +1670,7 @@
self.body.updateElementAddress(address_model, new_leading)
-cls = PLCOpenClasses.get("transitions_transition", None)
+cls = PLCOpenParser.GetElementClass("transition", "transitions")
if cls:
setattr(cls, "setbodyType", setbodyType)
setattr(cls, "getbodyType", getbodyType)
@@ -1706,7 +1698,7 @@
return search_result
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("actions_action", None)
+cls = PLCOpenParser.GetElementClass("action", "actions")
if cls:
setattr(cls, "setbodyType", setbodyType)
setattr(cls, "getbodyType", getbodyType)
@@ -1734,27 +1726,9 @@
return search_result
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("body", None)
+cls = PLCOpenParser.GetElementClass("body")
if cls:
cls.currentExecutionOrderId = 0
- cls.instances_dict = {}
-
- setattr(cls, "_init_", getattr(cls, "__init__"))
-
- def __init__(self, *args, **kwargs):
- self._init_(*args, **kwargs)
- self.instances_dict = {}
- setattr(cls, "__init__", __init__)
-
- setattr(cls, "_loadXMLTree", getattr(cls, "loadXMLTree"))
-
- def loadXMLTree(self, *args, **kwargs):
- self._loadXMLTree(*args, **kwargs)
- if self.content["name"] in ["LD","FBD","SFC"]:
- self.instances_dict = dict(
- [(element["value"].getlocalId(), element)
- for element in self.content["value"].getcontent()])
- setattr(cls, "loadXMLTree", loadXMLTree)
def resetcurrentExecutionOrderId(self):
object.__setattr__(self, "currentExecutionOrderId", 0)
@@ -1766,44 +1740,44 @@
setattr(cls, "getnewExecutionOrderId", getnewExecutionOrderId)
def resetexecutionOrder(self):
- if self.content["name"] == "FBD":
- for element in self.content["value"].getcontent():
- if not isinstance(element["value"], (PLCOpenClasses.get("commonObjects_comment", None),
- PLCOpenClasses.get("commonObjects_connector", None),
- PLCOpenClasses.get("commonObjects_continuation", None))):
- element["value"].setexecutionOrderId(0)
+ if self.content.getLocalTag() == "FBD":
+ for element in self.content.getcontent():
+ if not isinstance(element, (PLCOpenParser.GetElementClass("comment", "commonObjects"),
+ PLCOpenParser.GetElementClass("connector", "commonObjects"),
+ PLCOpenParser.GetElementClass("continuation", "commonObjects"))):
+ element.setexecutionOrderId(0)
else:
raise TypeError, _("Can only generate execution order on FBD networks!")
setattr(cls, "resetexecutionOrder", resetexecutionOrder)
def compileexecutionOrder(self):
- if self.content["name"] == "FBD":
+ if self.content.getLocalTag() == "FBD":
self.resetexecutionOrder()
self.resetcurrentExecutionOrderId()
- for element in self.content["value"].getcontent():
- if isinstance(element["value"], PLCOpenClasses.get("fbdObjects_outVariable", None)) and element["value"].getexecutionOrderId() == 0:
- connections = element["value"].connectionPointIn.getconnections()
+ for element in self.content.getcontent():
+ if isinstance(element, PLCOpenParser.GetElementClass("outVariable", "fbdObjects")) and element.getexecutionOrderId() == 0:
+ connections = element.connectionPointIn.getconnections()
if connections and len(connections) == 1:
self.compileelementExecutionOrder(connections[0])
- element["value"].setexecutionOrderId(self.getnewExecutionOrderId())
+ element.setexecutionOrderId(self.getnewExecutionOrderId())
else:
raise TypeError, _("Can only generate execution order on FBD networks!")
setattr(cls, "compileexecutionOrder", compileexecutionOrder)
def compileelementExecutionOrder(self, link):
- if self.content["name"] == "FBD":
+ if self.content.getLocalTag() == "FBD":
localid = link.getrefLocalId()
instance = self.getcontentInstance(localid)
- if isinstance(instance, PLCOpenClasses.get("fbdObjects_block", None)) and instance.getexecutionOrderId() == 0:
+ if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")) and instance.getexecutionOrderId() == 0:
for variable in instance.inputVariables.getvariable():
connections = variable.connectionPointIn.getconnections()
if connections and len(connections) == 1:
self.compileelementExecutionOrder(connections[0])
instance.setexecutionOrderId(self.getnewExecutionOrderId())
- elif isinstance(instance, PLCOpenClasses.get("commonObjects_continuation", None)) and instance.getexecutionOrderId() == 0:
+ elif isinstance(instance, PLCOpenParser.GetElementClass("continuation", "commonObjects")) and instance.getexecutionOrderId() == 0:
name = instance.getname()
for tmp_instance in self.getcontentInstances():
- if isinstance(tmp_instance, PLCOpenClasses.get("commonObjects_connector", None)) and tmp_instance.getname() == name and tmp_instance.getexecutionOrderId() == 0:
+ if isinstance(tmp_instance, PLCOpenParser.GetElementClass("connector", "commonObjects")) and tmp_instance.getname() == name and tmp_instance.getexecutionOrderId() == 0:
connections = tmp_instance.connectionPointIn.getconnections()
if connections and len(connections) == 1:
self.compileelementExecutionOrder(connections[0])
@@ -1812,74 +1786,73 @@
setattr(cls, "compileelementExecutionOrder", compileelementExecutionOrder)
def setelementExecutionOrder(self, instance, new_executionOrder):
- if self.content["name"] == "FBD":
+ if self.contentLgetLocalTag() == "FBD":
old_executionOrder = instance.getexecutionOrderId()
if old_executionOrder is not None and old_executionOrder != 0 and new_executionOrder != 0:
- for element in self.content["value"].getcontent():
- if element["value"] != instance and not isinstance(element["value"], PLCOpenClasses.get("commonObjects_comment", None)):
- element_executionOrder = element["value"].getexecutionOrderId()
+ for element in self.content.getcontent():
+ if element != instance and not isinstance(element, PLCOpenParser.GetElementClass("comment", "commonObjects")):
+ element_executionOrder = element.getexecutionOrderId()
if old_executionOrder <= element_executionOrder <= new_executionOrder:
- element["value"].setexecutionOrderId(element_executionOrder - 1)
+ element.setexecutionOrderId(element_executionOrder - 1)
if new_executionOrder <= element_executionOrder <= old_executionOrder:
- element["value"].setexecutionOrderId(element_executionOrder + 1)
+ element.setexecutionOrderId(element_executionOrder + 1)
instance.setexecutionOrderId(new_executionOrder)
else:
raise TypeError, _("Can only generate execution order on FBD networks!")
setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
def appendcontentInstance(self, name, instance):
- if self.content["name"] in ["LD","FBD","SFC"]:
- element = {"name" : name, "value" : instance}
- self.content["value"].appendcontent(element)
- self.instances_dict[instance.getlocalId()] = element
+ if self.content.getLocalTag() in ["LD","FBD","SFC"]:
+ self.content.appendcontent(instance)
else:
raise TypeError, _("%s body don't have instances!")%self.content["name"]
setattr(cls, "appendcontentInstance", appendcontentInstance)
def getcontentInstances(self):
- if self.content["name"] in ["LD","FBD","SFC"]:
- instances = []
- for element in self.content["value"].getcontent():
- instances.append(element["value"])
- return instances
+ if self.content.getLocalTag() in ["LD","FBD","SFC"]:
+ return self.content.getcontent()
else:
raise TypeError, _("%s body don't have instances!")%self.content["name"]
setattr(cls, "getcontentInstances", getcontentInstances)
- def getcontentInstance(self, id):
- if self.content["name"] in ["LD","FBD","SFC"]:
- instance = self.instances_dict.get(id, None)
- if instance is not None:
- return instance["value"]
+ def getcontentInstance(self, local_id):
+ if self.content.getLocalTag() in ["LD","FBD","SFC"]:
+ instance = self.content.xpath("*[@localId=%d]" % local_id)
+ if len(instance) > 0:
+ return instance[0]
return None
else:
raise TypeError, _("%s body don't have instances!")%self.content["name"]
setattr(cls, "getcontentInstance", getcontentInstance)
def getcontentRandomInstance(self, exclude):
- if self.content["name"] in ["LD","FBD","SFC"]:
- ids = self.instances_dict.viewkeys() - exclude
- if len(ids) > 0:
- return self.instances_dict[ids.pop()]["value"]
+ if self.content.getLocalTag() in ["LD","FBD","SFC"]:
+ instance = self.content.xpath("*%s[position()=1]" %
+ ("[not(%s)]" % " or ".join(
+ map(lambda x: "@localId=%d" % x, exclude))
+ if len(exclude) > 0 else ""))
+ if len(instance) > 0:
+ return instance[0]
return None
else:
raise TypeError, _("%s body don't have instances!")%self.content["name"]
setattr(cls, "getcontentRandomInstance", getcontentRandomInstance)
def getcontentInstanceByName(self, name):
- if self.content["name"] in ["LD","FBD","SFC"]:
- for element in self.content["value"].getcontent():
- if isinstance(element["value"], PLCOpenClasses.get("fbdObjects_block", None)) and element["value"].getinstanceName() == name:
- return element["value"]
+ if self.content.getLocalTag() in ["LD","FBD","SFC"]:
+ instance = self.content.xpath("ppx:block[@instanceName=%s]" % name, namespaces=PLCOpenParser.NSMAP)
+ if len(instance) > 0:
+ return instance[0]
+ return None
else:
raise TypeError, _("%s body don't have instances!")%self.content["name"]
setattr(cls, "getcontentInstanceByName", getcontentInstanceByName)
- def removecontentInstance(self, id):
- if self.content["name"] in ["LD","FBD","SFC"]:
- element = self.instances_dict.pop(id, None)
- if element is not None:
- self.content["value"].getcontent().remove(element)
+ def removecontentInstance(self, local_id):
+ if self.content.getLocalTag() in ["LD","FBD","SFC"]:
+ instance = self.content.xpath("*[@localId=%d]" % local_id)
+ if len(instance) > 0:
+ self.content.remove(instance[0])
else:
raise ValueError, _("Instance with id %d doesn't exist!")%id
else:
@@ -1887,49 +1860,49 @@
setattr(cls, "removecontentInstance", removecontentInstance)
def settext(self, text):
- if self.content["name"] in ["IL","ST"]:
- self.content["value"].settext(text)
+ if self.content.getLocalTag() in ["IL","ST"]:
+ self.content.setanyText(text)
else:
raise TypeError, _("%s body don't have text!")%self.content["name"]
setattr(cls, "settext", settext)
def gettext(self):
- if self.content["name"] in ["IL","ST"]:
- return self.content["value"].gettext()
+ if self.content.getLocalTag() in ["IL","ST"]:
+ return self.content.getanyText()
else:
raise TypeError, _("%s body don't have text!")%self.content["name"]
setattr(cls, "gettext", gettext)
def hasblock(self, block_type):
- if self.content["name"] in ["IL","ST"]:
- return self.content["value"].hasblock(block_type)
+ if self.content.getLocalTag() in ["IL","ST"]:
+ return self.content.hasblock(block_type)
else:
raise TypeError, _("%s body don't have text!")%self.content["name"]
setattr(cls, "hasblock", hasblock)
def updateElementName(self, old_name, new_name):
- if self.content["name"] in ["IL", "ST"]:
- self.content["value"].updateElementName(old_name, new_name)
+ if self.content.getLocalTag() in ["IL", "ST"]:
+ self.content.updateElementName(old_name, new_name)
else:
- for element in self.content["value"].getcontent():
- element["value"].updateElementName(old_name, new_name)
+ for element in self.content.getcontent():
+ element.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
def updateElementAddress(self, address_model, new_leading):
- if self.content["name"] in ["IL", "ST"]:
- self.content["value"].updateElementAddress(address_model, new_leading)
+ if self.content.getLocalTag() in ["IL", "ST"]:
+ self.content.updateElementAddress(address_model, new_leading)
else:
- for element in self.content["value"].getcontent():
- element["value"].updateElementAddress(address_model, new_leading)
+ for element in self.content.getcontent():
+ element.updateElementAddress(address_model, new_leading)
setattr(cls, "updateElementAddress", updateElementAddress)
def Search(self, criteria, parent_infos=[]):
- if self.content["name"] in ["IL", "ST"]:
- search_result = self.content["value"].Search(criteria, parent_infos + ["body", 0])
+ if self.content.getLocalTag() in ["IL", "ST"]:
+ search_result = self.content.Search(criteria, parent_infos + ["body", 0])
else:
search_result = []
- for element in self.content["value"].getcontent():
- search_result.extend(element["value"].Search(criteria, parent_infos))
+ for element in self.content.getcontent():
+ search_result.extend(element.Search(criteria, parent_infos))
return search_result
setattr(cls, "Search", Search)
@@ -1972,15 +1945,11 @@
def _filterConnections(connectionPointIn, localId, connections):
in_connections = connectionPointIn.getconnections()
if in_connections is not None:
- to_delete = []
- for i, connection in enumerate(in_connections):
+ for connection in in_connections:
connected = connection.getrefLocalId()
if not connections.has_key((localId, connected)) and \
not connections.has_key((connected, localId)):
- to_delete.append(i)
- to_delete.reverse()
- for i in to_delete:
- connectionPointIn.removeconnection(i)
+ connectionPointIn.remove(connection)
def _filterConnectionsSingle(self, connections):
if self.connectionPointIn is not None:
@@ -1991,8 +1960,8 @@
_filterConnections(connectionPointIn, self.localId, connections)
def _getconnectionsdefinition(instance, connections_end):
- id = instance.getlocalId()
- return dict([((id, end), True) for end in connections_end])
+ local_id = instance.getlocalId()
+ return dict([((local_id, end), True) for end in connections_end])
def _updateConnectionsId(connectionPointIn, translation):
connections_end = []
@@ -2063,9 +2032,8 @@
"multiple": _updateConnectionsIdMultiple},
}
-def _initElementClass(name, classname, connectionPointInType="none"):
- ElementNameToClass[name] = classname
- cls = PLCOpenClasses.get(classname, None)
+def _initElementClass(name, parent, connectionPointInType="none"):
+ cls = PLCOpenParser.GetElementClass(name, parent)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
@@ -2133,7 +2101,7 @@
infos = _getelementinfos(self)
infos["type"] = type
specific_values = infos["specific_values"]
- specific_values["name"] = self.getexpression()
+ specific_values["name"] = self.getexpression().text
_getexecutionOrder(self, specific_values)
if input and output:
infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True, "input"))
@@ -2146,7 +2114,7 @@
return getvariableinfos
def _getconnectorinfosFunction(type):
- def getvariableinfos(self):
+ def getconnectorinfos(self):
infos = _getelementinfos(self)
infos["type"] = type
infos["specific_values"]["name"] = self.getname()
@@ -2155,7 +2123,7 @@
elif type == "continuation":
infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
return infos
- return getvariableinfos
+ return getconnectorinfos
def _getpowerrailinfosFunction(type):
def getpowerrailinfos(self):
@@ -2210,7 +2178,7 @@
return infos
return getdivergenceinfos
-cls = _initElementClass("comment", "commonObjects_comment")
+cls = _initElementClass("comment", "commonObjects")
if cls:
def getinfos(self):
infos = _getelementinfos(self)
@@ -2220,11 +2188,11 @@
setattr(cls, "getinfos", getinfos)
def setcontentText(self, text):
- self.content.settext(text)
+ self.content.setanyText(text)
setattr(cls, "setcontentText", setcontentText)
def getcontentText(self):
- return self.content.gettext()
+ return self.content.getanyText()
setattr(cls, "getcontentText", getcontentText)
def updateElementName(self, old_name, new_name):
@@ -2239,7 +2207,7 @@
return self.content.Search(criteria, parent_infos + ["comment", self.getlocalId(), "content"])
setattr(cls, "Search", Search)
-cls = _initElementClass("block", "fbdObjects_block")
+cls = _initElementClass("block", "fbdObjects")
if cls:
def getBoundingBox(self):
bbox = _getBoundingBox(self)
@@ -2298,15 +2266,15 @@
return search_result
setattr(cls, "Search", Search)
-cls = _initElementClass("leftPowerRail", "ldObjects_leftPowerRail")
+cls = _initElementClass("leftPowerRail", "ldObjects")
if cls:
setattr(cls, "getinfos", _getpowerrailinfosFunction("leftPowerRail"))
-cls = _initElementClass("rightPowerRail", "ldObjects_rightPowerRail", "multiple")
+cls = _initElementClass("rightPowerRail", "ldObjects", "multiple")
if cls:
setattr(cls, "getinfos", _getpowerrailinfosFunction("rightPowerRail"))
-cls = _initElementClass("contact", "ldObjects_contact", "single")
+cls = _initElementClass("contact", "ldObjects", "single")
if cls:
setattr(cls, "getinfos", _getldelementinfosFunction("contact"))
@@ -2323,7 +2291,7 @@
return _Search([("reference", self.getvariable())], criteria, parent_infos + ["contact", self.getlocalId()])
setattr(cls, "Search", Search)
-cls = _initElementClass("coil", "ldObjects_coil", "single")
+cls = _initElementClass("coil", "ldObjects", "single")
if cls:
setattr(cls, "getinfos", _getldelementinfosFunction("coil"))
@@ -2340,7 +2308,7 @@
return _Search([("reference", self.getvariable())], criteria, parent_infos + ["coil", self.getlocalId()])
setattr(cls, "Search", Search)
-cls = _initElementClass("step", "sfcObjects_step", "single")
+cls = _initElementClass("step", "sfcObjects", "single")
if cls:
def getinfos(self):
infos = _getelementinfos(self)
@@ -2361,7 +2329,7 @@
return _Search([("name", self.getname())], criteria, parent_infos + ["step", self.getlocalId()])
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("transition_condition", None)
+cls = PLCOpenParser.GetElementClass("condition", "transition")
if cls:
def compatibility(self, tree):
connections = []
@@ -2378,7 +2346,7 @@
tree.childNodes = [node]
setattr(cls, "compatibility", compatibility)
-cls = _initElementClass("transition", "sfcObjects_transition")
+cls = _initElementClass("transition", "sfcObjects")
if cls:
def getinfos(self):
infos = _getelementinfos(self)
@@ -2399,33 +2367,32 @@
return infos
setattr(cls, "getinfos", getinfos)
- def setconditionContent(self, type, value):
+ def setconditionContent(self, condition_type, value):
if not self.condition:
self.addcondition()
- if type == "reference":
- condition = PLCOpenClasses["condition_reference"]()
+ if condition_type == "reference":
+ condition = PLCOpenParser.CreateElement("reference", "condition")
condition.setname(value)
- elif type == "inline":
- condition = PLCOpenClasses["condition_inline"]()
- condition.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
- condition.settext(value)
- elif type == "connection":
- type = "connectionPointIn"
- condition = PLCOpenClasses["connectionPointIn"]()
- self.condition.setcontent({"name" : type, "value" : condition})
+ elif condition_type == "inline":
+ condition = PLCOpenParser.CreateElement("inline", "condition")
+ condition.setcontent(PLCOpenParser.GetElementClass("ST", "inline"))
+ condition.setanyText(value)
+ elif condition_type == "connection":
+ condition = PLCOpenParser.CreateElementClass("connectionPointIn")
+ self.condition.setcontent(condition)
setattr(cls, "setconditionContent", setconditionContent)
def getconditionContent(self):
if self.condition:
content = self.condition.getcontent()
- values = {"type" : content["name"]}
+ values = {"type" : content.getLocalTag()}
if values["type"] == "reference":
- values["value"] = content["value"].getname()
+ values["value"] = content.getname()
elif values["type"] == "inline":
- values["value"] = content["value"].gettext()
+ values["value"] = content.getanyText()
elif values["type"] == "connectionPointIn":
values["type"] = "connection"
- values["value"] = content["value"]
+ values["value"] = content
return values
return ""
setattr(cls, "getconditionContent", getconditionContent)
@@ -2433,8 +2400,8 @@
def getconditionConnection(self):
if self.condition:
content = self.condition.getcontent()
- if content["name"] == "connectionPointIn":
- return content["value"]
+ if content.getLocalTag() == "connectionPointIn":
+ return content
return None
setattr(cls, "getconditionConnection", getconditionConnection)
@@ -2473,20 +2440,22 @@
def updateElementName(self, old_name, new_name):
if self.condition:
content = self.condition.getcontent()
- if content["name"] == "reference":
- if content["value"].getname() == old_name:
- content["value"].setname(new_name)
- elif content["name"] == "inline":
- content["value"].updateElementName(old_name, new_name)
+ content_name = content.getLocalTag()
+ if content_name == "reference":
+ if content.getname() == old_name:
+ content.setname(new_name)
+ elif content_name == "inline":
+ content.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
def updateElementAddress(self, address_model, new_leading):
if self.condition:
content = self.condition.getcontent()
- if content["name"] == "reference":
- content["value"].setname(update_address(content["value"].getname(), address_model, new_leading))
- elif content["name"] == "inline":
- content["value"].updateElementAddress(address_model, new_leading)
+ content_name = content.getLocalTag()
+ if content_name == "reference":
+ content.setname(update_address(content.getname(), address_model, new_leading))
+ elif content_name == "inline":
+ content.updateElementAddress(address_model, new_leading)
setattr(cls, "updateElementAddress", updateElementAddress)
def getconnections(self):
@@ -2500,30 +2469,31 @@
parent_infos = parent_infos + ["transition", self.getlocalId()]
search_result = []
content = self.condition.getcontent()
- if content["name"] == "reference":
- search_result.extend(_Search([("reference", content["value"].getname())], criteria, parent_infos))
- elif content["name"] == "inline":
- search_result.extend(content["value"].Search(criteria, parent_infos + ["inline"]))
+ content_name = content.getLocalTag()
+ if content_name == "reference":
+ search_result.extend(_Search([("reference", content.getname())], criteria, parent_infos))
+ elif content_name == "inline":
+ search_result.extend(content.Search(criteria, parent_infos + ["inline"]))
return search_result
setattr(cls, "Search", Search)
-cls = _initElementClass("selectionDivergence", "sfcObjects_selectionDivergence", "single")
+cls = _initElementClass("selectionDivergence", "sfcObjects", "single")
if cls:
setattr(cls, "getinfos", _getdivergenceinfosFunction(True, False))
-cls = _initElementClass("selectionConvergence", "sfcObjects_selectionConvergence", "multiple")
+cls = _initElementClass("selectionConvergence", "sfcObjects", "multiple")
if cls:
setattr(cls, "getinfos", _getdivergenceinfosFunction(False, False))
-cls = _initElementClass("simultaneousDivergence", "sfcObjects_simultaneousDivergence", "single")
+cls = _initElementClass("simultaneousDivergence", "sfcObjects", "single")
if cls:
setattr(cls, "getinfos", _getdivergenceinfosFunction(True, True))
-cls = _initElementClass("simultaneousConvergence", "sfcObjects_simultaneousConvergence", "multiple")
+cls = _initElementClass("simultaneousConvergence", "sfcObjects", "multiple")
if cls:
setattr(cls, "getinfos", _getdivergenceinfosFunction(False, True))
-cls = _initElementClass("jumpStep", "sfcObjects_jumpStep", "single")
+cls = _initElementClass("jumpStep", "sfcObjects", "single")
if cls:
def getinfos(self):
infos = _getelementinfos(self)
@@ -2537,7 +2507,7 @@
return _Search([("target", self.gettargetName())], criteria, parent_infos + ["jump", self.getlocalId()])
setattr(cls, "Search", Search)
-cls = PLCOpenClasses.get("actionBlock_action", None)
+cls = PLCOpenParser.GetElementClass("action", "actionBlock")
if cls:
def compatibility(self, tree):
relPosition = reduce(lambda x, y: x | (y.nodeName == "relPosition"), tree.childNodes, False)
@@ -2563,13 +2533,13 @@
def setinlineContent(self, content):
if self.inline:
- self.inline.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
- self.inline.settext(content)
+ self.inline.setcontent(PLCOpenParser.CreateElementClass("ST", "action"))
+ self.inline.setanyText(content)
setattr(cls, "setinlineContent", setinlineContent)
def getinlineContent(self):
if self.inline:
- return self.inline.gettext()
+ return self.inline.getanyText()
return None
setattr(cls, "getinlineContent", getinlineContent)
@@ -2599,7 +2569,7 @@
criteria, parent_infos)
setattr(cls, "Search", Search)
-cls = _initElementClass("actionBlock", "commonObjects_actionBlock", "single")
+cls = _initElementClass("actionBlock", "commonObjects", "single")
if cls:
def compatibility(self, tree):
for child in tree.childNodes[:]:
@@ -2618,7 +2588,7 @@
def setactions(self, actions):
self.action = []
for params in actions:
- action = PLCOpenClasses["actionBlock_action"]()
+ action = PLCOpenParser.GetElementClass("action", "actionBlock")()
action.setqualifier(params["qualifier"])
if params["type"] == "reference":
action.addreference()
@@ -2677,7 +2647,7 @@
def _SearchInIOVariable(self, criteria, parent_infos=[]):
return _Search([("expression", self.getexpression())], criteria, parent_infos + ["io_variable", self.getlocalId()])
-cls = _initElementClass("inVariable", "fbdObjects_inVariable")
+cls = _initElementClass("inVariable", "fbdObjects")
if cls:
setattr(cls, "getinfos", _getvariableinfosFunction("input", False, True))
@@ -2692,7 +2662,7 @@
setattr(cls, "Search", _SearchInIOVariable)
-cls = _initElementClass("outVariable", "fbdObjects_outVariable", "single")
+cls = _initElementClass("outVariable", "fbdObjects", "single")
if cls:
setattr(cls, "getinfos", _getvariableinfosFunction("output", True, False))
@@ -2707,7 +2677,7 @@
setattr(cls, "Search", _SearchInIOVariable)
-cls = _initElementClass("inOutVariable", "fbdObjects_inOutVariable", "single")
+cls = _initElementClass("inOutVariable", "fbdObjects", "single")
if cls:
setattr(cls, "getinfos", _getvariableinfosFunction("inout", True, True))
@@ -2726,7 +2696,7 @@
def _SearchInConnector(self, criteria, parent_infos=[]):
return _Search([("name", self.getname())], criteria, parent_infos + ["connector", self.getlocalId()])
-cls = _initElementClass("continuation", "commonObjects_continuation")
+cls = _initElementClass("continuation", "commonObjects")
if cls:
setattr(cls, "getinfos", _getconnectorinfosFunction("continuation"))
setattr(cls, "Search", _SearchInConnector)
@@ -2736,7 +2706,7 @@
self.name = new_name
setattr(cls, "updateElementName", updateElementName)
-cls = _initElementClass("connector", "commonObjects_connector", "single")
+cls = _initElementClass("connector", "commonObjects", "single")
if cls:
setattr(cls, "getinfos", _getconnectorinfosFunction("connector"))
setattr(cls, "Search", _SearchInConnector)
@@ -2746,15 +2716,16 @@
self.name = new_name
setattr(cls, "updateElementName", updateElementName)
-cls = PLCOpenClasses.get("connection", None)
+cls = PLCOpenParser.GetElementClass("connection")
if cls:
def setpoints(self, points):
- self.position = []
+ positions = []
for point in points:
- position = PLCOpenClasses["position"]()
+ position = PLCOpenParser.CreateElement("position")
position.setx(point.x)
position.sety(point.y)
- self.position.append(position)
+ positions.append(position)
+ self.positions = positions
setattr(cls, "setpoints", setpoints)
def getpoints(self):
@@ -2764,111 +2735,100 @@
return points
setattr(cls, "getpoints", getpoints)
-cls = PLCOpenClasses.get("connectionPointIn", None)
+cls = PLCOpenParser.GetElementClass("connectionPointIn")
if cls:
def setrelPositionXY(self, x, y):
- self.relPosition = PLCOpenClasses["position"]()
+ self.relPosition = PLCOpenParser.CreateElement("position")
self.relPosition.setx(x)
self.relPosition.sety(y)
setattr(cls, "setrelPositionXY", setrelPositionXY)
def getrelPositionXY(self):
- if self.relPosition:
+ if self.relPosition is not None:
return self.relPosition.getx(), self.relPosition.gety()
- else:
- return self.relPosition
+ return self.relPosition
setattr(cls, "getrelPositionXY", getrelPositionXY)
def addconnection(self):
- if not self.content:
- self.content = {"name" : "connection", "value" : [PLCOpenClasses["connection"]()]}
- else:
- self.content["value"].append(PLCOpenClasses["connection"]())
+ self.appendcontent(PLCOpenParser.CreateElement("connection"))
setattr(cls, "addconnection", addconnection)
def removeconnection(self, idx):
- if self.content:
- self.content["value"].pop(idx)
- if len(self.content["value"]) == 0:
- self.content = None
+ if len(self.content) > idx:
+ self.remove(self.content[idx])
setattr(cls, "removeconnection", removeconnection)
def removeconnections(self):
- if self.content:
- self.content = None
+ self.content = None
setattr(cls, "removeconnections", removeconnections)
def getconnections(self):
- if self.content:
- return self.content["value"]
- return []
+ return self.xpath("ppx:connection", namespaces=PLCOpenParser.NSMAP)
setattr(cls, "getconnections", getconnections)
- def setconnectionId(self, idx, id):
- if self.content:
- self.content["value"][idx].setrefLocalId(id)
+ def setconnectionId(self, idx, local_id):
+ if len(self.content) > idx:
+ self.content[idx].setrefLocalId(local_id)
setattr(cls, "setconnectionId", setconnectionId)
def getconnectionId(self, idx):
- if self.content:
- return self.content["value"][idx].getrefLocalId()
+ if len(self.content) > idx:
+ return self.content[idx].getrefLocalId()
return None
setattr(cls, "getconnectionId", getconnectionId)
def setconnectionPoints(self, idx, points):
- if self.content:
- self.content["value"][idx].setpoints(points)
+ if len(self.content) > idx:
+ self.content[idx].setpoints(points)
setattr(cls, "setconnectionPoints", setconnectionPoints)
def getconnectionPoints(self, idx):
- if self.content:
- return self.content["value"][idx].getpoints()
+ if len(self.content) > idx:
+ return self.content[idx].getpoints()
return []
setattr(cls, "getconnectionPoints", getconnectionPoints)
def setconnectionParameter(self, idx, parameter):
- if self.content:
- self.content["value"][idx].setformalParameter(parameter)
+ if len(self.content) > idx:
+ self.content[idx].setformalParameter(parameter)
setattr(cls, "setconnectionParameter", setconnectionParameter)
def getconnectionParameter(self, idx):
- if self.content:
- return self.content["value"][idx].getformalParameter()
+ if len(self.content) > idx:
+ return self.content[idx].getformalParameter()
return None
setattr(cls, "getconnectionParameter", getconnectionParameter)
-cls = PLCOpenClasses.get("connectionPointOut", None)
+cls = PLCOpenParser.GetElementClass("connectionPointOut")
if cls:
def setrelPositionXY(self, x, y):
- self.relPosition = PLCOpenClasses["position"]()
+ self.relPosition = PLCOpenParser.CreateElement("position")
self.relPosition.setx(x)
self.relPosition.sety(y)
setattr(cls, "setrelPositionXY", setrelPositionXY)
def getrelPositionXY(self):
- if self.relPosition:
+ if self.relPosition is not None:
return self.relPosition.getx(), self.relPosition.gety()
return self.relPosition
setattr(cls, "getrelPositionXY", getrelPositionXY)
-cls = PLCOpenClasses.get("value", None)
+cls = PLCOpenParser.GetElementClass("value")
if cls:
def setvalue(self, value):
value = value.strip()
if value.startswith("[") and value.endswith("]"):
- arrayValue = PLCOpenClasses["value_arrayValue"]()
- self.content = {"name" : "arrayValue", "value" : arrayValue}
+ content = PLCOpenParser.CreateElement("arrayValue", "value")
elif value.startswith("(") and value.endswith(")"):
- structValue = PLCOpenClasses["value_structValue"]()
- self.content = {"name" : "structValue", "value" : structValue}
+ content = PLCOpenParser.CreateElement("structValue", "value")
else:
- simpleValue = PLCOpenClasses["value_simpleValue"]()
- self.content = {"name" : "simpleValue", "value": simpleValue}
- self.content["value"].setvalue(value)
+ content = PLCOpenParser.CreateElement("simpleValue", "value")
+ content.setvalue(value)
+ self.setcontent(content)
setattr(cls, "setvalue", setvalue)
def getvalue(self):
- return self.content["value"].getvalue()
+ return self.content.getvalue()
setattr(cls, "getvalue", getvalue)
def extractValues(values):
@@ -2885,15 +2845,15 @@
raise ValueError, _("\"%s\" is an invalid value!")%value
return items
-cls = PLCOpenClasses.get("value_arrayValue", None)
+cls = PLCOpenParser.GetElementClass("arrayValue", "value")
if cls:
arrayValue_model = re.compile("([0-9]*)\((.*)\)$")
def setvalue(self, value):
- self.value = []
+ elements = []
for item in extractValues(value[1:-1]):
item = item.strip()
- element = PLCOpenClasses["arrayValue_value"]()
+ element = PLCOpenParser.CreateElement("value", "arrayValue")
result = arrayValue_model.match(item)
if result is not None:
groups = result.groups()
@@ -2901,7 +2861,8 @@
element.setvalue(groups[1].strip())
else:
element.setvalue(item)
- self.value.append(element)
+ elements.append(element)
+ self.value = elements
setattr(cls, "setvalue", setvalue)
def getvalue(self):
@@ -2918,20 +2879,21 @@
return "[%s]"%", ".join(values)
setattr(cls, "getvalue", getvalue)
-cls = PLCOpenClasses.get("value_structValue", None)
+cls = PLCOpenParser.GetElementClass("structValue", "value")
if cls:
structValue_model = re.compile("(.*):=(.*)")
def setvalue(self, value):
- self.value = []
+ elements = []
for item in extractValues(value[1:-1]):
result = structValue_model.match(item)
if result is not None:
groups = result.groups()
- element = PLCOpenClasses["structValue_value"]()
+ element = PLCOpenParser.CreateElement("value", "structValue")
element.setmember(groups[0].strip())
element.setvalue(groups[1].strip())
- self.value.append(element)
+ elements.append(element)
+ self.value = elements
setattr(cls, "setvalue", setvalue)
def getvalue(self):
@@ -2940,3 +2902,4 @@
values.append("%s := %s"%(element.getmember(), element.getvalue()))
return "(%s)"%", ".join(values)
setattr(cls, "getvalue", getvalue)
+
--- a/xmlclass/xmlclass.py Wed Aug 28 11:43:51 2013 +0200
+++ b/xmlclass/xmlclass.py Wed Aug 28 11:53:50 2013 +0200
@@ -28,7 +28,9 @@
from types import *
from xml.dom import minidom
from xml.sax.saxutils import escape, unescape, quoteattr
+from lxml import etree
from new import classobj
+from collections import OrderedDict
def CreateNode(name):
node = minidom.Node()
@@ -533,28 +535,33 @@
return GetModelNameList
def GenerateAnyInfos(infos):
+
def ExtractAny(tree):
- if tree.nodeName in ["#text", "#cdata-section"]:
- return unicode(unescape(tree.data))
- else:
- return tree
-
- def GenerateAny(value, name=None, indent=0):
- if isinstance(value, (StringType, UnicodeType)):
- try:
- value = value.decode("utf-8")
- except:
- pass
- return u'<![CDATA[%s]]>\n' % value
- else:
- return value.toprettyxml(indent=" "*indent, encoding="utf-8")
+ if infos["namespace"][0] == "##any":
+ return tree.xpath("p/text()")[0]
+ return tree.xpath("ns:p/text()", namespaces={"ns": infos["namespace"][0]})[0]
+
+ def GenerateAny(tree, value):
+ if infos["namespace"][0] == "##any":
+ p = tree.xpath("p")[0]
+ else:
+ p = tree.xpath("ns:p", namespaces={"ns": infos["namespace"][0]})[0]
+ p.text = etree.CDATA(value)
+
+ def InitialAny():
+ text = etree.CDATA(value)
+ if infos["namespace"][0] == "##any":
+ element_name = "p"
+ else:
+ element_name = "{%s}p" % infos["namespace"][0]
+ return etree.Element(element_name, text)
return {
"type": COMPLEXTYPE,
"extract": ExtractAny,
"generate": GenerateAny,
- "initial": lambda: "",
- "check": lambda x: isinstance(x, (StringType, UnicodeType, minidom.Node))
+ "initial": lambda: GenerateAny(""),
+ "check": lambda x: isinstance(x, (StringType, UnicodeType, etree.ElementBase))
}
def GenerateTagInfos(infos):
@@ -591,15 +598,21 @@
def GetElementInitialValue(factory, infos):
infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
- if infos["minOccurs"] == 0 and infos["maxOccurs"] == 1:
- if infos.has_key("default"):
- return infos["elmt_type"]["extract"](infos["default"], False)
- else:
- return None
- elif infos["minOccurs"] == 1 and infos["maxOccurs"] == 1:
- return infos["elmt_type"]["initial"]()
+ if infos["minOccurs"] == 1:
+ element_name = factory.etreeNamespaceFormat % infos["name"]
+ if infos["type"] == SIMPLETYPE:
+ def initial_value():
+ value = etree.Element(element_name)
+ value.text = (infos["elmt_type"]["generate"](infos["elmt_type"]["initial"]()))
+ return value
+ else:
+ def initial_value():
+ value = infos["elmt_type"]["initial"]()
+ DefaultElementClass.__setattr__(value, "tag", element_name)
+ return value
+ return [initial_value() for i in xrange(infos["minOccurs"])]
else:
- return [infos["elmt_type"]["initial"]() for i in xrange(infos["minOccurs"])]
+ return []
def HandleError(message, raise_exception):
if raise_exception:
@@ -649,6 +662,7 @@
sequence_element["elmt_type"] = element_infos
elif choice["elmt_type"] == "tag":
choice["elmt_type"] = GenerateTagInfos(choice)
+ factory.AddToLookupClass(choice["name"], name, DefaultElementClass)
else:
choice_infos = factory.ExtractTypeInfos(choice["name"], name, choice["elmt_type"])
if choice_infos is not None:
@@ -691,6 +705,10 @@
if choices_dict.has_key(choice_name):
raise ValueError("'%s' element defined two times in choice" % choice_name)
choices_dict[choice_name] = infos
+ choices_xpath = "|".join(map(lambda x: "%s:%s" % (factory.TargetNamespace, x), choices_dict.keys()))
+
+ def GetContentChoicesXPath():
+ return choices_xpath
def GetContentInitial():
content_name, infos = choices[0]
@@ -828,6 +846,7 @@
return {
"type": COMPLEXTYPE,
+ "choices_xpath": GetContentChoicesXPath,
"initial": GetContentInitial,
"check": CheckContent,
"extract": ExtractContent,
@@ -901,9 +920,11 @@
self.XMLClassDefinitions = {}
self.DefinedNamespaces = {}
+ self.NSMAP = {}
self.Namespaces = {}
self.SchemaNamespace = None
self.TargetNamespace = None
+ self.etreeNamespaceFormat = "%s"
self.CurrentCompilations = []
@@ -914,6 +935,8 @@
else:
self.ComputedClasses = {}
self.ComputedClassesInfos = {}
+ self.ComputedClassesLookUp = {}
+ self.EquivalentClassesParent = {}
self.AlreadyComputed = {}
def GetQualifiedNameInfos(self, name, namespace=None, canbenone=False):
@@ -1016,7 +1039,9 @@
attrs[name] = infos["extract"]["default"](attr)
elif namespace == "xmlns":
infos = self.GetQualifiedNameInfos("anyURI", self.SchemaNamespace)
- self.DefinedNamespaces[infos["extract"](attr)] = name
+ value = infos["extract"](attr)
+ self.DefinedNamespaces[value] = name
+ self.NSMAP[name] = value
else:
raise ValueError("Invalid attribute \"%s\" for member \"%s\"!" % (qualified_name, node.nodeName))
for attr in valid_attrs:
@@ -1063,20 +1088,45 @@
def ParseSchema(self):
pass
-
+
+ def AddEquivalentClass(self, name, base):
+ if name != base:
+ equivalences = self.EquivalentClassesParent.setdefault(self.etreeNamespaceFormat % base, {})
+ equivalences[self.etreeNamespaceFormat % name] = True
+
+ def AddToLookupClass(self, name, parent, typeinfos):
+ lookup_name = self.etreeNamespaceFormat % name
+ if isinstance(typeinfos, (StringType, UnicodeType)):
+ self.AddEquivalentClass(name, typeinfos)
+ typeinfos = self.etreeNamespaceFormat % typeinfos
+ lookup_classes = self.ComputedClassesLookUp.get(lookup_name)
+ if lookup_classes is None:
+ self.ComputedClassesLookUp[lookup_name] = (typeinfos, parent)
+ elif isinstance(lookup_classes, DictType):
+ lookup_classes[self.etreeNamespaceFormat % parent
+ if parent is not None else None] = typeinfos
+ else:
+ lookup_classes = {self.etreeNamespaceFormat % lookup_classes[1]
+ if lookup_classes[1] is not None else None: lookup_classes[0]}
+ lookup_classes[self.etreeNamespaceFormat % parent
+ if parent is not None else None] = typeinfos
+ self.ComputedClassesLookUp[lookup_name] = lookup_classes
+
def ExtractTypeInfos(self, name, parent, typeinfos):
if isinstance(typeinfos, (StringType, UnicodeType)):
- namespace, name = DecomposeQualifiedName(typeinfos)
- infos = self.GetQualifiedNameInfos(name, namespace)
+ namespace, type_name = DecomposeQualifiedName(typeinfos)
+ if namespace == self.TargetNamespace and name != "base":
+ self.AddToLookupClass(name, parent, type_name)
+ infos = self.GetQualifiedNameInfos(type_name, namespace)
if infos["type"] == COMPLEXTYPE:
- name, parent = self.SplitQualifiedName(name, namespace)
- result = self.CreateClass(name, parent, infos)
+ type_name, parent = self.SplitQualifiedName(type_name, namespace)
+ result = self.CreateClass(type_name, parent, infos)
if result is not None and not isinstance(result, (UnicodeType, StringType)):
self.Namespaces[self.TargetNamespace][result["name"]] = result
return result
elif infos["type"] == ELEMENT and infos["elmt_type"]["type"] == COMPLEXTYPE:
- name, parent = self.SplitQualifiedName(name, namespace)
- result = self.CreateClass(name, parent, infos["elmt_type"])
+ type_name, parent = self.SplitQualifiedName(type_name, namespace)
+ result = self.CreateClass(type_name, parent, infos["elmt_type"])
if result is not None and not isinstance(result, (UnicodeType, StringType)):
self.Namespaces[self.TargetNamespace][result["name"]] = result
return result
@@ -1086,7 +1136,12 @@
return self.CreateClass(name, parent, typeinfos)
elif typeinfos["type"] == SIMPLETYPE:
return typeinfos
-
+
+ def GetEquivalentParents(self, parent):
+ return reduce(lambda x, y: x + y,
+ [[p] + self.GetEquivalentParents(p)
+ for p in self.EquivalentClassesParent.get(parent, {}).keys()], [])
+
"""
Methods that generates the classes
"""
@@ -1123,6 +1178,21 @@
if result is not None and \
not isinstance(result, (UnicodeType, StringType)):
self.Namespaces[self.TargetNamespace][result["name"]] = result
+
+ for name, parents in self.ComputedClassesLookUp.iteritems():
+ if isinstance(parents, DictType):
+ computed_classes = parents.items()
+ elif parents[1] is not None:
+ computed_classes = [(self.etreeNamespaceFormat % parents[1], parents[0])]
+ else:
+ computed_classes = []
+ for parent, computed_class in computed_classes:
+ for equivalent_parent in self.GetEquivalentParents(parent):
+ if not isinstance(parents, DictType):
+ parents = dict(computed_classes)
+ self.ComputedClassesLookUp[name] = parents
+ parents[equivalent_parent] = computed_class
+
return self.ComputedClasses
def CreateClass(self, name, parent, classinfos, baseclass = False):
@@ -1141,9 +1211,12 @@
bases = []
base_infos = classinfos.get("base", None)
if base_infos is not None:
+ namespace, base_name = DecomposeQualifiedName(base_infos)
+ if namespace == self.TargetNamespace:
+ self.AddEquivalentClass(name, base_name)
result = self.ExtractTypeInfos("base", name, base_infos)
if result is None:
- namespace, base_name = DecomposeQualifiedName(base_infos)
+ namespace, base_name = DecomposeQualifiedName(base_infos)
if self.AlreadyComputed.get(base_name, False):
self.ComputeAfter.append((name, parent, classinfos))
if self.TargetNamespace is not None:
@@ -1164,7 +1237,7 @@
if classinfos["base"] is None:
raise ValueError("No class found for base type")
bases.append(classinfos["base"])
- bases.append(object)
+ bases.append(DefaultElementClass)
bases = tuple(bases)
classmembers = {"__doc__": classinfos.get("doc", ""), "IsBaseClass": baseclass}
@@ -1177,11 +1250,8 @@
raise ValueError("\"%s\" type is not a simple type!" % attribute["attr_type"])
attrname = attribute["name"]
if attribute["use"] == "optional":
- classmembers[attrname] = None
classmembers["add%s"%attrname] = generateAddMethod(attrname, self, attribute)
classmembers["delete%s"%attrname] = generateDeleteMethod(attrname)
- else:
- classmembers[attrname] = infos["initial"]()
classmembers["set%s"%attrname] = generateSetMethod(attrname)
classmembers["get%s"%attrname] = generateGetMethod(attrname)
else:
@@ -1200,36 +1270,31 @@
classmembers["set%sbytype" % elmtname] = generateSetChoiceByTypeMethod(self, element["choices"])
infos = GenerateContentInfos(self, name, choices)
elif element["type"] == ANY:
- elmtname = element["name"] = "text"
+ elmtname = element["name"] = "anyText"
element["minOccurs"] = element["maxOccurs"] = 1
infos = GenerateAnyInfos(element)
else:
elmtname = element["name"]
if element["elmt_type"] == "tag":
infos = GenerateTagInfos(element)
+ self.AddToLookupClass(element["name"], name, DefaultElementClass)
else:
infos = self.ExtractTypeInfos(element["name"], name, element["elmt_type"])
if infos is not None:
element["elmt_type"] = infos
if element["maxOccurs"] == "unbounded" or element["maxOccurs"] > 1:
- classmembers[elmtname] = []
classmembers["append%s" % elmtname] = generateAppendMethod(elmtname, element["maxOccurs"], self, element)
classmembers["insert%s" % elmtname] = generateInsertMethod(elmtname, element["maxOccurs"], self, element)
classmembers["remove%s" % elmtname] = generateRemoveMethod(elmtname, element["minOccurs"])
classmembers["count%s" % elmtname] = generateCountMethod(elmtname)
else:
if element["minOccurs"] == 0:
- classmembers[elmtname] = None
classmembers["add%s" % elmtname] = generateAddMethod(elmtname, self, element)
classmembers["delete%s" % elmtname] = generateDeleteMethod(elmtname)
- elif not isinstance(element["elmt_type"], (UnicodeType, StringType)):
- classmembers[elmtname] = element["elmt_type"]["initial"]()
- else:
- classmembers[elmtname] = None
classmembers["set%s" % elmtname] = generateSetMethod(elmtname)
classmembers["get%s" % elmtname] = generateGetMethod(elmtname)
- classmembers["__init__"] = generateInitMethod(self, classinfos)
+ classmembers["init"] = generateInitMethod(self, classinfos)
classmembers["getStructure"] = generateStructureMethod(classinfos)
classmembers["loadXMLTree"] = generateLoadXMLTree(self, classinfos)
classmembers["generateXMLText"] = generateGenerateXMLText(self, classinfos)
@@ -1241,6 +1306,7 @@
classmembers["extraAttrs"] = {}
class_definition = classobj(str(classname), bases, classmembers)
+ setattr(class_definition, "__getattr__", generateGetattrMethod(self, class_definition, classinfos))
setattr(class_definition, "__setattr__", generateSetattrMethod(self, class_definition, classinfos))
class_infos = {"type": COMPILEDCOMPLEXTYPE,
"name": classname,
@@ -1255,6 +1321,9 @@
self.ComputedClasses[classname] = class_definition
self.ComputedClassesInfos[classname] = class_infos
+ self.AddToLookupClass(name, parent, class_definition)
+ self.AddToLookupClass(classname, None, class_definition)
+
return class_infos
"""
@@ -1306,6 +1375,48 @@
return instance
return classExtractfunction
+def generateGetattrMethod(factory, class_definition, classinfos):
+ attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
+ optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
+ elements = dict([(element["name"], element) for element in classinfos["elements"]])
+
+ def getattrMethod(self, name):
+ if attributes.has_key(name):
+ attribute_infos = attributes[name]
+ attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"])
+ value = self.get(name)
+ if value is not None:
+ return attribute_infos["attr_type"]["extract"](value, extract=False)
+ elif attribute_infos.has_key("fixed"):
+ return attribute_infos["attr_type"]["extract"](attribute_infos["fixed"], extract=False)
+ return attribute_infos["attr_type"]["initial"]()
+
+ elif elements.has_key(name):
+ element_infos = elements[name]
+ element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"])
+ if element_infos["type"] == CHOICE:
+ content = self.xpath(element_infos["elmt_type"]["choices_xpath"](), namespaces=factory.NSMAP)
+ if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
+ return content
+ elif len(content) > 0:
+ return content[0]
+ return None
+ elif element_infos["type"] == ANY:
+ return element_infos["elmt_type"]["extract"](self)
+ else:
+ element_name = factory.etreeNamespaceFormat % name
+ if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
+ return self.findall(element_name)
+ else:
+ return self.find(element_name)
+
+ elif classinfos.has_key("base"):
+ return classinfos["base"].__getattr__(self, name)
+
+ return DefaultElementClass.__getattribute__(self, name)
+
+ return getattrMethod
+
"""
Method that generate the method for loading an xml tree by following the
attributes list defined
@@ -1313,31 +1424,56 @@
def generateSetattrMethod(factory, class_definition, classinfos):
attributes = dict([(attr["name"], attr) for attr in classinfos["attributes"] if attr["use"] != "prohibited"])
optional_attributes = dict([(attr["name"], True) for attr in classinfos["attributes"] if attr["use"] == "optional"])
- elements = dict([(element["name"], element) for element in classinfos["elements"]])
+ elements = OrderedDict([(element["name"], element) for element in classinfos["elements"]])
def setattrMethod(self, name, value):
if attributes.has_key(name):
- attributes[name]["attr_type"] = FindTypeInfos(factory, attributes[name]["attr_type"])
- if value is None:
- if optional_attributes.get(name, False):
- return object.__setattr__(self, name, None)
- else:
- raise ValueError("Attribute '%s' isn't optional." % name)
- elif attributes[name].has_key("fixed") and value != attributes[name]["fixed"]:
- raise ValueError, "Value of attribute '%s' can only be '%s'."%(name, str(attributes[name]["fixed"]))
- elif attributes[name]["attr_type"]["check"](value):
- return object.__setattr__(self, name, value)
+ attribute_infos = attributes[name]
+ attribute_infos["attr_type"] = FindTypeInfos(factory, attribute_infos["attr_type"])
+ if optional_attributes.get(name, False):
+ default = attribute_infos.get("default", None)
+ if value is None or value == default:
+ self.attrib.pop(name, None)
+ return
+ elif attribute_infos.has_key("fixed"):
+ return
+ return self.set(name, attribute_infos["attr_type"]["generate"](value))
+
+ elif elements.has_key(name):
+ element_infos = elements[name]
+ element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"])
+ if element_infos["type"] == ANY:
+ element_infos["elmt_type"]["generate"](self, value)
+
else:
- raise ValueError("Invalid value for attribute '%s'." % (name))
- elif elements.has_key(name):
- if CheckElementValue(factory, name, elements[name], value):
- return object.__setattr__(self, name, value)
- else:
- raise ValueError("Invalid value for attribute '%s'." % (name))
+ element_xpath = ("%s:%s" % (factory.TargetNamespace, name)
+ if name != "content"
+ else elements["content"]["elmt_type"]["choices_xpath"]())
+
+ for element in self.xpath(element_xpath, namespaces=factory.NSMAP):
+ self.remove(element)
+
+ if value is not None:
+ previous_elements_xpath = "|".join(map(
+ lambda x: "%s:%s" % (factory.TargetNamespace, x)
+ if x != "content"
+ else elements["content"]["elmt_type"]["choices_xpath"](),
+ elements.keys()[elements.keys().index(name)]))
+
+ insertion_point = len(self.xpath(previous_elements_xpath, namespaces=factory.NSMAP))
+
+ if not isinstance(value, ListType):
+ value = [value]
+
+ for element in reversed(value):
+ self.insert(insertion_point, element)
+
elif classinfos.has_key("base"):
return classinfos["base"].__setattr__(self, name, value)
+
elif class_definition.__dict__.has_key(name):
- return object.__setattr__(self, name, value)
+ return DefaultElementClass.__setattr__(self, name, value)
+
else:
raise AttributeError("'%s' can't have an attribute '%s'." % (self.__class__.__name__, name))
@@ -1725,18 +1861,23 @@
def initMethod(self):
self.extraAttrs = {}
if classinfos.has_key("base"):
- classinfos["base"].__init__(self)
+ classinfos["base"].init(self)
for attribute in classinfos["attributes"]:
attribute["attr_type"] = FindTypeInfos(factory, attribute["attr_type"])
if attribute["use"] == "required":
- setattr(self, attribute["name"], attribute["attr_type"]["initial"]())
- elif attribute["use"] == "optional":
- if attribute.has_key("default"):
- setattr(self, attribute["name"], attribute["attr_type"]["extract"](attribute["default"], False))
- else:
- setattr(self, attribute["name"], None)
+ self.set(attribute["name"], attribute["attr_type"]["generate"](attribute["attr_type"]["initial"]()))
for element in classinfos["elements"]:
- setattr(self, element["name"], GetElementInitialValue(factory, element))
+ if element["type"] != CHOICE:
+ element_name = (
+ etree.QName(factory.NSMAP["xhtml"], "p")
+ if element["type"] == ANY
+ else factory.etreeNamespaceFormat % element["name"])
+ initial = GetElementInitialValue(factory, element)
+ if initial is not None:
+ for value in initial:
+ DefaultElementClass.__setattr__(value, "tag", element_name)
+ value.init()
+ self.append(value)
return initMethod
def generateSetMethod(attr):
@@ -1761,9 +1902,7 @@
extract = infos["elmt_type"]["extract"]
else:
raise ValueError("Invalid class attribute!")
- if infos.has_key("default"):
- setattr(self, attr, extract(infos["default"], False))
- else:
+ if not infos.has_key("default"):
setattr(self, attr, initial())
return addMethod
@@ -1777,10 +1916,10 @@
infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
attr_list = getattr(self, attr)
if maxOccurs == "unbounded" or len(attr_list) < maxOccurs:
- if infos["elmt_type"]["check"](value):
- attr_list.append(value)
+ if len(attr_list) == 0:
+ setattr(self, attr, [value])
else:
- raise ValueError("\"%s\" value isn't valid!" % attr)
+ attr_list[-1].addnext(value)
else:
raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr))
return appendMethod
@@ -1790,10 +1929,12 @@
infos["elmt_type"] = FindTypeInfos(factory, infos["elmt_type"])
attr_list = getattr(self, attr)
if maxOccurs == "unbounded" or len(attr_list) < maxOccurs:
- if infos["elmt_type"]["check"](value):
- attr_list.insert(index, value)
+ if len(attr_list) == 0:
+ setattr(self, attr, [value])
+ elif index == 0:
+ attr_list[0].addprevious(value)
else:
- raise ValueError("\"%s\" value isn't valid!" % attr)
+ attr_list[min(index - 1, len(attr_list) - 1)].addnext(value)
else:
raise ValueError("There can't be more than %d values in \"%s\"!" % (maxOccurs, attr))
return insertMethod
@@ -1805,24 +1946,24 @@
def generateSetChoiceByTypeMethod(factory, choice_types):
choices = dict([(choice["name"], choice) for choice in choice_types])
- def setChoiceMethod(self, type):
- if not choices.has_key(type):
- raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
- choices[type]["elmt_type"] = FindTypeInfos(factory, choices[type]["elmt_type"])
- new_element = choices[type]["elmt_type"]["initial"]()
- self.content = {"name": type, "value": new_element}
- return new_element
+ def setChoiceMethod(self, content_type):
+ if not choices.has_key(content_type):
+ raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type)
+ choices[content_type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
+ new_content = choices[content_type]["elmt_type"]["initial"]()
+ self.content = new_content
+ return new_content
return setChoiceMethod
def generateAppendChoiceByTypeMethod(maxOccurs, factory, choice_types):
choices = dict([(choice["name"], choice) for choice in choice_types])
- def appendChoiceMethod(self, type):
- if not choices.has_key(type):
- raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
- choices[type]["elmt_type"] = FindTypeInfos(factory, choices[type]["elmt_type"])
+ def appendChoiceMethod(self, content_type):
+ if not choices.has_key(content_type):
+ raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type)
+ choices[content_type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
- new_element = choices[type]["elmt_type"]["initial"]()
- self.content.append({"name": type, "value": new_element})
+ new_element = choices[content_type]["elmt_type"]["initial"]()
+ self.appendcontent(new_element)
return new_element
else:
raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs)
@@ -1830,13 +1971,13 @@
def generateInsertChoiceByTypeMethod(maxOccurs, factory, choice_types):
choices = dict([(choice["name"], choice) for choice in choice_types])
- def insertChoiceMethod(self, index, type):
- if not choices.has_key(type):
- raise ValueError("Unknown \"%s\" choice type for \"content\"!" % type)
- choices[type]["elmt_type"] = FindTypeInfos(factory, choices[type]["elmt_type"])
+ def insertChoiceMethod(self, index, content_type):
+ if not choices.has_key(content_type):
+ raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type)
+ choices[type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
- new_element = choices[type]["elmt_type"]["initial"]()
- self.content.insert(index, {"name" : type, "value" : new_element})
+ new_element = choices[content_type]["elmt_type"]["initial"]()
+ self.insertcontent(index, new_element)
return new_element
else:
raise ValueError("There can't be more than %d values in \"content\"!" % maxOccurs)
@@ -1846,7 +1987,7 @@
def removeMethod(self, index):
attr_list = getattr(self, attr)
if len(attr_list) > minOccurs:
- getattr(self, attr).pop(index)
+ self.remove(attr_list[index])
else:
raise ValueError("There can't be less than %d values in \"%s\"!" % (minOccurs, attr))
return removeMethod
@@ -1857,16 +1998,104 @@
return countMethod
"""
-This function generate the classes from a class factory
-"""
-def GenerateClasses(factory):
+This function generate a xml parser from a class factory
+"""
+
+class DefaultElementClass(etree.ElementBase):
+
+ def init(self):
+ pass
+
+ def getLocalTag(self):
+ return etree.QName(self.tag).localname
+
+ def tostring(self):
+ return etree.tostring(self, pretty_print=True)
+
+class XMLElementClassLookUp(etree.PythonElementClassLookup):
+
+ def __init__(self, classes, *args, **kwargs):
+ etree.PythonElementClassLookup.__init__(self, *args, **kwargs)
+ self.LookUpClasses = classes
+
+ def GetElementClass(self, element_tag, parent_tag=None, default=DefaultElementClass):
+ element_class = self.LookUpClasses.get(element_tag, (default, None))
+ if not isinstance(element_class, DictType):
+ if isinstance(element_class[0], (StringType, UnicodeType)):
+ return self.GetElementClass(element_class[0], default=default)
+ return element_class[0]
+
+ element_with_parent_class = element_class.get(parent_tag, default)
+ if isinstance(element_with_parent_class, (StringType, UnicodeType)):
+ return self.GetElementClass(element_with_parent_class, default=default)
+ return element_with_parent_class
+
+ def lookup(self, document, element):
+ parent = element.getparent()
+ return self.GetElementClass(element.tag,
+ parent.tag if parent is not None else None)
+
+class XMLClassParser(etree.XMLParser):
+
+ def __init__(self, namespaces, default_namespace_format, base_class, *args, **kwargs):
+ etree.XMLParser.__init__(self, *args, **kwargs)
+ self.DefaultNamespaceFormat = default_namespace_format
+ self.NSMAP = namespaces
+ targetNamespace = etree.QName(default_namespace_format % "d").namespace
+ if targetNamespace is not None:
+ self.RootNSMAP = {
+ name if targetNamespace != uri else None: uri
+ for name, uri in namespaces.iteritems()}
+ else:
+ self.RootNSMAP = namespaces
+ self.BaseClass = base_class
+
+ def set_element_class_lookup(self, class_lookup):
+ etree.XMLParser.set_element_class_lookup(self, class_lookup)
+ self.ClassLookup = class_lookup
+
+ def CreateRoot(self):
+ if self.BaseClass is not None:
+ root = self.makeelement(
+ self.DefaultNamespaceFormat % self.BaseClass[0],
+ nsmap=self.RootNSMAP)
+ root.init()
+ return root
+ return None
+
+ def GetElementClass(self, element_tag, parent_tag=None):
+ return self.ClassLookup.GetElementClass(
+ self.DefaultNamespaceFormat % element_tag,
+ self.DefaultNamespaceFormat % parent_tag
+ if parent_tag is not None else parent_tag,
+ None)
+
+ def CreateElement(self, element_tag, parent_tag=None):
+ new_element = self.GetElementClass(element_tag, parent_tag)()
+ DefaultElementClass.__setattr__(new_element, "tag", self.DefaultNamespaceFormat % element_tag)
+ new_element.init()
+ return new_element
+
+def GenerateParser(factory, xsdstring):
ComputedClasses = factory.CreateClasses()
if factory.FileName is not None and len(ComputedClasses) == 1:
- UpdateXMLClassGlobals(ComputedClasses[factory.FileName])
- return ComputedClasses[factory.FileName]
+ ComputedClasses = ComputedClasses[factory.FileName]
+ BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass]
else:
- UpdateXMLClassGlobals(ComputedClasses)
- return ComputedClasses
+ BaseClass = []
+ UpdateXMLClassGlobals(ComputedClasses)
+
+ parser = XMLClassParser(
+ factory.NSMAP,
+ factory.etreeNamespaceFormat,
+ BaseClass[0] if len(BaseClass) == 1 else None,
+ schema = etree.XMLSchema(etree.fromstring(xsdstring)),
+ strip_cdata = False, remove_blank_text=True)
+ class_lookup = XMLElementClassLookUp(factory.ComputedClassesLookUp)
+ parser.set_element_class_lookup(class_lookup)
+
+ return parser
def UpdateXMLClassGlobals(classes):
globals().update(classes)
+