diff -r c8e008b8cefe -r 72a826dfcfbb plcopen/plcopen.py --- a/plcopen/plcopen.py Wed Mar 13 12:34:55 2013 +0900 +++ b/plcopen/plcopen.py Wed Jul 31 10:45:07 2013 +0900 @@ -155,6 +155,17 @@ self.text = text setattr(cls, "updateElementAddress", updateElementAddress) + def hasblock(self, block_type): + text = self.text.upper() + index = text.find(block_type.upper()) + while index != -1: + if (not (index > 0 and (text[index - 1].isalnum() or text[index - 1] == "_")) and + not (index < len(text) - len(block_type) and text[index + len(block_type)] != "(")): + return True + index = text.find(block_type.upper(), index + len(block_type)) + return False + setattr(cls, "hasblock", hasblock) + def Search(self, criteria, parent_infos): return [(tuple(parent_infos),) + result for result in TestTextElement(self.gettext(), criteria)] setattr(cls, "Search", Search) @@ -489,17 +500,19 @@ self.CustomBlockTypes.append(block_infos) setattr(cls, "AddCustomBlockType", AddCustomBlockType) + def AddElementUsingTreeInstance(self, name, type_infos): + typename = type_infos.getname() + if not self.ElementUsingTree.has_key(typename): + self.ElementUsingTree[typename] = [name] + elif name not in self.ElementUsingTree[typename]: + self.ElementUsingTree[typename].append(name) + setattr(cls, "AddElementUsingTreeInstance", AddElementUsingTreeInstance) + def RefreshElementUsingTree(self): # Reset the tree of user-defined element cross-use self.ElementUsingTree = {} pous = self.getpous() datatypes = self.getdataTypes() - # Reference all the user-defined elementu names and initialize the tree of - # user-defined elemnt cross-use - elementnames = [datatype.getname() for datatype in datatypes] + \ - [pou.getname() for pou in pous] - for name in elementnames: - self.ElementUsingTree[name] = [] # Analyze each datatype for datatype in datatypes: name = datatype.getname() @@ -511,16 +524,12 @@ elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned", "array"]: base_type = basetype_content["value"].baseType.getcontent() if base_type["name"] == "derived": - typename = base_type["value"].getname() - if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]: - self.ElementUsingTree[typename].append(name) + self.AddElementUsingTreeInstance(name, base_type["value"]) elif basetype_content["name"] == "struct": for element in basetype_content["value"].getvariable(): type_content = element.type.getcontent() if type_content["name"] == "derived": - typename = type_content["value"].getname() - if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]: - self.ElementUsingTree[typename].append(name) + self.AddElementUsingTreeInstance(name, type_content["value"]) # Analyze each pou for pou in pous: name = pou.getname() @@ -530,9 +539,11 @@ for var in varlist.getvariable(): vartype_content = var.gettype().getcontent() if vartype_content["name"] == "derived": - typename = vartype_content["value"].getname() - if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]: - self.ElementUsingTree[typename].append(name) + self.AddElementUsingTreeInstance(name, vartype_content["value"]) + for typename in self.ElementUsingTree.iterkeys(): + if typename != name and pou.hasblock(block_type=typename) and name not in self.ElementUsingTree[typename]: + self.ElementUsingTree[typename].append(name) + setattr(cls, "RefreshElementUsingTree", RefreshElementUsingTree) def GetParentType(self, type): @@ -840,6 +851,35 @@ cls = PLCOpenClasses.get("configurations_configuration", None) if cls: + + def addglobalVar(self, type, name, location="", description=""): + globalvars = self.getglobalVars() + if len(globalvars) == 0: + globalvars.append(PLCOpenClasses["varList"]()) + var = PLCOpenClasses["varListPlain_variable"]() + 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}) + else: + derived_type = PLCOpenClasses["derivedTypes_derived"]() + derived_type.setname(type) + var_type.setcontent({"name" : "derived", "value" : derived_type}) + var.settype(var_type) + if location != "": + var.setaddress(location) + if description != "": + ft = PLCOpenClasses["formattedText"]() + ft.settext(description) + var.setdocumentation(ft) + globalvars[-1].appendvariable(var) + setattr(cls, "addglobalVar", addglobalVar) + def updateElementName(self, old_name, new_name): _updateConfigurationResourceElementName(self, old_name, new_name) for resource in self.getresource(): @@ -1382,21 +1422,25 @@ break setattr(cls, "removepouVar", removepouVar) - def hasblock(self, name): + 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 instance.getinstanceName() == name: + if (isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and + (name and instance.getinstanceName() == name or + block_type and instance.gettypeName() == block_type)): return True if self.transitions: for transition in self.transitions.gettransition(): - result = transition.hasblock(name) + result = transition.hasblock(name, block_type) if result: return result if self.actions: for action in self.actions.getaction(): - result = action.hasblock(name) + result = action.hasblock(name, block_type) if result: return result + elif block_type is not None and len(self.body) > 0: + return self.body[0].hasblock(block_type) return False setattr(cls, "hasblock", hasblock) @@ -1626,6 +1670,24 @@ def gettext(self): return self.body.gettext() +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 + (name and instance.getinstanceName() == name or + block_type and instance.gettypeName() == block_type)): + return True + elif block_type is not None: + return self.body.hasblock(block_type) + return False + +def updateElementName(self, old_name, new_name): + self.body.updateElementName(old_name, new_name) + +def updateElementAddress(self, address_model, new_leading): + self.body.updateElementAddress(address_model, new_leading) + + cls = PLCOpenClasses.get("transitions_transition", None) if cls: setattr(cls, "setbodyType", setbodyType) @@ -1641,23 +1703,10 @@ 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, "hasblock", hasblock) 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(): - if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name: - return True - return False - setattr(cls, "hasblock", hasblock) - + def Search(self, criteria, parent_infos): search_result = [] parent_infos = parent_infos[:-1] + ["T::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())] @@ -1682,23 +1731,10 @@ 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, "hasblock", hasblock) 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(): - if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name: - return True - return False - setattr(cls, "hasblock", hasblock) - + def Search(self, criteria, parent_infos): search_result = [] parent_infos = parent_infos[:-1] + ["A::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())] @@ -1711,6 +1747,24 @@ cls = PLCOpenClasses.get("body", None) 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) @@ -1785,7 +1839,9 @@ def appendcontentInstance(self, name, instance): if self.content["name"] in ["LD","FBD","SFC"]: - self.content["value"].appendcontent({"name" : name, "value" : instance}) + element = {"name" : name, "value" : instance} + self.content["value"].appendcontent(element) + self.instances_dict[instance.getlocalId()] = element else: raise TypeError, _("%s body don't have instances!")%self.content["name"] setattr(cls, "appendcontentInstance", appendcontentInstance) @@ -1802,9 +1858,9 @@ 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"] + instance = self.instances_dict.get(id, None) + if instance is not None: + return instance["value"] return None else: raise TypeError, _("%s body don't have instances!")%self.content["name"] @@ -1812,9 +1868,9 @@ 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"] + ids = self.instances_dict.viewkeys() - exclude + if len(ids) > 0: + return self.instances_dict[ids.pop()]["value"] return None else: raise TypeError, _("%s body don't have instances!")%self.content["name"] @@ -1831,15 +1887,10 @@ 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: + element = self.instances_dict.pop(id, None) + if element is not None: + self.content["value"].getcontent().remove(element) + else: raise ValueError, _("Instance with id %d doesn't exist!")%id else: raise TypeError, "%s body don't have instances!"%self.content["name"] @@ -1859,6 +1910,13 @@ 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) + 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)