laurent@366: import wx laurent@366: import os laurent@366: import modules Edouard@717: from ConfigTree import ConfigTreeNode, opjimg laurent@654: from PLCControler import UndoBuffer laurent@657: from PythonEditor import PythonEditor laurent@366: laurent@366: from xml.dom import minidom laurent@366: from xmlclass import * laurent@366: import cPickle laurent@366: laurent@366: PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "python_xsd.xsd")) laurent@366: laurent@366: class PythonCodeTemplate: laurent@366: laurent@657: EditorType = PythonEditor laurent@657: laurent@366: def __init__(self): laurent@366: Edouard@717: self.ConfNodeMethods.insert(0, laurent@366: {"bitmap" : opjimg("editPYTHONcode"), laurent@366: "name" : _("Edit Python File"), laurent@366: "tooltip" : _("Edit Python File"), laurent@366: "method" : "_OpenView"}, laurent@366: ) laurent@366: laurent@366: filepath = self.PythonFileName() laurent@366: laurent@366: self.PythonCode = PythonClasses["Python"]() laurent@366: if os.path.isfile(filepath): laurent@366: xmlfile = open(filepath, 'r') laurent@366: tree = minidom.parse(xmlfile) laurent@366: xmlfile.close() laurent@366: laurent@366: for child in tree.childNodes: laurent@366: if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python": laurent@366: self.PythonCode.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"]) laurent@657: self.CreatePythonBuffer(True) laurent@366: else: laurent@657: self.CreatePythonBuffer(False) Edouard@718: self.OnCTNSave() laurent@366: Edouard@717: def ConfNodePath(self): Edouard@718: return os.path.join(self.CTNParent.ConfNodePath(), "modules", self.CTNType) laurent@366: laurent@366: def PythonFileName(self): Edouard@718: return os.path.join(self.CTNPath(), "python.xml") laurent@366: laurent@366: def GetFilename(self): laurent@366: if self.PythonBuffer.IsCurrentSaved(): laurent@366: return "python" laurent@366: else: laurent@366: return "~python~" laurent@366: laurent@366: def SetPythonCode(self, text): laurent@366: self.PythonCode.settext(text) laurent@366: laurent@366: def GetPythonCode(self): laurent@366: return self.PythonCode.gettext() laurent@366: Edouard@718: def CTNTestModified(self): laurent@657: return self.ChangesToSave or not self.PythonIsSaved() laurent@366: Edouard@718: def OnCTNSave(self): laurent@366: filepath = self.PythonFileName() laurent@366: laurent@366: text = "\n" laurent@366: extras = {"xmlns":"http://www.w3.org/2001/XMLSchema", laurent@366: "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance", laurent@366: "xsi:schemaLocation" : "python_xsd.xsd"} laurent@366: text += self.PythonCode.generateXMLText("Python", 0, extras) laurent@366: laurent@366: xmlfile = open(filepath,"w") laurent@430: xmlfile.write(text.encode("utf-8")) laurent@366: xmlfile.close() laurent@366: laurent@657: self.MarkPythonAsSaved() laurent@366: return True laurent@366: laurent@366: #------------------------------------------------------------------------------- laurent@366: # Current Buffering Management Functions laurent@366: #------------------------------------------------------------------------------- laurent@366: laurent@366: """ laurent@366: Return a copy of the project laurent@366: """ laurent@366: def Copy(self, model): laurent@366: return cPickle.loads(cPickle.dumps(model)) laurent@366: laurent@657: def CreatePythonBuffer(self, saved): laurent@657: self.Buffering = False laurent@657: self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved) laurent@657: laurent@366: def BufferPython(self): laurent@657: self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode)) laurent@366: laurent@366: def StartBuffering(self): laurent@366: self.Buffering = True laurent@366: laurent@366: def EndBuffering(self): laurent@366: if self.Buffering: laurent@657: self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode)) laurent@366: self.Buffering = False laurent@366: laurent@657: def MarkPythonAsSaved(self): laurent@657: self.EndBuffering() laurent@657: self.PythonBuffer.CurrentSaved() laurent@657: laurent@657: def PythonIsSaved(self): laurent@657: return self.PythonBuffer.IsCurrentSaved() and not self.Buffering laurent@657: laurent@366: def LoadPrevious(self): laurent@657: self.EndBuffering() laurent@657: self.PythonCode = cPickle.loads(self.PythonBuffer.Previous()) laurent@366: laurent@366: def LoadNext(self): laurent@657: self.PythonCode = cPickle.loads(self.PythonBuffer.Next()) laurent@366: laurent@366: def GetBufferState(self): laurent@657: first = self.PythonBuffer.IsFirst() and not self.Buffering laurent@366: last = self.PythonBuffer.IsLast() laurent@366: return not first, not last laurent@366: laurent@366: def _GetClassFunction(name): laurent@366: def GetRootClass(): Edouard@717: __import__("confnodes.python.modules." + name) laurent@366: return getattr(modules, name).RootClass laurent@366: return GetRootClass laurent@366: laurent@366: class RootClass(PythonCodeTemplate): laurent@366: Edouard@718: # For root object, available Children Types are modules of the modules packages. Edouard@718: CTNChildrenTypes = [(name, _GetClassFunction(name), help) for name, help in zip(modules.__all__,modules.helps)] laurent@366: Edouard@717: def ConfNodePath(self): Edouard@718: return os.path.join(self.CTNParent.ConfNodePath(), self.CTNType) laurent@366: Edouard@718: def CTNGenerate_C(self, buildpath, locations): laurent@366: """ laurent@366: Generate C code Edouard@717: @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5) laurent@366: @param locations: List of complete variables locations \ laurent@366: [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) laurent@366: "NAME" : name of the variable (generally "__IW0_1_2" style) laurent@366: "DIR" : direction "Q","I" or "M" laurent@366: "SIZE" : size "X", "B", "W", "D", "L" laurent@366: "LOC" : tuple of interger for IEC location (0,1,2,...) laurent@366: }, ...] laurent@366: @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND laurent@366: """ laurent@366: current_location = self.GetCurrentLocation() laurent@366: # define a unique name for the generated C file laurent@366: location_str = "_".join(map(lambda x:str(x), current_location)) laurent@366: Edouard@718: ctr = self.GetCTRoot() Edouard@717: ctr.GetIECProgramsAndVariables() laurent@366: laurent@366: plc_python_filepath = os.path.join(os.path.split(__file__)[0], "plc_python.c") laurent@366: plc_python_file = open(plc_python_filepath, 'r') laurent@366: plc_python_code = plc_python_file.read() laurent@366: plc_python_file.close() laurent@366: python_eval_fb_list = [] Edouard@717: for v in ctr._VariablesList: laurent@366: if v["vartype"] == "FB" and v["type"] in ["PYTHON_EVAL","PYTHON_POLL"]: laurent@366: python_eval_fb_list.append(v) laurent@366: python_eval_fb_count = max(1, len(python_eval_fb_list)) laurent@366: laurent@366: # prepare python code laurent@366: plc_python_code = plc_python_code % { laurent@366: "python_eval_fb_count": python_eval_fb_count, laurent@366: "location": location_str} laurent@366: laurent@366: Gen_Pythonfile_path = os.path.join(buildpath, "python_%s.c"%location_str) laurent@366: pythonfile = open(Gen_Pythonfile_path,'w') laurent@366: pythonfile.write(plc_python_code) laurent@366: pythonfile.close() laurent@366: laurent@366: runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str) laurent@366: runtimefile = open(runtimefile_path, 'w') laurent@366: runtimefile.write(self.GetPythonCode()) laurent@366: runtimefile.close() laurent@366: Edouard@718: matiec_flags = '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()) laurent@366: laurent@366: return [(Gen_Pythonfile_path, matiec_flags)], "", True, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))