use the enum module to represent states
[~helmut/onoff.git] / onoff / command.py
index c3dd4a6..7a40bbd 100644 (file)
@@ -1,25 +1,42 @@
 import logging
 
-from gi.repository import GObject
-
-from .common import OnoffDevice, ST_ACTIVE, ST_TRANSITION
+from .common import OnoffDevice, OnoffState
+from .gobject import spawn_child
 
 logger = logging.getLogger("onoff.command")
 
 class OnoffCommand(OnoffDevice):
+    """A device that is enabled and disabled by executing separate commands.
+    The transition period is the duration of the commands.
+    @type pid: int or None
+    @ivar pid: is either None or the pid of a transition command as long as
+            it lives.
+    @type desired_state: bool
+    @ivar desired_state: is the state that should be transitioned to
+    @type target_state: bool
+    @ivar target_state: is the state that we are currently transitioning to
+    """
     def __init__(self, oncommand, offcommand):
+        """
+
+        @type oncommand: [str]
+        @param oncommand: an argument vector to be executed for activation.
+        @type offcommand: [str]
+        @param offcommand: an argument vector to be executed for deactivation.
+        @note: For both commands the first element is used as executable and
+                looked up in $PATH.
+        """
         OnoffDevice.__init__(self)
         self.oncommand = oncommand
         self.offcommand = offcommand
-        self.desired_state = 0 # bit mask of just ST_ACTIVE
+        self.desired_state = OnoffState.inactive
         self.pid = None
-        self.watch = None
-        self.target_state = 0 # state the last command targeted
+        self.target_state = OnoffState.inactive  # last command target state
 
     @property
     def state(self):
         if self.pid is not None:
-            return self.desired_state | ST_TRANSITION
+            return self.desired_state | OnoffState.transition
         return self.desired_state
 
     def transition(self, state):
@@ -27,34 +44,31 @@ class OnoffCommand(OnoffDevice):
                          (self.oncommand, "oncommand")][state]
         self.target_state = state
         logger.info("invoking %s %s", name, " ".join(command))
-        ret = GObject.spawn_async(command, flags=GObject.SPAWN_SEARCH_PATH | GObject.SPAWN_DO_NOT_REAP_CHILD)
-        self.pid = ret[0]
-        assert self.pid
+        self.pid = spawn_child(command, self.process_died)
         logger.debug("started %s as pid %d", name, self.pid)
-        self.watch = GObject.child_watch_add(self.pid, self.process_died)
         self.changestate(self.state)
 
     def process_died(self, pid, condition):
         assert self.pid == pid
-        assert self.watch is not None
-        self.watch = None
         self.pid = None
-        logger.info("command %d targeting %d completed", pid, self.target_state)
+        logger.info("command %d targeting %s completed", pid,
+                    self.target_state.name)
         if self.desired_state == self.target_state:
             self.changestate(self.state)
         else:
-            logger.info("desired state changed to %d during invocation " +
-                        "targeting %d", self.desired_state, self.target_state)
+            logger.info("desired state changed to %s during invocation " +
+                        "targeting %s", self.desired_state.name,
+                        self.target_state.name)
             self.transition(self.desired_state)
 
     def activate(self):
-        if self.desired_state != ST_ACTIVE:
-            self.desired_state = ST_ACTIVE
+        if self.desired_state != OnoffState.active:
+            self.desired_state = OnoffState.active
             if self.pid is None:
                 self.transition(self.desired_state)
 
     def deactivate(self):
-        if self.desired_state != 0:
-            self.desired_state = 0
+        if self.desired_state != OnoffState.inactive:
+            self.desired_state = OnoffState.inactive
             if self.pid is None:
                 self.transition(self.desired_state)