#!/usr/bin/env python
# -*- coding: utf-8 -*-
#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
#based on the plcopen standard.
#
#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
#
#See COPYING file for copyrights details.
#
#This library is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public
#License as published by the Free Software Foundation; either
#version 2.1 of the License, or (at your option) any later version.
#
#This library is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#General Public License for more details.
#
#You should have received a copy of the GNU General Public
#License along with this library; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from xmlclass import *
from types import *
import os, re
"""
Dictionary that makes the relation between var names in plcopen and displayed values
"""
VarTypes = {"Local" : "localVars", "Temp" : "tempVars", "Input" : "inputVars",
"Output" : "outputVars", "InOut" : "inOutVars", "External" : "externalVars",
"Global" : "globalVars", "Access" : "accessVars"}
"""
Define in which order var types must be displayed
"""
VarOrder = ["Local","Temp","Input","Output","InOut","External","Global","Access"]
"""
Define which action qualifier must be associated with a duration
"""
QualifierList = {"N" : False, "R" : False, "S" : False, "L" : True, "D" : True,
"P" : False, "P0" : False, "P1" : False, "SD" : True, "DS" : True, "SL" : True}
PLCOpenClasses = GenerateClassesFromXSD(os.path.join(os.path.split(__file__)[0], "TC6_XML_V10_B.xsd"))
cls = PLCOpenClasses.get("formattedText", None)
if cls:
def updateElementName(self, old_name, new_name):
index = self.text.find(old_name)
while index != -1:
if index > 0 and (self.text[index - 1].isalnum() or self.text[index - 1] == "_"):
index = self.text.find(old_name, index + len(old_name))
elif index < len(self.text) - len(old_name) and (self.text[index + len(old_name)].isalnum() or self.text[index + len(old_name)] == "_"):
index = self.text.find(old_name, index + len(old_name))
else:
self.text = self.text[:index] + new_name + self.text[index + len(old_name):]
index = self.text.find(old_name, index + len(new_name))
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("project", None)
if cls:
cls.singleLineAttributes = False
def setname(self, name):
self.contentHeader.setname(name)
setattr(cls, "setname", setname)
def getname(self):
return self.contentHeader.getname()
setattr(cls, "getname", getname)
def getfileHeader(self):
fileheader = {}
fileheader["companyName"] = self.fileHeader.getcompanyName()
if self.fileHeader.getcompanyURL():
fileheader["companyURL"] = self.fileHeader.getcompanyURL()
fileheader["productName"] = self.fileHeader.getproductName()
fileheader["productVersion"] = self.fileHeader.getproductVersion()
if self.fileHeader.getproductRelease():
fileheader["productRelease"] = self.fileHeader.getproductRelease()
fileheader["creationDateTime"] = self.fileHeader.getcreationDateTime()
if self.fileHeader.getcontentDescription():
fileheader["contentDescription"] = self.fileHeader.getcontentDescription()
return fileheader
setattr(cls, "getfileHeader", getfileHeader)
def setfileHeader(self, fileheader):
self.fileHeader.setcompanyName(fileheader["companyName"])
if "companyURL" in fileheader:
self.fileHeader.setcompanyURL(fileheader["companyURL"])
self.fileHeader.setproductName(fileheader["productName"])
self.fileHeader.setproductVersion(fileheader["productVersion"])
if "productRelease" in fileheader:
self.fileHeader.setproductRelease(fileheader["productRelease"])
self.fileHeader.setcreationDateTime(fileheader["creationDateTime"])
if "contentDescription" in fileheader:
self.fileHeader.setcontentDescription(fileheader["contentDescription"])
setattr(cls, "setfileHeader", setfileHeader)
def getcontentHeader(self):
contentheader = {}
contentheader["projectName"] = self.contentHeader.getname()
if self.contentHeader.getversion():
contentheader["projectVersion"] = self.contentHeader.getversion()
if self.contentHeader.getmodificationDateTime():
contentheader["modificationDateTime"] = self.contentHeader.getmodificationDateTime()
if self.contentHeader.getorganization():
contentheader["organization"] = self.contentHeader.getorganization()
if self.contentHeader.getauthor():
contentheader["authorName"] = self.contentHeader.getauthor()
if self.contentHeader.getlanguage():
contentheader["language"] = self.contentHeader.getlanguage()
contentheader["pageSize"] = self.contentHeader.getpageSize()
contentheader["scaling"] = self.contentHeader.getscaling()
return contentheader
setattr(cls, "getcontentHeader", getcontentHeader)
def setcontentHeader(self, contentheader):
self.contentHeader.setname(contentheader["projectName"])
if "projectVersion" in contentheader:
self.contentHeader.setversion(contentheader["projectVersion"])
if "modificationDateTime" in contentheader:
self.contentHeader.setmodificationDateTime(contentheader["modificationDateTime"])
if "organization" in contentheader:
self.contentHeader.setorganization(contentheader["organization"])
if "authorName" in contentheader:
self.contentHeader.setauthor(contentheader["authorName"])
if "language" in contentheader:
self.contentHeader.setlanguage(contentheader["language"])
self.contentHeader.setpageSize(*contentheader["pageSize"])
self.contentHeader.setscaling(contentheader["scaling"])
setattr(cls, "setcontentHeader", setcontentHeader)
def getdataTypes(self):
return self.types.getdataTypeElements()
setattr(cls, "getdataTypes", getdataTypes)
def getdataType(self, name):
return self.types.getdataTypeElement(name)
setattr(cls, "getdataType", getdataType)
def appenddataType(self, name):
self.types.appenddataTypeElement(name)
setattr(cls, "appenddataType", appenddataType)
def insertdataType(self, index, datatype):
self.types.insertdataTypeElement(index, datatype)
setattr(cls, "insertdataType", insertdataType)
def removedataType(self, name):
self.types.removedataTypeElement(name)
setattr(cls, "removedataType", removedataType)
def getpous(self):
return self.types.getpouElements()
setattr(cls, "getpous", getpous)
def getpou(self, name):
return self.types.getpouElement(name)
setattr(cls, "getpou", getpou)
def appendpou(self, name, pou_type, body_type):
self.types.appendpouElement(name, pou_type, body_type)
setattr(cls, "appendpou", appendpou)
def insertpou(self, index, pou):
self.types.insertpouElement(index, pou)
setattr(cls, "insertpou", insertpou)
def removepou(self, name):
self.types.removepouElement(name)
setattr(cls, "removepou", removepou)
def getconfigurations(self):
configurations = self.instances.configurations.getconfiguration()
if configurations:
return configurations
return []
setattr(cls, "getconfigurations", getconfigurations)
def getconfiguration(self, name):
for configuration in self.instances.configurations.getconfiguration():
if configuration.getname() == name:
return configuration
return None
setattr(cls, "getconfiguration", getconfiguration)
def addconfiguration(self, name):
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.setname(name)
self.instances.configurations.appendconfiguration(new_configuration)
setattr(cls, "addconfiguration", addconfiguration)
def removeconfiguration(self, name):
found = False
for idx, configuration in enumerate(self.instances.configurations.getconfiguration()):
if configuration.getname() == name:
self.instances.configurations.removeconfiguration(idx)
found = True
break
if not found:
raise ValueError, "\"%s\" configuration doesn't exist !!!"%name
setattr(cls, "removeconfiguration", removeconfiguration)
def getconfigurationResource(self, config_name, name):
configuration = self.getconfiguration(config_name)
if configuration:
for resource in configuration.getresource():
if resource.getname() == name:
return resource
return None
setattr(cls, "getconfigurationResource", getconfigurationResource)
def addconfigurationResource(self, config_name, name):
configuration = self.getconfiguration(config_name)
if configuration:
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.setname(name)
configuration.appendresource(new_resource)
setattr(cls, "addconfigurationResource", addconfigurationResource)
def removeconfigurationResource(self, config_name, name):
configuration = self.getconfiguration(config_name)
if configuration:
found = False
for idx, resource in enumerate(configuration.getresource()):
if resource.getname() == name:
configuration.removeresource(idx)
found = True
break
if not found:
raise ValueError, "\"%s\" resource doesn't exist in \"%s\" configuration !!!"%(name, config_name)
setattr(cls, "removeconfigurationResource", removeconfigurationResource)
def updateElementName(self, old_name, new_name):
for pou in self.types.getpouElements():
pou.updateElementName(old_name, new_name)
for configuration in self.instances.configurations.getconfiguration():
configuration.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("project_fileHeader", None)
if cls:
cls.singleLineAttributes = False
cls = PLCOpenClasses.get("project_contentHeader", None)
if cls:
cls.singleLineAttributes = False
def setpageSize(self, width, height):
self.coordinateInfo.setpageSize(width, height)
setattr(cls, "setpageSize", setpageSize)
def getpageSize(self):
return self.coordinateInfo.getpageSize()
setattr(cls, "getpageSize", getpageSize)
def setscaling(self, scaling):
for language, (x, y) in scaling.items():
self.coordinateInfo.setscaling(language, x, y)
setattr(cls, "setscaling", setscaling)
def getscaling(self):
scaling = {}
scaling["FBD"] = self.coordinateInfo.getscaling("FBD")
scaling["LD"] = self.coordinateInfo.getscaling("LD")
scaling["SFC"] = self.coordinateInfo.getscaling("SFC")
return scaling
setattr(cls, "getscaling", getscaling)
cls = PLCOpenClasses.get("contentHeader_coordinateInfo", None)
if cls:
def setpageSize(self, width, height):
if width == 0 and height == 0:
self.deletepageSize()
else:
if self.pageSize is None:
self.addpageSize()
self.pageSize.setx(width)
self.pageSize.sety(height)
setattr(cls, "setpageSize", setpageSize)
def getpageSize(self):
if self.pageSize is not None:
return self.pageSize.getx(), self.pageSize.gety()
return 0, 0
setattr(cls, "getpageSize", getpageSize)
def setscaling(self, language, x, y):
if language == "FBD":
self.fbd.scaling.setx(x)
self.fbd.scaling.sety(y)
elif language == "LD":
self.ld.scaling.setx(x)
self.ld.scaling.sety(y)
elif language == "SFC":
self.sfc.scaling.setx(x)
self.sfc.scaling.sety(y)
setattr(cls, "setscaling", setscaling)
def getscaling(self, language):
if language == "FBD":
return self.fbd.scaling.getx(), self.fbd.scaling.gety()
elif language == "LD":
return self.ld.scaling.getx(), self.ld.scaling.gety()
elif language == "SFC":
return self.sfc.scaling.getx(), self.sfc.scaling.gety()
return 0, 0
setattr(cls, "getscaling", getscaling)
cls = PLCOpenClasses.get("configurations_configuration", None)
if cls:
def updateElementName(self, old_name, new_name):
for resource in self.getresource():
resource.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("configuration_resource", None)
if cls:
def updateElementName(self, old_name, new_name):
for instance in self.getpouInstance():
instance.updateElementName(old_name, new_name)
for task in self.gettask():
task.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("resource_task", None)
if cls:
def updateElementName(self, old_name, new_name):
if self.single == old_name:
self.single = new_name
for instance in self.getpouInstance():
instance.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("pouInstance", None)
if cls:
def updateElementName(self, old_name, new_name):
if self.type == old_name:
self.type = new_name
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("project_types", None)
if cls:
def getdataTypeElements(self):
return self.dataTypes.getdataType()
setattr(cls, "getdataTypeElements", getdataTypeElements)
def getdataTypeElement(self, name):
elements = self.dataTypes.getdataType()
for element in elements:
if element.getname() == name:
return element
return None
setattr(cls, "getdataTypeElement", getdataTypeElement)
def appenddataTypeElement(self, name):
for element in self.dataTypes.getdataType():
if element.getname() == name:
raise ValueError, "\"%s\" Data Type already exists !!!"%name
new_datatype = PLCOpenClasses["dataTypes_dataType"]()
new_datatype.setname(name)
new_datatype.baseType.setcontent({"name" : "BOOL", "value" : None})
self.dataTypes.appenddataType(new_datatype)
setattr(cls, "appenddataTypeElement", appenddataTypeElement)
def insertdataTypeElement(self, index, dataType):
self.dataTypes.insertdataType(index, dataType)
setattr(cls, "insertdataTypeElement", insertdataTypeElement)
def removedataTypeElement(self, name):
found = False
for idx, element in enumerate(self.dataTypes.getdataType()):
if element.getname() == name:
self.dataTypes.removedataType(idx)
found = True
break
if not found:
raise ValueError, "\"%s\" Data Type doesn't exist !!!"%name
setattr(cls, "removedataTypeElement", removedataTypeElement)
def getpouElements(self):
return self.pous.getpou()
setattr(cls, "getpouElements", getpouElements)
def getpouElement(self, name):
elements = self.pous.getpou()
for element in elements:
if element.getname() == name:
return element
return None
setattr(cls, "getpouElement", getpouElement)
def appendpouElement(self, name, pou_type, body_type):
for element in self.pous.getpou():
if element.getname() == name:
raise ValueError, "\"%s\" POU already exists !!!"%name
new_pou = PLCOpenClasses["pous_pou"]()
new_pou.setname(name)
new_pou.setpouType(pou_type)
new_pou.setbody(PLCOpenClasses["body"]())
new_pou.setbodyType(body_type)
self.pous.appendpou(new_pou)
setattr(cls, "appendpouElement", appendpouElement)
def insertpouElement(self, index, pou):
self.pous.insertpou(index, pou)
setattr(cls, "insertpouElement", insertpouElement)
def removepouElement(self, name):
found = False
for idx, element in enumerate(self.pous.getpou()):
if element.getname() == name:
self.pous.removepou(idx)
found = True
break
if not found:
raise ValueError, "\"%s\" POU doesn't exist !!!"%name
setattr(cls, "removepouElement", removepouElement)
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"]()})
else:
raise ValueError, "%s isn't a valid body type!"%type
def getbodyType(self):
return self.body.getcontent()["name"]
def resetexecutionOrder(self):
self.body.resetexecutionOrder()
def compileexecutionOrder(self):
self.body.compileexecutionOrder()
def setelementExecutionOrder(self, instance, new_executionOrder):
self.body.setelementExecutionOrder(instance, new_executionOrder)
def addinstance(self, name, instance):
self.body.appendcontentInstance(name, instance)
def getinstances(self):
return self.body.getcontentInstances()
def getinstance(self, id):
return self.body.getcontentInstance(id)
def getrandomInstance(self, exclude):
return self.body.getcontentRandomInstance(exclude)
def getinstanceByName(self, name):
return self.body.getcontentInstanceByName(name)
def removeinstance(self, id):
self.body.removecontentInstance(id)
def settext(self, text):
self.body.settext(text)
def gettext(self):
return self.body.gettext()
setattr(cls, "gettext", gettext)
cls = PLCOpenClasses.get("pous_pou", None)
if cls:
setattr(cls, "setbodyType", setbodyType)
setattr(cls, "getbodyType", getbodyType)
setattr(cls, "resetexecutionOrder", resetexecutionOrder)
setattr(cls, "compileexecutionOrder", compileexecutionOrder)
setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
setattr(cls, "addinstance", addinstance)
setattr(cls, "getinstances", getinstances)
setattr(cls, "getinstance", getinstance)
setattr(cls, "getrandomInstance", getrandomInstance)
setattr(cls, "getinstanceByName", getinstanceByName)
setattr(cls, "removeinstance", removeinstance)
setattr(cls, "settext", settext)
setattr(cls, "gettext", gettext)
def getvars(self):
vars = []
reverse_types = {}
for name, value in VarTypes.items():
reverse_types[value] = name
for varlist in self.interface.getcontent():
vars.append((reverse_types[varlist["name"]], varlist["value"]))
return vars
setattr(cls, "getvars", getvars)
def setvars(self, vars):
self.interface.setcontent([])
for vartype, varlist in vars:
self.interface.appendcontent({"name" : VarTypes[vartype], "value" : varlist})
setattr(cls, "setvars", setvars)
def addpouVar(self, type, name):
content = self.interface.getcontent()
if len(content) == 0 or content[-1]["name"] != "localVars":
content.append({"name" : "localVars", "value" : PLCOpenClasses["interface_localVars"]()})
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" : "localVars", "value" : PLCOpenClasses["interface_localVars"]()})
var = PLCOpenClasses["varListPlain_variable"]()
var.setname(name)
var_type = PLCOpenClasses["dataType"]()
derived_type = PLCOpenClasses["derivedTypes_derived"]()
derived_type.setname(type)
var_type.setcontent({"name" : "derived", "value" : derived_type})
var.settype(var_type)
content[-1]["value"].appendvariable(var)
setattr(cls, "addpouVar", addpouVar)
def changepouVar(self, old_type, old_name, new_type, new_name):
content = self.interface.getcontent()
for varlist in content:
variables = varlist["value"].getvariable()
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:
var.setname(new_name)
vartype_content["value"].setname(new_type)
return
setattr(cls, "changepouVar", changepouVar)
def removepouVar(self, type, name):
content = self.interface.getcontent()
for varlist in content:
variables = varlist["value"].getvariable()
for var in variables:
if var.getname() == name:
vartype_content = var.gettype().getcontent()
if vartype_content["name"] == "derived" and vartype_content["value"].getname() == type:
variables.remove(var)
break
if len(varlist["value"].getvariable()) == 0:
content.remove(varlist)
break
setattr(cls, "removepouVar", removepouVar)
def hasblock(self, name):
if self.getbodyType() in ["FBD", "LD", "SFC"]:
for instance in self.getinstances():
if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
return True
if self.transitions:
for transition in self.transitions.gettransition():
result = transition.hasblock(name)
if result:
return result
if self.actions:
for action in self.actions.getaction():
result = action.hasblock(name)
if result:
return result
return False
setattr(cls, "hasblock", hasblock)
def addtransition(self, name, type):
if not self.transitions:
self.addtransitions()
self.transitions.settransition([])
transition = PLCOpenClasses["transitions_transition"]()
transition.setname(name)
transition.setbodyType(type)
if type == "ST":
transition.settext(":= ;")
elif type == "IL":
transition.settext("\tST\t%s"%name)
self.transitions.appendtransition(transition)
setattr(cls, "addtransition", addtransition)
def gettransition(self, name):
if self.transitions:
for transition in self.transitions.gettransition():
if transition.getname() == name:
return transition
return None
setattr(cls, "gettransition", gettransition)
def gettransitionList(self):
if self.transitions:
return self.transitions.gettransition()
return []
setattr(cls, "gettransitionList", gettransitionList)
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:
transitions.pop(i)
removed = True
i += 1
if not removed:
raise ValueError, "Transition with name %s doesn't exists!"%name
setattr(cls, "removetransition", removetransition)
def addaction(self, name, type):
if not self.actions:
self.addactions()
self.actions.setaction([])
action = PLCOpenClasses["actions_action"]()
action.setname(name)
action.setbodyType(type)
self.actions.appendaction(action)
setattr(cls, "addaction", addaction)
def getaction(self, name):
if self.actions:
for action in self.actions.getaction():
if action.getname() == name:
return action
return None
setattr(cls, "getaction", getaction)
def getactionList(self):
if self.actions:
return self.actions.getaction()
return []
setattr(cls, "getactionList", getactionList)
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:
actions.pop(i)
removed = True
i += 1
if not removed:
raise ValueError, "Action with name %s doesn't exists!"%name
setattr(cls, "removeaction", removeaction)
def updateElementName(self, old_name, new_name):
self.body.updateElementName(old_name, new_name)
for action in self.getactionList():
action.updateElementName(old_name, new_name)
for transition in self.gettransitionList():
transition.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("transitions_transition", None)
if cls:
setattr(cls, "setbodyType", setbodyType)
setattr(cls, "getbodyType", getbodyType)
setattr(cls, "resetexecutionOrder", resetexecutionOrder)
setattr(cls, "compileexecutionOrder", compileexecutionOrder)
setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
setattr(cls, "addinstance", addinstance)
setattr(cls, "getinstances", getinstances)
setattr(cls, "getinstance", getinstance)
setattr(cls, "getrandomInstance", getrandomInstance)
setattr(cls, "getinstanceByName", getinstanceByName)
setattr(cls, "removeinstance", removeinstance)
setattr(cls, "settext", settext)
setattr(cls, "gettext", gettext)
def updateElementName(self, old_name, new_name):
self.body.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
def hasblock(self, name):
if self.getbodyType() in ["FBD", "LD", "SFC"]:
for instance in self.getinstances():
if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
return True
return False
setattr(cls, "hasblock", hasblock)
cls = PLCOpenClasses.get("actions_action", None)
if cls:
setattr(cls, "setbodyType", setbodyType)
setattr(cls, "getbodyType", getbodyType)
setattr(cls, "resetexecutionOrder", resetexecutionOrder)
setattr(cls, "compileexecutionOrder", compileexecutionOrder)
setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
setattr(cls, "addinstance", addinstance)
setattr(cls, "getinstances", getinstances)
setattr(cls, "getinstance", getinstance)
setattr(cls, "getrandomInstance", getrandomInstance)
setattr(cls, "getinstanceByName", getinstanceByName)
setattr(cls, "removeinstance", removeinstance)
setattr(cls, "settext", settext)
setattr(cls, "gettext", gettext)
def updateElementName(self, old_name, new_name):
self.body.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
def hasblock(self, name):
if self.getbodyType() in ["FBD", "LD", "SFC"]:
for instance in self.getinstances():
if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
return True
return False
setattr(cls, "hasblock", hasblock)
cls = PLCOpenClasses.get("body", None)
if cls:
cls.currentExecutionOrderId = 0
def resetcurrentExecutionOrderId(self):
object.__setattr__(self, "currentExecutionOrderId", 0)
setattr(cls, "resetcurrentExecutionOrderId", resetcurrentExecutionOrderId)
def getnewExecutionOrderId(self):
object.__setattr__(self, "currentExecutionOrderId", self.currentExecutionOrderId + 1)
return self.currentExecutionOrderId
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)
else:
raise TypeError, "Can only generate execution order on FBD networks!"
setattr(cls, "resetexecutionOrder", resetexecutionOrder)
def compileexecutionOrder(self):
if self.content["name"] == "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()
if connections and len(connections) == 1:
self.compileelementExecutionOrder(connections[0])
element["value"].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":
localid = link.getrefLocalId()
instance = self.getcontentInstance(localid)
if isinstance(instance, PLCOpenClasses.get("fbdObjects_block", None)) 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:
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:
connections = tmp_instance.connectionPointIn.getconnections()
if connections and len(connections) == 1:
self.compileelementExecutionOrder(connections[0])
else:
raise TypeError, "Can only generate execution order on FBD networks!"
setattr(cls, "compileelementExecutionOrder", compileelementExecutionOrder)
def setelementExecutionOrder(self, instance, new_executionOrder):
if self.content["name"] == "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()
if old_executionOrder <= element_executionOrder <= new_executionOrder:
element["value"].setexecutionOrderId(element_executionOrder - 1)
if new_executionOrder <= element_executionOrder <= old_executionOrder:
element["value"].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"]:
self.content["value"].appendcontent({"name" : name, "value" : 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
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"]:
for element in self.content["value"].getcontent():
if element["value"].getlocalId() == id:
return element["value"]
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"]:
for element in self.content["value"].getcontent():
if element["value"].getlocalId() not in exclude:
return element["value"]
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"]
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"]:
i = 0
removed = False
elements = self.content["value"].getcontent()
while i < len(elements) and not removed:
if elements[i]["value"].getlocalId() == id:
self.content["value"].removecontent(i)
removed = True
i += 1
if not removed:
raise ValueError, "Instance with id %d doesn't exists!"%id
else:
raise TypeError, "%s body don't have instances!"%self.content["name"]
setattr(cls, "removecontentInstance", removecontentInstance)
def settext(self, text):
if self.content["name"] in ["IL","ST"]:
self.content["value"].settext(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()
else:
raise TypeError, "%s body don't have text!"%self.content["name"]
setattr(cls, "gettext", gettext)
def updateElementName(self, old_name, new_name):
if self.content["name"] in ["IL", "ST"]:
self.content["value"].updateElementName(old_name, new_name)
else:
for element in self.content["value"].getcontent():
element["value"].updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
def getx(self):
return self.position.getx()
def gety(self):
return self.position.gety()
def setx(self, x):
self.position.setx(x)
def sety(self, y):
self.position.sety(y)
cls = PLCOpenClasses.get("commonObjects_comment", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def setcontentText(self, text):
self.content.settext(text)
setattr(cls, "setcontentText", setcontentText)
def getcontentText(self):
return self.content.gettext()
setattr(cls, "getcontentText", getcontentText)
def updateElementName(self, old_name, new_name):
self.content.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("fbdObjects_block", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
if self.typeName == old_name:
self.typeName = new_name
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("ldObjects_leftPowerRail", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
pass
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("ldObjects_rightPowerRail", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
pass
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("ldObjects_contact", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
if self.variable == old_name:
self.variable = new_name
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("ldObjects_coil", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
if self.variable == old_name:
self.variable = new_name
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("sfcObjects_step", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
pass
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("sfcObjects_transition", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def setconditionContent(self, type, value):
if not self.condition:
self.addcondition()
if type == "reference":
condition = PLCOpenClasses["condition_reference"]()
condition.setname(value)
elif type == "inline":
condition = PLCOpenClasses["condition_inline"]()
condition.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
condition.settext(value)
elif type == "connection":
condition = [PLCOpenClasses["connection"]()]
self.condition.setcontent({"name" : type, "value" : condition})
setattr(cls, "setconditionContent", setconditionContent)
def getconditionContent(self):
if self.condition:
content = self.condition.getcontent()
values = {"type" : content["name"]}
if values["type"] == "reference":
values["value"] = content["value"].getname()
elif values["type"] == "inline":
values["value"] = content["value"].gettext()
return values
return ""
setattr(cls, "getconditionContent", getconditionContent)
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)
setattr(cls, "updateElementName", updateElementName)
def addconnection(self):
if self.condition:
content = self.condition.getcontent()
if content["name"] != "connection":
self.condition.setcontent({"name" : "connection", "value" : [PLCOpenClasses["connection"]()]})
content = self.condition.getcontent()
else:
content["value"].append(PLCOpenClasses["connection"]())
setattr(cls, "addconnection", addconnection)
def removeconnection(self, idx):
if self.condition:
content = self.condition.getcontent()
if content["name"] == "connection":
content["value"].pop(idx)
setattr(cls, "removeconnection", removeconnection)
def removeconnections(self):
if self.condition:
content = self.condition.getcontent()
if content["name"] == "connection":
content["value"] = [PLCOpenClasses["connection"]()]
setattr(cls, "removeconnections", removeconnections)
def getconnections(self):
if self.condition:
content = self.condition.getcontent()
if content["name"] == "connection":
return content["value"]
setattr(cls, "getconnections", getconnections)
def setconnectionId(self, idx, id):
if self.condition:
content = self.condition.getcontent()
if content["name"] == "connection":
content["value"][idx].setrefLocalId(id)
setattr(cls, "setconnectionId", setconnectionId)
def getconnectionId(self, idx):
if self.condition:
content = self.condition.getcontent()
if content["name"] == "connection":
return content["value"][idx].getrefLocalId()
return None
setattr(cls, "getconnectionId", getconnectionId)
def setconnectionPoints(self, idx, points):
if self.condition:
content = self.condition.getcontent()
if content["name"] == "connection":
content["value"][idx].setpoints(points)
setattr(cls, "setconnectionPoints", setconnectionPoints)
def getconnectionPoints(self, idx):
if self.condition:
content = self.condition.getcontent()
if content["name"] == "connection":
return content["value"][idx].getpoints()
return None
setattr(cls, "getconnectionPoints", getconnectionPoints)
def setconnectionParameter(self, idx, parameter):
if self.condition:
content = self.condition.getcontent()
if content["name"] == "connection":
content["value"][idx].setformalParameter(parameter)
setattr(cls, "setconnectionParameter", setconnectionParameter)
def getconnectionParameter(self, idx):
if self.condition:
content = self.condition.getcontent()
if content["name"] == "connection":
return content["value"][idx].getformalParameter()
return None
setattr(cls, "getconnectionParameter", getconnectionParameter)
cls = PLCOpenClasses.get("sfcObjects_selectionDivergence", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
pass
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("sfcObjects_selectionConvergence", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
pass
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("sfcObjects_simultaneousDivergence", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
pass
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("sfcObjects_simultaneousConvergence", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
pass
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("sfcObjects_jumpStep", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
pass
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("actionBlock_action", None)
if cls:
def setreferenceName(self, name):
if self.reference:
self.reference.setname(name)
setattr(cls, "setreferenceName", setreferenceName)
def getreferenceName(self):
if self.reference:
return self.reference.getname()
return None
setattr(cls, "getreferenceName", getreferenceName)
def setinlineContent(self, content):
if self.inline:
self.inline.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
self.inline.settext(content)
setattr(cls, "setinlineContent", setinlineContent)
def getinlineContent(self):
if self.inline:
return self.inline.gettext()
return None
setattr(cls, "getinlineContent", getinlineContent)
def updateElementName(self, old_name, new_name):
if self.reference and self.reference.getname() == old_name:
self.reference.setname(new_name)
if self.inline:
self.inline.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("commonObjects_actionBlock", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def setactions(self, actions):
self.action = []
for params in actions:
action = PLCOpenClasses["actionBlock_action"]()
action.setqualifier(params["qualifier"])
if params["type"] == "reference":
action.addreference()
action.setreferenceName(params["value"])
else:
action.addinline()
action.setinlineContent(params["value"])
if "duration" in params:
action.setduration(params["duration"])
if "indicator" in params:
action.setindicator(params["indicator"])
self.action.append(action)
setattr(cls, "setactions", setactions)
def getactions(self):
actions = []
for action in self.action:
params = {}
params["qualifier"] = action.getqualifier()
if params["qualifier"] is None:
params["qualifier"] = "N"
if action.getreference():
params["type"] = "reference"
params["value"] = action.getreferenceName()
elif action.getinline():
params["type"] = "inline"
params["value"] = action.getinlineContent()
duration = action.getduration()
if duration:
params["duration"] = duration
indicator = action.getindicator()
if indicator:
params["indicator"] = indicator
actions.append(params)
return actions
setattr(cls, "getactions", getactions)
def updateElementName(self, old_name, new_name):
for action in self.action:
action.updateElementName(old_name, new_name)
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("fbdObjects_inVariable", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
if self.expression == old_name:
self.expression = new_name
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("fbdObjects_outVariable", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
if self.expression == old_name:
self.expression = new_name
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("fbdObjects_inOutVariable", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
if self.expression == old_name:
self.expression = new_name
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("commonObjects_continuation", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
pass
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("commonObjects_connector", None)
if cls:
setattr(cls, "getx", getx)
setattr(cls, "gety", gety)
setattr(cls, "setx", setx)
setattr(cls, "sety", sety)
def updateElementName(self, old_name, new_name):
pass
setattr(cls, "updateElementName", updateElementName)
cls = PLCOpenClasses.get("connection", None)
if cls:
def setpoints(self, points):
self.position = []
for point in points:
position = PLCOpenClasses["position"]()
position.setx(point.x)
position.sety(point.y)
self.position.append(position)
setattr(cls, "setpoints", setpoints)
def getpoints(self):
points = []
for position in self.position:
points.append((position.getx(),position.gety()))
return points
setattr(cls, "getpoints", getpoints)
cls = PLCOpenClasses.get("connectionPointIn", None)
if cls:
def setrelPositionXY(self, x, y):
self.relPosition = PLCOpenClasses["position"]()
self.relPosition.setx(x)
self.relPosition.sety(y)
setattr(cls, "setrelPositionXY", setrelPositionXY)
def getrelPositionXY(self):
if self.relPosition:
return self.relPosition.getx(), self.relPosition.gety()
else:
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"]())
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
setattr(cls, "removeconnection", removeconnection)
def removeconnections(self):
if self.content:
self.content = None
setattr(cls, "removeconnections", removeconnections)
def getconnections(self):
if self.content:
return self.content["value"]
setattr(cls, "getconnections", getconnections)
def setconnectionId(self, idx, id):
if self.content:
self.content["value"][idx].setrefLocalId(id)
setattr(cls, "setconnectionId", setconnectionId)
def getconnectionId(self, idx):
if self.content:
return self.content["value"][idx].getrefLocalId()
return None
setattr(cls, "getconnectionId", getconnectionId)
def setconnectionPoints(self, idx, points):
if self.content:
self.content["value"][idx].setpoints(points)
setattr(cls, "setconnectionPoints", setconnectionPoints)
def getconnectionPoints(self, idx):
if self.content:
return self.content["value"][idx].getpoints()
return None
setattr(cls, "getconnectionPoints", getconnectionPoints)
def setconnectionParameter(self, idx, parameter):
if self.content:
self.content["value"][idx].setformalParameter(parameter)
setattr(cls, "setconnectionParameter", setconnectionParameter)
def getconnectionParameter(self, idx):
if self.content:
return self.content["value"][idx].getformalParameter()
return None
setattr(cls, "getconnectionParameter", getconnectionParameter)
cls = PLCOpenClasses.get("connectionPointOut", None)
if cls:
def setrelPositionXY(self, x, y):
self.relPosition = PLCOpenClasses["position"]()
self.relPosition.setx(x)
self.relPosition.sety(y)
setattr(cls, "setrelPositionXY", setrelPositionXY)
def getrelPositionXY(self):
if self.relPosition:
return self.relPosition.getx(), self.relPosition.gety()
return self.relPosition
setattr(cls, "getrelPositionXY", getrelPositionXY)
cls = PLCOpenClasses.get("value", None)
if cls:
def setvalue(self, value):
if value.startswith("[") and value.endswith("]"):
arrayValue = PLCOpenClasses["value_arrayValue"]()
self.content = {"name" : "arrayValue", "value" : arrayValue}
elif value.startswith("(") and value.endswith(")"):
structValue = PLCOpenClasses["value_structValue"]()
self.content = {"name" : "structValue", "value" : structValue}
else:
simpleValue = PLCOpenClasses["value_simpleValue"]()
self.content = {"name" : "simpleValue", "value": simpleValue}
self.content["value"].setvalue(value)
setattr(cls, "setvalue", setvalue)
def getvalue(self):
return self.content["value"].getvalue()
setattr(cls, "getvalue", getvalue)
def extractValues(values):
items = values.split(",")
i = 1
while i < len(items):
opened = items[i - 1].count("(") + items[i - 1].count("[")
closed = items[i - 1].count(")") + items[i - 1].count("]")
if opened > closed:
items[i - 1] = ','.join([items[i - 1], items.pop(i)])
elif opened == closed:
i += 1
else:
raise ValueError, "\"%s\" is an invalid value!"%value
return items
cls = PLCOpenClasses.get("value_arrayValue", None)
if cls:
arrayValue_model = re.compile("([0-9]*)\((.*)\)$")
def setvalue(self, value):
self.value = []
for item in extractValues(value[1:-1]):
item = item.strip()
element = PLCOpenClasses["arrayValue_value"]()
result = arrayValue_model.match(item)
if result is not None:
groups = result.groups()
element.setrepetitionValue(int(groups[0]))
element.setvalue(groups[1].strip())
else:
element.setvalue(item)
self.value.append(element)
setattr(cls, "setvalue", setvalue)
def getvalue(self):
values = []
for element in self.value:
repetition = element.getrepetitionValue()
if repetition is not None and repetition > 1:
values.append("%d(%s)"%(repetition, element.getvalue()))
else:
values.append(element.getvalue())
return "[%s]"%", ".join(values)
setattr(cls, "getvalue", getvalue)
cls = PLCOpenClasses.get("value_structValue", None)
if cls:
structValue_model = re.compile("(.*):=(.*)")
def setvalue(self, value):
self.value = []
for item in extractValues(value[1:-1]):
result = arrayValue_model.match(item)
if result is not None:
groups = result.groups()
element = PLCOpenClasses["structValue_value"]()
element.setmember(groups[0].strip())
element.setvalue(groups[1].strip())
self.value.append(element)
setattr(cls, "setvalue", setvalue)
def getvalue(self):
values = []
for element in self.value:
values.append("%s := %s"%(element.getmember(), element.getvalue()))
return "(%s)"%", ".join(values)
setattr(cls, "getvalue", getvalue)