confnodes/python/python.py
changeset 721 ecf4d203c4d4
parent 720 6be032177e2a
child 722 a94f361fc42e
equal deleted inserted replaced
720:6be032177e2a 721:ecf4d203c4d4
     1 import wx
       
     2 import os
       
     3 import modules
       
     4 from ConfigTree import ConfigTreeNode, opjimg
       
     5 from PLCControler import UndoBuffer
       
     6 from PythonEditor import PythonEditor
       
     7 
       
     8 from xml.dom import minidom
       
     9 from xmlclass import *
       
    10 import cPickle
       
    11 
       
    12 PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "python_xsd.xsd")) 
       
    13 
       
    14 class PythonCodeTemplate:
       
    15     
       
    16     EditorType = PythonEditor
       
    17     
       
    18     def __init__(self):
       
    19         
       
    20         self.ConfNodeMethods.insert(0, 
       
    21                 {"bitmap" : opjimg("editPYTHONcode"),
       
    22                  "name" : _("Edit Python File"), 
       
    23                  "tooltip" : _("Edit Python File"),
       
    24                  "method" : "_OpenView"},
       
    25         )
       
    26 
       
    27         filepath = self.PythonFileName()
       
    28         
       
    29         self.PythonCode = PythonClasses["Python"]()
       
    30         if os.path.isfile(filepath):
       
    31             xmlfile = open(filepath, 'r')
       
    32             tree = minidom.parse(xmlfile)
       
    33             xmlfile.close()
       
    34             
       
    35             for child in tree.childNodes:
       
    36                 if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python":
       
    37                     self.PythonCode.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
       
    38                     self.CreatePythonBuffer(True)
       
    39         else:
       
    40             self.CreatePythonBuffer(False)
       
    41             self.OnCTNSave()
       
    42 
       
    43     def ConfNodePath(self):
       
    44         return os.path.join(self.CTNParent.ConfNodePath(), "modules", self.CTNType)
       
    45 
       
    46     def PythonFileName(self):
       
    47         return os.path.join(self.CTNPath(), "python.xml")
       
    48 
       
    49     def GetFilename(self):
       
    50         if self.PythonBuffer.IsCurrentSaved():
       
    51             return "python"
       
    52         else:
       
    53             return "~python~"
       
    54 
       
    55     def SetPythonCode(self, text):
       
    56         self.PythonCode.settext(text)
       
    57         
       
    58     def GetPythonCode(self):
       
    59         return self.PythonCode.gettext()
       
    60     
       
    61     def CTNTestModified(self):
       
    62         return self.ChangesToSave or not self.PythonIsSaved()
       
    63     
       
    64     def OnCTNSave(self):
       
    65         filepath = self.PythonFileName()
       
    66         
       
    67         text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
       
    68         extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
       
    69                   "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
       
    70                   "xsi:schemaLocation" : "python_xsd.xsd"}
       
    71         text += self.PythonCode.generateXMLText("Python", 0, extras)
       
    72 
       
    73         xmlfile = open(filepath,"w")
       
    74         xmlfile.write(text.encode("utf-8"))
       
    75         xmlfile.close()
       
    76         
       
    77         self.MarkPythonAsSaved()
       
    78         return True
       
    79         
       
    80 #-------------------------------------------------------------------------------
       
    81 #                      Current Buffering Management Functions
       
    82 #-------------------------------------------------------------------------------
       
    83 
       
    84     """
       
    85     Return a copy of the project
       
    86     """
       
    87     def Copy(self, model):
       
    88         return cPickle.loads(cPickle.dumps(model))
       
    89 
       
    90     def CreatePythonBuffer(self, saved):
       
    91         self.Buffering = False
       
    92         self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved)
       
    93 
       
    94     def BufferPython(self):
       
    95         self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
       
    96     
       
    97     def StartBuffering(self):
       
    98         self.Buffering = True
       
    99         
       
   100     def EndBuffering(self):
       
   101         if self.Buffering:
       
   102             self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
       
   103             self.Buffering = False
       
   104     
       
   105     def MarkPythonAsSaved(self):
       
   106         self.EndBuffering()
       
   107         self.PythonBuffer.CurrentSaved()
       
   108     
       
   109     def PythonIsSaved(self):
       
   110         return self.PythonBuffer.IsCurrentSaved() and not self.Buffering
       
   111         
       
   112     def LoadPrevious(self):
       
   113         self.EndBuffering()
       
   114         self.PythonCode = cPickle.loads(self.PythonBuffer.Previous())
       
   115     
       
   116     def LoadNext(self):
       
   117         self.PythonCode = cPickle.loads(self.PythonBuffer.Next())
       
   118     
       
   119     def GetBufferState(self):
       
   120         first = self.PythonBuffer.IsFirst() and not self.Buffering
       
   121         last = self.PythonBuffer.IsLast()
       
   122         return not first, not last
       
   123 
       
   124 def _GetClassFunction(name):
       
   125     def GetRootClass():
       
   126         __import__("confnodes.python.modules." + name)
       
   127         return getattr(modules, name).RootClass
       
   128     return GetRootClass
       
   129 
       
   130 class RootClass(PythonCodeTemplate):
       
   131 
       
   132     # For root object, available Children Types are modules of the modules packages.
       
   133     CTNChildrenTypes = [(name, _GetClassFunction(name), help) for name, help in zip(modules.__all__,modules.helps)]
       
   134     
       
   135     def ConfNodePath(self):
       
   136         return os.path.join(self.CTNParent.ConfNodePath(), self.CTNType)
       
   137     
       
   138     def CTNGenerate_C(self, buildpath, locations):
       
   139         """
       
   140         Generate C code
       
   141         @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
       
   142         @param locations: List of complete variables locations \
       
   143             [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
       
   144             "NAME" : name of the variable (generally "__IW0_1_2" style)
       
   145             "DIR" : direction "Q","I" or "M"
       
   146             "SIZE" : size "X", "B", "W", "D", "L"
       
   147             "LOC" : tuple of interger for IEC location (0,1,2,...)
       
   148             }, ...]
       
   149         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
       
   150         """
       
   151         current_location = self.GetCurrentLocation()
       
   152         # define a unique name for the generated C file
       
   153         location_str = "_".join(map(lambda x:str(x), current_location))
       
   154         
       
   155         ctr = self.GetCTRoot()
       
   156         ctr.GetIECProgramsAndVariables()
       
   157         
       
   158         plc_python_filepath = os.path.join(os.path.split(__file__)[0], "plc_python.c")
       
   159         plc_python_file = open(plc_python_filepath, 'r')
       
   160         plc_python_code = plc_python_file.read()
       
   161         plc_python_file.close()
       
   162         python_eval_fb_list = []
       
   163         for v in ctr._VariablesList:
       
   164             if v["vartype"] == "FB" and v["type"] in ["PYTHON_EVAL","PYTHON_POLL"]:
       
   165                 python_eval_fb_list.append(v)
       
   166         python_eval_fb_count = max(1, len(python_eval_fb_list))
       
   167         
       
   168         # prepare python code
       
   169         plc_python_code = plc_python_code % {
       
   170            "python_eval_fb_count": python_eval_fb_count,
       
   171            "location": location_str}
       
   172         
       
   173         Gen_Pythonfile_path = os.path.join(buildpath, "python_%s.c"%location_str)
       
   174         pythonfile = open(Gen_Pythonfile_path,'w')
       
   175         pythonfile.write(plc_python_code)
       
   176         pythonfile.close()
       
   177         
       
   178         runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
       
   179         runtimefile = open(runtimefile_path, 'w')
       
   180         runtimefile.write(self.GetPythonCode())
       
   181         runtimefile.close()
       
   182         
       
   183         matiec_flags = '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath())
       
   184         
       
   185         return [(Gen_Pythonfile_path, matiec_flags)], "", True, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))