瀏覽代碼

RealtimeInterrupts now work with more than strings

rparedis 1 月之前
父節點
當前提交
89e95374c5

二進制
pypdevs.tgz


+ 1 - 9
src/pypdevs/basesimulator.py

@@ -1098,15 +1098,7 @@ class BaseSimulator(Solver):
                     self.threading_backend.wait(wait_time, self.runsim)
                 return True
             try:
-                info = interrupt.split(" ")
-                portname = info[0]
-                event_value = " ".join(info[1:])
-                if event_value[0] in "([{":  # also allow tuples, lists or dictionaries
-                    try:
-                        event_value = eval(event_value)
-                    except: pass
-                # event_value = eval(" ".join(info[1:]))
-                # portname, event_value = interrupt.split(" ")
+                portname, event_value = interrupt
                 event_port = self.portmap[portname]
             except ValueError:
                 # Couldn't split, means we should stop

+ 9 - 4
src/pypdevs/controller.py

@@ -570,17 +570,22 @@ class Controller(BaseSimulator):
         """
         self.threading_backend.step()
 
-    def realtimeInterrupt(self, string):
+    def realtimeInterrupt(self, string: str, event=None):
         """
         Create an interrupt from other Python code instead of using stdin or the file
 
-        :param string: the value to inject
+        :param string: the value to inject, as `portname value`
+        :param event: optional event/object to pass onto the port. Will only be used if the string is a single portname
         """
-        self.threading_backend.interrupt(string)
+        action = string.split(" ", 1)
+        if len(action) > 1:
+            event = action[1]
+        self.threading_backend.interrupt(action[0], event)
 
     def stateChange(self, model_id, variable, value):
         """
-        Notification function for when a variable's value is altered. It will notify the node that is responsible for simulation of this model AND also notify the tracers of the event.
+        Notification function for when a variable's value is altered. It will notify the node that is responsible for
+        simulation of this model AND also notify the tracers of the event.
 
         :param model_id: the model_id of the model whose variable was changed
         :param variable: the name of the variable that was changed (as a string)

+ 1 - 1
src/pypdevs/realtime/asynchronousComboGenerator.py

@@ -73,7 +73,7 @@ class AsynchronousComboGenerator(object):
                         raise DEVSException(
                             "Inproperly formatted input in file: %s" % event)
                     self.next_scheduled = float(event[0])
-                    self.file_event = event[1].rstrip()
+                    self.file_event = event[1].rstrip().split(" ", 1)
 
     def getNextTime(self):
         """

+ 8 - 4
src/pypdevs/realtime/threadingBackend.py

@@ -49,20 +49,24 @@ class ThreadingBackend(object):
         """
         self.subsystem.wait(time, func)
 
-    def interrupt(self, value):
+    def interrupt(self, pname, value):
         """
         Interrupt a running wait call, overwriting any previous interrupts.
 
+        :param pname: the port on which the interrupt happens
         :param value: the value that interrupts
         """
-        self.interrupted_value = value
+        self.interrupted_value = pname, value
         self.subsystem.interrupt()
 
     def setInterrupt(self, value):
         """
-        Sets the value of the interrupt. This should not be used manually and is only required to prevent the asynchronous combo generator from making *interrrupt()* calls.
+        Sets the value of the interrupt.
+        This should not be used manually and is only required to prevent the asynchronous combo generator
+        from making *interrrupt()* calls.
         
-        :param value: value with which the interrupt variable should be set
+        :param value:   value with which the interrupt variable should be set;
+                        should be a space-separated string of `portname event`.
         """
         with self.value_lock:
             if self.interrupted_value is None:

+ 1 - 1
src/pypdevs/simulator.py

@@ -656,7 +656,7 @@ class Simulator(object):
         self.fillchar = "=" if len(locations) > 1 else "#"
         gvt = 0.0
         while 1:
-            # Several dirty checks for whether or not the simulation is done, if it is finished no more calls should be needed
+            # Several dirty checks for whether the simulation is done, if it is finished no more calls should be needed
             # Keep doing this until the main thread exits, this should be a thread!
             if self.checkpoint_interval > -1:
                 # Don't use an event while checkpointing, as this is unpicklable

+ 3 - 1
src/pypdevs/util.py

@@ -125,7 +125,9 @@ def easyCommand(function, args):
         if i != 0:
             text += ", "
         if isinstance(args[i], str):
-            args[i] = '"%s"' % args[i][1:-1].replace('"', "\\\"").replace("'", "\\'")
+            if len(args[i]) > 0 and args[i][0] == args[i][-1] and args[i][0] in '"\'':
+                s = args[i][0]
+                args[i] = (s + '%s' + s) % args[i][1:-1].replace('"', "\\\"").replace("'", "\\'")
         text += str(args[i])
     text += ")"
     return text

+ 1 - 1
test/testRealtime.py

@@ -82,7 +82,7 @@ def runLocal(name):
     removeFile(outfile)
     import subprocess
     try:
-        proc = subprocess.Popen("python testmodels/experiment.py " + str(name) + "_local >> /dev/null", shell=True)
+        proc = subprocess.Popen("python testmodels/experiment.py " + str(name) + "_local", shell=True)
         proc.wait()
     except:
         import sys