Added CurveEngine.run_command and reorganized CommandStack._execute
authorW. Trevor King <wking@drexel.edu>
Thu, 12 Aug 2010 15:02:06 +0000 (11:02 -0400)
committerW. Trevor King <wking@drexel.edu>
Thu, 12 Aug 2010 15:02:06 +0000 (11:02 -0400)
hooke/command_stack.py
hooke/curve.py
hooke/engine.py
hooke/hooke.py
hooke/playlist.py

index fc8dc751add0a9bece435ca37c27673ecbd853d0..3888a45e74efca10d1069b26833fecd6eff49fd3 100644 (file)
@@ -44,11 +44,9 @@ class CommandStack (list):
     >>> c.append(CommandMessage(ca, {'param':'C'}))
     >>> c.append(CommandMessage(cb, {'param':'D'}))
 
-    Implement a dummy :meth:`_execute` for testing.  This would
-    usually call :meth:`hooke.command.Command.run` with appropriate
-    arguments.
+    Implement a dummy :meth:`_execute` for testing.
     
-    >>> def execute(command_message):
+    >>> def execute(hooke, command_message):
     ...     cm = command_message
     ...     print 'EXECUTE', cm.command.name, cm.arguments
     >>> c._execute = execute
@@ -74,7 +72,7 @@ class CommandStack (list):
     EXECUTE CommandB {'param': 'B'}
     EXECUTE CommandB {'param': 'D'}
     """
-    def execute(self, *args, **kwargs):
+    def execute(self, hooke):
         """Execute a stack of commands.
 
         See Also
@@ -83,7 +81,7 @@ class CommandStack (list):
         """
         for command_message in self:
             if self.filter(command_message) == True:
-                self._execute(command_message, *args, **kwargs)
+                self._execute(hooke, command_message)
 
     def filter(self, command_message):
         """Any commands in the stack that are not subclasses of
@@ -91,5 +89,5 @@ class CommandStack (list):
         """
         return True
 
-    def _execute(self, command_message):
-        raise NotImplementedError()
+    def _execute(self, hooke, command_message):
+        hooke.run_command(command_message.command, command_message.arguments)
index 552eda6abe5582c2bf3b47f1926a8899f3829e77..34fb34e0135c53f58704fa04f4f889c4c833ae22 100644 (file)
@@ -170,6 +170,11 @@ class Curve (object):
         self.info = info
         self.name = os.path.basename(path)
         self.command_stack = CommandStack()
+        self._hooke = None  # Hooke instance for Curve.load()
+
+    def set_hooke(self, hooke=None):
+        if hooke != None:
+            self._hooke = hooke
 
     def identify(self, drivers):
         """Identify the appropriate :class:`hooke.driver.Driver` for
@@ -188,18 +193,21 @@ class Curve (object):
                 return
         raise NotRecognized(self)
 
-    def load(self, *args, **kwargs):
+    def load(self, hooke=None):
         """Use the driver to read the curve into memory.
 
         Also runs any commands in :attr:`command_stack`.  All
         arguments are passed through to
         :meth:`hooke.command_stack.CommandStack.execute`.
         """
+        self.set_hooke(hooke)
         data,info = self.driver.read(self.path, self.info)
         self.data = data
         for key,value in info.items():
             self.info[key] = value
-        self.command_stack.execute(*args, **kwargs)
+        if self.hooke != None:
+            # TODO: set 'curve' argument explicitly for CurveCommands
+            self.command_stack.execute(self.hooke)
 
     def unload(self):
         """Release memory intensive :attr:`.data`.
index 90c652ed47f40bbee51ceb3f53dd93257a6235f1..b4381298178f59723b540cfc901a7968ac93e1c1 100644 (file)
@@ -22,6 +22,8 @@
 
 import logging
 
+from .command import NullQueue
+
 
 class QueueMessage (object):
     def __str__(self):
@@ -73,3 +75,15 @@ class CommandEngine (object):
             log.debug('engine running %s' % msg.command.name)
             msg.command.run(hooke, ui_to_command_queue, command_to_ui_queue,
                             **msg.arguments)
+
+    def run_command(self, hooke, command, arguments):
+        """Internal command execution.
+
+        This allows commands to execute sub commands and enables
+        :class:`~hooke.command_stack.CommandStack` execution.
+
+        Note that these commands *do not* have access to the usual UI
+        communication queues, so make sure they will not need user
+        interaction.
+        """
+        command.run(hooke, NullQueue(), NullQueue(), arguments)
index 54f0f0fb695b7ec734f0ee91ff7d5d526b5d8f78..a8079a9a2e498ca19b0db75730ab4cd8bc202252 100644 (file)
@@ -90,7 +90,7 @@ class Hooke (object):
         self.load_plugins()
         self.load_drivers()
         self.load_ui()
-        self.command = engine.CommandEngine()
+        self.engine = engine.CommandEngine()
         self.playlists = playlist.NoteIndexList()
 
     def load_log(self):
@@ -118,6 +118,16 @@ class Hooke (object):
     def close(self):
         self.config.write() # Does not preserve original comments
 
+    def run_command(self, command, arguments):
+        """Run `command` with `arguments` using
+        :meth:`~hooke.engine.CommandEngine.run_command`.
+
+        Allows for running commands without spawning another process
+        as in :class:`HookeRunner`.
+        """
+        self.engine.run_command(self, command, arguments)
+
+
 class HookeRunner (object):
     def run(self, hooke):
         """Run Hooke's main execution loop.
@@ -153,7 +163,7 @@ class HookeRunner (object):
         command_to_ui = multiprocessing.Queue()
         manager = multiprocessing.Manager()
         command = multiprocessing.Process(name='command engine',
-            target=hooke.command.run, args=(hooke, ui_to_command, command_to_ui))
+            target=hooke.engine.run, args=(hooke, ui_to_command, command_to_ui))
         command.start()
         return (ui_to_command, command_to_ui, command)
 
index 906cb061a7c089220cfb49e07b679dd880c12b8a..d3ca4c6f2bfc3996b3f80462116deef0afc1a1dd 100644 (file)
@@ -118,8 +118,6 @@ class Playlist (NoteIndexList):
         self.drivers = drivers
         self._loaded = [] # List of loaded curves, see :meth:`._setup_item`.
         self._max_loaded = 100 # curves to hold in memory simultaneously.
-        self._curve_load_args = ()
-        self._curve_load_kwargs = {}
 
     def append_curve_by_path(self, path, info=None, identify=True):
         path = os.path.normpath(path)
@@ -129,10 +127,6 @@ class Playlist (NoteIndexList):
         self.append(c)
         return c
 
-    def set_curve_load_args(self, *args, **kwargs):
-        self._curve_load_args = args
-        self._curve_load_kwargs = kwargs
-
     def _setup_item(self, curve):
         if curve != None and curve not in self._loaded:
             if curve not in self:
@@ -140,7 +134,7 @@ class Playlist (NoteIndexList):
             if curve.driver == None:
                 c.identify(self.drivers)
             if curve.data == None:
-                curve.load(*self._curve_load_args, **self._curve_load_kwargs)
+                curve.load()
             self._loaded.append(curve)
             if len(self._loaded) > self._max_loaded:
                 oldest = self._loaded.pop(0)