etisserant@14: """ Edouard@725: Config Tree Node base class. Edouard@725: Edouard@725: - A Beremiz project is organized in a tree each node derivate from ConfigTreeNode Edouard@725: - Project tree organization match filesystem organization of project directory. Edouard@725: - Each node of the tree have its own xml configuration, whose grammar is defined for each node type, as XSD Edouard@725: - ... TODO : document etisserant@14: """ etisserant@14: Edouard@725: import os,traceback,types etisserant@14: import shutil etisserant@14: from xml.dom import minidom greg@126: etisserant@14: from xmlclass import GenerateClassesFromXSDstring Edouard@742: from util.misc import GetClassImporter Edouard@725: Edouard@725: from PLCControler import PLCControler, LOCATION_CONFNODE Laurent@814: from editors.ConfTreeNodeEditor import ConfTreeNodeEditor greg@274: etisserant@14: _BaseParamsClass = GenerateClassesFromXSDstring(""" etisserant@14: etisserant@14: etisserant@14: lbessard@86: lbessard@17: lbessard@86: etisserant@14: etisserant@14: lbessard@86: """)["BaseParams"] etisserant@14: etisserant@14: NameTypeSeparator = '@' etisserant@14: Edouard@717: class ConfigTreeNode: etisserant@14: """ Edouard@717: This class is the one that define confnodes. etisserant@14: """ etisserant@14: etisserant@14: XSD = None Edouard@718: CTNChildrenTypes = [] Edouard@718: CTNMaxCount = None Edouard@717: ConfNodeMethods = [] greg@274: LibraryControler = None laurent@743: EditorType = ConfTreeNodeEditor laurent@738: IconPath = None laurent@738: etisserant@14: def _AddParamsMembers(self): Edouard@718: self.CTNParams = None etisserant@29: if self.XSD: laurent@411: self.Classes = GenerateClassesFromXSDstring(self.XSD) laurent@411: Classes = [(name, XSDclass) for name, XSDclass in self.Classes.items() if XSDclass.IsBaseClass] etisserant@29: if len(Classes) == 1: etisserant@29: name, XSDclass = Classes[0] etisserant@29: obj = XSDclass() Edouard@718: self.CTNParams = (name, obj) etisserant@29: setattr(self, name, obj) lbessard@17: lbessard@17: def __init__(self): etisserant@14: # Create BaseParam etisserant@14: self.BaseParams = _BaseParamsClass() lbessard@17: self.MandatoryParams = ("BaseParams", self.BaseParams) etisserant@14: self._AddParamsMembers() Edouard@718: self.Children = {} laurent@656: self._View = None Edouard@717: # copy ConfNodeMethods so that it can be later customized Edouard@717: self.ConfNodeMethods = [dic.copy() for dic in self.ConfNodeMethods] lbessard@325: Edouard@718: def ConfNodeBaseXmlFilePath(self, CTNName=None): Edouard@718: return os.path.join(self.CTNPath(CTNName), "baseconfnode.xml") Edouard@718: Edouard@718: def ConfNodeXmlFilePath(self, CTNName=None): Edouard@718: return os.path.join(self.CTNPath(CTNName), "confnode.xml") Edouard@717: Edouard@717: def ConfNodePath(self): Edouard@718: return os.path.join(self.CTNParent.ConfNodePath(), self.CTNType) Edouard@718: Laurent@1061: def CTNPath(self,CTNName=None,project_path=None): Edouard@718: if not CTNName: Edouard@718: CTNName = self.CTNName() Laurent@1061: if not project_path: Laurent@1061: project_path = self.CTNParent.CTNPath() Laurent@1061: return os.path.join(project_path, Edouard@718: CTNName + NameTypeSeparator + self.CTNType) Edouard@718: Edouard@718: def CTNName(self): laurent@675: return self.BaseParams.getName() laurent@675: Edouard@718: def CTNEnabled(self): laurent@675: return self.BaseParams.getEnabled() laurent@675: Edouard@718: def CTNFullName(self): Edouard@718: parent = self.CTNParent.CTNFullName() laurent@656: if parent != "": Edouard@718: return parent + "." + self.CTNName() laurent@656: return self.BaseParams.getName() laurent@656: laurent@781: def GetIconName(self): Edouard@734: return None laurent@652: Edouard@718: def CTNTestModified(self): etisserant@118: return self.ChangesToSave etisserant@118: etisserant@118: def ProjectTestModified(self): etisserant@118: """ etisserant@118: recursively check modified status etisserant@118: """ Edouard@718: if self.CTNTestModified(): etisserant@118: return True etisserant@118: Edouard@718: for CTNChild in self.IterChildren(): Edouard@718: if CTNChild.ProjectTestModified(): etisserant@118: return True etisserant@118: etisserant@14: return False laurent@699: laurent@699: def RemoteExec(self, script, **kwargs): Edouard@718: return self.CTNParent.RemoteExec(script, **kwargs) Edouard@718: Laurent@1061: def OnCTNSave(self, from_project_path=None): etisserant@20: #Default, do nothing and return success etisserant@14: return True etisserant@14: lbessard@19: def GetParamsAttributes(self, path = None): lbessard@19: if path: lbessard@19: parts = path.split(".", 1) lbessard@19: if self.MandatoryParams and parts[0] == self.MandatoryParams[0]: lbessard@19: return self.MandatoryParams[1].getElementInfos(parts[0], parts[1]) Edouard@718: elif self.CTNParams and parts[0] == self.CTNParams[0]: Edouard@718: return self.CTNParams[1].getElementInfos(parts[0], parts[1]) lbessard@17: else: lbessard@19: params = [] Edouard@718: if self.CTNParams: Edouard@718: params.append(self.CTNParams[1].getElementInfos(self.CTNParams[0])) lbessard@19: return params lbessard@19: etisserant@203: def SetParamsAttribute(self, path, value): etisserant@118: self.ChangesToSave = True etisserant@29: # Filter IEC_Channel and Name, that have specific behavior etisserant@29: if path == "BaseParams.IEC_Channel": laurent@443: old_leading = ".".join(map(str, self.GetCurrentLocation())) laurent@443: new_value = self.FindNewIEC_Channel(value) Laurent@842: if new_value != value: Laurent@842: new_leading = ".".join(map(str, self.CTNParent.GetCurrentLocation() + (new_value,))) Laurent@842: self.GetCTRoot().UpdateProjectVariableLocation(old_leading, new_leading) laurent@443: return new_value, True etisserant@29: elif path == "BaseParams.Name": etisserant@203: res = self.FindNewName(value) Edouard@718: self.CTNRequestSave() etisserant@118: return res, True etisserant@29: lbessard@19: parts = path.split(".", 1) lbessard@19: if self.MandatoryParams and parts[0] == self.MandatoryParams[0]: lbessard@19: self.MandatoryParams[1].setElementValue(parts[1], value) Edouard@718: elif self.CTNParams and parts[0] == self.CTNParams[0]: Edouard@718: self.CTNParams[1].setElementValue(parts[1], value) etisserant@29: return value, False lbessard@17: Edouard@718: def CTNMakeDir(self): Edouard@718: os.mkdir(self.CTNPath()) Edouard@718: Laurent@1061: def CTNRequestSave(self, from_project_path=None): Edouard@718: if self.GetCTRoot().CheckProjectPathPerm(False): Edouard@717: # If confnode do not have corresponding directory Edouard@718: ctnpath = self.CTNPath() Edouard@718: if not os.path.isdir(ctnpath): greg@427: # Create it Edouard@718: os.mkdir(ctnpath) greg@427: Edouard@717: # generate XML for base XML parameters controller of the confnode greg@427: if self.MandatoryParams: Edouard@717: BaseXMLFile = open(self.ConfNodeBaseXmlFilePath(),'w') greg@427: BaseXMLFile.write("\n") laurent@430: BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0).encode("utf-8")) greg@427: BaseXMLFile.close() greg@427: Edouard@717: # generate XML for XML parameters controller of the confnode Edouard@718: if self.CTNParams: Edouard@717: XMLFile = open(self.ConfNodeXmlFilePath(),'w') greg@427: XMLFile.write("\n") Edouard@718: XMLFile.write(self.CTNParams[1].generateXMLText(self.CTNParams[0], 0).encode("utf-8")) greg@427: XMLFile.close() greg@427: Edouard@718: # Call the confnode specific OnCTNSave method Laurent@1061: result = self.OnCTNSave(from_project_path) greg@427: if not result: Edouard@718: return _("Error while saving \"%s\"\n")%self.CTNPath() greg@427: Edouard@717: # mark confnode as saved greg@427: self.ChangesToSave = False Edouard@718: # go through all children and do the same Edouard@718: for CTNChild in self.IterChildren(): Laurent@1063: CTNChildPath = None Laurent@1063: if from_project_path is not None: Laurent@1063: CTNChildPath = CTNChild.CTNPath(project_path=from_project_path) Laurent@1063: result = CTNChild.CTNRequestSave(CTNChildPath) greg@427: if result: greg@427: return result lbessard@17: return None etisserant@14: Edouard@718: def CTNImport(self, src_CTNPath): Edouard@718: shutil.copytree(src_CTNPath, self.CTNPath) etisserant@14: return True etisserant@14: Laurent@883: def CTNGlobalInstances(self): Laurent@883: """ Laurent@883: @return: [(instance_name, instance_type),...] Laurent@883: """ Laurent@883: return [] Laurent@883: Laurent@883: def _GlobalInstances(self): Laurent@883: instances = self.CTNGlobalInstances() Laurent@883: for CTNChild in self.IECSortedChildren(): Laurent@883: instances.extend(CTNChild._GlobalInstances()) Laurent@883: return instances Laurent@883: Edouard@718: def CTNGenerate_C(self, buildpath, locations): etisserant@14: """ etisserant@14: Generate C code etisserant@14: @param locations: List of complete variables locations \ etisserant@22: [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) etisserant@22: "NAME" : name of the variable (generally "__IW0_1_2" style) etisserant@22: "DIR" : direction "Q","I" or "M" etisserant@22: "SIZE" : size "X", "B", "W", "D", "L" etisserant@22: "LOC" : tuple of interger for IEC location (0,1,2,...) etisserant@22: }, ...] etisserant@18: @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND etisserant@18: """ Edouard@718: self.GetCTRoot().logger.write_warning(".".join(map(lambda x:str(x), self.GetCurrentLocation())) + " -> Nothing to do\n") etisserant@51: return [],"",False etisserant@14: etisserant@203: def _Generate_C(self, buildpath, locations): Edouard@717: # Generate confnodes [(Cfiles, CFLAGS)], LDFLAGS, DoCalls, extra_files etisserant@203: # extra_files = [(fname,fobject), ...] Edouard@718: gen_result = self.CTNGenerate_C(buildpath, locations) Edouard@718: CTNCFilesAndCFLAGS, CTNLDFLAGS, DoCalls = gen_result[:3] etisserant@203: extra_files = gen_result[3:] laurent@361: # if some files have been generated put them in the list with their location Edouard@718: if CTNCFilesAndCFLAGS: Edouard@718: LocationCFilesAndCFLAGS = [(self.GetCurrentLocation(), CTNCFilesAndCFLAGS, DoCalls)] etisserant@47: else: etisserant@47: LocationCFilesAndCFLAGS = [] etisserant@47: Edouard@717: # confnode asks for some LDFLAGS Edouard@718: if CTNLDFLAGS: etisserant@47: # LDFLAGS can be either string Edouard@718: if type(CTNLDFLAGS)==type(str()): Edouard@718: LDFLAGS=[CTNLDFLAGS] etisserant@47: #or list of strings Edouard@718: elif type(CTNLDFLAGS)==type(list()): Edouard@718: LDFLAGS=CTNLDFLAGS[:] etisserant@47: else: etisserant@47: LDFLAGS=[] etisserant@47: Edouard@718: # recurse through all children, and stack their results Edouard@718: for CTNChild in self.IECSortedChildren(): Edouard@718: new_location = CTNChild.GetCurrentLocation() etisserant@24: # How deep are we in the tree ? etisserant@24: depth=len(new_location) etisserant@203: _LocationCFilesAndCFLAGS, _LDFLAGS, _extra_files = \ Edouard@718: CTNChild._Generate_C( etisserant@14: #keep the same path etisserant@14: buildpath, etisserant@14: # filter locations that start with current IEC location etisserant@203: [loc for loc in locations if loc["LOC"][0:depth] == new_location ]) etisserant@14: # stack the result etisserant@47: LocationCFilesAndCFLAGS += _LocationCFilesAndCFLAGS etisserant@47: LDFLAGS += _LDFLAGS etisserant@203: extra_files += _extra_files etisserant@203: etisserant@203: return LocationCFilesAndCFLAGS, LDFLAGS, extra_files etisserant@14: Edouard@718: def IterChildren(self): Edouard@718: for CTNType, Children in self.Children.items(): Edouard@718: for CTNInstance in Children: Edouard@718: yield CTNInstance Edouard@718: Edouard@718: def IECSortedChildren(self): Edouard@718: # reorder children by IEC_channels Edouard@718: ordered = [(chld.BaseParams.getIEC_Channel(),chld) for chld in self.IterChildren()] etisserant@47: if ordered: etisserant@47: ordered.sort() etisserant@47: return zip(*ordered)[1] etisserant@47: else: etisserant@47: return [] etisserant@47: etisserant@47: def _GetChildBySomething(self, something, toks): Edouard@718: for CTNInstance in self.IterChildren(): etisserant@14: # if match component of the name Edouard@718: if getattr(CTNInstance.BaseParams, something) == toks[0]: etisserant@14: # if Name have other components etisserant@47: if len(toks) >= 2: etisserant@14: # Recurse in order to find the latest object Edouard@718: return CTNInstance._GetChildBySomething( something, toks[1:]) etisserant@14: # No sub name -> found Edouard@718: return CTNInstance etisserant@14: # Not found etisserant@14: return None etisserant@14: etisserant@14: def GetChildByName(self, Name): etisserant@47: if Name: etisserant@47: toks = Name.split('.') etisserant@47: return self._GetChildBySomething("Name", toks) etisserant@47: else: etisserant@47: return self etisserant@14: etisserant@14: def GetChildByIECLocation(self, Location): etisserant@47: if Location: etisserant@47: return self._GetChildBySomething("IEC_Channel", Location) etisserant@47: else: etisserant@47: return self etisserant@14: etisserant@23: def GetCurrentLocation(self): etisserant@24: """ Edouard@717: @return: Tupple containing confnode IEC location of current confnode : %I0.0.4.5 => (0,0,4,5) etisserant@24: """ Edouard@718: return self.CTNParent.GetCurrentLocation() + (self.BaseParams.getIEC_Channel(),) etisserant@23: etisserant@47: def GetCurrentName(self): etisserant@47: """ etisserant@47: @return: String "ParentParentName.ParentName.Name" etisserant@47: """ Edouard@718: return self.CTNParent._GetCurrentName() + self.BaseParams.getName() etisserant@47: etisserant@47: def _GetCurrentName(self): etisserant@47: """ etisserant@47: @return: String "ParentParentName.ParentName.Name." etisserant@47: """ Edouard@718: return self.CTNParent._GetCurrentName() + self.BaseParams.getName() + "." Edouard@718: Edouard@718: def GetCTRoot(self): Edouard@718: return self.CTNParent.GetCTRoot() etisserant@23: lbessard@97: def GetFullIEC_Channel(self): lbessard@97: return ".".join([str(i) for i in self.GetCurrentLocation()]) + ".x" lbessard@97: lbessard@97: def GetLocations(self): lbessard@97: location = self.GetCurrentLocation() Edouard@718: return [loc for loc in self.CTNParent.GetLocations() if loc["LOC"][0:len(location)] == location] lbessard@97: laurent@401: def GetVariableLocationTree(self): laurent@401: ''' Edouard@717: This function is meant to be overridden by confnodes. laurent@401: laurent@401: It should returns an list of dictionaries laurent@401: laurent@401: - IEC_type is an IEC type like BOOL/BYTE/SINT/... laurent@401: - location is a string of this variable's location, like "%IX0.0.0" laurent@401: ''' laurent@401: children = [] Edouard@718: for child in self.IECSortedChildren(): laurent@402: children.append(child.GetVariableLocationTree()) laurent@402: return {"name": self.BaseParams.getName(), Edouard@717: "type": LOCATION_CONFNODE, laurent@402: "location": self.GetFullIEC_Channel(), laurent@402: "children": children} laurent@401: etisserant@203: def FindNewName(self, DesiredName): etisserant@29: """ etisserant@29: Changes Name to DesiredName if available, Name-N if not. etisserant@29: @param DesiredName: The desired Name (string) etisserant@29: """ etisserant@29: # Get Current Name etisserant@29: CurrentName = self.BaseParams.getName() etisserant@29: # Do nothing if no change etisserant@29: #if CurrentName == DesiredName: return CurrentName Edouard@718: # Build a list of used Name out of parent's Children etisserant@29: AllNames=[] Edouard@718: for CTNInstance in self.CTNParent.IterChildren(): Edouard@718: if CTNInstance != self: Edouard@718: AllNames.append(CTNInstance.BaseParams.getName()) etisserant@29: etisserant@29: # Find a free name, eventually appending digit etisserant@29: res = DesiredName laurent@833: if DesiredName.endswith("_0"): Laurent@841: BaseDesiredName = DesiredName[:-2] Laurent@841: else: Laurent@841: BaseDesiredName = DesiredName etisserant@29: suffix = 1 etisserant@29: while res in AllNames: Laurent@841: res = "%s_%d"%(BaseDesiredName, suffix) etisserant@29: suffix += 1 etisserant@29: etisserant@29: # Get old path Edouard@718: oldname = self.CTNPath() Edouard@717: # Check previous confnode existance etisserant@29: dontexist = self.BaseParams.getName() == "__unnamed__" etisserant@29: # Set the new name etisserant@29: self.BaseParams.setName(res) Edouard@717: # Rename confnode dir if exist etisserant@29: if not dontexist: Edouard@718: shutil.move(oldname, self.CTNPath()) etisserant@29: # warn user he has two left hands etisserant@29: if DesiredName != res: laurent@801: self.GetCTRoot().logger.write_warning(_("A child named \"%s\" already exist -> \"%s\"\n")%(DesiredName,res)) etisserant@29: return res etisserant@29: laurent@683: def GetAllChannels(self): laurent@683: AllChannels=[] Edouard@718: for CTNInstance in self.CTNParent.IterChildren(): Edouard@718: if CTNInstance != self: Edouard@718: AllChannels.append(CTNInstance.BaseParams.getIEC_Channel()) laurent@683: AllChannels.sort() laurent@683: return AllChannels laurent@683: etisserant@203: def FindNewIEC_Channel(self, DesiredChannel): etisserant@14: """ etisserant@14: Changes IEC Channel number to DesiredChannel if available, nearest available if not. etisserant@14: @param DesiredChannel: The desired IEC channel (int) etisserant@14: """ etisserant@14: # Get Current IEC channel etisserant@14: CurrentChannel = self.BaseParams.getIEC_Channel() etisserant@14: # Do nothing if no change etisserant@29: #if CurrentChannel == DesiredChannel: return CurrentChannel Edouard@718: # Build a list of used Channels out of parent's Children laurent@683: AllChannels = self.GetAllChannels() laurent@683: etisserant@14: # Now, try to guess the nearest available channel etisserant@14: res = DesiredChannel etisserant@14: while res in AllChannels: # While channel not free etisserant@14: if res < CurrentChannel: # Want to go down ? etisserant@14: res -= 1 # Test for n-1 etisserant@33: if res < 0 : Edouard@718: self.GetCTRoot().logger.write_warning(_("Cannot find lower free IEC channel than %d\n")%CurrentChannel) etisserant@33: return CurrentChannel # Can't go bellow 0, do nothing etisserant@14: else : # Want to go up ? etisserant@14: res += 1 # Test for n-1 etisserant@14: # Finally set IEC Channel etisserant@14: self.BaseParams.setIEC_Channel(res) etisserant@14: return res etisserant@14: Laurent@967: def GetContextualMenuItems(self): Laurent@967: return None Laurent@967: laurent@782: def _OpenView(self, name=None, onlyopened=False): laurent@774: if self.EditorType is not None: laurent@782: app_frame = self.GetCTRoot().AppFrame laurent@784: if self._View is None and not onlyopened: laurent@774: laurent@774: self._View = self.EditorType(app_frame.TabsOpened, self, app_frame) laurent@784: laurent@784: if self._View is not None: laurent@786: if name is None: laurent@786: name = self.CTNFullName() laurent@786: app_frame.EditProjectElement(self._View, name) laurent@782: laurent@715: return self._View laurent@715: return None laurent@675: laurent@774: def _CloseView(self, view): laurent@774: app_frame = self.GetCTRoot().AppFrame laurent@774: if app_frame is not None: laurent@774: app_frame.DeletePage(view) laurent@774: laurent@675: def OnCloseEditor(self, view): laurent@675: if self._View == view: laurent@675: self._View = None laurent@656: Edouard@718: def OnCTNClose(self): laurent@656: if self._View is not None: laurent@780: self._CloseView(self._View) laurent@774: self._View = None etisserant@14: return True etisserant@14: Edouard@718: def _doRemoveChild(self, CTNInstance): Edouard@718: # Remove all children of child Edouard@718: for SubCTNInstance in CTNInstance.IterChildren(): Edouard@718: CTNInstance._doRemoveChild(SubCTNInstance) etisserant@14: # Call the OnCloseMethod Edouard@718: CTNInstance.OnCTNClose() Edouard@717: # Delete confnode dir Edouard@718: shutil.rmtree(CTNInstance.CTNPath()) Edouard@718: # Remove child of Children Edouard@718: self.Children[CTNInstance.CTNType].remove(CTNInstance) Laurent@1033: if len(self.Children[CTNInstance.CTNType]) == 0: Laurent@1033: self.Children.pop(CTNInstance.CTNType) etisserant@14: # Forget it... (View have to refresh) etisserant@14: Edouard@718: def CTNRemove(self): Edouard@717: # Fetch the confnode Edouard@718: #CTNInstance = self.GetChildByName(CTNName) etisserant@14: # Ask to his parent to remove it Edouard@718: self.CTNParent._doRemoveChild(self) Edouard@718: Edouard@718: def CTNAddChild(self, CTNName, CTNType, IEC_Channel=0): etisserant@14: """ Edouard@717: Create the confnodes that may be added as child to this node self Edouard@718: @param CTNType: string desining the confnode class name (get name from CTNChildrenTypes) Edouard@718: @param CTNName: string for the name of the confnode instance Edouard@718: """ Edouard@720: # reorganize self.CTNChildrenTypes tuples from (name, CTNClass, Help) Edouard@718: # to ( name, (CTNClass, Help)), an make a dict Edouard@718: transpose = zip(*self.CTNChildrenTypes) Edouard@718: CTNChildrenTypes = dict(zip(transpose[0],zip(transpose[1],transpose[2]))) Edouard@717: # Check that adding this confnode is allowed etisserant@14: try: Edouard@718: CTNClass, CTNHelp = CTNChildrenTypes[CTNType] etisserant@14: except KeyError: Edouard@718: raise Exception, _("Cannot create child %s of type %s ")%(CTNName, CTNType) Edouard@718: Edouard@718: # if CTNClass is a class factory, call it. (prevent unneeded imports) Edouard@718: if type(CTNClass) == types.FunctionType: Edouard@718: CTNClass = CTNClass() etisserant@14: Edouard@717: # Eventualy Initialize child instance list for this class of confnode Edouard@718: ChildrenWithSameClass = self.Children.setdefault(CTNType, list()) etisserant@14: # Check count Edouard@718: if getattr(CTNClass, "CTNMaxCount", None) and len(ChildrenWithSameClass) >= CTNClass.CTNMaxCount: Edouard@718: raise Exception, _("Max count (%d) reached for this confnode of type %s ")%(CTNClass.CTNMaxCount, CTNType) Edouard@717: Edouard@717: # create the final class, derived of provided confnode and template Edouard@718: class FinalCTNClass(CTNClass, ConfigTreeNode): etisserant@14: """ Edouard@718: ConfNode class is derivated into FinalCTNClass before being instanciated Edouard@717: This way __init__ is overloaded to ensure ConfigTreeNode.__init__ is called Edouard@718: before CTNClass.__init__, and to do the file related stuff. etisserant@14: """ etisserant@14: def __init__(_self): etisserant@14: # self is the parent Edouard@718: _self.CTNParent = self Edouard@717: # Keep track of the confnode type name Edouard@718: _self.CTNType = CTNType etisserant@106: # remind the help string, for more fancy display Edouard@718: _self.CTNHelp = CTNHelp Edouard@717: # Call the base confnode template init - change XSD into class members Edouard@717: ConfigTreeNode.__init__(_self) etisserant@29: # check name is unique Edouard@718: NewCTNName = _self.FindNewName(CTNName) etisserant@14: # If dir have already be made, and file exist Edouard@718: if os.path.isdir(_self.CTNPath(NewCTNName)): #and os.path.isfile(_self.ConfNodeXmlFilePath(CTNName)): Edouard@717: #Load the confnode.xml file into parameters members Edouard@718: _self.LoadXMLParams(NewCTNName) etisserant@20: # Basic check. Better to fail immediately. Edouard@718: if (_self.BaseParams.getName() != NewCTNName): Edouard@718: raise Exception, _("Project tree layout do not match confnode.xml %s!=%s ")%(NewCTNName, _self.BaseParams.getName()) Edouard@718: Edouard@718: # Now, self.CTNPath() should be OK etisserant@20: etisserant@15: # Check that IEC_Channel is not already in use. etisserant@203: _self.FindNewIEC_Channel(_self.BaseParams.getIEC_Channel()) Edouard@717: # Call the confnode real __init__ Edouard@718: if getattr(CTNClass, "__init__", None): Edouard@718: CTNClass.__init__(_self) Edouard@718: #Load and init all the children Edouard@718: _self.LoadChildren() etisserant@118: #just loaded, nothing to saved etisserant@118: _self.ChangesToSave = False etisserant@14: else: Edouard@717: # If confnode do not have corresponding file/dirs - they will be created on Save Edouard@718: _self.CTNMakeDir() etisserant@14: # Find an IEC number laurent@417: _self.FindNewIEC_Channel(IEC_Channel) Edouard@717: # Call the confnode real __init__ Edouard@718: if getattr(CTNClass, "__init__", None): Edouard@718: CTNClass.__init__(_self) Edouard@718: _self.CTNRequestSave() etisserant@118: #just created, must be saved etisserant@118: _self.ChangesToSave = True laurent@403: lbessard@77: def _getBuildPath(_self): lbessard@77: return self._getBuildPath() lbessard@77: etisserant@14: # Create the object out of the resulting class Edouard@718: newConfNodeOpj = FinalCTNClass() Edouard@718: # Store it in CTNgedChils Edouard@718: ChildrenWithSameClass.append(newConfNodeOpj) Edouard@717: Edouard@717: return newConfNodeOpj laurent@403: Edouard@718: def ClearChildren(self): Edouard@718: for child in self.IterChildren(): Edouard@718: child.ClearChildren() Edouard@718: self.Children = {} laurent@403: Edouard@718: def LoadXMLParams(self, CTNName = None): Edouard@718: methode_name = os.path.join(self.CTNPath(CTNName), "methods.py") etisserant@105: if os.path.isfile(methode_name): etisserant@105: execfile(methode_name) greg@274: lbessard@17: # Get the base xml tree etisserant@20: if self.MandatoryParams: etisserant@203: try: Edouard@718: basexmlfile = open(self.ConfNodeBaseXmlFilePath(CTNName), 'r') etisserant@106: basetree = minidom.parse(basexmlfile) etisserant@106: self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0]) etisserant@106: basexmlfile.close() etisserant@203: except Exception, exc: Edouard@741: self.GetCTRoot().logger.write_error(_("Couldn't load confnode base parameters %s :\n %s") % (CTNName, unicode(exc))) Edouard@718: self.GetCTRoot().logger.write_error(traceback.format_exc()) lbessard@17: etisserant@14: # Get the xml tree Edouard@718: if self.CTNParams: etisserant@203: try: Edouard@718: xmlfile = open(self.ConfNodeXmlFilePath(CTNName), 'r') etisserant@106: tree = minidom.parse(xmlfile) Edouard@718: self.CTNParams[1].loadXMLTree(tree.childNodes[0]) etisserant@106: xmlfile.close() etisserant@203: except Exception, exc: Edouard@741: self.GetCTRoot().logger.write_error(_("Couldn't load confnode parameters %s :\n %s") % (CTNName, unicode(exc))) Edouard@718: self.GetCTRoot().logger.write_error(traceback.format_exc()) Edouard@718: Edouard@718: def LoadChildren(self): Edouard@718: # Iterate over all CTNName@CTNType in confnode directory, and try to open them Edouard@718: for CTNDir in os.listdir(self.CTNPath()): Edouard@718: if os.path.isdir(os.path.join(self.CTNPath(), CTNDir)) and \ Edouard@718: CTNDir.count(NameTypeSeparator) == 1: Edouard@718: pname, ptype = CTNDir.split(NameTypeSeparator) etisserant@203: try: Edouard@718: self.CTNAddChild(pname, ptype) etisserant@203: except Exception, exc: Edouard@741: self.GetCTRoot().logger.write_error(_("Could not add child \"%s\", type %s :\n%s\n")%(pname, ptype, unicode(exc))) Edouard@718: self.GetCTRoot().logger.write_error(traceback.format_exc()) etisserant@13: