runtime/PLCObject.py
changeset 1784 64beb9e9c749
parent 1783 3311eea28d56
child 1831 56b48961cc68
--- a/runtime/PLCObject.py	Mon Aug 21 20:17:19 2017 +0000
+++ b/runtime/PLCObject.py	Mon Aug 21 23:22:58 2017 +0300
@@ -23,7 +23,12 @@
 
 import Pyro.core as pyro
 from threading import Timer, Thread, Lock, Semaphore, Event
-import ctypes, os, commands, types, sys
+import ctypes
+import os
+import commands
+import types
+import sys
+import traceback
 from targets.typemapping import LogLevelsDefault, LogLevelsCount, TypeTranslator, UnpackDebugBuffer
 from time import time
 
@@ -34,26 +39,29 @@
 elif os.name == "posix":
     from _ctypes import dlopen, dlclose
 
-import traceback
+
 def get_last_traceback(tb):
     while tb.tb_next:
         tb = tb.tb_next
     return tb
 
-lib_ext ={
-     "linux2":".so",
-     "win32":".dll",
+
+lib_ext = {
+     "linux2": ".so",
+     "win32":  ".dll",
      }.get(sys.platform, "")
 
+
 def PLCprint(message):
     sys.stdout.write("PLCobject : "+message+"\n")
     sys.stdout.flush()
 
+
 class PLCObject(pyro.ObjBase):
     def __init__(self, workingdir, daemon, argv, statuschange, evaluator, pyruntimevars):
         pyro.ObjBase.__init__(self)
         self.evaluator = evaluator
-        self.argv = [workingdir] + argv # force argv[0] to be "path" to exec...
+        self.argv = [workingdir] + argv  # force argv[0] to be "path" to exec...
         self.workingdir = workingdir
         self.PLCStatus = "Empty"
         self.PLClibraryHandle = None
@@ -75,14 +83,14 @@
     def AutoLoad(self):
         # Get the last transfered PLC if connector must be restart
         try:
-            self.CurrentPLCFilename=open(
+            self.CurrentPLCFilename = open(
                              self._GetMD5FileName(),
                              "r").read().strip() + lib_ext
             if self.LoadPLC():
                 self.PLCStatus = "Stopped"
         except Exception, e:
             self.PLCStatus = "Empty"
-            self.CurrentPLCFilename=None
+            self.CurrentPLCFilename = None
 
     def StatusChange(self):
         if self.statuschange is not None:
@@ -102,9 +110,9 @@
             self._ResetLogCount()
 
     def GetLogCount(self, level):
-        if self._GetLogCount is not None :
+        if self._GetLogCount is not None:
             return int(self._GetLogCount(level))
-        elif self._loading_error is not None and level==0:
+        elif self._loading_error is not None and level == 0:
             return 1
 
     def GetLogMessage(self, level, msgid):
@@ -114,23 +122,22 @@
         if self._GetLogMessage is not None:
             maxsz = len(self._log_read_buffer)-1
             sz = self._GetLogMessage(level, msgid,
-                self._log_read_buffer, maxsz,
-                ctypes.byref(tick),
-                ctypes.byref(tv_sec),
-                ctypes.byref(tv_nsec))
+                                     self._log_read_buffer, maxsz,
+                                     ctypes.byref(tick),
+                                     ctypes.byref(tv_sec),
+                                     ctypes.byref(tv_nsec))
             if sz and sz <= maxsz:
                 self._log_read_buffer[sz] = '\x00'
-                return self._log_read_buffer.value,tick.value,tv_sec.value,tv_nsec.value
-        elif self._loading_error is not None and level==0:
-            return self._loading_error,0,0,0
+                return self._log_read_buffer.value, tick.value, tv_sec.value, tv_nsec.value
+        elif self._loading_error is not None and level == 0:
+            return self._loading_error, 0, 0, 0
         return None
 
     def _GetMD5FileName(self):
         return os.path.join(self.workingdir, "lasttransferedPLC.md5")
 
     def _GetLibFileName(self):
-        return os.path.join(self.workingdir,self.CurrentPLCFilename)
-
+        return os.path.join(self.workingdir, self.CurrentPLCFilename)
 
     def LoadPLC(self):
         """
@@ -143,8 +150,8 @@
             self.PLClibraryHandle = ctypes.CDLL(self.CurrentPLCFilename, handle=self._PLClibraryHandle)
 
             self.PLC_ID = ctypes.c_char_p.in_dll(self.PLClibraryHandle, "PLC_ID")
-            if len(md5) == 32 : 
-                self.PLC_ID.value = md5 
+            if len(md5) == 32:
+                self.PLC_ID.value = md5
 
             self._startPLC = self.PLClibraryHandle.startPLC
             self._startPLC.restype = ctypes.c_int
@@ -163,6 +170,7 @@
                 # If python confnode is not enabled, we reuse _PythonIterator
                 # as a call that block pythonthread until StopPLC
                 self.PlcStopping = Event()
+
                 def PythonIterator(res, blkid):
                     self.PlcStopping.clear()
                     self.PlcStopping.wait()
@@ -174,7 +182,6 @@
                     self.PlcStopping.set()
                 self._stopPLC = __StopPLC
 
-
             self._ResetDebugVariables = self.PLClibraryHandle.ResetDebugVariables
             self._ResetDebugVariables.restype = None
 
@@ -207,7 +214,7 @@
             self._LogMessage.restype = ctypes.c_int
             self._LogMessage.argtypes = [ctypes.c_uint8, ctypes.c_char_p, ctypes.c_uint32]
 
-            self._log_read_buffer = ctypes.create_string_buffer(1<<14) #16K
+            self._log_read_buffer = ctypes.create_string_buffer(1 << 14)  # 16K
             self._GetLogMessage = self.PLClibraryHandle.GetLogMessage
             self._GetLogMessage.restype = ctypes.c_uint32
             self._GetLogMessage.argtypes = [ctypes.c_uint8, ctypes.c_uint32, ctypes.c_char_p, ctypes.c_uint32, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32)]
@@ -217,7 +224,7 @@
             self.PythonRuntimeInit()
 
             return True
-        except:
+        except Exception:
             self._loading_error = traceback.format_exc()
             PLCprint(self._loading_error)
             return False
@@ -233,22 +240,22 @@
         """
         self.PLClibraryLock.acquire()
         # Forget all refs to library
-        self._startPLC = lambda x,y:None
-        self._stopPLC = lambda:None
-        self._ResetDebugVariables = lambda:None
-        self._RegisterDebugVariable = lambda x, y:None
-        self._IterDebugData = lambda x,y:None
-        self._FreeDebugData = lambda:None
-        self._GetDebugData = lambda:-1
-        self._suspendDebug = lambda x:-1
-        self._resumeDebug = lambda:None
-        self._PythonIterator = lambda:""
+        self._startPLC = lambda x, y: None
+        self._stopPLC = lambda: None
+        self._ResetDebugVariables = lambda: None
+        self._RegisterDebugVariable = lambda x, y: None
+        self._IterDebugData = lambda x, y: None
+        self._FreeDebugData = lambda: None
+        self._GetDebugData = lambda: -1
+        self._suspendDebug = lambda x: -1
+        self._resumeDebug = lambda: None
+        self._PythonIterator = lambda: ""
         self._GetLogCount = None
-        self._LogMessage = lambda l,m,s:PLCprint("OFF LOG :"+m)
+        self._LogMessage = lambda l, m, s: PLCprint("OFF LOG :"+m)
         self._GetLogMessage = None
         self.PLClibraryHandle = None
         # Unload library explicitely
-        if getattr(self,"_PLClibraryHandle",None) is not None:
+        if getattr(self, "_PLClibraryHandle", None) is not None:
             dlclose(self._PLClibraryHandle)
             self._PLClibraryHandle = None
 
@@ -260,10 +267,10 @@
         Calls init, start, stop or cleanup method provided by
         runtime python files, loaded when new PLC uploaded
         """
-        for method in self.python_runtime_vars.get("_runtime_%s"%methodname, []):
-            res,exp = self.evaluator(method)
+        for method in self.python_runtime_vars.get("_runtime_%s" % methodname, []):
+            res, exp = self.evaluator(method)
             if exp is not None:
-                self.LogMessage(0,'\n'.join(traceback.format_exception(*exp)))
+                self.LogMessage(0, '\n'.join(traceback.format_exception(*exp)))
 
     def PythonRuntimeInit(self):
         MethodNames = ["init", "start", "stop", "cleanup"]
@@ -272,30 +279,31 @@
 
         class PLCSafeGlobals:
             def __getattr__(_self, name):
-                try :
+                try:
                     t = self.python_runtime_vars["_"+name+"_ctype"]
                 except KeyError:
-                    raise KeyError("Try to get unknown shared global variable : %s"%name)
+                    raise KeyError("Try to get unknown shared global variable : %s" % name)
                 v = t()
                 r = self.python_runtime_vars["_PySafeGetPLCGlob_"+name](ctypes.byref(v))
                 return self.python_runtime_vars["_"+name+"_unpack"](v)
+
             def __setattr__(_self, name, value):
-                try :
+                try:
                     t = self.python_runtime_vars["_"+name+"_ctype"]
                 except KeyError:
-                    raise KeyError("Try to set unknown shared global variable : %s"%name)
-                v = self.python_runtime_vars["_"+name+"_pack"](t,value)
+                    raise KeyError("Try to set unknown shared global variable : %s" % name)
+                v = self.python_runtime_vars["_"+name+"_pack"](t, value)
                 self.python_runtime_vars["_PySafeSetPLCGlob_"+name](ctypes.byref(v))
 
         self.python_runtime_vars.update({
-            "PLCGlobals" : PLCSafeGlobals(),
-            "WorkingDir" : self.workingdir,
-            "PLCObject"  : self,
-            "PLCBinary"  : self.PLClibraryHandle,
-            "PLCGlobalsDesc" : []})
-
-        for methodname in MethodNames :
-            self.python_runtime_vars["_runtime_%s"%methodname] = []
+            "PLCGlobals":     PLCSafeGlobals(),
+            "WorkingDir":     self.workingdir,
+            "PLCObject":      self,
+            "PLCBinary":      self.PLClibraryHandle,
+            "PLCGlobalsDesc": []})
+
+        for methodname in MethodNames:
+            self.python_runtime_vars["_runtime_%s" % methodname] = []
 
         try:
             filenames = os.listdir(self.workingdir)
@@ -307,15 +315,13 @@
                     for methodname in MethodNames:
                         method = self.python_runtime_vars.get("_%s_%s" % (name, methodname), None)
                         if method is not None:
-                            self.python_runtime_vars["_runtime_%s"%methodname].append(method)
-        except:
-            self.LogMessage(0,traceback.format_exc())
+                            self.python_runtime_vars["_runtime_%s" % methodname].append(method)
+        except Exception:
+            self.LogMessage(0, traceback.format_exc())
             raise
 
         self.PythonRuntimeCall("init")
 
-
-
     def PythonRuntimeCleanup(self):
         if self.python_runtime_vars is not None:
             self.PythonRuntimeCall("cleanup")
@@ -324,49 +330,49 @@
 
     def PythonThreadProc(self):
         self.StartSem.release()
-        res,cmd,blkid = "None","None",ctypes.c_void_p()
-        compile_cache={}
+        res, cmd, blkid = "None", "None", ctypes.c_void_p()
+        compile_cache = {}
         while True:
             # print "_PythonIterator(", res, ")",
-            cmd = self._PythonIterator(res,blkid)
+            cmd = self._PythonIterator(res, blkid)
             FBID = blkid.value
             # print " -> ", cmd, blkid
             if cmd is None:
                 break
-            try :
-                self.python_runtime_vars["FBID"]=FBID
-                ccmd,AST =compile_cache.get(FBID, (None,None))
-                if ccmd is None or ccmd!=cmd:
+            try:
+                self.python_runtime_vars["FBID"] = FBID
+                ccmd, AST = compile_cache.get(FBID, (None, None))
+                if ccmd is None or ccmd != cmd:
                     AST = compile(cmd, '<plc>', 'eval')
-                    compile_cache[FBID]=(cmd,AST)
-                result,exp = self.evaluator(eval,AST,self.python_runtime_vars)
+                    compile_cache[FBID] = (cmd, AST)
+                result, exp = self.evaluator(eval, AST, self.python_runtime_vars)
                 if exp is not None:
                     res = "#EXCEPTION : "+str(exp[1])
-                    self.LogMessage(1,('PyEval@0x%x(Code="%s") Exception "%s"')%(FBID,cmd,
-                        '\n'.join(traceback.format_exception(*exp))))
+                    self.LogMessage(1, ('PyEval@0x%x(Code="%s") Exception "%s"') % (
+                        FBID, cmd, '\n'.join(traceback.format_exception(*exp))))
                 else:
-                    res=str(result)
-                self.python_runtime_vars["FBID"]=None
-            except Exception,e:
+                    res = str(result)
+                self.python_runtime_vars["FBID"] = None
+            except Exception, e:
                 res = "#EXCEPTION : "+str(e)
-                self.LogMessage(1,('PyEval@0x%x(Code="%s") Exception "%s"')%(FBID,cmd,str(e)))
+                self.LogMessage(1, ('PyEval@0x%x(Code="%s") Exception "%s"') % (FBID, cmd, str(e)))
 
     def StartPLC(self):
         if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped":
             c_argv = ctypes.c_char_p * len(self.argv)
             error = None
-            res = self._startPLC(len(self.argv),c_argv(*self.argv))
+            res = self._startPLC(len(self.argv), c_argv(*self.argv))
             if res == 0:
                 self.PLCStatus = "Started"
                 self.StatusChange()
                 self.PythonRuntimeCall("start")
-                self.StartSem=Semaphore(0)
+                self.StartSem = Semaphore(0)
                 self.PythonThread = Thread(target=self.PythonThreadProc)
                 self.PythonThread.start()
                 self.StartSem.acquire()
                 self.LogMessage("PLC started")
             else:
-                self.LogMessage(0,_("Problem starting PLC : error %d" % res))
+                self.LogMessage(0, _("Problem starting PLC : error %d" % res))
                 self.PLCStatus = "Broken"
                 self.StatusChange()
 
@@ -378,7 +384,7 @@
             self.PLCStatus = "Stopped"
             self.StatusChange()
             self.PythonRuntimeCall("stop")
-            if self.TraceThread is not None :
+            if self.TraceThread is not None:
                 self.TraceWakeup.set()
                 self.TraceThread.join()
                 self.TraceThread = None
@@ -388,26 +394,26 @@
     def _Reload(self):
         self.daemon.shutdown(True)
         self.daemon.sock.close()
-        os.execv(sys.executable,[sys.executable]+sys.argv[:])
+        os.execv(sys.executable, [sys.executable]+sys.argv[:])
         # never reached
         return 0
 
     def ForceReload(self):
         # respawn python interpreter
-        Timer(0.1,self._Reload).start()
+        Timer(0.1, self._Reload).start()
         return True
 
     def GetPLCstatus(self):
-        return self.PLCStatus, map(self.GetLogCount,xrange(LogLevelsCount))
+        return self.PLCStatus, map(self.GetLogCount, xrange(LogLevelsCount))
 
     def NewPLC(self, md5sum, data, extrafiles):
         if self.PLCStatus in ["Stopped", "Empty", "Broken"]:
             NewFileName = md5sum + lib_ext
-            extra_files_log = os.path.join(self.workingdir,"extra_files.txt")
+            extra_files_log = os.path.join(self.workingdir, "extra_files.txt")
 
             self.UnLoadPLC()
 
-            self.LogMessage("NewPLC (%s)"%md5sum)
+            self.LogMessage("NewPLC (%s)" % md5sum)
             self.PLCStatus = "Empty"
 
             try:
@@ -416,14 +422,14 @@
                 for filename in file(extra_files_log, "r").readlines() + [extra_files_log]:
                     try:
                         os.remove(os.path.join(self.workingdir, filename.strip()))
-                    except:
+                    except Exception:
                         pass
-            except:
+            except Exception:
                 pass
 
             try:
                 # Create new PLC file
-                open(os.path.join(self.workingdir,NewFileName),
+                open(os.path.join(self.workingdir, NewFileName),
                      'wb').write(data)
 
                 # Store new PLC filename based on md5 key
@@ -431,14 +437,14 @@
 
                 # Then write the files
                 log = file(extra_files_log, "w")
-                for fname,fdata in extrafiles:
-                    fpath = os.path.join(self.workingdir,fname)
+                for fname, fdata in extrafiles:
+                    fpath = os.path.join(self.workingdir, fname)
                     open(fpath, "wb").write(fdata)
                     log.write(fname+'\n')
 
                 # Store new PLC filename
                 self.CurrentPLCFilename = NewFileName
-            except:
+            except Exception:
                 self.PLCStatus = "Broken"
                 self.StatusChange()
                 PLCprint(traceback.format_exc())
@@ -458,7 +464,7 @@
         try:
             last_md5 = open(self._GetMD5FileName(), "r").read()
             return last_md5 == MD5
-        except:
+        except Exception:
             pass
         return False
 
@@ -472,12 +478,12 @@
             if self._suspendDebug(False) == 0:
                 # keep a copy of requested idx
                 self._ResetDebugVariables()
-                for idx,iectype,force in idxs:
-                    if force !=None:
-                        c_type,unpack_func, pack_func = \
+                for idx, iectype, force in idxs:
+                    if force is not None:
+                        c_type, unpack_func, pack_func = \
                             TypeTranslator.get(iectype,
-                                                    (None,None,None))
-                        force = ctypes.byref(pack_func(c_type,force))
+                                               (None, None, None))
+                        force = ctypes.byref(pack_func(c_type, force))
                     self._RegisterDebugVariable(idx, force)
                 self._TracesSwap()
                 self._resumeDebug()
@@ -487,7 +493,7 @@
     def _TracesPush(self, trace):
         self.TraceLock.acquire()
         lT = len(self.Traces)
-        if lT != 0 and lT * len(self.Traces[0]) > 1024 * 1024 :
+        if lT != 0 and lT * len(self.Traces[0]) > 1024 * 1024:
             self.Traces.pop(0)
         self.Traces.append(trace)
         self.TraceLock.release()
@@ -511,10 +517,10 @@
             self.TraceLock.acquire()
             self.Traces = []
             self.TraceLock.release()
-            self._suspendDebug(True) # Disable debugger
+            self._suspendDebug(True)  # Disable debugger
             self.TraceWakeup.clear()
             self.TraceWakeup.wait()
-            self._resumeDebug() # Re-enable debugger
+            self._resumeDebug()  # Re-enable debugger
 
     def _TracesFlush(self):
         self.TraceLock.acquire()
@@ -528,7 +534,7 @@
         """
         Return a list of traces, corresponding to the list of required idx
         """
-        while self.PLCStatus == "Started" :
+        while self.PLCStatus == "Started":
             tick = ctypes.c_uint32()
             size = ctypes.c_uint32()
             buff = ctypes.c_void_p()
@@ -546,15 +552,12 @@
             self._TracesAutoSuspend()
         self._TracesFlush()
 
-
     def RemoteExec(self, script, *kwargs):
         try:
             exec script in kwargs
-        except:
+        except Exception:
             e_type, e_value, e_traceback = sys.exc_info()
             line_no = traceback.tb_lineno(get_last_traceback(e_traceback))
             return (-1, "RemoteExec script failed!\n\nLine %d: %s\n\t%s" %
                         (line_no, e_value, script.splitlines()[line_no - 1]))
         return (0, kwargs.get("returnVal", None))
-
-