Adding support for updating or removing located variables by their address or leading address numbers
authorlaurent
Tue, 01 Dec 2009 10:55:28 +0100
changeset 461 649a8465148d
parent 460 2ddf7bbd1f74
child 462 9abbc90c0263
child 464 765b741fc38f
Adding support for updating or removing located variables by their address or leading address numbers
plcopen/plcopen.py
--- a/plcopen/plcopen.py	Tue Dec 01 10:53:24 2009 +0100
+++ b/plcopen/plcopen.py	Tue Dec 01 10:55:28 2009 +0100
@@ -46,6 +46,15 @@
     "P" : False, "P0" : False, "P1" : False, "SD" : True, "DS" : True, "SL" : True}
 
 
+FILTER_ADDRESS_MODEL = "(%%[IQM](?:[XBWDL])?)(%s)((?:\.[0-9]+)*)" 
+
+def update_address(address, address_model, new_leading):
+    result = address_model.match(address)
+    if result is None:
+        return address
+    groups = result.groups()
+    return groups[0] + new_leading + groups[2]
+
 def _init_and_compare(function, v1, v2):
     if v1 is None:
         return v2
@@ -107,6 +116,17 @@
                 index = self.text.find(old_name, index + len(new_name))
     setattr(cls, "updateElementName", updateElementName)
     
+    def updateElementAddress(self, address_model, new_leading):
+        startpos = 0
+        result = address_model.search(self.text, startpos)
+        while result is not None:
+            groups = result.groups()
+            new_address = groups[0] + new_leading + groups[2]
+            self.text = self.text[:result.start()] + new_address + self.text[result.end():]
+            startpos = result.start() + len(new_address)
+            result = address_model.search(self.text, startpos)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+    
 cls = PLCOpenClasses.get("project", None)
 if cls:
     cls.singleLineAttributes = False
@@ -323,6 +343,29 @@
             configuration.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, old_leading, new_leading):
+        address_model = re.compile(FILTER_ADDRESS_MODEL % old_leading)
+        for pou in self.types.getpouElements():
+            pou.updateElementAddress(address_model, new_leading)
+        for configuration in self.instances.configurations.getconfiguration():
+            configuration.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def removeVariableByAddress(self, address):
+        for pou in self.types.getpouElements():
+            pou.removeVariableByAddress(address)
+        for configuration in self.instances.configurations.getconfiguration():
+            configuration.removeVariableByAddress(address)
+    setattr(cls, "removeVariableByAddress", removeVariableByAddress)
+
+    def removeVariableByFilter(self, leading):
+        address_model = re.compile(FILTER_ADDRESS_MODEL % leading)
+        for pou in self.types.getpouElements():
+            pou.removeVariableByFilter(address_model)
+        for configuration in self.instances.configurations.getconfiguration():
+            configuration.removeVariableByFilter(address_model)
+    setattr(cls, "removeVariableByFilter", removeVariableByFilter)
+
     def RefreshDataTypeHierarchy(self):
         self.EnumeratedDataTypeValues = {}
         self.CustomDataTypeRange = {}
@@ -687,20 +730,93 @@
 cls = PLCOpenClasses.get("configurations_configuration", None)
 if cls:
     def updateElementName(self, old_name, new_name):
+        for varlist in self.getglobalVars():
+            for var in varlist.getvariable():
+                var_address = var.getaddress()
+                if var_address is not None:
+                    if var_address == oldname:
+                        var.setaddress(new_name)
+                    if var.getname() == old_name:
+                        var.setname(new_name)
         for resource in self.getresource():
             resource.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        for varlist in self.getglobalVars():
+            for var in varlist.getvariable():
+                var_address = var.getaddress()
+                if var_address is not None:
+                    var.setaddress(update_address(var_address, address_model, new_leading))
+        for resource in self.getresource():
+            resource.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def removeVariableByAddress(self, address):
+        for varlist in self.getglobalVars():
+            variables = varlist.getvariable()
+            for i in xrange(len(variables)-1, -1, -1):
+                if variables[i].getaddress() == address:
+                    variables.pop(i)
+    setattr(cls, "removeVariableByAddress", removeVariableByAddress)
+
+    def removeVariableByFilter(self, address_model):
+        for varlist in self.getglobalVars():
+            variables = varlist.getvariable()
+            for i in xrange(len(variables)-1, -1, -1):
+                var_address = variables[i].getaddress()
+                if var_address is not None:
+                    result = address_model.match(var_address)
+                    if result is not None:
+                        variables.pop(i)
+    setattr(cls, "removeVariableByFilter", removeVariableByFilter)
 
 cls = PLCOpenClasses.get("configuration_resource", None)
 if cls:
     def updateElementName(self, old_name, new_name):
+        for varlist in self.getglobalVars():
+            for var in varlist.getvariable():
+                var_address = var.getaddress()
+                if var_address is not None:
+                    if var_address == oldname:
+                        var.setaddress(new_name)
+                    if var.getname() == old_name:
+                        var.setname(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)
 
+    def updateElementAddress(self, address_model, new_leading):
+        for varlist in self.getglobalVars():
+            for var in varlist.getvariable():
+                var_address = var.getaddress()
+                if var_address is not None:
+                    var.setaddress(update_address(var_address, address_model, new_leading))
+        for task in self.gettask():
+            task.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def removeVariableByAddress(self, address):
+        for varlist in self.getglobalVars():
+            variables = varlist.getvariable()
+            for i in xrange(len(variables)-1, -1, -1):
+                if variables[i].getaddress() == address:
+                    variables.pop(i)
+    setattr(cls, "removeVariableByAddress", removeVariableByAddress)
+
+    def removeVariableByFilter(self, address_model):
+        for varlist in self.getglobalVars():
+            variables = varlist.getvariable()
+            for i in xrange(len(variables)-1, -1, -1):
+                var_address = variables[i].getaddress()
+                if var_address is not None:
+                    result = address_model.match(var_address)
+                    if result is not None:
+                        variables.pop(i)
+    setattr(cls, "removeVariableByFilter", removeVariableByFilter)
+
 cls = PLCOpenClasses.get("resource_task", None)
 if cls:
     def compatibility(self, tree):
@@ -730,10 +846,19 @@
     def updateElementName(self, old_name, new_name):
         if self.single == old_name:
             self.single = new_name
+        if self.interval == old_name:
+            self.interval = new_name
         for instance in self.getpouInstance():
             instance.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        if self.single is not None:
+            self.single = update_address(self.single, address_model, new_leading)
+        if self.interval is not None:
+            self.interval = update_address(self.interval, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
 cls = PLCOpenClasses.get("pouInstance", None)
 if cls:
     def compatibility(self, tree):
@@ -1092,6 +1217,12 @@
         if self.interface:
             for content in self.interface.getcontent():
                 for var in content["value"].getvariable():
+                    var_address = var.getaddress()
+                    if var_address is not None:
+                        if var_address == oldname:
+                            var.setaddress(new_name)
+                        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:
@@ -1103,6 +1234,41 @@
             transition.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        if self.interface:
+            for content in self.interface.getcontent():
+                for var in content["value"].getvariable():
+                    var_address = var.getaddress()
+                    if var_address is not None:
+                        var.setaddress(update_address(var_address, address_model, new_leading))
+        self.body[0].updateElementAddress(address_model, new_leading)
+        for action in self.getactionList():
+            action.updateElementAddress(address_model, new_leading)
+        for transition in self.gettransitionList():
+            transition.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    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)
+    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()
+                    if var_address is not None:
+                        result = address_model.match(var_address)
+                        if result is not None:
+                            variables.pop(i)
+    setattr(cls, "removeVariableByFilter", removeVariableByFilter)
+
 def setbodyType(self, type):
     if type == "IL":
         self.body.setcontent({"name" : "IL", "value" : PLCOpenClasses["formattedText"]()})
@@ -1173,6 +1339,10 @@
         self.body.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        self.body.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
     def hasblock(self, name):
         if self.getbodyType() in ["FBD", "LD", "SFC"]:
             for instance in self.getinstances():
@@ -1201,6 +1371,10 @@
         self.body.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        self.body.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
     def hasblock(self, name):
         if self.getbodyType() in ["FBD", "LD", "SFC"]:
             for instance in self.getinstances():
@@ -1368,6 +1542,14 @@
                 element["value"].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)
+        else:
+            for element in self.content["value"].getcontent():
+                element["value"].updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
 def getx(self):
     return self.position.getx()
 
@@ -1477,6 +1659,9 @@
 def _updateElementName(self, old_name, new_name):
     pass
 
+def _updateElementAddress(self, address_model, new_leading):
+    pass
+
 _connectionsFunctions = {
     "bbox": {"none": _getBoundingBox,
              "single": _getBoundingBoxSingle,
@@ -1501,6 +1686,7 @@
         setattr(cls, "setx", setx)
         setattr(cls, "sety", sety)
         setattr(cls, "updateElementName", _updateElementName)
+        setattr(cls, "updateElementAddress", _updateElementAddress)
         setattr(cls, "getBoundingBox", _connectionsFunctions["bbox"][connectionPointInType])
         setattr(cls, "translate", _connectionsFunctions["translate"][connectionPointInType])
         setattr(cls, "filterConnections", _connectionsFunctions["filter"][connectionPointInType])
@@ -1658,6 +1844,10 @@
         self.content.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        self.content.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
 cls = _initElementClass("block", "fbdObjects_block")
 if cls:
     def getBoundingBox(self):
@@ -1720,6 +1910,10 @@
             self.variable = new_name
     setattr(cls, "updateElementName", updateElementName)
     
+    def updateElementAddress(self, address_model, new_leading):
+        self.variable = update_address(self.variable, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+    
 cls = _initElementClass("coil", "ldObjects_coil", "single")
 if cls:
     setattr(cls, "getinfos", _getldelementinfosFunction("coil"))
@@ -1729,6 +1923,10 @@
             self.variable = new_name
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        self.variable = update_address(self.variable, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
 cls = _initElementClass("step", "sfcObjects_step", "single")
 if cls:
     def getinfos(self):
@@ -1825,6 +2023,15 @@
                 content["value"].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)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
     def getconnections(self):
         if self.condition:
             content = self.condition.getcontent()
@@ -1901,6 +2108,13 @@
             self.inline.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        if self.reference:
+            self.reference.setname(update_address(self.reference.getname(), address_model, new_leading))
+        if self.inline:
+            self.inline.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
 cls = _initElementClass("actionBlock", "commonObjects_actionBlock", "single")
 if cls:
     def compatibility(self, tree):
@@ -1963,6 +2177,11 @@
             action.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        for action in self.action:
+            action.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
 cls = _initElementClass("inVariable", "fbdObjects_inVariable")
 if cls:
     setattr(cls, "getinfos", _getvariableinfosFunction("input", False, True))
@@ -1972,6 +2191,10 @@
             self.expression = new_name
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        self.expression = update_address(self.expression, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
 cls = _initElementClass("outVariable", "fbdObjects_outVariable", "single")
 if cls:
     setattr(cls, "getinfos", _getvariableinfosFunction("output", True, False))
@@ -1981,6 +2204,10 @@
             self.expression = new_name
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        self.expression = update_address(self.expression, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
 cls = _initElementClass("inOutVariable", "fbdObjects_inOutVariable", "single")
 if cls:
     setattr(cls, "getinfos", _getvariableinfosFunction("inout", True, True))
@@ -1990,6 +2217,10 @@
             self.expression = new_name
     setattr(cls, "updateElementName", updateElementName)
 
+    def updateElementAddress(self, address_model, new_leading):
+        self.expression = update_address(self.expression, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
 cls = _initElementClass("continuation", "commonObjects_continuation")
 if cls:
     setattr(cls, "getinfos", _getconnectorinfosFunction("continuation"))