Create Taskmaster.{Always,OutOfDate}Task subclasses of Taskmaster.Task
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 8 Dec 2008 19:04:22 +0000 (19:04 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 8 Dec 2008 19:04:22 +0000 (19:04 +0000)
to hold different implementations of the .needs_execute() method.

git-svn-id: http://scons.tigris.org/svn/scons/trunk@3817 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/JobTests.py
src/engine/SCons/SConf.py
src/engine/SCons/Script/Main.py
src/engine/SCons/Taskmaster.py

index b2a195ead4b56db5042b9a0aaff0ba04ac9e0a2b..852cb91592dcbdf16f3e1faab6af8c42db402172 100644 (file)
@@ -437,7 +437,9 @@ class _SConsTaskTest(unittest.TestCase):
         for tnum in range(num_tasks):
             testnodes.append(node_seq[tnum % len(node_seq)]())
 
-        taskmaster = SCons.Taskmaster.Taskmaster(testnodes)
+        taskmaster = SCons.Taskmaster.Taskmaster(testnodes,
+                                                 tasker=SCons.Taskmaster.AlwaysTask)
+
         jobs = SCons.Job.Jobs(num_jobs, taskmaster)
 
         # Exceptions thrown by tasks are not actually propagated to
index 25fc2bcffa14451f20ffb01a14ff8514f89dac57..6461dda92652b1e278263cd585e70f6ddc972cfc 100644 (file)
@@ -203,7 +203,7 @@ class Streamer:
         self.s.flush()
         
 
-class SConfBuildTask(SCons.Taskmaster.Task):
+class SConfBuildTask(SCons.Taskmaster.AlwaysTask):
     """
     This is almost the same as SCons.Script.BuildTask. Handles SConfErrors
     correctly and knows about the current cache_mode.
index 25e73dcedf4dc66d95e6c8526a088f55457e13a6..db712e6e16e85d5a585beaaeca21edc4728002d4 100644 (file)
@@ -155,7 +155,7 @@ _BuildFailures = []
 def GetBuildFailures():
     return _BuildFailures
 
-class BuildTask(SCons.Taskmaster.Task):
+class BuildTask(SCons.Taskmaster.OutOfDateTask):
     """An SCons build task."""
     progress = ProgressObject
 
@@ -164,16 +164,14 @@ class BuildTask(SCons.Taskmaster.Task):
 
     def prepare(self):
         self.progress(self.targets[0])
-        return SCons.Taskmaster.Task.prepare(self)
+        return SCons.Taskmaster.OutOfDateTask.prepare(self)
 
     def needs_execute(self):
-        target = self.targets[0]
-        if target.get_state() == SCons.Node.executing:
+        if SCons.Taskmaster.OutOfDateTask.needs_execute(self):
             return True
-        else:
-            if self.top and target.has_builder():
-                display("scons: `%s' is up to date." % str(self.node))
-            return False
+        if self.top and self.targets[0].has_builder():
+            display("scons: `%s' is up to date." % str(self.node))
+        return False
 
     def execute(self):
         if print_time:
@@ -181,7 +179,7 @@ class BuildTask(SCons.Taskmaster.Task):
             global first_command_start
             if first_command_start is None:
                 first_command_start = start_time
-        SCons.Taskmaster.Task.execute(self)
+        SCons.Taskmaster.OutOfDateTask.execute(self)
         if print_time:
             global cumulative_command_time
             global last_command_end
@@ -195,13 +193,13 @@ class BuildTask(SCons.Taskmaster.Task):
         global exit_status
         global this_build_status
         if self.options.ignore_errors:
-            SCons.Taskmaster.Task.executed(self)
+            SCons.Taskmaster.OutOfDateTask.executed(self)
         elif self.options.keep_going:
-            SCons.Taskmaster.Task.fail_continue(self)
+            SCons.Taskmaster.OutOfDateTask.fail_continue(self)
             exit_status = status
             this_build_status = status
         else:
-            SCons.Taskmaster.Task.fail_stop(self)
+            SCons.Taskmaster.OutOfDateTask.fail_stop(self)
             exit_status = status
             this_build_status = status
             
@@ -223,9 +221,9 @@ class BuildTask(SCons.Taskmaster.Task):
                 self.do_failed()
             else:
                 print "scons: Nothing to be done for `%s'." % t
-                SCons.Taskmaster.Task.executed(self)
+                SCons.Taskmaster.OutOfDateTask.executed(self)
         else:
-            SCons.Taskmaster.Task.executed(self)
+            SCons.Taskmaster.OutOfDateTask.executed(self)
 
     def failed(self):
         # Handle the failure of a build task.  The primary purpose here
@@ -293,17 +291,17 @@ class BuildTask(SCons.Taskmaster.Task):
                 if tree:
                     print
                     print tree
-        SCons.Taskmaster.Task.postprocess(self)
+        SCons.Taskmaster.OutOfDateTask.postprocess(self)
 
     def make_ready(self):
         """Make a task ready for execution"""
-        SCons.Taskmaster.Task.make_ready(self)
+        SCons.Taskmaster.OutOfDateTask.make_ready(self)
         if self.out_of_date and self.options.debug_explain:
             explanation = self.out_of_date[0].explain()
             if explanation:
                 sys.stdout.write("scons: " + explanation)
 
-class CleanTask(SCons.Taskmaster.Task):
+class CleanTask(SCons.Taskmaster.AlwaysTask):
     """An SCons clean task."""
     def fs_delete(self, path, pathstr, remove=1):
         try:
@@ -379,11 +377,11 @@ class CleanTask(SCons.Taskmaster.Task):
     def prepare(self):
         pass
 
-class QuestionTask(SCons.Taskmaster.Task):
+class QuestionTask(SCons.Taskmaster.AlwaysTask):
     """An SCons task for the -q (question) option."""
     def prepare(self):
         pass
-    
+
     def execute(self):
         if self.targets[0].get_state() != SCons.Node.up_to_date or \
            (self.top and not self.targets[0].exists()):
index eefe56bcc31e8052373b40b8c1b4b2840b60c469..f3604028a46bc336254f34d25808974abc38a739 100644 (file)
@@ -197,14 +197,11 @@ class Task:
         return self.node
 
     def needs_execute(self):
-        """
-        Called to determine whether the task's execute() method should
-        be run.
-
-        This method allows one to skip the somethat costly execution
-        of the execute() method in a seperate thread. For example,
-        that would be unnecessary for up-to-date targets.
-        """
+        # TODO(deprecate):  "return True" is the old default behavior;
+        # change it to NotImplementedError (after running through the
+        # Deprecation Cycle) so the desired behavior is explicitly
+        # determined by which concrete subclass is used.
+        #raise NotImplementedError
         return True
 
     def execute(self):
@@ -501,6 +498,30 @@ class Task:
             exc_traceback = None
         raise exc_type, exc_value, exc_traceback
 
+class AlwaysTask(Task):
+    def needs_execute(self):
+        """
+        Always returns True (indicating this Task should always
+        be executed).
+
+        Subclasses that need this behavior (as opposed to the default
+        of only executing Nodes that are out of date w.r.t. their
+        dependencies) can use this as follows:
+
+            class MyTaskSubclass(SCons.Taskmaster.Task):
+                needs_execute = SCons.Taskmaster.Task.execute_always
+        """
+        return True
+
+class OutOfDateTask(Task):
+    def needs_execute(self):
+        """
+        Returns True (indicating this Task should be executed) if this
+        Task's target state indicates it needs executing, which has
+        already been determined by an earlier up-to-date check.
+        """
+        return self.targets[0].get_state() == SCons.Node.executing
+
 
 def find_cycle(stack, visited):
     if stack[-1] in visited:
@@ -521,11 +542,13 @@ class Taskmaster:
     The Taskmaster for walking the dependency DAG.
     """
 
-    def __init__(self, targets=[], tasker=Task, order=None, trace=None):
+    def __init__(self, targets=[], tasker=None, order=None, trace=None):
         self.original_top = targets
         self.top_targets_left = targets[:]
         self.top_targets_left.reverse()
         self.candidates = []
+        if tasker is None:
+            tasker = OutOfDateTask
         self.tasker = tasker
         if not order:
             order = lambda l: l