save supposed afterEvent config in class Job member (fixes #394 DVDBurn shutdown...
[enigma2.git] / lib / python / Components / Task.py
index d5fffbc66b4da2f07358e1eca212d55084f8536c..2e4e757de86525bdc2054d3535d8263d43f32de9 100644 (file)
@@ -16,6 +16,7 @@ class Job(object):
                self.end = 100
                self.__progress = 0
                self.weightScale = 1
+               self.afterEvent = None
 
                self.state_changed = CList()
 
@@ -37,11 +38,15 @@ class Job(object):
 
        progress = property(getProgress)
 
+       def getStatustext(self):
+               return { self.NOT_STARTED: _("Waiting"), self.IN_PROGRESS: _("In Progress"), self.FINISHED: _("Finished"), self.FAILED: _("Failed") }[self.status]
+
        def task_progress_changed_CB(self):
                self.state_changed()
 
        def addTask(self, task):
                task.job = self
+               task.task_progress_changed = self.task_progress_changed_CB
                self.tasks.append(task)
 
        def start(self, callback):
@@ -53,7 +58,7 @@ class Job(object):
                self.status = self.IN_PROGRESS
                self.state_changed()
                self.runNext()
-               sumTaskWeightings = sum([t.weighting for t in self.tasks])
+               sumTaskWeightings = sum([t.weighting for t in self.tasks]) or 1
                self.weightScale = self.end / float(sumTaskWeightings)
 
        def runNext(self):
@@ -67,7 +72,7 @@ class Job(object):
                        else:
                                print "still waiting for %d resident task(s) %s to finish" % (len(self.resident_tasks), str(self.resident_tasks))
                else:
-                       self.tasks[self.current_task].run(self.taskCallback, self.task_progress_changed_CB)
+                       self.tasks[self.current_task].run(self.taskCallback)
                        self.state_changed()
 
        def taskCallback(self, task, res, stay_resident = False):
@@ -123,9 +128,11 @@ class Task(object):
                self.cmd = None
                self.cwd = "/tmp"
                self.args = [ ]
+               self.cmdline = None
                self.task_progress_changed = None
                self.output_line = ""
                job.addTask(self)
+               self.container = None
 
        def setCommandline(self, cmd, args):
                self.cmd = cmd
@@ -137,6 +144,9 @@ class Task(object):
                self.global_preconditions.append(ToolExistsPrecondition())
                self.postconditions.append(ReturncodePostcondition())
 
+       def setCmdline(self, cmdline):
+               self.cmdline = cmdline
+
        def checkPreconditions(self, immediate = False):
                not_met = [ ]
                if immediate:
@@ -148,7 +158,7 @@ class Task(object):
                                not_met.append(precondition)
                return not_met
 
-       def run(self, callback, task_progress_changed):
+       def run(self, callback):
                failed_preconditions = self.checkPreconditions(True) + self.checkPreconditions(False)
                if len(failed_preconditions):
                        callback(self, failed_preconditions)
@@ -156,20 +166,21 @@ class Task(object):
                self.prepare()
 
                self.callback = callback
-               self.task_progress_changed = task_progress_changed
                from enigma import eConsoleAppContainer
                self.container = eConsoleAppContainer()
-               self.container.appClosed.get().append(self.processFinished)
-               self.container.stdoutAvail.get().append(self.processStdout)
-               self.container.stderrAvail.get().append(self.processStderr)
-
-               assert self.cmd is not None
-               assert len(self.args) >= 1
+               self.container.appClosed.append(self.processFinished)
+               self.container.stdoutAvail.append(self.processStdout)
+               self.container.stderrAvail.append(self.processStderr)
 
                if self.cwd is not None:
                        self.container.setCWD(self.cwd)
 
-               print "execute:", self.container.execute(self.cmd, self.args), self.cmd, " ".join(self.args)
+               if not self.cmd and self.cmdline:
+                       print "execute:", self.container.execute(self.cmdline), self.cmdline
+               else:
+                       assert self.cmd is not None
+                       assert len(self.args) >= 1
+                       print "execute:", self.container.execute(self.cmd, *self.args), ' '.join(self.args)
                if self.initial_input:
                        self.writeInput(self.initial_input)
 
@@ -202,7 +213,8 @@ class Task(object):
                self.finish()
 
        def abort(self):
-               self.container.kill()
+               if self.container:
+                       self.container.kill()
                self.finish(aborted = True)
 
        def finish(self, aborted = False):
@@ -232,7 +244,8 @@ class Task(object):
                if progress < 0:
                        progress = 0
                self.__progress = progress
-               self.task_progress_changed()
+               if self.task_progress_changed:
+                       self.task_progress_changed()
 
        progress = property(getProgress, setProgress)
 
@@ -244,6 +257,7 @@ class JobManager:
                self.active_jobs = [ ]
                self.failed_jobs = [ ]
                self.job_classes = [ ]
+               self.in_background = False
                self.active_job = None
 
        def AddJob(self, job):
@@ -258,10 +272,18 @@ class JobManager:
 
        def jobDone(self, job, task, problems):
                print "job", job, "completed with", problems, "in", task
+               from Tools import Notifications
+               if self.in_background:
+                       from Screens.TaskView import JobView
+                       self.in_background = False
+                       Notifications.AddNotification(JobView, self.active_job)
                if problems:
-                       from Tools import Notifications
                        from Screens.MessageBox import MessageBox
-                       Notifications.AddNotificationWithCallback(self.errorCB, MessageBox, _("Error: %s\nRetry?") % (problems[0].getErrorMessage(task)))
+                       if problems[0].RECOVERABLE:
+                               Notifications.AddNotificationWithCallback(self.errorCB, MessageBox, _("Error: %s\nRetry?") % (problems[0].getErrorMessage(task)))
+                       else:
+                               Notifications.AddNotification(MessageBox, _("Error") + (': %s') % (problems[0].getErrorMessage(task)), type = MessageBox.TYPE_ERROR )
+                               self.errorCB(False)
                        return
                        #self.failed_jobs.append(self.active_job)
 
@@ -278,6 +300,12 @@ class JobManager:
                        self.active_job = None
                        self.kick()
 
+       def getPendingJobs(self):
+               list = [ ]
+               if self.active_job:
+                       list.append(self.active_job)
+               list += self.active_jobs
+               return list
 # some examples:
 #class PartitionExistsPostcondition:
 #      def __init__(self, device):
@@ -317,7 +345,7 @@ class Condition:
        RECOVERABLE = False
 
        def getErrorMessage(self, task):
-               return _("An error has occured. (%s)") % (self.__class__.__name__)
+               return _("An unknown error occured!") + " (%s @ task %s)" % (self.__class__.__name__, task.__class__.__name__)
 
 class WorkspaceExistsPrecondition(Condition):
        def check(self, task):
@@ -343,18 +371,27 @@ class DiskspacePrecondition(Condition):
 class ToolExistsPrecondition(Condition):
        def check(self, task):
                import os
+               
                if task.cmd[0]=='/':
-                       realpath = task.cmd
+                       self.realpath = task.cmd
+                       print "[Task.py][ToolExistsPrecondition] WARNING: usage of absolute paths for tasks should be avoided!" 
+                       return os.access(self.realpath, os.X_OK)
                else:
-                       realpath = task.cwd + '/' + task.cmd
-               self.realpath = realpath
-               return os.access(realpath, os.X_OK)
+                       self.realpath = task.cmd
+                       path = os.environ.get('PATH', '').split(os.pathsep)
+                       path.append(task.cwd + '/')
+                       absolutes = filter(lambda file: os.access(file, os.X_OK), map(lambda directory, file = task.cmd: os.path.join(directory, file), path))
+                       if len(absolutes) > 0:
+                               self.realpath = task.cmd[0]
+                               return True
+               return False 
 
        def getErrorMessage(self, task):
                return _("A required tool (%s) was not found.") % (self.realpath)
 
 class AbortedPostcondition(Condition):
-       pass
+       def getErrorMessage(self, task):
+               return "Cancelled upon user request"
 
 class ReturncodePostcondition(Condition):
        def check(self, task):