Runtime: add GetVersions() call to PLCObject, use it in web settings and expose it in WAMP and Pyro.
authorEdouard Tisserant
Wed, 29 Nov 2023 11:54:56 +0100
changeset 3861 7e17f7e02a2b
parent 3860 a1d7187b8402
child 3881 0b3ac94f494c
Runtime: add GetVersions() call to PLCObject, use it in web settings and expose it in WAMP and Pyro.

Note: WAMP changes are untested
connectors/ConnectorBase.py
connectors/PYRO/__init__.py
connectors/WAMP/__init__.py
runtime/NevowServer.py
runtime/PLCObject.py
--- a/connectors/ConnectorBase.py	Fri Nov 24 12:16:19 2023 +0100
+++ b/connectors/ConnectorBase.py	Wed Nov 29 11:54:56 2023 +0100
@@ -5,12 +5,21 @@
 
 from __future__ import absolute_import
 import hashlib
+from runtime import PlcStatus
 
 
 class ConnectorBase(object):
 
     chuncksize = 1024*1024
 
+    PLCObjDefaults = {
+        "StartPLC": False,
+        "GetTraceVariables": (PlcStatus.Broken, None),
+        "GetPLCstatus": (PlcStatus.Broken, None),
+        "RemoteExec": (-1, "RemoteExec script failed!"),
+        "GetVersions": "*** Unknown ***"
+    }
+
     def BlobFromFile(self, filepath, seed):
         s = hashlib.new('md5')
         s.update(seed)
--- a/connectors/PYRO/__init__.py	Fri Nov 24 12:16:19 2023 +0100
+++ b/connectors/PYRO/__init__.py	Wed Nov 29 11:54:56 2023 +0100
@@ -38,7 +38,6 @@
 
 import PSKManagement as PSK
 from connectors.PYRO.PSK_Adapter import setupPSKAdapter
-from runtime import PlcStatus
 
 
 def switch_pyro_adapter(use_ssl):
@@ -88,6 +87,9 @@
 
     RemotePLCObjectProxy.adapter.setTimeout(60)
 
+    class MissingCallException(Exception):
+        pass
+
     def PyroCatcher(func, default=None):
         """
         A function that catch a Pyro exceptions, write error to logger
@@ -101,6 +103,8 @@
                 confnodesroot.logger.write_error(_("Connection lost!\n"))
             except Pyro.errors.ProtocolError as e:
                 confnodesroot.logger.write_error(_("Pyro exception: %s\n") % e)
+            except MissingCallException as e:
+                confnodesroot.logger.write_warning(_("Remote call not supported: %s\n") % e.message)
             except Exception as e:
                 # confnodesroot.logger.write_error(traceback.format_exc())
                 errmess = ''.join(Pyro.util.getPyroTraceback(e))
@@ -119,13 +123,6 @@
         ID, secret = IDPSK
         PSK.UpdateID(confnodesroot.ProjectPath, ID, secret, uri)
 
-    _special_return_funcs = {
-        "StartPLC": False,
-        "GetTraceVariables": (PlcStatus.Broken, None),
-        "GetPLCstatus": (PlcStatus.Broken, None),
-        "RemoteExec": (-1, "RemoteExec script failed!")
-    }
-
     class PyroProxyProxy(object):
         """
         A proxy proxy class to handle Beremiz Pyro interface specific behavior.
@@ -135,8 +132,12 @@
             member = self.__dict__.get(attrName, None)
             if member is None:
                 def my_local_func(*args, **kwargs):
-                    return RemotePLCObjectProxy.__getattr__(attrName)(*args, **kwargs)
-                member = PyroCatcher(my_local_func, _special_return_funcs.get(attrName, None))
+                    call = RemotePLCObjectProxy.__getattr__(attrName)
+                    if call is None:
+                        raise MissingCallException(attrName)
+                    else:
+                        return call(*args, **kwargs)
+                member = PyroCatcher(my_local_func, self.PLCObjDefaults.get(attrName, None))
                 self.__dict__[attrName] = member
             return member
 
--- a/connectors/WAMP/__init__.py	Fri Nov 24 12:16:19 2023 +0100
+++ b/connectors/WAMP/__init__.py	Wed Nov 29 11:54:56 2023 +0100
@@ -38,7 +38,6 @@
 from autobahn.wamp.exception import TransportLost
 from autobahn.wamp.serializer import MsgPackSerializer
 
-from runtime import PlcStatus
 
 _WampSession = None
 _WampConnection = None
@@ -59,14 +58,6 @@
         print('WAMP session left')
 
 
-PLCObjDefaults = {
-    "StartPLC":          False,
-    "GetTraceVariables": ("Broken", None),
-    "GetPLCstatus":      (PlcStatus.Broken, None),
-    "RemoteExec":        (-1, "RemoteExec script failed!")
-}
-
-
 def _WAMP_connector_factory(cls, uri, confnodesroot):
     """
     WAMP://127.0.0.1:12345/path#realm#ID
@@ -110,26 +101,6 @@
         AddToDoBeforeQuit(reactor.stop)
         reactor.run(installSignalHandlers=False)
 
-    def WampSessionProcMapper(funcname):
-        wampfuncname = text('.'.join((ID, funcname)))
-
-        def catcher_func(*args, **kwargs):
-            if _WampSession is not None:
-                try:
-                    return threads.blockingCallFromThread(
-                        reactor, _WampSession.call, wampfuncname,
-                        *args, **kwargs)
-                except TransportLost:
-                    confnodesroot.logger.write_error(_("Connection lost!\n"))
-                    confnodesroot._SetConnector(None)
-                except Exception:
-                    errmess = traceback.format_exc()
-                    confnodesroot.logger.write_error(errmess+"\n")
-                    print(errmess)
-                    # confnodesroot._SetConnector(None)
-            return PLCObjDefaults.get(funcname)
-        return catcher_func
-
     class WampPLCObjectProxy(object):
         def __init__(self):
             global _WampConnection
@@ -147,10 +118,30 @@
             #
             # reactor.stop()
 
+        def WampSessionProcMapper(self, funcname):
+            wampfuncname = text('.'.join((ID, funcname)))
+
+            def catcher_func(*args, **kwargs):
+                if _WampSession is not None:
+                    try:
+                        return threads.blockingCallFromThread(
+                            reactor, _WampSession.call, wampfuncname,
+                            *args, **kwargs)
+                    except TransportLost:
+                        confnodesroot.logger.write_error(_("Connection lost!\n"))
+                        confnodesroot._SetConnector(None)
+                    except Exception:
+                        errmess = traceback.format_exc()
+                        confnodesroot.logger.write_error(errmess+"\n")
+                        print(errmess)
+                        # confnodesroot._SetConnector(None)
+                return self.PLCObjDefaults.get(funcname)
+            return catcher_func
+
         def __getattr__(self, attrName):
             member = self.__dict__.get(attrName, None)
             if member is None:
-                member = WampSessionProcMapper(attrName)
+                member = self.WampSessionProcMapper(attrName)
                 self.__dict__[attrName] = member
             return member
 
--- a/runtime/NevowServer.py	Fri Nov 24 12:16:19 2023 +0100
+++ b/runtime/NevowServer.py	Wed Nov 29 11:54:56 2023 +0100
@@ -28,7 +28,6 @@
 import os
 import collections
 import shutil
-import platform as platform_module
 from zope.interface import implements
 from nevow import appserver, inevow, tags, loaders, athena, url, rend
 from nevow.page import renderer
@@ -208,18 +207,9 @@
     extensions_settings_od.pop(token)
 
 
-def originalGetVersions():
-    return platform_module.system() + " " + platform_module.release()
-
-_getVersions = originalGetVersions
-
-def setVersionsCallable(versionsCallable):
-    global _getVersions
-    _getVersions = versionsCallable
-
 class ISettings(annotate.TypedInterface):
     platform = annotate.String(label=_("Platform"),
-                               default=lambda *a,**k:_getVersions(),
+                               default=lambda *a,**k:GetPLCObjectSingleton().GetVersions(),
                                immutable=True)
 
     # pylint: disable=no-self-argument
--- a/runtime/PLCObject.py	Fri Nov 24 12:16:19 2023 +0100
+++ b/runtime/PLCObject.py	Wed Nov 29 11:54:56 2023 +0100
@@ -29,6 +29,7 @@
 import sys
 import traceback
 import shutil
+import platform as platform_module
 from time import time
 import hashlib
 from tempfile import mkstemp
@@ -811,3 +812,7 @@
             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))
+
+    def GetVersions(self):
+        return platform_module.system() + " " + platform_module.release()
+