diff -r b2c02ca6271e -r ee8cb104dbe0 plugger.py --- a/plugger.py Wed Aug 29 07:58:49 2007 +0200 +++ b/plugger.py Fri Aug 31 15:11:30 2007 +0200 @@ -3,18 +3,20 @@ """ import os +import plugins import types import shutil from xml.dom import minidom -import plugins from xmlclass import GenerateClassesFromXSDstring +from PLCControler import PLCControler + _BaseParamsClass = GenerateClassesFromXSDstring(""" - + @@ -35,18 +37,22 @@ def _AddParamsMembers(self): Classes = GenerateClassesFromXSDstring(self.XSD)[0] self.PlugParams = [] - for name, XSDclass in Classes.items(): - if XSDclass.IsBaseClass: - obj = XSDclass() - self.PlugParams.append( (name, obj) ) - setattr(self, name, obj) - - def __init__(self, PlugPath): + Classes = [(name, XSDclass) for name, XSDclass in Classes.items() if XSDclass.IsBaseClass] + if len(Classes) == 1: + name, XSDclass = Classes[0] + obj = XSDclass() + self.PlugParams = (name, obj) + setattr(self, name, obj) + + def __init__(self): # Create BaseParam self.BaseParams = _BaseParamsClass() - self.MandatoryParams = [("BaseParams", self.BaseParams)] + self.MandatoryParams = ("BaseParams", self.BaseParams) self._AddParamsMembers() self.PluggedChilds = {} + + def PluginBaseXmlFilePath(self, PlugName=None): + return os.path.join(self.PlugPath(PlugName), "baseplugin.xml") def PluginXmlFilePath(self, PlugName=None): return os.path.join(self.PlugPath(PlugName), "plugin.xml") @@ -62,26 +68,50 @@ def OnPlugSave(self): return True + def GetPlugParamsAttributes(self): + return self.PlugParams[1].getElementAttributes() + + def SetPlugParamsAttribute(self, name, value): + attr = getattr(self.PlugParams[1], name, None) + if isinstance(attr, types.ClassType): + attr.SetValue(value) + else: + setattr(self.PlugParams[1], name, value) + def PlugRequestSave(self): # If plugin do not have corresponding directory - if not os.path.isdir(self.PlugPath(PlugName)): + plugpath = self.PlugPath() + if not os.path.isdir(plugpath): # Create it - os.mkdir(self.PlugPath(PlugName)) - - # generate XML for all XML parameters controllers of the plugin - XMLString = '' - for nodeName, XMLController in self.PlugParams + self.MandatoryParams: - XMLString += XMLController.generateXMLTextMethod(self, nodeName, 0) - XMLFile = open(self.PluginXmlFilePath(PlugName),'w') - XMLFile.write(XMLString) - XMLFile.close() + os.mkdir(plugpath) + + # generate XML for base XML parameters controller of the plugin + basexmlfilepath = self.PluginBaseXmlFilePath() + if basexmlfilepath: + BaseXMLFile = open(basexmlfilepath,'w') + BaseXMLFile.write("\n") + BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0)) + BaseXMLFile.close() + + # generate XML for XML parameters controller of the plugin + xmlfilepath = self.PluginXmlFilePath() + if xmlfilepath: + XMLFile = open(xmlfilepath,'w') + XMLFile.write("\n") + XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0)) + XMLFile.close() # Call the plugin specific OnPlugSave method - self.OnPlugSave() + result = self.OnPlugSave() + if not result: + return "Error while saving \"%s\""%self.PlugPath() # go through all childs and do the same for PlugChild in self.IterChilds(): - PlugChild.PlugRequestSave() + result = PlugChild.PlugRequestSave() + if result: + return result + return None def PlugImport(self, src_PlugPath): shutil.copytree(src_PlugPath, self.PlugPath) @@ -92,7 +122,7 @@ Generate C code @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) @param locations: List of complete variables locations \ - [(IEC_loc, IEC_Direction IEC_Type, Name)]\ + [(IEC_loc, IEC_Direction, IEC_Type, Name)]\ ex: [((0,0,4,5),'I','STRING','__IX_0_0_4_5'),...] """ return [],"" @@ -132,7 +162,7 @@ def _GetChildBySomething(self, sep, something, matching): toks = matching.split(sep,1) - for PlugInstance in self.IterChilds: + for PlugInstance in self.IterChilds(): # if match component of the name if getattr(PlugInstance.BaseParams, something) == toks[0]: # if Name have other components @@ -150,6 +180,12 @@ def GetChildByIECLocation(self, Location): return self._GetChildBySomething('_',"IEC_Channel", Name) + def GetPlugInfos(self): + childs = [] + for child in self.IterChilds(): + childs.append(child.GetPlugInfos()) + return {"name" : self.BaseParams.getName(), "type" : None, "values" : childs} + def FindNewIEC_Channel(self, DesiredChannel): """ Changes IEC Channel number to DesiredChannel if available, nearest available if not. @@ -217,10 +253,10 @@ PlugClass = PlugClass() # Eventualy Initialize child instance list for this class of plugin - PluggedChildsWithSameClass = self.PluggedChilds.setdefault(PlugType,list()) + PluggedChildsWithSameClass = self.PluggedChilds.setdefault(PlugType, list()) # Check count - if PlugClass.MaxCount and len(PluggedChildsWithSameClass) >= PlugClass.MaxCount: - raise Exception, "Max count (%d) reached for this plugin of type %s "%(PlugClass.MaxCount, PlugType) + if getattr(PlugClass, "PlugMaxCount", None) and len(PluggedChildsWithSameClass) >= PlugClass.PlugMaxCount: + raise Exception, "Max count (%d) reached for this plugin of type %s "%(PlugClass.PlugMaxCount, PlugType) # create the final class, derived of provided plugin and template class FinalPlugClass(PlugClass, PlugTemplate): @@ -239,21 +275,25 @@ # If dir have already be made, and file exist if os.path.isdir(_self.PlugPath(PlugName)) and os.path.isfile(_self.PluginXmlFilePath(PlugName)): #Load the plugin.xml file into parameters members - _self.LoadXMLParams() + _self.LoadXMLParams(PlugName) # Check that IEC_Channel is not already in use. self.FindNewIEC_Channel(self.BaseParams.getIEC_Channel()) # Call the plugin real __init__ - PlugClass.__init__(_self) + if getattr(PlugClass, "__init__", None): + PlugClass.__init__(_self) #Load and init all the childs _self.LoadChilds() else: # If plugin do not have corresponding file/dirs - they will be created on Save # Set plugin name _self.BaseParams.setName(PlugName) + os.mkdir(_self.PlugPath()) # Find an IEC number _self.FindNewIEC_Channel(0) # Call the plugin real __init__ - PlugClass.__init__(_self) + if getattr(PlugClass, "__init__", None): + PlugClass.__init__(_self) + _self.PlugRequestSave() # Create the object out of the resulting class newPluginOpj = FinalPlugClass() @@ -263,39 +303,50 @@ return newPluginOpj - def LoadXMLParams(self): - # PlugParams have been filled, make a local dict to work with - PlugParams = dict(self.PlugParams + self.MandatoryParams) + def LoadXMLParams(self, PlugName = None, test = True): + # Get the base xml tree + basexmlfilepath = self.PluginBaseXmlFilePath(PlugName) + if basexmlfilepath: + basexmlfile = open(basexmlfilepath, 'r') + basetree = minidom.parse(basexmlfile) + self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0]) + basexmlfile.close() + # Get the xml tree - xmlfile = open(self.PluginXmlFilePath(PlugName), 'r') - tree = minidom.parse(xmlfile) - xmlfile.close() - # for each root elements - for subtree in tree.childNodes: - # if a plugin specific parameter set - if subtree.nodeName in PlugParams: - #Load into associated xmlclass. - PlugParams[subtree.nodeName].loadXMLTree(subtree) - - # Basic check. Better to fail immediately. - if(self.BaseParams.getName() != PlugName): - raise Exception, "Project tree layout do not match plugin.xml %s!=%s "%(PlugName,self.BaseParams.getName()) - # Now, self.PlugPath() should be OK + xmlfilepath = self.PluginXmlFilePath(PlugName) + if xmlfilepath: + xmlfile = open(xmlfilepath, 'r') + tree = minidom.parse(xmlfile) + self.PlugParams[1].loadXMLTree(tree.childNodes[0]) + xmlfile.close() + + if test: + # Basic check. Better to fail immediately. + if not PlugName: + PlugName = os.path.split(self.PlugPath())[1].split(NameTypeSeparator)[0] + if (self.BaseParams.getName() != PlugName): + raise Exception, "Project tree layout do not match plugin.xml %s!=%s "%(PlugName, self.BaseParams.getName()) + # Now, self.PlugPath() should be OK def LoadChilds(self): # Iterate over all PlugName@PlugType in plugin directory, and try to open them for PlugDir in os.listdir(self.PlugPath()): - if os.path.isdir(os.path.join(self.PlugPath(),PlugDir)) and \ + if os.path.isdir(os.path.join(self.PlugPath(), PlugDir)) and \ PlugDir.count(NameTypeSeparator) == 1: try: - self.PlugAddChild(*PlugDir.split[NameTypeSeparator]) + self.PlugAddChild(*PlugDir.split(NameTypeSeparator)) except Exception, e: print e +def _GetClassFunction(name): + def GetRootClass(): + return getattr(__import__("plugins." + name), name).RootClass + return GetRootClass + class PluginsRoot(PlugTemplate): # For root object, available Childs Types are modules of the plugin packages. - PlugChildsTypes = [(name,lambda : getattr(__import__("plugins." + name), name).RootClass) for name in plugins.__all__] + PlugChildsTypes = [(name, _GetClassFunction(name)) for name in plugins.__all__] XSD = """ @@ -314,33 +365,33 @@ - + - + - - + + - - - + + + - - + + @@ -351,29 +402,120 @@ """ - def __init__(self, ProjectPath): + def __init__(self): + PlugTemplate.__init__(self) # self is the parent self.PlugParent = None # Keep track of the plugin type name self.PlugType = "Beremiz" - # Keep track of the root plugin (i.e. project path) - self.ProjectPath = ProjectPath + + self.ProjectPath = "" + self.PLCManager = None + + def HasProjectOpened(self): + """ + Return if a project is actually opened + """ + return self.ProjectPath != "" + + def GetProjectPath(self): + return self.ProjectPath + + def GetTargetTypes(self): + return self.BeremizRoot.TargetType.getChoices().keys() + + def ChangeTargetType(self, target_type): + self.BeremizRoot.TargetType.addContent(target_type) + + def GetTargetAttributes(self): + content = self.BeremizRoot.TargetType.getContent() + if content: + return content["value"].getElementAttributes() + else: + return [] + + def SetTargetAttribute(self, name, value): + content = self.BeremizRoot.TargetType.getContent() + if content: + attr = getattr(content["value"], name, None) + if isinstance(attr, types.ClassType): + attr.SetValue(value) + else: + setattr(content["value"], name, value) + + def GetTargetType(self): + content = self.BeremizRoot.TargetType.getContent() + if content: + return content["name"] + else: + return "" + + def NewProject(self, ProjectPath, PLCParams): + """ + Create a new project in an empty folder + @param ProjectPath: path of the folder where project have to be created + @param PLCParams: properties of the PLCOpen program created + """ + # Verify that choosen folder is empty + if not os.path.isdir(ProjectPath) or len(os.listdir(ProjectPath)) > 0: + return "Folder choosen isn't empty. You can't use it for a new project!" + # Create Controler for PLCOpen program + self.PLCManager = PLCControler() + self.PLCManager.CreateNewProject(PLCParams.pop("projectName")) + self.PLCManager.SetProjectProperties(properties = PLCParams) # Change XSD into class members self._AddParamsMembers() self.PluggedChilds = {} # No IEC channel, name, etc... self.MandatoryParams = [] + # Keep track of the root plugin (i.e. project path) + self.ProjectPath = ProjectPath + self.BaseParams.setName(os.path.split(ProjectPath)[1]) + return None + + def LoadProject(self, ProjectPath): + """ + Load a project contained in a folder + @param ProjectPath: path of the project folder + """ + # Verify that project contains a PLCOpen program + plc_file = os.path.join(ProjectPath, "plc.xml") + if not os.path.isfile(plc_file): + return "Folder choosen doesn't contain a program. It's not a valid project!" + # Create Controler for PLCOpen program + self.PLCManager = PLCControler() + # Load PLCOpen file + result = self.PLCManager.OpenXMLFile(plc_file) + if result: + return result + # Change XSD into class members + self._AddParamsMembers() + self.PluggedChilds = {} + # No IEC channel, name, etc... + self.MandatoryParams = None + # Keep track of the root plugin (i.e. project path) + self.ProjectPath = ProjectPath # If dir have already be made, and file exist - if os.path.isdir(_self.PlugPath(PlugName)) and os.path.isfile(_self.PluginXmlFilePath(PlugName)): + if os.path.isdir(self.PlugPath()) and os.path.isfile(self.PluginXmlFilePath()): #Load the plugin.xml file into parameters members - _self.LoadXMLParams() + result = self.LoadXMLParams(test = False) + if result: + return result #Load and init all the childs - _self.LoadChilds() - - def PlugPath(self,PlugName=None): + self.LoadChilds() + self.BaseParams.setName(os.path.split(ProjectPath)[1]) + return None + + def SaveProject(self): + if not self.PLCManager.SaveXMLFile(): + self.PLCManager.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml')) + self.PlugRequestSave() + + def PlugPath(self, PlugName=None): return self.ProjectPath - + + def PluginBaseXmlFilePath(self, PlugName=None): + return None + def PluginXmlFilePath(self, PlugName=None): return os.path.join(self.PlugPath(PlugName), "beremiz.xml") - -